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