Whamcloud - gitweb
LU-4257 llite: fix up iov_iter implementation 56/20256/6
authorJinshan Xiong <jinshan.xiong@intel.com>
Fri, 27 May 2016 23:13:18 +0000 (16:13 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 3 Jun 2016 04:35:04 +0000 (04:35 +0000)
Clean up and fix up the usage of iov_iter in client.

Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Change-Id: I331b48a0978dd3258946ee7bae8362e60026b037
Reviewed-on: http://review.whamcloud.com/20256
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/autoconf/lustre-core.m4
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/vvp_internal.h
lustre/llite/vvp_io.c

index 8e04313..0d5c599 100644 (file)
@@ -1297,6 +1297,23 @@ file_f_inode, [
 ]) # LC_HAVE_FILE_F_INODE
 
 #
 ]) # LC_HAVE_FILE_F_INODE
 
 #
+# LC_HAVE_FILE_INODE
+#
+# 3.8 has introduced inline function file_inode
+#
+AC_DEFUN([LC_HAVE_FILE_INODE], [
+LB_CHECK_COMPILE([if file_inode() exists],
+file_inode, [
+       #include <linux/fs.h>
+],[
+       file_inode(NULL);
+],[
+       AC_DEFINE(HAVE_FILE_INODE, 1,
+               [file_inode() has been defined])
+])
+]) # LC_HAVE_FILE_INODE
+
+#
 # LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
 #
 AC_DEFUN([LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS], [
 # LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
 #
 AC_DEFUN([LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS], [
@@ -1704,6 +1721,29 @@ EXTRA_KCFLAGS="$tmp_flags"
 ]) # LC_HAVE_IOV_ITER_INIT_DIRECTION
 
 #
 ]) # LC_HAVE_IOV_ITER_INIT_DIRECTION
 
 #
