fs/erofs/fileio.c

Source file repositories/reference/linux-study-clean/fs/erofs/fileio.c

File Facts

System
Linux kernel
Corpus path
fs/erofs/fileio.c
Extension
.c
Size
5336 bytes
Lines
197
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct erofs_fileio_rq {
	struct bio_vec bvecs[16];
	struct bio bio;
	struct kiocb iocb;
	struct super_block *sb;
	refcount_t ref;
};

struct erofs_fileio {
	struct erofs_map_blocks map;
	struct erofs_map_dev dev;
	struct erofs_fileio_rq *rq;
};

static void erofs_fileio_ki_complete(struct kiocb *iocb, long ret)
{
	struct erofs_fileio_rq *rq =
			container_of(iocb, struct erofs_fileio_rq, iocb);
	struct folio_iter fi;

	if (ret >= 0 && ret != rq->bio.bi_iter.bi_size)
		ret = -EIO;
	if (!rq->bio.bi_end_io) {
		bio_for_each_folio_all(fi, &rq->bio) {
			DBG_BUGON(folio_test_uptodate(fi.folio));
			erofs_onlinefolio_end(fi.folio, ret < 0, false);
		}
	} else if (ret < 0 && !rq->bio.bi_status) {
		rq->bio.bi_status = errno_to_blk_status(ret);
	}
	bio_endio(&rq->bio);
	bio_uninit(&rq->bio);
	if (refcount_dec_and_test(&rq->ref))
		kfree(rq);
}

static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
{
	struct iov_iter iter;
	ssize_t ret;

	if (!rq)
		return;
	rq->iocb.ki_pos = rq->bio.bi_iter.bi_sector << SECTOR_SHIFT;
	rq->iocb.ki_ioprio = get_current_ioprio();
	rq->iocb.ki_complete = erofs_fileio_ki_complete;
	if (test_opt(&EROFS_SB(rq->sb)->opt, DIRECT_IO) &&
	    rq->iocb.ki_filp->f_mode & FMODE_CAN_ODIRECT)
		rq->iocb.ki_flags = IOCB_DIRECT;
	iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt,
		      rq->bio.bi_iter.bi_size);
	scoped_with_creds(rq->iocb.ki_filp->f_cred)
		ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
	if (ret != -EIOCBQUEUED)
		erofs_fileio_ki_complete(&rq->iocb, ret);
	if (refcount_dec_and_test(&rq->ref))
		kfree(rq);
}

static struct erofs_fileio_rq *erofs_fileio_rq_alloc(struct erofs_map_dev *mdev)
{
	struct erofs_fileio_rq *rq = kzalloc_obj(*rq, GFP_KERNEL | __GFP_NOFAIL);

	bio_init(&rq->bio, NULL, rq->bvecs, ARRAY_SIZE(rq->bvecs), REQ_OP_READ);
	rq->iocb.ki_filp = mdev->m_dif->file;
	rq->sb = mdev->m_sb;
	refcount_set(&rq->ref, 2);
	return rq;
}

struct bio *erofs_fileio_bio_alloc(struct erofs_map_dev *mdev)
{
	return &erofs_fileio_rq_alloc(mdev)->bio;
}

void erofs_fileio_submit_bio(struct bio *bio)
{
	return erofs_fileio_rq_submit(container_of(bio, struct erofs_fileio_rq,
						   bio));
}

static int erofs_fileio_scan_folio(struct erofs_fileio *io,
				   struct inode *inode, struct folio *folio)
{
	struct erofs_map_blocks *map = &io->map;
	unsigned int cur = 0, end = folio_size(folio), len, attached = 0;
	loff_t pos = folio_pos(folio), ofs;
	int err = 0;

	erofs_onlinefolio_init(folio);

Annotation

Implementation Notes