aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota/quota.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/quota/quota.c')
-rw-r--r--fs/quota/quota.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 9af95c7a0bbe..f3d32b0d9008 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -20,6 +20,7 @@
#include <linux/writeback.h>
#include <linux/nospec.h>
#include "compat.h"
+#include "../internal.h"
static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
qid_t id)
@@ -868,6 +869,7 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
struct block_device *bdev;
struct super_block *sb;
struct filename *tmp = getname(special);
+ bool excl = false, thawed = false;
if (IS_ERR(tmp))
return ERR_CAST(tmp);
@@ -875,17 +877,32 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
putname(tmp);
if (IS_ERR(bdev))
return ERR_CAST(bdev);
- if (quotactl_cmd_onoff(cmd))
- sb = get_super_exclusive_thawed(bdev);
- else if (quotactl_cmd_write(cmd))
- sb = get_super_thawed(bdev);
- else
- sb = get_super(bdev);
+
+ if (quotactl_cmd_onoff(cmd)) {
+ excl = true;
+ thawed = true;
+ } else if (quotactl_cmd_write(cmd)) {
+ thawed = true;
+ }
+
+retry:
+ sb = __get_super(bdev, excl);
+ if (thawed && sb && sb->s_writers.frozen != SB_UNFROZEN) {
+ if (excl)
+ up_write(&sb->s_umount);
+ else
+ up_read(&sb->s_umount);
+ wait_event(sb->s_writers.wait_unfrozen,
+ sb->s_writers.frozen == SB_UNFROZEN);
+ put_super(sb);
+ goto retry;
+ }
+
bdput(bdev);
if (!sb)
return ERR_PTR(-ENODEV);
-
return sb;
+
#else
return ERR_PTR(-ENODEV);
#endif