Whamcloud - gitweb
LU-7382 llite: Fix iovec references accounting in ll_file_aio_read/write 32/17632/6
authorAndriy Skulysh <andriy.skulysh@seagate.com>
Wed, 16 Dec 2015 14:05:31 +0000 (16:05 +0200)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 14 Jan 2016 04:00:26 +0000 (04:00 +0000)
lti_local_iov is used to store iovec in case of 1 segment.

It is needed to hold reference on lu_env during
call of ll_file_write_iter() or ll_file_read_iter().

Otherwise an assertion fails:
vvp_io_update_iov()) ASSERTION( vio->vui_tot_nrsegs >= vio->vui_iter->nr_segs ) failed

Change-Id: Iaff4c81c6ced9ac0e1557dd0eb1fab5205b48e28
Signed-off-by: Andriy Skulysh <andriy.skulysh@seagate.com>
Reviewed-on: http://review.whamcloud.com/17632
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Patrick Farrell <paf@cray.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/llite/file.c

index d620c12..b4f3779 100644 (file)
@@ -1249,6 +1249,8 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
        struct iov_iter *to;
        size_t iov_count;
        ssize_t result;
+       struct lu_env *env = NULL;
+       __u16 refcheck;
        ENTRY;
 
        result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
@@ -1256,8 +1258,6 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                RETURN(result);
 
        if (nr_segs == 1) {
-               struct lu_env *env;
-               __u16 refcheck;
 
                env = cl_env_get(&refcheck);
                if (IS_ERR(env))
@@ -1266,7 +1266,6 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                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)
@@ -1290,7 +1289,9 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 
        OBD_FREE_PTR(to);
 out:
-       if (nr_segs > 1)
+       if (nr_segs == 1)
+               cl_env_put(env, &refcheck);
+       else
                OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
 
        RETURN(result);
@@ -1337,6 +1338,8 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        struct iov_iter *from;
        size_t iov_count;
        ssize_t result;
+       struct lu_env *env = NULL;
+       __u16 refcheck;
        ENTRY;
 
        result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
@@ -1344,17 +1347,12 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                RETURN(result);
 
        if (nr_segs == 1) {
-               struct lu_env *env;
-               __u16 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)
@@ -1378,7 +1376,9 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
        OBD_FREE_PTR(from);
 out:
-       if (nr_segs > 1)
+       if (nr_segs == 1)
+               cl_env_put(env, &refcheck);
+       else
                OBD_FREE(local_iov, sizeof(*iov) * nr_segs);
 
        RETURN(result);