From: Jinshan Xiong Date: Wed, 11 May 2011 02:20:12 +0000 (-0700) Subject: LU-300: Oops in cl_page_put of page fault path X-Git-Tag: 2.0.61.0~16 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=15ac26cb2fc0b9b4c6c4507d8cdab683b9b40b7e;p=fs%2Flustre-release.git LU-300: Oops in cl_page_put of page fault path 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 Reviewed-on: http://review.whamcloud.com/530 Tested-by: Hudson Reviewed-by: wangdi Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lclient.h b/lustre/include/lclient.h index 1883df6..1f5d908 100644 --- a/lustre/include/lclient.h +++ b/lustre/include/lclient.h @@ -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; }; diff --git a/lustre/lclient/glimpse.c b/lustre/lclient/glimpse.c index 8c69708..268f5d7 100644 --- a/lustre/lclient/glimpse.c +++ b/lustre/lclient/glimpse.c @@ -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; diff --git a/lustre/lclient/lcommon_cl.c b/lustre/lclient/lcommon_cl.c index 6096207..6bb311a 100644 --- a/lustre/lclient/lcommon_cl.c +++ b/lustre/lclient/lcommon_cl.c @@ -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); diff --git a/lustre/lclient/lcommon_misc.c b/lustre/lclient/lcommon_misc.c index 5b85217..1cd1897 100644 --- a/lustre/lclient/lcommon_misc.c +++ b/lustre/lclient/lcommon_misc.c @@ -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); } diff --git a/lustre/liblustre/rw.c b/lustre/liblustre/rw.c index 9d4d581..c8929f4 100644 --- a/lustre/liblustre/rw.c +++ b/lustre/liblustre/rw.c @@ -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); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index d316e18..e8a0cc1 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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) { diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index 9611d6b..39d3756 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -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; diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index 7aab4bf..25f45fb 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -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) {