aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index c2a87c885b73..1a96cac31791 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -894,9 +894,9 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
894 struct ocfs2_super *osb = OCFS2_SB(sb); 894 struct ocfs2_super *osb = OCFS2_SB(sb);
895 struct buffer_head *bh = NULL; 895 struct buffer_head *bh = NULL;
896 handle_t *handle = NULL; 896 handle_t *handle = NULL;
897 int locked[MAXQUOTAS] = {0, 0}; 897 int qtype;
898 int credits, qtype; 898 struct dquot *transfer_from[MAXQUOTAS] = { };
899 struct ocfs2_mem_dqinfo *oinfo; 899 struct dquot *transfer_to[MAXQUOTAS] = { };
900 900
901 mlog_entry("(0x%p, '%.*s')\n", dentry, 901 mlog_entry("(0x%p, '%.*s')\n", dentry,
902 dentry->d_name.len, dentry->d_name.name); 902 dentry->d_name.len, dentry->d_name.name);
@@ -969,30 +969,37 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
969 969
970 if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 970 if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
971 (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { 971 (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
972 credits = OCFS2_INODE_UPDATE_CREDITS; 972 /*
973 * Gather pointers to quota structures so that allocation /
974 * freeing of quota structures happens here and not inside
975 * vfs_dq_transfer() where we have problems with lock ordering
976 */
973 if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid 977 if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
974 && OCFS2_HAS_RO_COMPAT_FEATURE(sb, 978 && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
975 OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { 979 OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
976 oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv; 980 transfer_to[USRQUOTA] = dqget(sb, attr->ia_uid,
977 status = ocfs2_lock_global_qf(oinfo, 1); 981 USRQUOTA);
978 if (status < 0) 982 transfer_from[USRQUOTA] = dqget(sb, inode->i_uid,
983 USRQUOTA);
984 if (!transfer_to[USRQUOTA] || !transfer_from[USRQUOTA]) {
985 status = -ESRCH;
979 goto bail_unlock; 986 goto bail_unlock;
980 credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) + 987 }
981 ocfs2_calc_qdel_credits(sb, USRQUOTA);
982 locked[USRQUOTA] = 1;
983 } 988 }
984 if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid 989 if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
985 && OCFS2_HAS_RO_COMPAT_FEATURE(sb, 990 && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
986 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { 991 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
987 oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv; 992 transfer_to[GRPQUOTA] = dqget(sb, attr->ia_gid,
988 status = ocfs2_lock_global_qf(oinfo, 1); 993 GRPQUOTA);
989 if (status < 0) 994 transfer_from[GRPQUOTA] = dqget(sb, inode->i_gid,
995 GRPQUOTA);
996 if (!transfer_to[GRPQUOTA] || !transfer_from[GRPQUOTA]) {
997 status = -ESRCH;
990 goto bail_unlock; 998 goto bail_unlock;
991 credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) + 999 }
992 ocfs2_calc_qdel_credits(sb, GRPQUOTA);
993 locked[GRPQUOTA] = 1;
994 } 1000 }
995 handle = ocfs2_start_trans(osb, credits); 1001 handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS +
1002 2 * ocfs2_quota_trans_credits(sb));
996 if (IS_ERR(handle)) { 1003 if (IS_ERR(handle)) {
997 status = PTR_ERR(handle); 1004 status = PTR_ERR(handle);
998 mlog_errno(status); 1005 mlog_errno(status);
@@ -1030,12 +1037,6 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
1030bail_commit: 1037bail_commit:
1031 ocfs2_commit_trans(osb, handle); 1038 ocfs2_commit_trans(osb, handle);
1032bail_unlock: 1039bail_unlock:
1033 for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
1034 if (!locked[qtype])
1035 continue;
1036 oinfo = sb_dqinfo(sb, qtype)->dqi_priv;
1037 ocfs2_unlock_global_qf(oinfo, 1);
1038 }
1039 ocfs2_inode_unlock(inode, 1); 1040 ocfs2_inode_unlock(inode, 1);
1040bail_unlock_rw: 1041bail_unlock_rw:
1041 if (size_change) 1042 if (size_change)
@@ -1043,6 +1044,12 @@ bail_unlock_rw:
1043bail: 1044bail:
1044 brelse(bh); 1045 brelse(bh);
1045 1046
1047 /* Release quota pointers in case we acquired them */
1048 for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
1049 dqput(transfer_to[qtype]);
1050 dqput(transfer_from[qtype]);
1051 }
1052
1046 if (!status && attr->ia_valid & ATTR_MODE) { 1053 if (!status && attr->ia_valid & ATTR_MODE) {
1047 status = ocfs2_acl_chmod(inode); 1054 status = ocfs2_acl_chmod(inode);
1048 if (status < 0) 1055 if (status < 0)