From: Jinshan Xiong Date: Thu, 29 May 2014 23:36:37 +0000 (-0700) Subject: LU-5108 llite: define per open file cache for ll_cl_context X-Git-Tag: 2.5.60~1 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=f1b9122ce683c78f83fe05850728fea3662fe006 LU-5108 llite: define per open file cache for ll_cl_context In ll_readpage and ll_write_begin, it needs to find out the cl_env and cl_io, a.k.a ll_cl_context, when the IO is initialized. It used to call cl_env_get() to figure it out but turned out to be contended if multiple threads are doing IO. In this patch, a per open file ll_cl_context cache is created. When IO type of CIT_READ, CIT_WRITE and CIR_FAULT is initialized, it will add a ll_cl_context into the cache maintained in ll_file_data. In this case, the ll_cl_context can be found in ll_readpage and ll_write_begin later. Signed-off-by: Jinshan Xiong Change-Id: I757d1df44f60c8b79be7bb458df59350be72d86b Reviewed-on: http://review.whamcloud.com/10503 Tested-by: Jenkins Reviewed-by: Lai Siyao Reviewed-by: Bobi Jam Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 8f7321d..614df9b 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -543,6 +543,10 @@ static int ll_local_open(struct file *file, struct lookup_intent *it, ll_readahead_init(inode, &fd->fd_ras); fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); + /* ll_cl_context initialize */ + rwlock_init(&fd->fd_lock); + INIT_LIST_HEAD(&fd->fd_lccs); + RETURN(0); } @@ -1160,8 +1164,10 @@ restart: struct ccc_io *cio = ccc_env_io(env); int write_mutex_locked = 0; - cio->cui_fd = LUSTRE_FPRIVATE(file); - vio->cui_io_subtype = args->via_io_subtype; + cio->cui_fd = LUSTRE_FPRIVATE(file); + vio->cui_io_subtype = args->via_io_subtype; + + ll_cl_add(file, env, io); switch (vio->cui_io_subtype) { case IO_NORMAL: @@ -1191,6 +1197,7 @@ restart: up_read(&lli->lli_trunc_sem); if (write_mutex_locked) mutex_unlock(&lli->lli_write_mutex); + ll_cl_remove(file, env); } else { /* cl_io_rw_init() handled IO */ result = io->ci_result; diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index cb6a254..85ea3ab 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -668,6 +668,8 @@ struct ll_file_data { * true: failure is known, not report again. * false: unknown failure, should report. */ bool fd_write_failed; + rwlock_t fd_lock; /* protect lcc list */ + struct list_head fd_lccs; /* list of ll_cl_context */ }; struct lov_stripe_md; @@ -758,8 +760,9 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, struct cl_page_list *queue, struct ll_readahead_state *ras, bool hit); int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io); -struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage); -void ll_cl_fini(struct ll_cl_context *lcc); +struct ll_cl_context *ll_cl_find(struct file *file); +void ll_cl_add(struct file *file, const struct lu_env *env, struct cl_io *io); +void ll_cl_remove(struct file *file, const struct lu_env *env); #ifndef MS_HAS_NEW_AOPS extern const struct address_space_operations ll_aops; @@ -989,11 +992,11 @@ struct vvp_io_args { }; struct ll_cl_context { - void *lcc_cookie; - struct cl_io *lcc_io; - struct cl_page *lcc_page; - struct lu_env *lcc_env; - int lcc_refcheck; + struct list_head lcc_list; + void *lcc_cookie; + const struct lu_env *lcc_env; + struct cl_io *lcc_io; + struct cl_page *lcc_page; }; struct vvp_thread_info { diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index 3a24076..eab0a31 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -318,8 +318,13 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf) vio->u.fault.ft_vmpage = NULL; vio->u.fault.fault.ft_vmf = vmf; + /* May call ll_readpage() */ + ll_cl_add(vma->vm_file, env, io); + result = cl_io_loop(env, io); + ll_cl_remove(vma->vm_file, env); + fault_ret = vio->u.fault.fault.ft_flags; vmpage = vio->u.fault.ft_vmpage; if (result != 0 && vmpage != NULL) { diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index 355d07e..8ea255a 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -62,83 +62,6 @@ #include "llite_internal.h" #include -/** - * Finalizes cl-data before exiting typical address_space operation. Dual to - * ll_cl_init(). - */ -void ll_cl_fini(struct ll_cl_context *lcc) -{ - struct lu_env *env = lcc->lcc_env; - struct cl_io *io = lcc->lcc_io; - struct cl_page *page = lcc->lcc_page; - - LASSERT(lcc->lcc_cookie == current); - LASSERT(env != NULL); - - if (page != NULL) { - lu_ref_del(&page->cp_reference, "cl_io", io); - cl_page_put(env, page); - } - - cl_env_put(env, &lcc->lcc_refcheck); -} - -/** - * Initializes common cl-data at the typical address_space operation entry - * point. - */ -struct ll_cl_context *ll_cl_init(struct file *file, struct page *vmpage) -{ - struct ll_cl_context *lcc; - struct lu_env *env; - struct cl_io *io; - struct cl_object *clob; - struct ccc_io *cio; - - int refcheck; - int result = 0; - - clob = ll_i2info(file->f_dentry->d_inode)->lli_clob; - LASSERT(clob != NULL); - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - return ERR_PTR(PTR_ERR(env)); - - lcc = &vvp_env_info(env)->vti_io_ctx; - memset(lcc, 0, sizeof(*lcc)); - lcc->lcc_env = env; - lcc->lcc_refcheck = refcheck; - lcc->lcc_cookie = current; - - cio = ccc_env_io(env); - io = cio->cui_cl.cis_io; - lcc->lcc_io = io; - if (io == NULL) - result = -EIO; - if (result == 0 && vmpage != NULL) { - struct cl_page *page; - - LASSERT(io != NULL); - LASSERT(io->ci_state == CIS_IO_GOING); - LASSERT(cio->cui_fd == LUSTRE_FPRIVATE(file)); - page = cl_page_find(env, clob, vmpage->index, vmpage, - CPT_CACHEABLE); - if (!IS_ERR(page)) { - lcc->lcc_page = page; - lu_ref_add(&page->cp_reference, "cl_io", io); - result = 0; - } else - result = PTR_ERR(page); - } - if (result) { - ll_cl_fini(lcc); - lcc = ERR_PTR(result); - } - - return lcc; -} - struct obd_capa *cl_capa_lookup(struct inode *inode, enum cl_req_type crt) { __u64 opc; @@ -1172,33 +1095,87 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc) RETURN(result); } +struct ll_cl_context *ll_cl_find(struct file *file) +{ + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct ll_cl_context *lcc; + struct ll_cl_context *found = NULL; + + read_lock(&fd->fd_lock); + list_for_each_entry(lcc, &fd->fd_lccs, lcc_list) { + if (lcc->lcc_cookie == current) { + found = lcc; + break; + } + } + read_unlock(&fd->fd_lock); + + return found; +} + +void ll_cl_add(struct file *file, const struct lu_env *env, struct cl_io *io) +{ + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct ll_cl_context *lcc = &vvp_env_info(env)->vti_io_ctx; + + memset(lcc, 0, sizeof(*lcc)); + INIT_LIST_HEAD(&lcc->lcc_list); + lcc->lcc_cookie = current; + lcc->lcc_env = env; + lcc->lcc_io = io; + + write_lock(&fd->fd_lock); + list_add(&lcc->lcc_list, &fd->fd_lccs); + write_unlock(&fd->fd_lock); +} + +void ll_cl_remove(struct file *file, const struct lu_env *env) +{ + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct ll_cl_context *lcc = &vvp_env_info(env)->vti_io_ctx; + + write_lock(&fd->fd_lock); + list_del_init(&lcc->lcc_list); + write_unlock(&fd->fd_lock); +} + int ll_readpage(struct file *file, struct page *vmpage) { - struct ll_cl_context *lcc; - int result; - ENTRY; + struct cl_object *clob = ll_i2info(file->f_dentry->d_inode)->lli_clob; + struct ll_cl_context *lcc; + const struct lu_env *env; + struct cl_io *io; + struct cl_page *page; + int result; + ENTRY; - lcc = ll_cl_init(file, vmpage); - if (!IS_ERR(lcc)) { - struct lu_env *env = lcc->lcc_env; - struct cl_io *io = lcc->lcc_io; - struct cl_page *page = lcc->lcc_page; + lcc = ll_cl_find(file); + if (lcc == NULL) { + unlock_page(vmpage); + RETURN(-EIO); + } - LASSERT(page->cp_type == CPT_CACHEABLE); - if (likely(!PageUptodate(vmpage))) { - cl_page_assume(env, io, page); - result = cl_io_read_page(env, io, page); - } else { - /* Page from a non-object file. */ - unlock_page(vmpage); - result = 0; - } - ll_cl_fini(lcc); - } else { - unlock_page(vmpage); - result = PTR_ERR(lcc); + env = lcc->lcc_env; + io = lcc->lcc_io; + LASSERT(io != NULL); + LASSERT(io->ci_state == CIS_IO_GOING); + page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE); + if (!IS_ERR(page)) { + LASSERT(page->cp_type == CPT_CACHEABLE); + if (likely(!PageUptodate(vmpage))) { + cl_page_assume(env, io, page); + result = cl_io_read_page(env, io, page); + } else { + /* Page from a non-object file. */ + unlock_page(vmpage); + result = 0; + } + cl_page_put(env, page); + } else { + unlock_page(vmpage); + result = PTR_ERR(page); } - RETURN(result); + RETURN(result); } int ll_page_sync_io(const struct lu_env *env, struct cl_io *io, diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index c3fe272..b605fa4 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -533,7 +533,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, struct page **pagep, void **fsdata) { struct ll_cl_context *lcc; - struct lu_env *env; + const struct lu_env *env; struct cl_io *io; struct cl_page *page; @@ -547,9 +547,9 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, CDEBUG(D_VFSTRACE, "Writing %lu of %d to %d bytes\n", index, from, len); - lcc = ll_cl_init(file, NULL); - if (IS_ERR(lcc)) - GOTO(out, result = PTR_ERR(lcc)); + lcc = ll_cl_find(file); + if (lcc == NULL) + GOTO(out, result = -EIO); env = lcc->lcc_env; io = lcc->lcc_io; @@ -619,8 +619,6 @@ out: unlock_page(vmpage); page_cache_release(vmpage); } - if (!IS_ERR(lcc)) - ll_cl_fini(lcc); } else { *pagep = vmpage; *fsdata = lcc; @@ -633,7 +631,7 @@ static int ll_write_end(struct file *file, struct address_space *mapping, struct page *vmpage, void *fsdata) { struct ll_cl_context *lcc = fsdata; - struct lu_env *env; + const struct lu_env *env; struct cl_io *io; struct ccc_io *cio; struct cl_page *page; @@ -678,15 +676,17 @@ static int ll_write_end(struct file *file, struct address_space *mapping, } else { cl_page_disown(env, io, page); + lcc->lcc_page = NULL; + lu_ref_del(&page->cp_reference, "cl_io", io); + cl_page_put(env, page); + /* page list is not contiguous now, commit it now */ unplug = true; } - if (unplug || file->f_flags & O_SYNC || IS_SYNC(file->f_dentry->d_inode)) result = vvp_io_write_commit(env, io); - ll_cl_fini(lcc); RETURN(result >= 0 ? copied : result); }