From 1101120d3258509fa74f952cd8664bfdc17bd97d Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Fri, 27 May 2016 16:13:18 -0700 Subject: [PATCH] LU-4257 llite: fix up iov_iter implementation Clean up and fix up the usage of iov_iter in client. Signed-off-by: Jinshan Xiong Change-Id: I331b48a0978dd3258946ee7bae8362e60026b037 Reviewed-on: http://review.whamcloud.com/20256 Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 42 ++++++++++++++++++ lustre/llite/file.c | 34 +++------------ lustre/llite/llite_internal.h | 89 +++++++++++++++++++++++++++++++++++++ lustre/llite/vvp_internal.h | 10 ----- lustre/llite/vvp_io.c | 99 ++---------------------------------------- 5 files changed, 139 insertions(+), 135 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 8e04313..0d5c599 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -1297,6 +1297,23 @@ 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 +],[ + 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], [ @@ -1704,6 +1721,29 @@ EXTRA_KCFLAGS="$tmp_flags" ]) # 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 + #include +],[ + 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 @@ -2144,6 +2184,7 @@ AC_DEFUN([LC_PROG_LINUX], [ # 3.8 LC_HAVE_FILE_F_INODE + LC_HAVE_FILE_INODE 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 + LC_HAVE_IOV_ITER_TRUNCATE LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER # 3.17 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 258efb8..1fe33f8 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1069,9 +1069,6 @@ restart: 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 @@ -1117,12 +1114,8 @@ 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; -#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: @@ -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) { - struct iovec *local_iov; 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); - 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 - 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 */ - 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); - OBD_FREE(local_iov, sizeof(*iov) * nr_segs); 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) { - struct iovec *local_iov; 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); - 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 - 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 */ - 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); - OBD_FREE(local_iov, sizeof(*iov) * nr_segs); - RETURN(result); } diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 6c823be..f205f8a 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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); +#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 */ diff --git a/lustre/llite/vvp_internal.h b/lustre/llite/vvp_internal.h index f844023..832e746 100644 --- a/lustre/llite/vvp_internal.h +++ b/lustre/llite/vvp_internal.h @@ -69,16 +69,6 @@ struct vvp_io { * 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. */ diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index a076e5a..8a81b83 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -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; -#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER struct iovec iov; struct iov_iter i; -#else - unsigned long seg; -#endif int result = 0; ENTRY; @@ -416,12 +412,7 @@ static int vvp_mmap_locks(const struct lu_env *env, if (mm == NULL) RETURN(0); -#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_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; @@ -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; -#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; -#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER 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; -#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); -#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, @@ -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); -#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_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, @@ -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. */ -#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_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; @@ -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; - else { + else 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. -- 1.8.3.1