From: James Simmons Date: Tue, 21 Jul 2015 19:32:34 +0000 (-0400) Subject: LU-6260 llite: add support for new iter functionality X-Git-Tag: 2.7.58~54 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F28%2F15028%2F10;p=fs%2Flustre-release.git LU-6260 llite: add support for new iter functionality For the 3.16+ kernels struct file_operations added new read and write methods; read_iter and write_iter; to use struct iov_iter as a parameter since it contains all the iovec data needed. This avoid having the file system managing iovec data like transversing the iovec page list. Now we can use supplied iov_iter helper functions that does this work for us. In later kernels only this back end is supported. Backported from the upstream lustre client. ----------------------------------------------------------------------- Linux-commit: b42b15fdad3ebb790250041d1517acebb9bd56d9 lustre: get rid of messing with iovecs * switch to ->read_iter/->write_iter * keep a pointer to iov_iter instead of iov/nr_segs * do not modify iovecs; use iov_iter_truncate()/iov_iter_advance() and a new primitive - iov_iter_reexpand() (expand previously truncated iterator) istead. * (racy) check for lustre VMAs intersecting with iovecs kept for now as for_each_iov() loop. Signed-off-by: Al Viro ----------------------------------------------------------------------- Signed-off-by: James Simmons Change-Id: I71928beaa7b1c87f3e2c689e1dee96052eaef872 Reviewed-on: http://review.whamcloud.com/15028 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin --- diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index f553668..b35cdc5 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -1656,6 +1656,50 @@ direct_io_iter, [ ]) # LC_DIRECTIO_USE_ITER # +# LC_HAVE_IOV_ITER_INIT_DIRECTION +# +# +# 3.16 linux commit 71d8e532b1549a478e6a6a8a44f309d050294d00 +# changed iov_iter_init api to start accepting a tag +# that defines if its a read or write operation +# +AC_DEFUN([LC_HAVE_IOV_ITER_INIT_DIRECTION], [ +tmp_flags="$EXTRA_KCFLAGS" +EXTRA_KCFLAGS="-Werror" +LB_CHECK_COMPILE([if 'iov_iter_init' takes a tag], +iter_init, [ + #include + #include +],[ + const struct iovec *iov = NULL; + + iov_iter_init(NULL, READ, iov, 1, 0); +],[ + AC_DEFINE(HAVE_IOV_ITER_INIT_DIRECTION, 1, + [iov_iter_init handles directional tag]) +]) +EXTRA_KCFLAGS="$tmp_flags" +]) # LC_HAVE_IOV_ITER_INIT_DIRECTION + +# +# LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER +# +# 3.16 introduces [read|write]_iter to struct file_operations +# +AC_DEFUN([LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER], [ +LB_CHECK_COMPILE([if 'file_operations.[read|write]_iter' exist], +file_function_iter, [ + #include +],[ + ((struct file_operations *)NULL)->read_iter(NULL, NULL); + ((struct file_operations *)NULL)->write_iter(NULL, NULL); +],[ + AC_DEFINE(HAVE_FILE_OPERATIONS_READ_WRITE_ITER, 1, + [file_operations.[read|write]_iter functions exist]) +]) +]) # LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER + +# # LC_NFS_FILLDIR_USE_CTX # # 3.18 kernel moved from void cookie to struct dir_context @@ -1872,6 +1916,8 @@ AC_DEFUN([LC_PROG_LINUX], [ # 3.16 LC_DIRECTIO_USE_ITER + LC_HAVE_IOV_ITER_INIT_DIRECTION + LC_HAVE_FILE_OPERATIONS_READ_WRITE_ITER # 3.18 LC_NFS_FILLDIR_USE_CTX diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 97f0754..b10ef2e 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1080,9 +1080,10 @@ restart: switch (vio->vui_io_subtype) { case IO_NORMAL: - vio->vui_iov = args->u.normal.via_iov; - vio->vui_nrsegs = args->u.normal.via_nrsegs; - vio->vui_tot_nrsegs = vio->vui_nrsegs; + 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 @@ -1129,8 +1130,10 @@ restart: /* prepare IO restart */ if (count > 0 && args->via_io_subtype == IO_NORMAL) { - args->u.normal.via_iov = vio->vui_iov; - args->u.normal.via_nrsegs = vio->vui_tot_nrsegs; + 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); @@ -1166,78 +1169,133 @@ out: } /* + * Read from a file (through the page cache). + */ +static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + struct vvp_io_args *args; + struct lu_env *env; + ssize_t result; + int refcheck; + + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); + + args = ll_env_args(env, IO_NORMAL); + args->u.normal.via_iter = to; + args->u.normal.via_iocb = iocb; + + result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ, + &iocb->ki_pos, iov_iter_count(to)); + cl_env_put(env, &refcheck); + return result; +} + +/* + * Write to a file (through the page cache). + */ +static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct vvp_io_args *args; + struct lu_env *env; + ssize_t result; + int refcheck; + + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + return PTR_ERR(env); + + args = ll_env_args(env, IO_NORMAL); + args->u.normal.via_iter = from; + args->u.normal.via_iocb = iocb; + + result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE, + &iocb->ki_pos, iov_iter_count(from)); + cl_env_put(env, &refcheck); + return result; +} + +#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER +/* * XXX: exact copy from kernel code (__generic_file_aio_write_nolock) */ static int ll_file_get_iov_count(const struct iovec *iov, - unsigned long *nr_segs, size_t *count) + unsigned long *nr_segs, size_t *count) { - size_t cnt = 0; - unsigned long seg; + size_t cnt = 0; + unsigned long seg; - for (seg = 0; seg < *nr_segs; seg++) { - const struct iovec *iv = &iov[seg]; + for (seg = 0; seg < *nr_segs; seg++) { + const struct iovec *iv = &iov[seg]; - /* - * If any segment has a negative length, or the cumulative - * length ever wraps negative then return -EINVAL. - */ - cnt += iv->iov_len; - if (unlikely((ssize_t)(cnt|iv->iov_len) < 0)) - return -EINVAL; - if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len)) - continue; - if (seg == 0) - return -EFAULT; - *nr_segs = seg; - cnt -= iv->iov_len; /* This segment is no good */ - break; - } - *count = cnt; - return 0; + /* + * If any segment has a negative length, or the cumulative + * length ever wraps negative then return -EINVAL. + */ + cnt += iv->iov_len; + if (unlikely((ssize_t)(cnt|iv->iov_len) < 0)) + return -EINVAL; + if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len)) + continue; + if (seg == 0) + return -EFAULT; + *nr_segs = seg; + cnt -= iv->iov_len; /* This segment is no good */ + break; + } + *count = cnt; + return 0; } static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { - struct lu_env *env; - struct vvp_io_args *args; - struct iovec *local_iov; - size_t count; - ssize_t result; - int refcheck; - ENTRY; + struct iovec *local_iov; + struct iov_iter *to; + size_t iov_count; + ssize_t result; + ENTRY; - result = ll_file_get_iov_count(iov, &nr_segs, &count); - if (result) - RETURN(result); - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - RETURN(PTR_ERR(env)); + result = ll_file_get_iov_count(iov, &nr_segs, &iov_count); + if (result) + RETURN(result); if (nr_segs == 1) { + struct lu_env *env; + int refcheck; + + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + RETURN(PTR_ERR(env)); + local_iov = &ll_env_info(env)->lti_local_iov; *local_iov = *iov; + + cl_env_put(env, &refcheck); } else { OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs); - if (local_iov == NULL) { - cl_env_put(env, &refcheck); + if (local_iov == NULL) RETURN(-ENOMEM); - } memcpy(local_iov, iov, sizeof(*iov) * nr_segs); } - args = ll_env_args(env, IO_NORMAL); - args->u.normal.via_iov = local_iov; - args->u.normal.via_nrsegs = nr_segs; - args->u.normal.via_iocb = iocb; - - result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ, - &iocb->ki_pos, count); + OBD_ALLOC_PTR(to); + if (to == NULL) { + result = -ENOMEM; + goto out; + } +# ifdef HAVE_IOV_ITER_INIT_DIRECTION + iov_iter_init(to, READ, local_iov, nr_segs, iov_count); +# else /* !HAVE_IOV_ITER_INIT_DIRECTION */ + iov_iter_init(to, local_iov, nr_segs, iov_count, 0); +# endif /* HAVE_IOV_ITER_INIT_DIRECTION */ - cl_env_put(env, &refcheck); + result = ll_file_read_iter(iocb, to); + OBD_FREE_PTR(to); +out: if (nr_segs > 1) OBD_FREE(local_iov, sizeof(*iov) * nr_segs); @@ -1281,44 +1339,51 @@ 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 lu_env *env; - struct vvp_io_args *args; - struct iovec *local_iov; - size_t count; - ssize_t result; - int refcheck; - ENTRY; - - result = ll_file_get_iov_count(iov, &nr_segs, &count); - if (result) - RETURN(result); + struct iovec *local_iov; + struct iov_iter *from; + size_t iov_count; + ssize_t result; + ENTRY; - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - RETURN(PTR_ERR(env)); + result = ll_file_get_iov_count(iov, &nr_segs, &iov_count); + if (result) + RETURN(result); if (nr_segs == 1) { + struct lu_env *env; + int refcheck; + + env = cl_env_get(&refcheck); + if (IS_ERR(env)) + RETURN(PTR_ERR(env)); + local_iov = &ll_env_info(env)->lti_local_iov; *local_iov = *iov; + + cl_env_put(env, &refcheck); } else { OBD_ALLOC(local_iov, sizeof(*iov) * nr_segs); - if (local_iov == NULL) { - cl_env_put(env, &refcheck); + if (local_iov == NULL) RETURN(-ENOMEM); - } memcpy(local_iov, iov, sizeof(*iov) * nr_segs); } - args = ll_env_args(env, IO_NORMAL); - args->u.normal.via_iov = local_iov; - args->u.normal.via_nrsegs = nr_segs; - args->u.normal.via_iocb = iocb; + OBD_ALLOC_PTR(from); + if (from == NULL) { + result = -ENOMEM; + goto out; + } +# ifdef HAVE_IOV_ITER_INIT_DIRECTION + iov_iter_init(from, WRITE, local_iov, nr_segs, iov_count); +# else /* !HAVE_IOV_ITER_INIT_DIRECTION */ + iov_iter_init(from, local_iov, nr_segs, iov_count, 0); +# endif /* HAVE_IOV_ITER_INIT_DIRECTION */ - result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE, - &iocb->ki_pos, count); - cl_env_put(env, &refcheck); + result = ll_file_write_iter(iocb, from); + OBD_FREE_PTR(from); +out: if (nr_segs > 1) OBD_FREE(local_iov, sizeof(*iov) * nr_segs); @@ -1355,6 +1420,7 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf, cl_env_put(env, &refcheck); RETURN(result); } +#endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ /* * Send file content (through pagecache) somewhere with helper @@ -3393,53 +3459,74 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd) /* -o localflock - only provides locally consistent flock locks */ struct file_operations ll_file_operations = { - .read = ll_file_read, - .aio_read = ll_file_aio_read, - .write = ll_file_write, - .aio_write = ll_file_aio_write, - .unlocked_ioctl = ll_file_ioctl, - .open = ll_file_open, - .release = ll_file_release, - .mmap = ll_file_mmap, - .llseek = ll_file_seek, - .splice_read = ll_file_splice_read, - .fsync = ll_fsync, - .flush = ll_flush +#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER + .read = new_sync_read, + .read_iter = ll_file_read_iter, + .write = new_sync_write, + .write_iter = ll_file_write_iter, +#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ + .read = ll_file_read, + .aio_read = ll_file_aio_read, + .write = ll_file_write, + .aio_write = ll_file_aio_write, +#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ + .unlocked_ioctl = ll_file_ioctl, + .open = ll_file_open, + .release = ll_file_release, + .mmap = ll_file_mmap, + .llseek = ll_file_seek, + .splice_read = ll_file_splice_read, + .fsync = ll_fsync, + .flush = ll_flush }; struct file_operations ll_file_operations_flock = { - .read = ll_file_read, - .aio_read = ll_file_aio_read, - .write = ll_file_write, - .aio_write = ll_file_aio_write, - .unlocked_ioctl = ll_file_ioctl, - .open = ll_file_open, - .release = ll_file_release, - .mmap = ll_file_mmap, - .llseek = ll_file_seek, - .splice_read = ll_file_splice_read, - .fsync = ll_fsync, - .flush = ll_flush, - .flock = ll_file_flock, - .lock = ll_file_flock +#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER + .read = new_sync_read, + .read_iter = ll_file_read_iter, + .write = new_sync_write, + .write_iter = ll_file_write_iter, +#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ + .read = ll_file_read, + .aio_read = ll_file_aio_read, + .write = ll_file_write, + .aio_write = ll_file_aio_write, +#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ + .unlocked_ioctl = ll_file_ioctl, + .open = ll_file_open, + .release = ll_file_release, + .mmap = ll_file_mmap, + .llseek = ll_file_seek, + .splice_read = ll_file_splice_read, + .fsync = ll_fsync, + .flush = ll_flush, + .flock = ll_file_flock, + .lock = ll_file_flock }; /* These are for -o noflock - to return ENOSYS on flock calls */ struct file_operations ll_file_operations_noflock = { - .read = ll_file_read, - .aio_read = ll_file_aio_read, - .write = ll_file_write, - .aio_write = ll_file_aio_write, - .unlocked_ioctl = ll_file_ioctl, - .open = ll_file_open, - .release = ll_file_release, - .mmap = ll_file_mmap, - .llseek = ll_file_seek, - .splice_read = ll_file_splice_read, - .fsync = ll_fsync, - .flush = ll_flush, - .flock = ll_file_noflock, - .lock = ll_file_noflock +#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER + .read = new_sync_read, + .read_iter = ll_file_read_iter, + .write = new_sync_write, + .write_iter = ll_file_write_iter, +#else /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ + .read = ll_file_read, + .aio_read = ll_file_aio_read, + .write = ll_file_write, + .aio_write = ll_file_aio_write, +#endif /* HAVE_FILE_OPERATIONS_READ_WRITE_ITER */ + .unlocked_ioctl = ll_file_ioctl, + .open = ll_file_open, + .release = ll_file_release, + .mmap = ll_file_mmap, + .llseek = ll_file_seek, + .splice_read = ll_file_splice_read, + .fsync = ll_fsync, + .flush = ll_flush, + .flock = ll_file_noflock, + .lock = ll_file_noflock }; struct inode_operations ll_file_inode_operations = { diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index c393a38..c37c102 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -987,8 +987,7 @@ struct vvp_io_args { union { struct { struct kiocb *via_iocb; - struct iovec *via_iov; - unsigned long via_nrsegs; + struct iov_iter *via_iter; } normal; struct { struct pipe_inode_info *via_pipe; diff --git a/lustre/llite/vvp_internal.h b/lustre/llite/vvp_internal.h index d92dd1f..31aff08 100644 --- a/lustre/llite/vvp_internal.h +++ b/lustre/llite/vvp_internal.h @@ -68,8 +68,8 @@ struct vvp_io { /** * I/O vector information to or from which read/write is going. */ - struct iovec *vui_iov; - unsigned long vui_nrsegs; + struct iov_iter *vui_iter; +#ifndef HAVE_FILE_OPERATIONS_READ_WRITE_ITER /** * Total iov count for left IO. */ @@ -78,6 +78,7 @@ struct vvp_io { * 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 9871e80..02afd2a 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -393,29 +393,37 @@ static int vvp_mmap_locks(const struct lu_env *env, struct vm_area_struct *vma; struct cl_lock_descr *descr = &vti->vti_descr; ldlm_policy_data_t policy; - unsigned long addr; - unsigned long seg; - ssize_t count; - int result = 0; - ENTRY; +#ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER + struct iovec iov; + struct iov_iter i; +#else + unsigned long seg; +#endif + int result = 0; + ENTRY; LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); if (!cl_is_normalio(env, io)) RETURN(0); - if (vio->vui_iov == NULL) /* nfs or loop back device write */ + /* nfs or loop back device write */ + if (vio->vui_iter == NULL) RETURN(0); /* No MM (e.g. NFS)? No vmas too. */ if (mm == NULL) RETURN(0); - for (seg = 0; seg < vio->vui_nrsegs; seg++) { - const struct iovec *iv = &vio->vui_iov[seg]; +#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; - addr = (unsigned long)iv->iov_base; - count = iv->iov_len; if (count == 0) continue; @@ -478,24 +486,39 @@ 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; - LASSERT(vio->vui_tot_nrsegs >= vio->vui_nrsegs); +#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) { - vio->vui_iov[vio->vui_nrsegs - 1].iov_len = vio->vui_iov_olen; + 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; } - /* advance iov */ - iov = vio->vui_iov; + /* 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; @@ -508,22 +531,29 @@ static void vvp_io_advance(const struct lu_env *env, vio->vui_tot_nrsegs--; } - vio->vui_iov = iov; + 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) { - int i; 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 = &vio->vui_iov[i]; + struct iovec *iv = (struct iovec *) &vio->vui_iter->iov[i]; if (iv->iov_len < size) { size -= iv->iov_len; @@ -536,10 +566,11 @@ static void vvp_io_update_iov(const struct lu_env *env, } } - vio->vui_nrsegs = i + 1; - LASSERTF(vio->vui_tot_nrsegs >= vio->vui_nrsegs, + 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_nrsegs); + 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, @@ -799,9 +830,14 @@ 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_iov, vio->vui_nrsegs, + 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, @@ -1054,7 +1090,7 @@ static int vvp_io_write_start(const struct lu_env *env, RETURN(-EFBIG); } - if (vio->vui_iov == NULL) { + if (vio->vui_iter == NULL) { /* from a temp io in ll_cl_init(). */ result = 0; } else { @@ -1066,9 +1102,14 @@ 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_iov, vio->vui_nrsegs, + vio->vui_iter->iov, + vio->vui_iter->nr_segs, &vio->vui_iocb->ki_pos); +#endif if (result > 0 || result == -EIOCBQUEUED) { ssize_t err; @@ -1437,7 +1478,9 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, result = 1; 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