ssize_t do_sync_read(struct file *filp, char _user *buf, size_t len, loff_t *ppos)

struct iovec iov = { .iov_base = buf, .iov_len = len }; struct kiocb kiocb; ssize_t ret;

init_sync_kiocb(&kiocb, filp); kiocb.ki_pos = *ppos; kiocb.ki_left = len;

ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);

ret = wait_on_sync_kiocb(&kiocb); *ppos = kiocb.ki_pos; return ret;

init_sync_kiocb initializes a kiocb instance that controls the asynchronous I/O operation; its detailed contents are of little interest here.25 The real work is delegated to the filesystem-specific asynchronous read operation that is stored in aio_read of struct file_operations. Usually generic_file_aio_read, which I discuss shortly, is used. However, the routine performs work asynchronously, so there is no guarantee that the data have already been read when the routine returns to the caller.

24In former kernel versions, the standard read and write operations used to be generic_file_read and generic_file_ write, but they have been replaced by the variants I am about to discuss.

25Asynchronous I/O operations are used to submit a read or write request to the kernel. These requests are not satisfied immediately but are queued in a list. The code flow then returns immediately to the calling function (in contrast to the regular I/O operations implemented here). In this case, the calling function has the impression that the result is returned immediately because it does not notice the delay involved in performing the operation. The data can be queried later after the request has been dealt with asynchronously.

Asynchronous operations are not performed with file handles but with I/O control blocks. Consequently, an instance of the corresponding data type must first be generated with init_sync_kiocb. Currently, asynchronous I/O is used only by very few applications (e.g., large databases), so it's not worth going into the details.

The -eiocbqueued return value indicates that the read request was queued and not yet processed. In this case, wait_on_sync_kiocb waits until the data are in memory. The function can check this by referring to the initialized control block. The process is put to sleep while it is waiting so that the CPU is available for other tasks. For the sake of simplicity, I do not differentiate between synchronous or asynchronous termination of the read operation in the following description.

Continue reading here: Asynchronous Reading

Was this article helpful?

0 0