aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-09-15 11:38:58 -0400
committerJan Kara <jack@suse.cz>2011-01-12 13:14:55 -0500
commitf00c9e44ad1a9660fe8cd3ca15b6cd9497172eab (patch)
treecbb47ae0d8aba9d8b3c44714b000156715cdf969 /fs/ext4
parent4162cf64973df51fc885825bc9ca4d055891c49f (diff)
quota: Fix deadlock during path resolution
As Al Viro pointed out path resolution during Q_QUOTAON calls to quotactl is prone to deadlocks. We hold s_umount semaphore for reading during the path resolution and resolution itself may need to acquire the semaphore for writing when e. g. autofs mountpoint is passed. Solve the problem by performing the resolution before we get hold of the superblock (and thus s_umount semaphore). The whole thing is complicated by the fact that some filesystems (OCFS2) ignore the path argument. So to distinguish between filesystem which want the path and which do not we introduce new .quota_on_meta callback which does not get the path. OCFS2 then uses this callback instead of old .quota_on. CC: Al Viro <viro@ZenIV.linux.org.uk> CC: Christoph Hellwig <hch@lst.de> CC: Ted Ts'o <tytso@mit.edu> CC: Joel Becker <joel.becker@oracle.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/super.c25
1 files changed, 7 insertions, 18 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 29c80f6d8b27..0f10ccd6bfc0 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1162,7 +1162,7 @@ static int ext4_release_dquot(struct dquot *dquot);
1162static int ext4_mark_dquot_dirty(struct dquot *dquot); 1162static int ext4_mark_dquot_dirty(struct dquot *dquot);
1163static int ext4_write_info(struct super_block *sb, int type); 1163static int ext4_write_info(struct super_block *sb, int type);
1164static int ext4_quota_on(struct super_block *sb, int type, int format_id, 1164static int ext4_quota_on(struct super_block *sb, int type, int format_id,
1165 char *path); 1165 struct path *path);
1166static int ext4_quota_off(struct super_block *sb, int type); 1166static int ext4_quota_off(struct super_block *sb, int type);
1167static int ext4_quota_on_mount(struct super_block *sb, int type); 1167static int ext4_quota_on_mount(struct super_block *sb, int type);
1168static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, 1168static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
@@ -4566,27 +4566,20 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
4566 * Standard function to be called on quota_on 4566 * Standard function to be called on quota_on
4567 */ 4567 */
4568static int ext4_quota_on(struct super_block *sb, int type, int format_id, 4568static int ext4_quota_on(struct super_block *sb, int type, int format_id,
4569 char *name) 4569 struct path *path)
4570{ 4570{
4571 int err; 4571 int err;
4572 struct path path;
4573 4572
4574 if (!test_opt(sb, QUOTA)) 4573 if (!test_opt(sb, QUOTA))
4575 return -EINVAL; 4574 return -EINVAL;
4576 4575
4577 err = kern_path(name, LOOKUP_FOLLOW, &path);
4578 if (err)
4579 return err;
4580
4581 /* Quotafile not on the same filesystem? */ 4576 /* Quotafile not on the same filesystem? */
4582 if (path.mnt->mnt_sb != sb) { 4577 if (path->mnt->mnt_sb != sb)
4583 path_put(&path);
4584 return -EXDEV; 4578 return -EXDEV;
4585 }
4586 /* Journaling quota? */ 4579 /* Journaling quota? */
4587 if (EXT4_SB(sb)->s_qf_names[type]) { 4580 if (EXT4_SB(sb)->s_qf_names[type]) {
4588 /* Quotafile not in fs root? */ 4581 /* Quotafile not in fs root? */
4589 if (path.dentry->d_parent != sb->s_root) 4582 if (path->dentry->d_parent != sb->s_root)
4590 ext4_msg(sb, KERN_WARNING, 4583 ext4_msg(sb, KERN_WARNING,
4591 "Quota file not on filesystem root. " 4584 "Quota file not on filesystem root. "
4592 "Journaled quota will not work"); 4585 "Journaled quota will not work");
@@ -4597,7 +4590,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
4597 * all updates to the file when we bypass pagecache... 4590 * all updates to the file when we bypass pagecache...
4598 */ 4591 */
4599 if (EXT4_SB(sb)->s_journal && 4592 if (EXT4_SB(sb)->s_journal &&
4600 ext4_should_journal_data(path.dentry->d_inode)) { 4593 ext4_should_journal_data(path->dentry->d_inode)) {
4601 /* 4594 /*
4602 * We don't need to lock updates but journal_flush() could 4595 * We don't need to lock updates but journal_flush() could
4603 * otherwise be livelocked... 4596 * otherwise be livelocked...
@@ -4605,15 +4598,11 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
4605 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); 4598 jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
4606 err = jbd2_journal_flush(EXT4_SB(sb)->s_journal); 4599 err = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
4607 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); 4600 jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
4608 if (err) { 4601 if (err)
4609 path_put(&path);
4610 return err; 4602 return err;
4611 }
4612 } 4603 }
4613 4604
4614 err = dquot_quota_on_path(sb, type, format_id, &path); 4605 return dquot_quota_on(sb, type, format_id, path);
4615 path_put(&path);
4616 return err;
4617} 4606}
4618 4607
4619static int ext4_quota_off(struct super_block *sb, int type) 4608static int ext4_quota_off(struct super_block *sb, int type)