aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota
diff options
context:
space:
mode:
Diffstat (limited to 'fs/quota')
-rw-r--r--fs/quota/dquot.c74
-rw-r--r--fs/quota/quota.c41
-rw-r--r--fs/quota/quota_v2.c2
3 files changed, 58 insertions, 59 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 84becd3e4772..d3c032f5fa0a 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -76,7 +76,7 @@
76#include <linux/buffer_head.h> 76#include <linux/buffer_head.h>
77#include <linux/capability.h> 77#include <linux/capability.h>
78#include <linux/quotaops.h> 78#include <linux/quotaops.h>
79#include <linux/writeback.h> /* for inode_lock, oddly enough.. */ 79#include "../internal.h" /* ugh */
80 80
81#include <asm/uaccess.h> 81#include <asm/uaccess.h>
82 82
@@ -442,7 +442,7 @@ EXPORT_SYMBOL(dquot_acquire);
442 */ 442 */
443int dquot_commit(struct dquot *dquot) 443int dquot_commit(struct dquot *dquot)
444{ 444{
445 int ret = 0, ret2 = 0; 445 int ret = 0;
446 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); 446 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
447 447
448 mutex_lock(&dqopt->dqio_mutex); 448 mutex_lock(&dqopt->dqio_mutex);
@@ -454,15 +454,10 @@ int dquot_commit(struct dquot *dquot)
454 spin_unlock(&dq_list_lock); 454 spin_unlock(&dq_list_lock);
455 /* Inactive dquot can be only if there was error during read/init 455 /* Inactive dquot can be only if there was error during read/init
456 * => we have better not writing it */ 456 * => we have better not writing it */
457 if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { 457 if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
458 ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot); 458 ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
459 if (info_dirty(&dqopt->info[dquot->dq_type])) { 459 else
460 ret2 = dqopt->ops[dquot->dq_type]->write_file_info( 460 ret = -EIO;
461 dquot->dq_sb, dquot->dq_type);
462 }
463 if (ret >= 0)
464 ret = ret2;
465 }
466out_sem: 461out_sem:
467 mutex_unlock(&dqopt->dqio_mutex); 462 mutex_unlock(&dqopt->dqio_mutex);
468 return ret; 463 return ret;
@@ -900,33 +895,38 @@ static void add_dquot_ref(struct super_block *sb, int type)
900 int reserved = 0; 895 int reserved = 0;
901#endif 896#endif
902 897
903 spin_lock(&inode_lock); 898 spin_lock(&inode_sb_list_lock);
904 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 899 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
905 if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) 900 spin_lock(&inode->i_lock);
901 if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
902 !atomic_read(&inode->i_writecount) ||
903 !dqinit_needed(inode, type)) {
904 spin_unlock(&inode->i_lock);
906 continue; 905 continue;
906 }
907#ifdef CONFIG_QUOTA_DEBUG 907#ifdef CONFIG_QUOTA_DEBUG
908 if (unlikely(inode_get_rsv_space(inode) > 0)) 908 if (unlikely(inode_get_rsv_space(inode) > 0))
909 reserved = 1; 909 reserved = 1;
910#endif 910#endif
911 if (!atomic_read(&inode->i_writecount))
912 continue;
913 if (!dqinit_needed(inode, type))
914 continue;
915
916 __iget(inode); 911 __iget(inode);
917 spin_unlock(&inode_lock); 912 spin_unlock(&inode->i_lock);
913 spin_unlock(&inode_sb_list_lock);
918 914
919 iput(old_inode); 915 iput(old_inode);
920 __dquot_initialize(inode, type); 916 __dquot_initialize(inode, type);
921 /* We hold a reference to 'inode' so it couldn't have been 917
922 * removed from s_inodes list while we dropped the inode_lock. 918 /*
923 * We cannot iput the inode now as we can be holding the last 919 * We hold a reference to 'inode' so it couldn't have been
924 * reference and we cannot iput it under inode_lock. So we 920 * removed from s_inodes list while we dropped the
925 * keep the reference and iput it later. */ 921 * inode_sb_list_lock We cannot iput the inode now as we can be
922 * holding the last reference and we cannot iput it under
923 * inode_sb_list_lock. So we keep the reference and iput it
924 * later.
925 */
926 old_inode = inode; 926 old_inode = inode;
927 spin_lock(&inode_lock); 927 spin_lock(&inode_sb_list_lock);
928 } 928 }
929 spin_unlock(&inode_lock); 929 spin_unlock(&inode_sb_list_lock);
930 iput(old_inode); 930 iput(old_inode);
931 931
932#ifdef CONFIG_QUOTA_DEBUG 932#ifdef CONFIG_QUOTA_DEBUG
@@ -951,7 +951,7 @@ static inline int dqput_blocks(struct dquot *dquot)
951 951
952/* 952/*
953 * Remove references to dquots from inode and add dquot to list for freeing 953 * Remove references to dquots from inode and add dquot to list for freeing
954 * if we have the last referece to dquot 954 * if we have the last reference to dquot
955 * We can't race with anybody because we hold dqptr_sem for writing... 955 * We can't race with anybody because we hold dqptr_sem for writing...
956 */ 956 */
957static int remove_inode_dquot_ref(struct inode *inode, int type, 957static int remove_inode_dquot_ref(struct inode *inode, int type,
@@ -1007,7 +1007,7 @@ static void remove_dquot_ref(struct super_block *sb, int type,
1007 struct inode *inode; 1007 struct inode *inode;
1008 int reserved = 0; 1008 int reserved = 0;
1009 1009
1010 spin_lock(&inode_lock); 1010 spin_lock(&inode_sb_list_lock);
1011 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 1011 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
1012 /* 1012 /*
1013 * We have to scan also I_NEW inodes because they can already 1013 * We have to scan also I_NEW inodes because they can already
@@ -1021,7 +1021,7 @@ static void remove_dquot_ref(struct super_block *sb, int type,
1021 remove_inode_dquot_ref(inode, type, tofree_head); 1021 remove_inode_dquot_ref(inode, type, tofree_head);
1022 } 1022 }
1023 } 1023 }
1024 spin_unlock(&inode_lock); 1024 spin_unlock(&inode_sb_list_lock);
1025#ifdef CONFIG_QUOTA_DEBUG 1025#ifdef CONFIG_QUOTA_DEBUG
1026 if (reserved) { 1026 if (reserved) {
1027 printk(KERN_WARNING "VFS (%s): Writes happened after quota" 1027 printk(KERN_WARNING "VFS (%s): Writes happened after quota"
@@ -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/quota/quota_v2.c b/fs/quota/quota_v2.c
index 65444d29406b..f1ab3604db5a 100644
--- a/fs/quota/quota_v2.c
+++ b/fs/quota/quota_v2.c
@@ -112,7 +112,7 @@ static int v2_read_file_info(struct super_block *sb, int type)
112 if (!info->dqi_priv) { 112 if (!info->dqi_priv) {
113 printk(KERN_WARNING 113 printk(KERN_WARNING
114 "Not enough memory for quota information structure.\n"); 114 "Not enough memory for quota information structure.\n");
115 return -1; 115 return -ENOMEM;
116 } 116 }
117 qinfo = info->dqi_priv; 117 qinfo = info->dqi_priv;
118 if (version == 0) { 118 if (version == 0) {