Linux-EROFS Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] erofs-utils: introduce extra xattr name prefix
@ 2023-04-04  8:02 Jingbo Xu
  2023-04-04  8:02 ` [PATCH 1/6] erofs-utils: declare prefix_len as u8 Jingbo Xu
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

As discussed in [1], erofs paring with overlayfs could satisfy the
scenario which originally composefs targets.  In this case, each file of
erofs is tagged with overlay.metacopy and overlay.redirect xattr, which
can be consumed by overlayfs.

The example xattr arrangement is like:

user.overlay.metacopy=""
user.overlay.redirect="/d6/a6748c13e2ef146a9587c47cd51ef692a368b180fc3d32b1ee32df4bb99133"


In the current implementation of erofs, "user.overlay.redirect" xattr
name will consume duplicate on-disk space.  In other words, each file
will allocate on-disk space for its "user.overlay.redirect" xattr name,
which explodes the output erofs image as a consequence.

This patch set introduces extra xattr name prefix feature, in which user
could specify customised xattr name prefix through mkfs.erofs.  When
matched with a user specified extra xattr name prefix, only the
trailing part of the xattr name apart from the xattr name prefix will be
stored on disk.  Please refer to patch 3 for more details of the on-disk
format.

This feature can significantly reduces the size of the output erofs image
in the scenario where files share the same xattr name or prefix heavily.

Below is the test result of the size of the output erofs image with
different option combinations of mkfs.erofs.  This is tested on the
rootfs givin in [2].

```
4.2M  large.erofs.T0.noxattr
7.4M  large.erofs.T0.xattr
6.4M  large.erofs.T0.xattr.share
5.7M  large.erofs.noxattr
8.9M  large.erofs.xattr
7.8M  large.erofs.xattr.share
```

T0: "-T0" of mkfs.erofs, w/ this option, 32 bytes on-disk inode is used;
wo/ this option, 64 byte on-disk inode is used instead

xattr: no extra option specified
noxattr: "-x -1", i.e. disable xattr

share: "--xattr-prefix=user.overlay.metacopy" and
"--xattr-prefix=user.overlay.redirect" option of mkfs.erofs. w/ this
option, the extra xattr name prefix feature is enabled.

It can be seen ~10% disk space is saved with this feature in the typical
workload.

patch 1-2 are preparing patch.


[1] https://lore.kernel.org/all/CAOQ4uxgGc33_QVBXMbQTnmbpHio4amv=W7ax2vQ1UMet0k_KoA@mail.gmail.com/
[2] https://my.owndrive.com/index.php/s/irHJXRpZHtT3a5i


Jingbo Xu (6):
  erofs-utils: declare prefix_len as u8
  erofs-utils: extract packedfile API
  erofs-utils: introduce on-disk format for extra xattr name prefix
  erofs-utils: introduce init/cleanup routine for extra xattr name prefix
  erofs-utils: build erofs_xattr_entry upon extra xattr name prefix
  erofs-utils: mkfs.erofs: introduce --xattr-prefix option

 include/erofs/config.h    |   2 +
 include/erofs/fragments.h |  19 +++++--
 include/erofs/inode.h     |   2 +
 include/erofs/internal.h  |   3 ++
 include/erofs/xattr.h     |   3 ++
 include/erofs_fs.h        |   7 ++-
 lib/fragments.c           |  20 +++-----
 lib/xattr.c               | 104 +++++++++++++++++++++++++++++++++++++-
 mkfs/main.c               |  48 +++++++++++++++---
 9 files changed, 183 insertions(+), 25 deletions(-)

-- 
2.19.1.6.gb485710b


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

* [PATCH 1/6] erofs-utils: declare prefix_len as u8
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  2023-04-04  8:02 ` [PATCH 2/6] erofs-utils: extract packedfile API Jingbo Xu
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

The on-disk erofs_xattr_entry.e_name_len is declared as u8, which
implies the maximum length of the xattr name.

