|
@@ -292,11 +292,26 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* Return 1 if 'cmd' will block on frozen filesystem */
|
|
|
+static int quotactl_cmd_write(int cmd)
|
|
|
+{
|
|
|
+ switch (cmd) {
|
|
|
+ case Q_GETFMT:
|
|
|
+ case Q_GETINFO:
|
|
|
+ case Q_SYNC:
|
|
|
+ case Q_XGETQSTAT:
|
|
|
+ case Q_XGETQUOTA:
|
|
|
+ case Q_XQUOTASYNC:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* look up a superblock on which quota ops will be performed
|
|
|
* - use the name of a block device to find the superblock thereon
|
|
|
*/
|
|
|
-static struct super_block *quotactl_block(const char __user *special)
|
|
|
+static struct super_block *quotactl_block(const char __user *special, int cmd)
|
|
|
{
|
|
|
#ifdef CONFIG_BLOCK
|
|
|
struct block_device *bdev;
|
|
@@ -309,7 +324,10 @@ static struct super_block *quotactl_block(const char __user *special)
|
|
|
putname(tmp);
|
|
|
if (IS_ERR(bdev))
|
|
|
return ERR_CAST(bdev);
|
|
|
- sb = get_super(bdev);
|
|
|
+ if (quotactl_cmd_write(cmd))
|
|
|
+ sb = get_super_thawed(bdev);
|
|
|
+ else
|
|
|
+ sb = get_super(bdev);
|
|
|
bdput(bdev);
|
|
|
if (!sb)
|
|
|
return ERR_PTR(-ENODEV);
|
|
@@ -361,7 +379,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
|
|
|
pathp = &path;
|
|
|
}
|
|
|
|
|
|
- sb = quotactl_block(special);
|
|
|
+ sb = quotactl_block(special, cmds);
|
|
|
if (IS_ERR(sb)) {
|
|
|
ret = PTR_ERR(sb);
|
|
|
goto out;
|