--- lustre-2.1.2.orig/lustre/obdclass/cl_lock.c 2012-10-05 17:18:37.000000000 +0200 +++ lustre-2.1.2.bfi/lustre/obdclass/cl_lock.c 2012-10-18 16:11:47.713063955 +0200 @@ -1880,6 +1880,74 @@ EXPORT_SYMBOL(cl_lock_at_page); /** + * Finds an existing lock covering given page and optionally different from a + * given \a except lock. With debug traces+check. + */ +struct cl_lock *cl_lock_at_page_dup(const struct lu_env *env, struct cl_object *obj, + struct cl_page *page, struct cl_lock *except, + int pending, int canceld) +{ + struct cl_object_header *head; + struct cl_lock *scan; + struct cl_lock *lock; + struct cl_lock_descr *need; + + ENTRY; + + head = cl_object_header(obj); + need = &cl_env_info(env)->clt_descr; + lock = NULL; + + need->cld_mode = CLM_READ; /* CLM_READ matches both READ & WRITE, but + * not PHANTOM */ + need->cld_start = need->cld_end = page->cp_index; + need->cld_enq_flags = 0; + + cfs_spin_lock(&head->coh_lock_guard); + /* It is fine to match any group lock since there could be only one + * with a uniq gid and it conflicts with all other lock modes too */ + cfs_list_for_each_entry(scan, &head->coh_locks, cll_linkage) { + if (scan != except && + (scan->cll_descr.cld_mode == CLM_GROUP || + cl_lock_ext_match(&scan->cll_descr, need)) && + scan->cll_state >= CLS_HELD && + scan->cll_state < CLS_FREEING && + /* + * This check is racy as the lock can be canceled right + * after it is done, but this is fine, because page exists + * already. + */ + (canceld || !(scan->cll_flags & CLF_CANCELLED)) && + (pending || !(scan->cll_flags & CLF_CANCELPEND))) { + /* Don't increase cs_hit here since this + * is just a helper function. */ + cl_lock_get_trust(scan); + lock = scan; + break; + } + } + + if (lock == NULL) { + struct cl_object_header *head; + struct cl_lock *scan; + + head = cl_object_header(page->cp_obj); + cfs_list_for_each_entry(scan, &head->coh_locks, + cll_linkage) + CL_LOCK_DEBUG(D_ERROR, env, scan, + "no cover page!\n"); + CL_PAGE_DEBUG(D_ERROR, env, page, + "dump uncover page!\n"); + libcfs_debug_dumpstack(NULL); + LBUG(); + } + + cfs_spin_unlock(&head->coh_lock_guard); + RETURN(lock); +} +EXPORT_SYMBOL(cl_lock_at_page); + +/** * Calculate the page offset at the layer of @lock. * At the time of this writing, @page is top page and @lock is sub lock. */ --- lustre-2.1.2.orig/lustre/osc/osc_io.c 2012-10-05 17:18:37.000000000 +0200 +++ lustre-2.1.2.bfi/lustre/osc/osc_io.c 2012-10-18 15:53:30.663130201 +0200 @@ -686,7 +686,7 @@ struct cl_page, cp_flight); opg = osc_cl_page_osc(apage); apage = opg->ops_cl.cpl_page; /* now apage is a sub-page */ - lock = cl_lock_at_page(env, apage->cp_obj, apage, NULL, 1, 1); + lock = cl_lock_at_page_dup(env, apage->cp_obj, apage, NULL, 1, 1); if (lock == NULL) { struct cl_object_header *head; struct cl_lock *scan;