[PATCH v6 3/3] erofs-utils: mkfs: enable xattr name filter

Jingbo Xu jefflexu at linux.alibaba.com
Wed Aug 30 00:20:28 AEST 2023



On 8/29/23 8:53 PM, Gao Xiang wrote:
> 
> 
> On 2023/8/29 20:41, Jingbo Xu wrote:
>> Introduce "-Exattr-name-filter" option to enable the xattr name bloom
>> filter feature.
>>
>> Signed-off-by: Jingbo Xu <jefflexu at linux.alibaba.com>
>> ---
>>   include/erofs/config.h   |  1 +
>>   include/erofs/internal.h |  1 +
>>   lib/xattr.c              | 63 ++++++++++++++++++++++++++++++++++++++++
>>   mkfs/main.c              |  7 +++++
>>   4 files changed, 72 insertions(+)
>>
>> diff --git a/include/erofs/config.h b/include/erofs/config.h
>> index 8f52d2c..c51f0cd 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_name_filter;
>>     #ifdef HAVE_LIBSELINUX
>>       struct selabel_handle *sehnd;
>> diff --git a/include/erofs/internal.h b/include/erofs/internal.h
>> index 3e73eef..382024a 100644
>> --- a/include/erofs/internal.h
>> +++ b/include/erofs/internal.h
>> @@ -139,6 +139,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 46a301a..325241d 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
>> @@ -783,6 +784,63 @@ out:
>>       return ret;
>>   }
>>   +
>> +static int erofs_xattr_filter_hashbit(struct xattr_item *item)
>> +{
>> +    u8 prefix = item->prefix;
>> +    const char *key = item->kvbuf;
>> +    unsigned int len = item->len[0];
>> +    char *name = NULL;
>> +    uint32_t hashbit;
>> +
>> +    if (prefix & EROFS_XATTR_LONG_PREFIX) {
>> +        struct ea_type_node *tnode;
>> +        u16 prefix_len;
>> +        int ret;
>> +
>> +        list_for_each_entry(tnode, &ea_name_prefixes, list) {
>> +            if (tnode->index == item->prefix) {
>> +                ret = asprintf(&name, "%s%.*s",
>> +                           tnode->type.prefix, len, key);
>> +                if (ret < 0)
>> +                    return -ENOMEM;
>> +                break;
>> +            }
>> +        }
>> +        if (!name)
>> +            return -ENOENT;
>> +
>> +        if (!match_base_prefix(name, &prefix, &prefix_len)) {
>> +            free(name);
>> +            return -ENOENT;
>> +        }
>> +        key = name + prefix_len;
>> +        len = strlen(key);
>> +    }
>> +
>> +    hashbit = xxh32(key, len, EROFS_XATTR_FILTER_SEED + prefix) &
>> +          (EROFS_XATTR_FILTER_BITS - 1);
>> +    if (name)
>> +        free(name);
>> +    return hashbit;
>> +}
>> +
>> +static u32 erofs_xattr_filter_map(struct list_head *ixattrs)
>> +{
>> +    struct inode_xattr_node *node, *n;
>> +    u32 name_filter;
>> +    int hashbit;
>> +
>> +    name_filter = 0;
>> +    list_for_each_entry_safe(node, n, ixattrs, list) {
>> +        hashbit = erofs_xattr_filter_hashbit(node->item);
>> +        if (hashbit < 0)
> 
> I'd suggest to clear feature bit instead:
> 
> erofs_sb_clear_xattr_filter(&sbi);

Good idea.


> 
>> +            return 0;
>> +        name_filter |= (1UL << hashbit);
>> +    }
>> +    return EROFS_XATTR_FILTER_DEFAULT & ~name_filter;
>> +}
>> +
>>   char *erofs_export_xattr_ibody(struct list_head *ixattrs, unsigned
>> int size)
>>   {
>>       struct inode_xattr_node *node, *n;
>> @@ -797,6 +855,11 @@ 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_name_filter) {
>> +        u32 name_filter = erofs_xattr_filter_map(ixattrs);
> 
> Leave a blank line here.
> 
>> +        header->h_name_filter = cpu_to_le32(name_filter);
> 
> Or
>         header->h_name_filter =
>             cpu_to_le32(erofs_xattr_filter_map(ixattrs));
> 

Okay.  I would prefer the latter.

-- 
Thanks,
Jingbo


More information about the Linux-erofs mailing list