aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/ext3/super.c25
-rw-r--r--fs/ext4/super.c25
-rw-r--r--fs/ocfs2/super.c5
-rw-r--r--fs/quota/dquot.c18
-rw-r--r--fs/quota/quota.c41
-rw-r--r--fs/reiserfs/super.c17
6 files changed, 51 insertions, 80 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b7d0554631e4..0e0d391626be 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -755,7 +755,7 @@ static int ext3_release_dquot(struct dquot *dquot);
755static int ext3_mark_dquot_dirty(struct dquot *dquot); 755static int ext3_mark_dquot_dirty(struct dquot *dquot);
756static int ext3_write_info(struct super_block *sb, int type); 756static int ext3_write_info(struct super_block *sb, int type);
757static int ext3_quota_on(struct super_block *sb, int type, int format_id, 757static int ext3_quota_on(struct super_block *sb, int type, int format_id,
758 char *path); 758 struct path *path);
759static int ext3_quota_on_mount(struct super_block *sb, int type); 759static int ext3_quota_on_mount(struct super_block *sb, int type);
760static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data, 760static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
761 size_t len, loff_t off); 761 size_t len, loff_t off);
@@ -2885,27 +2885,20 @@ static int ext3_quota_on_mount(struct super_block *sb, int type)
2885 * Standard function to be called on quota_on 2885 * Standard function to be called on quota_on
2886 */ 2886 */
2887static int ext3_quota_on(struct super_block *sb, int type, int format_id, 2887static int ext3_quota_on(struct super_block *sb, int type, int format_id,
2888 char *name) 2888 struct path *path)
2889{ 2889{
2890 int err; 2890 int err;
2891 struct path path;
2892 2891
2893 if (!test_opt(sb, QUOTA)) 2892 if (!test_opt(sb, QUOTA))
2894 return -EINVAL; 2893 return -EINVAL;
2895 2894
2896 err = kern_path(name, LOOKUP_FOLLOW, &path);
2897 if (err)
2898 return err;
2899
2900 /* Quotafile not on the same filesystem? */ 2895 /* Quotafile not on the same filesystem? */
2901 if (path.mnt->mnt_sb != sb) { 2896 if (path->mnt->mnt_sb != sb)
2902 path_put(&path);
2903 return -EXDEV; 2897 return -EXDEV;
2904 }
2905 /* Journaling quota? */ 2898 /* Journaling quota? */
2906 if (EXT3_SB(sb)->s_qf_names[type]) { 2899 if (EXT3_SB(sb)->s_qf_names[type]) {
2907 /* Quotafile not of fs root? */ 2900 /* Quotafile not of fs root? */
2908 if (path.dentry->d_parent != sb->s_root) 2901 if (path->dentry->d_parent != sb->s_root)
2909 ext3_msg(sb, KERN_WARNING, 2902 ext3_msg(sb, KERN_WARNING,
2910 "warning: Quota file not on filesystem root. " 2903 "warning: Quota file not on filesystem root. "
2911 "Journaled quota will not work."); 2904 "Journaled quota will not work.");
@@ -2915,7 +2908,7 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
2915 * When we journal data on quota file, we have to flush journal to see 2908 * When we journal data on quota file, we have to flush journal to see
2916 * all updates to the file when we bypass pagecache... 2909 * all updates to the file when we bypass pagecache...
2917 */ 2910 */
2918 if (ext3_should_journal_data(path.dentry->d_inode)) { 2911 if (ext3_should_journal_data(path->dentry->d_inode)) {
2919 /* 2912 /*
2920 * We don't need to lock updates but journal_flush() could 2913 * We don't need to lock updates but journal_flush() could
2921 * otherwise be livelocked... 2914 * otherwise be livelocked...
@@ -2923,15 +2916,11 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
2923 journal_lock_updates(EXT3_SB(sb)->s_journal); 2916 journal_lock_updates(EXT3_SB(sb)->s_journal);
2924 err = journal_flush(EXT3_SB(sb)->s_journal); 2917 err = journal_flush(EXT3_SB(sb)->s_journal);
2925 journal_unlock_updates(EXT3_SB(sb)->s_journal); 2918 journal_unlock_updates(EXT3_SB(sb)->s_journal);
2926 if (err) { 2919 if (err)
2927 path_put(&path);
2928 return err; 2920 return err;
2929 }
2930 } 2921 }
2931 2922
2932 err = dquot_quota_on_path(sb, type, format_id, &path); 2923 return dquot_quota_on(sb, type, format_id, path);
2933 path_put(&path);
2934 return err;
2935} 2924}
2936 2925
2937/* Read data from quotafile - avoid pagecache and such because we cannot afford 2926/* Read data from quotafile - avoid pagecache and such because we cannot afford
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)
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 17ff46fa8a10..31c3ffd2f8d0 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -993,8 +993,7 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb)
993} 993}
994 994
995/* Handle quota on quotactl */ 995/* Handle quota on quotactl */
996static int ocfs2_quota_on(struct super_block *sb, int type, int format_id, 996static int ocfs2_quota_on(struct super_block *sb, int type, int format_id)
997 char *path)
998{ 997{
999 unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, 998 unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
1000 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; 999 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
@@ -1013,7 +1012,7 @@ static int ocfs2_quota_off(struct super_block *sb, int type)
1013} 1012}
1014 1013
1015static const struct quotactl_ops ocfs2_quotactl_ops = { 1014static const struct quotactl_ops ocfs2_quotactl_ops = {
1016 .quota_on = ocfs2_quota_on, 1015 .quota_on_meta = ocfs2_quota_on,
1017 .quota_off = ocfs2_quota_off, 1016 .quota_off = ocfs2_quota_off,
1018 .quota_sync = dquot_quota_sync, 1017 .quota_sync = dquot_quota_sync,
1019 .get_info = dquot_get_dqinfo, 1018 .get_info = dquot_get_dqinfo,
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 84becd3e4772..a2a622e079f0 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2189,8 +2189,8 @@ int dquot_resume(struct super_block *sb, int type)
2189} 2189}
2190EXPORT_SYMBOL(dquot_resume); 2190EXPORT_SYMBOL(dquot_resume);
2191 2191
2192int dquot_quota_on_path(struct super_block *sb, int type, int format_id, 2192int dquot_quota_on(struct super_block *sb, int type, int format_id,
2193 struct path *path) 2193 struct path *path)
2194{ 2194{
2195 int error = security_quota_on(path->dentry); 2195 int error = security_quota_on(path->dentry);
2196 if (error) 2196 if (error)
@@ -2204,20 +2204,6 @@ int dquot_quota_on_path(struct super_block *sb, int type, int format_id,
2204 DQUOT_LIMITS_ENABLED); 2204 DQUOT_LIMITS_ENABLED);
2205 return error; 2205 return error;
2206} 2206}
2207EXPORT_SYMBOL(dquot_quota_on_path);
2208
2209int dquot_quota_on(struct super_block *sb, int type, int format_id, char *name)
2210{
2211 struct path path;
2212 int error;
2213
2214 error = kern_path(name, LOOKUP_FOLLOW, &path);
2215 if (!error) {
2216 error = dquot_quota_on_path(sb, type, format_id, &path);
2217 path_put(&path);
2218 }
2219 return error;
2220}
2221EXPORT_SYMBOL(dquot_quota_on); 2207EXPORT_SYMBOL(dquot_quota_on);
2222 2208
2223/* 2209/*
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index b299961e1edb..b34bdb25490c 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -64,18 +64,15 @@ static int quota_sync_all(int type)
64} 64}
65 65
66static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, 66static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
67 void __user *addr) 67 struct path *path)
68{ 68{
69 char *pathname; 69 if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta)
70 int ret = -ENOSYS; 70 return -ENOSYS;
71 71 if (sb->s_qcop->quota_on_meta)
72 pathname = getname(addr); 72 return sb->s_qcop->quota_on_meta(sb, type, id);
73 if (IS_ERR(pathname)) 73 if (IS_ERR(path))
74 return PTR_ERR(pathname); 74 return PTR_ERR(path);
75 if (sb->s_qcop->quota_on) 75 return sb->s_qcop->quota_on(sb, type, id, path);
76 ret = sb->s_qcop->quota_on(sb, type, id, pathname);
77 putname(pathname);
78 return ret;
79} 76}
80 77
81static int quota_getfmt(struct super_block *sb, int type, void __user *addr) 78static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
@@ -241,7 +238,7 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id,
241 238
242/* Copy parameters and call proper function */ 239/* Copy parameters and call proper function */
243static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, 240static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
244 void __user *addr) 241 void __user *addr, struct path *path)
245{ 242{
246 int ret; 243 int ret;
247 244
@@ -256,7 +253,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
256 253
257 switch (cmd) { 254 switch (cmd) {
258 case Q_QUOTAON: 255 case Q_QUOTAON:
259 return quota_quotaon(sb, type, cmd, id, addr); 256 return quota_quotaon(sb, type, cmd, id, path);
260 case Q_QUOTAOFF: 257 case Q_QUOTAOFF:
261 if (!sb->s_qcop->quota_off) 258 if (!sb->s_qcop->quota_off)
262 return -ENOSYS; 259 return -ENOSYS;
@@ -335,6 +332,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
335{ 332{
336 uint cmds, type; 333 uint cmds, type;
337 struct super_block *sb = NULL; 334 struct super_block *sb = NULL;
335 struct path path, *pathp = NULL;
338 int ret; 336 int ret;
339 337
340 cmds = cmd >> SUBCMDSHIFT; 338 cmds = cmd >> SUBCMDSHIFT;
@@ -351,12 +349,27 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
351 return -ENODEV; 349 return -ENODEV;
352 } 350 }
353 351
352 /*
353 * Path for quotaon has to be resolved before grabbing superblock
354 * because that gets s_umount sem which is also possibly needed by path
355 * resolution (think about autofs) and thus deadlocks could arise.
356 */
357 if (cmds == Q_QUOTAON) {
358 ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW, &path);
359 if (ret)
360 pathp = ERR_PTR(ret);
361 else
362 pathp = &path;
363 }
364
354 sb = quotactl_block(special); 365 sb = quotactl_block(special);
355 if (IS_ERR(sb)) 366 if (IS_ERR(sb))
356 return PTR_ERR(sb); 367 return PTR_ERR(sb);
357 368
358 ret = do_quotactl(sb, type, cmds, id, addr); 369 ret = do_quotactl(sb, type, cmds, id, addr, pathp);
359 370
360 drop_super(sb); 371 drop_super(sb);
372 if (pathp && !IS_ERR(pathp))
373 path_put(pathp);
361 return ret; 374 return ret;
362} 375}
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 2575682a9ead..0aab04f46827 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -632,7 +632,7 @@ static int reiserfs_acquire_dquot(struct dquot *);
632static int reiserfs_release_dquot(struct dquot *); 632static int reiserfs_release_dquot(struct dquot *);
633static int reiserfs_mark_dquot_dirty(struct dquot *); 633static int reiserfs_mark_dquot_dirty(struct dquot *);
634static int reiserfs_write_info(struct super_block *, int); 634static int reiserfs_write_info(struct super_block *, int);
635static int reiserfs_quota_on(struct super_block *, int, int, char *); 635static int reiserfs_quota_on(struct super_block *, int, int, struct path *);
636 636
637static const struct dquot_operations reiserfs_quota_operations = { 637static const struct dquot_operations reiserfs_quota_operations = {
638 .write_dquot = reiserfs_write_dquot, 638 .write_dquot = reiserfs_write_dquot,
@@ -2048,25 +2048,21 @@ static int reiserfs_quota_on_mount(struct super_block *sb, int type)
2048 * Standard function to be called on quota_on 2048 * Standard function to be called on quota_on
2049 */ 2049 */
2050static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, 2050static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
2051 char *name) 2051 struct path *path)
2052{ 2052{
2053 int err; 2053 int err;
2054 struct path path;
2055 struct inode *inode; 2054 struct inode *inode;
2056 struct reiserfs_transaction_handle th; 2055 struct reiserfs_transaction_handle th;
2057 2056
2058 if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA))) 2057 if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
2059 return -EINVAL; 2058 return -EINVAL;
2060 2059
2061 err = kern_path(name, LOOKUP_FOLLOW, &path);
2062 if (err)
2063 return err;
2064 /* Quotafile not on the same filesystem? */ 2060 /* Quotafile not on the same filesystem? */
2065 if (path.mnt->mnt_sb != sb) { 2061 if (path->mnt->mnt_sb != sb) {
2066 err = -EXDEV; 2062 err = -EXDEV;
2067 goto out; 2063 goto out;
2068 } 2064 }
2069 inode = path.dentry->d_inode; 2065 inode = path->dentry->d_inode;
2070 /* We must not pack tails for quota files on reiserfs for quota IO to work */ 2066 /* We must not pack tails for quota files on reiserfs for quota IO to work */
2071 if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) { 2067 if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
2072 err = reiserfs_unpack(inode, NULL); 2068 err = reiserfs_unpack(inode, NULL);
@@ -2082,7 +2078,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
2082 /* Journaling quota? */ 2078 /* Journaling quota? */
2083 if (REISERFS_SB(sb)->s_qf_names[type]) { 2079 if (REISERFS_SB(sb)->s_qf_names[type]) {
2084 /* Quotafile not of fs root? */ 2080 /* Quotafile not of fs root? */
2085 if (path.dentry->d_parent != sb->s_root) 2081 if (path->dentry->d_parent != sb->s_root)
2086 reiserfs_warning(sb, "super-6521", 2082 reiserfs_warning(sb, "super-6521",
2087 "Quota file not on filesystem root. " 2083 "Quota file not on filesystem root. "
2088 "Journalled quota will not work."); 2084 "Journalled quota will not work.");
@@ -2101,9 +2097,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
2101 if (err) 2097 if (err)
2102 goto out; 2098 goto out;
2103 } 2099 }
2104 err = dquot_quota_on_path(sb, type, format_id, &path); 2100 err = dquot_quota_on(sb, type, format_id, path);
2105out: 2101out:
2106 path_put(&path);
2107 return err; 2102 return err;
2108} 2103}
2109 2104