From: Liu Xuezhao Date: Wed, 7 Nov 2012 03:17:44 +0000 (+0800) Subject: LU-1337 llite: take trunc_sem outside cl_io_loop for mkwrite X-Git-Tag: 2.3.57~62 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=77e2f09e3ba863018ff373e198ac0e62487aa675;p=fs%2Flustre-release.git LU-1337 llite: take trunc_sem outside cl_io_loop for mkwrite In truncate path it acquires lli_trunc_sem and then dlm lock, so in page_mkwrite we should take it in the same sequence to avoid dead lock. This is a fix for f78805dbf041bb42b250fe754dff7b864856203f . Signed-off-by: Liu Xuezhao Change-Id: Idb5574bffdaf00461befd43b867cdd9b3e549efe Reviewed-on: http://review.whamcloud.com/4485 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index 5310b14..3a0c077 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -172,38 +172,51 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma, static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, bool *retry) { - struct lu_env *env; - struct cl_io *io; - struct vvp_io *vio; - struct cl_env_nest nest; - int result; + struct lu_env *env; + struct cl_io *io; + struct vvp_io *vio; + struct cl_env_nest nest; + int result; cfs_sigset_t set; - ENTRY; + struct inode *inode; + struct ll_inode_info *lli; + ENTRY; - LASSERT(vmpage != NULL); + LASSERT(vmpage != NULL); - io = ll_fault_io_init(vma, &env, &nest, vmpage->index, NULL); - if (IS_ERR(io)) - GOTO(out, result = PTR_ERR(io)); + io = ll_fault_io_init(vma, &env, &nest, vmpage->index, NULL); + if (IS_ERR(io)) + GOTO(out, result = PTR_ERR(io)); - result = io->ci_result; - if (result < 0) - GOTO(out, result); + result = io->ci_result; + if (result < 0) + GOTO(out, result); - /* Don't enqueue new locks for page_mkwrite(). - * If the lock has been cancelled then page must have been - * truncated, in that case, kernel will handle it. - */ - io->ci_lockreq = CILR_PEEK; - io->u.ci_fault.ft_mkwrite = 1; - io->u.ci_fault.ft_writable = 1; + /* Don't enqueue new locks for page_mkwrite(). + * If the lock has been cancelled then page must have been + * truncated, in that case, kernel will handle it. + */ + io->ci_lockreq = CILR_PEEK; + io->u.ci_fault.ft_mkwrite = 1; + io->u.ci_fault.ft_writable = 1; - vio = vvp_env_io(env); - vio->u.fault.ft_vma = vma; - vio->u.fault.ft_vmpage = vmpage; + vio = vvp_env_io(env); + vio->u.fault.ft_vma = vma; + vio->u.fault.ft_vmpage = vmpage; set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM)); + + /* we grab lli_trunc_sem to exclude truncate case. + * Otherwise, we could add dirty pages into osc cache + * while truncate is on-going. */ + inode = ccc_object_inode(io->ci_obj); + lli = ll_i2info(inode); + cfs_down_read(&lli->lli_trunc_sem); + result = cl_io_loop(env, io); + + cfs_up_read(&lli->lli_trunc_sem); + cfs_restore_sigs(set); if (result == -ENODATA) /* peek failed, no lock caching. */ diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index a656e71..46644c8 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -663,7 +663,6 @@ static int vvp_io_fault_start(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct cl_object *obj = io->ci_obj; struct inode *inode = ccc_object_inode(obj); - struct ll_inode_info *lli = ll_i2info(inode); struct cl_fault_io *fio = &io->u.ci_fault; struct vvp_fault_io *cfio = &vio->u.fault; loff_t offset; @@ -688,11 +687,6 @@ static int vvp_io_fault_start(const struct lu_env *env, /* must return locked page */ if (fio->ft_mkwrite) { - /* we grab lli_trunc_sem to exclude truncate case. - * Otherwise, we could add dirty pages into osc cache - * while truncate is on-going. */ - cfs_down_read(&lli->lli_trunc_sem); - LASSERT(cfio->ft_vmpage != NULL); lock_page(cfio->ft_vmpage); } else { @@ -777,8 +771,6 @@ out: /* return unlocked vmpage to avoid deadlocking */ if (vmpage != NULL) unlock_page(vmpage); - if (fio->ft_mkwrite) - cfs_up_read(&lli->lli_trunc_sem); #ifdef HAVE_VM_OP_FAULT cfio->fault.ft_flags &= ~VM_FAULT_LOCKED; #endif