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>
]) # 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_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
# 3.8
LC_HAVE_FILE_F_INODE
+ LC_HAVE_FILE_INODE
LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
# 3.9
# 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
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
*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:
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;
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);
}
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;
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);
}
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 */
* 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.
*/
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;
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;
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,
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,
* 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;
* 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.