Whamcloud - gitweb
LU-300: Oops in cl_page_put of page fault path
authorJinshan Xiong <jay@whamcloud.com>
Wed, 11 May 2011 02:20:12 +0000 (19:20 -0700)
committerOleg Drokin <green@whamcloud.com>
Wed, 18 May 2011 23:05:26 +0000 (16:05 -0700)
This problem is due to the unintialization of cl_io, so that an invalid page
address will be accessed in vvp_io_fault_fini().

Change-Id: Ic85a5d22e175cc74ada0e51831142d9f37798c08
Signed-off-by: Jinshan Xiong <jay@whamcloud.com>
Reviewed-on: http://review.whamcloud.com/530
Tested-by: Hudson
Reviewed-by: wangdi <di.wang@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lclient.h
lustre/lclient/glimpse.c
lustre/lclient/lcommon_cl.c
lustre/lclient/lcommon_misc.c
lustre/liblustre/rw.c
lustre/llite/file.c
lustre/llite/llite_mmap.c
lustre/llite/rw.c

index 1883df6..1f5d908 100644 (file)
@@ -135,6 +135,13 @@ static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env)
         return attr;
 }
 
+static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env)
+{
+        struct cl_io *io = &ccc_env_info(env)->cti_io;
+        memset(io, 0, sizeof(*io));
+        return io;
+}
+
 struct ccc_session {
         struct ccc_io cs_ios;
 };
