[f2fs-dev] [RFC PATCH 5/5] fsck.f2fs: reconnect unreachable files to lost+found

2018-02-05 Thread Sheng Yong
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

2018-02-07 Thread Sheng Yong


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

2018-02-07 Thread Sheng Yong



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

2018-02-13 Thread Chao Yu
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,