Skip to content

Commit 3b428e1

Browse files
committed
Merge tag 'erofs-for-6.16-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs fixes from Gao Xiang: "Fix for a cache aliasing issue by adding missing flush_dcache_folio(), which causes execution failures on some arm32 setups. Fix for large compressed fragments, which could be generated by -Eall-fragments option (but should be rare) and was rejected by mistake due to an on-disk hardening commit. The remaining ones are small fixes. Summary: - Address cache aliasing for mappable page cache folios - Allow readdir() to be interrupted - Fix large fragment handling which was errored out by mistake - Add missing tracepoints - Use memcpy_to_folio() to replace copy_to_iter() for inline data" * tag 'erofs-for-6.16-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: fix large fragment handling erofs: allow readdir() to be interrupted erofs: address D-cache aliasing erofs: use memcpy_to_folio() to replace copy_to_iter() erofs: fix to add missing tracepoint in erofs_read_folio() erofs: fix to add missing tracepoint in erofs_readahead()
2 parents 4412b8b + b44686c commit 3b428e1

File tree

7 files changed

+41
-35
lines changed

7 files changed

+41
-35
lines changed

fs/erofs/data.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,11 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
214214

215215
/*
216216
* bit 30: I/O error occurred on this folio
217+
* bit 29: CPU has dirty data in D-cache (needs aliasing handling);
217218
* bit 0 - 29: remaining parts to complete this folio
218219
*/
219-
#define EROFS_ONLINEFOLIO_EIO (1 << 30)
220+
#define EROFS_ONLINEFOLIO_EIO 30
221+
#define EROFS_ONLINEFOLIO_DIRTY 29
220222

221223
void erofs_onlinefolio_init(struct folio *folio)
222224
{
@@ -233,19 +235,23 @@ void erofs_onlinefolio_split(struct folio *folio)
233235
atomic_inc((atomic_t *)&folio->private);
234236
}
235237

236-
void erofs_onlinefolio_end(struct folio *folio, int err)
238+
void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty)
237239
{
238240
int orig, v;
239241

240242
do {
241243
orig = atomic_read((atomic_t *)&folio->private);
242-
v = (orig - 1) | (err ? EROFS_ONLINEFOLIO_EIO : 0);
244+
DBG_BUGON(orig <= 0);
245+
v = dirty << EROFS_ONLINEFOLIO_DIRTY;
246+
v |= (orig - 1) | (!!err << EROFS_ONLINEFOLIO_EIO);
243247
} while (atomic_cmpxchg((atomic_t *)&folio->private, orig, v) != orig);
244248

245-
if (v & ~EROFS_ONLINEFOLIO_EIO)
249+
if (v & (BIT(EROFS_ONLINEFOLIO_DIRTY) - 1))
246250
return;
247251
folio->private = 0;
248-
folio_end_read(folio, !(v & EROFS_ONLINEFOLIO_EIO));
252+
if (v & BIT(EROFS_ONLINEFOLIO_DIRTY))
253+
flush_dcache_folio(folio);
254+
folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO)));
249255
}
250256

251257
static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
@@ -351,11 +357,16 @@ int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
351357
*/
352358
static int erofs_read_folio(struct file *file, struct folio *folio)
353359
{
360+
trace_erofs_read_folio(folio, true);
361+
354362
return iomap_read_folio(folio, &erofs_iomap_ops);
355363
}
356364

357365
static void erofs_readahead(struct readahead_control *rac)
358366
{
367+
trace_erofs_readahead(rac->mapping->host, readahead_index(rac),
368+
readahead_count(rac), true);
369+
359370
return iomap_readahead(rac, &erofs_iomap_ops);
360371
}
361372

