Commit 9e382914 authored by Jingbo Xu's avatar Jingbo Xu Committed by Gao Xiang
Browse files

erofs: add helpers to load long xattr name prefixes



Long xattr name prefixes will be scanned upon mounting and the in-memory
long xattr name prefix array will be initialized accordingly.

Signed-off-by: default avatarJingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
Acked-by: default avatarChao Yu <chao@kernel.org>
Link: https://lore.kernel.org/r/20230407141710.113882-6-jefflexu@linux.alibaba.com


Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
parent b3bfcb9d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -117,6 +117,11 @@ struct erofs_fscache {
	char *name;
};

struct erofs_xattr_prefix_item {
	struct erofs_xattr_long_prefix *prefix;
	u8 infix_len;
};

struct erofs_sb_info {
	struct erofs_mount_opts opt;	/* options */
#ifdef CONFIG_EROFS_FS_ZIP
@@ -145,6 +150,9 @@ struct erofs_sb_info {
	u32 meta_blkaddr;
#ifdef CONFIG_EROFS_FS_XATTR
	u32 xattr_blkaddr;
	u32 xattr_prefix_start;
	u8 xattr_prefix_count;
	struct erofs_xattr_prefix_item *xattr_prefixes;
#endif
	u16 device_id_mask;	/* valid bits of device id to be used */

@@ -440,6 +448,8 @@ extern const struct iomap_ops z_erofs_iomap_report_ops;
#define EROFS_REG_COOKIE_SHARE		0x0001
#define EROFS_REG_COOKIE_NEED_NOEXIST	0x0002

void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
			  erofs_off_t *offset, int *lengthp);
void erofs_unmap_metabuf(struct erofs_buf *buf);
void erofs_put_metabuf(struct erofs_buf *buf);
void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
+3 −3
Original line number Diff line number Diff line
@@ -126,9 +126,8 @@ static bool check_layout_compatibility(struct super_block *sb,
	return true;
}

#ifdef CONFIG_EROFS_FS_ZIP
/* read variable-sized metadata, offset will be aligned by 4-byte */
static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
			  erofs_off_t *offset, int *lengthp)
{
	u8 *buffer, *ptr;
@@ -162,6 +161,7 @@ static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
	return buffer;
}

#ifdef CONFIG_EROFS_FS_ZIP
static int erofs_load_compr_cfgs(struct super_block *sb,
				 struct erofs_super_block *dsb)
{
+56 −0
Original line number Diff line number Diff line
@@ -610,6 +610,62 @@ ssize_t erofs_listxattr(struct dentry *dentry,
	return ret;
}

void erofs_xattr_prefixes_cleanup(struct super_block *sb)
{
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	int i;

	if (sbi->xattr_prefixes) {
		for (i = 0; i < sbi->xattr_prefix_count; i++)
			kfree(sbi->xattr_prefixes[i].prefix);
		kfree(sbi->xattr_prefixes);
		sbi->xattr_prefixes = NULL;
	}
}

int erofs_xattr_prefixes_init(struct super_block *sb)
{
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
	erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2;
	struct erofs_xattr_prefix_item *pfs;
	int ret = 0, i, len;

	if (!sbi->xattr_prefix_count)
		return 0;

	pfs = kzalloc(sbi->xattr_prefix_count * sizeof(*pfs), GFP_KERNEL);
	if (!pfs)
		return -ENOMEM;

	if (erofs_sb_has_fragments(sbi))
		buf.inode = sbi->packed_inode;
	else
		erofs_init_metabuf(&buf, sb);

	for (i = 0; i < sbi->xattr_prefix_count; i++) {
		void *ptr = erofs_read_metadata(sb, &buf, &pos, &len);

		if (IS_ERR(ptr)) {
			ret = PTR_ERR(ptr);
			break;
		} else if (len < sizeof(*pfs->prefix) ||
			   len > EROFS_NAME_LEN + sizeof(*pfs->prefix)) {
			kfree(ptr);
			ret = -EFSCORRUPTED;
			break;
		}
		pfs[i].prefix = ptr;
		pfs[i].infix_len = len - sizeof(struct erofs_xattr_long_prefix);
	}

	erofs_put_metabuf(&buf);
	sbi->xattr_prefixes = pfs;
	if (ret)
		erofs_xattr_prefixes_cleanup(sb);
	return ret;
}

#ifdef CONFIG_EROFS_FS_POSIX_ACL
struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu)
{
+4 −0
Original line number Diff line number Diff line
@@ -40,9 +40,13 @@ static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)

extern const struct xattr_handler *erofs_xattr_handlers[];

int erofs_xattr_prefixes_init(struct super_block *sb);
void erofs_xattr_prefixes_cleanup(struct super_block *sb);
int erofs_getxattr(struct inode *, int, const char *, void *, size_t);
ssize_t erofs_listxattr(struct dentry *, char *, size_t);
#else
static inline int erofs_xattr_prefixes_init(struct super_block *sb) { return 0; }
static inline void erofs_xattr_prefixes_cleanup(struct super_block *sb) {}
static inline int erofs_getxattr(struct inode *inode, int index,
				 const char *name, void *buffer,
				 size_t buffer_size)