Let's also declare xattr_prefix.prefix_len as u8 to keep sync with the
on-disk structure.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 lib/xattr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/xattr.c b/lib/xattr.c
index 1a22284..a292f2c 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -41,7 +41,7 @@ static unsigned int shared_xattrs_count, shared_xattrs_size;
 
 static struct xattr_prefix {
 	const char *prefix;
-	u16 prefix_len;
+	u8 prefix_len;
 } xattr_types[] = {
 	[EROFS_XATTR_INDEX_USER] = {
 		XATTR_USER_PREFIX,
-- 
2.19.1.6.gb485710b


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

* [PATCH 2/6] erofs-utils: extract packedfile API
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
  2023-04-04  8:02 ` [PATCH 1/6] erofs-utils: declare prefix_len as u8 Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  2023-04-04  8:02 ` [PATCH 3/6] erofs-utils: introduce on-disk format for extra xattr name prefix Jingbo Xu
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

Later packed_inode will be used in more scenarios other than fragments,
thus extract the separate packedfile API for future use.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 include/erofs/config.h    |  1 +
 include/erofs/fragments.h | 19 ++++++++++++++++---
 include/erofs/inode.h     |  2 ++
 lib/fragments.c           | 20 ++++++++------------
 mkfs/main.c               | 32 ++++++++++++++++++++++++--------
 5 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index 648a3e8..e4d4130 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -52,6 +52,7 @@ struct erofs_configure {
 	bool c_dedupe;
 	bool c_ignore_mtime;
 	bool c_showprogress;
+	bool c_packedfile;
 
 #ifdef HAVE_LIBSELINUX
 	struct selabel_handle *sehnd;
diff --git a/include/erofs/fragments.h b/include/erofs/fragments.h
index 21753ec..1b7c06b 100644
--- a/include/erofs/fragments.h
+++ b/include/erofs/fragments.h
@@ -12,15 +12,28 @@ extern "C"
 
 #include "erofs/internal.h"
 
-extern const char *frags_packedname;
-#define EROFS_PACKED_INODE	frags_packedname
+extern FILE *packedfile;
+int erofs_packedfile_init(void);
+void erofs_packedfile_exit(void);
+struct erofs_inode *erofs_mkfs_build_packedfile(void);
+
+static inline int erofs_packedfile_is_empty(void)
+{
+#ifdef HAVE_FTELLO64
+	off64_t offset = ftello64(packedfile);
+#else
+	off_t offset = ftello(packedfile);
+#endif
+	if (offset < 0)
+		return -errno;
+	return offset == 0;
+}
 
 int z_erofs_fragments_dedupe(struct erofs_inode *inode, int fd, u32 *tofcrc);
 int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd, u32 tofcrc);
 int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
 			   unsigned int len, u32 tofcrc);
 void z_erofs_fragments_commit(struct erofs_inode *inode);
-struct erofs_inode *erofs_mkfs_build_fragments(void);
 int erofs_fragments_init(void);
 void erofs_fragments_exit(void);
 
diff --git a/include/erofs/inode.h b/include/erofs/inode.h
index 058a235..cb8568a 100644
--- a/include/erofs/inode.h
+++ b/include/erofs/inode.h
@@ -21,6 +21,8 @@ void erofs_inode_manager_init(void);
 unsigned int erofs_iput(struct erofs_inode *inode);
 erofs_nid_t erofs_lookupnid(struct erofs_inode *inode);
 struct erofs_inode *erofs_mkfs_build_tree_from_path(const char *path);
+
+#define EROFS_PACKED_INODE	("packed_file")
 struct erofs_inode *erofs_mkfs_build_special_from_fd(int fd, const char *name);
 
 #ifdef __cplusplus
diff --git a/lib/fragments.c b/lib/fragments.c
index 0366c82..25d72f9 100644
--- a/lib/fragments.c
+++ b/lib/fragments.c
@@ -39,8 +39,7 @@ struct erofs_fragment_dedupe_item {
 
 static struct list_head dupli_frags[FRAGMENT_HASHSIZE];
 
-static FILE *packedfile;
-const char *frags_packedname = "packed_file";
+FILE *packedfile;
 
 #ifndef HAVE_LSEEK64
 #define erofs_lseek64 lseek
@@ -195,15 +194,16 @@ static int z_erofs_fragments_dedupe_insert(void *data, unsigned int len,
 	return 0;
 }
 
-static void z_erofs_fragments_dedupe_init(void)
+int erofs_fragments_init(void)
 {
 	unsigned int i;
 
 	for (i = 0; i < FRAGMENT_HASHSIZE; ++i)
 		init_list_head(&dupli_frags[i]);
+	return 0;
 }
 
-static void z_erofs_fragments_dedupe_exit(void)
+void erofs_fragments_exit(void)
 {
 	struct erofs_fragment_dedupe_item *di, *n;
 	struct list_head *head;
@@ -324,23 +324,21 @@ int z_erofs_pack_fragments(struct erofs_inode *inode, void *data,
 	return len;
 }
 
-struct erofs_inode *erofs_mkfs_build_fragments(void)
+struct erofs_inode *erofs_mkfs_build_packedfile(void)
 {
 	fflush(packedfile);
 
 	return erofs_mkfs_build_special_from_fd(fileno(packedfile),
-						frags_packedname);
+						EROFS_PACKED_INODE);
 }
 
-void erofs_fragments_exit(void)
+void erofs_packedfile_exit(void)
 {
 	if (packedfile)
 		fclose(packedfile);
-
-	z_erofs_fragments_dedupe_exit();
 }
 
-int erofs_fragments_init(void)
+int erofs_packedfile_init(void)
 {
 #ifdef HAVE_TMPFILE64
 	packedfile = tmpfile64();
@@ -349,7 +347,5 @@ int erofs_fragments_init(void)
 #endif
 	if (!packedfile)
 		return -ENOMEM;
-
-	z_erofs_fragments_dedupe_init();
 	return 0;
 }
diff --git a/mkfs/main.c b/mkfs/main.c
index 65d3df6..50fd908 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -555,6 +555,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 		}
 		cfg.c_pclusterblks_packed = pclustersize_packed >> sbi.blkszbits;
 	}