fs/erofs/decompressor.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,11 @@ static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
301301
cur = min(cur, rq->outputsize);
302302
if (cur && rq->out[0]) {
303303
kin = kmap_local_page(rq->in[nrpages_in - 1]);
304-
if (rq->out[0] == rq->in[nrpages_in - 1]) {
304+
if (rq->out[0] == rq->in[nrpages_in - 1])
305305
memmove(kin + rq->pageofs_out, kin + pi, cur);
306-
flush_dcache_page(rq->out[0]);
307-
} else {
306+
else
308307
memcpy_to_page(rq->out[0], rq->pageofs_out,
309308
kin + pi, cur);
310-
}
311309
kunmap_local(kin);
312310
}
313311
rq->outputsize -= cur;
@@ -325,14 +323,12 @@ static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
325323
po = (rq->pageofs_out + cur + pi) & ~PAGE_MASK;
326324
DBG_BUGON(no >= nrpages_out);
327325
cnt = min(insz - pi, PAGE_SIZE - po);
328-
if (rq->out[no] == rq->in[ni]) {
326+
if (rq->out[no] == rq->in[ni])
329327
memmove(kin + po,
330328
kin + rq->pageofs_in + pi, cnt);
331-
flush_dcache_page(rq->out[no]);
332-
} else if (rq->out[no]) {
329+
else if (rq->out[no])
333330
memcpy_to_page(rq->out[no], po,
334331
kin + rq->pageofs_in + pi, cnt);
335-
}
336332
pi += cnt;
337333
} while (pi < insz);
338334
kunmap_local(kin);

fs/erofs/dir.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
5858
struct erofs_dirent *de;
5959
unsigned int nameoff, maxsize;
6060

61+
if (fatal_signal_pending(current)) {
62+
err = -ERESTARTSYS;
63+
break;
64+
}
65+
6166
de = erofs_bread(&buf, dbstart, true);
6267
if (IS_ERR(de)) {
6368
erofs_err(sb, "failed to readdir of logical block %llu of nid %llu",
@@ -88,6 +93,7 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
8893
break;
8994
ctx->pos = dbstart + maxsize;
9095
ofs = 0;
96+
cond_resched();
9197
}
9298
erofs_put_metabuf(&buf);
9399
if (EROFS_I(dir)->dot_omitted && ctx->pos == dir->i_size) {

fs/erofs/fileio.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret)
3838
} else {
3939
bio_for_each_folio_all(fi, &rq->bio) {
4040
DBG_BUGON(folio_test_uptodate(fi.folio));
41-
erofs_onlinefolio_end(fi.folio, ret);
41+
erofs_onlinefolio_end(fi.folio, ret, false);
4242
}
4343
}
4444
bio_uninit(&rq->bio);
@@ -96,8 +96,6 @@ static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *folio)
9696
struct erofs_map_blocks *map = &io->map;
9797
unsigned int cur = 0, end = folio_size(folio), len, attached = 0;
9898
loff_t pos = folio_pos(folio), ofs;
99-
struct iov_iter iter;
100-
struct bio_vec bv;
10199
int err = 0;
102100

103101
erofs_onlinefolio_init(folio);
@@ -122,13 +120,7 @@ static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *folio)
122120
err = PTR_ERR(src);
123121
break;
124122
}
125-
bvec_set_folio(&bv, folio, len, cur);
126-
iov_iter_bvec(&iter, ITER_DEST, &bv, 1, len);
127-
if (copy_to_iter(src, len, &iter) != len) {
128-
erofs_put_metabuf(&buf);
129-
err = -EIO;
130-
break;
131-
}
123+
memcpy_to_folio(folio, cur, src, len);
132124
erofs_put_metabuf(&buf);
133125
} else if (!(map->m_flags & EROFS_MAP_MAPPED)) {
134126
folio_zero_segment(folio, cur, cur + len);
@@ -162,7 +154,7 @@ static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *folio)
162154
}
163155
cur += len;
164156
}
165-
erofs_onlinefolio_end(folio, err);
157+
erofs_onlinefolio_end(folio, err, false);
166158
return err;
167159
}
168160

fs/erofs/internal.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,12 @@ static inline struct folio *erofs_grab_folio_nowait(struct address_space *as,
315315
/* The length of extent is full */
316316
#define EROFS_MAP_FULL_MAPPED 0x0008
317317
/* Located in the special packed inode */
318-
#define EROFS_MAP_FRAGMENT 0x0010
318+
#define __EROFS_MAP_FRAGMENT 0x0010
319319
/* The extent refers to partial decompressed data */
320320
#define EROFS_MAP_PARTIAL_REF 0x0020
321321

322+
#define EROFS_MAP_FRAGMENT (EROFS_MAP_MAPPED | __EROFS_MAP_FRAGMENT)
323+
322324
struct erofs_map_blocks {
323325
struct erofs_buf buf;
324326

@@ -390,7 +392,7 @@ int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
390392
int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map);
391393
void erofs_onlinefolio_init(struct folio *folio);
392394
void erofs_onlinefolio_split(struct folio *folio);
393-
void erofs_onlinefolio_end(struct folio *folio, int err);
395+
void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty);
394396
struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid);
395397
int erofs_getattr(struct mnt_idmap *idmap, const struct path *path,
396398
struct kstat *stat, u32 request_mask,

fs/erofs/zdata.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ static int z_erofs_scan_folio(struct z_erofs_frontend *f,
10341034
if (!(map->m_flags & EROFS_MAP_MAPPED)) {
10351035
folio_zero_segment(folio, cur, end);
10361036
tight = false;
1037-
} else if (map->m_flags & EROFS_MAP_FRAGMENT) {
1037+
} else if (map->m_flags & __EROFS_MAP_FRAGMENT) {
10381038
erofs_off_t fpos = offset + cur - map->m_la;
10391039

10401040
err = z_erofs_read_fragment(inode->i_sb, folio, cur,
@@ -1091,7 +1091,7 @@ static int z_erofs_scan_folio(struct z_erofs_frontend *f,
10911091
tight = (bs == PAGE_SIZE);
10921092
}
10931093
} while ((end = cur) > 0);
1094-
erofs_onlinefolio_end(folio, err);
1094+
erofs_onlinefolio_end(folio, err, false);
10951095
return err;
10961096
}
10971097

@@ -1196,7 +1196,7 @@ static void z_erofs_fill_other_copies(struct z_erofs_backend *be, int err)
11961196
cur += len;
11971197
}
11981198
kunmap_local(dst);
1199-
erofs_onlinefolio_end(page_folio(bvi->bvec.page), err);
1199+
erofs_onlinefolio_end(page_folio(bvi->bvec.page), err, true);
12001200
list_del(p);
12011201
kfree(bvi);
12021202
}
@@ -1355,7 +1355,7 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err)
13551355

13561356
DBG_BUGON(z_erofs_page_is_invalidated(page));
13571357
if (!z_erofs_is_shortlived_page(page)) {
1358-
erofs_onlinefolio_end(page_folio(page), err);
1358+
erofs_onlinefolio_end(page_folio(page), err, true);
13591359
continue;
13601360
}
13611361
if (pcl->algorithmformat != Z_EROFS_COMPRESSION_LZ4) {

fs/erofs/zmap.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
413413
!vi->z_tailextent_headlcn) {
414414
map->m_la = 0;
415415
map->m_llen = inode->i_size;
416-
map->m_flags = EROFS_MAP_MAPPED |
417-
EROFS_MAP_FULL_MAPPED | EROFS_MAP_FRAGMENT;
416+
map->m_flags = EROFS_MAP_FRAGMENT;
418417
return 0;
419418
}
420419
initial_lcn = ofs >> lclusterbits;
@@ -489,7 +488,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
489488
goto unmap_out;
490489
}
491490
} else if (fragment && m.lcn == vi->z_tailextent_headlcn) {
492-
map->m_flags |= EROFS_MAP_FRAGMENT;
491+
map->m_flags = EROFS_MAP_FRAGMENT;
493492
} else {
494493
map->m_pa = erofs_pos(sb, m.pblk);
495494
err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
@@ -617,7 +616,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
617616
if (lstart < lend) {
618617
map->m_la = lstart;
619618
if (last && (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)) {
620-
map->m_flags |= EROFS_MAP_MAPPED | EROFS_MAP_FRAGMENT;
619+
map->m_flags = EROFS_MAP_FRAGMENT;
621620
vi->z_fragmentoff = map->m_plen;
622621
if (recsz > offsetof(struct z_erofs_extent, pstart_lo))
623622
vi->z_fragmentoff |= map->m_pa << 32;
@@ -797,7 +796,7 @@ static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset,
797796
iomap->length = map.m_llen;
798797
if (map.m_flags & EROFS_MAP_MAPPED) {
799798
iomap->type = IOMAP_MAPPED;
800-
iomap->addr = map.m_flags & EROFS_MAP_FRAGMENT ?
799+
iomap->addr = map.m_flags & __EROFS_MAP_FRAGMENT ?
801800
IOMAP_NULL_ADDR : map.m_pa;
802801
} else {
803802
iomap->type = IOMAP_HOLE;

0 commit comments

Comments
 (0)