Skip to content

Commit a1bafc3

Browse files
lostjefflehsiangkao
authored andcommitted
erofs: support compressed inodes over fscache
Since fscache can utilize iov_iter to write dest buffers, bio_vec can be used in this way too. To simplify this, pseudo bios are prepared and bio_vec will be filled with bio_add_page(). And a common .bi_end_io will be called directly to handle I/O completions. Signed-off-by: Jingbo Xu <[email protected]> Reviewed-by: Gao Xiang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Gao Xiang <[email protected]>
1 parent f2151df commit a1bafc3

File tree

4 files changed

+77
-20
lines changed

4 files changed

+77
-20
lines changed

fs/erofs/fscache.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,53 @@ static int erofs_fscache_read_io_async(struct fscache_cookie *cookie,
174174
return 0;
175175
}
176176

177+
struct erofs_fscache_bio {
178+
struct erofs_fscache_io io;
179+
struct bio bio; /* w/o bdev to share bio_add_page/endio() */
180+
struct bio_vec bvecs[BIO_MAX_VECS];
181+
};
182+
183+
static void erofs_fscache_bio_endio(void *priv,
184+
ssize_t transferred_or_error, bool was_async)
185+
{
186+
struct erofs_fscache_bio *io = priv;
187+
188+
if (IS_ERR_VALUE(transferred_or_error))
189+
io->bio.bi_status = errno_to_blk_status(transferred_or_error);
190+
io->bio.bi_end_io(&io->bio);
191+
BUILD_BUG_ON(offsetof(struct erofs_fscache_bio, io) != 0);
192+
erofs_fscache_io_put(&io->io);
193+
}
194+
195+
struct bio *erofs_fscache_bio_alloc(struct erofs_map_dev *mdev)
196+
{
197+
struct erofs_fscache_bio *io;
198+
199+
io = kmalloc(sizeof(*io), GFP_KERNEL | __GFP_NOFAIL);
200+
bio_init(&io->bio, NULL, io->bvecs, BIO_MAX_VECS, REQ_OP_READ);
201+
io->io.private = mdev->m_fscache->cookie;
202+
io->io.end_io = erofs_fscache_bio_endio;
203+
refcount_set(&io->io.ref, 1);
204+
return &io->bio;
205+
}
206+
207+
void erofs_fscache_submit_bio(struct bio *bio)
208+
{
209+
struct erofs_fscache_bio *io = container_of(bio,
210+
struct erofs_fscache_bio, bio);
211+
int ret;
212+
213+
iov_iter_bvec(&io->io.iter, ITER_DEST, io->bvecs, bio->bi_vcnt,
214+
bio->bi_iter.bi_size);
215+
ret = erofs_fscache_read_io_async(io->io.private,
216+
bio->bi_iter.bi_sector << 9, &io->io);
217+
erofs_fscache_io_put(&io->io);
218+
if (!ret)
219+
return;
220+
bio->bi_status = errno_to_blk_status(ret);
221+
bio->bi_end_io(bio);
222+
}
223+
177224
static int erofs_fscache_meta_read_folio(struct file *data, struct folio *folio)
178225
{
179226
struct erofs_fscache *ctx = folio->mapping->host->i_private;

fs/erofs/inode.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,14 +259,12 @@ static int erofs_fill_inode(struct inode *inode)
259259

260260
if (erofs_inode_is_data_compressed(vi->datalayout)) {
261261
#ifdef CONFIG_EROFS_FS_ZIP
262-
if (!erofs_is_fscache_mode(inode->i_sb)) {
263-
DO_ONCE_LITE_IF(inode->i_sb->s_blocksize != PAGE_SIZE,
264-
erofs_info, inode->i_sb,
265-
"EXPERIMENTAL EROFS subpage compressed block support in use. Use at your own risk!");
266-
inode->i_mapping->a_ops = &z_erofs_aops;
267-
err = 0;
268-
goto out_unlock;
269-
}
262+
DO_ONCE_LITE_IF(inode->i_blkbits != PAGE_SHIFT,
263+
erofs_info, inode->i_sb,
264+
"EXPERIMENTAL EROFS subpage compressed block support in use. Use at your own risk!");
265+
inode->i_mapping->a_ops = &z_erofs_aops;
266+
err = 0;
267+
goto out_unlock;
270268
#endif
271269
err = -EOPNOTSUPP;
272270
goto out_unlock;

fs/erofs/internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ void erofs_fscache_unregister_fs(struct super_block *sb);
512512
struct erofs_fscache *erofs_fscache_register_cookie(struct super_block *sb,
513513
char *name, unsigned int flags);
514514
void erofs_fscache_unregister_cookie(struct erofs_fscache *fscache);
515+
struct bio *erofs_fscache_bio_alloc(struct erofs_map_dev *mdev);
516+
void erofs_fscache_submit_bio(struct bio *bio);
515517
#else
516518
static inline int erofs_fscache_register_fs(struct super_block *sb)
517519
{
@@ -529,6 +531,8 @@ struct erofs_fscache *erofs_fscache_register_cookie(struct super_block *sb,
529531
static inline void erofs_fscache_unregister_cookie(struct erofs_fscache *fscache)
530532
{
531533
}
534+
static inline struct bio *erofs_fscache_bio_alloc(struct erofs_map_dev *mdev) { return NULL; }
535+
static inline void erofs_fscache_submit_bio(struct bio *bio) {}
532536
#endif
533537

534538
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */

fs/erofs/zdata.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,7 @@ static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl,
15611561
qtail[JQ_BYPASS] = &pcl->next;
15621562
}
15631563

1564-
static void z_erofs_submissionqueue_endio(struct bio *bio)
1564+
static void z_erofs_endio(struct bio *bio)
15651565
{
15661566
struct z_erofs_decompressqueue *q = bio->bi_private;
15671567
blk_status_t err = bio->bi_status;
@@ -1582,7 +1582,8 @@ static void z_erofs_submissionqueue_endio(struct bio *bio)
15821582
if (err)
15831583
q->eio = true;
15841584
z_erofs_decompress_kickoff(q, -1);
1585-
bio_put(bio);
1585+
if (bio->bi_bdev)
1586+
bio_put(bio);
15861587
}
15871588

15881589
static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
@@ -1596,7 +1597,6 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
15961597
z_erofs_next_pcluster_t owned_head = f->owned_head;
15971598
/* bio is NULL initially, so no need to initialize last_{index,bdev} */
15981599
erofs_off_t last_pa;
1599-
struct block_device *last_bdev;
16001600
unsigned int nr_bios = 0;
16011601
struct bio *bio = NULL;
16021602
unsigned long pflags;
@@ -1643,9 +1643,13 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
16431643
continue;
16441644

16451645
if (bio && (cur != last_pa ||
1646-
last_bdev != mdev.m_bdev)) {
1647-
submit_bio_retry:
1648-
submit_bio(bio);
1646+
bio->bi_bdev != mdev.m_bdev)) {
1647+
io_retry:
1648+
if (!erofs_is_fscache_mode(sb))
1649+
submit_bio(bio);
1650+
else
1651+
erofs_fscache_submit_bio(bio);
1652+
16491653
if (memstall) {
16501654
psi_memstall_leave(&pflags);
16511655
memstall = 0;
@@ -1660,23 +1664,24 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
16601664
}
16611665

16621666
if (!bio) {
1663-
bio = bio_alloc(mdev.m_bdev, BIO_MAX_VECS,
1664-
REQ_OP_READ, GFP_NOIO);
1665-
bio->bi_end_io = z_erofs_submissionqueue_endio;
1667+
bio = erofs_is_fscache_mode(sb) ?
1668+
erofs_fscache_bio_alloc(&mdev) :
1669+
bio_alloc(mdev.m_bdev, BIO_MAX_VECS,
1670+
REQ_OP_READ, GFP_NOIO);
1671+
bio->bi_end_io = z_erofs_endio;
16661672
bio->bi_iter.bi_sector = cur >> 9;
16671673
bio->bi_private = q[JQ_SUBMIT];
16681674
if (readahead)
16691675
bio->bi_opf |= REQ_RAHEAD;
16701676
++nr_bios;
1671-
last_bdev = mdev.m_bdev;
16721677
}
16731678

16741679
if (cur + bvec.bv_len > end)
16751680
bvec.bv_len = end - cur;
16761681
DBG_BUGON(bvec.bv_len < sb->s_blocksize);
16771682
if (!bio_add_page(bio, bvec.bv_page, bvec.bv_len,
16781683
bvec.bv_offset))
1679-
goto submit_bio_retry;
1684+
goto io_retry;
16801685

16811686
last_pa = cur + bvec.bv_len;
16821687
bypass = false;
@@ -1689,7 +1694,10 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
16891694
} while (owned_head != Z_EROFS_PCLUSTER_TAIL);
16901695

16911696
if (bio) {
1692-
submit_bio(bio);
1697+
if (!erofs_is_fscache_mode(sb))
1698+
submit_bio(bio);
1699+
else
1700+
erofs_fscache_submit_bio(bio);
16931701
if (memstall)
16941702
psi_memstall_leave(&pflags);
16951703
}

0 commit comments

Comments
 (0)