+	if (cfg.c_fragments)
+		cfg.c_packedfile = true;
 	return 0;
 }
 
@@ -770,10 +772,17 @@ int main(int argc, char **argv)
 	}
 #endif
 	erofs_show_config();
-	if (cfg.c_fragments) {
+	if (cfg.c_packedfile) {
 		if (!cfg.c_pclusterblks_packed)
 			cfg.c_pclusterblks_packed = cfg.c_pclusterblks_def;
 
+		err = erofs_packedfile_init();
+		if (err) {
+			erofs_err("failed to initialize packedfile");
+			return 1;
+		}
+	}
+	if (cfg.c_fragments) {
 		err = erofs_fragments_init();
 		if (err) {
 			erofs_err("failed to initialize fragments");
@@ -880,15 +889,20 @@ int main(int argc, char **argv)
 	}
 
 	packed_nid = 0;
-	if (cfg.c_fragments && erofs_sb_has_fragments()) {
-		erofs_update_progressinfo("Handling packed_file ...");
-		packed_inode = erofs_mkfs_build_fragments();
-		if (IS_ERR(packed_inode)) {
-			err = PTR_ERR(packed_inode);
+	if (cfg.c_packedfile) {
+		err = erofs_packedfile_is_empty();
+		if (err < 0)
 			goto exit;
+		if (!err) {
+			erofs_update_progressinfo("Handling packed_file ...");
+			packed_inode = erofs_mkfs_build_packedfile();
+			if (IS_ERR(packed_inode)) {
+				err = PTR_ERR(packed_inode);
+				goto exit;
+			}
+			packed_nid = erofs_lookupnid(packed_inode);
+			erofs_iput(packed_inode);
 		}
-		packed_nid = erofs_lookupnid(packed_inode);
-		erofs_iput(packed_inode);
 	}
 
 	err = erofs_mkfs_update_super_block(sb_bh, root_nid, &nblocks,
@@ -917,6 +931,8 @@ exit:
 		erofs_blob_exit();
 	if (cfg.c_fragments)
 		erofs_fragments_exit();
+	if (cfg.c_packedfile)
+		erofs_packedfile_exit();
 	erofs_exit_configure();
 
 	if (err) {
-- 
2.19.1.6.gb485710b


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

* [PATCH 3/6] erofs-utils: introduce on-disk format for extra xattr name prefix
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
  2023-04-04  8:02 ` [PATCH 1/6] erofs-utils: declare prefix_len as u8 Jingbo Xu
  2023-04-04  8:02 ` [PATCH 2/6] erofs-utils: extract packedfile API Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  2023-04-04  8:19   ` Gao Xiang
  2023-04-04  8:02 ` [PATCH 4/6] erofs-utils: introduce init/cleanup routine " Jingbo Xu
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

Besides the predefined xattr name prefixes, introduces extra xattr name
prefixes, which works similarly as the predefined xattr name prefixees,
except that they are user specified.

When matched with a user specified extra xattr name prefix, only the
trailing part of the xattr name except the xattr name prefix will be
stored in erofs_xattr_entry.e_name.  e_name is empty if the xattr name
matches exactly as the extra xattr name prefix.

All extra xattr name prefixes are stored in the packed file.  For each
extra xattr name prefix, the on-disk format in packed file can be shown
as (u8 prefix_len, prefix string), where the first u8 represents the
length of the prefix string (excluding '\0'), followed by the content of
the prefix string (including '\0').

Two fields are introduced to the on-disk superblock, where
ea_prefix_count represents the total number of the extra xattr name
prefixes recorded in the packed file, and ea_prefix_off represents the
start offset of recorded name prefixes in the packed file.

When referring to an extra xattr name prefix, the highest bit (bit 7) of
erofs_xattr_entry.e_name_index is set, while the lower bits (bit 0-6)
as a whole represents the index of the referred name prefix among all
extra xattr name prefixes in the packed file.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 include/erofs_fs.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index 8835a76..3d8eb5f 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -77,7 +77,9 @@ struct erofs_super_block {
 	} __packed u1;
 	__le16 extra_devices;	/* # of devices besides the primary device */
 	__le16 devt_slotoff;	/* startoff = devt_slotoff * devt_slotsize */
-	__u8 reserved[6];
+	__u8 reserved;
+	__u8 ea_prefix_count;	/* # of extra xattr name prefix */
+	__le32 ea_prefix_off;	/* start offset of extra prefixes in packed inode */
 	__le64 packed_nid;	/* nid of the special packed inode */
 	__u8 reserved2[24];
 };
@@ -228,6 +230,9 @@ struct erofs_xattr_ibody_header {
 #define EROFS_XATTR_INDEX_LUSTRE            5
 #define EROFS_XATTR_INDEX_SECURITY          6
 
+#define EROFS_XATTR_EA_FLAG	(1 << 7)
+#define EROFS_XATTR_EA_MASK	(EROFS_XATTR_EINDEX_FLAG - 1)
+
 /* xattr entry (for both inline & shared xattrs) */
 struct erofs_xattr_entry {
 	__u8   e_name_len;      /* length of name */
-- 
2.19.1.6.gb485710b


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

* [PATCH 4/6] erofs-utils: introduce init/cleanup routine for extra xattr name prefix
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
                   ` (2 preceding siblings ...)
  2023-04-04  8:02 ` [PATCH 3/6] erofs-utils: introduce on-disk format for extra xattr name prefix Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  2023-04-04  8:02 ` [PATCH 5/6] erofs-utils: build erofs_xattr_entry upon " Jingbo Xu
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

Introduce helpers for registering and cleaning up extra xattr name
prefix.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 include/erofs/xattr.h |  3 +++
 lib/xattr.c           | 58 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
index 9efadc5..1085908 100644
--- a/include/erofs/xattr.h
+++ b/include/erofs/xattr.h
@@ -70,6 +70,9 @@ int erofs_prepare_xattr_ibody(struct erofs_inode *inode);
 char *erofs_export_xattr_ibody(struct list_head *ixattrs, unsigned int size);
 int erofs_build_shared_xattrs_from_path(const char *path);
 
+int erofs_insert_ea_type(const char *prefix);
+void erofs_cleanup_ea_type(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/xattr.c b/lib/xattr.c
index a292f2c..ec40aad 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -61,6 +61,14 @@ static struct xattr_prefix {
 	}
 };
 
+struct ea_type_node {
+	struct list_head list;
+	struct xattr_prefix type;
+	u8 index;
+};
+static LIST_HEAD(ea_types);
+static unsigned int ea_types_count;
+
 static unsigned int BKDRHash(char *str, unsigned int len)
 {
 	const unsigned int seed = 131313;
@@ -1222,3 +1230,53 @@ int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size)
 		return ret;
 	return shared_listxattr(vi, &it);
 }
+
+int erofs_insert_ea_type(const char *prefix)
+{
+	struct ea_type_node *tnode;
+	struct xattr_prefix *p;
+	bool matched = false;
+	char *s;
+
+	if (ea_types_count == EROFS_XATTR_EA_FLAG || strlen(prefix) > UINT8_MAX)
+		return -EOVERFLOW;
+
+	for (p = xattr_types; p < xattr_types + ARRAY_SIZE(xattr_types); ++p) {
+		if (!strncmp(p->prefix, prefix, p->prefix_len)) {
+			matched = true;
+			break;
+		}
+	}
+	if (!matched)
+		return -ENODATA;
+
+	s = strdup(prefix);
+	if (!s)
+		return -ENOMEM;
+
+	tnode = malloc(sizeof(*tnode));
+	if (!tnode) {
+		free(s);
+		return -ENOMEM;
+	}
+
+	tnode->type.prefix = s;
+	tnode->type.prefix_len = strlen(prefix);
+
+	tnode->index = EROFS_XATTR_EA_FLAG | ea_types_count;
+	ea_types_count++;
+	init_list_head(&tnode->list);
+	list_add_tail(&tnode->list, &ea_types);
+	return 0;
+}
+
+void erofs_cleanup_ea_type(void)
+{
+	struct ea_type_node *tnode, *n;
+
+	list_for_each_entry_safe(tnode, n, &ea_types, list) {
+		list_del(&tnode->list);
+		free(tnode->type.prefix);
+		free(tnode);
+	}
+}
-- 
2.19.1.6.gb485710b


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

* [PATCH 5/6] erofs-utils: build erofs_xattr_entry upon extra xattr name prefix
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
                   ` (3 preceding siblings ...)
  2023-04-04  8:02 ` [PATCH 4/6] erofs-utils: introduce init/cleanup routine " Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  2023-04-04  8:02 ` [PATCH 6/6] erofs-utils: mkfs.erofs: introduce --xattr-prefix option Jingbo Xu
  2023-04-04  8:02 ` [PATCH] tmp debug Jingbo Xu
  6 siblings, 0 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

Build the xattr entry also considering the extra xattr name prefix.  The
user specified extra xattr name prefix takes precedence over the
predefined xattr name prefix.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 include/erofs/internal.h |  3 +++
 lib/xattr.c              | 44 ++++++++++++++++++++++++++++++++++++++++
 mkfs/main.c              |  2 ++
 3 files changed, 49 insertions(+)

diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 641a795..f441429 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -102,6 +102,9 @@ struct erofs_sb_info {
 		u16 device_id_mask;		/* used for others */
 	};
 	erofs_nid_t packed_nid;
+
+	u32 ea_prefix_off;
+	u8 ea_prefix_count;
 };
 
 /* make sure that any user of the erofs headers has atleast 64bit off_t type */
diff --git a/lib/xattr.c b/lib/xattr.c
index ec40aad..f1db8bf 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -17,6 +17,7 @@
 #include "erofs/xattr.h"
 #include "erofs/cache.h"
 #include "erofs/io.h"
+#include "erofs/fragments.h"
 #include "liberofs_private.h"
 
 #define EA_HASHTABLE_BITS 16
@@ -138,7 +139,16 @@ static struct xattr_item *get_xattritem(u8 prefix, char *kvbuf,
 static bool match_prefix(const char *key, u8 *index, u16 *len)
 {
 	struct xattr_prefix *p;
+	struct ea_type_node *tnode;
 
+	list_for_each_entry(tnode, &ea_types, list) {
+		p = &tnode->type;
+		if (p->prefix && !strncmp(p->prefix, key, p->prefix_len)) {
+			*len = p->prefix_len;
+			*index = tnode->index;
+			return true;
+		}
+	}
 	for (p = xattr_types; p < xattr_types + ARRAY_SIZE(xattr_types); ++p) {
 		if (p->prefix && !strncmp(p->prefix, key, p->prefix_len)) {
 			*len = p->prefix_len;
@@ -587,6 +597,34 @@ static int comp_xattr_item(const void *a, const void *b)
 	return la > lb;
 }
 
+static int erofs_xattr_write_ea_prefix(void)
+{
+	struct ea_type_node *tnode;
+	struct xattr_prefix *p;
+#ifdef HAVE_FTELLO64
+	off64_t offset = ftello64(packedfile);
+#else
+	off_t offset = ftello(packedfile);
+#endif
+
+	if (offset < 0)
+		return -errno;
+	if (offset > UINT32_MAX)
+		return -EOVERFLOW;
+
+	sbi.ea_prefix_count = ea_types_count;
+	sbi.ea_prefix_off = (u32)offset;
+
+	list_for_each_entry(tnode, &ea_types, list) {
+		p = &tnode->type;
+		if (fwrite(&p->prefix_len, sizeof(u8), 1, packedfile) != 1)
+			return -EIO;
+		if (fwrite(p->prefix, p->prefix_len + 1, 1, packedfile) != 1)
+			return -EIO;
+	}
+	return 0;
+}
+
 int erofs_build_shared_xattrs_from_path(const char *path)
 {
 	int ret;
@@ -610,6 +648,12 @@ int erofs_build_shared_xattrs_from_path(const char *path)
 	if (ret)
 		return ret;
 
+	if (ea_types_count) {
+		ret = erofs_xattr_write_ea_prefix();
+		if (ret)
+			return ret;
+	}
+
 	if (!shared_xattrs_size)
 		goto out;
 
diff --git a/mkfs/main.c b/mkfs/main.c
index 50fd908..56b100c 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -574,6 +574,8 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 		.blocks = 0,
 		.meta_blkaddr  = sbi.meta_blkaddr,
 		.xattr_blkaddr = sbi.xattr_blkaddr,
+		.ea_prefix_count = sbi.ea_prefix_count,
+		.ea_prefix_off = cpu_to_le32(sbi.ea_prefix_off),
 		.feature_incompat = cpu_to_le32(sbi.feature_incompat),
 		.feature_compat = cpu_to_le32(sbi.feature_compat &
 					      ~EROFS_FEATURE_COMPAT_SB_CHKSUM),
-- 
2.19.1.6.gb485710b


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

* [PATCH 6/6] erofs-utils: mkfs.erofs: introduce --xattr-prefix option
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
                   ` (4 preceding siblings ...)
  2023-04-04  8:02 ` [PATCH 5/6] erofs-utils: build erofs_xattr_entry upon " Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  2023-04-04  8:02 ` [PATCH] tmp debug Jingbo Xu
  6 siblings, 0 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

Introduce --xattr-prefix option to make user capable of specifying
customised extra xattr name prefix.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 include/erofs/config.h |  1 +
 mkfs/main.c            | 16 +++++++++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index e4d4130..bf3c5d2 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -53,6 +53,7 @@ struct erofs_configure {
 	bool c_ignore_mtime;
 	bool c_showprogress;
 	bool c_packedfile;
+	bool c_ea_prefix;
 
 #ifdef HAVE_LIBSELINUX
 	struct selabel_handle *sehnd;
diff --git a/mkfs/main.c b/mkfs/main.c
index 56b100c..09b03fc 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -56,6 +56,7 @@ static struct option long_options[] = {
 	{"preserve-mtime", no_argument, NULL, 15},
 	{"uid-offset", required_argument, NULL, 16},
 	{"gid-offset", required_argument, NULL, 17},
+	{"xattr-prefix", required_argument, NULL, 19},
 	{"mount-point", required_argument, NULL, 512},
 #ifdef WITH_ANDROID
 	{"product-out", required_argument, NULL, 513},
@@ -116,6 +117,7 @@ static void usage(void)
 	      " --random-pclusterblks randomize pclusterblks for big pcluster (debugging only)\n"
 	      " --random-algorithms   randomize per-file algorithms (debugging only)\n"
 #endif
+	      " --xattr-prefix=X      X=extra xattr name prefix\n"
 	      " --mount-point=X       X=prefix of target fs path (default: /)\n"
 #ifdef WITH_ANDROID
 	      "\nwith following android-specific options:\n"
@@ -475,6 +477,16 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 				return -EINVAL;
 			}
 			break;
+		case 19:
+			errno = 0;
+			opt = erofs_insert_ea_type(optarg);
+			if (opt) {
+				erofs_err("failed to parse extra xattr prefix: %s",
+					  erofs_strerror(opt));
+				return opt;
+			}
+			cfg.c_ea_prefix = true;
+			break;
 		case 1:
 			usage();
 			exit(0);
@@ -555,7 +567,7 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 		}
 		cfg.c_pclusterblks_packed = pclustersize_packed >> sbi.blkszbits;
 	}
-	if (cfg.c_fragments)
+	if (cfg.c_fragments || cfg.c_ea_prefix)
 		cfg.c_packedfile = true;
 	return 0;
 }
@@ -935,6 +947,8 @@ exit:
 		erofs_fragments_exit();
 	if (cfg.c_packedfile)
 		erofs_packedfile_exit();
+	if (cfg.c_ea_prefix)
+		erofs_cleanup_ea_type();
 	erofs_exit_configure();
 
 	if (err) {
-- 
2.19.1.6.gb485710b


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

* [PATCH] tmp debug
  2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
                   ` (5 preceding siblings ...)
  2023-04-04  8:02 ` [PATCH 6/6] erofs-utils: mkfs.erofs: introduce --xattr-prefix option Jingbo Xu
@ 2023-04-04  8:02 ` Jingbo Xu
  6 siblings, 0 replies; 9+ messages in thread
From: Jingbo Xu @ 2023-04-04  8:02 UTC (permalink / raw)
  To: linux-erofs, hsiangkao

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 lib/inode.c | 7 ++++++-
 lib/xattr.c | 3 +++
 mkfs/main.c | 4 ++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/lib/inode.c b/lib/inode.c
index 6861b99..b252904 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -272,8 +272,11 @@ erofs_nid_t erofs_lookupnid(struct erofs_inode *inode)
 	struct erofs_buffer_head *const bh = inode->bh;
 	erofs_off_t off, meta_offset;
 
-	if (!bh || (long long)inode->nid > 0)
+	if (!bh || (long long)inode->nid > 0) {
+		erofs_dbg(" nid %llu to file %s, bh %p",
+		  inode->nid, inode->i_srcpath, inode->bh);
 		return inode->nid;
+	}
 
 	erofs_mapbh(bh->block);
 	off = erofs_btell(bh, false);
@@ -1266,6 +1269,8 @@ struct erofs_inode *erofs_mkfs_build_special_from_fd(int fd, const char *name)
 	if (name == EROFS_PACKED_INODE) {
 		sbi.packed_nid = EROFS_PACKED_NID_UNALLOCATED;
 		inode->nid = sbi.packed_nid;
+		erofs_dbg("erofs_mkfs_build_special_from_fd: nid %llu to file %s, bh %p",
+		  inode->nid, inode->i_srcpath, inode->bh);
 	}
 
 	ret = erofs_write_compressed_file(inode, fd);
diff --git a/lib/xattr.c b/lib/xattr.c
index de462ab..c336d9d 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -141,11 +141,14 @@ static bool match_prefix(const char *key, u8 *index, u16 *len)
 	struct xattr_prefix *p;
 	struct extra_xattr_type_node *tnode;
 
+	printf("[match_prefix]: enter extra_xattr_types_count++ is %u\n", extra_xattr_types_count);
 	list_for_each_entry(tnode, &extra_xattr_types, list) {
 		p = &tnode->type;
+		printf("[iterating]: key %s, prefix %s\n", key, p->prefix);
 		if (p->prefix && !strncmp(p->prefix, key, p->prefix_len)) {
 			*len = p->prefix_len;
 			*index = tnode->index;
+			printf("match_prefix: key %s, matches prefix %s, index %u\n", key, p->prefix, tnode->index);
 			return true;
 		}
 	}
diff --git a/mkfs/main.c b/mkfs/main.c
index d06f6f5..ce220c7 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -911,13 +911,17 @@ int main(int argc, char **argv)
 			erofs_update_progressinfo("Handling packed_file ...");
 			packed_inode = erofs_mkfs_build_packedfile();
 			if (IS_ERR(packed_inode)) {
+				printf("[%s %d] erofs_mkfs_build_packedfile failed\n", __func__, __LINE__);
 				err = PTR_ERR(packed_inode);
 				goto exit;
 			}
+			printf("[%s %d] start erofs_lookupnid...\n", __func__, __LINE__);
 			packed_nid = erofs_lookupnid(packed_inode);
+			printf("[%s %d] packed_nid %lu\n", __func__, __LINE__, packed_nid);
 			erofs_iput(packed_inode);
 		}
 	}
+	printf("[%s %d] packed_nid %lu\n", __func__, __LINE__, packed_nid);
 
 	err = erofs_mkfs_update_super_block(sb_bh, root_nid, &nblocks,
 					    packed_nid);
-- 
2.19.1.6.gb485710b


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

* Re: [PATCH 3/6] erofs-utils: introduce on-disk format for extra xattr name prefix
  2023-04-04  8:02 ` [PATCH 3/6] erofs-utils: introduce on-disk format for extra xattr name prefix Jingbo Xu
@ 2023-04-04  8:19   ` Gao Xiang
  0 siblings, 0 replies; 9+ messages in thread
From: Gao Xiang @ 2023-04-04  8:19 UTC (permalink / raw)
  To: Jingbo Xu, linux-erofs



On 2023/4/4 16:02, Jingbo Xu wrote:
> Besides the predefined xattr name prefixes, introduces extra xattr name
> prefixes, which works similarly as the predefined xattr name prefixees,
> except that they are user specified.

Besides the built-in xattr name prefixes, let's introduce user-defined
extra xattr name prefixes, which works similarly as the pre-defined xattr
name prefixees, except that they are user specified.

> 
> When matched with a user specified extra xattr name prefix, only the
> trailing part of the xattr name except the xattr name prefix will be
> stored in erofs_xattr_entry.e_name.  e_name is empty if the xattr name
> matches exactly as the extra xattr name prefix.

When a user-specified extra xattr name prefix is matched, only the
trailing part of the xattr name which already eliminates the given
prefix will be stored in `erofs_xattr_entry.e_name`.  `e_name` can be
empty if the xattr full name matches exactly as the name prefix.

> 
> All extra xattr name prefixes are stored in the packed file.  For each
> extra xattr name prefix, the on-disk format in packed file can be shown
> as (u8 prefix_len, prefix string), where the first u8 represents the
> length of the prefix string (excluding '\0'), followed by the content of
> the prefix string (including '\0').

Why we have to introduce a prefix_len here?

> 
> Two fields are introduced to the on-disk superblock, where
> ea_prefix_count represents the total number of the extra xattr name
> prefixes recorded in the packed file, and ea_prefix_off represents the
> start offset of recorded name prefixes in the packed file.
> 
> When referring to an extra xattr name prefix, the highest bit (bit 7) of
> erofs_xattr_entry.e_name_index is set, while the lower bits (bit 0-6)
> as a whole represents the index of the referred name prefix among all
> extra xattr name prefixes in the packed file.

When an extra xattr name prefix is referred, the highest bit (bit 7) of
`erofs_xattr_entry.e_name_index` is set, while the lower bits (bit 0-6)
as a whole represents the index of the referred name prefix among all
extra xattr name prefixes in the packed file.

> 
> Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
> ---
>   include/erofs_fs.h | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> index 8835a76..3d8eb5f 100644
> --- a/include/erofs_fs.h
> +++ b/include/erofs_fs.h
> @@ -77,7 +77,9 @@ struct erofs_super_block {
>   	} __packed u1;
>   	__le16 extra_devices;	/* # of devices besides the primary device */
>   	__le16 devt_slotoff;	/* startoff = devt_slotoff * devt_slotsize */
> -	__u8 reserved[6];
> +	__u8 reserved;
> +	__u8 ea_prefix_count;	/* # of extra xattr name prefix */
> +	__le32 ea_prefix_off;	/* start offset of extra prefixes in packed inode */
>   	__le64 packed_nid;	/* nid of the special packed inode */
>   	__u8 reserved2[24];
>   };
> @@ -228,6 +230,9 @@ struct erofs_xattr_ibody_header {
>   #define EROFS_XATTR_INDEX_LUSTRE            5
>   #define EROFS_XATTR_INDEX_SECURITY          6
>   
> +#define EROFS_XATTR_EA_FLAG	(1 << 7)
> +#define EROFS_XATTR_EA_MASK	(EROFS_XATTR_EINDEX_FLAG - 1)

EROFS_EXTRA_XATTR_FLAG		0x80
EROFS_EXTRA_XATTR_MASK		0x7F

?

Thanks,
Gao Xiang

> +
>   /* xattr entry (for both inline & shared xattrs) */
>   struct erofs_xattr_entry {
>   	__u8   e_name_len;      /* length of name */

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

end of thread, other threads:[~2023-04-04  8:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-04  8:02 [PATCH 0/6] erofs-utils: introduce extra xattr name prefix Jingbo Xu
2023-04-04  8:02 ` [PATCH 1/6] erofs-utils: declare prefix_len as u8 Jingbo Xu
2023-04-04  8:02 ` [PATCH 2/6] erofs-utils: extract packedfile API Jingbo Xu
2023-04-04  8:02 ` [PATCH 3/6] erofs-utils: introduce on-disk format for extra xattr name prefix Jingbo Xu
2023-04-04  8:19   ` Gao Xiang
2023-04-04  8:02 ` [PATCH 4/6] erofs-utils: introduce init/cleanup routine " Jingbo Xu
2023-04-04  8:02 ` [PATCH 5/6] erofs-utils: build erofs_xattr_entry upon " Jingbo Xu
2023-04-04  8:02 ` [PATCH 6/6] erofs-utils: mkfs.erofs: introduce --xattr-prefix option Jingbo Xu
2023-04-04  8:02 ` [PATCH] tmp debug Jingbo Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox