Commit 61d325dc authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'erofs-for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs

Pull erofs updates from Gao Xiang:
 "In this cycle, sub-page block support for uncompressed files is
  available. It's mainly used to enable original signing ('golden')
  4k-block images on arm64 with 16/64k pages. In addition, end users
  could also use this feature to build a manifest to directly refer to
  golden tar data.

  Besides, long xattr name prefix support is also introduced in this
  cycle to avoid too many xattrs with the same prefix (e.g. overlayfs
  xattrs). It's useful for erofs + overlayfs combination (like Composefs
  model): the image size is reduced by ~14% and runtime performance is
  also slightly improved.

  Others are random fixes and cleanups as usual.

  Summary:

   - Add sub-page block size support for uncompressed files

   - Support flattened block device for multi-blob images to be attached
     into virtual machines (including cloud servers) and bare metals

   - Support long xattr name prefixes to optimize images with common
     xattr namespaces (e.g. files with overlayfs xattrs) use cases

   - Various minor cleanups & fixes"

* tag 'erofs-for-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
  erofs: cleanup i_format-related stuffs
  erofs: sunset erofs_dbg()
  erofs: fix potential overflow calculating xattr_isize
  erofs: get rid of z_erofs_fill_inode()
  erofs: enable long extended attribute name prefixes
  erofs: handle long xattr name prefixes properly
  erofs: add helpers to load long xattr name prefixes
  erofs: introduce on-disk format for long xattr name prefixes
  erofs: move packed inode out of the compression part
  erofs: keep meta inode into erofs_buf
  erofs: initialize packed inode after root inode is assigned
  erofs: stop parsing non-compact HEAD index if clusterofs is invalid
  erofs: don't warn ztailpacking feature anymore
  erofs: simplify erofs_xattr_generic_get()
  erofs: rename init_inode_xattrs with erofs_ prefix
  erofs: move several xattr helpers into xattr.c
  erofs: tidy up EROFS on-disk naming
  erofs: support flattened block device for multi-blob images
  erofs: set block size to the on-disk block size
  erofs: avoid hardcoded blocksize for subpage block support
