pos = iocb->ki_pos;
        count = iov_iter_count(from);
+       if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
+               err = -EDQUOT;
+               goto out;
+       }
+
        err = file_remove_privs(file);
        if (err)
                goto out;
                goto unlock;
        }
 
+       if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) &&
+           ceph_quota_is_max_bytes_exceeded(inode, offset + length)) {
+               ret = -EDQUOT;
+               goto unlock;
+       }
+
        if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) &&
            !(mode & FALLOC_FL_PUNCH_HOLE)) {
                ret = -ENOSPC;
 
        if (err != 0)
                return err;
 
+       if ((attr->ia_valid & ATTR_SIZE) &&
+           ceph_quota_is_max_bytes_exceeded(inode, attr->ia_size))
+               return -EDQUOT;
+
        err = __ceph_setattr(inode, attr);
 
        if (err >= 0 && (attr->ia_valid & ATTR_MODE))
 
 }
 
 enum quota_check_op {
-       QUOTA_CHECK_MAX_FILES_OP        /* check quota max_files limit */
+       QUOTA_CHECK_MAX_FILES_OP,       /* check quota max_files limit */
+       QUOTA_CHECK_MAX_BYTES_OP        /* check quota max_files limit */
 };
 
 /*
                if (op == QUOTA_CHECK_MAX_FILES_OP) {
                        max = ci->i_max_files;
                        rvalue = ci->i_rfiles + ci->i_rsubdirs;
+               } else {
+                       max = ci->i_max_bytes;
+                       rvalue = ci->i_rbytes;
                }
                is_root = (ci->i_vino.ino == CEPH_INO_ROOT);
                spin_unlock(&ci->i_ceph_lock);
                case QUOTA_CHECK_MAX_FILES_OP:
                        exceeded = (max && (rvalue >= max));
                        break;
+               case QUOTA_CHECK_MAX_BYTES_OP:
+                       exceeded = (max && (rvalue + delta > max));
+                       break;
                default:
                        /* Shouldn't happen */
                        pr_warn("Invalid quota check op (%d)\n", op);
 
        return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0);
 }
+
+/*
+ * ceph_quota_is_max_bytes_exceeded - check if we can write to a file
+ * @inode:     inode being written
+ * @newsize:   new size if write succeeds
+ *
+ * This functions returns true is max_bytes quota allows a file size to reach
+ * @newsize; it returns false otherwise.
+ */
+bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize)
+{
+       loff_t size = i_size_read(inode);
+
+       /* return immediately if we're decreasing file size */
+       if (newsize <= size)
+               return false;
+
+       return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size));
+}
 
                              struct ceph_msg *msg);
 extern bool ceph_quota_is_max_files_exceeded(struct inode *inode);
 extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new);
+extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
+                                            loff_t newlen);
 
 #endif /* _FS_CEPH_SUPER_H */