Skip to content

Commit 4b077b5

Browse files
lostjefflehsiangkao
authored andcommitted
erofs: unify inline/shared xattr iterators for listxattr/getxattr
Make inline_{list,get}xattr() as well as inline_xattr_iter_begin() unified as erofs_xattr_iter_inline(), and shared_{list,get}xattr() unified as erofs_xattr_iter_shared(). After these changes, both erofs_xattr_iter_{inline,shared}() return 0 on success, and negative error on failure. One thing worth noting is that, the logic of returning it->buffer_ofs when there's no shared xattrs in shared_listxattr() is moved to erofs_listxattr() to make the unification possible. The only difference is that, semantically the old behavior will return ENOATTR rather than it->buffer_ofs if ENOATTR encountered when listxattr is parsing upon a specific shared xattr, while now the new behavior will return it->buffer_ofs in this case. This is not an issue, as listxattr upon a specific xattr won't return ENOATTR. Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com> Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com> Link: https://lore.kernel.org/r/20230613074114.120115-5-jefflexu@linux.alibaba.com Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
1 parent 5a8ffb1 commit 4b077b5

File tree

1 file changed

+73
-117
lines changed

1 file changed

+73
-117
lines changed

fs/erofs/xattr.c

Lines changed: 73 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -139,27 +139,6 @@ struct xattr_iter_handlers {
139139
unsigned int len);
140140
};
141141

