[PATCH 08/11] erofs-utils: lib: use meta buffers for xattr operations

Gao Xiang hsiangkao at linux.alibaba.com
Fri Jul 18 16:54:16 AEST 2025


Source kernel commit: bb88e8da00253bea0e7f0f4cdfd7910572d7799f

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/xattr.c | 92 +++++++++++++++++++++++++----------------------------
 1 file changed, 44 insertions(+), 48 deletions(-)

diff --git a/lib/xattr.c b/lib/xattr.c
index 6711dcc1..a2ef8d20 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -1033,13 +1033,12 @@ char *erofs_export_xattr_ibody(struct erofs_inode *inode)
 }
 
 struct xattr_iter {
-	char page[EROFS_MAX_BLOCK_SIZE];
-
+	struct erofs_sb_info *sbi;
+	struct erofs_buf buf;
 	void *kaddr;
 
 	erofs_blk_t blkaddr;
 	unsigned int ofs;
-	struct erofs_sb_info *sbi;
 };
 
 static int init_inode_xattrs(struct erofs_inode *vi)
@@ -1075,20 +1074,23 @@ static int init_inode_xattrs(struct erofs_inode *vi)
 		return -ENOATTR;
 	}
 
+	it.buf = __EROFS_BUF_INITIALIZER;
 	it.blkaddr = erofs_blknr(sbi, erofs_iloc(vi) + vi->inode_isize);
 	it.ofs = erofs_blkoff(sbi, erofs_iloc(vi) + vi->inode_isize);
 
-	ret = erofs_blk_read(sbi, 0, it.page, it.blkaddr, 1);
-	if (ret < 0)
-		return -EIO;
+	/* read in shared xattr array (non-atomic, see kmalloc below) */
+	it.kaddr = erofs_read_metabuf(&it.buf, sbi, erofs_pos(sbi, it.blkaddr));
+	if (IS_ERR(it.kaddr))
+		return PTR_ERR(it.kaddr);
 
-	it.kaddr = it.page;
 	ih = (struct erofs_xattr_ibody_header *)(it.kaddr + it.ofs);
 
 	vi->xattr_shared_count = ih->h_shared_count;
 	vi->xattr_shared_xattrs = malloc(vi->xattr_shared_count * sizeof(uint));
-	if (!vi->xattr_shared_xattrs)
+	if (!vi->xattr_shared_xattrs) {
+		erofs_put_metabuf(&it.buf);
 		return -ENOMEM;
+	}
 
 	/* let's skip ibody header */
 	it.ofs += sizeof(struct erofs_xattr_ibody_header);
@@ -1098,20 +1100,20 @@ static int init_inode_xattrs(struct erofs_inode *vi)
 			/* cannot be unaligned */
 			DBG_BUGON(it.ofs != erofs_blksiz(sbi));
 
-			ret = erofs_blk_read(sbi, 0, it.page, ++it.blkaddr, 1);
-			if (ret < 0) {
+			it.kaddr = erofs_read_metabuf(&it.buf, sbi,
+					erofs_pos(sbi, ++it.blkaddr));
+			if (IS_ERR(it.kaddr)) {
 				free(vi->xattr_shared_xattrs);
 				vi->xattr_shared_xattrs = NULL;
-				return -EIO;
+				return PTR_ERR(it.kaddr);
 			}
-
-			it.kaddr = it.page;
 			it.ofs = 0;
 		}
 		vi->xattr_shared_xattrs[i] =
 			le32_to_cpu(*(__le32 *)(it.kaddr + it.ofs));
 		it.ofs += sizeof(__le32);
 	}
+	erofs_put_metabuf(&it.buf);
 	erofs_atomic_set_bit(EROFS_I_EA_INITED_BIT, &vi->flags);
 	return ret;
 }