@@ -378,6 +385,7 @@ int cl_ocd_update(struct obd_device *host,
 
 struct ccc_grouplock {
         struct lu_env   *cg_env;
+        struct cl_io    *cg_io;
         struct cl_lock  *cg_lock;
         unsigned long    cg_gid;
 };
index 8c69708..268f5d7 100644 (file)
@@ -141,7 +141,6 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
 static int cl_io_get(struct inode *inode, struct lu_env **envout,
                      struct cl_io **ioout, int *refcheck)
 {
-        struct ccc_thread_info *info;
         struct lu_env          *env;
         struct cl_io           *io;
         struct cl_inode_info   *lli = cl_i2info(inode);
@@ -151,8 +150,7 @@ static int cl_io_get(struct inode *inode, struct lu_env **envout,
         if (S_ISREG(cl_inode_mode(inode))) {
                 env = cl_env_get(refcheck);
                 if (!IS_ERR(env)) {
-                        info = ccc_env_info(env);
-                        io = &info->cti_io;
+                        io = ccc_env_thread_io(env);
                         io->ci_obj = clob;
                         *envout = env;
                         *ioout  = io;
index 6096207..6bb311a 100644 (file)
@@ -1033,7 +1033,7 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-        io = &ccc_env_info(env)->cti_io;
+        io = ccc_env_thread_io(env);
         io->ci_obj = cl_i2info(inode)->lli_clob;
 
         io->u.ci_setattr.sa_attr.lvb_atime = LTIME_S(attr->ia_atime);
index 5b85217..1cd1897 100644 (file)
@@ -136,7 +136,7 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock,
         if (IS_ERR(env))
                 return PTR_ERR(env);
 
-        io = &ccc_env_info(env)->cti_io;
+        io = ccc_env_thread_io(env);
         io->ci_obj = obj;
 
         rc = cl_io_init(env, io, CIT_MISC, io->ci_obj);
@@ -163,9 +163,10 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock,
                 return PTR_ERR(lock);
         }
 
-        cg->cg_env = cl_env_get(&refcheck);
+        cg->cg_env  = cl_env_get(&refcheck);
+        cg->cg_io   = io;
         cg->cg_lock = lock;
-        cg->cg_gid = gid;
+        cg->cg_gid  = gid;
         LASSERT(cg->cg_env == env);
 
         cl_env_unplant(env, &refcheck);
@@ -174,9 +175,10 @@ int cl_get_grouplock(struct cl_object *obj, unsigned long gid, int nonblock,
 
 void cl_put_grouplock(struct ccc_grouplock *cg)
 {
-        struct lu_env          *env = cg->cg_env;
-        struct cl_lock         *lock = cg->cg_lock;
-        int                     refcheck;
+        struct lu_env  *env  = cg->cg_env;
+        struct cl_io   *io   = cg->cg_io;
+        struct cl_lock *lock = cg->cg_lock;
+        int             refcheck;
 
         LASSERT(cg->cg_env);
         LASSERT(cg->cg_gid);
@@ -186,7 +188,7 @@ void cl_put_grouplock(struct ccc_grouplock *cg)
 
         cl_unuse(env, lock);
         cl_lock_release(env, lock, GROUPLOCK_SCOPE, cfs_current());
-        cl_io_fini(env, &ccc_env_info(env)->cti_io);
+        cl_io_fini(env, io);
         cl_env_put(env, NULL);
 }
 
index 9d4d581..c8929f4 100644 (file)
@@ -329,8 +329,7 @@ ssize_t llu_file_prwv(const struct iovec *iovec, int iovlen,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-        io = &ccc_env_info(env)->cti_io;
-
+        io = ccc_env_thread_io(env);
         if (cl_io_rw_init(env, io, session->lis_cmd == OBD_BRW_WRITE?CIT_WRITE:
                                                                       CIT_READ,
                           pos, len) == 0) {
@@ -425,8 +424,6 @@ void llu_io_init(struct cl_io *io, struct inode *inode, int write)
 {
         struct llu_inode_info *lli = llu_i2info(inode);
 
-        memset(io, 0, sizeof *io);
-
         io->u.ci_rw.crw_nonblock = lli->lli_open_flags & O_NONBLOCK;
         if (write)
                 io->u.ci_wr.wr_append = lli->lli_open_flags & O_APPEND;
@@ -454,7 +451,7 @@ int llu_iop_read(struct inode *ino,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-        io = &ccc_env_info(env)->cti_io;
+        io = ccc_env_thread_io(env);
         llu_io_init(io, ino, 0);
 
         ret = llu_file_rwx(ino, ioctx, 1);
@@ -478,7 +475,7 @@ int llu_iop_write(struct inode *ino,
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-        io = &ccc_env_info(env)->cti_io;
+        io = ccc_env_thread_io(env);
         llu_io_init(io, ino, 1);
 
         ret = llu_file_rwx(ino, ioctx, 0);
index d316e18..e8a0cc1 100644 (file)
@@ -808,7 +808,6 @@ void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
         struct inode *inode = file->f_dentry->d_inode;
 
-        memset(io, 0, sizeof *io);
         io->u.ci_rw.crw_nonblock = file->f_flags & O_NONBLOCK;
         if (write)
                 io->u.ci_wr.wr_append = !!(file->f_flags & O_APPEND);
@@ -831,7 +830,7 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
         ssize_t               result;
         ENTRY;
 
-        io = &ccc_env_info(env)->cti_io;
+        io = ccc_env_thread_io(env);
         ll_io_init(io, file, iot == CIT_WRITE);
 
         if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
index 9611d6b..39d3756 100644 (file)
@@ -119,8 +119,10 @@ struct vm_area_struct * our_vma(unsigned long addr, size_t count)
  * \retval EINVAL if env can't allocated
  * \return other error codes from cl_io_init.
  */
-int ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret,
-                     struct cl_env_nest *nest, pgoff_t index, unsigned long *ra_flags)
+struct cl_io *ll_fault_io_init(struct vm_area_struct *vma,
+                               struct lu_env **env_ret,
+                               struct cl_env_nest *nest,
+                               pgoff_t index, unsigned long *ra_flags)
 {
         struct file       *file  = vma->vm_file;
         struct inode      *inode = file->f_dentry->d_inode;
@@ -130,8 +132,9 @@ int ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret,
         struct lu_env     *env;
         ENTRY;
 
+        *env_ret = NULL;
         if (ll_file_nolock(file))
-                RETURN(-EOPNOTSUPP);
+                RETURN(ERR_PTR(-EOPNOTSUPP));
 
         /*
          * page fault can be called when lustre IO is
@@ -141,14 +144,12 @@ int ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret,
          * one.
          */
         env = cl_env_nested_get(nest);
-        if (IS_ERR(env)) {
-                *env_ret = NULL;
-                 RETURN(-EINVAL);
-        }
+        if (IS_ERR(env))
+                 RETURN(ERR_PTR(-EINVAL));
 
         *env_ret = env;
 
-        io = &ccc_env_info(env)->cti_io;
+        io = ccc_env_thread_io(env);
         io->ci_obj = ll_i2info(inode)->lli_clob;
         LASSERT(io->ci_obj != NULL);
 
@@ -182,7 +183,7 @@ int ll_fault_io_init(struct vm_area_struct *vma, struct lu_env **env_ret,
                 cio->cui_fd  = fd;
         }
 
-        return io->ci_result;
+        return io;
 }
 
 #ifndef HAVE_VM_OP_FAULT
@@ -214,16 +215,15 @@ struct page *ll_nopage(struct vm_area_struct *vma, unsigned long address,
         ENTRY;
 
         pg_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-        result = ll_fault_io_init(vma, &env,  &nest, pg_offset, &ra_flags);
-        if (env == NULL)
+        io = ll_fault_io_init(vma, &env,  &nest, pg_offset, &ra_flags);
+        if (IS_ERR(io))
                 return NOPAGE_SIGBUS;
 
-        io = &ccc_env_info(env)->cti_io;
+        result = io->ci_result;
         if (result < 0)
                 goto out_err;
 
         vio = vvp_env_io(env);
-
         vio->u.fault.ft_vma            = vma;
         vio->u.fault.nopage.ft_address = address;
         vio->u.fault.nopage.ft_type    = type;
@@ -270,11 +270,11 @@ int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf)
         int                      fault_ret = 0;
         ENTRY;
 
-        result = ll_fault_io_init(vma, &env,  &nest, vmf->pgoff, &ra_flags);
-        if (env == NULL)
+        io = ll_fault_io_init(vma, &env,  &nest, vmf->pgoff, &ra_flags);
+        if (IS_ERR(io))
                 RETURN(VM_FAULT_ERROR);
 
-        io = &ccc_env_info(env)->cti_io;
+        result = io->ci_result;
         if (result < 0)
                 goto out_err;
 
index 7aab4bf..25f45fb 100644 (file)
@@ -159,7 +159,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file,
                  * so cl_io has to be created here.
                  */
 
-                io = &ccc_env_info(env)->cti_io;
+                io = ccc_env_thread_io(env);
                 vio = vvp_env_io(env);
                 ll_io_init(io, file, 1);
 
@@ -1142,11 +1142,11 @@ int ll_writepage(struct page *vmpage, struct writeback_control *unused)
         if (IS_ERR(env))
                 RETURN(PTR_ERR(env));
 
-        io    = &ccc_env_info(env)->cti_io;
         queue = &vvp_env_info(env)->vti_queue;
         clob  = ll_i2info(inode)->lli_clob;
         LASSERT(clob != NULL);
 
+        io = ccc_env_thread_io(env);
         io->ci_obj = clob;
         result = cl_io_init(env, io, CIT_MISC, clob);
         if (result == 0) {