Skip to content

Commit c5aa903

Browse files
committed
erofs: support reading chunk-based uncompressed files
Add runtime support for chunk-based uncompressed files described in the previous patch. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Liu Bo <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Gao Xiang <[email protected]>
1 parent 2a9dc7a commit c5aa903

File tree

3 files changed

+102
-11
lines changed

3 files changed

+102
-11
lines changed

fs/erofs/data.c

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright (C) 2017-2018 HUAWEI, Inc.
44
* https://www.huawei.com/
5+
* Copyright (C) 2021, Alibaba Cloud
56
*/
67
#include "internal.h"
78
#include <linux/prefetch.h>
@@ -36,13 +37,6 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
3637
nblocks = DIV_ROUND_UP(inode->i_size, PAGE_SIZE);
3738
lastblk = nblocks - tailendpacking;
3839

39-
if (offset >= inode->i_size) {
40-
/* leave out-of-bound access unmapped */
41-
map->m_flags = 0;
42-
map->m_plen = 0;
43-
goto out;
44-
}
45-
4640
/* there is no hole in flatmode */
4741
map->m_flags = EROFS_MAP_MAPPED;
4842

@@ -77,14 +71,90 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
7771
goto err_out;
7872
}
7973

80-
out:
8174
map->m_llen = map->m_plen;
82-
8375
err_out:
8476
trace_erofs_map_blocks_flatmode_exit(inode, map, flags, 0);
8577
return err;
8678
}
8779

80+
static int erofs_map_blocks(struct inode *inode,
81+
struct erofs_map_blocks *map, int flags)
82+
{
83+
struct super_block *sb = inode->i_sb;
84+
struct erofs_inode *vi = EROFS_I(inode);
85+
struct erofs_inode_chunk_index *idx;
86+
struct page *page;
87+
u64 chunknr;
88+
unsigned int unit;
89+
erofs_off_t pos;
90+
int err = 0;
91+
92+
if (map->m_la >= inode->i_size) {
93+
/* leave out-of-bound access unmapped */
94+
map->m_flags = 0;
95+
map->m_plen = 0;
96+
goto out;
97+
}
98+
99+
if (vi->datalayout != EROFS_INODE_CHUNK_BASED)
100+
return erofs_map_blocks_flatmode(inode, map, flags);
101+
102+
if (vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)
103+
unit = sizeof(*idx); /* chunk index */
104+
else
105+
unit = EROFS_BLOCK_MAP_ENTRY_SIZE; /* block map */
106+
107+
chunknr = map->m_la >> vi->chunkbits;
108+
pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize +
109+
vi->xattr_isize, unit) + unit * chunknr;
110+
111+
page = erofs_get_meta_page(inode->i_sb, erofs_blknr(pos));
112+
if (IS_ERR(page))
113+
return PTR_ERR(page);
114+
115+
map->m_la = chunknr << vi->chunkbits;
116+
map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
117+
roundup(inode->i_size - map->m_la, EROFS_BLKSIZ));
118+
119+
/* handle block map */
120+
if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
121+
__le32 *blkaddr = page_address(page) + erofs_blkoff(pos);
122+
123+
if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
124+
map->m_flags = 0;
125+
} else {
126+
map->m_pa = blknr_to_addr(le32_to_cpu(*blkaddr));
127+
map->m_flags = EROFS_MAP_MAPPED;
128+
}
129+
goto out_unlock;
130+
}
131+
/* parse chunk indexes */
132+
idx = page_address(page) + erofs_blkoff(pos);
133+
switch (le32_to_cpu(idx->blkaddr)) {
134+
case EROFS_NULL_ADDR:
135+
map->m_flags = 0;
136+
break;
137+
default:
138+
/* only one device is supported for now */
139+
if (idx->device_id) {
140+
erofs_err(sb, "invalid device id %u @ %llu for nid %llu",
141+
le16_to_cpu(idx->device_id),
142+
chunknr, vi->nid);
143+
err = -EFSCORRUPTED;
144+
goto out_unlock;
145+
}
146+
map->m_pa = blknr_to_addr(le32_to_cpu(idx->blkaddr));
147+
map->m_flags = EROFS_MAP_MAPPED;
148+
break;
149+
}
150+
out_unlock:
151+
unlock_page(page);
152+
put_page(page);
153+
out:
154+
map->m_llen = map->m_plen;
155+
return err;
156+
}
157+
88158
static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
89159
unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
90160
{
@@ -94,7 +164,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
94164
map.m_la = offset;
95165
map.m_llen = length;
96166

97-
ret = erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW);
167+
ret = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW);
98168
if (ret < 0)
99169
return ret;
100170

fs/erofs/inode.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright (C) 2017-2018 HUAWEI, Inc.
44
* https://www.huawei.com/
5+
* Copyright (C) 2021, Alibaba Cloud
56
*/
67
#include "xattr.h"
78

@@ -122,7 +123,9 @@ static struct page *erofs_read_inode(struct inode *inode,
122123
/* total blocks for compressed files */
123124
if (erofs_inode_is_data_compressed(vi->datalayout))
124125
nblks = le32_to_cpu(die->i_u.compressed_blocks);
125-
126+
else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
127+
/* fill chunked inode summary info */
128+
vi->chunkformat = le16_to_cpu(die->i_u.c.format);
126129
kfree(copied);
127130
break;
128131
case EROFS_INODE_LAYOUT_COMPACT:
@@ -160,6 +163,8 @@ static struct page *erofs_read_inode(struct inode *inode,
160163
inode->i_size = le32_to_cpu(dic->i_size);
161164
if (erofs_inode_is_data_compressed(vi->datalayout))
162165
nblks = le32_to_cpu(dic->i_u.compressed_blocks);
166+
else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
167+
vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
163168
break;
164169
default:
165170
erofs_err(inode->i_sb,
@@ -169,6 +174,17 @@ static struct page *erofs_read_inode(struct inode *inode,
169174
goto err_out;
170175
}
171176

177+
if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
178+
if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_ALL)) {
179+
erofs_err(inode->i_sb,
180+
"unsupported chunk format %x of nid %llu",
181+
vi->chunkformat, vi->nid);
182+
err = -EOPNOTSUPP;
183+
goto err_out;
184+
}
185+
vi->chunkbits = LOG_BLOCK_SIZE +
186+
(vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
187+
}
172188
inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
173189
inode->i_atime.tv_sec = inode->i_ctime.tv_sec;
174190
inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec;

fs/erofs/internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright (C) 2017-2018 HUAWEI, Inc.
44
* https://www.huawei.com/
5+
* Copyright (C) 2021, Alibaba Cloud
56
*/
67
#ifndef __EROFS_INTERNAL_H
78
#define __EROFS_INTERNAL_H
@@ -261,6 +262,10 @@ struct erofs_inode {
261262

262263
union {
263264
erofs_blk_t raw_blkaddr;
265+
struct {
266+
unsigned short chunkformat;
267+
unsigned char chunkbits;
268+
};
264269
#ifdef CONFIG_EROFS_FS_ZIP
265270
struct {
266271
unsigned short z_advise;

0 commit comments

Comments
 (0)