Commit 53d514b9 authored by Yiyang Wu's avatar Yiyang Wu Committed by Gao Xiang

erofs: refactor read_inode calling convention

Refactor out the iop binding behavior out of the erofs_fill_symlink
and move erofs_buf into the erofs_read_inode, so that erofs_fill_inode
can only deal with inode operation bindings and can be decoupled from
metabuf operations. This results in better calling conventions.

Note that after this patch, we do not need erofs_buf and ofs as
parameters any more when calling erofs_read_inode as
all the data operations are now included in itself.
Suggested-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Link: https://lore.kernel.org/all/20240425222847.GN2118490@ZenIV/Signed-off-by: default avatarYiyang Wu <toolmanp@tlmp.cc>
Reviewed-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
Reviewed-by: default avatarChao Yu <chao@kernel.org>
Link: https://lore.kernel.org/r/20240902093412.509083-1-toolmanp@tlmp.ccSigned-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
parent b1bbb9a6
...@@ -8,8 +8,24 @@ ...@@ -8,8 +8,24 @@
#include <trace/events/erofs.h> #include <trace/events/erofs.h>
static void *erofs_read_inode(struct erofs_buf *buf, static int erofs_fill_symlink(struct inode *inode, void *kaddr,
struct inode *inode, unsigned int *ofs) unsigned int m_pofs)
{
struct erofs_inode *vi = EROFS_I(inode);
loff_t off;
m_pofs += vi->xattr_isize;
/* check if it cannot be handled with fast symlink scheme */
if (vi->datalayout != EROFS_INODE_FLAT_INLINE || inode->i_size < 0 ||
check_add_overflow(m_pofs, inode->i_size, &off) ||
off > i_blocksize(inode))
return 0;
inode->i_link = kmemdup_nul(kaddr + m_pofs, inode->i_size, GFP_KERNEL);
return inode->i_link ? 0 : -ENOMEM;
}
static int erofs_read_inode(struct inode *inode)
{ {
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_sb_info *sbi = EROFS_SB(sb);
...@@ -20,20 +36,21 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -20,20 +36,21 @@ static void *erofs_read_inode(struct erofs_buf *buf,
struct erofs_inode_compact *dic; struct erofs_inode_compact *dic;
struct erofs_inode_extended *die, *copied = NULL; struct erofs_inode_extended *die, *copied = NULL;
union erofs_inode_i_u iu; union erofs_inode_i_u iu;
unsigned int ifmt; struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
int err; unsigned int ifmt, ofs;
int err = 0;
blkaddr = erofs_blknr(sb, inode_loc); blkaddr = erofs_blknr(sb, inode_loc);
*ofs = erofs_blkoff(sb, inode_loc); ofs = erofs_blkoff(sb, inode_loc);
kaddr = erofs_read_metabuf(buf, sb, erofs_pos(sb, blkaddr), EROFS_KMAP); kaddr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr), EROFS_KMAP);
if (IS_ERR(kaddr)) { if (IS_ERR(kaddr)) {
erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld", erofs_err(sb, "failed to get inode (nid: %llu) page, err %ld",
vi->nid, PTR_ERR(kaddr)); vi->nid, PTR_ERR(kaddr));
return kaddr; return PTR_ERR(kaddr);
} }
dic = kaddr + *ofs; dic = kaddr + ofs;
ifmt = le16_to_cpu(dic->i_format); ifmt = le16_to_cpu(dic->i_format);
if (ifmt & ~EROFS_I_ALL) { if (ifmt & ~EROFS_I_ALL) {
erofs_err(sb, "unsupported i_format %u of nid %llu", erofs_err(sb, "unsupported i_format %u of nid %llu",
...@@ -54,11 +71,11 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -54,11 +71,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
case EROFS_INODE_LAYOUT_EXTENDED: case EROFS_INODE_LAYOUT_EXTENDED:
vi->inode_isize = sizeof(struct erofs_inode_extended); vi->inode_isize = sizeof(struct erofs_inode_extended);
/* check if the extended inode acrosses block boundary */ /* check if the extended inode acrosses block boundary */
if (*ofs + vi->inode_isize <= sb->s_blocksize) { if (ofs + vi->inode_isize <= sb->s_blocksize) {
*ofs += vi->inode_isize; ofs += vi->inode_isize;
die = (struct erofs_inode_extended *)dic; die = (struct erofs_inode_extended *)dic;
} else { } else {
const unsigned int gotten = sb->s_blocksize - *ofs; const unsigned int gotten = sb->s_blocksize - ofs;
copied = kmalloc(vi->inode_isize, GFP_KERNEL); copied = kmalloc(vi->inode_isize, GFP_KERNEL);
if (!copied) { if (!copied) {
...@@ -66,16 +83,16 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -66,16 +83,16 @@ static void *erofs_read_inode(struct erofs_buf *buf,
goto err_out; goto err_out;
} }
memcpy(copied, dic, gotten); memcpy(copied, dic, gotten);
kaddr = erofs_read_metabuf(buf, sb, erofs_pos(sb, blkaddr + 1), kaddr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr + 1),
EROFS_KMAP); EROFS_KMAP);
if (IS_ERR(kaddr)) { if (IS_ERR(kaddr)) {
erofs_err(sb, "failed to get inode payload block (nid: %llu), err %ld", erofs_err(sb, "failed to get inode payload block (nid: %llu), err %ld",
vi->nid, PTR_ERR(kaddr)); vi->nid, PTR_ERR(kaddr));
kfree(copied); kfree(copied);
return kaddr; return PTR_ERR(kaddr);
} }
*ofs = vi->inode_isize - gotten; ofs = vi->inode_isize - gotten;
memcpy((u8 *)copied + gotten, kaddr, *ofs); memcpy((u8 *)copied + gotten, kaddr, ofs);
die = copied; die = copied;
} }
vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount); vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);
...@@ -91,11 +108,10 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -91,11 +108,10 @@ static void *erofs_read_inode(struct erofs_buf *buf,
inode->i_size = le64_to_cpu(die->i_size); inode->i_size = le64_to_cpu(die->i_size);
kfree(copied); kfree(copied);
copied = NULL;
break; break;
case EROFS_INODE_LAYOUT_COMPACT: case EROFS_INODE_LAYOUT_COMPACT:
vi->inode_isize = sizeof(struct erofs_inode_compact); vi->inode_isize = sizeof(struct erofs_inode_compact);
*ofs += vi->inode_isize; ofs += vi->inode_isize;
vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount); vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount);
inode->i_mode = le16_to_cpu(dic->i_mode); inode->i_mode = le16_to_cpu(dic->i_mode);
...@@ -120,6 +136,11 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -120,6 +136,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
case S_IFDIR: case S_IFDIR:
case S_IFLNK: case S_IFLNK:
vi->raw_blkaddr = le32_to_cpu(iu.raw_blkaddr); vi->raw_blkaddr = le32_to_cpu(iu.raw_blkaddr);
if(S_ISLNK(inode->i_mode)) {
err = erofs_fill_symlink(inode, kaddr, ofs);
if (err)
goto err_out;
}
break; break;
case S_IFCHR: case S_IFCHR:
case S_IFBLK: case S_IFBLK:
...@@ -165,51 +186,24 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -165,51 +186,24 @@ static void *erofs_read_inode(struct erofs_buf *buf,
inode->i_blocks = round_up(inode->i_size, sb->s_blocksize) >> 9; inode->i_blocks = round_up(inode->i_size, sb->s_blocksize) >> 9;
else else
inode->i_blocks = nblks << (sb->s_blocksize_bits - 9); inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
return kaddr;
err_out: err_out:
DBG_BUGON(1); DBG_BUGON(err);
kfree(copied); erofs_put_metabuf(&buf);
erofs_put_metabuf(buf); return err;
return ERR_PTR(err);
}
static int erofs_fill_symlink(struct inode *inode, void *kaddr,
unsigned int m_pofs)
{
struct erofs_inode *vi = EROFS_I(inode);
loff_t off;
m_pofs += vi->xattr_isize;
/* check if it cannot be handled with fast symlink scheme */
if (vi->datalayout != EROFS_INODE_FLAT_INLINE || inode->i_size < 0 ||
check_add_overflow(m_pofs, inode->i_size, &off) ||
off > i_blocksize(inode)) {
inode->i_op = &erofs_symlink_iops;
return 0;
}
inode->i_link = kmemdup_nul(kaddr + m_pofs, inode->i_size, GFP_KERNEL);
if (!inode->i_link)
return -ENOMEM;
inode->i_op = &erofs_fast_symlink_iops;
return 0;
} }
static int erofs_fill_inode(struct inode *inode) static int erofs_fill_inode(struct inode *inode)
{ {
struct erofs_inode *vi = EROFS_I(inode); struct erofs_inode *vi = EROFS_I(inode);
struct erofs_buf buf = __EROFS_BUF_INITIALIZER; int err;
void *kaddr;
unsigned int ofs;
int err = 0;
trace_erofs_fill_inode(inode); trace_erofs_fill_inode(inode);
/* read inode base data from disk */ /* read inode base data from disk */
kaddr = erofs_read_inode(&buf, inode, &ofs); err = erofs_read_inode(inode);
if (IS_ERR(kaddr)) if (err)
return PTR_ERR(kaddr); return err;
/* setup the new inode */ /* setup the new inode */
switch (inode->i_mode & S_IFMT) { switch (inode->i_mode & S_IFMT) {
...@@ -226,9 +220,10 @@ static int erofs_fill_inode(struct inode *inode) ...@@ -226,9 +220,10 @@ static int erofs_fill_inode(struct inode *inode)
inode_nohighmem(inode); inode_nohighmem(inode);
break; break;
case S_IFLNK: case S_IFLNK:
err = erofs_fill_symlink(inode, kaddr, ofs); if (inode->i_link)
if (err) inode->i_op = &erofs_fast_symlink_iops;
goto out_unlock; else
inode->i_op = &erofs_symlink_iops;
inode_nohighmem(inode); inode_nohighmem(inode);
break; break;
case S_IFCHR: case S_IFCHR:
...@@ -237,10 +232,9 @@ static int erofs_fill_inode(struct inode *inode) ...@@ -237,10 +232,9 @@ static int erofs_fill_inode(struct inode *inode)
case S_IFSOCK: case S_IFSOCK:
inode->i_op = &erofs_generic_iops; inode->i_op = &erofs_generic_iops;
init_special_inode(inode, inode->i_mode, inode->i_rdev); init_special_inode(inode, inode->i_mode, inode->i_rdev);
goto out_unlock; return 0;
default: default:
err = -EFSCORRUPTED; return -EFSCORRUPTED;
goto out_unlock;
} }
mapping_set_large_folios(inode->i_mapping); mapping_set_large_folios(inode->i_mapping);
...@@ -264,8 +258,7 @@ static int erofs_fill_inode(struct inode *inode) ...@@ -264,8 +258,7 @@ static int erofs_fill_inode(struct inode *inode)
inode->i_mapping->a_ops = &erofs_fileio_aops; inode->i_mapping->a_ops = &erofs_fileio_aops;
#endif #endif
} }
out_unlock:
erofs_put_metabuf(&buf);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment