struct file *file, enum cl_io_type iot,
loff_t *ppos, size_t count)
{
- struct vvp_io *vio = vvp_env_io(env);
- struct inode *inode = file_inode(file);
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_file_data *fd = file->private_data;
- struct range_lock range;
- struct cl_io *io;
- ssize_t result = 0;
- int rc = 0;
- unsigned retried = 0;
- unsigned ignore_lockless = 0;
+ struct vvp_io *vio = vvp_env_io(env);
+ struct inode *inode = file_inode(file);
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct ll_file_data *fd = file->private_data;
+ struct range_lock range;
+ struct cl_io *io;
+ ssize_t result = 0;
+ int rc = 0;
+ unsigned int retried = 0, ignore_lockless = 0;
+ bool is_aio = false;
ENTRY;
case IO_NORMAL:
vio->vui_iter = args->u.normal.via_iter;
vio->vui_iocb = args->u.normal.via_iocb;
+ if (file->f_flags & O_DIRECT) {
+ if (!is_sync_kiocb(vio->vui_iocb))
+ is_aio = true;
+ io->ci_aio = cl_aio_alloc(vio->vui_iocb);
+ if (!io->ci_aio)
+ GOTO(out, rc = -ENOMEM);
+ }
/* Direct IO reads must also take range lock,
* or multiple reads will try to work on the same pages
* See LU-6227 for details. */
rc = io->ci_result;
}
- if (io->ci_nob > 0) {
+ /*
+ * In order to move forward AIO, ci_nob was increased,
+ * but that doesn't mean io have been finished, it just
+ * means io have been submited, we will always return
+ * EIOCBQUEUED to the caller, So we could only return
+ * number of bytes in non-AIO case.
+ */
+ if (io->ci_nob > 0 && !is_aio) {
result += io->ci_nob;
count -= io->ci_nob;
*ppos = io->u.ci_wr.wr.crw_pos; /* for splice */
args->u.normal.via_iter = vio->vui_iter;
}
out:
+ if (io->ci_aio) {
+ /**
+ * Drop one extra reference so that end_io() could be
+ * called for this IO context, we could call it after
+ * we make sure all AIO requests have been proceed.
+ */
+ cl_sync_io_note(env, &io->ci_aio->cda_sync,
+ rc == -EIOCBQUEUED ? 0 : rc);
+ if (!is_aio) {
+ cl_aio_free(io->ci_aio);
+ io->ci_aio = NULL;
+ }
+ }
cl_io_fini(env, io);
CDEBUG(D_VFSTRACE,