All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jingbo Xu <jefflexu@linux.alibaba.com>
To: hsiangkao@linux.alibaba.com, chao@kernel.org, huyue2@coolpad.com,
	linux-erofs@lists.ozlabs.org
Cc: alexl@redhat.com
Subject: [PATCH v2 3/3] erofs-utils: mkfs: enable xattr name filter
Date: Wed,  5 Jul 2023 15:10:17 +0800	[thread overview]
Message-ID: <20230705071017.104130-4-jefflexu@linux.alibaba.com> (raw)
In-Reply-To: <20230705071017.104130-1-jefflexu@linux.alibaba.com>

Introduce "--xattr-filter" option to enable the xattr name bloom filter
feature.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 include/erofs/config.h   |  1 +
 include/erofs/internal.h |  1 +
 lib/xattr.c              | 74 +++++++++++++++++++++++++++++++---------
 mkfs/main.c              |  6 ++++
 4 files changed, 66 insertions(+), 16 deletions(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index 8f52d2c..2803f37 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_extra_ea_name_prefixes;
+	bool c_xattr_filter;
 
 #ifdef HAVE_LIBSELINUX
 	struct selabel_handle *sehnd;
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index ab964d4..1d7ef73 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -133,6 +133,7 @@ EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
 EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
 EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
+EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER)
 
 #define EROFS_I_EA_INITED	(1 << 0)
 #define EROFS_I_Z_INITED	(1 << 1)
diff --git a/lib/xattr.c b/lib/xattr.c
index 7d7dc54..c9126c6 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -18,6 +18,7 @@
 #include "erofs/cache.h"
 #include "erofs/io.h"
 #include "erofs/fragments.h"
+#include "erofs/xxhash.h"
 #include "liberofs_private.h"
 
 #define EA_HASHTABLE_BITS 16
@@ -26,6 +27,7 @@ struct xattr_item {
 	struct xattr_item *next_shared_xattr;
 	const char *kvbuf;
 	unsigned int hash[2], len[2], count;
+	unsigned int name_filter_bit;
 	int shared_xattr_id;
 	u8 prefix;
 	struct hlist_node node;
@@ -101,7 +103,8 @@ static unsigned int put_xattritem(struct xattr_item *item)
 }
 
 static struct xattr_item *get_xattritem(u8 prefix, char *kvbuf,
-					unsigned int len[2])
+					unsigned int len[2],
+					unsigned int name_filter_bit)
 {
 	struct xattr_item *item;
 	unsigned int hash[2], hkey;
@@ -133,40 +136,59 @@ static struct xattr_item *get_xattritem(u8 prefix, char *kvbuf,
 	item->hash[1] = hash[1];
 	item->shared_xattr_id = -1;
 	item->prefix = prefix;
+	item->name_filter_bit = name_filter_bit;
 	hash_add(ea_hashtable, &item->node, hkey);
 	return item;
 }
 
-static bool match_prefix(const char *key, u8 *index, u16 *len)
+static unsigned int erofs_xattr_calc_name_filter_bit(u8 prefix, const char *key,
+						     unsigned int len)
+{
+	if (!cfg.c_xattr_filter)
+		return 0;
+	return xxh32(key, len, EROFS_XATTR_FILTER_SEED + prefix) &
+			EROFS_XATTR_FILTER_MASK;
+}
+
+static bool match_short_prefix(const char *key, u8 *index, u16 *len)
 {
 	struct xattr_prefix *p;
-	struct ea_type_node *tnode;
 
-	list_for_each_entry(tnode, &ea_name_prefixes, list) {
-		p = &tnode->type;
+	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;
-			*index = tnode->index;
+			*index = p - xattr_types;
 			return true;
 		}
 	}
-	for (p = xattr_types; p < xattr_types + ARRAY_SIZE(xattr_types); ++p) {
+	return false;
+}
+
+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_name_prefixes, list) {
+		p = &tnode->type;
 		if (p->prefix && !strncmp(p->prefix, key, p->prefix_len)) {
 			*len = p->prefix_len;
-			*index = p - xattr_types;
+			*index = tnode->index;
 			return true;
 		}
 	}
