Skip to content

Commit b2e7b0f

Browse files
committed
Merge tag 'erofs-for-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs updates from Gao Xiang: "In this cycle, EROFS 48-bit block addressing is available to support massive datasets for model training and other large data archive use cases. In addition, byte-oriented encoded extents have been supported to reduce metadata sizes when using large configurations as well as to improve Zstd compression speed. There are some bugfixes and cleanups as usual. Summary: - Support 48-bit block addressing for large images - Introduce encoded extents to reduce metadata on larger pclusters - Enable unaligned compressed data to improve Zstd compression speed - Allow 16-byte volume names again - Minor cleanups" * tag 'erofs-for-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: enable 48-bit layout support erofs: support unaligned encoded data erofs: implement encoded extent metadata erofs: add encoded extent on-disk definition erofs: initialize decompression early erofs: support dot-omitted directories erofs: implement 48-bit block addressing for unencoded inodes erofs: add 48-bit block addressing on-disk support erofs: simplify erofs_{read,fill}_inode() erofs: get rid of erofs_map_blocks_flatmode() erofs: move {in,out}pages into struct z_erofs_decompress_req erofs: clean up header parsing for ztailpacking and fragments erofs: simplify tail inline pcluster handling erofs: allow 16-byte volume name again erofs: get rid of erofs_kmap_type erofs: use Z_EROFS_LCLUSTER_TYPE_MAX to simplify switches
2 parents ef479de + 0f24e3c commit b2e7b0f

20 files changed

+579
-571
lines changed

fs/erofs/Kconfig

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ config EROFS_FS
1313
smartphones with Android OS, LiveCDs and high-density hosts with
1414
numerous containers;
1515

16-
It also provides fixed-sized output compression support in order to
17-
improve storage density as well as keep relatively higher compression
18-
ratios and implements in-place decompression to reuse the file page
19-
for compressed data temporarily with proper strategies, which is
20-
quite useful to ensure guaranteed end-to-end runtime decompression
21-
performance under extremely memory pressure without extra cost.
16+
It also provides transparent compression and deduplication support to
17+
improve storage density and maintain relatively high compression
18+
ratios, and it implements in-place decompression to temporarily reuse
19+
page cache for compressed data using proper strategies, which is
20+
quite useful for ensuring guaranteed end-to-end runtime decompression
21+
performance under extreme memory pressure without extra cost.
2222

2323
See the documentation at <file:Documentation/filesystems/erofs.rst>
2424
and the web pages at <https://erofs.docs.kernel.org> for more details.
@@ -97,7 +97,7 @@ config EROFS_FS_ZIP
9797
select LZ4_DECOMPRESS
9898
default y
9999
help
100-
Enable fixed-sized output compression for EROFS.
100+
Enable transparent compression support for EROFS file systems.
101101

102102
If you don't want to enable compression feature, say N.
103103

fs/erofs/compress.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
struct z_erofs_decompress_req {
1212
struct super_block *sb;
1313
struct page **in, **out;
14+
unsigned int inpages, outpages;
1415
unsigned short pageofs_in, pageofs_out;
1516
unsigned int inputsize, outputsize;
1617

@@ -59,7 +60,6 @@ extern const struct z_erofs_decompressor *z_erofs_decomp[];
5960

6061
struct z_erofs_stream_dctx {
6162
struct z_erofs_decompress_req *rq;
62-
unsigned int inpages, outpages; /* # of {en,de}coded pages */
6363
int no, ni; /* the current {en,de}coded page # */
6464

6565
unsigned int avail_out; /* remaining bytes in the decoded buffer */

fs/erofs/data.c

Lines changed: 64 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ void erofs_put_metabuf(struct erofs_buf *buf)
2525
buf->page = NULL;
2626
}
2727

28-
void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset,
29-
enum erofs_kmap_type type)
28+
void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap)
3029
{
3130
pgoff_t index = offset >> PAGE_SHIFT;
3231
struct folio *folio = NULL;
@@ -43,10 +42,10 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset,
4342
return folio;
4443
}
4544
buf->page = folio_file_page(folio, index);
46-
if (!buf->base && type == EROFS_KMAP)
47-
buf->base = kmap_local_page(buf->page);
48-
if (type == EROFS_NO_KMAP)
45+
if (!need_kmap)
4946
return NULL;
47+
if (!buf->base)
48+
buf->base = kmap_local_page(buf->page);
5049
return buf->base + (offset & ~PAGE_MASK);
5150
}
5251

@@ -65,64 +64,47 @@ void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
6564
}
6665

