Linux-EROFS Archive mirror
 help / color / mirror / Atom feed
* [PATCH] erofs-utils: fsck: add support for extracting hard links
@ 2023-06-27  8:53 Yue Hu
  2023-06-27  9:47 ` Gao Xiang
  0 siblings, 1 reply; 4+ messages in thread
From: Yue Hu @ 2023-06-27  8:53 UTC (permalink / raw
  To: linux-erofs; +Cc: huyue2, zhangwen

From: Yue Hu <huyue2@coolpad.com>

Currently hard links can't be extracted correctly, let's support it now.

Signed-off-by: Yue Hu <huyue2@coolpad.com>
---
 fsck/main.c | 152 ++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 124 insertions(+), 28 deletions(-)

diff --git a/fsck/main.c b/fsck/main.c
index f816bec..e78f67c 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -49,6 +49,16 @@ static struct option long_options[] = {
 	{0, 0, 0, 0},
 };
 
+#define NR_HARDLINK_HASHTABLE	16384
+
+struct hardlink_entry {
+	struct list_head list;
+	erofs_nid_t nid;
+	char *path;
+};
+
+static struct list_head hardlink_hashtable[NR_HARDLINK_HASHTABLE];
+
 static void print_available_decompressors(FILE *f, const char *delim)
 {
 	unsigned int i = 0;
@@ -550,6 +560,64 @@ static inline int erofs_extract_dir(struct erofs_inode *inode)
 	return 0;
 }
 
+static char *erofsfsck_hardlink_find(erofs_nid_t nid)
+{
+	struct list_head *head =
+			&hardlink_hashtable[nid % NR_HARDLINK_HASHTABLE];
+	struct hardlink_entry *entry;
+
+	if (list_empty(head))
+		return NULL;
+
+	list_for_each_entry(entry, head, list)
+		if (entry->nid == nid)
+			return entry->path;
+	return NULL;
+}
+
+static int erofsfsck_hardlink_insert(erofs_nid_t nid, const char *path)
+{
+	struct hardlink_entry *entry;
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		return -ENOMEM;
+
+	entry->nid = nid;
+	entry->path = strdup(path);
+	if (!entry->path)
+		return -ENOMEM;
+
+	list_add_tail(&entry->list,
+		      &hardlink_hashtable[nid % NR_HARDLINK_HASHTABLE]);
+	return 0;
+}
+
+static void erofsfsck_hardlink_init(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_HARDLINK_HASHTABLE; ++i)
+		init_list_head(&hardlink_hashtable[i]);
+}
+
+static void erofsfsck_hardlink_exit(void)
+{
+	struct hardlink_entry *entry, *n;
+	struct list_head *head;
+	unsigned int i;
+
+	for (i = 0; i < NR_HARDLINK_HASHTABLE; ++i) {
+		head = &hardlink_hashtable[i];
+
+		list_for_each_entry_safe(entry, n, head, list) {
+			if (entry->path)
+				free(entry->path);
+			free(entry);
+		}
+	}
+}
+
 static inline int erofs_extract_file(struct erofs_inode *inode)
 {
 	bool tryagain = true;
@@ -719,6 +787,57 @@ static int erofsfsck_dirent_iter(struct erofs_dir_context *ctx)
 	return ret;
 }
 
+static int erofsfsck_extract_inode(struct erofs_inode *inode)
+{
+	int ret;
+	char *oldpath;
+
+	if (!fsckcfg.extract_path || erofs_is_packed_inode(inode)) {
+verify:
+		/* verify data chunk layout */
+		return erofs_verify_inode_data(inode, -1);
+	}
+
+	oldpath = erofsfsck_hardlink_find(inode->nid);
+	if (oldpath) {
+		if (link(oldpath, fsckcfg.extract_path) == -1) {
+			erofs_err("failed to extract hard link: %s (%s)",
+				  fsckcfg.extract_path, strerror(errno));
+			return -errno;
+		}
+		return 0;
+	}
+
+	switch (inode->i_mode & S_IFMT) {
+	case S_IFDIR:
+		ret = erofs_extract_dir(inode);
+		break;
+	case S_IFREG:
+		ret = erofs_extract_file(inode);
+		break;
+	case S_IFLNK:
+		ret = erofs_extract_symlink(inode);
+		break;
+	case S_IFCHR:
+	case S_IFBLK:
+	case S_IFIFO:
+	case S_IFSOCK:
+		ret = erofs_extract_special(inode);
+		break;
+	default:
+		/* TODO */
+		goto verify;
+	}
+	if (ret && ret != -ECANCELED)
+		return ret;
+
+	/* record nid and old path for hardlink */
+	if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
+		ret = erofsfsck_hardlink_insert(inode->nid,
+						fsckcfg.extract_path);
+	return ret;
+}
+
 static int erofsfsck_check_inode(erofs_nid_t pnid, erofs_nid_t nid)
 {
 	int ret;
@@ -740,34 +859,7 @@ static int erofsfsck_check_inode(erofs_nid_t pnid, erofs_nid_t nid)
 	if (ret)
 		goto out;
 
-	if (fsckcfg.extract_path) {
-		switch (inode.i_mode & S_IFMT) {
-		case S_IFDIR:
-			ret = erofs_extract_dir(&inode);
-			break;
-		case S_IFREG:
-			if (erofs_is_packed_inode(&inode))
-				goto verify;
-			ret = erofs_extract_file(&inode);
-			break;
-		case S_IFLNK:
-			ret = erofs_extract_symlink(&inode);
-			break;
-		case S_IFCHR:
-		case S_IFBLK:
-		case S_IFIFO:
-		case S_IFSOCK:
-			ret = erofs_extract_special(&inode);
-			break;
-		default:
-			/* TODO */
-			goto verify;
-		}
-	} else {
-verify:
-		/* verify data chunk layout */
-		ret = erofs_verify_inode_data(&inode, -1);
-	}
+	ret = erofsfsck_extract_inode(&inode);
 	if (ret && ret != -ECANCELED)
 		goto out;
 
@@ -854,6 +946,8 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	erofsfsck_hardlink_init();
+
 	err = erofsfsck_check_inode(sbi.root_nid, sbi.root_nid);
 	if (fsckcfg.corrupted) {
 		if (!fsckcfg.extract_path)
@@ -876,6 +970,8 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	erofsfsck_hardlink_exit();
+
 exit_put_super:
 	erofs_put_super();
 exit_dev_close:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] erofs-utils: fsck: add support for extracting hard links
  2023-06-27  8:53 [PATCH] erofs-utils: fsck: add support for extracting hard links Yue Hu
@ 2023-06-27  9:47 ` Gao Xiang
  2023-06-27 13:11   ` Yue Hu
  0 siblings, 1 reply; 4+ messages in thread
From: Gao Xiang @ 2023-06-27  9:47 UTC (permalink / raw
  To: Yue Hu, linux-erofs; +Cc: huyue2, zhangwen

Hi Yue,

On 2023/6/27 16:53, Yue Hu wrote:
> From: Yue Hu <huyue2@coolpad.com>
> 
> Currently hard links can't be extracted correctly, let's support it now.
> 
> Signed-off-by: Yue Hu <huyue2@coolpad.com>

Thanks for the patch!  Some minor comments below...

> ---
>   fsck/main.c | 152 ++++++++++++++++++++++++++++++++++++++++++----------
>   1 file changed, 124 insertions(+), 28 deletions(-)
> 
> diff --git a/fsck/main.c b/fsck/main.c
> index f816bec..e78f67c 100644
> --- a/fsck/main.c
> +++ b/fsck/main.c
> @@ -49,6 +49,16 @@ static struct option long_options[] = {
>   	{0, 0, 0, 0},
>   };
>   
> +#define NR_HARDLINK_HASHTABLE	16384
> +
> +struct hardlink_entry {

erofsfsck_hardlink_entry {

or erofsfsck_linkentry if the above is too long

> +	struct list_head list;
> +	erofs_nid_t nid;
> +	char *path;
> +};
> +
> +static struct list_head hardlink_hashtable[NR_HARDLINK_HASHTABLE];

erofsfsck_link_hashtable

> +
>   static void print_available_decompressors(FILE *f, const char *delim)
>   {
>   	unsigned int i = 0;
> @@ -550,6 +560,64 @@ static inline int erofs_extract_dir(struct erofs_inode *inode)
>   	return 0;
>   }
>   
> +static char *erofsfsck_hardlink_find(erofs_nid_t nid)
> +{
> +	struct list_head *head =
> +			&hardlink_hashtable[nid % NR_HARDLINK_HASHTABLE];
> +	struct hardlink_entry *entry;
> +
> +	if (list_empty(head))
> +		return NULL;

why we need that?

> +
> +	list_for_each_entry(entry, head, list)
> +		if (entry->nid == nid)
> +			return entry->path;
> +	return NULL;
> +}
> +
> +static int erofsfsck_hardlink_insert(erofs_nid_t nid, const char *path)
> +{
> +	struct hardlink_entry *entry;
> +
> +	entry = malloc(sizeof(*entry));
> +	if (!entry)
> +		return -ENOMEM;
> +
> +	entry->nid = nid;
> +	entry->path = strdup(path);
> +	if (!entry->path)
> +		return -ENOMEM;
> +
> +	list_add_tail(&entry->list,
> +		      &hardlink_hashtable[nid % NR_HARDLINK_HASHTABLE]);
> +	return 0;
> +}
> +
> +static void erofsfsck_hardlink_init(void)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < NR_HARDLINK_HASHTABLE; ++i)
> +		init_list_head(&hardlink_hashtable[i]);
> +}
> +
> +static void erofsfsck_hardlink_exit(void)
> +{
> +	struct hardlink_entry *entry, *n;
> +	struct list_head *head;
> +	unsigned int i;
> +
> +	for (i = 0; i < NR_HARDLINK_HASHTABLE; ++i) {
> +		head = &hardlink_hashtable[i];
> +
> +		list_for_each_entry_safe(entry, n, head, list) {
> +			if (entry->path)
> +				free(entry->path);
> +			free(entry);
> +		}
> +	}
> +}
> +
>   static inline int erofs_extract_file(struct erofs_inode *inode)
>   {
>   	bool tryagain = true;
> @@ -719,6 +787,57 @@ static int erofsfsck_dirent_iter(struct erofs_dir_context *ctx)
>   	return ret;
>   }
>   
> +static int erofsfsck_extract_inode(struct erofs_inode *inode)
> +{
> +	int ret;
> +	char *oldpath;
> +
> +	if (!fsckcfg.extract_path || erofs_is_packed_inode(inode)) {

why introducing erofs_is_packed_inode here?

Thanks,
Gao Xiang

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] erofs-utils: fsck: add support for extracting hard links
  2023-06-27  9:47 ` Gao Xiang
