On 02/26, Sheng Yong wrote:
> Hi, Chao
> 
> On 2018/2/26 16:23, Chao Yu wrote:
> > On 2018/2/23 11:18, 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 <shengyo...@huawei.com>
> > > ---
> > >   fsck/dir.c   |  19 ++-
> > >   fsck/fsck.c  | 388 
> > > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> > >   fsck/fsck.h  |   3 +
> > >   fsck/mount.c |   2 +
> > >   4 files changed, 409 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;
> > >   }
> [...]
> > > +
> > > +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, namelen)) {
> > > +         ASSERT_MSG("Name %s already exist in lost+found", name);
> > > +         return -EEXIST;
> > > + }
> > > +
> > > + get_node_info(sbi, le32_to_cpu(lpf->footer.ino), &ni);
> > > + ret = f2fs_add_link(sbi, lpf, (unsigned char *)name, namelen,
> > > +                     ino, F2FS_FT_REG_FILE, ni.blk_addr, 0);
> > 
> > Need to change F2FS_FT_REG_FILE to ftype due to we expect to reconnect all 
> > kinds
> > of inode except directory, right?
> > 
> Right. My bad, will fix this in next version. Thanks.

Hi Sheng,

I merged this series except this patch. Please update this one only. :)

Thanks,

> 
> > > + if (ret) {
> > > +         ASSERT_MSG("Failed to add inode [0x%x] to lost+found", ino);
> > > +         return -EINVAL;
> > > + }
> > > +
> > > + /* update fnode */
> > > + memcpy(fnode->i.i_name, name, namelen);
> > > + fnode->i.i_namelen = cpu_to_le32(namelen);
> > > + fnode->i.i_pino = c.lpf_ino;
> > > + get_node_info(sbi, le32_to_cpu(fnode->footer.ino), &ni);
> > > + ret = dev_write_block(fnode, ni.blk_addr);
> > > + ASSERT(ret >= 0);
> > > +
> > > + DBG(1, "Reconnect inode [0x%x] to lost+found\n", ino);
> > > + return 0;
> > > +}
> > > +
> [...]
> > > +
> > > +/*
> > > + * Scan unreachable nids and find only regular file inodes. If these 
> > > files
> > > + * are not corrupted, reconnect them to lost+found.
> > > + *
> > > + * Since all unreachable nodes are already checked, we can allocate new
> > > + * blocks safely.
> > > + *
> > > + * This function returns the number of files been reconnected.
> > > + */
> > > +static int fsck_reconnect_file(struct f2fs_sb_info *sbi)
> > > +{
> > > + struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> > > + struct f2fs_node *lpf_node, *node;
> > > + struct node_info ni;
> > > + char *reconnect_bitmap;
> > > + u32 blk_cnt;
> > > + nid_t nid;
> > > + int err, cnt = 0, ftype;
> > > +
> > > + node = calloc(F2FS_BLKSIZE, 1);
> > > + ASSERT(node);
> > > +
> > > + reconnect_bitmap = calloc(fsck->nat_area_bitmap_sz, 1);
> > > + ASSERT(reconnect_bitmap);
> > > +
> > > + for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
> > > +         if (f2fs_test_bit(nid, fsck->nat_area_bitmap)) {
> > > +                 if (is_qf_ino(F2FS_RAW_SUPER(sbi), nid)) {
> > > +                         DBG(1, "Not support quota inode [0x%x]\n",
> > > +                             nid);
> > > +                         continue;
> > > +                 }
> > > +
> > > +                 get_node_info(sbi, nid, &ni);
> > > +                 err = dev_read_block(node, ni.blk_addr);
> > > +                 ASSERT(err >= 0);
> > > +
> > > +                 /* reconnection will restore these nodes if needed */
> > > +                 if (node->footer.ino != node->footer.nid) {
> > > +                         DBG(1, "Not support non-inode node [0x%x]\n",
> > > +                             nid);
> > > +                         continue;
> > > +                 }
> > > +
> > > +                 if (S_ISDIR(le16_to_cpu(node->i.i_mode))) {
> > > +                         DBG(1, "Not support directory inode [0x%x]\n",
> > > +                             nid);
> > > +                         continue;
> > > +                 }
> > > +
> > > +                 ftype = map_de_type(le16_to_cpu(node->i.i_mode));
> > > +                 if (sanity_check_nid(sbi, nid, node, ftype,
> > > +                                      TYPE_INODE, &ni)) {
> > > +                         ASSERT_MSG("Invalid nid [0x%x]\n", nid);
> > > +                         continue;
> > > +                 }
> > > +
> > > +                 DBG(1, "Check inode 0x%x\n", nid);
> > > +                 blk_cnt = 1;
> > > +                 fsck_chk_inode_blk(sbi, nid, F2FS_FT_REG_FILE,
> > 
> > Ditto,
> > 
> Will fix it :)
> 
> Thanks,
> Sheng
> 
> > Thanks,
> > 
> > > +                                    node, &blk_cnt, &ni, NULL);
> > > +
> > > +                 f2fs_set_bit(nid, reconnect_bitmap);
> > > +         }
> > > + }
> > > +
> > > + lpf_node = fsck_get_lpf(sbi);
> > > + if (!lpf_node)
> > > +         goto out;
> > > +
> > > + for (nid = 0; nid < fsck->nr_nat_entries; nid++) {
> > > +         if (f2fs_test_bit(nid, reconnect_bitmap)) {
> > > +                 get_node_info(sbi, nid, &ni);
> > > +                 err = dev_read_block(node, ni.blk_addr);
> > > +                 ASSERT(err >= 0);
> > > +
> > > +                 if (fsck_do_reconnect_file(sbi, lpf_node, node)) {
> > > +                         DBG(1, "Failed to reconnect inode [0x%x]\n",
> > > +                             nid);
> > > +                         fsck_failed_reconnect_file(sbi, nid);
> > > +                         continue;
> > > +                 }
> > > +
> > > +                 quota_add_inode_usage(fsck->qctx, nid, &node->i);
> > > +
> > > +                 DBG(1, "Reconnected inode [0x%x] to lost+found\n", nid);
> > > +                 cnt++;
> > > +         }
> > > + }
> > > +
> > > +out:
> > > + free(node);
> > > + free(lpf_node);
> > > + free(reconnect_bitmap);
> > > + return cnt;
> > > +}
> > > +
> > >   int fsck_verify(struct f2fs_sb_info *sbi)
> > >   {
> > >           unsigned int i = 0;
> > > @@ -2057,6 +2431,16 @@ int fsck_verify(struct f2fs_sb_info *sbi)
> > >           printf("\n");
> > > + if (c.feature & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) {
> > > +         for (i = 0; i < fsck->nr_nat_entries; i++)
> > > +                 if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0)
> > > +                         break;
> > > +         if (i < fsck->nr_nat_entries) {
> > > +                 i = fsck_reconnect_file(sbi);
> > > +                 printf("[FSCK] Reconnect %u files to lost+found\n", i);
> > > +         }
> > > + }
> > > +
> > >           for (i = 0; i < fsck->nr_nat_entries; i++) {
> > >                   if (f2fs_test_bit(i, fsck->nat_area_bitmap) != 0) {
> > >                           printf("NID[0x%x] is unreachable\n", i);
> > > diff --git a/fsck/fsck.h b/fsck/fsck.h
> > > index 648c2db..8e133fa 100644
> > > --- a/fsck/fsck.h
> > > +++ b/fsck/fsck.h
> > > @@ -243,6 +243,9 @@ int f2fs_mkdir(struct f2fs_sb_info *, struct dentry 
> > > *);
> > >   int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
> > >   int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
> > >   int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
> > > +nid_t f2fs_lookup(struct f2fs_sb_info *, struct f2fs_node *, u8 *, int);
> > > +int f2fs_add_link(struct f2fs_sb_info *, struct f2fs_node *,
> > > +         const unsigned char *, int, nid_t, int, block_t, int);
> > >   /* xattr.c */
> > >   void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
> > > diff --git a/fsck/mount.c b/fsck/mount.c
> > > index b8e7643..545f862 100644
> > > --- a/fsck/mount.c
> > > +++ b/fsck/mount.c
> > > @@ -1587,6 +1587,8 @@ void update_nat_blkaddr(struct f2fs_sb_info *sbi, 
> > > nid_t ino,
> > >           if (ino)
> > >                   nat_block->entries[entry_off].ino = cpu_to_le32(ino);
> > >           nat_block->entries[entry_off].block_addr = cpu_to_le32(newaddr);
> > > + if (c.func == FSCK)
> > > +         F2FS_FSCK(sbi)->entries[nid] = nat_block->entries[entry_off];
> > >           ret = dev_write_block(nat_block, block_addr);
> > >           ASSERT(ret >= 0);
> > > 
> > 
> > 
> > .
> > 

------------------------------------------------------------------------------
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

Reply via email to