* [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).