+# LC_HAVE_IOV_ITER_TRUNCATE
+#
+#
+# 3.16 introduces a new API iov_iter_truncate()
+#
+AC_DEFUN([LC_HAVE_IOV_ITER_TRUNCATE], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'iov_iter_truncate' exists ],
+iter_truncate, [
+       #include <linux/uio.h>
+       #include <linux/fs.h>
+],[
+       struct iov_iter *i = NULL;
+
+       iov_iter_truncate(i, 0);
+],[
+       AC_DEFINE(HAVE_IOV_ITER_TRUNCATE, 1, [iov_iter_truncate exists])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_HAVE_IOV_ITER_TRUNCATE
+
+#
 # LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 #
 # 3.16 introduces [read|write]_iter to struct file_operations
 # LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 #
 # 3.16 introduces [read|write]_iter to struct file_operations
@@ -2144,6 +2184,7 @@ AC_DEFUN([LC_PROG_LINUX], [
 
        # 3.8
        LC_HAVE_FILE_F_INODE
 
        # 3.8
        LC_HAVE_FILE_F_INODE
+       LC_HAVE_FILE_INODE
        LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
 
        # 3.9
        LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
 
        # 3.9
@@ -2181,6 +2222,7 @@ AC_DEFUN([LC_PROG_LINUX], [
        # 3.16
        LC_DIRECTIO_USE_ITER
        LC_HAVE_IOV_ITER_INIT_DIRECTION
        # 3.16
        LC_DIRECTIO_USE_ITER
        LC_HAVE_IOV_ITER_INIT_DIRECTION
+       LC_HAVE_IOV_ITER_TRUNCATE
        LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 
        # 3.17
        LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 
        # 3.17
index 258efb8..1fe33f8 100644 (file)
@@ -1069,9 +1069,6 @@ restart:
                switch (vio->vui_io_subtype) {
                case IO_NORMAL:
                        vio->vui_iter = args->u.normal.via_iter;
                switch (vio->vui_io_subtype) {
                case IO_NORMAL:
                        vio->vui_iter = args->u.normal.via_iter;
-#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
-                       vio->vui_tot_nrsegs = vio->vui_iter->nr_segs;
-#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
                        vio->vui_iocb = args->u.normal.via_iocb;
                        /* Direct IO reads must also take range lock,
                         * or multiple reads will try to work on the same pages
                        vio->vui_iocb = args->u.normal.via_iocb;
                        /* Direct IO reads must also take range lock,
                         * or multiple reads will try to work on the same pages
@@ -1117,12 +1114,8 @@ restart:
                *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */
 
                /* prepare IO restart */
                *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */
 
                /* prepare IO restart */
-               if (count > 0 && args->via_io_subtype == IO_NORMAL) {
+               if (count > 0 && args->via_io_subtype == IO_NORMAL)
                        args->u.normal.via_iter = vio->vui_iter;
                        args->u.normal.via_iter = vio->vui_iter;
-#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
-                       args->u.normal.via_iter->nr_segs = vio->vui_tot_nrsegs;
-#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
-               }
        }
        GOTO(out, rc);
 out:
        }
        GOTO(out, rc);
 out:
@@ -1245,7 +1238,6 @@ static int ll_file_get_iov_count(const struct iovec *iov,
 static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos)
 {
 static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos)
 {
-       struct iovec *local_iov;
        struct iov_iter to;
        size_t iov_count;
        ssize_t result;
        struct iov_iter to;
        size_t iov_count;
        ssize_t result;
@@ -1255,21 +1247,14 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
        if (result)
                RETURN(result);
 
        if (result)
                RETURN(result);
 
-       OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs);
-       if (local_iov == NULL)
-               RETURN(-ENOMEM);
-
-       memcpy(local_iov, iov, sizeof(*iov) * nr_segs);
-
 # ifdef HAVE_IOV_ITER_INIT_DIRECTION
 # ifdef HAVE_IOV_ITER_INIT_DIRECTION
-       iov_iter_init(&to, READ, local_iov, nr_segs, iov_count);
+       iov_iter_init(&to, READ, iov, nr_segs, iov_count);
 # else /* !HAVE_IOV_ITER_INIT_DIRECTION */
 # else /* !HAVE_IOV_ITER_INIT_DIRECTION */
-       iov_iter_init(&to, local_iov, nr_segs, iov_count, 0);
+       iov_iter_init(&to, iov, nr_segs, iov_count, 0);
 # endif /* HAVE_IOV_ITER_INIT_DIRECTION */
 
        result = ll_file_read_iter(iocb, &to);
 
 # endif /* HAVE_IOV_ITER_INIT_DIRECTION */
 
        result = ll_file_read_iter(iocb, &to);
 
-       OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
        RETURN(result);
 }
 
        RETURN(result);
 }
 
@@ -1307,7 +1292,6 @@ static ssize_t ll_file_read(struct file *file, char __user *buf, size_t count,
 static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                 unsigned long nr_segs, loff_t pos)
 {
 static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                 unsigned long nr_segs, loff_t pos)
 {
-       struct iovec *local_iov;
        struct iov_iter from;
        size_t iov_count;
        ssize_t result;
        struct iov_iter from;
        size_t iov_count;
        ssize_t result;
@@ -1317,22 +1301,14 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (result)
                RETURN(result);
 
        if (result)
                RETURN(result);
 
-       OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs);
-       if (local_iov == NULL)
-               RETURN(-ENOMEM);
-
-       memcpy(local_iov, iov, sizeof(*iov) * nr_segs);
-
 # ifdef HAVE_IOV_ITER_INIT_DIRECTION
 # ifdef HAVE_IOV_ITER_INIT_DIRECTION
-       iov_iter_init(&from, WRITE, local_iov, nr_segs, iov_count);
+       iov_iter_init(&from, WRITE, iov, nr_segs, iov_count);
 # else /* !HAVE_IOV_ITER_INIT_DIRECTION */
 # else /* !HAVE_IOV_ITER_INIT_DIRECTION */
-       iov_iter_init(&from, local_iov, nr_segs, iov_count, 0);
+       iov_iter_init(&from, iov, nr_segs, iov_count, 0);
 # endif /* HAVE_IOV_ITER_INIT_DIRECTION */
 
        result = ll_file_write_iter(iocb, &from);
 
 # endif /* HAVE_IOV_ITER_INIT_DIRECTION */
 
        result = ll_file_write_iter(iocb, &from);
 
-       OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
-
        RETURN(result);
 }
 
        RETURN(result);
 }
 
index 6c823be..f205f8a 100644 (file)
@@ -1507,4 +1507,93 @@ void cl_inode_fini(struct inode *inode);
 u64 cl_fid_build_ino(const struct lu_fid *fid, int api32);
 u32 cl_fid_build_gen(const struct lu_fid *fid);
 
 u64 cl_fid_build_ino(const struct lu_fid *fid, int api32);
 u32 cl_fid_build_gen(const struct lu_fid *fid);
 
+#ifndef HAVE_FILE_INODE
+static inline struct inode *file_inode(struct file *file)
+{
+       return file->f_path.dentry->d_inode;
+}
+#endif
+
+#ifndef HAVE_IOV_ITER_TRUNCATE
+static inline void iov_iter_truncate(struct iov_iter *i, u64 count)
+{
+       if (i->count > count)
+               i->count = count;
+}
+#endif
+
+#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
+{
+       i->count = count;
+}
+
+static inline struct iovec iov_iter_iovec(const struct iov_iter *iter)
+{
+       return (struct iovec) {
+               .iov_base = iter->iov->iov_base + iter->iov_offset,
+               .iov_len = min(iter->count,
+                              iter->iov->iov_len - iter->iov_offset),
+       };
+}
+
+#define iov_for_each(iov, iter, start)                                 \
+       for (iter = (start);                                            \
+            (iter).count && ((iov = iov_iter_iovec(&(iter))), 1);      \
+            iov_iter_advance(&(iter), (iov).iov_len))
+
+static inline ssize_t
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct iovec iov;
+       struct iov_iter i;
+       ssize_t bytes = 0;
+
+       iov_for_each(iov, i, *iter) {
+               ssize_t res;
+
+               res = generic_file_aio_read(iocb, &iov, 1, iocb->ki_pos);
+               if (res <= 0) {
+                       if (bytes == 0)
+                               bytes = res;
+                       break;
+               }
+
+               bytes += res;
+               if (res < iov.iov_len)
+                       break;
+       }
+
+       if (bytes > 0)
+               iov_iter_advance(iter, bytes);
+       return bytes;
+}
+
+static inline ssize_t
+generic_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct iovec iov;
+       struct iov_iter i;
+       ssize_t bytes = 0;
+
+       iov_for_each(iov, i, *iter) {
+               ssize_t res;
+
+               res = __generic_file_aio_write(iocb, &iov, 1, &iocb->ki_pos);
+               if (res <= 0) {
+                       if (bytes == 0)
+                               bytes = res;
+                       break;
+               }
+
+               bytes += res;
+               if (res < iov.iov_len)
+                       break;
+       }
+
+       if (bytes > 0)
+               iov_iter_advance(iter, bytes);
+       return bytes;
+}
+#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
 #endif /* LLITE_INTERNAL_H */
 #endif /* LLITE_INTERNAL_H */