-	return false;
+
+	return match_short_prefix(key, index, len);
 }
 
 static struct xattr_item *parse_one_xattr(const char *path, const char *key,
 					  unsigned int keylen)
 {
 	ssize_t ret;
-	u8 prefix;
-	u16 prefixlen;
+	u8 prefix, o_prefix;
+	u16 prefixlen, o_prefixlen;
 	unsigned int len[2];
+	unsigned int bit = 0;
 	char *kvbuf;
 
 	erofs_dbg("parse xattr [%s] of %s", path, key);
@@ -176,6 +198,13 @@ static struct xattr_item *parse_one_xattr(const char *path, const char *key,
 
 	DBG_BUGON(keylen < prefixlen);
 
+	if (cfg.c_xattr_filter) {
+		if (!match_short_prefix(key, &o_prefix, &o_prefixlen))
+			return ERR_PTR(-ENODATA);
+		bit = erofs_xattr_calc_name_filter_bit(o_prefix,
+				key + o_prefixlen, keylen - o_prefixlen);
+	}
+
 	/* determine length of the value */
 #ifdef HAVE_LGETXATTR
 	ret = lgetxattr(path, key, NULL, 0);
@@ -216,7 +245,7 @@ static struct xattr_item *parse_one_xattr(const char *path, const char *key,
 			len[1] = ret;
 		}
 	}
-	return get_xattritem(prefix, kvbuf, len);
+	return get_xattritem(prefix, kvbuf, len, bit);
 }
 
 static struct xattr_item *erofs_get_selabel_xattr(const char *srcpath,
@@ -226,7 +255,7 @@ static struct xattr_item *erofs_get_selabel_xattr(const char *srcpath,
 	if (cfg.sehnd) {
 		char *secontext;
 		int ret;
-		unsigned int len[2];
+		unsigned int bit, len[2];
 		char *kvbuf, *fspath;
 
 		if (cfg.mount_point)
@@ -260,7 +289,8 @@ static struct xattr_item *erofs_get_selabel_xattr(const char *srcpath,
 		}
 		sprintf(kvbuf, "selinux%s", secontext);
 		freecon(secontext);
-		return get_xattritem(EROFS_XATTR_INDEX_SECURITY, kvbuf, len);
+		bit = erofs_xattr_calc_name_filter_bit(EROFS_XATTR_INDEX_SECURITY, "selinux", len[0]);
+		return get_xattritem(EROFS_XATTR_INDEX_SECURITY, kvbuf, len, bit);
 	}
 #endif
 	return NULL;
@@ -408,7 +438,7 @@ static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
 {
 	const u64 capabilities = inode->capabilities;
 	char *kvbuf;
-	unsigned int len[2];
+	unsigned int bit, len[2];
 	struct vfs_cap_data caps;
 	struct xattr_item *item;
 
@@ -430,7 +460,8 @@ static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
 	caps.data[1].inheritable = 0;
 	memcpy(kvbuf + len[0], &caps, len[1]);
 
-	item = get_xattritem(EROFS_XATTR_INDEX_SECURITY, kvbuf, len);
+	bit = erofs_xattr_calc_name_filter_bit(EROFS_XATTR_INDEX_SECURITY, "capability", len[0]);
+	item = get_xattritem(EROFS_XATTR_INDEX_SECURITY, kvbuf, len, bit);
 	if (IS_ERR(item))
 		return PTR_ERR(item);
 	if (!item)
@@ -754,6 +785,17 @@ char *erofs_export_xattr_ibody(struct list_head *ixattrs, unsigned int size)
 	header = (struct erofs_xattr_ibody_header *)buf;
 	header->h_shared_count = 0;
 
+	if (cfg.c_xattr_filter) {
+		u32 name_filter = 0;
+
+		list_for_each_entry_safe(node, n, ixattrs, list) {
+			struct xattr_item *const item = node->item;
+			name_filter |= 1UL << item->name_filter_bit;
+		}
+		name_filter = EROFS_XATTR_FILTER_DEFAULT & ~name_filter;
+		header->h_name_filter = cpu_to_le32(name_filter);
+	}
+
 	p = sizeof(struct erofs_xattr_ibody_header);
 	list_for_each_entry_safe(node, n, ixattrs, list) {
 		struct xattr_item *const item = node->item;
diff --git a/mkfs/main.c b/mkfs/main.c
index ac208e5..84d4414 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -58,6 +58,7 @@ static struct option long_options[] = {
 	{"gid-offset", required_argument, NULL, 17},
 	{"mount-point", required_argument, NULL, 512},
 	{"xattr-prefix", required_argument, NULL, 19},
+	{"xattr-filter", no_argument, NULL, 20},
 #ifdef WITH_ANDROID
 	{"product-out", required_argument, NULL, 513},
 	{"fs-config-file", required_argument, NULL, 514},
@@ -118,6 +119,7 @@ static void usage(void)
 	      " --random-algorithms   randomize per-file algorithms (debugging only)\n"
 #endif
 	      " --xattr-prefix=X      X=extra xattr name prefix\n"
+	      " --xattr-filter	      enable xattr name bloom filter\n"
 	      " --mount-point=X       X=prefix of target fs path (default: /)\n"
 #ifdef WITH_ANDROID
 	      "\nwith following android-specific options:\n"
@@ -482,6 +484,10 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 			}
 			cfg.c_extra_ea_name_prefixes = true;
 			break;
+		case 20:
+			cfg.c_xattr_filter = true;
+			erofs_sb_set_xattr_filter();
+			break;
 		case 1:
 			usage();
 			exit(0);
-- 
2.19.1.6.gb485710b


      parent reply	other threads:[~2023-07-05  7:10 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-05  7:10 [PATCH v2 0/3] erofs-utils: introduce xattr name bloom filter Jingbo Xu
2023-07-05  7:10 ` [PATCH v2 1/3] erofs-utils: add xxh32 library Jingbo Xu
2023-07-05  7:29   ` Gao Xiang
2023-07-12 11:58     ` Jingbo Xu
2023-07-05  7:10 ` [PATCH v2 2/3] erofs-utils: update on-disk format for xattr name filter Jingbo Xu
2023-07-05  7:10 ` Jingbo Xu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230705071017.104130-4-jefflexu@linux.alibaba.com \
    --to=jefflexu@linux.alibaba.com \
    --cc=alexl@redhat.com \
    --cc=chao@kernel.org \
    --cc=hsiangkao@linux.alibaba.com \
    --cc=huyue2@coolpad.com \
    --cc=linux-erofs@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.