Whamcloud - gitweb
LU-13697 llite: fix short io for AIO
[fs/lustre-release.git] / lustre / llite / file.c
index 4f5bba4..92bef32 100644 (file)
@@ -1478,16 +1478,16 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                   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;
 
@@ -1516,6 +1516,13 @@ restart:
                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. */
@@ -1554,7 +1561,14 @@ restart:
                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 */
@@ -1564,6 +1578,19 @@ restart:
                        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,