@@ -1135,28 +1137,24 @@ struct xattr_iter_handlers {
 static inline int xattr_iter_fixup(struct xattr_iter *it)
 {
 	struct erofs_sb_info *sbi = it->sbi;
-	int ret;
 
 	if (it->ofs < erofs_blksiz(sbi))
 		return 0;
 
 	it->blkaddr += erofs_blknr(sbi, it->ofs);
-
-	ret = erofs_blk_read(sbi, 0, it->page, it->blkaddr, 1);
-	if (ret < 0)
-		return -EIO;
-
-	it->kaddr = it->page;
+	it->kaddr = erofs_read_metabuf(&it->buf, sbi,
+				       erofs_pos(sbi, it->blkaddr));
+	if (IS_ERR(it->kaddr))
+		return PTR_ERR(it->kaddr);
 	it->ofs = erofs_blkoff(sbi, it->ofs);
 	return 0;
 }
 
-static int inline_xattr_iter_pre(struct xattr_iter *it,
+static int inline_xattr_iter_begin(struct xattr_iter *it,
 				   struct erofs_inode *vi)
 {
 	struct erofs_sb_info *sbi = vi->sbi;
 	unsigned int xattr_header_sz, inline_xattr_ofs;
-	int ret;
 
 	xattr_header_sz = inlinexattr_header_size(vi);
 	if (xattr_header_sz >= vi->xattr_isize) {
@@ -1169,11 +1167,10 @@ static int inline_xattr_iter_pre(struct xattr_iter *it,
 	it->blkaddr = erofs_blknr(sbi, erofs_iloc(vi) + inline_xattr_ofs);
 	it->ofs = erofs_blkoff(sbi, erofs_iloc(vi) + inline_xattr_ofs);
 
-	ret = erofs_blk_read(sbi, 0, it->page, it->blkaddr, 1);
-	if (ret < 0)
-		return -EIO;
-
-	it->kaddr = it->page;
+	it->kaddr = erofs_read_metabuf(&it->buf, sbi,
+				       erofs_pos(sbi, it->blkaddr));
+	if (IS_ERR(it->kaddr))
+		return PTR_ERR(it->kaddr);
 	return vi->xattr_isize - xattr_header_sz;
 }
 
@@ -1370,7 +1367,7 @@ static int inline_getxattr(struct erofs_inode *vi, struct getxattr_iter *it)
 	int ret;
 	unsigned int remaining;
 
-	ret = inline_xattr_iter_pre(&it->it, vi);
+	ret = inline_xattr_iter_begin(&it->it, vi);
 	if (ret < 0)
 		return ret;
 
@@ -1386,6 +1383,7 @@ static int inline_getxattr(struct erofs_inode *vi, struct getxattr_iter *it)
 
 static int shared_getxattr(struct erofs_inode *vi, struct getxattr_iter *it)
 {
+	struct erofs_sb_info *sbi = vi->sbi;
 	unsigned int i;
 	int ret = -ENOATTR;
 
@@ -1394,15 +1392,11 @@ static int shared_getxattr(struct erofs_inode *vi, struct getxattr_iter *it)
 			xattrblock_addr(vi, vi->xattr_shared_xattrs[i]);
 
 		it->it.ofs = xattrblock_offset(vi, vi->xattr_shared_xattrs[i]);
-
-		if (!i || blkaddr != it->it.blkaddr) {
-			ret = erofs_blk_read(vi->sbi, 0, it->it.page, blkaddr, 1);
-			if (ret < 0)
-				return -EIO;
-
-			it->it.kaddr = it->it.page;
-			it->it.blkaddr = blkaddr;
-		}
+		it->it.kaddr = erofs_read_metabuf(&it->it.buf, sbi,
+						  erofs_pos(sbi, blkaddr));
+		if (IS_ERR(it->it.kaddr))
+			return PTR_ERR(it->it.kaddr);
+		it->it.blkaddr = blkaddr;
 
 		ret = xattr_foreach(&it->it, &find_xattr_handlers, NULL);
 		if (ret != -ENOATTR)
@@ -1435,12 +1429,14 @@ int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
 	if (it.len > EROFS_NAME_LEN)
 		return -ERANGE;
 
+	it.it.buf = __EROFS_BUF_INITIALIZER;
 	it.buffer = buffer;
 	it.buffer_size = buffer_size;
 
 	ret = inline_getxattr(vi, &it);
 	if (ret == -ENOATTR)
 		ret = shared_getxattr(vi, &it);
+	erofs_put_metabuf(&it.it.buf);
 	return ret;
 }
 
@@ -1526,7 +1522,7 @@ static int inline_listxattr(struct erofs_inode *vi, struct listxattr_iter *it)
 	int ret;
 	unsigned int remaining;
 
-	ret = inline_xattr_iter_pre(&it->it, vi);
+	ret = inline_xattr_iter_begin(&it->it, vi);
 	if (ret < 0)
 		return ret;
 
@@ -1542,6 +1538,7 @@ static int inline_listxattr(struct erofs_inode *vi, struct listxattr_iter *it)
 
 static int shared_listxattr(struct erofs_inode *vi, struct listxattr_iter *it)
 {
+	struct erofs_sb_info *sbi = vi->sbi;
 	unsigned int i;
 	int ret = 0;
 
@@ -1550,14 +1547,11 @@ static int shared_listxattr(struct erofs_inode *vi, struct listxattr_iter *it)
 			xattrblock_addr(vi, vi->xattr_shared_xattrs[i]);
 
 		it->it.ofs = xattrblock_offset(vi, vi->xattr_shared_xattrs[i]);
-		if (!i || blkaddr != it->it.blkaddr) {
-			ret = erofs_blk_read(vi->sbi, 0, it->it.page, blkaddr, 1);
-			if (ret < 0)
-				return -EIO;
-
-			it->it.kaddr = it->it.page;
-			it->it.blkaddr = blkaddr;
-		}
+		it->it.kaddr = erofs_read_metabuf(&it->it.buf, sbi,
+						  erofs_pos(sbi, blkaddr));
+		if (IS_ERR(it->it.kaddr))
+			return PTR_ERR(it->it.kaddr);
+		it->it.blkaddr = blkaddr;
 
 		ret = xattr_foreach(&it->it, &list_xattr_handlers, NULL);
 		if (ret)
@@ -1579,14 +1573,16 @@ int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size)
 		return ret;
 
 	it.it.sbi = vi->sbi;
+	it.it.buf = __EROFS_BUF_INITIALIZER;
 	it.buffer = buffer;
 	it.buffer_size = buffer_size;
 	it.buffer_ofs = 0;
 
 	ret = inline_listxattr(vi, &it);
 	if (ret < 0 && ret != -ENOATTR)
-		return ret;
-	return shared_listxattr(vi, &it);
+		ret = shared_listxattr(vi, &it);
+	erofs_put_metabuf(&it.it.buf);
+	return ret;
 }
 
 int erofs_xattr_insert_name_prefix(const char *prefix)
-- 
2.43.5



More information about the Linux-erofs mailing list