fs/iomap/direct-io.c

Source file repositories/reference/linux-study-clean/fs/iomap/direct-io.c

File Facts

System
Linux kernel
Corpus path
fs/iomap/direct-io.c
Extension
.c
Size
25355 bytes
Lines
905
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration 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 iomap_dio {
	struct kiocb		*iocb;
	const struct iomap_dio_ops *dops;
	loff_t			i_size;
	loff_t			size;
	atomic_t		ref;
	unsigned		flags;
	int			error;
	size_t			done_before;
	bool			wait_for_completion;

	union {
		/* used during submission and for synchronous completion: */
		struct {
			struct iov_iter		*iter;
			struct task_struct	*waiter;
		} submit;

		/* used for aio completion: */
		struct {
			struct work_struct	work;
		} aio;
	};
};

static struct bio *iomap_dio_alloc_bio(const struct iomap_iter *iter,
		struct iomap_dio *dio, unsigned short nr_vecs, blk_opf_t opf)
{
	if (dio->dops && dio->dops->bio_set)
		return bio_alloc_bioset(iter->iomap.bdev, nr_vecs, opf,
					GFP_KERNEL, dio->dops->bio_set);
	return bio_alloc(iter->iomap.bdev, nr_vecs, opf, GFP_KERNEL);
}

static void iomap_dio_submit_bio(const struct iomap_iter *iter,
		struct iomap_dio *dio, struct bio *bio, loff_t pos)
{
	struct kiocb *iocb = dio->iocb;

	atomic_inc(&dio->ref);

	/* Sync dio can't be polled reliably */
	if ((iocb->ki_flags & IOCB_HIPRI) && !is_sync_kiocb(iocb)) {
		bio->bi_opf |= REQ_POLLED;
		WRITE_ONCE(iocb->private, bio);
	}

	if (dio->dops && dio->dops->submit_io) {
		dio->dops->submit_io(iter, bio, pos);
	} else {
		WARN_ON_ONCE(iter->iomap.flags & IOMAP_F_ANON_WRITE);
		blk_crypto_submit_bio(bio);
	}
}

static inline enum fserror_type iomap_dio_err_type(const struct iomap_dio *dio)
{
	if (dio->flags & IOMAP_DIO_WRITE)
		return FSERR_DIRECTIO_WRITE;
	return FSERR_DIRECTIO_READ;
}

static inline bool should_report_dio_fserror(const struct iomap_dio *dio)
{
	switch (dio->error) {
	case 0:
	case -EAGAIN:
	case -ENOTBLK:
		/* don't send fsnotify for success or magic retry codes */
		return false;
	default:
		return true;
	}
}

ssize_t iomap_dio_complete(struct iomap_dio *dio)
{
	const struct iomap_dio_ops *dops = dio->dops;
	struct kiocb *iocb = dio->iocb;
	loff_t offset = iocb->ki_pos;
	ssize_t ret = dio->error;

	if (dops && dops->end_io)
		ret = dops->end_io(iocb, dio->size, ret, dio->flags);
	if (should_report_dio_fserror(dio))
		fserror_report_io(file_inode(iocb->ki_filp),
				  iomap_dio_err_type(dio), offset, dio->size,
				  dio->error, GFP_NOFS);

	if (likely(!ret)) {

Annotation

Implementation Notes