Skip to content

Commit 72558e2

Browse files
committed
erofs: use inode_set_cached_link()
Symlink lengths are now cached in in-memory inodes directly so that readlink can be sped up. Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
1 parent 1729f7c commit 72558e2

1 file changed

Lines changed: 21 additions & 13 deletions

File tree

fs/erofs/inode.c

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,29 @@
88
#include <linux/compat.h>
99
#include <trace/events/erofs.h>
1010

11-
static int erofs_fill_symlink(struct inode *inode, void *kaddr,
12-
unsigned int m_pofs)
11+
static int erofs_fill_symlink(struct inode *inode, void *bptr, unsigned int ofs)
1312
{
1413
struct erofs_inode *vi = EROFS_I(inode);
15-
loff_t off;
16-
17-
m_pofs += vi->xattr_isize;
18-
/* check if it cannot be handled with fast symlink scheme */
19-
if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
20-
check_add_overflow(m_pofs, inode->i_size, &off) ||
21-
off > i_blocksize(inode))
22-
return 0;
23-
24-
inode->i_link = kmemdup_nul(kaddr + m_pofs, inode->i_size, GFP_KERNEL);
25-
return inode->i_link ? 0 : -ENOMEM;
14+
char *link;
15+
loff_t end;
16+
17+
ofs += vi->xattr_isize;
18+
/* check whether the symlink data is small enough to be inlined */
19+
if (vi->datalayout == EROFS_INODE_FLAT_INLINE &&
20+
!check_add_overflow(ofs, inode->i_size, &end) &&
21+
end <= i_blocksize(inode)) {
22+
link = kmemdup_nul(bptr + ofs, inode->i_size, GFP_KERNEL);
23+
if (!link)
24+
return -ENOMEM;
25+
if (unlikely(!inode->i_size || strlen(link) != inode->i_size)) {
26+
erofs_err(inode->i_sb, "invalid fast symlink size %llu @ nid %llu",
27+
inode->i_size | 0ULL, vi->nid);
28+
kfree(link);
29+
return -EFSCORRUPTED;
30+
}
31+
inode_set_cached_link(inode, link, inode->i_size);
32+
}
33+
return 0;
2634
}
2735

2836
static int erofs_read_inode(struct inode *inode)

0 commit comments

Comments
 (0)