6766
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
68-
erofs_off_t offset, enum erofs_kmap_type type)
67+
erofs_off_t offset, bool need_kmap)
6968
{
7069
erofs_init_metabuf(buf, sb);
71-
return erofs_bread(buf, offset, type);
72-
}
73-
74-
static int erofs_map_blocks_flatmode(struct inode *inode,
75-
struct erofs_map_blocks *map)
76-
{
77-
struct erofs_inode *vi = EROFS_I(inode);
78-
struct super_block *sb = inode->i_sb;
79-
bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
80-
erofs_blk_t lastblk = erofs_iblks(inode) - tailendpacking;
81-
82-
map->m_flags = EROFS_MAP_MAPPED; /* no hole in flat inodes */
83-
if (map->m_la < erofs_pos(sb, lastblk)) {
84-
map->m_pa = erofs_pos(sb, vi->raw_blkaddr) + map->m_la;
85-
map->m_plen = erofs_pos(sb, lastblk) - map->m_la;
86-
} else {
87-
DBG_BUGON(!tailendpacking);
88-
map->m_pa = erofs_iloc(inode) + vi->inode_isize +
89-
vi->xattr_isize + erofs_blkoff(sb, map->m_la);
90-
map->m_plen = inode->i_size - map->m_la;
91-
92-
/* inline data should be located in the same meta block */
93-
if (erofs_blkoff(sb, map->m_pa) + map->m_plen > sb->s_blocksize) {
94-
erofs_err(sb, "inline data across blocks @ nid %llu", vi->nid);
95-
DBG_BUGON(1);
96-
return -EFSCORRUPTED;
97-
}
98-
map->m_flags |= EROFS_MAP_META;
99-
}
100-
return 0;
70+
return erofs_bread(buf, offset, need_kmap);
10171
}
10272

10373
int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
10474
{
75+
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
10576
struct super_block *sb = inode->i_sb;
77+
unsigned int unit, blksz = sb->s_blocksize;
10678
struct erofs_inode *vi = EROFS_I(inode);
10779
struct erofs_inode_chunk_index *idx;
108-
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
109-
u64 chunknr;
110-
unsigned int unit;
80+
erofs_blk_t startblk, addrmask;
81+
bool tailpacking;
11182
erofs_off_t pos;
112-
void *kaddr;
83+
u64 chunknr;
11384
int err = 0;
11485

11586
trace_erofs_map_blocks_enter(inode, map, 0);
11687
map->m_deviceid = 0;
117-
if (map->m_la >= inode->i_size) {
118-
/* leave out-of-bound access unmapped */
119-
map->m_flags = 0;
120-
map->m_plen = map->m_llen;
88+
map->m_flags = 0;
89+
if (map->m_la >= inode->i_size)
12190
goto out;
122-
}
12391

12492
if (vi->datalayout != EROFS_INODE_CHUNK_BASED) {
125-
err = erofs_map_blocks_flatmode(inode, map);
93+
tailpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
94+
if (!tailpacking && vi->startblk == EROFS_NULL_ADDR)
95+
goto out;
96+
pos = erofs_pos(sb, erofs_iblks(inode) - tailpacking);
97+
98+
map->m_flags = EROFS_MAP_MAPPED;
99+
if (map->m_la < pos) {
100+
map->m_pa = erofs_pos(sb, vi->startblk) + map->m_la;
101+
map->m_llen = pos - map->m_la;
102+
} else {
103+
map->m_pa = erofs_iloc(inode) + vi->inode_isize +
104+
vi->xattr_isize + erofs_blkoff(sb, map->m_la);
105+
map->m_llen = inode->i_size - map->m_la;
106+
map->m_flags |= EROFS_MAP_META;
107+
}
126108
goto out;
127109
}
128110

@@ -135,45 +117,44 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
135117
pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
136118
vi->xattr_isize, unit) + unit * chunknr;
137119

