Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-drm-fsl-dcu.git] / fs / quota.c
index 612e04db4b939189721f35182c2dd1793804ae89..b9dae76a0b6e2212083efa9ca0281e31661c0375 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
+#include <linux/capability.h>
 #include <linux/quotaops.h>
 
 /* Check validity of generic quotactl commands */
@@ -168,11 +169,11 @@ static void quota_sync_sb(struct super_block *sb, int type)
        sync_blockdev(sb->s_bdev);
 
        /* Now when everything is written we can discard the pagecache so
-        * that userspace sees the changes. We need i_sem and so we could
-        * not do it inside dqonoff_sem. Moreover we need to be carefull
+        * that userspace sees the changes. We need i_mutex and so we could
+        * not do it inside dqonoff_mutex. Moreover we need to be carefull
         * about races with quotaoff() (that is the reason why we have own
         * reference to inode). */
-       down(&sb_dqopt(sb)->dqonoff_sem);
+       mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                discard[cnt] = NULL;
                if (type != -1 && cnt != type)
@@ -181,12 +182,12 @@ static void quota_sync_sb(struct super_block *sb, int type)
                        continue;
                discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
        }
-       up(&sb_dqopt(sb)->dqonoff_sem);
+       mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (discard[cnt]) {
-                       down(&discard[cnt]->i_sem);
+                       mutex_lock(&discard[cnt]->i_mutex);
                        truncate_inode_pages(&discard[cnt]->i_data, 0);
-                       up(&discard[cnt]->i_sem);
+                       mutex_unlock(&discard[cnt]->i_mutex);
                        iput(discard[cnt]);
                }
        }
@@ -336,6 +337,34 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
        return 0;
 }
 
+/*
+ * look up a superblock on which quota ops will be performed
+ * - use the name of a block device to find the superblock thereon
+ */
+static inline struct super_block *quotactl_block(const char __user *special)
+{
+#ifdef CONFIG_BLOCK
+       struct block_device *bdev;
+       struct super_block *sb;
+       char *tmp = getname(special);
+
+       if (IS_ERR(tmp))
+               return ERR_PTR(PTR_ERR(tmp));
+       bdev = lookup_bdev(tmp);
+       putname(tmp);
+       if (IS_ERR(bdev))
+               return ERR_PTR(PTR_ERR(bdev));
+       sb = get_super(bdev);
+       bdput(bdev);
+       if (!sb)
+               return ERR_PTR(-ENODEV);
+
+       return sb;
+#else
+       return ERR_PTR(-ENODEV);
+#endif
+}
+
 /*
  * This is the system call interface. This communicates with
  * the user-level programs. Currently this only supports diskquota
@@ -346,25 +375,15 @@ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t
 {
        uint cmds, type;
        struct super_block *sb = NULL;
-       struct block_device *bdev;
-       char *tmp;
        int ret;
 
        cmds = cmd >> SUBCMDSHIFT;
        type = cmd & SUBCMDMASK;
 
        if (cmds != Q_SYNC || special) {
-               tmp = getname(special);
-               if (IS_ERR(tmp))
-                       return PTR_ERR(tmp);
-               bdev = lookup_bdev(tmp);
-               putname(tmp);
-               if (IS_ERR(bdev))
-                       return PTR_ERR(bdev);
-               sb = get_super(bdev);
-               bdput(bdev);
-               if (!sb)
-                       return -ENODEV;
+               sb = quotactl_block(special);
+               if (IS_ERR(sb))
+                       return PTR_ERR(sb);
        }
 
        ret = check_quotactl_valid(sb, type, cmds, id);