[f2fs-dev] [RFC PATCH 5/5] fsck.f2fs: reconnect unreachable files to lost+found
This patch introduces lost+found feature to fsck. If a file is found unreachable by fsck. Fsck tries to reconnect the file to lost+found directory: 1. Scan all unreachable file inodes, ignore non-inodes ones and directories. 2. Check them and fix incorrupted data to make sure filesystem metadata (mainly counters and main/nat bitmap) are all consistent. 3. Reconnect these files to lost+found. If lost+found does not exist, create it first. During reconnecting, expand lost+found's dentry block automatically. Reconnected files are renamed after its ino number. 4. If reconnect fails drop the node and restore filesystem metadata. Signed-off-by: Sheng Yong --- fsck/dir.c | 19 ++- fsck/fsck.c | 376 ++- fsck/fsck.h | 3 + fsck/mount.c | 2 + 4 files changed, 397 insertions(+), 3 deletions(-) diff --git a/fsck/dir.c b/fsck/dir.c index b2ea18f..567a4e9 100644 --- a/fsck/dir.c +++ b/fsck/dir.c @@ -176,6 +176,23 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi, return 0; } +/* return ino if file exists, otherwise return 0 */ +nid_t f2fs_lookup(struct f2fs_sb_info *sbi, struct f2fs_node *dir, + u8 *name, int len) +{ + int err; + struct dentry de = { + .name = name, + .len = len, + }; + + err = f2fs_find_entry(sbi, dir, &de); + if (err == 1) + return de.ino; + else + return 0; +} + static void f2fs_update_dentry(nid_t ino, int file_type, struct f2fs_dentry_ptr *d, const unsigned char *name, int len, f2fs_hash_t name_hash, @@ -199,7 +216,7 @@ static void f2fs_update_dentry(nid_t ino, int file_type, /* * f2fs_add_link - Add a new file(dir) to parent dir. */ -static int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent, +int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent, const unsigned char *name, int name_len, nid_t ino, int file_type, block_t p_blkaddr, int inc_link) { diff --git a/fsck/fsck.c b/fsck/fsck.c index fcaab14..81e1145 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -10,6 +10,7 @@ */ #include "fsck.h" #include "quotaio.h" +#include char *tree_mark; uint32_t tree_mark_size = 256; @@ -43,6 +44,14 @@ static inline int f2fs_test_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) fsck->main_area_bitmap); } +static inline int f2fs_clear_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + + return f2fs_clear_bit(BLKOFF_FROM_MAIN(sbi, blk), + fsck->main_area_bitmap); +} + static inline int f2fs_test_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); @@ -448,9 +457,11 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, /* workaround to fix later */ if (ftype != F2FS_FT_ORPHAN || - f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) + f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) { f2fs_clear_bit(nid, fsck->nat_area_bitmap); - else + /* avoid reusing nid when reconnecting files */ + f2fs_set_bit(nid, NM_I(sbi)->nid_bitmap); + } else ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n", nid); @@ -2041,6 +2052,362 @@ int check_sit_types(struct f2fs_sb_info *sbi) return err; } +static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi) +{ + struct f2fs_node *node; + struct node_info ni; + nid_t lpf_ino; + int err; + + /* read root inode first */ + node = calloc(F2FS_BLKSIZE, 1); + ASSERT(node); + get_node_info(sbi, F2FS_ROOT_INO(sbi), &ni); + err = dev_read_block(node, ni.blk_addr); + ASSERT(err >= 0); + + /* lookup lost+found in root directory */ + lpf_ino = f2fs_lookup(sbi, node, (u8 *) LPF, strlen(LPF)); + if (lpf_ino) { /* found */ + get_node_info(sbi, lpf_ino, &ni); + err = dev_read_block(node, ni.blk_addr); + ASSERT(err >= 0); + DBG(1, "Found lost+found 0x%x at blkaddr [0x%x]\n", + lpf_ino, ni.blk_addr); + if (!S_ISDIR(le16_to_cpu(node->i.i_mode))) { + ASSERT_MSG("lost+found is not directory [0%o]\n", + le16_to_cpu(node->i.i_mode)); + /* FIXME: give up? */ + goto out; + } + } else { /* not found, create it */ + struct dentry de; + + memset(&de, 0, sizeof(de)); + de.name = (u8 *) LPF; + de.len = strlen(LPF); + de.mode
Re: [f2fs-dev] [RFC PATCH 5/5] fsck.f2fs: reconnect unreachable files to lost+found
On 2018/2/6 12:31, Sheng Yong wrote: This patch introduces lost+found feature to fsck. If a file is found unreachable by fsck. Fsck tries to reconnect the file to lost+found directory: 1. Scan all unreachable file inodes, ignore non-inodes ones and directories. 2. Check them and fix incorrupted data to make sure filesystem metadata (mainly counters and main/nat bitmap) are all consistent. 3. Reconnect these files to lost+found. If lost+found does not exist, create it first. During reconnecting, expand lost+found's dentry block automatically. Reconnected files are renamed after its ino number. 4. If reconnect fails drop the node and restore filesystem metadata. Signed-off-by: Sheng Yong --- fsck/dir.c | 19 ++- fsck/fsck.c | 376 ++- fsck/fsck.h | 3 + fsck/mount.c | 2 + 4 files changed, 397 insertions(+), 3 deletions(-) diff --git a/fsck/dir.c b/fsck/dir.c index b2ea18f..567a4e9 100644 --- a/fsck/dir.c +++ b/fsck/dir.c @@ -176,6 +176,23 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi, return 0; } +/* return ino if file exists, otherwise return 0 */ +nid_t f2fs_lookup(struct f2fs_sb_info *sbi, struct f2fs_node *dir, + u8 *name, int len) +{ + int err; + struct dentry de = { + .name = name, + .len = len, + }; + + err = f2fs_find_entry(sbi, dir, &de); + if (err == 1) + return de.ino; + else + return 0; +} + static void f2fs_update_dentry(nid_t ino, int file_type, struct f2fs_dentry_ptr *d, const unsigned char *name, int len, f2fs_hash_t name_hash, @@ -199,7 +216,7 @@ static void f2fs_update_dentry(nid_t ino, int file_type, /* * f2fs_add_link - Add a new file(dir) to parent dir. */ -static int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent, +int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent, const unsigned char *name, int name_len, nid_t ino, int file_type, block_t p_blkaddr, int inc_link) { diff --git a/fsck/fsck.c b/fsck/fsck.c index fcaab14..81e1145 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -10,6 +10,7 @@ */ #include "fsck.h" #include "quotaio.h" +#include char *tree_mark; uint32_t tree_mark_size = 256; @@ -43,6 +44,14 @@ static inline int f2fs_test_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) fsck->main_area_bitmap); } +static inline int f2fs_clear_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) +{ + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); + + return f2fs_clear_bit(BLKOFF_FROM_MAIN(sbi, blk), + fsck->main_area_bitmap); +} + static inline int f2fs_test_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk) { struct f2fs_fsck *fsck = F2FS_FSCK(sbi); @@ -448,9 +457,11 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid, /* workaround to fix later */ if (ftype != F2FS_FT_ORPHAN || - f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) + f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) { f2fs_clear_bit(nid, fsck->nat_area_bitmap); - else + /* avoid reusing nid when reconnecting files */ + f2fs_set_bit(nid, NM_I(sbi)->nid_bitmap); + } else ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n", nid); @@ -2041,6 +2052,362 @@ int check_sit_types(struct f2fs_sb_info *sbi) return err; } +static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi) +{ + struct f2fs_node *node; + struct node_info ni; + nid_t lpf_ino; + int err; + + /* read root inode first */ + node = calloc(F2FS_BLKSIZE, 1); + ASSERT(node); + get_node_info(sbi, F2FS_ROOT_INO(sbi), &ni); + err = dev_read_block(node, ni.blk_addr); + ASSERT(err >= 0); + + /* lookup lost+found in root directory */ + lpf_ino = f2fs_lookup(sbi, node, (u8 *) LPF, strlen(LPF)); The 4th parameter should be namelen but not strlen(LPF). + if (lpf_ino) { /* found */ + get_node_info(sbi, lpf_ino, &ni); + err = dev_read_block(node, ni.blk_addr); + ASSERT(err >= 0); + DBG(1, "Found lost+found 0x%x at blkaddr [0x%x]\n", + lpf_ino, ni.blk_addr); + if (!S_ISDIR(le16_to_cpu(node->i.i_mode))) { + ASSERT_MSG("lost+found is not directory [0%o]\n", + le16_to_cpu(node->i.i_mode)); + /* FIXME: give up? */ + goto out; + } + } else { /* not found, create it */ + struct dentry de; + +
Re: [f2fs-dev] [RFC PATCH 5/5] fsck.f2fs: reconnect unreachable files to lost+found
On 2018/2/7 18:01, Sheng Yong wrote: [...] + +/* lookup lost+found in root directory */ +lpf_ino = f2fs_lookup(sbi, node, (u8 *) LPF, strlen(LPF)); The 4th parameter should be namelen but not strlen(LPF). Sorry for the noise. The comment here is wrong :( [...] + +static int fsck_do_reconnect_file(struct f2fs_sb_info *sbi, + struct f2fs_node *lpf, + struct f2fs_node *fnode) +{ +char name[80]; +size_t namelen; +nid_t ino = le32_to_cpu(fnode->footer.ino); +struct node_info ni; +int ret; + +namelen = snprintf(name, 80, "%u", ino); +if (namelen >= 80) +/* ignore terminating '\0', should never happen */ +namelen = 79; + +if (f2fs_lookup(sbi, lpf, (u8 *) name, strlen(LPF))) { The 4th parameter should be namelen but not strlen(LPF). +ASSERT_MSG("Name %s already exist in lost+found", name); +return -EEXIST; +} + [...] -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [RFC PATCH 5/5] fsck.f2fs: reconnect unreachable files to lost+found
On 2018/2/6 12:31, Sheng Yong wrote: > This patch introduces lost+found feature to fsck. If a file is found > unreachable by fsck. Fsck tries to reconnect the file to lost+found > directory: > 1. Scan all unreachable file inodes, ignore non-inodes ones and > directories. > 2. Check them and fix incorrupted data to make sure filesystem > metadata (mainly counters and main/nat bitmap) are all consistent. > 3. Reconnect these files to lost+found. If lost+found does not exist, > create it first. During reconnecting, expand lost+found's dentry > block automatically. Reconnected files are renamed after its ino > number. > 4. If reconnect fails drop the node and restore filesystem metadata. > > Signed-off-by: Sheng Yong > --- > fsck/dir.c | 19 ++- > fsck/fsck.c | 376 > ++- > fsck/fsck.h | 3 + > fsck/mount.c | 2 + > 4 files changed, 397 insertions(+), 3 deletions(-) > > diff --git a/fsck/dir.c b/fsck/dir.c > index b2ea18f..567a4e9 100644 > --- a/fsck/dir.c > +++ b/fsck/dir.c > @@ -176,6 +176,23 @@ static int f2fs_find_entry(struct f2fs_sb_info *sbi, > return 0; > } > > +/* return ino if file exists, otherwise return 0 */ > +nid_t f2fs_lookup(struct f2fs_sb_info *sbi, struct f2fs_node *dir, > + u8 *name, int len) > +{ > + int err; > + struct dentry de = { > + .name = name, > + .len = len, > + }; > + > + err = f2fs_find_entry(sbi, dir, &de); > + if (err == 1) > + return de.ino; > + else > + return 0; > +} > + > static void f2fs_update_dentry(nid_t ino, int file_type, > struct f2fs_dentry_ptr *d, > const unsigned char *name, int len, f2fs_hash_t name_hash, > @@ -199,7 +216,7 @@ static void f2fs_update_dentry(nid_t ino, int file_type, > /* > * f2fs_add_link - Add a new file(dir) to parent dir. > */ > -static int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent, > +int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent, > const unsigned char *name, int name_len, nid_t ino, > int file_type, block_t p_blkaddr, int inc_link) > { > diff --git a/fsck/fsck.c b/fsck/fsck.c > index fcaab14..81e1145 100644 > --- a/fsck/fsck.c > +++ b/fsck/fsck.c > @@ -10,6 +10,7 @@ > */ > #include "fsck.h" > #include "quotaio.h" > +#include > > char *tree_mark; > uint32_t tree_mark_size = 256; > @@ -43,6 +44,14 @@ static inline int f2fs_test_main_bitmap(struct > f2fs_sb_info *sbi, u32 blk) > fsck->main_area_bitmap); > } > > +static inline int f2fs_clear_main_bitmap(struct f2fs_sb_info *sbi, u32 blk) > +{ > + struct f2fs_fsck *fsck = F2FS_FSCK(sbi); > + > + return f2fs_clear_bit(BLKOFF_FROM_MAIN(sbi, blk), > + fsck->main_area_bitmap); > +} > + > static inline int f2fs_test_sit_bitmap(struct f2fs_sb_info *sbi, u32 blk) > { > struct f2fs_fsck *fsck = F2FS_FSCK(sbi); > @@ -448,9 +457,11 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, > u32 nid, > > /* workaround to fix later */ > if (ftype != F2FS_FT_ORPHAN || > - f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) > + f2fs_test_bit(nid, fsck->nat_area_bitmap) != 0) { > f2fs_clear_bit(nid, fsck->nat_area_bitmap); > - else > + /* avoid reusing nid when reconnecting files */ > + f2fs_set_bit(nid, NM_I(sbi)->nid_bitmap); > + } else > ASSERT_MSG("orphan or xattr nid is duplicated [0x%x]\n", > nid); > > @@ -2041,6 +2052,362 @@ int check_sit_types(struct f2fs_sb_info *sbi) > return err; > } > > +static struct f2fs_node *fsck_get_lpf(struct f2fs_sb_info *sbi) > +{ > + struct f2fs_node *node; > + struct node_info ni; > + nid_t lpf_ino; > + int err; > + > + /* read root inode first */ > + node = calloc(F2FS_BLKSIZE, 1); > + ASSERT(node); > + get_node_info(sbi, F2FS_ROOT_INO(sbi), &ni); > + err = dev_read_block(node, ni.blk_addr); > + ASSERT(err >= 0); > + > + /* lookup lost+found in root directory */ > + lpf_ino = f2fs_lookup(sbi, node, (u8 *) LPF, strlen(LPF)); > + if (lpf_ino) { /* found */ > + get_node_info(sbi, lpf_ino, &ni); > + err = dev_read_block(node, ni.blk_addr); > + ASSERT(err >= 0); > + DBG(1, "Found lost+found 0x%x at blkaddr [0x%x]\n", > + lpf_ino, ni.blk_addr); > + if (!S_ISDIR(le16_to_cpu(node->i.i_mode))) { > + ASSERT_MSG("lost+found is not directory [0%o]\n", > +le16_to_cpu(node->i.i_mode)); > + /* FIXME: give up? */ > + goto out; > + } > + } else { /* not found,