138-
kaddr = erofs_read_metabuf(&buf, sb, pos, EROFS_KMAP);
139-
if (IS_ERR(kaddr)) {
140-
err = PTR_ERR(kaddr);
120+
idx = erofs_read_metabuf(&buf, sb, pos, true);
121+
if (IS_ERR(idx)) {
122+
err = PTR_ERR(idx);
141123
goto out;
142124
}
143125
map->m_la = chunknr << vi->chunkbits;
144-
map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
145-
round_up(inode->i_size - map->m_la, sb->s_blocksize));
146-
147-
/* handle block map */
148-
if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
149-
__le32 *blkaddr = kaddr;
150-
151-
if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
152-
map->m_flags = 0;
153-
} else {
154-
map->m_pa = erofs_pos(sb, le32_to_cpu(*blkaddr));
126+
map->m_llen = min_t(erofs_off_t, 1UL << vi->chunkbits,
127+
round_up(inode->i_size - map->m_la, blksz));
128+
if (vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES) {
129+
addrmask = (vi->chunkformat & EROFS_CHUNK_FORMAT_48BIT) ?
130+
BIT_ULL(48) - 1 : BIT_ULL(32) - 1;
131+
startblk = (((u64)le16_to_cpu(idx->startblk_hi) << 32) |
132+
le32_to_cpu(idx->startblk_lo)) & addrmask;
133+
if ((startblk ^ EROFS_NULL_ADDR) & addrmask) {
134+
map->m_deviceid = le16_to_cpu(idx->device_id) &
135+
EROFS_SB(sb)->device_id_mask;
136+
map->m_pa = erofs_pos(sb, startblk);
137+
map->m_flags = EROFS_MAP_MAPPED;
138+
}
139+
} else {
140+
startblk = le32_to_cpu(*(__le32 *)idx);
141+
if (startblk != (u32)EROFS_NULL_ADDR) {
142+
map->m_pa = erofs_pos(sb, startblk);
155143
map->m_flags = EROFS_MAP_MAPPED;
156144
}
157-
goto out_unlock;
158-
}
159-
/* parse chunk indexes */
160-
idx = kaddr;
161-
switch (le32_to_cpu(idx->blkaddr)) {
162-
case EROFS_NULL_ADDR:
163-
map->m_flags = 0;
164-
break;
165-
default:
166-
map->m_deviceid = le16_to_cpu(idx->device_id) &
167-
EROFS_SB(sb)->device_id_mask;
168-
map->m_pa = erofs_pos(sb, le32_to_cpu(idx->blkaddr));
169-
map->m_flags = EROFS_MAP_MAPPED;
170-
break;
171145
}
172-
out_unlock:
173146
erofs_put_metabuf(&buf);
174147
out:
175-
if (!err)
176-
map->m_llen = map->m_plen;
148+
if (!err) {
149+
map->m_plen = map->m_llen;
150+
/* inline data should be located in the same meta block */
151+
if ((map->m_flags & EROFS_MAP_META) &&
152+
erofs_blkoff(sb, map->m_pa) + map->m_plen > blksz) {
153+
erofs_err(sb, "inline data across blocks @ nid %llu", vi->nid);
154+
DBG_BUGON(1);
155+
return -EFSCORRUPTED;
156+
}
157+
}
177158
trace_erofs_map_blocks_exit(inode, map, 0, err);
178159
return err;
179160
}
@@ -192,7 +173,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
192173
{
193174
struct erofs_dev_context *devs = EROFS_SB(sb)->devs;
194175
struct erofs_device_info *dif;
195-
erofs_off_t startoff, length;
176+
erofs_off_t startoff;
196177
int id;
197178

198179
erofs_fill_from_devinfo(map, sb, &EROFS_SB(sb)->dif0);
@@ -205,7 +186,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
205186
return -ENODEV;
206187
}
207188
if (devs->flatdev) {
208-
map->m_pa += erofs_pos(sb, dif->mapped_blkaddr);
189+
map->m_pa += erofs_pos(sb, dif->uniaddr);
209190
up_read(&devs->rwsem);
210191
return 0;
211192
}
@@ -214,13 +195,12 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
214195
} else if (devs->extra_devices && !devs->flatdev) {
215196
down_read(&devs->rwsem);
216197
idr_for_each_entry(&devs->tree, dif, id) {
217-
if (!dif->mapped_blkaddr)
198+
if (!dif->uniaddr)
218199
continue;
219200

220-
startoff = erofs_pos(sb, dif->mapped_blkaddr);
221-
length = erofs_pos(sb, dif->blocks);
201+
startoff = erofs_pos(sb, dif->uniaddr);
222202
if (map->m_pa >= startoff &&
223-
map->m_pa < startoff + length) {
203+
map->m_pa < startoff + erofs_pos(sb, dif->blocks)) {
224204
map->m_pa -= startoff;
225205
erofs_fill_from_devinfo(map, sb, dif);
226206
break;
@@ -312,7 +292,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
312292
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
313293

314294
iomap->type = IOMAP_INLINE;
315-
ptr = erofs_read_metabuf(&buf, sb, mdev.m_pa, EROFS_KMAP);
295+
ptr = erofs_read_metabuf(&buf, sb, mdev.m_pa, true);
316296
if (IS_ERR(ptr))
317297
return PTR_ERR(ptr);
318298
iomap->inline_data = ptr;

0 commit comments

Comments
 (0)