@ 2023-06-27 13:11   ` Yue Hu
  2023-06-27 13:43     ` Gao Xiang
  0 siblings, 1 reply; 4+ messages in thread
From: Yue Hu @ 2023-06-27 13:11 UTC (permalink / raw
  To: Gao Xiang; +Cc: huyue2, linux-erofs, zhangwen

On Tue, 27 Jun 2023 17:47:33 +0800
Gao Xiang <hsiangkao@linux.alibaba.com> wrote:

> Hi Yue,
> 
> On 2023/6/27 16:53, Yue Hu wrote:
> > From: Yue Hu <huyue2@coolpad.com>
> > 
> > Currently hard links can't be extracted correctly, let's support it now.
> > 
> > Signed-off-by: Yue Hu <huyue2@coolpad.com>  
> 
> Thanks for the patch!  Some minor comments below...
> 
> > ---
> >   fsck/main.c | 152 ++++++++++++++++++++++++++++++++++++++++++----------
> >   1 file changed, 124 insertions(+), 28 deletions(-)
> > 
> > diff --git a/fsck/main.c b/fsck/main.c
> > index f816bec..e78f67c 100644
> > --- a/fsck/main.c
> > +++ b/fsck/main.c
> > @@ -49,6 +49,16 @@ static struct option long_options[] = {
> >   	{0, 0, 0, 0},
> >   };
> >   
> > +#define NR_HARDLINK_HASHTABLE	16384
> > +
> > +struct hardlink_entry {  
> 
> erofsfsck_hardlink_entry {
> 
> or erofsfsck_linkentry if the above is too long
> 
> > +	struct list_head list;
> > +	erofs_nid_t nid;
> > +	char *path;
> > +};
> > +
> > +static struct list_head hardlink_hashtable[NR_HARDLINK_HASHTABLE];  
> 
> erofsfsck_link_hashtable
> 
> > +
> >   static void print_available_decompressors(FILE *f, const char *delim)
> >   {
> >   	unsigned int i = 0;
> > @@ -550,6 +560,64 @@ static inline int erofs_extract_dir(struct erofs_inode *inode)
> >   	return 0;
> >   }
> >   
> > +static char *erofsfsck_hardlink_find(erofs_nid_t nid)
> > +{
> > +	struct list_head *head =
> > +			&hardlink_hashtable[nid % NR_HARDLINK_HASHTABLE];
> > +	struct hardlink_entry *entry;
> > +
> > +	if (list_empty(head))
> > +		return NULL;  
> 
> why we need that?

yeah, it's unneeded, will remove it in v2.

> 
> > +
> > +	list_for_each_entry(entry, head, list)
> > +		if (entry->nid == nid)
> > +			return entry->path;
> > +	return NULL;
> > +}
> > +
> > +static int erofsfsck_hardlink_insert(erofs_nid_t nid, const char *path)
> > +{
> > +	struct hardlink_entry *entry;
> > +
> > +	entry = malloc(sizeof(*entry));
> > +	if (!entry)
> > +		return -ENOMEM;
> > +
> > +	entry->nid = nid;
> > +	entry->path = strdup(path);
> > +	if (!entry->path)
> > +		return -ENOMEM;
> > +
> > +	list_add_tail(&entry->list,
> > +		      &hardlink_hashtable[nid % NR_HARDLINK_HASHTABLE]);
> > +	return 0;
> > +}
> > +
> > +static void erofsfsck_hardlink_init(void)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < NR_HARDLINK_HASHTABLE; ++i)
> > +		init_list_head(&hardlink_hashtable[i]);
> > +}
> > +
> > +static void erofsfsck_hardlink_exit(void)
> > +{
> > +	struct hardlink_entry *entry, *n;
> > +	struct list_head *head;
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < NR_HARDLINK_HASHTABLE; ++i) {
> > +		head = &hardlink_hashtable[i];
> > +
> > +		list_for_each_entry_safe(entry, n, head, list) {
> > +			if (entry->path)
> > +				free(entry->path);
> > +			free(entry);
> > +		}
> > +	}
> > +}
> > +
> >   static inline int erofs_extract_file(struct erofs_inode *inode)
> >   {
> >   	bool tryagain = true;
> > @@ -719,6 +787,57 @@ static int erofsfsck_dirent_iter(struct erofs_dir_context *ctx)
> >   	return ret;
> >   }
> >   
> > +static int erofsfsck_extract_inode(struct erofs_inode *inode)
> > +{
> > +	int ret;
> > +	char *oldpath;
> > +
> > +	if (!fsckcfg.extract_path || erofs_is_packed_inode(inode)) {  
> 
> why introducing erofs_is_packed_inode here?

hardlink hashtable will be initialized after verify packed inode. 

> 
> Thanks,
> Gao Xiang


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] erofs-utils: fsck: add support for extracting hard links
  2023-06-27 13:11   ` Yue Hu
@ 2023-06-27 13:43     ` Gao Xiang
  0 siblings, 0 replies; 4+ messages in thread
From: Gao Xiang @ 2023-06-27 13:43 UTC (permalink / raw
  To: Yue Hu; +Cc: huyue2, linux-erofs, zhangwen



On 2023/6/27 21:11, Yue Hu wrote:
> On Tue, 27 Jun 2023 17:47:33 +0800
> Gao Xiang <hsiangkao@linux.alibaba.com> wrote:
> 

...

>>> +
>>> +	if (!fsckcfg.extract_path || erofs_is_packed_inode(inode)) {
>>
>> why introducing erofs_is_packed_inode here?
> 
> hardlink hashtable will be initialized after verify packed inode.

we could initialize it before verifing packed inode.

Thanks,
Gao Xiang

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-06-27 13:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-27  8:53 [PATCH] erofs-utils: fsck: add support for extracting hard links Yue Hu
2023-06-27  9:47 ` Gao Xiang
2023-06-27 13:11   ` Yue Hu
2023-06-27 13:43     ` Gao Xiang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).