diff options
author | Chao Yu <yuchao0@huawei.com> | 2019-07-25 05:33:37 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2019-08-23 10:57:12 -0400 |
commit | fe973b065bce0e61414c33251afae501a757f8c6 (patch) | |
tree | 6cc8f115a25c34d68242b6f7e301d8e68531de33 | |
parent | a25c2cdcb61ab3d8d99623a9e72cf1747979a1f9 (diff) |
f2fs: fix to handle quota_{on,off} correctly
With quota_ino feature on, generic/232 reports an inconsistence issue
on the image.
The root cause is that the testcase tries to:
- use quotactl to shutdown journalled quota based on sysfile;
- and then use quotactl to enable/turn on quota based on specific file
(aquota.user or aquota.group).
Eventually, quota sysfile will be out-of-update due to following specific
file creation.
Change as below to fix this issue:
- deny enabling quota based on specific file if quota sysfile exists.
- set SBI_QUOTA_NEED_REPAIR once sysfile based quota shutdowns via
ioctl.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/super.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 2d2c91c7eadd..9167deb0c417 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -2000,6 +2000,12 @@ static int f2fs_quota_on(struct super_block *sb, int type, int format_id, | |||
2000 | struct inode *inode; | 2000 | struct inode *inode; |
2001 | int err; | 2001 | int err; |
2002 | 2002 | ||
2003 | /* if quota sysfile exists, deny enabling quota with specific file */ | ||
2004 | if (f2fs_sb_has_quota_ino(F2FS_SB(sb))) { | ||
2005 | f2fs_err(F2FS_SB(sb), "quota sysfile already exists"); | ||
2006 | return -EBUSY; | ||
2007 | } | ||
2008 | |||
2003 | err = f2fs_quota_sync(sb, type); | 2009 | err = f2fs_quota_sync(sb, type); |
2004 | if (err) | 2010 | if (err) |
2005 | return err; | 2011 | return err; |
@@ -2019,7 +2025,7 @@ static int f2fs_quota_on(struct super_block *sb, int type, int format_id, | |||
2019 | return 0; | 2025 | return 0; |
2020 | } | 2026 | } |
2021 | 2027 | ||
2022 | static int f2fs_quota_off(struct super_block *sb, int type) | 2028 | static int __f2fs_quota_off(struct super_block *sb, int type) |
2023 | { | 2029 | { |
2024 | struct inode *inode = sb_dqopt(sb)->files[type]; | 2030 | struct inode *inode = sb_dqopt(sb)->files[type]; |
2025 | int err; | 2031 | int err; |
@@ -2045,13 +2051,30 @@ out_put: | |||
2045 | return err; | 2051 | return err; |
2046 | } | 2052 | } |
2047 | 2053 | ||
2054 | static int f2fs_quota_off(struct super_block *sb, int type) | ||
2055 | { | ||
2056 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
2057 | int err; | ||
2058 | |||
2059 | err = __f2fs_quota_off(sb, type); | ||
2060 | |||
2061 | /* | ||
2062 | * quotactl can shutdown journalled quota, result in inconsistence | ||
2063 | * between quota record and fs data by following updates, tag the | ||
2064 | * flag to let fsck be aware of it. | ||
2065 | */ | ||
2066 | if (is_journalled_quota(sbi)) | ||
2067 | set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); | ||
2068 | return err; | ||
2069 | } | ||
2070 | |||
2048 | void f2fs_quota_off_umount(struct super_block *sb) | 2071 | void f2fs_quota_off_umount(struct super_block *sb) |
2049 | { | 2072 | { |
2050 | int type; | 2073 | int type; |
2051 | int err; | 2074 | int err; |
2052 | 2075 | ||
2053 | for (type = 0; type < MAXQUOTAS; type++) { | 2076 | for (type = 0; type < MAXQUOTAS; type++) { |
2054 | err = f2fs_quota_off(sb, type); | 2077 | err = __f2fs_quota_off(sb, type); |
2055 | if (err) { | 2078 | if (err) { |
2056 | int ret = dquot_quota_off(sb, type); | 2079 | int ret = dquot_quota_off(sb, type); |
2057 | 2080 | ||