parents 97adb49f 745ed7d7
...@@ -40,8 +40,8 @@ Here are the main features of EROFS: ...@@ -40,8 +40,8 @@ Here are the main features of EROFS:
- Support multiple devices to refer to external blobs, which can be used - Support multiple devices to refer to external blobs, which can be used
for container images; for container images;
- 4KiB block size and 32-bit block addresses for each device, therefore - 32-bit block addresses for each device, therefore 16TiB address space at
16TiB address space at most for now; most with 4KiB block size for now;
- Two inode layouts for different requirements: - Two inode layouts for different requirements:
......
...@@ -27,11 +27,15 @@ void erofs_put_metabuf(struct erofs_buf *buf) ...@@ -27,11 +27,15 @@ void erofs_put_metabuf(struct erofs_buf *buf)
buf->page = NULL; buf->page = NULL;
} }
void *erofs_bread(struct erofs_buf *buf, struct inode *inode, /*
erofs_blk_t blkaddr, enum erofs_kmap_type type) * Derive the block size from inode->i_blkbits to make compatible with
* anonymous inode in fscache mode.
*/
void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
enum erofs_kmap_type type)
{ {
struct address_space *const mapping = inode->i_mapping; struct inode *inode = buf->inode;
erofs_off_t offset = blknr_to_addr(blkaddr); erofs_off_t offset = (erofs_off_t)blkaddr << inode->i_blkbits;
pgoff_t index = offset >> PAGE_SHIFT; pgoff_t index = offset >> PAGE_SHIFT;
struct page *page = buf->page; struct page *page = buf->page;
struct folio *folio; struct folio *folio;
...@@ -41,7 +45,7 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode, ...@@ -41,7 +45,7 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
erofs_put_metabuf(buf); erofs_put_metabuf(buf);
nofs_flag = memalloc_nofs_save(); nofs_flag = memalloc_nofs_save();
folio = read_cache_folio(mapping, index, NULL, NULL); folio = read_cache_folio(inode->i_mapping, index, NULL, NULL);
memalloc_nofs_restore(nofs_flag); memalloc_nofs_restore(nofs_flag);
if (IS_ERR(folio)) if (IS_ERR(folio))
return folio; return folio;
...@@ -63,14 +67,19 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode, ...@@ -63,14 +67,19 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
return buf->base + (offset & ~PAGE_MASK); return buf->base + (offset & ~PAGE_MASK);
} }
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
erofs_blk_t blkaddr, enum erofs_kmap_type type)
{ {
if (erofs_is_fscache_mode(sb)) if (erofs_is_fscache_mode(sb))
return erofs_bread(buf, EROFS_SB(sb)->s_fscache->inode, buf->inode = EROFS_SB(sb)->s_fscache->inode;
blkaddr, type); else
buf->inode = sb->s_bdev->bd_inode;
}
return erofs_bread(buf, sb->s_bdev->bd_inode, blkaddr, type); void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
erofs_blk_t blkaddr, enum erofs_kmap_type type)
{
erofs_init_metabuf(buf, sb);
return erofs_bread(buf, blkaddr, type);
} }
static int erofs_map_blocks_flatmode(struct inode *inode, static int erofs_map_blocks_flatmode(struct inode *inode,
...@@ -79,33 +88,32 @@ static int erofs_map_blocks_flatmode(struct inode *inode, ...@@ -79,33 +88,32 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
erofs_blk_t nblocks, lastblk; erofs_blk_t nblocks, lastblk;
u64 offset = map->m_la; u64 offset = map->m_la;
struct erofs_inode *vi = EROFS_I(inode); struct erofs_inode *vi = EROFS_I(inode);
struct super_block *sb = inode->i_sb;
bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE); bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
nblocks = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); nblocks = erofs_iblks(inode);
lastblk = nblocks - tailendpacking; lastblk = nblocks - tailendpacking;
/* there is no hole in flatmode */ /* there is no hole in flatmode */
map->m_flags = EROFS_MAP_MAPPED; map->m_flags = EROFS_MAP_MAPPED;
if (offset < blknr_to_addr(lastblk)) { if (offset < erofs_pos(sb, lastblk)) {
map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la; map->m_pa = erofs_pos(sb, vi->raw_blkaddr) + map->m_la;
map->m_plen = blknr_to_addr(lastblk) - offset; map->m_plen = erofs_pos(sb, lastblk) - offset;
} else if (tailendpacking) { } else if (tailendpacking) {
map->m_pa = erofs_iloc(inode) + vi->inode_isize + map->m_pa = erofs_iloc(inode) + vi->inode_isize +
vi->xattr_isize + erofs_blkoff(offset); vi->xattr_isize + erofs_blkoff(sb, offset);
map->m_plen = inode->i_size - offset; map->m_plen = inode->i_size - offset;
/* inline data should be located in the same meta block */ /* inline data should be located in the same meta block */
if (erofs_blkoff(map->m_pa) + map->m_plen > EROFS_BLKSIZ) { if (erofs_blkoff(sb, map->m_pa) + map->m_plen > sb->s_blocksize) {
erofs_err(inode->i_sb, erofs_err(sb, "inline data cross block boundary @ nid %llu",
"inline data cross block boundary @ nid %llu",
vi->nid); vi->nid);
DBG_BUGON(1); DBG_BUGON(1);
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
map->m_flags |= EROFS_MAP_META; map->m_flags |= EROFS_MAP_META;
} else { } else {
erofs_err(inode->i_sb, erofs_err(sb, "internal error @ nid: %llu (size %llu), m_la 0x%llx",
"internal error @ nid: %llu (size %llu), m_la 0x%llx",
vi->nid, inode->i_size, map->m_la); vi->nid, inode->i_size, map->m_la);
DBG_BUGON(1); DBG_BUGON(1);
return -EIO; return -EIO;
...@@ -148,29 +156,29 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map) ...@@ -148,29 +156,29 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
pos = ALIGN(erofs_iloc(inode) + vi->inode_isize + pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
vi->xattr_isize, unit) + unit * chunknr; vi->xattr_isize, unit) + unit * chunknr;
kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP); kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(sb, pos), EROFS_KMAP);
if (IS_ERR(kaddr)) { if (IS_ERR(kaddr)) {
err = PTR_ERR(kaddr); err = PTR_ERR(kaddr);
goto out; goto out;
} }
map->m_la = chunknr << vi->chunkbits; map->m_la = chunknr << vi->chunkbits;
map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits, map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
roundup(inode->i_size - map->m_la, EROFS_BLKSIZ)); round_up(inode->i_size - map->m_la, sb->s_blocksize));
/* handle block map */ /* handle block map */
if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) { if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
__le32 *blkaddr = kaddr + erofs_blkoff(pos); __le32 *blkaddr = kaddr + erofs_blkoff(sb, pos);
if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) { if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
map->m_flags = 0; map->m_flags = 0;
} else { } else {
map->m_pa = blknr_to_addr(le32_to_cpu(*blkaddr)); map->m_pa = erofs_pos(sb, le32_to_cpu(*blkaddr));
map->m_flags = EROFS_MAP_MAPPED; map->m_flags = EROFS_MAP_MAPPED;
} }
goto out_unlock; goto out_unlock;
} }
/* parse chunk indexes */ /* parse chunk indexes */
idx = kaddr + erofs_blkoff(pos); idx = kaddr + erofs_blkoff(sb, pos);
switch (le32_to_cpu(idx->blkaddr)) { switch (le32_to_cpu(idx->blkaddr)) {
case EROFS_NULL_ADDR: case EROFS_NULL_ADDR:
map->m_flags = 0; map->m_flags = 0;
...@@ -178,7 +186,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map) ...@@ -178,7 +186,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
default: default:
map->m_deviceid = le16_to_cpu(idx->device_id) & map->m_deviceid = le16_to_cpu(idx->device_id) &
EROFS_SB(sb)->device_id_mask; EROFS_SB(sb)->device_id_mask;
map->m_pa = blknr_to_addr(le32_to_cpu(idx->blkaddr)); map->m_pa = erofs_pos(sb, le32_to_cpu(idx->blkaddr));
map->m_flags = EROFS_MAP_MAPPED; map->m_flags = EROFS_MAP_MAPPED;
break; break;
} }
...@@ -197,7 +205,6 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map) ...@@ -197,7 +205,6 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
struct erofs_device_info *dif; struct erofs_device_info *dif;
int id; int id;
/* primary device by default */
map->m_bdev = sb->s_bdev; map->m_bdev = sb->s_bdev;
map->m_daxdev = EROFS_SB(sb)->dax_dev; map->m_daxdev = EROFS_SB(sb)->dax_dev;
map->m_dax_part_off = EROFS_SB(sb)->dax_part_off; map->m_dax_part_off = EROFS_SB(sb)->dax_part_off;
...@@ -210,20 +217,25 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map) ...@@ -210,20 +217,25 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
up_read(&devs->rwsem); up_read(&devs->rwsem);
return -ENODEV; return -ENODEV;
} }
if (devs->flatdev) {
map->m_pa += erofs_pos(sb, dif->mapped_blkaddr);
up_read(&devs->rwsem);
return 0;
}
map->m_bdev = dif->bdev; map->m_bdev = dif->bdev;
map->m_daxdev = dif->dax_dev; map->m_daxdev = dif->dax_dev;
map->m_dax_part_off = dif->dax_part_off; map->m_dax_part_off = dif->dax_part_off;
map->m_fscache = dif->fscache; map->m_fscache = dif->fscache;
up_read(&devs->rwsem); up_read(&devs->rwsem);
} else if (devs->extra_devices) { } else if (devs->extra_devices && !devs->flatdev) {
down_read(&devs->rwsem); down_read(&devs->rwsem);
idr_for_each_entry(&devs->tree, dif, id) { idr_for_each_entry(&devs->tree, dif, id) {
erofs_off_t startoff, length; erofs_off_t startoff, length;
if (!dif->mapped_blkaddr) if (!dif->mapped_blkaddr)
continue; continue;
startoff = blknr_to_addr(dif->mapped_blkaddr); startoff = erofs_pos(sb, dif->mapped_blkaddr);
length = blknr_to_addr(dif->blocks); length = erofs_pos(sb, dif->blocks);
if (map->m_pa >= startoff && if (map->m_pa >= startoff &&
map->m_pa < startoff + length) { map->m_pa < startoff + length) {
...@@ -244,6 +256,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, ...@@ -244,6 +256,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
unsigned int flags, struct iomap *iomap, struct iomap *srcmap) unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
{ {
int ret; int ret;
struct super_block *sb = inode->i_sb;
struct erofs_map_blocks map; struct erofs_map_blocks map;
struct erofs_map_dev mdev; struct erofs_map_dev mdev;
...@@ -258,7 +271,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, ...@@ -258,7 +271,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
.m_deviceid = map.m_deviceid, .m_deviceid = map.m_deviceid,
.m_pa = map.m_pa, .m_pa = map.m_pa,
}; };
ret = erofs_map_dev(inode->i_sb, &mdev); ret = erofs_map_dev(sb, &mdev);
if (ret) if (ret)
return ret; return ret;
...@@ -284,11 +297,11 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, ...@@ -284,11 +297,11 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
struct erofs_buf buf = __EROFS_BUF_INITIALIZER; struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
iomap->type = IOMAP_INLINE; iomap->type = IOMAP_INLINE;
ptr = erofs_read_metabuf(&buf, inode->i_sb, ptr = erofs_read_metabuf(&buf, sb,
erofs_blknr(mdev.m_pa), EROFS_KMAP); erofs_blknr(sb, mdev.m_pa), EROFS_KMAP);
if (IS_ERR(ptr)) if (IS_ERR(ptr))
return PTR_ERR(ptr); return PTR_ERR(ptr);
iomap->inline_data = ptr + erofs_blkoff(mdev.m_pa); iomap->inline_data = ptr + erofs_blkoff(sb, mdev.m_pa);
iomap->private = buf.base; iomap->private = buf.base;
} else { } else {
iomap->type = IOMAP_MAPPED; iomap->type = IOMAP_MAPPED;
......
...@@ -42,7 +42,7 @@ int z_erofs_load_lz4_config(struct super_block *sb, ...@@ -42,7 +42,7 @@ int z_erofs_load_lz4_config(struct super_block *sb,
if (!sbi->lz4.max_pclusterblks) { if (!sbi->lz4.max_pclusterblks) {
sbi->lz4.max_pclusterblks = 1; /* reserved case */ sbi->lz4.max_pclusterblks = 1; /* reserved case */
} else if (sbi->lz4.max_pclusterblks > } else if (sbi->lz4.max_pclusterblks >
Z_EROFS_PCLUSTER_MAX_SIZE / EROFS_BLKSIZ) { erofs_blknr(sb, Z_EROFS_PCLUSTER_MAX_SIZE)) {
erofs_err(sb, "too large lz4 pclusterblks %u", erofs_err(sb, "too large lz4 pclusterblks %u",
sbi->lz4.max_pclusterblks); sbi->lz4.max_pclusterblks);
return -EINVAL; return -EINVAL;
...@@ -221,13 +221,13 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx, ...@@ -221,13 +221,13 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,
support_0padding = true; support_0padding = true;
ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in, ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
min_t(unsigned int, rq->inputsize, min_t(unsigned int, rq->inputsize,
EROFS_BLKSIZ - rq->pageofs_in)); rq->sb->s_blocksize - rq->pageofs_in));
if (ret) { if (ret) {
kunmap_atomic(headpage); kunmap_atomic(headpage);
return ret; return ret;
} }
may_inplace = !((rq->pageofs_in + rq->inputsize) & may_inplace = !((rq->pageofs_in + rq->inputsize) &
(EROFS_BLKSIZ - 1)); (rq->sb->s_blocksize - 1));
} }
inputmargin = rq->pageofs_in; inputmargin = rq->pageofs_in;
......
...@@ -167,7 +167,7 @@ int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, ...@@ -167,7 +167,7 @@ int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
kin = kmap(*rq->in); kin = kmap(*rq->in);
err = z_erofs_fixup_insize(rq, kin + rq->pageofs_in, err = z_erofs_fixup_insize(rq, kin + rq->pageofs_in,
min_t(unsigned int, rq->inputsize, min_t(unsigned int, rq->inputsize,
EROFS_BLKSIZ - rq->pageofs_in)); rq->sb->s_blocksize - rq->pageofs_in));
if (err) { if (err) {
kunmap(*rq->in); kunmap(*rq->in);
return err; return err;
......
...@@ -50,44 +50,43 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) ...@@ -50,44 +50,43 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
{ {
struct inode *dir = file_inode(f); struct inode *dir = file_inode(f);
struct erofs_buf buf = __EROFS_BUF_INITIALIZER; struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
struct super_block *sb = dir->i_sb;
unsigned long bsz = sb->s_blocksize;
const size_t dirsize = i_size_read(dir); const size_t dirsize = i_size_read(dir);
unsigned int i = ctx->pos / EROFS_BLKSIZ; unsigned int i = erofs_blknr(sb, ctx->pos);
unsigned int ofs = ctx->pos % EROFS_BLKSIZ; unsigned int ofs = erofs_blkoff(sb, ctx->pos);
int err = 0; int err = 0;
bool initial = true; bool initial = true;
buf.inode = dir;
while (ctx->pos < dirsize) { while (ctx->pos < dirsize) {
struct erofs_dirent *de; struct erofs_dirent *de;
unsigned int nameoff, maxsize; unsigned int nameoff, maxsize;
de = erofs_bread(&buf, dir, i, EROFS_KMAP); de = erofs_bread(&buf, i, EROFS_KMAP);
if (IS_ERR(de)) { if (IS_ERR(de)) {
erofs_err(dir->i_sb, erofs_err(sb, "fail to readdir of logical block %u of nid %llu",
"fail to readdir of logical block %u of nid %llu",
i, EROFS_I(dir)->nid); i, EROFS_I(dir)->nid);
err = PTR_ERR(de); err = PTR_ERR(de);
break; break;
} }
nameoff = le16_to_cpu(de->nameoff); nameoff = le16_to_cpu(de->nameoff);
if (nameoff < sizeof(struct erofs_dirent) || if (nameoff < sizeof(struct erofs_dirent) || nameoff >= bsz) {
nameoff >= EROFS_BLKSIZ) { erofs_err(sb, "invalid de[0].nameoff %u @ nid %llu",
erofs_err(dir->i_sb,
"invalid de[0].nameoff %u @ nid %llu",
nameoff, EROFS_I(dir)->nid); nameoff, EROFS_I(dir)->nid);
err = -EFSCORRUPTED; err = -EFSCORRUPTED;
break; break;
} }
maxsize = min_t(unsigned int, maxsize = min_t(unsigned int, dirsize - ctx->pos + ofs, bsz);
dirsize - ctx->pos + ofs, EROFS_BLKSIZ);
/* search dirents at the arbitrary position */ /* search dirents at the arbitrary position */
if (initial) { if (initial) {
initial = false; initial = false;
ofs = roundup(ofs, sizeof(struct erofs_dirent)); ofs = roundup(ofs, sizeof(struct erofs_dirent));
ctx->pos = blknr_to_addr(i) + ofs; ctx->pos = erofs_pos(sb, i) + ofs;
if (ofs >= nameoff) if (ofs >= nameoff)
goto skip_this; goto skip_this;
} }
...@@ -97,7 +96,7 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) ...@@ -97,7 +96,7 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
if (err) if (err)
break; break;
skip_this: skip_this:
ctx->pos = blknr_to_addr(i) + maxsize; ctx->pos = erofs_pos(sb, i) + maxsize;
++i; ++i;
ofs = 0; ofs = 0;
} }
......
This diff is collapsed.
...@@ -209,8 +209,8 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_request *primary) ...@@ -209,8 +209,8 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_request *primary)
void *src; void *src;
/* For tail packing layout, the offset may be non-zero. */ /* For tail packing layout, the offset may be non-zero. */
offset = erofs_blkoff(map.m_pa); offset = erofs_blkoff(sb, map.m_pa);
blknr = erofs_blknr(map.m_pa); blknr = erofs_blknr(sb, map.m_pa);
size = map.m_llen; size = map.m_llen;
src = erofs_read_metabuf(&buf, sb, blknr, EROFS_KMAP); src = erofs_read_metabuf(&buf, sb, blknr, EROFS_KMAP);
...@@ -460,6 +460,7 @@ static struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb ...@@ -460,6 +460,7 @@ static struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb
inode->i_size = OFFSET_MAX; inode->i_size = OFFSET_MAX;
inode->i_mapping->a_ops = &erofs_fscache_meta_aops; inode->i_mapping->a_ops = &erofs_fscache_meta_aops;
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
inode->i_blkbits = EROFS_SB(sb)->blkszbits;
inode->i_private = ctx; inode->i_private = ctx;
ctx->cookie = cookie; ctx->cookie = cookie;
......
...@@ -23,11 +23,8 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -23,11 +23,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
unsigned int ifmt; unsigned int ifmt;
int err; int err;
blkaddr = erofs_blknr(inode_loc); blkaddr = erofs_blknr(sb, inode_loc);
*ofs = erofs_blkoff(inode_loc); *ofs = erofs_blkoff(sb, inode_loc);
erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u",
__func__, vi->nid, *ofs, blkaddr);
kaddr = erofs_read_metabuf(buf, sb, blkaddr, EROFS_KMAP); kaddr = erofs_read_metabuf(buf, sb, blkaddr, EROFS_KMAP);
if (IS_ERR(kaddr)) { if (IS_ERR(kaddr)) {
...@@ -58,11 +55,11 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -58,11 +55,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 <= EROFS_BLKSIZ) { 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 = EROFS_BLKSIZ - *ofs; const unsigned int gotten = sb->s_blocksize - *ofs;
copied = kmalloc(vi->inode_isize, GFP_NOFS); copied = kmalloc(vi->inode_isize, GFP_NOFS);
if (!copied) { if (!copied) {
...@@ -176,7 +173,7 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -176,7 +173,7 @@ static void *erofs_read_inode(struct erofs_buf *buf,
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto err_out; goto err_out;
} }
vi->chunkbits = LOG_BLOCK_SIZE + vi->chunkbits = sb->s_blocksize_bits +
(vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK); (vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
} }
inode->i_mtime.tv_sec = inode->i_ctime.tv_sec; inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
...@@ -188,11 +185,12 @@ static void *erofs_read_inode(struct erofs_buf *buf, ...@@ -188,11 +185,12 @@ static void *erofs_read_inode(struct erofs_buf *buf,
if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) && if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
vi->datalayout == EROFS_INODE_FLAT_PLAIN) vi->datalayout == EROFS_INODE_FLAT_PLAIN)
inode->i_flags |= S_DAX; inode->i_flags |= S_DAX;
if (!nblks) if (!nblks)
/* measure inode.i_blocks as generic filesystems */ /* measure inode.i_blocks as generic filesystems */
inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; inode->i_blocks = round_up(inode->i_size, sb->s_blocksize) >> 9;
else else
inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
return kaddr; return kaddr;
bogusimode: bogusimode:
...@@ -210,11 +208,12 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr, ...@@ -210,11 +208,12 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
unsigned int m_pofs) unsigned int m_pofs)
{ {
struct erofs_inode *vi = EROFS_I(inode); struct erofs_inode *vi = EROFS_I(inode);
unsigned int bsz = i_blocksize(inode);
char *lnk; char *lnk;
/* if it cannot be handled with fast symlink scheme */ /* if it cannot be handled with fast symlink scheme */
if (vi->datalayout != EROFS_INODE_FLAT_INLINE || if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
inode->i_size >= EROFS_BLKSIZ || inode->i_size < 0) { inode->i_size >= bsz || inode->i_size < 0) {
inode->i_op = &erofs_symlink_iops; inode->i_op = &erofs_symlink_iops;
return 0; return 0;
} }
...@@ -225,7 +224,7 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr, ...@@ -225,7 +224,7 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
m_pofs += vi->xattr_isize; m_pofs += vi->xattr_isize;
/* inline symlink data shouldn't cross block boundary */ /* inline symlink data shouldn't cross block boundary */
if (m_pofs + inode->i_size > EROFS_BLKSIZ) { if (m_pofs + inode->i_size > bsz) {
kfree(lnk); kfree(lnk);
erofs_err(inode->i_sb, erofs_err(inode->i_sb,
"inline data cross block boundary @ nid %llu", "inline data cross block boundary @ nid %llu",
...@@ -289,9 +288,14 @@ static int erofs_fill_inode(struct inode *inode) ...@@ -289,9 +288,14 @@ static int erofs_fill_inode(struct inode *inode)
} }
if (erofs_inode_is_data_compressed(vi->datalayout)) { if (erofs_inode_is_data_compressed(vi->datalayout)) {
if (!erofs_is_fscache_mode(inode->i_sb)) #ifdef CONFIG_EROFS_FS_ZIP
err = z_erofs_fill_inode(inode); if (!erofs_is_fscache_mode(inode->i_sb) &&
else inode->i_sb->s_blocksize_bits == PAGE_SHIFT) {
inode->i_mapping->a_ops = &z_erofs_aops;
err = 0;
goto out_unlock;
}
#endif
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto out_unlock; goto out_unlock;
} }
......
...@@ -31,10 +31,8 @@ __printf(3, 4) void _erofs_info(struct super_block *sb, ...@@ -31,10 +31,8 @@ __printf(3, 4) void _erofs_info(struct super_block *sb,
#define erofs_info(sb, fmt, ...) \ #define erofs_info(sb, fmt, ...) \
_erofs_info(sb, __func__, fmt "\n", ##__VA_ARGS__) _erofs_info(sb, __func__, fmt "\n", ##__VA_ARGS__)
#ifdef CONFIG_EROFS_FS_DEBUG #ifdef CONFIG_EROFS_FS_DEBUG
#define erofs_dbg(x, ...) pr_debug(x "\n", ##__VA_ARGS__)
#define DBG_BUGON BUG_ON #define DBG_BUGON BUG_ON
#else #else
#define erofs_dbg(x, ...) ((void)0)
#define DBG_BUGON(x) ((void)(x)) #define DBG_BUGON(x) ((void)(x))
#endif /* !CONFIG_EROFS_FS_DEBUG */ #endif /* !CONFIG_EROFS_FS_DEBUG */
...@@ -81,6 +79,7 @@ struct erofs_dev_context { ...@@ -81,6 +79,7 @@ struct erofs_dev_context {
struct rw_semaphore rwsem; struct rw_semaphore rwsem;
unsigned int extra_devices; unsigned int extra_devices;
bool flatdev;
}; };
struct erofs_fs_context { struct erofs_fs_context {
...@@ -116,6 +115,11 @@ struct erofs_fscache { ...@@ -116,6 +115,11 @@ struct erofs_fscache {
char *name; char *name;
}; };
struct erofs_xattr_prefix_item {
struct erofs_xattr_long_prefix *prefix;
u8 infix_len;
};
struct erofs_sb_info { struct erofs_sb_info {
struct erofs_mount_opts opt; /* options */ struct erofs_mount_opts opt; /* options */
#ifdef CONFIG_EROFS_FS_ZIP #ifdef CONFIG_EROFS_FS_ZIP
...@@ -133,8 +137,8 @@ struct erofs_sb_info { ...@@ -133,8 +137,8 @@ struct erofs_sb_info {
struct inode *managed_cache; struct inode *managed_cache;
struct erofs_sb_lz4_info lz4; struct erofs_sb_lz4_info lz4;
struct inode *packed_inode;
#endif /* CONFIG_EROFS_FS_ZIP */ #endif /* CONFIG_EROFS_FS_ZIP */
struct inode *packed_inode;
struct erofs_dev_context *devs; struct erofs_dev_context *devs;
struct dax_device *dax_dev; struct dax_device *dax_dev;
u64 dax_part_off; u64 dax_part_off;
...@@ -144,11 +148,14 @@ struct erofs_sb_info { ...@@ -144,11 +148,14 @@ struct erofs_sb_info {
u32 meta_blkaddr; u32 meta_blkaddr;
#ifdef CONFIG_EROFS_FS_XATTR #ifdef CONFIG_EROFS_FS_XATTR
u32 xattr_blkaddr; u32 xattr_blkaddr;
u32 xattr_prefix_start;
u8 xattr_prefix_count;
struct erofs_xattr_prefix_item *xattr_prefixes;
#endif #endif
u16 device_id_mask; /* valid bits of device id to be used */ u16 device_id_mask; /* valid bits of device id to be used */
/* inode slot unit size in bit shift */ unsigned char islotbits; /* inode slot unit size in bit shift */
unsigned char islotbits; unsigned char blkszbits; /* filesystem block size in bit shift */
u32 sb_size; /* total superblock size */ u32 sb_size; /* total superblock size */
u32 build_time_nsec; u32 build_time_nsec;
...@@ -156,6 +163,7 @@ struct erofs_sb_info { ...@@ -156,6 +163,7 @@ struct erofs_sb_info {
/* what we really care is nid, rather than ino.. */ /* what we really care is nid, rather than ino.. */
erofs_nid_t root_nid; erofs_nid_t root_nid;
erofs_nid_t packed_nid;
/* used for statfs, f_files - f_favail */ /* used for statfs, f_files - f_favail */
u64 inos; u64 inos;
...@@ -240,27 +248,13 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) ...@@ -240,27 +248,13 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
VAL != EROFS_LOCKED_MAGIC); VAL != EROFS_LOCKED_MAGIC);
} }
/* we strictly follow PAGE_SIZE and no buffer head yet */
#define LOG_BLOCK_SIZE PAGE_SHIFT
#undef LOG_SECTORS_PER_BLOCK
#define LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9)
#undef SECTORS_PER_BLOCK
#define SECTORS_PER_BLOCK (1 << SECTORS_PER_BLOCK)
#define EROFS_BLKSIZ (1 << LOG_BLOCK_SIZE)
#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ)
#error erofs cannot be used in this platform
#endif
enum erofs_kmap_type { enum erofs_kmap_type {
EROFS_NO_KMAP, /* don't map the buffer */ EROFS_NO_KMAP, /* don't map the buffer */
EROFS_KMAP, /* use kmap_local_page() to map the buffer */ EROFS_KMAP, /* use kmap_local_page() to map the buffer */
}; };
struct erofs_buf { struct erofs_buf {
struct inode *inode;
struct page *page; struct page *page;
void *base; void *base;
enum erofs_kmap_type kmap_type; enum erofs_kmap_type kmap_type;
...@@ -269,9 +263,10 @@ struct erofs_buf { ...@@ -269,9 +263,10 @@ struct erofs_buf {
#define ROOT_NID(sb) ((sb)->root_nid) #define ROOT_NID(sb) ((sb)->root_nid)
#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) #define erofs_blknr(sb, addr) ((addr) >> (sb)->s_blocksize_bits)
#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) #define erofs_blkoff(sb, addr) ((addr) & ((sb)->s_blocksize - 1))
#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) #define erofs_pos(sb, blk) ((erofs_off_t)(blk) << (sb)->s_blocksize_bits)
#define erofs_iblks(i) (round_up((i)->i_size, i_blocksize(i)) >> (i)->i_blkbits)
#define EROFS_FEATURE_FUNCS(name, compat, feature) \ #define EROFS_FEATURE_FUNCS(name, compat, feature) \
static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \ static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \
...@@ -288,6 +283,7 @@ EROFS_FEATURE_FUNCS(compr_head2, incompat, INCOMPAT_COMPR_HEAD2) ...@@ -288,6 +283,7 @@ EROFS_FEATURE_FUNCS(compr_head2, incompat, INCOMPAT_COMPR_HEAD2)
EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING) EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS) EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE) EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
/* atomic flag definitions */ /* atomic flag definitions */
...@@ -306,7 +302,7 @@ struct erofs_inode { ...@@ -306,7 +302,7 @@ struct erofs_inode {
unsigned char datalayout; unsigned char datalayout;
unsigned char inode_isize; unsigned char inode_isize;
unsigned short xattr_isize; unsigned int xattr_isize;
unsigned int xattr_shared_count; unsigned int xattr_shared_count;
unsigned int *xattr_shared_xattrs; unsigned int *xattr_shared_xattrs;
...@@ -343,28 +339,18 @@ static inline erofs_off_t erofs_iloc(struct inode *inode) ...@@ -343,28 +339,18 @@ static inline erofs_off_t erofs_iloc(struct inode *inode)
{ {
struct erofs_sb_info *sbi = EROFS_I_SB(inode); struct erofs_sb_info *sbi = EROFS_I_SB(inode);
return blknr_to_addr(sbi->meta_blkaddr) + return erofs_pos(inode->i_sb, sbi->meta_blkaddr) +
(EROFS_I(inode)->nid << sbi->islotbits); (EROFS_I(inode)->nid << sbi->islotbits);
} }
static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit, static inline unsigned int erofs_inode_version(unsigned int ifmt)
unsigned int bits)
{
return (value >> bit) & ((1 << bits) - 1);
}
static inline unsigned int erofs_inode_version(unsigned int value)
{ {
return erofs_bitrange(value, EROFS_I_VERSION_BIT, return (ifmt >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASK;
EROFS_I_VERSION_BITS);
} }
static inline unsigned int erofs_inode_datalayout(unsigned int value) static inline unsigned int erofs_inode_datalayout(unsigned int ifmt)
{ {
return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT, return (ifmt >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASK;
EROFS_I_DATALAYOUT_BITS);
} }
/* /*
...@@ -451,10 +437,13 @@ extern const struct iomap_ops z_erofs_iomap_report_ops; ...@@ -451,10 +437,13 @@ extern const struct iomap_ops z_erofs_iomap_report_ops;
#define EROFS_REG_COOKIE_SHARE 0x0001 #define EROFS_REG_COOKIE_SHARE 0x0001
#define EROFS_REG_COOKIE_NEED_NOEXIST 0x0002 #define EROFS_REG_COOKIE_NEED_NOEXIST 0x0002
void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
erofs_off_t *offset, int *lengthp);
void erofs_unmap_metabuf(struct erofs_buf *buf); void erofs_unmap_metabuf(struct erofs_buf *buf);
void erofs_put_metabuf(struct erofs_buf *buf); void erofs_put_metabuf(struct erofs_buf *buf);
void *erofs_bread(struct erofs_buf *buf, struct inode *inode, void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
erofs_blk_t blkaddr, enum erofs_kmap_type type); enum erofs_kmap_type type);
void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb);
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
erofs_blk_t blkaddr, enum erofs_kmap_type type); erofs_blk_t blkaddr, enum erofs_kmap_type type);
int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev); int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev);
...@@ -521,7 +510,6 @@ int erofs_try_to_free_cached_page(struct page *page); ...@@ -521,7 +510,6 @@ int erofs_try_to_free_cached_page(struct page *page);
int z_erofs_load_lz4_config(struct super_block *sb, int z_erofs_load_lz4_config(struct super_block *sb,
struct erofs_super_block *dsb, struct erofs_super_block *dsb,
struct z_erofs_lz4_cfgs *lz4, int len); struct z_erofs_lz4_cfgs *lz4, int len);
int z_erofs_fill_inode(struct inode *inode);
int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
int flags); int flags);
#else #else
...@@ -541,7 +529,6 @@ static inline int z_erofs_load_lz4_config(struct super_block *sb, ...@@ -541,7 +529,6 @@ static inline int z_erofs_load_lz4_config(struct super_block *sb,
} }
return 0; return 0;
} }
static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; }
#endif /* !CONFIG_EROFS_FS_ZIP */ #endif /* !CONFIG_EROFS_FS_ZIP */
#ifdef CONFIG_EROFS_FS_ZIP_LZMA #ifdef CONFIG_EROFS_FS_ZIP_LZMA
......
...@@ -89,7 +89,8 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name, ...@@ -89,7 +89,8 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
static void *erofs_find_target_block(struct erofs_buf *target, static void *erofs_find_target_block(struct erofs_buf *target,
struct inode *dir, struct erofs_qstr *name, int *_ndirents) struct inode *dir, struct erofs_qstr *name, int *_ndirents)
{ {
int head = 0, back = DIV_ROUND_UP(dir->i_size, EROFS_BLKSIZ) - 1; unsigned int bsz = i_blocksize(dir);
int head = 0, back = erofs_iblks(dir) - 1;
unsigned int startprfx = 0, endprfx = 0; unsigned int startprfx = 0, endprfx = 0;
void *candidate = ERR_PTR(-ENOENT); void *candidate = ERR_PTR(-ENOENT);
...@@ -98,10 +99,10 @@ static void *erofs_find_target_block(struct erofs_buf *target, ...@@ -98,10 +99,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
struct erofs_buf buf = __EROFS_BUF_INITIALIZER; struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
struct erofs_dirent *de; struct erofs_dirent *de;
de = erofs_bread(&buf, dir, mid, EROFS_KMAP); buf.inode = dir;
de = erofs_bread(&buf, mid, EROFS_KMAP);
if (!IS_ERR(de)) { if (!IS_ERR(de)) {
const int nameoff = nameoff_from_disk(de->nameoff, const int nameoff = nameoff_from_disk(de->nameoff, bsz);
EROFS_BLKSIZ);
const int ndirents = nameoff / sizeof(*de); const int ndirents = nameoff / sizeof(*de);
int diff; int diff;
unsigned int matched; unsigned int matched;
...@@ -121,11 +122,10 @@ static void *erofs_find_target_block(struct erofs_buf *target, ...@@ -121,11 +122,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
dname.name = (u8 *)de + nameoff; dname.name = (u8 *)de + nameoff;
if (ndirents == 1) if (ndirents == 1)
dname.end = (u8 *)de + EROFS_BLKSIZ; dname.end = (u8 *)de + bsz;
else else
dname.end = (u8 *)de + dname.end = (u8 *)de +
nameoff_from_disk(de[1].nameoff, nameoff_from_disk(de[1].nameoff, bsz);
EROFS_BLKSIZ);
/* string comparison without already matched prefix */ /* string comparison without already matched prefix */
diff = erofs_dirnamecmp(name, &dname, &matched); diff = erofs_dirnamecmp(name, &dname, &matched);
...@@ -171,6 +171,7 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid, ...@@ -171,6 +171,7 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
qn.name = name->name; qn.name = name->name;
qn.end = name->name + name->len; qn.end = name->name + name->len;
buf.inode = dir;
ndirents = 0; ndirents = 0;
de = erofs_find_target_block(&buf, dir, &qn, &ndirents); de = erofs_find_target_block(&buf, dir, &qn, &ndirents);
...@@ -178,7 +179,8 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid, ...@@ -178,7 +179,8 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
return PTR_ERR(de); return PTR_ERR(de);
if (ndirents) if (ndirents)
de = find_target_dirent(&qn, (u8 *)de, EROFS_BLKSIZ, ndirents); de = find_target_dirent(&qn, (u8 *)de, i_blocksize(dir),
ndirents);
if (!IS_ERR(de)) { if (!IS_ERR(de)) {
*nid = le64_to_cpu(de->nid); *nid = le64_to_cpu(de->nid);
...@@ -203,16 +205,13 @@ static struct dentry *erofs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -203,16 +205,13 @@ static struct dentry *erofs_lookup(struct inode *dir, struct dentry *dentry,
err = erofs_namei(dir, &dentry->d_name, &nid, &d_type); err = erofs_namei(dir, &dentry->d_name, &nid, &d_type);
if (err == -ENOENT) { if (err == -ENOENT)
/* negative dentry */ /* negative dentry */
inode = NULL; inode = NULL;
} else if (err) { else if (err)
inode = ERR_PTR(err); inode = ERR_PTR(err);
} else { else
erofs_dbg("%s, %pd (nid %llu) found, d_type %u", __func__,
dentry, nid, d_type);
inode = erofs_iget(dir->i_sb, nid); inode = erofs_iget(dir->i_sb, nid);
}
return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry);
} }
......
...@@ -52,18 +52,21 @@ void _erofs_info(struct super_block *sb, const char *function, ...@@ -52,18 +52,21 @@ void _erofs_info(struct super_block *sb, const char *function,
static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata) static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
{ {
size_t len = 1 << EROFS_SB(sb)->blkszbits;
struct erofs_super_block *dsb; struct erofs_super_block *dsb;
u32 expected_crc, crc; u32 expected_crc, crc;
dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, if (len > EROFS_SUPER_OFFSET)
EROFS_BLKSIZ - EROFS_SUPER_OFFSET, GFP_KERNEL); len -= EROFS_SUPER_OFFSET;
dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, len, GFP_KERNEL);
if (!dsb) if (!dsb)
return -ENOMEM; return -ENOMEM;
expected_crc = le32_to_cpu(dsb->checksum); expected_crc = le32_to_cpu(dsb->checksum);
dsb->checksum = 0; dsb->checksum = 0;
/* to allow for x86 boot sectors and other oddities. */ /* to allow for x86 boot sectors and other oddities. */
crc = crc32c(~0, dsb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET); crc = crc32c(~0, dsb, len);
kfree(dsb); kfree(dsb);
if (crc != expected_crc) { if (crc != expected_crc) {
...@@ -123,20 +126,19 @@ static bool check_layout_compatibility(struct super_block *sb, ...@@ -123,20 +126,19 @@ static bool check_layout_compatibility(struct super_block *sb,
return true; return true;
} }
#ifdef CONFIG_EROFS_FS_ZIP
/* read variable-sized metadata, offset will be aligned by 4-byte */ /* read variable-sized metadata, offset will be aligned by 4-byte */
static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf, void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
erofs_off_t *offset, int *lengthp) erofs_off_t *offset, int *lengthp)
{ {
u8 *buffer, *ptr; u8 *buffer, *ptr;
int len, i, cnt; int len, i, cnt;
*offset = round_up(*offset, 4); *offset = round_up(*offset, 4);
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*offset), EROFS_KMAP); ptr = erofs_bread(buf, erofs_blknr(sb, *offset), EROFS_KMAP);
if (IS_ERR(ptr)) if (IS_ERR(ptr))
return ptr; return ptr;
len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(*offset)]); len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(sb, *offset)]);
if (!len) if (!len)
len = U16_MAX + 1; len = U16_MAX + 1;
buffer = kmalloc(len, GFP_KERNEL); buffer = kmalloc(len, GFP_KERNEL);
...@@ -146,19 +148,20 @@ static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf, ...@@ -146,19 +148,20 @@ static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
*lengthp = len; *lengthp = len;
for (i = 0; i < len; i += cnt) { for (i = 0; i < len; i += cnt) {
cnt = min(EROFS_BLKSIZ - (int)erofs_blkoff(*offset), len - i); cnt = min_t(int, sb->s_blocksize - erofs_blkoff(sb, *offset),
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*offset), len - i);
EROFS_KMAP); ptr = erofs_bread(buf, erofs_blknr(sb, *offset), EROFS_KMAP);
if (IS_ERR(ptr)) { if (IS_ERR(ptr)) {
kfree(buffer); kfree(buffer);
return ptr; return ptr;
} }
memcpy(buffer + i, ptr + erofs_blkoff(*offset), cnt); memcpy(buffer + i, ptr + erofs_blkoff(sb, *offset), cnt);
*offset += cnt; *offset += cnt;
} }
return buffer; return buffer;
} }
#ifdef CONFIG_EROFS_FS_ZIP
static int erofs_load_compr_cfgs(struct super_block *sb, static int erofs_load_compr_cfgs(struct super_block *sb,
struct erofs_super_block *dsb) struct erofs_super_block *dsb)
{ {
...@@ -175,6 +178,7 @@ static int erofs_load_compr_cfgs(struct super_block *sb, ...@@ -175,6 +178,7 @@ static int erofs_load_compr_cfgs(struct super_block *sb,
return -EINVAL; return -EINVAL;
} }
erofs_init_metabuf(&buf, sb);
offset = EROFS_SUPER_OFFSET + sbi->sb_size; offset = EROFS_SUPER_OFFSET + sbi->sb_size;
alg = 0; alg = 0;
for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) { for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) {
...@@ -228,10 +232,10 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb, ...@@ -228,10 +232,10 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
struct block_device *bdev; struct block_device *bdev;
void *ptr; void *ptr;
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*pos), EROFS_KMAP); ptr = erofs_read_metabuf(buf, sb, erofs_blknr(sb, *pos), EROFS_KMAP);
if (IS_ERR(ptr)) if (IS_ERR(ptr))
return PTR_ERR(ptr); return PTR_ERR(ptr);
dis = ptr + erofs_blkoff(*pos); dis = ptr + erofs_blkoff(sb, *pos);
if (!dif->path) { if (!dif->path) {
if (!dis->tag[0]) { if (!dis->tag[0]) {
...@@ -248,7 +252,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb, ...@@ -248,7 +252,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
if (IS_ERR(fscache)) if (IS_ERR(fscache))
return PTR_ERR(fscache); return PTR_ERR(fscache);
dif->fscache = fscache; dif->fscache = fscache;
} else { } else if (!sbi->devs->flatdev) {
bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL, bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL,
sb->s_type); sb->s_type);
if (IS_ERR(bdev)) if (IS_ERR(bdev))
...@@ -290,6 +294,9 @@ static int erofs_scan_devices(struct super_block *sb, ...@@ -290,6 +294,9 @@ static int erofs_scan_devices(struct super_block *sb,
if (!ondisk_extradevs) if (!ondisk_extradevs)
return 0; return 0;
if (!sbi->devs->extra_devices && !erofs_is_fscache_mode(sb))
sbi->devs->flatdev = true;
sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1; sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE; pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
down_read(&sbi->devs->rwsem); down_read(&sbi->devs->rwsem);
...@@ -329,7 +336,6 @@ static int erofs_read_superblock(struct super_block *sb) ...@@ -329,7 +336,6 @@ static int erofs_read_superblock(struct super_block *sb)
struct erofs_sb_info *sbi; struct erofs_sb_info *sbi;
struct erofs_buf buf = __EROFS_BUF_INITIALIZER; struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
struct erofs_super_block *dsb; struct erofs_super_block *dsb;
unsigned int blkszbits;
void *data; void *data;
int ret; int ret;
...@@ -348,6 +354,16 @@ static int erofs_read_superblock(struct super_block *sb) ...@@ -348,6 +354,16 @@ static int erofs_read_superblock(struct super_block *sb)
goto out; goto out;
} }
sbi->blkszbits = dsb->blkszbits;
if (sbi->blkszbits < 9 || sbi->blkszbits > PAGE_SHIFT) {
erofs_err(sb, "blkszbits %u isn't supported", sbi->blkszbits);
goto out;
}
if (dsb->dirblkbits) {
erofs_err(sb, "dirblkbits %u isn't supported", dsb->dirblkbits);
goto out;
}
sbi->feature_compat = le32_to_cpu(dsb->feature_compat); sbi->feature_compat = le32_to_cpu(dsb->feature_compat);
if (erofs_sb_has_sb_chksum(sbi)) { if (erofs_sb_has_sb_chksum(sbi)) {
ret = erofs_superblock_csum_verify(sb, data); ret = erofs_superblock_csum_verify(sb, data);
...@@ -356,19 +372,11 @@ static int erofs_read_superblock(struct super_block *sb) ...@@ -356,19 +372,11 @@ static int erofs_read_superblock(struct super_block *sb)
} }
ret = -EINVAL; ret = -EINVAL;
blkszbits = dsb->blkszbits;
/* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
if (blkszbits != LOG_BLOCK_SIZE) {
erofs_err(sb, "blkszbits %u isn't supported on this platform",
blkszbits);
goto out;
}
if (!check_layout_compatibility(sb, dsb)) if (!check_layout_compatibility(sb, dsb))
goto out; goto out;
sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE; sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE;
if (sbi->sb_size > EROFS_BLKSIZ) { if (sbi->sb_size > PAGE_SIZE - EROFS_SUPER_OFFSET) {
erofs_err(sb, "invalid sb_extslots %u (more than a fs block)", erofs_err(sb, "invalid sb_extslots %u (more than a fs block)",
sbi->sb_size); sbi->sb_size);
goto out; goto out;
...@@ -377,20 +385,12 @@ static int erofs_read_superblock(struct super_block *sb) ...@@ -377,20 +385,12 @@ static int erofs_read_superblock(struct super_block *sb)
sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr); sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
#ifdef CONFIG_EROFS_FS_XATTR #ifdef CONFIG_EROFS_FS_XATTR
sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr); sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
sbi->xattr_prefix_start = le32_to_cpu(dsb->xattr_prefix_start);
sbi->xattr_prefix_count = dsb->xattr_prefix_count;
#endif #endif
sbi->islotbits = ilog2(sizeof(struct erofs_inode_compact)); sbi->islotbits = ilog2(sizeof(struct erofs_inode_compact));
sbi->root_nid = le16_to_cpu(dsb->root_nid); sbi->root_nid = le16_to_cpu(dsb->root_nid);
#ifdef CONFIG_EROFS_FS_ZIP sbi->packed_nid = le64_to_cpu(dsb->packed_nid);
sbi->packed_inode = NULL;
if (erofs_sb_has_fragments(sbi) && dsb->packed_nid) {
sbi->packed_inode =
erofs_iget(sb, le64_to_cpu(dsb->packed_nid));
if (IS_ERR(sbi->packed_inode)) {
ret = PTR_ERR(sbi->packed_inode);
goto out;
}
}
#endif
sbi->inos = le64_to_cpu(dsb->inos); sbi->inos = le64_to_cpu(dsb->inos);
sbi->build_time = le64_to_cpu(dsb->build_time); sbi->build_time = le64_to_cpu(dsb->build_time);
...@@ -417,8 +417,6 @@ static int erofs_read_superblock(struct super_block *sb) ...@@ -417,8 +417,6 @@ static int erofs_read_superblock(struct super_block *sb)
/* handle multiple devices */ /* handle multiple devices */
ret = erofs_scan_devices(sb, dsb); ret = erofs_scan_devices(sb, dsb);
if (erofs_sb_has_ztailpacking(sbi))
erofs_info(sb, "EXPERIMENTAL compressed inline data feature in use. Use at your own risk!");
if (erofs_is_fscache_mode(sb)) if (erofs_is_fscache_mode(sb))
erofs_info(sb, "EXPERIMENTAL fscache-based on-demand read feature in use. Use at your own risk!"); erofs_info(sb, "EXPERIMENTAL fscache-based on-demand read feature in use. Use at your own risk!");
if (erofs_sb_has_fragments(sbi)) if (erofs_sb_has_fragments(sbi))
...@@ -733,9 +731,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -733,9 +731,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
sbi->domain_id = ctx->domain_id; sbi->domain_id = ctx->domain_id;
ctx->domain_id = NULL; ctx->domain_id = NULL;
sbi->blkszbits = PAGE_SHIFT;
if (erofs_is_fscache_mode(sb)) { if (erofs_is_fscache_mode(sb)) {
sb->s_blocksize = EROFS_BLKSIZ; sb->s_blocksize = PAGE_SIZE;
sb->s_blocksize_bits = LOG_BLOCK_SIZE; sb->s_blocksize_bits = PAGE_SHIFT;
err = erofs_fscache_register_fs(sb); err = erofs_fscache_register_fs(sb);
if (err) if (err)
...@@ -745,8 +744,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -745,8 +744,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
if (err) if (err)
return err; return err;
} else { } else {
if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) { if (!sb_set_blocksize(sb, PAGE_SIZE)) {
erofs_err(sb, "failed to set erofs blksize"); errorfc(fc, "failed to set initial blksize");
return -EINVAL; return -EINVAL;
} }
...@@ -759,12 +758,24 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -759,12 +758,24 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
if (err) if (err)
return err; return err;
if (test_opt(&sbi->opt, DAX_ALWAYS)) { if (sb->s_blocksize_bits != sbi->blkszbits) {
BUILD_BUG_ON(EROFS_BLKSIZ != PAGE_SIZE); if (erofs_is_fscache_mode(sb)) {
errorfc(fc, "unsupported blksize for fscache mode");
return -EINVAL;
}
if (!sb_set_blocksize(sb, 1 << sbi->blkszbits)) {
errorfc(fc, "failed to set erofs blksize");
return -EINVAL;
}
}
if (test_opt(&sbi->opt, DAX_ALWAYS)) {
if (!sbi->dax_dev) { if (!sbi->dax_dev) {
errorfc(fc, "DAX unsupported by block device. Turning off DAX."); errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
clear_opt(&sbi->opt, DAX_ALWAYS); clear_opt(&sbi->opt, DAX_ALWAYS);
} else if (sbi->blkszbits != PAGE_SHIFT) {
errorfc(fc, "unsupported blocksize for DAX");
clear_opt(&sbi->opt, DAX_ALWAYS);
} }
} }
...@@ -799,10 +810,22 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -799,10 +810,22 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
erofs_shrinker_register(sb); erofs_shrinker_register(sb);
/* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */
if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) {
sbi->packed_inode = erofs_iget(sb, sbi->packed_nid);
if (IS_ERR(sbi->packed_inode)) {
err = PTR_ERR(sbi->packed_inode);
sbi->packed_inode = NULL;
return err;
}
}
err = erofs_init_managed_cache(sb); err = erofs_init_managed_cache(sb);
if (err) if (err)
return err; return err;
err = erofs_xattr_prefixes_init(sb);
if (err)
return err;
err = erofs_register_sysfs(sb); err = erofs_register_sysfs(sb);
if (err) if (err)
return err; return err;
...@@ -962,12 +985,13 @@ static void erofs_put_super(struct super_block *sb) ...@@ -962,12 +985,13 @@ static void erofs_put_super(struct super_block *sb)
erofs_unregister_sysfs(sb); erofs_unregister_sysfs(sb);
erofs_shrinker_unregister(sb); erofs_shrinker_unregister(sb);
erofs_xattr_prefixes_cleanup(sb);
#ifdef CONFIG_EROFS_FS_ZIP #ifdef CONFIG_EROFS_FS_ZIP
iput(sbi->managed_cache); iput(sbi->managed_cache);
sbi->managed_cache = NULL; sbi->managed_cache = NULL;
#endif
iput(sbi->packed_inode); iput(sbi->packed_inode);
sbi->packed_inode = NULL; sbi->packed_inode = NULL;
#endif
erofs_free_dev_context(sbi->devs); erofs_free_dev_context(sbi->devs);
sbi->devs = NULL; sbi->devs = NULL;
erofs_fscache_unregister_fs(sb); erofs_fscache_unregister_fs(sb);
...@@ -1060,7 +1084,7 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -1060,7 +1084,7 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
id = huge_encode_dev(sb->s_bdev->bd_dev); id = huge_encode_dev(sb->s_bdev->bd_dev);
buf->f_type = sb->s_magic; buf->f_type = sb->s_magic;
buf->f_bsize = EROFS_BLKSIZ; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = sbi->total_blocks; buf->f_blocks = sbi->total_blocks;
buf->f_bfree = buf->f_bavail = 0; buf->f_bfree = buf->f_bavail = 0;
......
This diff is collapsed.
...@@ -13,29 +13,6 @@ ...@@ -13,29 +13,6 @@
/* Attribute not found */ /* Attribute not found */
#define ENOATTR ENODATA #define ENOATTR ENODATA
static inline unsigned int inlinexattr_header_size(struct inode *inode)
{
return sizeof(struct erofs_xattr_ibody_header) +
sizeof(u32) * EROFS_I(inode)->xattr_shared_count;
}
static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi,
unsigned int xattr_id)
{
#ifdef CONFIG_EROFS_FS_XATTR
return sbi->xattr_blkaddr +
xattr_id * sizeof(__u32) / EROFS_BLKSIZ;
#else
return 0;
#endif
}
static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi,
unsigned int xattr_id)
{
return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ;
}
#ifdef CONFIG_EROFS_FS_XATTR #ifdef CONFIG_EROFS_FS_XATTR
extern const struct xattr_handler erofs_xattr_user_handler; extern const struct xattr_handler erofs_xattr_user_handler;
extern const struct xattr_handler erofs_xattr_trusted_handler; extern const struct xattr_handler erofs_xattr_trusted_handler;
...@@ -69,9 +46,13 @@ static inline const char *erofs_xattr_prefix(unsigned int idx, ...@@ -69,9 +46,13 @@ static inline const char *erofs_xattr_prefix(unsigned int idx,
extern const struct xattr_handler *erofs_xattr_handlers[]; extern const struct xattr_handler *erofs_xattr_handlers[];
int erofs_xattr_prefixes_init(struct super_block *sb);
void erofs_xattr_prefixes_cleanup(struct super_block *sb);
int erofs_getxattr(struct inode *, int, const char *, void *, size_t); int erofs_getxattr(struct inode *, int, const char *, void *, size_t);
ssize_t erofs_listxattr(struct dentry *, char *, size_t); ssize_t erofs_listxattr(struct dentry *, char *, size_t);
#else #else
static inline int erofs_xattr_prefixes_init(struct super_block *sb) { return 0; }
static inline void erofs_xattr_prefixes_cleanup(struct super_block *sb) {}
static inline int erofs_getxattr(struct inode *inode, int index, static inline int erofs_getxattr(struct inode *inode, int index,
const char *name, void *buffer, const char *name, void *buffer,
size_t buffer_size) size_t buffer_size)
......
...@@ -807,7 +807,7 @@ static int z_erofs_register_pcluster(struct z_erofs_decompress_frontend *fe) ...@@ -807,7 +807,7 @@ static int z_erofs_register_pcluster(struct z_erofs_decompress_frontend *fe)
if (ztailpacking) { if (ztailpacking) {
pcl->obj.index = 0; /* which indicates ztailpacking */ pcl->obj.index = 0; /* which indicates ztailpacking */
pcl->pageofs_in = erofs_blkoff(map->m_pa); pcl->pageofs_in = erofs_blkoff(fe->inode->i_sb, map->m_pa);
pcl->tailpacking_size = map->m_plen; pcl->tailpacking_size = map->m_plen;
} else { } else {
pcl->obj.index = map->m_pa >> PAGE_SHIFT; pcl->obj.index = map->m_pa >> PAGE_SHIFT;
...@@ -930,6 +930,7 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos, ...@@ -930,6 +930,7 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos,
struct page *page, unsigned int pageofs, struct page *page, unsigned int pageofs,
unsigned int len) unsigned int len)
{ {
struct super_block *sb = inode->i_sb;
struct inode *packed_inode = EROFS_I_SB(inode)->packed_inode; struct inode *packed_inode = EROFS_I_SB(inode)->packed_inode;
struct erofs_buf buf = __EROFS_BUF_INITIALIZER; struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
u8 *src, *dst; u8 *src, *dst;
...@@ -938,19 +939,19 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos, ...@@ -938,19 +939,19 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos,
if (!packed_inode) if (!packed_inode)
return -EFSCORRUPTED; return -EFSCORRUPTED;
buf.inode = packed_inode;
pos += EROFS_I(inode)->z_fragmentoff; pos += EROFS_I(inode)->z_fragmentoff;
for (i = 0; i < len; i += cnt) { for (i = 0; i < len; i += cnt) {
cnt = min_t(unsigned int, len - i, cnt = min_t(unsigned int, len - i,
EROFS_BLKSIZ - erofs_blkoff(pos)); sb->s_blocksize - erofs_blkoff(sb, pos));
src = erofs_bread(&buf, packed_inode, src = erofs_bread(&buf, erofs_blknr(sb, pos), EROFS_KMAP);
erofs_blknr(pos), EROFS_KMAP);
if (IS_ERR(src)) { if (IS_ERR(src)) {
erofs_put_metabuf(&buf); erofs_put_metabuf(&buf);
return PTR_ERR(src); return PTR_ERR(src);
} }
dst = kmap_local_page(page); dst = kmap_local_page(page);
memcpy(dst + pageofs + i, src + erofs_blkoff(pos), cnt); memcpy(dst + pageofs + i, src + erofs_blkoff(sb, pos), cnt);
kunmap_local(dst); kunmap_local(dst);
pos += cnt; pos += cnt;
} }
...@@ -978,8 +979,6 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, ...@@ -978,8 +979,6 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe,
if (offset + cur < map->m_la || if (offset + cur < map->m_la ||
offset + cur >= map->m_la + map->m_llen) { offset + cur >= map->m_la + map->m_llen) {
erofs_dbg("out-of-range map @ pos %llu", offset + cur);
if (z_erofs_collector_end(fe)) if (z_erofs_collector_end(fe))
fe->backmost = false; fe->backmost = false;
map->m_la = offset + cur; map->m_la = offset + cur;
...@@ -1005,7 +1004,8 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, ...@@ -1005,7 +1004,8 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe,
void *mp; void *mp;
mp = erofs_read_metabuf(&fe->map.buf, inode->i_sb, mp = erofs_read_metabuf(&fe->map.buf, inode->i_sb,
erofs_blknr(map->m_pa), EROFS_NO_KMAP); erofs_blknr(inode->i_sb, map->m_pa),
EROFS_NO_KMAP);
if (IS_ERR(mp)) { if (IS_ERR(mp)) {
err = PTR_ERR(mp); err = PTR_ERR(mp);
erofs_err(inode->i_sb, erofs_err(inode->i_sb,
...@@ -1103,9 +1103,6 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, ...@@ -1103,9 +1103,6 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe,
if (err) if (err)
z_erofs_page_mark_eio(page); z_erofs_page_mark_eio(page);
z_erofs_onlinepage_endio(page); z_erofs_onlinepage_endio(page);
erofs_dbg("%s, finish page: %pK spiltted: %u map->m_llen %llu",
__func__, page, spiltted, map->m_llen);
return err; return err;
} }
...@@ -1726,11 +1723,11 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, ...@@ -1726,11 +1723,11 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
/* no device id here, thus it will always succeed */ /* no device id here, thus it will always succeed */
mdev = (struct erofs_map_dev) { mdev = (struct erofs_map_dev) {
.m_pa = blknr_to_addr(pcl->obj.index), .m_pa = erofs_pos(sb, pcl->obj.index),
}; };
(void)erofs_map_dev(sb, &mdev); (void)erofs_map_dev(sb, &mdev);
cur = erofs_blknr(mdev.m_pa); cur = erofs_blknr(sb, mdev.m_pa);
end = cur + pcl->pclusterpages; end = cur + pcl->pclusterpages;
do { do {
...@@ -1764,7 +1761,7 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, ...@@ -1764,7 +1761,7 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
last_bdev = mdev.m_bdev; last_bdev = mdev.m_bdev;
bio->bi_iter.bi_sector = (sector_t)cur << bio->bi_iter.bi_sector = (sector_t)cur <<
LOG_SECTORS_PER_BLOCK; (sb->s_blocksize_bits - 9);
bio->bi_private = q[JQ_SUBMIT]; bio->bi_private = q[JQ_SUBMIT];
if (f->readahead) if (f->readahead)
bio->bi_opf |= REQ_RAHEAD; bio->bi_opf |= REQ_RAHEAD;
......
This diff is collapsed.
...@@ -71,8 +71,8 @@ TRACE_EVENT(erofs_fill_inode, ...@@ -71,8 +71,8 @@ TRACE_EVENT(erofs_fill_inode,
TP_fast_assign( TP_fast_assign(
__entry->dev = inode->i_sb->s_dev; __entry->dev = inode->i_sb->s_dev;
__entry->nid = EROFS_I(inode)->nid; __entry->nid = EROFS_I(inode)->nid;
__entry->blkaddr = erofs_blknr(erofs_iloc(inode)); __entry->blkaddr = erofs_blknr(inode->i_sb, erofs_iloc(inode));
__entry->ofs = erofs_blkoff(erofs_iloc(inode)); __entry->ofs = erofs_blkoff(inode->i_sb, erofs_iloc(inode));
), ),
TP_printk("dev = (%d,%d), nid = %llu, blkaddr %u ofs %u", TP_printk("dev = (%d,%d), nid = %llu, blkaddr %u ofs %u",
......
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