+ bspace = obj->oo_inode->i_blocks;
+ bspace <<= obj->oo_inode->i_sb->s_blocksize_bits;
+ bspace = toqb(bspace);
+
+ /* Changing ownership is always preformed by super user, it should not
+ * fail with EDQUOT.
+ *
+ * We still need to call the osd_declare_qid() to calculate the journal
+ * credits for updating quota accounting files and to trigger quota
+ * space adjustment once the operation is completed.*/
+ if ((attr->la_valid & LA_UID) != 0 &&
+ attr->la_uid != obj->oo_inode->i_uid) {
+ qi->lqi_type = USRQUOTA;
+
+ /* inode accounting */
+ qi->lqi_is_blk = false;
+
+ /* one more inode for the new owner ... */
+ qi->lqi_id.qid_uid = attr->la_uid;
+ qi->lqi_space = 1;
+ allocated = (attr->la_uid == 0) ? true : false;
+ rc = osd_declare_qid(env, oh, qi, allocated, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+
+ /* and one less inode for the current uid */
+ qi->lqi_id.qid_uid = obj->oo_inode->i_uid;
+ qi->lqi_space = -1;
+ rc = osd_declare_qid(env, oh, qi, true, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+
+ /* block accounting */
+ qi->lqi_is_blk = true;
+
+ /* more blocks for the new owner ... */
+ qi->lqi_id.qid_uid = attr->la_uid;
+ qi->lqi_space = bspace;
+ allocated = (attr->la_uid == 0) ? true : false;
+ rc = osd_declare_qid(env, oh, qi, allocated, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+
+ /* and finally less blocks for the current owner */
+ qi->lqi_id.qid_uid = obj->oo_inode->i_uid;
+ qi->lqi_space = -bspace;
+ rc = osd_declare_qid(env, oh, qi, true, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+ }
+
+ if (attr->la_valid & LA_GID &&
+ attr->la_gid != obj->oo_inode->i_gid) {
+ qi->lqi_type = GRPQUOTA;
+
+ /* inode accounting */
+ qi->lqi_is_blk = false;
+
+ /* one more inode for the new group owner ... */
+ qi->lqi_id.qid_gid = attr->la_gid;
+ qi->lqi_space = 1;
+ allocated = (attr->la_gid == 0) ? true : false;
+ rc = osd_declare_qid(env, oh, qi, allocated, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+
+ /* and one less inode for the current gid */
+ qi->lqi_id.qid_gid = obj->oo_inode->i_gid;
+ qi->lqi_space = -1;
+ rc = osd_declare_qid(env, oh, qi, true, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+
+ /* block accounting */
+ qi->lqi_is_blk = true;
+
+ /* more blocks for the new owner ... */
+ qi->lqi_id.qid_gid = attr->la_gid;
+ qi->lqi_space = bspace;
+ allocated = (attr->la_gid == 0) ? true : false;
+ rc = osd_declare_qid(env, oh, qi, allocated, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+
+ /* and finally less blocks for the current owner */
+ qi->lqi_id.qid_gid = obj->oo_inode->i_gid;
+ qi->lqi_space = -bspace;
+ rc = osd_declare_qid(env, oh, qi, true, NULL);
+ if (rc == -EDQUOT || rc == -EINPROGRESS)
+ rc = 0;
+ if (rc)
+ RETURN(rc);
+ }
+
+ RETURN(rc);