index f844023..832e746 100644 (file)
@@ -69,16 +69,6 @@ struct vvp_io {
         * I/O vector information to or from which read/write is going.
         */
        struct iov_iter *vui_iter;
         * I/O vector information to or from which read/write is going.
         */
        struct iov_iter *vui_iter;
-#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
-       /**
-        * Total iov count for left IO.
-        */
-       unsigned long vui_tot_nrsegs;
-       /**
-        * Old length for iov that was truncated partially.
-        */
-       size_t vui_iov_olen;
-#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
        /**
         * Total size for the left IO.
         */
        /**
         * Total size for the left IO.
         */
index a076e5a..8a81b83 100644 (file)
@@ -394,12 +394,8 @@ static int vvp_mmap_locks(const struct lu_env *env,
        struct vm_area_struct *vma;
        struct cl_lock_descr *descr = &vti->vti_descr;
        union ldlm_policy_data policy;
        struct vm_area_struct *vma;
        struct cl_lock_descr *descr = &vti->vti_descr;
        union ldlm_policy_data policy;
-#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
        struct iovec iov;
        struct iov_iter i;
        struct iovec iov;
        struct iov_iter i;
-#else
-       unsigned long seg;
-#endif
        int result = 0;
        ENTRY;
 
        int result = 0;
        ENTRY;
 
@@ -416,12 +412,7 @@ static int vvp_mmap_locks(const struct lu_env *env,
        if (mm == NULL)
                RETURN(0);
 
        if (mm == NULL)
                RETURN(0);
 
-#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
        iov_for_each(iov, i, *(vio->vui_iter)) {
        iov_for_each(iov, i, *(vio->vui_iter)) {
-#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
-       for (seg = 0; seg < vio->vui_iter->nr_segs; seg++) {
-               const struct iovec iov = vio->vui_iter->iov[seg];
-#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
                unsigned long addr = (unsigned long)iov.iov_base;
                size_t count = iov.iov_len;
 
                unsigned long addr = (unsigned long)iov.iov_base;
                size_t count = iov.iov_len;
 
@@ -487,91 +478,25 @@ static void vvp_io_advance(const struct lu_env *env,
        struct vvp_io    *vio = cl2vvp_io(env, ios);
        struct cl_io     *io  = ios->cis_io;
        struct cl_object *obj = ios->cis_io->ci_obj;
        struct vvp_io    *vio = cl2vvp_io(env, ios);
        struct cl_io     *io  = ios->cis_io;
        struct cl_object *obj = ios->cis_io->ci_obj;
-#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
-       struct iovec     *iov;
-#endif
+
        CLOBINVRNT(env, obj, vvp_object_invariant(obj));
 
        if (!cl_is_normalio(env, io))
                return;
 
        CLOBINVRNT(env, obj, vvp_object_invariant(obj));
 
        if (!cl_is_normalio(env, io))
                return;
 
-#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
        vio->vui_tot_count -= nob;
        iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count);
        vio->vui_tot_count -= nob;
        iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count);
-#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
-       LASSERT(vio->vui_tot_nrsegs >= vio->vui_iter->nr_segs);
-       LASSERT(vio->vui_tot_count  >= nob);
-
-       /* Restore the iov changed in vvp_io_update_iov() */
-       if (vio->vui_iov_olen > 0) {
-               unsigned long idx = vio->vui_iter->nr_segs - 1;
-
-               /* In the latest kernels iov is const so that
-                * changes are done using iter helpers. In older
-                * kernels those helpers don't exist we lustre
-                * has to do some of the management of the iter
-                * itself. */
-               iov = (struct iovec *)&vio->vui_iter->iov[idx];
-               iov->iov_len = vio->vui_iov_olen;
-               vio->vui_iov_olen = 0;
-       }
-
-       /* In the latest kernels special helpers exist to help
-        * advance the iov but we don't have that in older kernels
-        * so we need to do the book keeping ourselves. */
-       iov = (struct iovec *)vio->vui_iter->iov;
-       while (nob > 0) {
-               if (iov->iov_len > nob) {
-                       iov->iov_len -= nob;
-                       iov->iov_base += nob;
-                       break;
-               }
-
-               nob -= iov->iov_len;
-               iov++;
-               vio->vui_tot_nrsegs--;
-       }
-
-       vio->vui_iter->iov = iov;
-       vio->vui_tot_count -= nob;
-#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
 }
 
 static void vvp_io_update_iov(const struct lu_env *env,
                              struct vvp_io *vio, struct cl_io *io)
 {
        size_t size = io->u.ci_rw.crw_count;
 }
 
 static void vvp_io_update_iov(const struct lu_env *env,
                              struct vvp_io *vio, struct cl_io *io)
 {
        size_t size = io->u.ci_rw.crw_count;
-#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
+
        if (!cl_is_normalio(env, io) || vio->vui_iter == NULL)
                return;
 
        iov_iter_truncate(vio->vui_iter, size);
        if (!cl_is_normalio(env, io) || vio->vui_iter == NULL)
                return;
 
        iov_iter_truncate(vio->vui_iter, size);
-#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
-       unsigned long i;
-
-       vio->vui_iov_olen = 0;
-       if (!cl_is_normalio(env, io) || vio->vui_tot_nrsegs == 0)
-               return;
-
-       for (i = 0; i < vio->vui_tot_nrsegs; i++) {
-               struct iovec *iv = (struct iovec *) &vio->vui_iter->iov[i];
-
-               if (iv->iov_len < size) {
-                       size -= iv->iov_len;
-               } else {
-                       if (iv->iov_len > size) {
-                               vio->vui_iov_olen = iv->iov_len;
-                               iv->iov_len = size;
-                       }
-                       break;
-               }
-       }
-
-       vio->vui_iter->nr_segs = i + 1;
-       LASSERTF(vio->vui_tot_nrsegs >= vio->vui_iter->nr_segs,
-                "tot_nrsegs: %lu, nrsegs: %lu\n",
-                vio->vui_tot_nrsegs, vio->vui_iter->nr_segs);
-#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
 }
 
 static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io,
 }
 
 static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io,
@@ -831,14 +756,7 @@ static int vvp_io_read_start(const struct lu_env *env,
        switch (vio->vui_io_subtype) {
        case IO_NORMAL:
                LASSERT(vio->vui_iocb->ki_pos == pos);
        switch (vio->vui_io_subtype) {
        case IO_NORMAL:
                LASSERT(vio->vui_iocb->ki_pos == pos);
-#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
                result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter);
                result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter);
-#else
-               result = generic_file_aio_read(vio->vui_iocb,
-                                              vio->vui_iter->iov,
-                                              vio->vui_iter->nr_segs,
-                                              vio->vui_iocb->ki_pos);
-#endif
                break;
        case IO_SPLICE:
                result = generic_file_splice_read(file, &pos,
                break;
        case IO_SPLICE:
                result = generic_file_splice_read(file, &pos,
@@ -1103,14 +1021,7 @@ static int vvp_io_write_start(const struct lu_env *env,
                 * consistency, proper locking to protect against writes,
                 * trucates, etc. is handled in the higher layers of lustre.
                 */
                 * consistency, proper locking to protect against writes,
                 * trucates, etc. is handled in the higher layers of lustre.
                 */
-#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
                result = generic_file_write_iter(vio->vui_iocb, vio->vui_iter);
                result = generic_file_write_iter(vio->vui_iocb, vio->vui_iter);
-#else
-               result = __generic_file_aio_write(vio->vui_iocb,
-                                                 vio->vui_iter->iov,
-                                                 vio->vui_iter->nr_segs,
-                                                 &vio->vui_iocb->ki_pos);
-#endif
                if (result > 0 || result == -EIOCBQUEUED) {
                        ssize_t err;
 
                if (result > 0 || result == -EIOCBQUEUED) {
                        ssize_t err;
 
@@ -1474,12 +1385,8 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
                  *  results."  -- Single Unix Spec */
                 if (count == 0)
                         result = 1;
                  *  results."  -- Single Unix Spec */
                 if (count == 0)
                         result = 1;
-               else {
+               else
                        vio->vui_tot_count = count;
                        vio->vui_tot_count = count;
-#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
-                       vio->vui_tot_nrsegs = 0;
-#endif
-               }
 
                /* for read/write, we store the jobid in the inode, and
                 * it'll be fetched by osc when building RPC.
 
                /* for read/write, we store the jobid in the inode, and
                 * it'll be fetched by osc when building RPC.