142-
static int inline_xattr_iter_begin(struct erofs_xattr_iter *it,
143-
struct inode *inode)
144-
{
145-
struct erofs_inode *const vi = EROFS_I(inode);
146-
unsigned int xattr_header_sz;
147-
148-
xattr_header_sz = sizeof(struct erofs_xattr_ibody_header) +
149-
sizeof(u32) * vi->xattr_shared_count;
150-
if (xattr_header_sz >= vi->xattr_isize) {
151-
DBG_BUGON(xattr_header_sz > vi->xattr_isize);
152-
return -ENOATTR;
153-
}
154-
155-
it->pos = erofs_iloc(inode) + vi->inode_isize + xattr_header_sz;
156-
it->kaddr = erofs_bread(&it->buf, erofs_blknr(it->sb, it->pos),
157-
EROFS_KMAP);
158-
if (IS_ERR(it->kaddr))
159-
return PTR_ERR(it->kaddr);
160-
return vi->xattr_isize - xattr_header_sz;
161-
}
162-
163142
/*
164143
* Regardless of success or failure, `xattr_foreach' will end up with
165144
* `pos' pointing to the next xattr item rather than an arbitrary position.
@@ -333,47 +312,6 @@ static const struct xattr_iter_handlers find_xattr_handlers = {
333312
.value = xattr_copyvalue
334313
};
335314

336-
static int inline_getxattr(struct inode *inode, struct erofs_xattr_iter *it)
337-
{
338-
int ret;
339-
unsigned int remaining;
340-
341-
ret = inline_xattr_iter_begin(it, inode);
342-
if (ret < 0)
343-
return ret;
344-
345-
remaining = ret;
346-
while (remaining) {
347-
ret = xattr_foreach(it, &find_xattr_handlers, &remaining);
348-
if (ret != -ENOATTR)
349-
break;
350-
}
351-
return ret ? ret : it->buffer_ofs;
352-
}
353-
354-
static int shared_getxattr(struct inode *inode, struct erofs_xattr_iter *it)
355-
{
356-
struct erofs_inode *const vi = EROFS_I(inode);
357-
struct super_block *const sb = it->sb;
358-
struct erofs_sb_info *sbi = EROFS_SB(sb);
359-
unsigned int i;
360-
int ret = -ENOATTR;
361-
362-
for (i = 0; i < vi->xattr_shared_count; ++i) {
363-
it->pos = erofs_pos(sb, sbi->xattr_blkaddr) +
364-
vi->xattr_shared_xattrs[i] * sizeof(__le32);
365-
it->kaddr = erofs_bread(&it->buf, erofs_blknr(sb, it->pos),
366-
EROFS_KMAP);
367-
if (IS_ERR(it->kaddr))
368-
return PTR_ERR(it->kaddr);
369-
370-
ret = xattr_foreach(it, &find_xattr_handlers, NULL);
371-
if (ret != -ENOATTR)
372-
break;
373-
}
374-
return ret ? ret : it->buffer_ofs;
375-
}
376-
377315
static bool erofs_xattr_user_list(struct dentry *dentry)
378316
{
379317
return test_opt(&EROFS_SB(dentry->d_sb)->opt, XATTR_USER);
@@ -384,39 +322,6 @@ static bool erofs_xattr_trusted_list(struct dentry *dentry)
384322
return capable(CAP_SYS_ADMIN);
385323
}
386324

387-
int erofs_getxattr(struct inode *inode, int index,
388-
const char *name,
389-
void *buffer, size_t buffer_size)
390-
{
391-
int ret;
392-
struct erofs_xattr_iter it;
393-
394-
if (!name)
395-
return -EINVAL;
396-
397-
ret = erofs_init_inode_xattrs(inode);
398-
if (ret)
399-
return ret;
400-
401-
it.index = index;
402-
it.name = (struct qstr)QSTR_INIT(name, strlen(name));
403-
if (it.name.len > EROFS_NAME_LEN)
404-
return -ERANGE;
405-
406-
it.sb = inode->i_sb;
407-
it.buf = __EROFS_BUF_INITIALIZER;
408-
erofs_init_metabuf(&it.buf, it.sb);
409-
it.buffer = buffer;
410-
it.buffer_size = buffer_size;
411-
it.buffer_ofs = 0;
412-
413-
ret = inline_getxattr(inode, &it);
414-
if (ret == -ENOATTR)
415-
ret = shared_getxattr(inode, &it);
416-
erofs_put_metabuf(&it.buf);
417-
return ret;
418-
}
419-
420325
static int erofs_xattr_generic_get(const struct xattr_handler *handler,
421326
struct dentry *unused, struct inode *inode,
422327
const char *name, void *buffer, size_t size)
@@ -521,32 +426,49 @@ static const struct xattr_iter_handlers list_xattr_handlers = {
521426
.value = NULL
522427
};
523428

524-
static int inline_listxattr(struct erofs_xattr_iter *it)
429+
static int erofs_xattr_iter_inline(struct erofs_xattr_iter *it,
430+
struct inode *inode, bool getxattr)
525431
{
432+
struct erofs_inode *const vi = EROFS_I(inode);
433+
const struct xattr_iter_handlers *op;
434+
unsigned int xattr_header_sz, remaining;
526435
int ret;
527-
unsigned int remaining;
528436

529-
ret = inline_xattr_iter_begin(it, d_inode(it->dentry));
530-
if (ret < 0)
531-
return ret;
437+
xattr_header_sz = sizeof(struct erofs_xattr_ibody_header) +
438+
sizeof(u32) * vi->xattr_shared_count;
439+
if (xattr_header_sz >= vi->xattr_isize) {
440+
DBG_BUGON(xattr_header_sz > vi->xattr_isize);
441+
return -ENOATTR;
442+
}
443+
444+
it->pos = erofs_iloc(inode) + vi->inode_isize + xattr_header_sz;
445+
it->kaddr = erofs_bread(&it->buf, erofs_blknr(it->sb, it->pos),
446+
EROFS_KMAP);
447+
if (IS_ERR(it->kaddr))
448+
return PTR_ERR(it->kaddr);
449+
450+
remaining = vi->xattr_isize - xattr_header_sz;
451+
op = getxattr ? &find_xattr_handlers : &list_xattr_handlers;
532452

533-
remaining = ret;
534453
while (remaining) {
535-
ret = xattr_foreach(it, &list_xattr_handlers, &remaining);
536-
if (ret)
454+
ret = xattr_foreach(it, op, &remaining);
455+
if ((getxattr && ret != -ENOATTR) || (!getxattr && ret))
537456
break;
538457
}
539-
return ret ? ret : it->buffer_ofs;
458+
return ret;
540459
}
541460

542-
static int shared_listxattr(struct erofs_xattr_iter *it)
461+
static int erofs_xattr_iter_shared(struct erofs_xattr_iter *it,
462+
struct inode *inode, bool getxattr)
543463
{
544-
struct inode *const inode = d_inode(it->dentry);
545464
struct erofs_inode *const vi = EROFS_I(inode);
546465
struct super_block *const sb = it->sb;
547466
struct erofs_sb_info *sbi = EROFS_SB(sb);
548467
unsigned int i;
549-
int ret = 0;
468+
const struct xattr_iter_handlers *op;
469+
int ret = -ENOATTR;
470+
471+
op = getxattr ? &find_xattr_handlers : &list_xattr_handlers;
550472

551473
for (i = 0; i < vi->xattr_shared_count; ++i) {
552474
it->pos = erofs_pos(sb, sbi->xattr_blkaddr) +
@@ -556,20 +478,52 @@ static int shared_listxattr(struct erofs_xattr_iter *it)
556478
if (IS_ERR(it->kaddr))
557479
return PTR_ERR(it->kaddr);
558480

559-
ret = xattr_foreach(it, &list_xattr_handlers, NULL);
560-
if (ret)
481+
ret = xattr_foreach(it, op, NULL);
482+
if ((getxattr && ret != -ENOATTR) || (!getxattr && ret))
561483
break;
562484
}
563-
return ret ? ret : it->buffer_ofs;
485+
return ret;
564486
}
565487

566-
ssize_t erofs_listxattr(struct dentry *dentry,
567-
char *buffer, size_t buffer_size)
488+
int erofs_getxattr(struct inode *inode, int index, const char *name,
489+
void *buffer, size_t buffer_size)
568490
{
569491
int ret;
570492
struct erofs_xattr_iter it;
571493

572-
ret = erofs_init_inode_xattrs(d_inode(dentry));
494+
if (!name)
495+
return -EINVAL;
496+
497+
ret = erofs_init_inode_xattrs(inode);
498+
if (ret)
499+
return ret;
500+
501+
it.index = index;
502+
it.name = (struct qstr)QSTR_INIT(name, strlen(name));
503+
if (it.name.len > EROFS_NAME_LEN)
504+
return -ERANGE;
505+
506+
it.sb = inode->i_sb;
507+
it.buf = __EROFS_BUF_INITIALIZER;
508+
erofs_init_metabuf(&it.buf, it.sb);
509+
it.buffer = buffer;
510+
it.buffer_size = buffer_size;
511+
it.buffer_ofs = 0;
512+
513+
ret = erofs_xattr_iter_inline(&it, inode, true);
514+
if (ret == -ENOATTR)
515+
ret = erofs_xattr_iter_shared(&it, inode, true);
516+
erofs_put_metabuf(&it.buf);
517+
return ret ? ret : it.buffer_ofs;
518+
}
519+
520+
ssize_t erofs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
521+
{
522+
int ret;
523+
struct erofs_xattr_iter it;
524+
struct inode *inode = d_inode(dentry);
525+
526+
ret = erofs_init_inode_xattrs(inode);
573527
if (ret == -ENOATTR)
574528
return 0;
575529
if (ret)
@@ -583,11 +537,13 @@ ssize_t erofs_listxattr(struct dentry *dentry,
583537
it.buffer_size = buffer_size;
584538
it.buffer_ofs = 0;
585539

586-
ret = inline_listxattr(&it);
587-
if (ret >= 0 || ret == -ENOATTR)
588-
ret = shared_listxattr(&it);
540+
ret = erofs_xattr_iter_inline(&it, inode, false);
541+
if (!ret || ret == -ENOATTR)
542+
ret = erofs_xattr_iter_shared(&it, inode, false);
543+
if (ret == -ENOATTR)
544+
ret = 0;
589545
erofs_put_metabuf(&it.buf);
590-
return ret;
546+
return ret ? ret : it.buffer_ofs;
591547
}
592548

593549
void erofs_xattr_prefixes_cleanup(struct super_block *sb)

0 commit comments

Comments
 (0)