author: Christoph Hellwig <hch@lst.de> 2020-11-16 15:21:18 +0100
committer: Jens Axboe <axboe@kernel.dk> 2020-12-01 14:53:38 -0700
commit: 60b498852bf219c0bf2b0864c69972840978ca43
parent: 5df1a6726973ee2444e11f16daa013971dc52e8b
Commit Summary:
Diffstat:
1 file changed, 22 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