diff options
author | Jan Kara <jack@suse.cz> | 2010-09-15 11:38:58 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2011-01-12 13:14:55 -0500 |
commit | f00c9e44ad1a9660fe8cd3ca15b6cd9497172eab (patch) | |
tree | cbb47ae0d8aba9d8b3c44714b000156715cdf969 | |
parent | 4162cf64973df51fc885825bc9ca4d055891c49f (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>
-rw-r--r-- | fs/ext3/super.c | 25 | ||||
-rw-r--r-- | fs/ext4/super.c | 25 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 5 | ||||
-rw-r--r-- | fs/quota/dquot.c | 18 | ||||
-rw-r--r-- | fs/quota/quota.c | 41 | ||||
-rw-r--r-- | fs/reiserfs/super.c | 17 | ||||
-rw-r--r-- | include/linux/quota.h | 5 | ||||
-rw-r--r-- | include/linux/quotaops.h | 4 |
8 files changed, 56 insertions, 84 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); | |||
755 | static int ext3_mark_dquot_dirty(struct dquot *dquot); | 755 | static int ext3_mark_dquot_dirty(struct dquot *dquot); |
756 | static int ext3_write_info(struct super_block *sb, int type); | 756 | static int ext3_write_info(struct super_block *sb, int type); |
757 | static int ext3_quota_on(struct super_block *sb, int type, int format_id, | 757 | static int ext3_quota_on(struct super_block *sb, int type, int format_id, |
758 | char *path); | 758 | struct path *path); |
759 | static int ext3_quota_on_mount(struct super_block *sb, int type); | 759 | static int ext3_quota_on_mount(struct super_block *sb, int type); |
760 | static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data, | 760 | static 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 | */ |
2887 | static int ext3_quota_on(struct super_block *sb, int type, int format_id, | 2887 | static 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); | |||
1162 | static int ext4_mark_dquot_dirty(struct dquot *dquot); | 1162 | static int ext4_mark_dquot_dirty(struct dquot *dquot); |
1163 | static int ext4_write_info(struct super_block *sb, int type); | 1163 | static int ext4_write_info(struct super_block *sb, int type); |
1164 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, | 1164 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, |
1165 | char *path); | 1165 | struct path *path); |
1166 | static int ext4_quota_off(struct super_block *sb, int type); | 1166 | static int ext4_quota_off(struct super_block *sb, int type); |
1167 | static int ext4_quota_on_mount(struct super_block *sb, int type); | 1167 | static int ext4_quota_on_mount(struct super_block *sb, int type); |
1168 | static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, | 1168 | static 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 | */ |
4568 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, | 4568 | static 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 | ||
4619 | static int ext4_quota_off(struct super_block *sb, int type) | 4608 | static 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 */ |
996 | static int ocfs2_quota_on(struct super_block *sb, int type, int format_id, | 996 | static 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 | ||
1015 | static const struct quotactl_ops ocfs2_quotactl_ops = { | 1014 | static 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 | } |
2190 | EXPORT_SYMBOL(dquot_resume); | 2190 | EXPORT_SYMBOL(dquot_resume); |
2191 | 2191 | ||
2192 | int dquot_quota_on_path(struct super_block *sb, int type, int format_id, | 2192 | int 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 | } |
2207 | EXPORT_SYMBOL(dquot_quota_on_path); | ||
2208 | |||
2209 | int 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 | } | ||
2221 | EXPORT_SYMBOL(dquot_quota_on); | 2207 | EXPORT_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 | ||
66 | static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, | 66 | static 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 | ||
81 | static int quota_getfmt(struct super_block *sb, int type, void __user *addr) | 78 | static 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 */ |
243 | static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, | 240 | static 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 *); | |||
632 | static int reiserfs_release_dquot(struct dquot *); | 632 | static int reiserfs_release_dquot(struct dquot *); |
633 | static int reiserfs_mark_dquot_dirty(struct dquot *); | 633 | static int reiserfs_mark_dquot_dirty(struct dquot *); |
634 | static int reiserfs_write_info(struct super_block *, int); | 634 | static int reiserfs_write_info(struct super_block *, int); |
635 | static int reiserfs_quota_on(struct super_block *, int, int, char *); | 635 | static int reiserfs_quota_on(struct super_block *, int, int, struct path *); |
636 | 636 | ||
637 | static const struct dquot_operations reiserfs_quota_operations = { | 637 | static 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 | */ |
2050 | static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, | 2050 | static 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); |
2105 | out: | 2101 | out: |
2106 | path_put(&path); | ||
2107 | return err; | 2102 | return err; |
2108 | } | 2103 | } |
2109 | 2104 | ||
diff --git a/include/linux/quota.h b/include/linux/quota.h index 94c1f03b50eb..9a85412e0db6 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -322,9 +322,12 @@ struct dquot_operations { | |||
322 | qsize_t *(*get_reserved_space) (struct inode *); | 322 | qsize_t *(*get_reserved_space) (struct inode *); |
323 | }; | 323 | }; |
324 | 324 | ||
325 | struct path; | ||
326 | |||
325 | /* Operations handling requests from userspace */ | 327 | /* Operations handling requests from userspace */ |
326 | struct quotactl_ops { | 328 | struct quotactl_ops { |
327 | int (*quota_on)(struct super_block *, int, int, char *); | 329 | int (*quota_on)(struct super_block *, int, int, struct path *); |
330 | int (*quota_on_meta)(struct super_block *, int, int); | ||
328 | int (*quota_off)(struct super_block *, int); | 331 | int (*quota_off)(struct super_block *, int); |
329 | int (*quota_sync)(struct super_block *, int, int); | 332 | int (*quota_sync)(struct super_block *, int, int); |
330 | int (*get_info)(struct super_block *, int, struct if_dqinfo *); | 333 | int (*get_info)(struct super_block *, int, struct if_dqinfo *); |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 223b14cd129c..eb354f6f26b3 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
@@ -76,11 +76,9 @@ int dquot_mark_dquot_dirty(struct dquot *dquot); | |||
76 | 76 | ||
77 | int dquot_file_open(struct inode *inode, struct file *file); | 77 | int dquot_file_open(struct inode *inode, struct file *file); |
78 | 78 | ||
79 | int dquot_quota_on(struct super_block *sb, int type, int format_id, | ||
80 | char *path); | ||
81 | int dquot_enable(struct inode *inode, int type, int format_id, | 79 | int dquot_enable(struct inode *inode, int type, int format_id, |
82 | unsigned int flags); | 80 | unsigned int flags); |
83 | int dquot_quota_on_path(struct super_block *sb, int type, int format_id, | 81 | int dquot_quota_on(struct super_block *sb, int type, int format_id, |
84 | struct path *path); | 82 | struct path *path); |
85 | int dquot_quota_on_mount(struct super_block *sb, char *qf_name, | 83 | int dquot_quota_on_mount(struct super_block *sb, char *qf_name, |
86 | int format_id, int type); | 84 | int format_id, int type); |