aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2007-05-17 01:11:19 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-17 08:23:05 -0400
commit7925409e202a41176b729671eab6e610a54153cd (patch)
tree7b97858fa33169a1616cc6f1e05b66117e97c1b3 /fs/quota.c
parentbb49b32fece7910fbb02a6934bca4495596f6c8c (diff)
circular locking dependency found in QUOTA OFF
i_mutex on quota files is special. Unlike i_mutexes for other inodes it is acquired under dqonoff_mutex. Tell lockdep about this lock ranking. Also comment and code in quota_sync_sb() seem to be bogus (as i_mutex for quota file can be acquired under dqonoff_mutex). Move truncate_inode_pages() call under dqonoff_mutex and save some problems with races... Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/quota.c')
-rw-r--r--fs/quota.c23
1 files changed, 7 insertions, 16 deletions
diff --git a/fs/quota.c b/fs/quota.c
index e9d88fd0eca8..9f237d6182c9 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -157,7 +157,6 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
157static void quota_sync_sb(struct super_block *sb, int type) 157static void quota_sync_sb(struct super_block *sb, int type)
158{ 158{
159 int cnt; 159 int cnt;
160 struct inode *discard[MAXQUOTAS];
161 160
162 sb->s_qcop->quota_sync(sb, type); 161 sb->s_qcop->quota_sync(sb, type);
163 /* This is not very clever (and fast) but currently I don't know about 162 /* This is not very clever (and fast) but currently I don't know about
@@ -167,29 +166,21 @@ static void quota_sync_sb(struct super_block *sb, int type)
167 sb->s_op->sync_fs(sb, 1); 166 sb->s_op->sync_fs(sb, 1);
168 sync_blockdev(sb->s_bdev); 167 sync_blockdev(sb->s_bdev);
169 168
170 /* Now when everything is written we can discard the pagecache so 169 /*
171 * that userspace sees the changes. We need i_mutex and so we could 170 * Now when everything is written we can discard the pagecache so
172 * not do it inside dqonoff_mutex. Moreover we need to be carefull 171 * that userspace sees the changes.
173 * about races with quotaoff() (that is the reason why we have own 172 */
174 * reference to inode). */
175 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); 173 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
176 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 174 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
177 discard[cnt] = NULL;
178 if (type != -1 && cnt != type) 175 if (type != -1 && cnt != type)
179 continue; 176 continue;
180 if (!sb_has_quota_enabled(sb, cnt)) 177 if (!sb_has_quota_enabled(sb, cnt))
181 continue; 178 continue;
182 discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]); 179 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA);
180 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
181 mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
183 } 182 }
184 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); 183 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
185 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
186 if (discard[cnt]) {
187 mutex_lock(&discard[cnt]->i_mutex);
188 truncate_inode_pages(&discard[cnt]->i_data, 0);
189 mutex_unlock(&discard[cnt]->i_mutex);
190 iput(discard[cnt]);
191 }
192 }
193} 184}
194 185
195void sync_dquots(struct super_block *sb, int type) 186void sync_dquots(struct super_block *sb, int type)