Skip to content

Commit

Permalink
erofs: add helpers to load long xattr name prefixes
Browse files Browse the repository at this point in the history
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: Jingbo Xu <[email protected]>
Reviewed-by: Gao Xiang <[email protected]>
Acked-by: Chao Yu <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Gao Xiang <[email protected]>
  • Loading branch information
lostjeffle authored and hsiangkao committed Apr 16, 2023
1 parent b3bfcb9 commit 9e38291
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 3 deletions.
10 changes: 10 additions & 0 deletions fs/erofs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions fs/erofs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,9 @@ 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,
erofs_off_t *offset, int *lengthp)
void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
erofs_off_t *offset, int *lengthp)
{
u8 *buffer, *ptr;
int len, i, cnt;
Expand Down Expand Up @@ -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)
{
Expand Down
56 changes: 56 additions & 0 deletions fs/erofs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
4 changes: 4 additions & 0 deletions fs/erofs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 9e38291

Please sign in to comment.