[PATCH] erofs: reuse xattr metabuf across init and iterators

"Jia Zhu" <[email protected]>
Newsgroups org.ozlabs.lists.linux-erofs,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
erofs_init_inode_xattrs() used a local metabuf to read the inline xattr
header and shared xattr ids.

getxattr and listxattr then initialized a separate iterator metabuf for
the following inline/shared xattr walk.

Pass the iterator metabuf into erofs_init_inode_xattrs() so initialization
and the inline iterator path share the same metabuf lifetime. The getxattr
and listxattr callers now use a single cleanup exit for their iterator
metabuf.

Drop and reinitialize the metabuf before switching from inline xattrs to
the shared xattr metadata area, since that path may use a different
mapping.

Signed-off-by: Jia Zhu <[email protected]>
---
 fs/erofs/xattr.c | 76 ++++++++++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 32 deletions(-)

diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c
index df7ea019526d7..f7eb7431b0b81 100644
--- a/fs/erofs/xattr.c
+++ b/fs/erofs/xattr.c
@@ -27,9 +27,8 @@ struct erofs_xattr_iter {
 
 static const char *erofs_xattr_prefix(unsigned int idx, struct dentry *dentry);
 
-static int erofs_init_inode_xattrs(struct inode *inode)
+static int erofs_init_inode_xattrs(struct erofs_buf *buf, struct inode *inode)
 {
-	struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
 	struct erofs_inode *vi = EROFS_I(inode);
 	struct super_block *sb = inode->i_sb;
 	const struct erofs_xattr_ibody_header *ih;
@@ -78,7 +77,7 @@ static int erofs_init_inode_xattrs(struct inode *inode)
 	}
 
 	pos = erofs_iloc(inode) + vi->inode_isize;
-	ih = erofs_read_metabuf(&buf, sb, pos, erofs_inode_in_metabox(inode));
+	ih = erofs_read_metabuf(buf, sb, pos, erofs_inode_in_metabox(inode));
 	if (IS_ERR(ih)) {
 		ret = PTR_ERR(ih);
 		goto out_unlock;
@@ -101,7 +100,7 @@ static int erofs_init_inode_xattrs(struct inode *inode)
 	/* skip the ibody header and read the shared xattr array */
 	pos += sizeof(struct erofs_xattr_ibody_header);
 	for (i = 0; i < vi->xattr_shared_count; ++i) {
-		xattr_id = erofs_bread(&buf, pos + i * sizeof(__le32), true);
+		xattr_id = erofs_bread(buf, pos + i * sizeof(__le32), true);
 		if (IS_ERR(xattr_id)) {
 			kfree(vi->xattr_shared_xattrs);
 			vi->xattr_shared_xattrs = NULL;
@@ -115,7 +114,6 @@ static int erofs_init_inode_xattrs(struct inode *inode)
 	smp_mb();
 	set_bit(EROFS_I_EA_INITED_BIT, &vi->flags);
 out_unlock:
-	erofs_put_metabuf(&buf);
 	clear_and_wake_up_bit(EROFS_I_BL_XATTR_BIT, &vi->flags);
 	return ret;
 }
@@ -337,40 +335,48 @@ static int erofs_getxattr(struct inode *inode, int index, const char *name,
 {
 	int ret;
 	unsigned int hashbit;
-	struct erofs_xattr_iter it;
+	struct erofs_xattr_iter it = {
+		.sb = inode->i_sb,
+		.buf = __EROFS_BUF_INITIALIZER,
+		.buffer = buffer,
+		.buffer_size = buffer_size,
+		.buffer_ofs = 0,
+	};
 	struct erofs_inode *vi = EROFS_I(inode);
 	struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
 
 	if (!name)
 		return -EINVAL;
 
-	ret = erofs_init_inode_xattrs(inode);
+	ret = erofs_init_inode_xattrs(&it.buf, inode);
 	if (ret)
-		return ret;
+		goto out;
 
 	/* reserved flag is non-zero if there's any change of on-disk format */
 	if (erofs_sb_has_xattr_filter(sbi) && !sbi->xattr_filter_reserved) {
 		hashbit = xxh32(name, strlen(name),
 				EROFS_XATTR_FILTER_SEED + index);
 		hashbit &= EROFS_XATTR_FILTER_BITS - 1;
-		if (vi->xattr_name_filter & (1U << hashbit))
-			return -ENODATA;
+		if (vi->xattr_name_filter & (1U << hashbit)) {
+			ret = -ENODATA;
+			goto out;
+		}
 	}
 
 	it.index = index;
 	it.name = QSTR(name);
-	if (it.name.len > EROFS_NAME_LEN)
-		return -ERANGE;
-
-	it.sb = inode->i_sb;
-	it.buf = __EROFS_BUF_INITIALIZER;
-	it.buffer = buffer;
-	it.buffer_size = buffer_size;
-	it.buffer_ofs = 0;
+	if (it.name.len > EROFS_NAME_LEN) {
+		ret = -ERANGE;
+		goto out;
+	}
 
 	ret = erofs_xattr_iter_inline(&it, inode, true);
-	if (ret == -ENODATA)
+	if (ret == -ENODATA) {
+		erofs_put_metabuf(&it.buf);
+		it.buf = __EROFS_BUF_INITIALIZER;
 		ret = erofs_xattr_iter_shared(&it, inode, true);
+	}
+out:
 	erofs_put_metabuf(&it.buf);
 	return ret ? ret : it.buffer_ofs;
 }
@@ -378,27 +384,33 @@ static int erofs_getxattr(struct inode *inode, int index, const char *name,
 ssize_t erofs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	int ret;
-	struct erofs_xattr_iter it;
+	struct erofs_xattr_iter it = {
+		.sb = dentry->d_sb,
+		.buf = __EROFS_BUF_INITIALIZER,
+		.dentry = dentry,
+		.buffer = buffer,
+		.buffer_size = buffer_size,
+		.buffer_ofs = 0,
+	};
 	struct inode *inode = d_inode(dentry);
 
-	ret = erofs_init_inode_xattrs(inode);
-	if (ret == -ENODATA)
-		return 0;
+	ret = erofs_init_inode_xattrs(&it.buf, inode);
+	if (ret == -ENODATA) {
+		ret = 0;
+		goto out;
+	}
 	if (ret)
-		return ret;
-
-	it.sb = dentry->d_sb;
-	it.buf = __EROFS_BUF_INITIALIZER;
-	it.dentry = dentry;
-	it.buffer = buffer;
-	it.buffer_size = buffer_size;
-	it.buffer_ofs = 0;
+		goto out;
 
 	ret = erofs_xattr_iter_inline(&it, inode, false);
-	if (!ret || ret == -ENODATA)
+	if (!ret || ret == -ENODATA) {
+		erofs_put_metabuf(&it.buf);
+		it.buf = __EROFS_BUF_INITIALIZER;
 		ret = erofs_xattr_iter_shared(&it, inode, false);
+	}
 	if (ret == -ENODATA)
 		ret = 0;
+out:
 	erofs_put_metabuf(&it.buf);
 	return ret ? ret : it.buffer_ofs;
 }
-- 
2.39.5 (Apple Git-154)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.