* [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted
@ 2018-07-23 3:13 Sheng Yong
2018-07-23 12:49 ` Jaegeuk Kim
0 siblings, 1 reply; 5+ messages in thread
From: Sheng Yong @ 2018-07-23 3:13 UTC (permalink / raw)
To: jaegeuk, yuchao0; +Cc: miaoxie, linux-f2fs-devel
If a quota node is corrupted, it may be removed. But its qf_ino in
super blocks is not cleared. To keep quota feature available, let's
try to rebuild a new quota node.
Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
fsck/fsck.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
fsck/fsck.h | 1 +
fsck/mount.c | 7 +++--
3 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/fsck/fsck.c b/fsck/fsck.c
index e95dedf..dd10182 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -10,6 +10,7 @@
*/
#include "fsck.h"
#include "quotaio.h"
+#include "quotaio_v2.h"
#include <time.h>
char *tree_mark;
@@ -1697,13 +1698,80 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
}
ret = fsck_chk_node_blk(sbi, NULL, ino,
F2FS_FT_REG_FILE, TYPE_INODE, &blk_cnt, NULL);
- if (ret)
- ASSERT_MSG("wrong quota inode, qtype [%d] ino [0x%x]",
- qtype, ino);
+ if (ret) {
+ /* sanity_check_nid failed, node should be removed */
+ ASSERT_MSG("[0x%x] wrong quota inode", ino);
+ if (c.fix_on)
+ F2FS_FSCK(sbi)->corrupt_quotas = 1 << qtype;
+ }
}
return ret;
}
+static nid_t prepare_rebuild_qf_inode(struct f2fs_sb_info *sbi, int qtype)
+{
+ struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
+ struct f2fs_summary sum;
+ struct f2fs_node *qf_node;
+ nid_t nid = QUOTA_INO(F2FS_RAW_SUPER(sbi), qtype);
+ block_t node_blkaddr;
+ int ret;
+
+ DBG(1, "Rebuild Quota file (qtype [%3d] ino [0x%x])\n", qtype, nid);
+
+ qf_node = calloc(F2FS_BLKSIZE, 1);
+ if (!qf_node) {
+ MSG(0, "\tError: calloc failed for qf_inode!!!\n");
+ return 0;
+ }
+
+ /* prepare qf_node */
+ qf_node->footer.nid = cpu_to_le32(nid);
+ qf_node->footer.ino = cpu_to_le32(nid);
+ qf_node->footer.cp_ver = cpu_to_le64(get_cp(checkpoint_ver));
+
+ qf_node->i.i_mode = cpu_to_le16(0x8180);
+ qf_node->i.i_links = cpu_to_le32(1);
+ qf_node->i.i_uid = cpu_to_le32(getuid());
+ qf_node->i.i_gid = cpu_to_le32(getgid());
+ qf_node->i.i_size = 0;
+ qf_node->i.i_blocks = 1;
+ qf_node->i.i_atime = cpu_to_le32(time(NULL));
+ qf_node->i.i_atime_nsec = 0;
+ qf_node->i.i_ctime = cpu_to_le32(time(NULL));
+ qf_node->i.i_ctime_nsec = 0;
+ qf_node->i.i_mtime = cpu_to_le32(time(NULL));
+ qf_node->i.i_mtime_nsec = 0;
+ qf_node->i.i_generation = 0;
+ qf_node->i.i_xattr_nid = 0;
+ qf_node->i.i_flags = FS_IMMUTABLE_FL;
+ qf_node->i.i_current_depth = cpu_to_le32(1);
+ qf_node->i.i_dir_level = DEF_DIR_LEVEL;
+ if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
+ qf_node->i.i_inline = F2FS_EXTRA_ATTR;
+ qf_node->i.i_extra_isize =
+ cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
+ }
+ if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
+ qf_node->i.i_crtime = cpu_to_le32(time(NULL));
+ qf_node->i.i_crtime_nsec = 0;
+ }
+
+ /* write back qf inode */
+ node_blkaddr = 0;
+ set_summary(&sum, nid, 0, 0);
+ reserve_new_block(sbi, &node_blkaddr, &sum, CURSEG_HOT_NODE);
+ update_nat_blkaddr(sbi, nid, nid, node_blkaddr);
+ DBG(1, "Write new qf_node to blk %#x\n", node_blkaddr);
+
+ ret = dev_write_block(qf_node, node_blkaddr);
+ ASSERT(ret >= 0);
+ f2fs_clear_bit(nid, F2FS_FSCK(sbi)->nat_area_bitmap);
+
+ free(qf_node);
+ return nid;
+}
+
int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
{
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
@@ -1722,6 +1790,12 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
if (!ino)
continue;
+ if (fsck->corrupt_quotas & (1 << qtype) && c.fix_on) {
+ ino = prepare_rebuild_qf_inode(sbi, qtype);
+ if (!ino)
+ continue;
+ }
+
DBG(1, "Checking Quota file ([%3d] ino [0x%x])\n", qtype, ino);
needs_writeout = 0;
ret = quota_compare_and_update(sbi, qtype, &needs_writeout,
@@ -1733,7 +1807,7 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
/* Something is wrong */
if (c.fix_on) {
- DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
+ FIX_MSG("Fixing Quota file ([%3d] ino [0x%x])\n",
qtype, ino);
f2fs_filesize_update(sbi, ino, 0);
ret = quota_write_inode(sbi, qtype);
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 580e851..393c995 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -91,6 +91,7 @@ struct f2fs_fsck {
u32 nat_valid_inode_cnt;
struct quota_ctx *qctx;
+ unsigned short corrupt_quotas;
};
#define BLOCK_SZ 4096
diff --git a/fsck/mount.c b/fsck/mount.c
index 3c9607f..121b26a 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -2022,8 +2022,11 @@ int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, int type)
if (se2->valid_blocks)
break;
}
- if (i == sbi->segs_per_sec)
+ if (i == sbi->segs_per_sec) {
+ /* find a free seg, init its type */
+ se->orig_type = type;
return 0;
+ }
}
if (se->type == type &&
@@ -2244,7 +2247,7 @@ void write_superblock(struct f2fs_super_block *new_sb)
ASSERT(ret >= 0);
}
free(buf);
- DBG(0, "Info: Done to rebuild superblock\n");
+ MSG(0, "Info: Done to rebuild superblock\n");
}
void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
--
2.17.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted
2018-07-23 3:13 [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted Sheng Yong
@ 2018-07-23 12:49 ` Jaegeuk Kim
2018-07-24 2:11 ` Sheng Yong
0 siblings, 1 reply; 5+ messages in thread
From: Jaegeuk Kim @ 2018-07-23 12:49 UTC (permalink / raw)
To: Sheng Yong; +Cc: miaoxie, linux-f2fs-devel
On 07/23, Sheng Yong wrote:
> If a quota node is corrupted, it may be removed. But its qf_ino in
> super blocks is not cleared. To keep quota feature available, let's
> try to rebuild a new quota node.
Hi Sheng,
IIRC, we need to rebuild whole quota structures, no?
Thanks,
>
> Signed-off-by: Sheng Yong <shengyong1@huawei.com>
> ---
> fsck/fsck.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
> fsck/fsck.h | 1 +
> fsck/mount.c | 7 +++--
> 3 files changed, 84 insertions(+), 6 deletions(-)
>
> diff --git a/fsck/fsck.c b/fsck/fsck.c
> index e95dedf..dd10182 100644
> --- a/fsck/fsck.c
> +++ b/fsck/fsck.c
> @@ -10,6 +10,7 @@
> */
> #include "fsck.h"
> #include "quotaio.h"
> +#include "quotaio_v2.h"
> #include <time.h>
>
> char *tree_mark;
> @@ -1697,13 +1698,80 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
> }
> ret = fsck_chk_node_blk(sbi, NULL, ino,
> F2FS_FT_REG_FILE, TYPE_INODE, &blk_cnt, NULL);
> - if (ret)
> - ASSERT_MSG("wrong quota inode, qtype [%d] ino [0x%x]",
> - qtype, ino);
> + if (ret) {
> + /* sanity_check_nid failed, node should be removed */
> + ASSERT_MSG("[0x%x] wrong quota inode", ino);
> + if (c.fix_on)
> + F2FS_FSCK(sbi)->corrupt_quotas = 1 << qtype;
> + }
> }
> return ret;
> }
>
> +static nid_t prepare_rebuild_qf_inode(struct f2fs_sb_info *sbi, int qtype)
> +{
> + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
> + struct f2fs_summary sum;
> + struct f2fs_node *qf_node;
> + nid_t nid = QUOTA_INO(F2FS_RAW_SUPER(sbi), qtype);
> + block_t node_blkaddr;
> + int ret;
> +
> + DBG(1, "Rebuild Quota file (qtype [%3d] ino [0x%x])\n", qtype, nid);
> +
> + qf_node = calloc(F2FS_BLKSIZE, 1);
> + if (!qf_node) {
> + MSG(0, "\tError: calloc failed for qf_inode!!!\n");
> + return 0;
> + }
> +
> + /* prepare qf_node */
> + qf_node->footer.nid = cpu_to_le32(nid);
> + qf_node->footer.ino = cpu_to_le32(nid);
> + qf_node->footer.cp_ver = cpu_to_le64(get_cp(checkpoint_ver));
> +
> + qf_node->i.i_mode = cpu_to_le16(0x8180);
> + qf_node->i.i_links = cpu_to_le32(1);
> + qf_node->i.i_uid = cpu_to_le32(getuid());
> + qf_node->i.i_gid = cpu_to_le32(getgid());
> + qf_node->i.i_size = 0;
> + qf_node->i.i_blocks = 1;
> + qf_node->i.i_atime = cpu_to_le32(time(NULL));
> + qf_node->i.i_atime_nsec = 0;
> + qf_node->i.i_ctime = cpu_to_le32(time(NULL));
> + qf_node->i.i_ctime_nsec = 0;
> + qf_node->i.i_mtime = cpu_to_le32(time(NULL));
> + qf_node->i.i_mtime_nsec = 0;
> + qf_node->i.i_generation = 0;
> + qf_node->i.i_xattr_nid = 0;
> + qf_node->i.i_flags = FS_IMMUTABLE_FL;
> + qf_node->i.i_current_depth = cpu_to_le32(1);
> + qf_node->i.i_dir_level = DEF_DIR_LEVEL;
> + if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
> + qf_node->i.i_inline = F2FS_EXTRA_ATTR;
> + qf_node->i.i_extra_isize =
> + cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
> + }
> + if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
> + qf_node->i.i_crtime = cpu_to_le32(time(NULL));
> + qf_node->i.i_crtime_nsec = 0;
> + }
> +
> + /* write back qf inode */
> + node_blkaddr = 0;
> + set_summary(&sum, nid, 0, 0);
> + reserve_new_block(sbi, &node_blkaddr, &sum, CURSEG_HOT_NODE);
> + update_nat_blkaddr(sbi, nid, nid, node_blkaddr);
> + DBG(1, "Write new qf_node to blk %#x\n", node_blkaddr);
> +
> + ret = dev_write_block(qf_node, node_blkaddr);
> + ASSERT(ret >= 0);
> + f2fs_clear_bit(nid, F2FS_FSCK(sbi)->nat_area_bitmap);
> +
> + free(qf_node);
> + return nid;
> +}
> +
> int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> {
> struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> @@ -1722,6 +1790,12 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> if (!ino)
> continue;
>
> + if (fsck->corrupt_quotas & (1 << qtype) && c.fix_on) {
> + ino = prepare_rebuild_qf_inode(sbi, qtype);
> + if (!ino)
> + continue;
> + }
> +
> DBG(1, "Checking Quota file ([%3d] ino [0x%x])\n", qtype, ino);
> needs_writeout = 0;
> ret = quota_compare_and_update(sbi, qtype, &needs_writeout,
> @@ -1733,7 +1807,7 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>
> /* Something is wrong */
> if (c.fix_on) {
> - DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
> + FIX_MSG("Fixing Quota file ([%3d] ino [0x%x])\n",
> qtype, ino);
> f2fs_filesize_update(sbi, ino, 0);
> ret = quota_write_inode(sbi, qtype);
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index 580e851..393c995 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -91,6 +91,7 @@ struct f2fs_fsck {
> u32 nat_valid_inode_cnt;
>
> struct quota_ctx *qctx;
> + unsigned short corrupt_quotas;
> };
>
> #define BLOCK_SZ 4096
> diff --git a/fsck/mount.c b/fsck/mount.c
> index 3c9607f..121b26a 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -2022,8 +2022,11 @@ int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, int type)
> if (se2->valid_blocks)
> break;
> }
> - if (i == sbi->segs_per_sec)
> + if (i == sbi->segs_per_sec) {
> + /* find a free seg, init its type */
> + se->orig_type = type;
> return 0;
> + }
> }
>
> if (se->type == type &&
> @@ -2244,7 +2247,7 @@ void write_superblock(struct f2fs_super_block *new_sb)
> ASSERT(ret >= 0);
> }
> free(buf);
> - DBG(0, "Info: Done to rebuild superblock\n");
> + MSG(0, "Info: Done to rebuild superblock\n");
> }
>
> void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
> --
> 2.17.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted
2018-07-23 12:49 ` Jaegeuk Kim
@ 2018-07-24 2:11 ` Sheng Yong
2018-07-27 9:23 ` Jaegeuk Kim
0 siblings, 1 reply; 5+ messages in thread
From: Sheng Yong @ 2018-07-24 2:11 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: hyojun, linux-f2fs-devel, miaoxie
Hi, Jaegeuk
On 2018/7/23 20:49, Jaegeuk Kim wrote:
> On 07/23, Sheng Yong wrote:
>> If a quota node is corrupted, it may be removed. But its qf_ino in
>> super blocks is not cleared. To keep quota feature available, let's
>> try to rebuild a new quota node.
>
> Hi Sheng,
>
> IIRC, we need to rebuild whole quota structures, no?
>
I'm afraid not. Fsck records all dquot entries to a dict during checking all files.
If a quota file is removed or quota content is corrupted, quota_write_inode (in
fsck_chk_quota_files) will rebuild quota structures for us according to data recorded
in the dict. We only have to make sure the inode of a quota file is correct.
In the scenario where a quota file is removed, I think, rebuilding the inode of the
unreachable quota file is enough. Am I missing something?
thanks,
Sheng
> Thanks,
>
>>
>> Signed-off-by: Sheng Yong <shengyong1@huawei.com>
>> ---
>> fsck/fsck.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
>> fsck/fsck.h | 1 +
>> fsck/mount.c | 7 +++--
>> 3 files changed, 84 insertions(+), 6 deletions(-)
>>
>> diff --git a/fsck/fsck.c b/fsck/fsck.c
>> index e95dedf..dd10182 100644
>> --- a/fsck/fsck.c
>> +++ b/fsck/fsck.c
>> @@ -10,6 +10,7 @@
>> */
>> #include "fsck.h"
>> #include "quotaio.h"
>> +#include "quotaio_v2.h"
>> #include <time.h>
>>
>> char *tree_mark;
>> @@ -1697,13 +1698,80 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
>> }
>> ret = fsck_chk_node_blk(sbi, NULL, ino,
>> F2FS_FT_REG_FILE, TYPE_INODE, &blk_cnt, NULL);
>> - if (ret)
>> - ASSERT_MSG("wrong quota inode, qtype [%d] ino [0x%x]",
>> - qtype, ino);
>> + if (ret) {
>> + /* sanity_check_nid failed, node should be removed */
>> + ASSERT_MSG("[0x%x] wrong quota inode", ino);
>> + if (c.fix_on)
>> + F2FS_FSCK(sbi)->corrupt_quotas = 1 << qtype;
>> + }
>> }
>> return ret;
>> }
>>
>> +static nid_t prepare_rebuild_qf_inode(struct f2fs_sb_info *sbi, int qtype)
>> +{
>> + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
>> + struct f2fs_summary sum;
>> + struct f2fs_node *qf_node;
>> + nid_t nid = QUOTA_INO(F2FS_RAW_SUPER(sbi), qtype);
>> + block_t node_blkaddr;
>> + int ret;
>> +
>> + DBG(1, "Rebuild Quota file (qtype [%3d] ino [0x%x])\n", qtype, nid);
>> +
>> + qf_node = calloc(F2FS_BLKSIZE, 1);
>> + if (!qf_node) {
>> + MSG(0, "\tError: calloc failed for qf_inode!!!\n");
>> + return 0;
>> + }
>> +
>> + /* prepare qf_node */
>> + qf_node->footer.nid = cpu_to_le32(nid);
>> + qf_node->footer.ino = cpu_to_le32(nid);
>> + qf_node->footer.cp_ver = cpu_to_le64(get_cp(checkpoint_ver));
>> +
>> + qf_node->i.i_mode = cpu_to_le16(0x8180);
>> + qf_node->i.i_links = cpu_to_le32(1);
>> + qf_node->i.i_uid = cpu_to_le32(getuid());
>> + qf_node->i.i_gid = cpu_to_le32(getgid());
>> + qf_node->i.i_size = 0;
>> + qf_node->i.i_blocks = 1;
>> + qf_node->i.i_atime = cpu_to_le32(time(NULL));
>> + qf_node->i.i_atime_nsec = 0;
>> + qf_node->i.i_ctime = cpu_to_le32(time(NULL));
>> + qf_node->i.i_ctime_nsec = 0;
>> + qf_node->i.i_mtime = cpu_to_le32(time(NULL));
>> + qf_node->i.i_mtime_nsec = 0;
>> + qf_node->i.i_generation = 0;
>> + qf_node->i.i_xattr_nid = 0;
>> + qf_node->i.i_flags = FS_IMMUTABLE_FL;
>> + qf_node->i.i_current_depth = cpu_to_le32(1);
>> + qf_node->i.i_dir_level = DEF_DIR_LEVEL;
>> + if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
>> + qf_node->i.i_inline = F2FS_EXTRA_ATTR;
>> + qf_node->i.i_extra_isize =
>> + cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
>> + }
>> + if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
>> + qf_node->i.i_crtime = cpu_to_le32(time(NULL));
>> + qf_node->i.i_crtime_nsec = 0;
>> + }
>> +
>> + /* write back qf inode */
>> + node_blkaddr = 0;
>> + set_summary(&sum, nid, 0, 0);
>> + reserve_new_block(sbi, &node_blkaddr, &sum, CURSEG_HOT_NODE);
>> + update_nat_blkaddr(sbi, nid, nid, node_blkaddr);
>> + DBG(1, "Write new qf_node to blk %#x\n", node_blkaddr);
>> +
>> + ret = dev_write_block(qf_node, node_blkaddr);
Ah.. It should be write_inode instead of dev_write_block.
>> + ASSERT(ret >= 0);
>> + f2fs_clear_bit(nid, F2FS_FSCK(sbi)->nat_area_bitmap);
>> +
>> + free(qf_node);
>> + return nid;
>> +}
>> +
>> int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>> {
>> struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
>> @@ -1722,6 +1790,12 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>> if (!ino)
>> continue;
>>
>> + if (fsck->corrupt_quotas & (1 << qtype) && c.fix_on) {
>> + ino = prepare_rebuild_qf_inode(sbi, qtype);
>> + if (!ino)
>> + continue;
>> + }
>> +
>> DBG(1, "Checking Quota file ([%3d] ino [0x%x])\n", qtype, ino);
>> needs_writeout = 0;
>> ret = quota_compare_and_update(sbi, qtype, &needs_writeout,
>> @@ -1733,7 +1807,7 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>>
>> /* Something is wrong */
>> if (c.fix_on) {
>> - DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
>> + FIX_MSG("Fixing Quota file ([%3d] ino [0x%x])\n",
>> qtype, ino);
>> f2fs_filesize_update(sbi, ino, 0);
>> ret = quota_write_inode(sbi, qtype);
>> diff --git a/fsck/fsck.h b/fsck/fsck.h
>> index 580e851..393c995 100644
>> --- a/fsck/fsck.h
>> +++ b/fsck/fsck.h
>> @@ -91,6 +91,7 @@ struct f2fs_fsck {
>> u32 nat_valid_inode_cnt;
>>
>> struct quota_ctx *qctx;
>> + unsigned short corrupt_quotas;
>> };
>>
>> #define BLOCK_SZ 4096
>> diff --git a/fsck/mount.c b/fsck/mount.c
>> index 3c9607f..121b26a 100644
>> --- a/fsck/mount.c
>> +++ b/fsck/mount.c
>> @@ -2022,8 +2022,11 @@ int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, int type)
>> if (se2->valid_blocks)
>> break;
>> }
>> - if (i == sbi->segs_per_sec)
>> + if (i == sbi->segs_per_sec) {
>> + /* find a free seg, init its type */
>> + se->orig_type = type;
>> return 0;
>> + }
>> }
>>
>> if (se->type == type &&
>> @@ -2244,7 +2247,7 @@ void write_superblock(struct f2fs_super_block *new_sb)
>> ASSERT(ret >= 0);
>> }
>> free(buf);
>> - DBG(0, "Info: Done to rebuild superblock\n");
>> + MSG(0, "Info: Done to rebuild superblock\n");
>> }
>>
>> void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
>> --
>> 2.17.1
>
> .
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted
2018-07-24 2:11 ` Sheng Yong
@ 2018-07-27 9:23 ` Jaegeuk Kim
2018-07-28 1:40 ` Sheng Yong
0 siblings, 1 reply; 5+ messages in thread
From: Jaegeuk Kim @ 2018-07-27 9:23 UTC (permalink / raw)
To: Sheng Yong; +Cc: hyojun, linux-f2fs-devel, miaoxie
On 07/24, Sheng Yong wrote:
> Hi, Jaegeuk
>
> On 2018/7/23 20:49, Jaegeuk Kim wrote:
> > On 07/23, Sheng Yong wrote:
> > > If a quota node is corrupted, it may be removed. But its qf_ino in
> > > super blocks is not cleared. To keep quota feature available, let's
> > > try to rebuild a new quota node.
> >
> > Hi Sheng,
> >
> > IIRC, we need to rebuild whole quota structures, no?
> >
> I'm afraid not. Fsck records all dquot entries to a dict during checking all files.
> If a quota file is removed or quota content is corrupted, quota_write_inode (in
> fsck_chk_quota_files) will rebuild quota structures for us according to data recorded
> in the dict. We only have to make sure the inode of a quota file is correct.
>
> In the scenario where a quota file is removed, I think, rebuilding the inode of the
> unreachable quota file is enough. Am I missing something?
Ahha, got the point. Can we consider trying this iff there is no error found in
other areas? I'm not slightly sure whether we can get a valid node block to store
the new node. If it's wrong, we're going to corrupt the partition more.
Thanks,
>
> thanks,
> Sheng
>
> > Thanks,
> >
> > >
> > > Signed-off-by: Sheng Yong <shengyong1@huawei.com>
> > > ---
> > > fsck/fsck.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
> > > fsck/fsck.h | 1 +
> > > fsck/mount.c | 7 +++--
> > > 3 files changed, 84 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/fsck/fsck.c b/fsck/fsck.c
> > > index e95dedf..dd10182 100644
> > > --- a/fsck/fsck.c
> > > +++ b/fsck/fsck.c
> > > @@ -10,6 +10,7 @@
> > > */
> > > #include "fsck.h"
> > > #include "quotaio.h"
> > > +#include "quotaio_v2.h"
> > > #include <time.h>
> > > char *tree_mark;
> > > @@ -1697,13 +1698,80 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
> > > }
> > > ret = fsck_chk_node_blk(sbi, NULL, ino,
> > > F2FS_FT_REG_FILE, TYPE_INODE, &blk_cnt, NULL);
> > > - if (ret)
> > > - ASSERT_MSG("wrong quota inode, qtype [%d] ino [0x%x]",
> > > - qtype, ino);
> > > + if (ret) {
> > > + /* sanity_check_nid failed, node should be removed */
> > > + ASSERT_MSG("[0x%x] wrong quota inode", ino);
> > > + if (c.fix_on)
> > > + F2FS_FSCK(sbi)->corrupt_quotas = 1 << qtype;
> > > + }
> > > }
> > > return ret;
> > > }
> > > +static nid_t prepare_rebuild_qf_inode(struct f2fs_sb_info *sbi, int qtype)
> > > +{
> > > + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
> > > + struct f2fs_summary sum;
> > > + struct f2fs_node *qf_node;
> > > + nid_t nid = QUOTA_INO(F2FS_RAW_SUPER(sbi), qtype);
> > > + block_t node_blkaddr;
> > > + int ret;
> > > +
> > > + DBG(1, "Rebuild Quota file (qtype [%3d] ino [0x%x])\n", qtype, nid);
> > > +
> > > + qf_node = calloc(F2FS_BLKSIZE, 1);
> > > + if (!qf_node) {
> > > + MSG(0, "\tError: calloc failed for qf_inode!!!\n");
> > > + return 0;
> > > + }
> > > +
> > > + /* prepare qf_node */
> > > + qf_node->footer.nid = cpu_to_le32(nid);
> > > + qf_node->footer.ino = cpu_to_le32(nid);
> > > + qf_node->footer.cp_ver = cpu_to_le64(get_cp(checkpoint_ver));
> > > +
> > > + qf_node->i.i_mode = cpu_to_le16(0x8180);
> > > + qf_node->i.i_links = cpu_to_le32(1);
> > > + qf_node->i.i_uid = cpu_to_le32(getuid());
> > > + qf_node->i.i_gid = cpu_to_le32(getgid());
> > > + qf_node->i.i_size = 0;
> > > + qf_node->i.i_blocks = 1;
> > > + qf_node->i.i_atime = cpu_to_le32(time(NULL));
> > > + qf_node->i.i_atime_nsec = 0;
> > > + qf_node->i.i_ctime = cpu_to_le32(time(NULL));
> > > + qf_node->i.i_ctime_nsec = 0;
> > > + qf_node->i.i_mtime = cpu_to_le32(time(NULL));
> > > + qf_node->i.i_mtime_nsec = 0;
> > > + qf_node->i.i_generation = 0;
> > > + qf_node->i.i_xattr_nid = 0;
> > > + qf_node->i.i_flags = FS_IMMUTABLE_FL;
> > > + qf_node->i.i_current_depth = cpu_to_le32(1);
> > > + qf_node->i.i_dir_level = DEF_DIR_LEVEL;
> > > + if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
> > > + qf_node->i.i_inline = F2FS_EXTRA_ATTR;
> > > + qf_node->i.i_extra_isize =
> > > + cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
> > > + }
> > > + if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
> > > + qf_node->i.i_crtime = cpu_to_le32(time(NULL));
> > > + qf_node->i.i_crtime_nsec = 0;
> > > + }
> > > +
> > > + /* write back qf inode */
> > > + node_blkaddr = 0;
> > > + set_summary(&sum, nid, 0, 0);
> > > + reserve_new_block(sbi, &node_blkaddr, &sum, CURSEG_HOT_NODE);
> > > + update_nat_blkaddr(sbi, nid, nid, node_blkaddr);
> > > + DBG(1, "Write new qf_node to blk %#x\n", node_blkaddr);
> > > +
> > > + ret = dev_write_block(qf_node, node_blkaddr);
>
> Ah.. It should be write_inode instead of dev_write_block.
>
> > > + ASSERT(ret >= 0);
> > > + f2fs_clear_bit(nid, F2FS_FSCK(sbi)->nat_area_bitmap);
> > > +
> > > + free(qf_node);
> > > + return nid;
> > > +}
> > > +
> > > int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> > > {
> > > struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> > > @@ -1722,6 +1790,12 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> > > if (!ino)
> > > continue;
> > > + if (fsck->corrupt_quotas & (1 << qtype) && c.fix_on) {
> > > + ino = prepare_rebuild_qf_inode(sbi, qtype);
> > > + if (!ino)
> > > + continue;
> > > + }
> > > +
> > > DBG(1, "Checking Quota file ([%3d] ino [0x%x])\n", qtype, ino);
> > > needs_writeout = 0;
> > > ret = quota_compare_and_update(sbi, qtype, &needs_writeout,
> > > @@ -1733,7 +1807,7 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> > > /* Something is wrong */
> > > if (c.fix_on) {
> > > - DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
> > > + FIX_MSG("Fixing Quota file ([%3d] ino [0x%x])\n",
> > > qtype, ino);
> > > f2fs_filesize_update(sbi, ino, 0);
> > > ret = quota_write_inode(sbi, qtype);
> > > diff --git a/fsck/fsck.h b/fsck/fsck.h
> > > index 580e851..393c995 100644
> > > --- a/fsck/fsck.h
> > > +++ b/fsck/fsck.h
> > > @@ -91,6 +91,7 @@ struct f2fs_fsck {
> > > u32 nat_valid_inode_cnt;
> > > struct quota_ctx *qctx;
> > > + unsigned short corrupt_quotas;
> > > };
> > > #define BLOCK_SZ 4096
> > > diff --git a/fsck/mount.c b/fsck/mount.c
> > > index 3c9607f..121b26a 100644
> > > --- a/fsck/mount.c
> > > +++ b/fsck/mount.c
> > > @@ -2022,8 +2022,11 @@ int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, int type)
> > > if (se2->valid_blocks)
> > > break;
> > > }
> > > - if (i == sbi->segs_per_sec)
> > > + if (i == sbi->segs_per_sec) {
> > > + /* find a free seg, init its type */
> > > + se->orig_type = type;
> > > return 0;
> > > + }
> > > }
> > > if (se->type == type &&
> > > @@ -2244,7 +2247,7 @@ void write_superblock(struct f2fs_super_block *new_sb)
> > > ASSERT(ret >= 0);
> > > }
> > > free(buf);
> > > - DBG(0, "Info: Done to rebuild superblock\n");
> > > + MSG(0, "Info: Done to rebuild superblock\n");
> > > }
> > > void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
> > > --
> > > 2.17.1
> >
> > .
> >
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted
2018-07-27 9:23 ` Jaegeuk Kim
@ 2018-07-28 1:40 ` Sheng Yong
0 siblings, 0 replies; 5+ messages in thread
From: Sheng Yong @ 2018-07-28 1:40 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: hyojun, linux-f2fs-devel, miaoxie
On 2018/7/27 17:23, Jaegeuk Kim wrote:
> On 07/24, Sheng Yong wrote:
>> Hi, Jaegeuk
>>
>> On 2018/7/23 20:49, Jaegeuk Kim wrote:
>>> On 07/23, Sheng Yong wrote:
>>>> If a quota node is corrupted, it may be removed. But its qf_ino in
>>>> super blocks is not cleared. To keep quota feature available, let's
>>>> try to rebuild a new quota node.
>>>
>>> Hi Sheng,
>>>
>>> IIRC, we need to rebuild whole quota structures, no?
>>>
>> I'm afraid not. Fsck records all dquot entries to a dict during checking all files.
>> If a quota file is removed or quota content is corrupted, quota_write_inode (in
>> fsck_chk_quota_files) will rebuild quota structures for us according to data recorded
>> in the dict. We only have to make sure the inode of a quota file is correct.
>>
>> In the scenario where a quota file is removed, I think, rebuilding the inode of the
>> unreachable quota file is enough. Am I missing something?
>
> Ahha, got the point. Can we consider trying this iff there is no error found in
> other areas? I'm not slightly sure whether we can get a valid node block to store
> the new node. If it's wrong, we're going to corrupt the partition more.
Right, we must be careful when allocating blocks in fsck. I think reserve_new_block(),
called by fsck, should have more check to ensure blkaddr is really free. I'll try to
fix that.
thanks
>
> Thanks,
>
>>
>> thanks,
>> Sheng
>>
>>> Thanks,
>>>
>>>>
>>>> Signed-off-by: Sheng Yong <shengyong1@huawei.com>
>>>> ---
>>>> fsck/fsck.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
>>>> fsck/fsck.h | 1 +
>>>> fsck/mount.c | 7 +++--
>>>> 3 files changed, 84 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/fsck/fsck.c b/fsck/fsck.c
>>>> index e95dedf..dd10182 100644
>>>> --- a/fsck/fsck.c
>>>> +++ b/fsck/fsck.c
>>>> @@ -10,6 +10,7 @@
>>>> */
>>>> #include "fsck.h"
>>>> #include "quotaio.h"
>>>> +#include "quotaio_v2.h"
>>>> #include <time.h>
>>>> char *tree_mark;
>>>> @@ -1697,13 +1698,80 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
>>>> }
>>>> ret = fsck_chk_node_blk(sbi, NULL, ino,
>>>> F2FS_FT_REG_FILE, TYPE_INODE, &blk_cnt, NULL);
>>>> - if (ret)
>>>> - ASSERT_MSG("wrong quota inode, qtype [%d] ino [0x%x]",
>>>> - qtype, ino);
>>>> + if (ret) {
>>>> + /* sanity_check_nid failed, node should be removed */
>>>> + ASSERT_MSG("[0x%x] wrong quota inode", ino);
>>>> + if (c.fix_on)
>>>> + F2FS_FSCK(sbi)->corrupt_quotas = 1 << qtype;
>>>> + }
>>>> }
>>>> return ret;
>>>> }
>>>> +static nid_t prepare_rebuild_qf_inode(struct f2fs_sb_info *sbi, int qtype)
>>>> +{
>>>> + struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
>>>> + struct f2fs_summary sum;
>>>> + struct f2fs_node *qf_node;
>>>> + nid_t nid = QUOTA_INO(F2FS_RAW_SUPER(sbi), qtype);
>>>> + block_t node_blkaddr;
>>>> + int ret;
>>>> +
>>>> + DBG(1, "Rebuild Quota file (qtype [%3d] ino [0x%x])\n", qtype, nid);
>>>> +
>>>> + qf_node = calloc(F2FS_BLKSIZE, 1);
>>>> + if (!qf_node) {
>>>> + MSG(0, "\tError: calloc failed for qf_inode!!!\n");
>>>> + return 0;
>>>> + }
>>>> +
>>>> + /* prepare qf_node */
>>>> + qf_node->footer.nid = cpu_to_le32(nid);
>>>> + qf_node->footer.ino = cpu_to_le32(nid);
>>>> + qf_node->footer.cp_ver = cpu_to_le64(get_cp(checkpoint_ver));
>>>> +
>>>> + qf_node->i.i_mode = cpu_to_le16(0x8180);
>>>> + qf_node->i.i_links = cpu_to_le32(1);
>>>> + qf_node->i.i_uid = cpu_to_le32(getuid());
>>>> + qf_node->i.i_gid = cpu_to_le32(getgid());
>>>> + qf_node->i.i_size = 0;
>>>> + qf_node->i.i_blocks = 1;
>>>> + qf_node->i.i_atime = cpu_to_le32(time(NULL));
>>>> + qf_node->i.i_atime_nsec = 0;
>>>> + qf_node->i.i_ctime = cpu_to_le32(time(NULL));
>>>> + qf_node->i.i_ctime_nsec = 0;
>>>> + qf_node->i.i_mtime = cpu_to_le32(time(NULL));
>>>> + qf_node->i.i_mtime_nsec = 0;
>>>> + qf_node->i.i_generation = 0;
>>>> + qf_node->i.i_xattr_nid = 0;
>>>> + qf_node->i.i_flags = FS_IMMUTABLE_FL;
>>>> + qf_node->i.i_current_depth = cpu_to_le32(1);
>>>> + qf_node->i.i_dir_level = DEF_DIR_LEVEL;
>>>> + if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) {
>>>> + qf_node->i.i_inline = F2FS_EXTRA_ATTR;
>>>> + qf_node->i.i_extra_isize =
>>>> + cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE);
>>>> + }
>>>> + if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
>>>> + qf_node->i.i_crtime = cpu_to_le32(time(NULL));
>>>> + qf_node->i.i_crtime_nsec = 0;
>>>> + }
>>>> +
>>>> + /* write back qf inode */
>>>> + node_blkaddr = 0;
>>>> + set_summary(&sum, nid, 0, 0);
>>>> + reserve_new_block(sbi, &node_blkaddr, &sum, CURSEG_HOT_NODE);
>>>> + update_nat_blkaddr(sbi, nid, nid, node_blkaddr);
>>>> + DBG(1, "Write new qf_node to blk %#x\n", node_blkaddr);
>>>> +
>>>> + ret = dev_write_block(qf_node, node_blkaddr);
>>
>> Ah.. It should be write_inode instead of dev_write_block.
>>
>>>> + ASSERT(ret >= 0);
>>>> + f2fs_clear_bit(nid, F2FS_FSCK(sbi)->nat_area_bitmap);
>>>> +
>>>> + free(qf_node);
>>>> + return nid;
>>>> +}
>>>> +
>>>> int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>>>> {
>>>> struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
>>>> @@ -1722,6 +1790,12 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>>>> if (!ino)
>>>> continue;
>>>> + if (fsck->corrupt_quotas & (1 << qtype) && c.fix_on) {
>>>> + ino = prepare_rebuild_qf_inode(sbi, qtype);
>>>> + if (!ino)
>>>> + continue;
>>>> + }
>>>> +
>>>> DBG(1, "Checking Quota file ([%3d] ino [0x%x])\n", qtype, ino);
>>>> needs_writeout = 0;
>>>> ret = quota_compare_and_update(sbi, qtype, &needs_writeout,
>>>> @@ -1733,7 +1807,7 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
>>>> /* Something is wrong */
>>>> if (c.fix_on) {
>>>> - DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
>>>> + FIX_MSG("Fixing Quota file ([%3d] ino [0x%x])\n",
>>>> qtype, ino);
>>>> f2fs_filesize_update(sbi, ino, 0);
>>>> ret = quota_write_inode(sbi, qtype);
>>>> diff --git a/fsck/fsck.h b/fsck/fsck.h
>>>> index 580e851..393c995 100644
>>>> --- a/fsck/fsck.h
>>>> +++ b/fsck/fsck.h
>>>> @@ -91,6 +91,7 @@ struct f2fs_fsck {
>>>> u32 nat_valid_inode_cnt;
>>>> struct quota_ctx *qctx;
>>>> + unsigned short corrupt_quotas;
>>>> };
>>>> #define BLOCK_SZ 4096
>>>> diff --git a/fsck/mount.c b/fsck/mount.c
>>>> index 3c9607f..121b26a 100644
>>>> --- a/fsck/mount.c
>>>> +++ b/fsck/mount.c
>>>> @@ -2022,8 +2022,11 @@ int find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, int type)
>>>> if (se2->valid_blocks)
>>>> break;
>>>> }
>>>> - if (i == sbi->segs_per_sec)
>>>> + if (i == sbi->segs_per_sec) {
>>>> + /* find a free seg, init its type */
>>>> + se->orig_type = type;
>>>> return 0;
>>>> + }
>>>> }
>>>> if (se->type == type &&
>>>> @@ -2244,7 +2247,7 @@ void write_superblock(struct f2fs_super_block *new_sb)
>>>> ASSERT(ret >= 0);
>>>> }
>>>> free(buf);
>>>> - DBG(0, "Info: Done to rebuild superblock\n");
>>>> + MSG(0, "Info: Done to rebuild superblock\n");
>>>> }
>>>> void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
>>>> --
>>>> 2.17.1
>>>
>>> .
>>>
>
> .
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-07-28 1:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-23 3:13 [PATCH] fsck.f2fs: rebuild qf_ino if quota node is corrupted Sheng Yong
2018-07-23 12:49 ` Jaegeuk Kim
2018-07-24 2:11 ` Sheng Yong
2018-07-27 9:23 ` Jaegeuk Kim
2018-07-28 1:40 ` Sheng Yong
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.