Previously, xattr long prefixes were always kept in packed_inode by mkfs.erofs [1], even when the fragments feature could be avoided.
This is messy, so let's fix the placement as follows: COMPAT_PLAIN_XATTR_PFX is not set: - If INCOMPAT_METABOX is set, place long prefixes into metabox_inode (since it should be treated as metadata); - If INCOMPAT_FRAGMENTS is set, place long prefixes into packed_inode (for compatibility only); Otherwise, always place long prefixes directly on disk. [1] ff160922e94a ("erofs-utils: introduce on-disk format for long xattr name prefixes") Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- include/erofs/internal.h | 1 + include/erofs/xattr.h | 2 +- include/erofs_fs.h | 1 + lib/xattr.c | 71 +++++++++++++++++++++++++++++++--------- mkfs/main.c | 7 +++- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/include/erofs/internal.h b/include/erofs/internal.h index 3e1000d..cea6420 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -186,6 +186,7 @@ EROFS_FEATURE_FUNCS(48bit, incompat, INCOMPAT_48BIT) EROFS_FEATURE_FUNCS(metabox, incompat, INCOMPAT_METABOX) EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER) +EROFS_FEATURE_FUNCS(plain_xattr_pfx, compat, COMPAT_PLAIN_XATTR_PFX) #define EROFS_I_EA_INITED_BIT 0 #define EROFS_I_Z_INITED_BIT 1 diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h index 81604b6..769791a 100644 --- a/include/erofs/xattr.h +++ b/include/erofs/xattr.h @@ -50,7 +50,7 @@ int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *p int erofs_xattr_insert_name_prefix(const char *prefix); void erofs_xattr_cleanup_name_prefixes(void); -int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi); +int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi, bool plain); void erofs_xattr_prefixes_cleanup(struct erofs_sb_info *sbi); int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi); diff --git a/include/erofs_fs.h b/include/erofs_fs.h index df1af98..887f37f 100644 --- a/include/erofs_fs.h +++ b/include/erofs_fs.h @@ -16,6 +16,7 @@ #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 #define EROFS_FEATURE_COMPAT_MTIME 0x00000002 #define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004 +#define EROFS_FEATURE_COMPAT_PLAIN_XATTR_PFX 0x00000010 /* * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should diff --git a/lib/xattr.c b/lib/xattr.c index 114e2bb..977031d 100644 --- a/lib/xattr.c +++ b/lib/xattr.c @@ -17,6 +17,7 @@ #include "erofs/xattr.h" #include "erofs/fragments.h" #include "liberofs_cache.h" +#include "liberofs_metabox.h" #include "liberofs_xxhash.h" #include "liberofs_private.h" @@ -804,23 +805,48 @@ static int comp_shared_xattr_item(const void *a, const void *b) return la > lb; } -int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi) +int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi, bool plain) { - int fd = erofs_packedfile(sbi); + bool may_fragments = cfg.c_fragments || erofs_sb_has_fragments(sbi); + struct erofs_vfile *vf = &sbi->bdev; + struct erofs_bufmgr *bmgr = sbi->bmgr; + struct erofs_buffer_head *bh = NULL; + struct erofs_vfile _vf; struct ea_type_node *tnode; - s64 offset; + s64 start, offset = 0; int err; if (!ea_prefix_count) return 0; - offset = lseek(fd, 0, SEEK_CUR); - if (offset < 0) - return -errno; - offset = round_up(offset, 4); + + if (plain) { + erofs_sb_set_plain_xattr_pfx(sbi); + if (may_fragments) + erofs_sb_set_metabox(sbi); + } else if (erofs_sb_has_metabox(sbi)) { + bmgr = erofs_metabox_bmgr(sbi); + vf = bmgr->vf; + } else if (may_fragments) { + erofs_sb_set_fragments(sbi); + _vf = (struct erofs_vfile){ .fd = erofs_packedfile(sbi) }; + vf = &_vf; + offset = lseek(vf->fd, 0, SEEK_CUR); + if (offset < 0) + return -errno; + bmgr = NULL; + } + + if (bmgr) { + bh = erofs_balloc(bmgr, XATTR, 0, 0); + if (IS_ERR(bh)) + return PTR_ERR(bh); + (void)erofs_mapbh(bmgr, bh->block); + offset = erofs_btell(bh, false); + } + if ((offset >> 2) > UINT32_MAX) return -EOVERFLOW; - if (lseek(fd, offset, SEEK_SET) < 0) - return -errno; + start = offset; sbi->xattr_prefix_start = (u32)offset >> 2; sbi->xattr_prefix_count = ea_prefix_count; @@ -842,17 +868,27 @@ int erofs_xattr_flush_name_prefixes(struct erofs_sb_info *sbi) infix_len); len = sizeof(struct erofs_xattr_long_prefix) + infix_len; u.s.size = cpu_to_le16(len); - err = __erofs_io_write(fd, &u.s, sizeof(__le16) + len); + err = erofs_io_pwrite(vf, &u.s, offset, sizeof(__le16) + len); if (err != sizeof(__le16) + len) { if (err < 0) - return -errno; + return err; return -EIO; } offset = round_up(offset + sizeof(__le16) + len, 4); - if (lseek(fd, offset, SEEK_SET) < 0) + } + + if (bh) { + bh->op = &erofs_drop_directly_bhops; + err = erofs_bh_balloon(bh, offset - start); + if (err < 0) + return err; + bh->op = &erofs_drop_directly_bhops; + erofs_bdrop(bh, false); + } else { + DBG_BUGON(bmgr); + if (lseek(vf->fd, offset, SEEK_CUR) < 0) return -errno; } - erofs_sb_set_fragments(sbi); erofs_sb_set_xattr_prefixes(sbi); return 0; } @@ -1641,6 +1677,7 @@ void erofs_xattr_prefixes_cleanup(struct erofs_sb_info *sbi) int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi) { + bool plain = erofs_sb_has_plain_xattr_pfx(sbi); erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2; struct erofs_xattr_prefix_item *pfs; erofs_nid_t nid = 0; @@ -1650,8 +1687,12 @@ int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi) if (!sbi->xattr_prefix_count) return 0; - if (sbi->packed_nid) - nid = sbi->packed_nid; + if (!plain) { + if (sbi->metabox_nid) + nid = sbi->metabox_nid; + else if (sbi->packed_nid) + nid = sbi->packed_nid; + } pfs = calloc(sbi->xattr_prefix_count, sizeof(*pfs)); if (!pfs) diff --git a/mkfs/main.c b/mkfs/main.c index c328e0a..a8208d4 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -415,6 +415,7 @@ static struct { }; static bool mkfs_no_datainline; +static bool mkfs_plain_xattr_pfx; static int parse_extended_opts(const char *opts) { @@ -491,6 +492,10 @@ static int parse_extended_opts(const char *opts) if (vallen) return -EINVAL; cfg.c_xattr_name_filter = !clear; + } else if (MATCH_EXTENTED_OPT("plain-xattr-prefixes", token, keylen)) { + if (vallen) + return -EINVAL; + mkfs_plain_xattr_pfx = true; } else { int i, err; @@ -1788,7 +1793,7 @@ int main(int argc, char **argv) } if (cfg.c_extra_ea_name_prefixes) - erofs_xattr_flush_name_prefixes(&g_sbi); + erofs_xattr_flush_name_prefixes(&g_sbi, mkfs_plain_xattr_pfx); root = erofs_new_inode(&g_sbi); if (IS_ERR(root)) { -- 2.43.5