* [RFC PATCH 1/2] erofs-utils: dump: cleanup update_file_size_statatics()
@ 2022-12-19 9:50 Yue Hu
2022-12-19 9:50 ` [RFC PATCH 2/2] erofs-utils: dump: support fragments Yue Hu
0 siblings, 1 reply; 7+ messages in thread
From: Yue Hu @ 2022-12-19 9:50 UTC (permalink / raw)
To: linux-erofs; +Cc: Yue Hu, zhangwen
From: Yue Hu <huyue2@coolpad.com>
The statistic update of occupied_size is the same as original size.
Also, correct naming to update_file_size_statistics().
Signed-off-by: Yue Hu <huyue2@coolpad.com>
---
dump/main.c | 38 +++++++++++++-------------------------
1 file changed, 13 insertions(+), 25 deletions(-)
diff --git a/dump/main.c b/dump/main.c
index 93dce8b..bc4f047 100644
--- a/dump/main.c
+++ b/dump/main.c
@@ -225,36 +225,23 @@ static void inc_file_extension_count(const char *dname, unsigned int len)
++stats.file_type_stat[type];
}
-static void update_file_size_statatics(erofs_off_t occupied_size,
- erofs_off_t original_size)
+static void update_file_size_statistics(erofs_off_t size, bool original)
{
- int occupied_size_mark, original_size_mark;
+ unsigned int *file_size = original ? stats.file_original_size :
+ stats.file_comp_size;
+ int size_mark = 0;
- original_size_mark = 0;
- occupied_size_mark = 0;
- occupied_size >>= 10;
- original_size >>= 10;
+ size >>= 10;
- while (occupied_size || original_size) {
- if (occupied_size) {
- occupied_size >>= 1;
- occupied_size_mark++;
- }
- if (original_size) {
- original_size >>= 1;
- original_size_mark++;
- }
+ while (size) {
+ size >>= 1;
+ size_mark++;
}
- if (original_size_mark >= FILE_MAX_SIZE_BITS)
- stats.file_original_size[FILE_MAX_SIZE_BITS]++;
- else
- stats.file_original_size[original_size_mark]++;
-
- if (occupied_size_mark >= FILE_MAX_SIZE_BITS)
- stats.file_comp_size[FILE_MAX_SIZE_BITS]++;
+ if (size_mark >= FILE_MAX_SIZE_BITS)
+ file_size[FILE_MAX_SIZE_BITS]++;
else
- stats.file_comp_size[occupied_size_mark]++;
+ file_size[size_mark]++;
}
static int erofsdump_ls_dirent_iter(struct erofs_dir_context *ctx)
@@ -301,7 +288,8 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
stats.files_total_origin_size += vi.i_size;
inc_file_extension_count(ctx->dname, ctx->de_namelen);
stats.files_total_size += occupied_size;
- update_file_size_statatics(occupied_size, vi.i_size);
+ update_file_size_statistics(vi.i_size, true);
+ update_file_size_statistics(occupied_size, false);
}
/* XXXX: the dir depth should be restricted in order to avoid loops */
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 2/2] erofs-utils: dump: support fragments
2022-12-19 9:50 [RFC PATCH 1/2] erofs-utils: dump: cleanup update_file_size_statatics() Yue Hu
@ 2022-12-19 9:50 ` Yue Hu
2023-01-04 3:13 ` Xiang Gao
0 siblings, 1 reply; 7+ messages in thread
From: Yue Hu @ 2022-12-19 9:50 UTC (permalink / raw)
To: linux-erofs; +Cc: Yue Hu, zhangwen
From: Yue Hu <huyue2@coolpad.com>
Add compressed fragments support for dump feature.
Signed-off-by: Yue Hu <huyue2@coolpad.com>
---
dump/main.c | 78 ++++++++++++++++++++++++++++++++--------
include/erofs/internal.h | 1 +
lib/zmap.c | 2 +-
3 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/dump/main.c b/dump/main.c
index bc4f047..d387841 100644
--- a/dump/main.c
+++ b/dump/main.c
@@ -14,6 +14,8 @@
#include "erofs/inode.h"
#include "erofs/io.h"
#include "erofs/dir.h"
+#include "erofs/compress.h"
+#include "erofs/fragments.h"
#include "../lib/liberofs_private.h"
#ifdef HAVE_LIBUUID
@@ -96,6 +98,7 @@ static struct erofsdump_feature feature_lists[] = {
{ false, EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, "chunked_file" },
{ false, EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, "device_table" },
{ false, EROFS_FEATURE_INCOMPAT_ZTAILPACKING, "ztailpacking" },
+ { false, EROFS_FEATURE_INCOMPAT_FRAGMENTS, "fragments" },
};
static int erofsdump_readdir(struct erofs_dir_context *ctx);
@@ -285,10 +288,12 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
}
if (S_ISREG(vi.i_mode)) {
- stats.files_total_origin_size += vi.i_size;
- inc_file_extension_count(ctx->dname, ctx->de_namelen);
+ if (!erofs_is_packed_inode(&vi)) {
+ stats.files_total_origin_size += vi.i_size;
+ inc_file_extension_count(ctx->dname, ctx->de_namelen);
+ update_file_size_statistics(vi.i_size, true);
+ }
stats.files_total_size += occupied_size;
- update_file_size_statistics(vi.i_size, true);
update_file_size_statistics(occupied_size, false);
}
@@ -320,6 +325,10 @@ static void erofsdump_show_fileinfo(bool show_extent)
"%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 "\n",
"%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 " # device %u\n"
};
+ const char *frag_ext_fmt[] = {
+ "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 "\n",
+ "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " # device %u\n"
+ };
int err, i;
erofs_off_t size;
u16 access_mode;
@@ -348,16 +357,31 @@ static void erofsdump_show_fileinfo(bool show_extent)
}
}
+ if (erofs_inode_is_data_compressed(inode.datalayout)) {
+ err = z_erofs_fill_inode_lazy(&inode);
+ if (err) {
+ erofs_err("read inode map header failed @ nid %llu",
+ inode.nid | 0ULL);
+ return;
+ }
+ }
+
err = erofs_get_occupied_size(&inode, &size);
if (err) {
erofs_err("get file size failed @ nid %llu", inode.nid | 0ULL);
return;
}
- err = erofs_get_pathname(inode.nid, path, sizeof(path));
- if (err < 0) {
- erofs_err("file path not found @ nid %llu", inode.nid | 0ULL);
- return;
+ if (erofs_is_packed_inode(&inode)) {
+ strncpy(path, EROFS_PACKED_INODE, sizeof(path) - 1);
+ path[sizeof(path) - 1] = '\0';
+ } else {
+ err = erofs_get_pathname(inode.nid, path, sizeof(path));
+ if (err < 0) {
+ erofs_err("file path not found @ nid %llu",
+ inode.nid | 0ULL);
+ return;
+ }
}
strftime(timebuf, sizeof(timebuf),
@@ -372,9 +396,13 @@ static void erofsdump_show_fileinfo(bool show_extent)
file_category_types[erofs_mode_to_ftype(inode.i_mode)]);
fprintf(stdout, "NID: %" PRIu64 " ", inode.nid);
fprintf(stdout, "Links: %u ", inode.i_nlink);
- fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
- inode.datalayout,
- (double)(100 * size) / (double)(inode.i_size));
+ if (inode.z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)
+ fprintf(stdout, "Layout: %d Fragment: %s\n",
+ inode.datalayout, size ? "partial" : "full");
+ else
+ fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
+ inode.datalayout,
+ (double)(100 * size) / (double)(inode.i_size));
fprintf(stdout, "Inode size: %d ", inode.inode_isize);
fprintf(stdout, "Extent size: %u ", inode.extent_isize);
fprintf(stdout, "Xattr size: %u\n", inode.xattr_isize);
@@ -404,7 +432,8 @@ static void erofsdump_show_fileinfo(bool show_extent)
if (!dumpcfg.show_extent)
return;
- fprintf(stdout, "\n Ext: logical offset | length : physical offset | length\n");
+ fprintf(stdout, "\n Ext: logical offset | length%s\n",
+ size ? " : physical offset | length" : "");
while (map.m_la < inode.i_size) {
struct erofs_map_dev mdev;
@@ -425,10 +454,17 @@ static void erofsdump_show_fileinfo(bool show_extent)
return;
}
- fprintf(stdout, ext_fmt[!!mdev.m_deviceid], extent_count++,
- map.m_la, map.m_la + map.m_llen, map.m_llen,
- mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
- mdev.m_deviceid);
+ if (map.m_flags & EROFS_MAP_FRAGMENT)
+ fprintf(stdout, frag_ext_fmt[!!mdev.m_deviceid],
+ extent_count++,
+ map.m_la, map.m_la + map.m_llen, map.m_llen,
+ mdev.m_deviceid);
+ else
+ fprintf(stdout, ext_fmt[!!mdev.m_deviceid],
+ extent_count++,
+ map.m_la, map.m_la + map.m_llen, map.m_llen,
+ mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
+ mdev.m_deviceid);
map.m_la += map.m_llen;
}
fprintf(stdout, "%s: %d extents found\n", path, extent_count);
@@ -537,6 +573,15 @@ static void erofsdump_print_statistic(void)
erofs_err("read dir failed");
return;
}
+ if (erofs_sb_has_fragments()) {
+ err = erofsdump_readdir(&(struct erofs_dir_context) {
+ .de_nid = sbi.packed_nid
+ });
+ if (err) {
+ erofs_err("read packed inode failed");
+ return;
+ }
+ }
erofsdump_file_statistic();
erofsdump_filesize_distribution("Original",
stats.file_original_size,
@@ -563,6 +608,9 @@ static void erofsdump_show_superblock(void)
sbi.xattr_blkaddr);
fprintf(stdout, "Filesystem root nid: %llu\n",
sbi.root_nid | 0ULL);
+ if (erofs_sb_has_fragments())
+ fprintf(stdout, "Filesystem packed nid: %llu\n",
+ sbi.packed_nid | 0ULL);
fprintf(stdout, "Filesystem inode count: %llu\n",
sbi.inos | 0ULL);
fprintf(stdout, "Filesystem created: %s",
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 206913c..947894d 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -383,6 +383,7 @@ int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
/* zmap.c */
int z_erofs_fill_inode(struct erofs_inode *vi);
+int z_erofs_fill_inode_lazy(struct erofs_inode *vi);
int z_erofs_map_blocks_iter(struct erofs_inode *vi,
struct erofs_map_blocks *map, int flags);
diff --git a/lib/zmap.c b/lib/zmap.c
index 89e9da1..41e0713 100644
--- a/lib/zmap.c
+++ b/lib/zmap.c
@@ -29,7 +29,7 @@ int z_erofs_fill_inode(struct erofs_inode *vi)
return 0;
}
-static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
+int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
{
int ret;
erofs_off_t pos;
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/2] erofs-utils: dump: support fragments
2022-12-19 9:50 ` [RFC PATCH 2/2] erofs-utils: dump: support fragments Yue Hu
@ 2023-01-04 3:13 ` Xiang Gao
2023-01-04 6:16 ` Yue Hu
0 siblings, 1 reply; 7+ messages in thread
From: Xiang Gao @ 2023-01-04 3:13 UTC (permalink / raw)
To: Yue Hu, linux-erofs; +Cc: Yue Hu, zhangwen
On 2022/12/19 17:50, Yue Hu wrote:
> From: Yue Hu <huyue2@coolpad.com>
>
> Add compressed fragments support for dump feature.
>
> Signed-off-by: Yue Hu <huyue2@coolpad.com>
> ---
> dump/main.c | 78 ++++++++++++++++++++++++++++++++--------
> include/erofs/internal.h | 1 +
> lib/zmap.c | 2 +-
> 3 files changed, 65 insertions(+), 16 deletions(-)
>
> diff --git a/dump/main.c b/dump/main.c
> index bc4f047..d387841 100644
> --- a/dump/main.c
> +++ b/dump/main.c
> @@ -14,6 +14,8 @@
> #include "erofs/inode.h"
> #include "erofs/io.h"
> #include "erofs/dir.h"
> +#include "erofs/compress.h"
> +#include "erofs/fragments.h"
> #include "../lib/liberofs_private.h"
>
> #ifdef HAVE_LIBUUID
> @@ -96,6 +98,7 @@ static struct erofsdump_feature feature_lists[] = {
> { false, EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, "chunked_file" },
> { false, EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, "device_table" },
> { false, EROFS_FEATURE_INCOMPAT_ZTAILPACKING, "ztailpacking" },
> + { false, EROFS_FEATURE_INCOMPAT_FRAGMENTS, "fragments" },
> };
>
> static int erofsdump_readdir(struct erofs_dir_context *ctx);
> @@ -285,10 +288,12 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
> }
>
> if (S_ISREG(vi.i_mode)) {
> - stats.files_total_origin_size += vi.i_size;
> - inc_file_extension_count(ctx->dname, ctx->de_namelen);
> + if (!erofs_is_packed_inode(&vi)) {
> + stats.files_total_origin_size += vi.i_size;
> + inc_file_extension_count(ctx->dname, ctx->de_namelen);
> + update_file_size_statistics(vi.i_size, true);
> + }
> stats.files_total_size += occupied_size;
> - update_file_size_statistics(vi.i_size, true);
> update_file_size_statistics(occupied_size, false);
> }
>
> @@ -320,6 +325,10 @@ static void erofsdump_show_fileinfo(bool show_extent)
> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 "\n",
> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 " # device %u\n"
> };
> + const char *frag_ext_fmt[] = {
> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 "\n",
> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " # device %u\n"
> + };
Why do we need another fmt rather than just fill fragment extent with
physical addr 0?
> int err, i;
> erofs_off_t size;
> u16 access_mode;
> @@ -348,16 +357,31 @@ static void erofsdump_show_fileinfo(bool show_extent)
> }
> }
>
> + if (erofs_inode_is_data_compressed(inode.datalayout)) {
> + err = z_erofs_fill_inode_lazy(&inode);
> + if (err) {
> + erofs_err("read inode map header failed @ nid %llu",
> + inode.nid | 0ULL);
> + return;
> + }
> + }
Why do we need to call z_erofs_fill_inode_lazy here?
> +
> err = erofs_get_occupied_size(&inode, &size);
> if (err) {
> erofs_err("get file size failed @ nid %llu", inode.nid | 0ULL);
> return;
> }
>
> - err = erofs_get_pathname(inode.nid, path, sizeof(path));
> - if (err < 0) {
> - erofs_err("file path not found @ nid %llu", inode.nid | 0ULL);
> - return;
Can we just ignore pathname if it doesn't exist?
> + if (erofs_is_packed_inode(&inode) { > + strncpy(path, EROFS_PACKED_INODE, sizeof(path) - 1);
> + path[sizeof(path) - 1] = '\0';
> + } else {
> + err = erofs_get_pathname(inode.nid, path, sizeof(path));
> + if (err < 0) {
> + erofs_err("file path not found @ nid %llu",
> + inode.nid | 0ULL);
> + return;
> + }
> }
>
> strftime(timebuf, sizeof(timebuf),
> @@ -372,9 +396,13 @@ static void erofsdump_show_fileinfo(bool show_extent)
> file_category_types[erofs_mode_to_ftype(inode.i_mode)]);
> fprintf(stdout, "NID: %" PRIu64 " ", inode.nid);
> fprintf(stdout, "Links: %u ", inode.i_nlink);
> - fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
> - inode.datalayout,
> - (double)(100 * size) / (double)(inode.i_size));
> + if (inode.z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)
> + fprintf(stdout, "Layout: %d Fragment: %s\n",
> + inode.datalayout, size ? "partial" : "full");
> + else
> + fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
> + inode.datalayout,
> + (double)(100 * size) / (double)(inode.i_size));
> fprintf(stdout, "Inode size: %d ", inode.inode_isize);
> fprintf(stdout, "Extent size: %u ", inode.extent_isize);
> fprintf(stdout, "Xattr size: %u\n", inode.xattr_isize);
> @@ -404,7 +432,8 @@ static void erofsdump_show_fileinfo(bool show_extent)
> if (!dumpcfg.show_extent)
> return;
>
> - fprintf(stdout, "\n Ext: logical offset | length : physical offset | length\n");
> + fprintf(stdout, "\n Ext: logical offset | length%s\n",
> + size ? " : physical offset | length" : "");
> while (map.m_la < inode.i_size) {
> struct erofs_map_dev mdev;
>
> @@ -425,10 +454,17 @@ static void erofsdump_show_fileinfo(bool show_extent)
> return;
> }
>
> - fprintf(stdout, ext_fmt[!!mdev.m_deviceid], extent_count++,
> - map.m_la, map.m_la + map.m_llen, map.m_llen,
> - mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
> - mdev.m_deviceid);
> + if (map.m_flags & EROFS_MAP_FRAGMENT)
> + fprintf(stdout, frag_ext_fmt[!!mdev.m_deviceid],
> + extent_count++,
> + map.m_la, map.m_la + map.m_llen, map.m_llen,
> + mdev.m_deviceid);
except for the last fragment extent, the other extents all have physical
addr and length...
> + else
> + fprintf(stdout, ext_fmt[!!mdev.m_deviceid],
> + extent_count++,
> + map.m_la, map.m_la + map.m_llen, map.m_llen,
> + mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
> + mdev.m_deviceid);
> map.m_la += map.m_llen;
> }
> fprintf(stdout, "%s: %d extents found\n", path, extent_count);
> @@ -537,6 +573,15 @@ static void erofsdump_print_statistic(void)
> erofs_err("read dir failed");
> return;
> }
> + if (erofs_sb_has_fragments()) {
> + err = erofsdump_readdir(&(struct erofs_dir_context) {
> + .de_nid = sbi.packed_nid
> + });
why do we need this?
Thanks,
Gao Xiang
> + if (err) {
> + erofs_err("read packed inode failed");
> + return;
> + }
> + }
> erofsdump_file_statistic();
> erofsdump_filesize_distribution("Original",
> stats.file_original_size,
> @@ -563,6 +608,9 @@ static void erofsdump_show_superblock(void)
> sbi.xattr_blkaddr);
> fprintf(stdout, "Filesystem root nid: %llu\n",
> sbi.root_nid | 0ULL);
> + if (erofs_sb_has_fragments())
> + fprintf(stdout, "Filesystem packed nid: %llu\n",
> + sbi.packed_nid | 0ULL);
> fprintf(stdout, "Filesystem inode count: %llu\n",
> sbi.inos | 0ULL);
> fprintf(stdout, "Filesystem created: %s",
> diff --git a/include/erofs/internal.h b/include/erofs/internal.h
> index 206913c..947894d 100644
> --- a/include/erofs/internal.h
> +++ b/include/erofs/internal.h
> @@ -383,6 +383,7 @@ int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
>
> /* zmap.c */
> int z_erofs_fill_inode(struct erofs_inode *vi);
> +int z_erofs_fill_inode_lazy(struct erofs_inode *vi);
> int z_erofs_map_blocks_iter(struct erofs_inode *vi,
> struct erofs_map_blocks *map, int flags);
>
> diff --git a/lib/zmap.c b/lib/zmap.c
> index 89e9da1..41e0713 100644
> --- a/lib/zmap.c
> +++ b/lib/zmap.c
> @@ -29,7 +29,7 @@ int z_erofs_fill_inode(struct erofs_inode *vi)
> return 0;
> }
>
> -static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
> +int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
> {
> int ret;
> erofs_off_t pos;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/2] erofs-utils: dump: support fragments
2023-01-04 3:13 ` Xiang Gao
@ 2023-01-04 6:16 ` Yue Hu
2023-01-04 6:44 ` Xiang Gao
0 siblings, 1 reply; 7+ messages in thread
From: Yue Hu @ 2023-01-04 6:16 UTC (permalink / raw)
To: Xiang Gao; +Cc: Yue Hu, linux-erofs, zhangwen
Hi Xiang,
Thanks for the reviewing. I'm planning to send v2.
On Wed, 4 Jan 2023 11:13:55 +0800
Xiang Gao <hsiangkao@linux.alibaba.com> wrote:
> On 2022/12/19 17:50, Yue Hu wrote:
> > From: Yue Hu <huyue2@coolpad.com>
> >
> > Add compressed fragments support for dump feature.
> >
> > Signed-off-by: Yue Hu <huyue2@coolpad.com>
> > ---
> > dump/main.c | 78 ++++++++++++++++++++++++++++++++--------
> > include/erofs/internal.h | 1 +
> > lib/zmap.c | 2 +-
> > 3 files changed, 65 insertions(+), 16 deletions(-)
> >
> > diff --git a/dump/main.c b/dump/main.c
> > index bc4f047..d387841 100644
> > --- a/dump/main.c
> > +++ b/dump/main.c
> > @@ -14,6 +14,8 @@
> > #include "erofs/inode.h"
> > #include "erofs/io.h"
> > #include "erofs/dir.h"
> > +#include "erofs/compress.h"
> > +#include "erofs/fragments.h"
> > #include "../lib/liberofs_private.h"
> >
> > #ifdef HAVE_LIBUUID
> > @@ -96,6 +98,7 @@ static struct erofsdump_feature feature_lists[] = {
> > { false, EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, "chunked_file" },
> > { false, EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, "device_table" },
> > { false, EROFS_FEATURE_INCOMPAT_ZTAILPACKING, "ztailpacking" },
> > + { false, EROFS_FEATURE_INCOMPAT_FRAGMENTS, "fragments" },
> > };
> >
> > static int erofsdump_readdir(struct erofs_dir_context *ctx);
> > @@ -285,10 +288,12 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
> > }
> >
> > if (S_ISREG(vi.i_mode)) {
> > - stats.files_total_origin_size += vi.i_size;
> > - inc_file_extension_count(ctx->dname, ctx->de_namelen);
> > + if (!erofs_is_packed_inode(&vi)) {
> > + stats.files_total_origin_size += vi.i_size;
> > + inc_file_extension_count(ctx->dname, ctx->de_namelen);
> > + update_file_size_statistics(vi.i_size, true);
> > + }
> > stats.files_total_size += occupied_size;
> > - update_file_size_statistics(vi.i_size, true);
> > update_file_size_statistics(occupied_size, false);
> > }
> >
> > @@ -320,6 +325,10 @@ static void erofsdump_show_fileinfo(bool show_extent)
> > "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 "\n",
> > "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 " # device %u\n"
> > };
> > + const char *frag_ext_fmt[] = {
> > + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 "\n",
> > + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " # device %u\n"
> > + };
>
> Why do we need another fmt rather than just fill fragment extent with
I also plan to remove this fmt in v2.
> physical addr 0?
Okay. Just leave latter physical length as empty?
>
> > int err, i;
> > erofs_off_t size;
> > u16 access_mode;
> > @@ -348,16 +357,31 @@ static void erofsdump_show_fileinfo(bool show_extent)
> > }
> > }
> >
> > + if (erofs_inode_is_data_compressed(inode.datalayout)) {
> > + err = z_erofs_fill_inode_lazy(&inode);
> > + if (err) {
> > + erofs_err("read inode map header failed @ nid %llu",
> > + inode.nid | 0ULL);
> > + return;
> > + }
> > + }
>
> Why do we need to call z_erofs_fill_inode_lazy here?
Used to check if the file has fragment. If yes, i think 'Compression ratio' can not be showed
exactly.
So, I'd like to show fragment information related instead as below:
NID: 715 Links: 1 Layout: 1 Fragment: entire file
NID: 715 Links: 1 Layout: 3 Fragment: tail of file
>
> > +
> > err = erofs_get_occupied_size(&inode, &size);
> > if (err) {
> > erofs_err("get file size failed @ nid %llu", inode.nid | 0ULL);
> > return;
> > }
> >
> > - err = erofs_get_pathname(inode.nid, path, sizeof(path));
> > - if (err < 0) {
> > - erofs_err("file path not found @ nid %llu", inode.nid | 0ULL);
> > - return;
>
> Can we just ignore pathname if it doesn't exist?
Okay.
>
> > + if (erofs_is_packed_inode(&inode) { > + strncpy(path, EROFS_PACKED_INODE, sizeof(path) - 1);
> > + path[sizeof(path) - 1] = '\0';
> > + } else {
> > + err = erofs_get_pathname(inode.nid, path, sizeof(path));
> > + if (err < 0) {
> > + erofs_err("file path not found @ nid %llu",
> > + inode.nid | 0ULL);
> > + return;
> > + }
> > }
> >
> > strftime(timebuf, sizeof(timebuf),
> > @@ -372,9 +396,13 @@ static void erofsdump_show_fileinfo(bool show_extent)
> > file_category_types[erofs_mode_to_ftype(inode.i_mode)]);
> > fprintf(stdout, "NID: %" PRIu64 " ", inode.nid);
> > fprintf(stdout, "Links: %u ", inode.i_nlink);
> > - fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
> > - inode.datalayout,
> > - (double)(100 * size) / (double)(inode.i_size));
> > + if (inode.z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)
> > + fprintf(stdout, "Layout: %d Fragment: %s\n",
> > + inode.datalayout, size ? "partial" : "full");
> > + else
> > + fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
> > + inode.datalayout,
> > + (double)(100 * size) / (double)(inode.i_size));
> > fprintf(stdout, "Inode size: %d ", inode.inode_isize);
> > fprintf(stdout, "Extent size: %u ", inode.extent_isize);
> > fprintf(stdout, "Xattr size: %u\n", inode.xattr_isize);
> > @@ -404,7 +432,8 @@ static void erofsdump_show_fileinfo(bool show_extent)
> > if (!dumpcfg.show_extent)
> > return;
> >
> > - fprintf(stdout, "\n Ext: logical offset | length : physical offset | length\n");
> > + fprintf(stdout, "\n Ext: logical offset | length%s\n",
> > + size ? " : physical offset | length" : "");
> > while (map.m_la < inode.i_size) {
> > struct erofs_map_dev mdev;
> >
> > @@ -425,10 +454,17 @@ static void erofsdump_show_fileinfo(bool show_extent)
> > return;
> > }
> >
> > - fprintf(stdout, ext_fmt[!!mdev.m_deviceid], extent_count++,
> > - map.m_la, map.m_la + map.m_llen, map.m_llen,
> > - mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
> > - mdev.m_deviceid);
> > + if (map.m_flags & EROFS_MAP_FRAGMENT)
> > + fprintf(stdout, frag_ext_fmt[!!mdev.m_deviceid],
> > + extent_count++,
> > + map.m_la, map.m_la + map.m_llen, map.m_llen,
> > + mdev.m_deviceid);
>
> except for the last fragment extent, the other extents all have physical
> addr and length...
It's true.
What bothers me is how to better show fragment extent based on current format (especially
no physical address and offset for fragment extent).
Now, i think the fragment extent should be showed like below (just use a '0' to represent it)?
a) the whole file is a fragment:
Ext: logical offset | length : physical offset | length
1: 0.. 1046 | 1046 : 0
b) the tail of file is a fragment:
Ext: logical offset | length : physical offset | length
0: 0.. 19672 | 19672 : 1314816.. 1323008 | 8192
...
13: 165989.. 182474 | 16485 : 1421312.. 1429504 | 8192
14: 182474.. 196435 | 13961 : 0
>
> > + else
> > + fprintf(stdout, ext_fmt[!!mdev.m_deviceid],
> > + extent_count++,
> > + map.m_la, map.m_la + map.m_llen, map.m_llen,
> > + mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
> > + mdev.m_deviceid);
> > map.m_la += map.m_llen;
> > }
> > fprintf(stdout, "%s: %d extents found\n", path, extent_count);
> > @@ -537,6 +573,15 @@ static void erofsdump_print_statistic(void)
> > erofs_err("read dir failed");
> > return;
> > }
> > + if (erofs_sb_has_fragments()) {
> > + err = erofsdump_readdir(&(struct erofs_dir_context) {
> > + .de_nid = sbi.packed_nid
> > + });
>
> why do we need this?
Since some status need to be updated such as stats.files_total_size.
>
> Thanks,
> Gao Xiang
>
> > + if (err) {
> > + erofs_err("read packed inode failed");
> > + return;
> > + }
> > + }
> > erofsdump_file_statistic();
> > erofsdump_filesize_distribution("Original",
> > stats.file_original_size,
> > @@ -563,6 +608,9 @@ static void erofsdump_show_superblock(void)
> > sbi.xattr_blkaddr);
> > fprintf(stdout, "Filesystem root nid: %llu\n",
> > sbi.root_nid | 0ULL);
> > + if (erofs_sb_has_fragments())
> > + fprintf(stdout, "Filesystem packed nid: %llu\n",
> > + sbi.packed_nid | 0ULL);
> > fprintf(stdout, "Filesystem inode count: %llu\n",
> > sbi.inos | 0ULL);
> > fprintf(stdout, "Filesystem created: %s",
> > diff --git a/include/erofs/internal.h b/include/erofs/internal.h
> > index 206913c..947894d 100644
> > --- a/include/erofs/internal.h
> > +++ b/include/erofs/internal.h
> > @@ -383,6 +383,7 @@ int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
> >
> > /* zmap.c */
> > int z_erofs_fill_inode(struct erofs_inode *vi);
> > +int z_erofs_fill_inode_lazy(struct erofs_inode *vi);
> > int z_erofs_map_blocks_iter(struct erofs_inode *vi,
> > struct erofs_map_blocks *map, int flags);
> >
> > diff --git a/lib/zmap.c b/lib/zmap.c
> > index 89e9da1..41e0713 100644
> > --- a/lib/zmap.c
> > +++ b/lib/zmap.c
> > @@ -29,7 +29,7 @@ int z_erofs_fill_inode(struct erofs_inode *vi)
> > return 0;
> > }
> >
> > -static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
> > +int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
> > {
> > int ret;
> > erofs_off_t pos;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/2] erofs-utils: dump: support fragments
2023-01-04 6:16 ` Yue Hu
@ 2023-01-04 6:44 ` Xiang Gao
2023-01-04 7:12 ` Yue Hu
0 siblings, 1 reply; 7+ messages in thread
From: Xiang Gao @ 2023-01-04 6:44 UTC (permalink / raw)
To: Yue Hu; +Cc: Yue Hu, linux-erofs, zhangwen
On 2023/1/4 14:16, Yue Hu wrote:
> Hi Xiang,
>
> Thanks for the reviewing. I'm planning to send v2.
>
> On Wed, 4 Jan 2023 11:13:55 +0800
> Xiang Gao <hsiangkao@linux.alibaba.com> wrote:
>
>> On 2022/12/19 17:50, Yue Hu wrote:
>>> From: Yue Hu <huyue2@coolpad.com>
>>>
>>> Add compressed fragments support for dump feature.
>>>
>>> Signed-off-by: Yue Hu <huyue2@coolpad.com>
>>> ---
>>> dump/main.c | 78 ++++++++++++++++++++++++++++++++--------
>>> include/erofs/internal.h | 1 +
>>> lib/zmap.c | 2 +-
>>> 3 files changed, 65 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/dump/main.c b/dump/main.c
>>> index bc4f047..d387841 100644
>>> --- a/dump/main.c
>>> +++ b/dump/main.c
>>> @@ -14,6 +14,8 @@
>>> #include "erofs/inode.h"
>>> #include "erofs/io.h"
>>> #include "erofs/dir.h"
>>> +#include "erofs/compress.h"
>>> +#include "erofs/fragments.h"
>>> #include "../lib/liberofs_private.h"
>>>
>>> #ifdef HAVE_LIBUUID
>>> @@ -96,6 +98,7 @@ static struct erofsdump_feature feature_lists[] = {
>>> { false, EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, "chunked_file" },
>>> { false, EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, "device_table" },
>>> { false, EROFS_FEATURE_INCOMPAT_ZTAILPACKING, "ztailpacking" },
>>> + { false, EROFS_FEATURE_INCOMPAT_FRAGMENTS, "fragments" },
>>> };
>>>
>>> static int erofsdump_readdir(struct erofs_dir_context *ctx);
>>> @@ -285,10 +288,12 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
>>> }
>>>
>>> if (S_ISREG(vi.i_mode)) {
>>> - stats.files_total_origin_size += vi.i_size;
>>> - inc_file_extension_count(ctx->dname, ctx->de_namelen);
>>> + if (!erofs_is_packed_inode(&vi)) {
>>> + stats.files_total_origin_size += vi.i_size;
>>> + inc_file_extension_count(ctx->dname, ctx->de_namelen);
>>> + update_file_size_statistics(vi.i_size, true);
>>> + }
>>> stats.files_total_size += occupied_size;
>>> - update_file_size_statistics(vi.i_size, true);
>>> update_file_size_statistics(occupied_size, false);
>>> }
>>>
>>> @@ -320,6 +325,10 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 "\n",
>>> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 " # device %u\n"
>>> };
>>> + const char *frag_ext_fmt[] = {
>>> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 "\n",
>>> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " # device %u\n"
>>> + };
>>
>> Why do we need another fmt rather than just fill fragment extent with
>
> I also plan to remove this fmt in v2.
>
>> physical addr 0?
>
> Okay. Just leave latter physical length as empty?
>
>>
>>> int err, i;
>>> erofs_off_t size;
>>> u16 access_mode;
>>> @@ -348,16 +357,31 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>> }
>>> }
>>>
>>> + if (erofs_inode_is_data_compressed(inode.datalayout)) {
>>> + err = z_erofs_fill_inode_lazy(&inode);
>>> + if (err) {
>>> + erofs_err("read inode map header failed @ nid %llu",
>>> + inode.nid | 0ULL);
>>> + return;
>>> + }
>>> + }
>>
>> Why do we need to call z_erofs_fill_inode_lazy here?
>
> Used to check if the file has fragment. If yes, i think 'Compression ratio' can not be showed
> exactly.
>
> So, I'd like to show fragment information related instead as below:
>
> NID: 715 Links: 1 Layout: 1 Fragment: entire file
>
> NID: 715 Links: 1 Layout: 3 Fragment: tail of file
I think no need to distinguish these two stuffs considering extra
complexity.
>
>>
>>> +
>>> err = erofs_get_occupied_size(&inode, &size);
>>> if (err) {
>>> erofs_err("get file size failed @ nid %llu", inode.nid | 0ULL);
>>> return;
>>> }
>>>
>>> - err = erofs_get_pathname(inode.nid, path, sizeof(path));
>>> - if (err < 0) {
>>> - erofs_err("file path not found @ nid %llu", inode.nid | 0ULL);
>>> - return;
>>
>> Can we just ignore pathname if it doesn't exist?
>
> Okay.
>
>>
>>> + if (erofs_is_packed_inode(&inode) { > + strncpy(path, EROFS_PACKED_INODE, sizeof(path) - 1);
>>> + path[sizeof(path) - 1] = '\0';
>>> + } else {
>>> + err = erofs_get_pathname(inode.nid, path, sizeof(path));
>>> + if (err < 0) {
>>> + erofs_err("file path not found @ nid %llu",
>>> + inode.nid | 0ULL);
>>> + return;
>>> + }
>>> }
>>>
>>> strftime(timebuf, sizeof(timebuf),
>>> @@ -372,9 +396,13 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>> file_category_types[erofs_mode_to_ftype(inode.i_mode)]);
>>> fprintf(stdout, "NID: %" PRIu64 " ", inode.nid);
>>> fprintf(stdout, "Links: %u ", inode.i_nlink);
>>> - fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
>>> - inode.datalayout,
>>> - (double)(100 * size) / (double)(inode.i_size));
>>> + if (inode.z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)
>>> + fprintf(stdout, "Layout: %d Fragment: %s\n",
>>> + inode.datalayout, size ? "partial" : "full");
>>> + else
>>> + fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
>>> + inode.datalayout,
>>> + (double)(100 * size) / (double)(inode.i_size));
>>> fprintf(stdout, "Inode size: %d ", inode.inode_isize);
>>> fprintf(stdout, "Extent size: %u ", inode.extent_isize);
>>> fprintf(stdout, "Xattr size: %u\n", inode.xattr_isize);
>>> @@ -404,7 +432,8 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>> if (!dumpcfg.show_extent)
>>> return;
>>>
>>> - fprintf(stdout, "\n Ext: logical offset | length : physical offset | length\n");
>>> + fprintf(stdout, "\n Ext: logical offset | length%s\n",
>>> + size ? " : physical offset | length" : "");
>>> while (map.m_la < inode.i_size) {
>>> struct erofs_map_dev mdev;
>>>
>>> @@ -425,10 +454,17 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>> return;
>>> }
>>>
>>> - fprintf(stdout, ext_fmt[!!mdev.m_deviceid], extent_count++,
>>> - map.m_la, map.m_la + map.m_llen, map.m_llen,
>>> - mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
>>> - mdev.m_deviceid);
>>> + if (map.m_flags & EROFS_MAP_FRAGMENT)
>>> + fprintf(stdout, frag_ext_fmt[!!mdev.m_deviceid],
>>> + extent_count++,
>>> + map.m_la, map.m_la + map.m_llen, map.m_llen,
>>> + mdev.m_deviceid);
>>
>> except for the last fragment extent, the other extents all have physical
>> addr and length...
>
> It's true.
>
> What bothers me is how to better show fragment extent based on current format (especially
> no physical address and offset for fragment extent).
>
> Now, i think the fragment extent should be showed like below (just use a '0' to represent it)?
>
> a) the whole file is a fragment:
>
> Ext: logical offset | length : physical offset | length
> 1: 0.. 1046 | 1046 : 0
Can we use
Ext: logical offset | length : physical offset | length
1: 0.. 1046 | 1046 : 0..0 | 0
>
> b) the tail of file is a fragment:
>
> Ext: logical offset | length : physical offset | length
> 0: 0.. 19672 | 19672 : 1314816.. 1323008 | 8192
> ...
> 13: 165989.. 182474 | 16485 : 1421312.. 1429504 | 8192
> 14: 182474.. 196435 | 13961 : 0
Here
14: 182474.. 196435 | 13961 : 0.. 0 | 0
as well?
>
>>
>>> + else
>>> + fprintf(stdout, ext_fmt[!!mdev.m_deviceid],
>>> + extent_count++,
>>> + map.m_la, map.m_la + map.m_llen, map.m_llen,
>>> + mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
>>> + mdev.m_deviceid);
>>> map.m_la += map.m_llen;
>>> }
>>> fprintf(stdout, "%s: %d extents found\n", path, extent_count);
>>> @@ -537,6 +573,15 @@ static void erofsdump_print_statistic(void)
>>> erofs_err("read dir failed");
>>> return;
>>> }
>>> + if (erofs_sb_has_fragments()) {
>>> + err = erofsdump_readdir(&(struct erofs_dir_context) {
>>> + .de_nid = sbi.packed_nid
>>> + });
>>
>> why do we need this?
>
> Since some status need to be updated such as stats.files_total_size.
why should packed file be recorded in files_total_size?
Thanks,
Gao Xiang
>
>>
>> Thanks,
>> Gao Xiang
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/2] erofs-utils: dump: support fragments
2023-01-04 6:44 ` Xiang Gao
@ 2023-01-04 7:12 ` Yue Hu
2023-01-04 7:19 ` Xiang Gao
0 siblings, 1 reply; 7+ messages in thread
From: Yue Hu @ 2023-01-04 7:12 UTC (permalink / raw)
To: Xiang Gao; +Cc: Yue Hu, linux-erofs, zhangwen
On Wed, 4 Jan 2023 14:44:35 +0800
Xiang Gao <hsiangkao@linux.alibaba.com> wrote:
> On 2023/1/4 14:16, Yue Hu wrote:
> > Hi Xiang,
> >
> > Thanks for the reviewing. I'm planning to send v2.
> >
> > On Wed, 4 Jan 2023 11:13:55 +0800
> > Xiang Gao <hsiangkao@linux.alibaba.com> wrote:
> >
> >> On 2022/12/19 17:50, Yue Hu wrote:
> >>> From: Yue Hu <huyue2@coolpad.com>
> >>>
> >>> Add compressed fragments support for dump feature.
> >>>
> >>> Signed-off-by: Yue Hu <huyue2@coolpad.com>
> >>> ---
> >>> dump/main.c | 78 ++++++++++++++++++++++++++++++++--------
> >>> include/erofs/internal.h | 1 +
> >>> lib/zmap.c | 2 +-
> >>> 3 files changed, 65 insertions(+), 16 deletions(-)
> >>>
> >>> diff --git a/dump/main.c b/dump/main.c
> >>> index bc4f047..d387841 100644
> >>> --- a/dump/main.c
> >>> +++ b/dump/main.c
> >>> @@ -14,6 +14,8 @@
> >>> #include "erofs/inode.h"
> >>> #include "erofs/io.h"
> >>> #include "erofs/dir.h"
> >>> +#include "erofs/compress.h"
> >>> +#include "erofs/fragments.h"
> >>> #include "../lib/liberofs_private.h"
> >>>
> >>> #ifdef HAVE_LIBUUID
> >>> @@ -96,6 +98,7 @@ static struct erofsdump_feature feature_lists[] = {
> >>> { false, EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, "chunked_file" },
> >>> { false, EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, "device_table" },
> >>> { false, EROFS_FEATURE_INCOMPAT_ZTAILPACKING, "ztailpacking" },
> >>> + { false, EROFS_FEATURE_INCOMPAT_FRAGMENTS, "fragments" },
> >>> };
> >>>
> >>> static int erofsdump_readdir(struct erofs_dir_context *ctx);
> >>> @@ -285,10 +288,12 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
> >>> }
> >>>
> >>> if (S_ISREG(vi.i_mode)) {
> >>> - stats.files_total_origin_size += vi.i_size;
> >>> - inc_file_extension_count(ctx->dname, ctx->de_namelen);
> >>> + if (!erofs_is_packed_inode(&vi)) {
> >>> + stats.files_total_origin_size += vi.i_size;
> >>> + inc_file_extension_count(ctx->dname, ctx->de_namelen);
> >>> + update_file_size_statistics(vi.i_size, true);
> >>> + }
> >>> stats.files_total_size += occupied_size;
> >>> - update_file_size_statistics(vi.i_size, true);
> >>> update_file_size_statistics(occupied_size, false);
> >>> }
> >>>
> >>> @@ -320,6 +325,10 @@ static void erofsdump_show_fileinfo(bool show_extent)
> >>> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 "\n",
> >>> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 " # device %u\n"
> >>> };
> >>> + const char *frag_ext_fmt[] = {
> >>> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 "\n",
> >>> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " # device %u\n"
> >>> + };
> >>
> >> Why do we need another fmt rather than just fill fragment extent with
> >
> > I also plan to remove this fmt in v2.
> >
> >> physical addr 0?
> >
> > Okay. Just leave latter physical length as empty?
> >
> >>
> >>> int err, i;
> >>> erofs_off_t size;
> >>> u16 access_mode;
> >>> @@ -348,16 +357,31 @@ static void erofsdump_show_fileinfo(bool show_extent)
> >>> }
> >>> }
> >>>
> >>> + if (erofs_inode_is_data_compressed(inode.datalayout)) {
> >>> + err = z_erofs_fill_inode_lazy(&inode);
> >>> + if (err) {
> >>> + erofs_err("read inode map header failed @ nid %llu",
> >>> + inode.nid | 0ULL);
> >>> + return;
> >>> + }
> >>> + }
> >>
> >> Why do we need to call z_erofs_fill_inode_lazy here?
> >
> > Used to check if the file has fragment. If yes, i think 'Compression ratio' can not be showed
> > exactly.
> >
> > So, I'd like to show fragment information related instead as below:
> >
> > NID: 715 Links: 1 Layout: 1 Fragment: entire file
> >
> > NID: 715 Links: 1 Layout: 3 Fragment: tail of file
>
> I think no need to distinguish these two stuffs considering extra
> complexity.
So, no need to check fragment or not? just keep the original look?
>
> >
> >>
> >>> +
> >>> err = erofs_get_occupied_size(&inode, &size);
> >>> if (err) {
> >>> erofs_err("get file size failed @ nid %llu", inode.nid | 0ULL);
> >>> return;
> >>> }
> >>>
> >>> - err = erofs_get_pathname(inode.nid, path, sizeof(path));
> >>> - if (err < 0) {
> >>> - erofs_err("file path not found @ nid %llu", inode.nid | 0ULL);
> >>> - return;
> >>
> >> Can we just ignore pathname if it doesn't exist?
> >
> > Okay.
> >
> >>
> >>> + if (erofs_is_packed_inode(&inode) { > + strncpy(path, EROFS_PACKED_INODE, sizeof(path) - 1);
> >>> + path[sizeof(path) - 1] = '\0';
> >>> + } else {
> >>> + err = erofs_get_pathname(inode.nid, path, sizeof(path));
> >>> + if (err < 0) {
> >>> + erofs_err("file path not found @ nid %llu",
> >>> + inode.nid | 0ULL);
> >>> + return;
> >>> + }
> >>> }
> >>>
> >>> strftime(timebuf, sizeof(timebuf),
> >>> @@ -372,9 +396,13 @@ static void erofsdump_show_fileinfo(bool show_extent)
> >>> file_category_types[erofs_mode_to_ftype(inode.i_mode)]);
> >>> fprintf(stdout, "NID: %" PRIu64 " ", inode.nid);
> >>> fprintf(stdout, "Links: %u ", inode.i_nlink);
> >>> - fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
> >>> - inode.datalayout,
> >>> - (double)(100 * size) / (double)(inode.i_size));
> >>> + if (inode.z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)
> >>> + fprintf(stdout, "Layout: %d Fragment: %s\n",
> >>> + inode.datalayout, size ? "partial" : "full");
> >>> + else
> >>> + fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
> >>> + inode.datalayout,
> >>> + (double)(100 * size) / (double)(inode.i_size));
> >>> fprintf(stdout, "Inode size: %d ", inode.inode_isize);
> >>> fprintf(stdout, "Extent size: %u ", inode.extent_isize);
> >>> fprintf(stdout, "Xattr size: %u\n", inode.xattr_isize);
> >>> @@ -404,7 +432,8 @@ static void erofsdump_show_fileinfo(bool show_extent)
> >>> if (!dumpcfg.show_extent)
> >>> return;
> >>>
> >>> - fprintf(stdout, "\n Ext: logical offset | length : physical offset | length\n");
> >>> + fprintf(stdout, "\n Ext: logical offset | length%s\n",
> >>> + size ? " : physical offset | length" : "");
> >>> while (map.m_la < inode.i_size) {
> >>> struct erofs_map_dev mdev;
> >>>
> >>> @@ -425,10 +454,17 @@ static void erofsdump_show_fileinfo(bool show_extent)
> >>> return;
> >>> }
> >>>
> >>> - fprintf(stdout, ext_fmt[!!mdev.m_deviceid], extent_count++,
> >>> - map.m_la, map.m_la + map.m_llen, map.m_llen,
> >>> - mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
> >>> - mdev.m_deviceid);
> >>> + if (map.m_flags & EROFS_MAP_FRAGMENT)
> >>> + fprintf(stdout, frag_ext_fmt[!!mdev.m_deviceid],
> >>> + extent_count++,
> >>> + map.m_la, map.m_la + map.m_llen, map.m_llen,
> >>> + mdev.m_deviceid);
> >>
> >> except for the last fragment extent, the other extents all have physical
> >> addr and length...
> >
> > It's true.
> >
> > What bothers me is how to better show fragment extent based on current format (especially
> > no physical address and offset for fragment extent).
> >
> > Now, i think the fragment extent should be showed like below (just use a '0' to represent it)?
> >
> > a) the whole file is a fragment:
> >
> > Ext: logical offset | length : physical offset | length
> > 1: 0.. 1046 | 1046 : 0
>
>
> Can we use
> Ext: logical offset | length : physical offset | length
> 1: 0.. 1046 | 1046 : 0..0 | 0
>
> >
> > b) the tail of file is a fragment:
> >
> > Ext: logical offset | length : physical offset | length
> > 0: 0.. 19672 | 19672 : 1314816.. 1323008 | 8192
> > ...
> > 13: 165989.. 182474 | 16485 : 1421312.. 1429504 | 8192
> > 14: 182474.. 196435 | 13961 : 0
>
> Here
> 14: 182474.. 196435 | 13961 : 0.. 0 | 0
>
> as well?
No problem now.
>
> >
> >>
> >>> + else
> >>> + fprintf(stdout, ext_fmt[!!mdev.m_deviceid],
> >>> + extent_count++,
> >>> + map.m_la, map.m_la + map.m_llen, map.m_llen,
> >>> + mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
> >>> + mdev.m_deviceid);
> >>> map.m_la += map.m_llen;
> >>> }
> >>> fprintf(stdout, "%s: %d extents found\n", path, extent_count);
> >>> @@ -537,6 +573,15 @@ static void erofsdump_print_statistic(void)
> >>> erofs_err("read dir failed");
> >>> return;
> >>> }
> >>> + if (erofs_sb_has_fragments()) {
> >>> + err = erofsdump_readdir(&(struct erofs_dir_context) {
> >>> + .de_nid = sbi.packed_nid
> >>> + });
> >>
> >> why do we need this?
> >
> > Since some status need to be updated such as stats.files_total_size.
>
> why should packed file be recorded in files_total_size?
Mainly related to compression ratio. files_total_size records on-disk (un)compressed size.
296 stats.files_total_size += occupied_size;
544 stats.compress_rate = (double)(100 * stats.files_total_size) /
545 (double)(stats.files_total_origin_size);
The file system compression ratio will be incorrect (since all compressed fragments are
missing).
>
> Thanks,
> Gao Xiang
>
> >
> >>
> >> Thanks,
> >> Gao Xiang
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/2] erofs-utils: dump: support fragments
2023-01-04 7:12 ` Yue Hu
@ 2023-01-04 7:19 ` Xiang Gao
0 siblings, 0 replies; 7+ messages in thread
From: Xiang Gao @ 2023-01-04 7:19 UTC (permalink / raw)
To: Yue Hu; +Cc: Yue Hu, linux-erofs, Qi Wang, zhangwen
(+ add Qi Wang)
On 2023/1/4 15:12, Yue Hu wrote:
> On Wed, 4 Jan 2023 14:44:35 +0800
> Xiang Gao <hsiangkao@linux.alibaba.com> wrote:
>
>> On 2023/1/4 14:16, Yue Hu wrote:
>>> Hi Xiang,
>>>
>>> Thanks for the reviewing. I'm planning to send v2.
>>>
>>> On Wed, 4 Jan 2023 11:13:55 +0800
>>> Xiang Gao <hsiangkao@linux.alibaba.com> wrote:
>>>
>>>> On 2022/12/19 17:50, Yue Hu wrote:
>>>>> From: Yue Hu <huyue2@coolpad.com>
>>>>>
>>>>> Add compressed fragments support for dump feature.
>>>>>
>>>>> Signed-off-by: Yue Hu <huyue2@coolpad.com>
>>>>> ---
>>>>> dump/main.c | 78 ++++++++++++++++++++++++++++++++--------
>>>>> include/erofs/internal.h | 1 +
>>>>> lib/zmap.c | 2 +-
>>>>> 3 files changed, 65 insertions(+), 16 deletions(-)
>>>>>
>>>>> diff --git a/dump/main.c b/dump/main.c
>>>>> index bc4f047..d387841 100644
>>>>> --- a/dump/main.c
>>>>> +++ b/dump/main.c
>>>>> @@ -14,6 +14,8 @@
>>>>> #include "erofs/inode.h"
>>>>> #include "erofs/io.h"
>>>>> #include "erofs/dir.h"
>>>>> +#include "erofs/compress.h"
>>>>> +#include "erofs/fragments.h"
>>>>> #include "../lib/liberofs_private.h"
>>>>>
>>>>> #ifdef HAVE_LIBUUID
>>>>> @@ -96,6 +98,7 @@ static struct erofsdump_feature feature_lists[] = {
>>>>> { false, EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, "chunked_file" },
>>>>> { false, EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, "device_table" },
>>>>> { false, EROFS_FEATURE_INCOMPAT_ZTAILPACKING, "ztailpacking" },
>>>>> + { false, EROFS_FEATURE_INCOMPAT_FRAGMENTS, "fragments" },
>>>>> };
>>>>>
>>>>> static int erofsdump_readdir(struct erofs_dir_context *ctx);
>>>>> @@ -285,10 +288,12 @@ static int erofsdump_readdir(struct erofs_dir_context *ctx)
>>>>> }
>>>>>
>>>>> if (S_ISREG(vi.i_mode)) {
>>>>> - stats.files_total_origin_size += vi.i_size;
>>>>> - inc_file_extension_count(ctx->dname, ctx->de_namelen);
>>>>> + if (!erofs_is_packed_inode(&vi)) {
>>>>> + stats.files_total_origin_size += vi.i_size;
>>>>> + inc_file_extension_count(ctx->dname, ctx->de_namelen);
>>>>> + update_file_size_statistics(vi.i_size, true);
>>>>> + }
>>>>> stats.files_total_size += occupied_size;
>>>>> - update_file_size_statistics(vi.i_size, true);
>>>>> update_file_size_statistics(occupied_size, false);
>>>>> }
>>>>>
>>>>> @@ -320,6 +325,10 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>>>> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 "\n",
>>>>> "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " : %10" PRIu64 "..%10" PRIu64 " | %7" PRIu64 " # device %u\n"
>>>>> };
>>>>> + const char *frag_ext_fmt[] = {
>>>>> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 "\n",
>>>>> + "%4d: %8" PRIu64 "..%8" PRIu64 " | %7" PRIu64 " # device %u\n"
>>>>> + };
>>>>
>>>> Why do we need another fmt rather than just fill fragment extent with
>>>
>>> I also plan to remove this fmt in v2.
>>>
>>>> physical addr 0?
>>>
>>> Okay. Just leave latter physical length as empty?
>>>
>>>>
>>>>> int err, i;
>>>>> erofs_off_t size;
>>>>> u16 access_mode;
>>>>> @@ -348,16 +357,31 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>>>> }
>>>>> }
>>>>>
>>>>> + if (erofs_inode_is_data_compressed(inode.datalayout)) {
>>>>> + err = z_erofs_fill_inode_lazy(&inode);
>>>>> + if (err) {
>>>>> + erofs_err("read inode map header failed @ nid %llu",
>>>>> + inode.nid | 0ULL);
>>>>> + return;
>>>>> + }
>>>>> + }
>>>>
>>>> Why do we need to call z_erofs_fill_inode_lazy here?
>>>
>>> Used to check if the file has fragment. If yes, i think 'Compression ratio' can not be showed
>>> exactly.
>>>
>>> So, I'd like to show fragment information related instead as below:
>>>
>>> NID: 715 Links: 1 Layout: 1 Fragment: entire file
>>>
>>> NID: 715 Links: 1 Layout: 3 Fragment: tail of file
>>
>> I think no need to distinguish these two stuffs considering extra
>> complexity.
>
> So, no need to check fragment or not? just keep the original look?
because we could get such information by observing inode extents directly.
>
>>
>>>
>>>>
>>>>> +
>>>>> err = erofs_get_occupied_size(&inode, &size);
>>>>> if (err) {
>>>>> erofs_err("get file size failed @ nid %llu", inode.nid | 0ULL);
>>>>> return;
>>>>> }
>>>>>
>>>>> - err = erofs_get_pathname(inode.nid, path, sizeof(path));
>>>>> - if (err < 0) {
>>>>> - erofs_err("file path not found @ nid %llu", inode.nid | 0ULL);
>>>>> - return;
>>>>
>>>> Can we just ignore pathname if it doesn't exist?
>>>
>>> Okay.
>>>
>>>>
>>>>> + if (erofs_is_packed_inode(&inode) { > + strncpy(path, EROFS_PACKED_INODE, sizeof(path) - 1);
>>>>> + path[sizeof(path) - 1] = '\0';
>>>>> + } else {
>>>>> + err = erofs_get_pathname(inode.nid, path, sizeof(path));
>>>>> + if (err < 0) {
>>>>> + erofs_err("file path not found @ nid %llu",
>>>>> + inode.nid | 0ULL);
>>>>> + return;
>>>>> + }
>>>>> }
>>>>>
>>>>> strftime(timebuf, sizeof(timebuf),
>>>>> @@ -372,9 +396,13 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>>>> file_category_types[erofs_mode_to_ftype(inode.i_mode)]);
>>>>> fprintf(stdout, "NID: %" PRIu64 " ", inode.nid);
>>>>> fprintf(stdout, "Links: %u ", inode.i_nlink);
>>>>> - fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
>>>>> - inode.datalayout,
>>>>> - (double)(100 * size) / (double)(inode.i_size));
>>>>> + if (inode.z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)
>>>>> + fprintf(stdout, "Layout: %d Fragment: %s\n",
>>>>> + inode.datalayout, size ? "partial" : "full");
>>>>> + else
>>>>> + fprintf(stdout, "Layout: %d Compression ratio: %.2f%%\n",
>>>>> + inode.datalayout,
>>>>> + (double)(100 * size) / (double)(inode.i_size));
>>>>> fprintf(stdout, "Inode size: %d ", inode.inode_isize);
>>>>> fprintf(stdout, "Extent size: %u ", inode.extent_isize);
>>>>> fprintf(stdout, "Xattr size: %u\n", inode.xattr_isize);
>>>>> @@ -404,7 +432,8 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>>>> if (!dumpcfg.show_extent)
>>>>> return;
>>>>>
>>>>> - fprintf(stdout, "\n Ext: logical offset | length : physical offset | length\n");
>>>>> + fprintf(stdout, "\n Ext: logical offset | length%s\n",
>>>>> + size ? " : physical offset | length" : "");
>>>>> while (map.m_la < inode.i_size) {
>>>>> struct erofs_map_dev mdev;
>>>>>
>>>>> @@ -425,10 +454,17 @@ static void erofsdump_show_fileinfo(bool show_extent)
>>>>> return;
>>>>> }
>>>>>
>>>>> - fprintf(stdout, ext_fmt[!!mdev.m_deviceid], extent_count++,
>>>>> - map.m_la, map.m_la + map.m_llen, map.m_llen,
>>>>> - mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
>>>>> - mdev.m_deviceid);
>>>>> + if (map.m_flags & EROFS_MAP_FRAGMENT)
>>>>> + fprintf(stdout, frag_ext_fmt[!!mdev.m_deviceid],
>>>>> + extent_count++,
>>>>> + map.m_la, map.m_la + map.m_llen, map.m_llen,
>>>>> + mdev.m_deviceid);
>>>>
>>>> except for the last fragment extent, the other extents all have physical
>>>> addr and length...
>>>
>>> It's true.
>>>
>>> What bothers me is how to better show fragment extent based on current format (especially
>>> no physical address and offset for fragment extent).
>>>
>>> Now, i think the fragment extent should be showed like below (just use a '0' to represent it)?
>>>
>>> a) the whole file is a fragment:
>>>
>>> Ext: logical offset | length : physical offset | length
>>> 1: 0.. 1046 | 1046 : 0
>>
>>
>> Can we use
>> Ext: logical offset | length : physical offset | length
>> 1: 0.. 1046 | 1046 : 0..0 | 0
>>
>>>
>>> b) the tail of file is a fragment:
>>>
>>> Ext: logical offset | length : physical offset | length
>>> 0: 0.. 19672 | 19672 : 1314816.. 1323008 | 8192
>>> ...
>>> 13: 165989.. 182474 | 16485 : 1421312.. 1429504 | 8192
>>> 14: 182474.. 196435 | 13961 : 0
>>
>> Here
>> 14: 182474.. 196435 | 13961 : 0.. 0 | 0
>>
>> as well?
>
> No problem now.
>
>>
>>>
>>>>
>>>>> + else
>>>>> + fprintf(stdout, ext_fmt[!!mdev.m_deviceid],
>>>>> + extent_count++,
>>>>> + map.m_la, map.m_la + map.m_llen, map.m_llen,
>>>>> + mdev.m_pa, mdev.m_pa + map.m_plen, map.m_plen,
>>>>> + mdev.m_deviceid);
>>>>> map.m_la += map.m_llen;
>>>>> }
>>>>> fprintf(stdout, "%s: %d extents found\n", path, extent_count);
>>>>> @@ -537,6 +573,15 @@ static void erofsdump_print_statistic(void)
>>>>> erofs_err("read dir failed");
>>>>> return;
>>>>> }
>>>>> + if (erofs_sb_has_fragments()) {
>>>>> + err = erofsdump_readdir(&(struct erofs_dir_context) {
>>>>> + .de_nid = sbi.packed_nid
>>>>> + });
>>>>
>>>> why do we need this?
>>>
>>> Since some status need to be updated such as stats.files_total_size.
>>
>> why should packed file be recorded in files_total_size?
>
> Mainly related to compression ratio. files_total_size records on-disk (un)compressed size.
>
> 296 stats.files_total_size += occupied_size;
>
> 544 stats.compress_rate = (double)(100 * stats.files_total_size) /
> 545 (double)(stats.files_total_origin_size);
>
> The file system compression ratio will be incorrect (since all compressed fragments are
> missing).
I really think erofsdump should deserve a deep cleanup first. we should
count the correct compression ratio for the packed file. But I don't
think we need:
static int erofsdump_readdir(struct erofs_dir_context *ctx)
{
...
stats.files++;
stats.file_category_stat[erofs_mode_to_ftype(vi.i_mode)]++;
...
}
Thanks,
Gao Xiang
>
>>
>> Thanks,
>> Gao Xiang
>>
>>>
>>>>
>>>> Thanks,
>>>> Gao Xiang
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-01-04 7:19 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-19 9:50 [RFC PATCH 1/2] erofs-utils: dump: cleanup update_file_size_statatics() Yue Hu
2022-12-19 9:50 ` [RFC PATCH 2/2] erofs-utils: dump: support fragments Yue Hu
2023-01-04 3:13 ` Xiang Gao
2023-01-04 6:16 ` Yue Hu
2023-01-04 6:44 ` Xiang Gao
2023-01-04 7:12 ` Yue Hu
2023-01-04 7:19 ` Xiang Gao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox