From 1364ab2c166d69bc857a729f3eff2c965db847c9 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 22 May 2012 14:02:33 -0700 Subject: [PATCH] LU-1299 clio: a combo patch to fix cl_lock In this patch, the following issues are fixed: * redefine cl_lock_error(). There are two kinds of error when enqueuing a cl_lock: internal errors return from server side and local error for example interrupted by signal when waiting for a lock. Obviously the latter one is not fatal so we shouldn't err the lock out; * for fault handling, only signal SIGKILL and SIGTERM is not allowed; * handle return code of ll_fault correctly; * redefine ->unuse() to release resource it held if enqueuing lock failed; * in cl_lock_hold_release(), only CLS_CACHED mode lock will be cached, for locks in other states, they will be cancelled voluntarily; * fix the problem that cfs_block_sigs() is wrongly used as cfs_restore_sigs() and implementation of cfs_block_sigs() was wrong * other minor fixes. Signed-off-by: Jinshan Xiong Change-Id: Ice6d237d367c54bfd84a4a33cea8a4c1081e7696 Reviewed-on: http://review.whamcloud.com/2654 Reviewed-by: Andreas Dilger Tested-by: Hudson Reviewed-by: Niu Yawei Tested-by: Maloo Reviewed-by: Oleg Drokin --- libcfs/include/libcfs/libcfs.h | 2 +- libcfs/libcfs/darwin/darwin-prim.c | 8 ++-- libcfs/libcfs/linux/linux-prim.c | 38 ++++++++------- libcfs/libcfs/user-prim.c | 27 +++++------ lustre/include/cl_object.h | 8 ++++ lustre/include/lustre_lib.h | 2 +- lustre/include/obd_support.h | 1 + lustre/llite/llite_mmap.c | 95 +++++++++++++++++++++++++------------- lustre/lov/lov_lock.c | 10 +--- lustre/lov/lovsub_lock.c | 6 ++- lustre/obdclass/cl_lock.c | 92 ++++++++++++++++++------------------ lustre/obdclass/obd_mount.c | 2 +- lustre/osc/osc_lock.c | 4 ++ lustre/ptlrpc/client.c | 2 +- lustre/tests/sanity.sh | 12 +++++ 15 files changed, 181 insertions(+), 128 deletions(-) diff --git a/libcfs/include/libcfs/libcfs.h b/libcfs/include/libcfs/libcfs.h index f93285f..28e9f3b 100644 --- a/libcfs/include/libcfs/libcfs.h +++ b/libcfs/include/libcfs/libcfs.h @@ -223,7 +223,7 @@ void cfs_daemonize(char *str); int cfs_daemonize_ctxt(char *str); cfs_sigset_t cfs_get_blocked_sigs(void); cfs_sigset_t cfs_block_allsigs(void); -cfs_sigset_t cfs_block_sigs(cfs_sigset_t bits); +cfs_sigset_t cfs_block_sigs(unsigned long sigs); cfs_sigset_t cfs_block_sigsinv(unsigned long sigs); void cfs_restore_sigs(cfs_sigset_t); int cfs_signal_pending(void); diff --git a/libcfs/libcfs/darwin/darwin-prim.c b/libcfs/libcfs/darwin/darwin-prim.c index 6a8d80f..9544e46 100644 --- a/libcfs/libcfs/darwin/darwin-prim.c +++ b/libcfs/libcfs/darwin/darwin-prim.c @@ -375,14 +375,14 @@ cfs_sigset_t cfs_block_allsigs() return old; } -cfs_sigset_t cfs_block_sigs(sigset_t bit) +cfs_sigset_t cfs_block_sigs(unsigned long sigs) { - cfs_sigset_t old = 0; + cfs_sigset_t old = 0; #ifdef __DARWIN8__ #else - block_procsigmask(current_proc(), bit); + block_procsigmask(current_proc(), sigs); #endif - return old; + return old; } /* Block all signals except for the @sigs. It's only used in diff --git a/libcfs/libcfs/linux/linux-prim.c b/libcfs/libcfs/linux/linux-prim.c index 9ebfe70..e5c56b5 100644 --- a/libcfs/libcfs/linux/linux-prim.c +++ b/libcfs/libcfs/linux/linux-prim.c @@ -310,34 +310,32 @@ cfs_block_allsigs(void) return old; } -sigset_t -cfs_block_sigs(sigset_t bits) +sigset_t cfs_block_sigs(unsigned long sigs) { - unsigned long flags; - sigset_t old; + unsigned long flags; + sigset_t old; - SIGNAL_MASK_LOCK(current, flags); - old = current->blocked; - current->blocked = bits; - RECALC_SIGPENDING; - SIGNAL_MASK_UNLOCK(current, flags); - return old; + SIGNAL_MASK_LOCK(current, flags); + old = current->blocked; + sigaddsetmask(¤t->blocked, sigs); + RECALC_SIGPENDING; + SIGNAL_MASK_UNLOCK(current, flags); + return old; } /* Block all signals except for the @sigs */ -cfs_sigset_t -cfs_block_sigsinv(unsigned long sigs) +sigset_t cfs_block_sigsinv(unsigned long sigs) { - unsigned long flags; - cfs_sigset_t old; + unsigned long flags; + sigset_t old; - SIGNAL_MASK_LOCK(current, flags); - old = current->blocked; - siginitsetinv(¤t->blocked, sigs); - RECALC_SIGPENDING; - SIGNAL_MASK_UNLOCK(current, flags); + SIGNAL_MASK_LOCK(current, flags); + old = current->blocked; + sigaddsetmask(¤t->blocked, ~sigs); + RECALC_SIGPENDING; + SIGNAL_MASK_UNLOCK(current, flags); - return old; + return old; } void diff --git a/libcfs/libcfs/user-prim.c b/libcfs/libcfs/user-prim.c index c02a951..e6aaaea 100644 --- a/libcfs/libcfs/user-prim.c +++ b/libcfs/libcfs/user-prim.c @@ -282,26 +282,27 @@ int cfs_daemonize_ctxt(char *str) cfs_sigset_t cfs_block_allsigs(void) { - cfs_sigset_t all; - cfs_sigset_t old; - int rc; + cfs_sigset_t all; + cfs_sigset_t old; + int rc; - sigfillset(&all); - rc = sigprocmask(SIG_SETMASK, &all, &old); - LASSERT(rc == 0); + sigfillset(&all); + rc = sigprocmask(SIG_BLOCK, &all, &old); + LASSERT(rc == 0); - return old; + return old; } -cfs_sigset_t cfs_block_sigs(cfs_sigset_t blocks) +cfs_sigset_t cfs_block_sigs(unsigned long sigs) { - cfs_sigset_t old; - int rc; + cfs_sigset_t old; + cfs_sigset_t blocks = { { sigs } }; /* kludge */ + int rc; - rc = sigprocmask(SIG_SETMASK, &blocks, &old); - LASSERT (rc == 0); + rc = sigprocmask(SIG_BLOCK, &blocks, &old); + LASSERT (rc == 0); - return old; + return old; } /* Block all signals except for the @sigs. It's only used in diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index c0f014d..1acd1ba 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -1798,6 +1798,14 @@ do { \ } \ } while (0) +#define CL_LOCK_ASSERT(expr, env, lock) do { \ + if (likely(expr)) \ + break; \ + \ + CL_LOCK_DEBUG(D_ERROR, env, lock, "failed at %s.\n", #expr); \ + LBUG(); \ +} while (0) + /** @} cl_lock */ /** \addtogroup cl_page_list cl_page_list diff --git a/lustre/include/lustre_lib.h b/lustre/include/lustre_lib.h index 57430fc..7b19c51 100644 --- a/lustre/include/lustre_lib.h +++ b/lustre/include/lustre_lib.h @@ -782,7 +782,7 @@ do { \ } \ } \ \ - cfs_block_sigs(__blocked); \ + cfs_restore_sigs(__blocked); \ \ cfs_set_current_state(CFS_TASK_RUNNING); \ cfs_waitq_del(&wq, &__wait); \ diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index 800721e..9411f04 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -434,6 +434,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, #define OBD_FAIL_LLITE 0x1400 #define OBD_FAIL_LLITE_FAULT_TRUNC_RACE 0x1401 +#define OBD_FAIL_LOCK_STATE_WAIT_INTR 0x1402 /* Assign references to moved code to reduce code changes */ #define OBD_FAIL_PRECHECK(id) CFS_FAIL_PRECHECK(id) diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index 00e0c1a..ebdc99a 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -183,6 +183,7 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, struct vvp_io *vio; struct cl_env_nest nest; int result; + cfs_sigset_t set; ENTRY; LASSERT(vmpage != NULL); @@ -207,7 +208,9 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, vio->u.fault.ft_vma = vma; vio->u.fault.ft_vmpage = vmpage; - result = cl_io_loop(env, io); + set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM)); + result = cl_io_loop(env, io); + cfs_restore_sigs(set); if (result == -ENODATA) /* peek failed, no lock caching. */ CDEBUG(D_MMAP, "race on page_mkwrite: %lx (%lu %p)\n", @@ -292,6 +295,7 @@ struct page *ll_nopage(struct vm_area_struct *vma, unsigned long address, pgoff_t pg_offset; int result; const unsigned long writable = VM_SHARED|VM_WRITE; + cfs_sigset_t set; ENTRY; pg_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; @@ -311,10 +315,15 @@ struct page *ll_nopage(struct vm_area_struct *vma, unsigned long address, vio->u.fault.nopage.ft_type = type; vio->u.fault.ft_vmpage = NULL; - result = cl_io_loop(env, io); - page = vio->u.fault.ft_vmpage; - if (result != 0 && page != NULL) - page_cache_release(page); + set = cfs_block_sigsinv(sigmask(SIGKILL)|sigmask(SIGTERM)); + result = cl_io_loop(env, io); + cfs_restore_sigs(set); + + page = vio->u.fault.ft_vmpage; + if (result != 0 && page != NULL) { + page_cache_release(page); + page = NOPAGE_SIGBUS; + } out_err: if (result == -ENOMEM) @@ -330,6 +339,26 @@ out_err: } #else + +static inline int to_fault_error(int result) +{ + switch(result) { + case 0: + result = VM_FAULT_LOCKED; + break; + case -EFAULT: + result = VM_FAULT_NOPAGE; + break; + case -ENOMEM: + result = VM_FAULT_OOM; + break; + default: + result = VM_FAULT_SIGBUS; + break; + } + return result; +} + /** * Lustre implementation of a vm_operations_struct::fault() method, called by * VM to server page fault (both in kernel and user space). @@ -355,36 +384,31 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf) io = ll_fault_io_init(vma, &env, &nest, vmf->pgoff, &ra_flags); if (IS_ERR(io)) - RETURN(VM_FAULT_ERROR); + RETURN(to_fault_error(PTR_ERR(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.ft_vmpage = NULL; - vio->u.fault.fault.ft_vmf = vmf; - - result = cl_io_loop(env, io); - - vmpage = vio->u.fault.ft_vmpage; - if (result != 0 && vmpage != NULL) { - page_cache_release(vmpage); - vmf->page = NULL; + if (result == 0) { + vio = vvp_env_io(env); + vio->u.fault.ft_vma = vma; + vio->u.fault.ft_vmpage = NULL; + vio->u.fault.fault.ft_vmf = vmf; + + result = cl_io_loop(env, io); + + fault_ret = vio->u.fault.fault.ft_flags; + vmpage = vio->u.fault.ft_vmpage; + if (result != 0 && vmpage != NULL) { + page_cache_release(vmpage); + vmf->page = NULL; + } } - - fault_ret = vio->u.fault.fault.ft_flags; - -out_err: - if (result != 0 && fault_ret == 0) - fault_ret = VM_FAULT_ERROR; - - vma->vm_flags |= ra_flags; - cl_io_fini(env, io); cl_env_nested_put(&nest, env); + vma->vm_flags |= ra_flags; + if (result != 0 && !(fault_ret & VM_FAULT_RETRY)) + fault_ret |= to_fault_error(result); + CDEBUG(D_MMAP, "%s fault %d/%d\n", cfs_current()->comm, fault_ret, result); RETURN(fault_ret); @@ -392,9 +416,15 @@ out_err: static int ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - int count = 0; - bool printed = false; - int result; + int count = 0; + bool printed = false; + int result; + cfs_sigset_t set; + + /* Only SIGKILL and SIGTERM is allowed for fault/nopage/mkwrite + * so that it can be killed by admin but not cause segfault by + * other signals. */ + set = cfs_block_sigsinv(sigmask(SIGKILL) | sigmask(SIGTERM)); restart: result = ll_fault0(vma, vmf); @@ -421,6 +451,7 @@ restart: result |= VM_FAULT_LOCKED; } + cfs_restore_sigs(set); return result; } #endif diff --git a/lustre/lov/lov_lock.c b/lustre/lov/lov_lock.c index 4cd37e5..40192ce 100644 --- a/lustre/lov/lov_lock.c +++ b/lustre/lov/lov_lock.c @@ -751,17 +751,9 @@ static void lov_lock_cancel(const struct lu_env *env, switch(sublock->cll_state) { case CLS_HELD: - rc = cl_unuse_try(subenv->lse_env, - sublock); + rc = cl_unuse_try(subenv->lse_env, sublock); lov_sublock_release(env, lck, i, 0, 0); break; - case CLS_ENQUEUED: - /* TODO: it's not a good idea to cancel this - * lock because it's innocent. But it's - * acceptable. The better way would be to - * define a new lock method to unhold the - * dlm lock. */ - cl_lock_cancel(env, sublock); default: lov_sublock_release(env, lck, i, 1, 0); break; diff --git a/lustre/lov/lovsub_lock.c b/lustre/lov/lovsub_lock.c index e6484dc..ab1d9d9 100644 --- a/lustre/lov/lovsub_lock.c +++ b/lustre/lov/lovsub_lock.c @@ -299,6 +299,11 @@ static int lovsub_lock_delete_one(const struct lu_env *env, result = 0; switch (parent->cll_state) { + case CLS_ENQUEUED: + /* See LU-1355 for the case that a glimpse lock is + * interrupted by signal */ + LASSERT(parent->cll_flags & CLF_CANCELLED); + break; case CLS_QUEUING: case CLS_FREEING: cl_lock_signal(env, parent); @@ -374,7 +379,6 @@ static int lovsub_lock_delete_one(const struct lu_env *env, } } break; - case CLS_ENQUEUED: case CLS_HELD: CL_LOCK_DEBUG(D_ERROR, env, parent, "Delete CLS_HELD lock\n"); default: diff --git a/lustre/obdclass/cl_lock.c b/lustre/obdclass/cl_lock.c index 2dba495..677d652 100644 --- a/lustre/obdclass/cl_lock.c +++ b/lustre/obdclass/cl_lock.c @@ -603,19 +603,17 @@ struct cl_lock *cl_lock_peek(const struct lu_env *env, const struct cl_io *io, cl_lock_mutex_get(env, lock); if (lock->cll_state == CLS_INTRANSIT) cl_lock_state_wait(env, lock); /* Don't care return value. */ - if (lock->cll_state == CLS_CACHED) { - int result; - result = cl_use_try(env, lock, 1); - if (result < 0) - cl_lock_error(env, lock, result); - } - if (lock->cll_state == CLS_HELD) { - cl_lock_hold_add(env, lock, scope, source); - cl_lock_user_add(env, lock); - cl_lock_mutex_put(env, lock); - cl_lock_lockdep_acquire(env, lock, 0); - cl_lock_put(env, lock); - } else { + cl_lock_hold_add(env, lock, scope, source); + cl_lock_user_add(env, lock); + if (lock->cll_state == CLS_CACHED) + cl_use_try(env, lock, 1); + if (lock->cll_state == CLS_HELD) { + cl_lock_mutex_put(env, lock); + cl_lock_lockdep_acquire(env, lock, 0); + cl_lock_put(env, lock); + } else { + cl_unuse_try(env, lock); + cl_lock_unhold(env, lock, scope, source); cl_lock_mutex_put(env, lock); cl_lock_put(env, lock); lock = NULL; @@ -898,8 +896,10 @@ static void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock, lu_ref_del(&lock->cll_holders, scope, source); cl_lock_hold_mod(env, lock, -1); if (lock->cll_holds == 0) { - if (lock->cll_descr.cld_mode == CLM_PHANTOM || - lock->cll_descr.cld_mode == CLM_GROUP) + CL_LOCK_ASSERT(lock->cll_state != CLS_HELD, env, lock); + if (lock->cll_descr.cld_mode == CLM_PHANTOM || + lock->cll_descr.cld_mode == CLM_GROUP || + lock->cll_state != CLS_CACHED) /* * If lock is still phantom or grouplock when user is * done with it---destroy the lock. @@ -963,12 +963,17 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock) cl_lock_mutex_put(env, lock); LASSERT(cl_lock_nr_mutexed(env) == 0); - cfs_waitq_wait(&waiter, CFS_TASK_INTERRUPTIBLE); + + result = -EINTR; + if (likely(!OBD_FAIL_CHECK(OBD_FAIL_LOCK_STATE_WAIT_INTR))) { + cfs_waitq_wait(&waiter, CFS_TASK_INTERRUPTIBLE); + if (!cfs_signal_pending()) + result = 0; + } cl_lock_mutex_get(env, lock); cfs_set_current_state(CFS_TASK_RUNNING); cfs_waitq_del(&lock->cll_wq, &waiter); - result = cfs_signal_pending() ? -EINTR : 0; /* Restore old blocked signals */ cfs_restore_sigs(blocked); @@ -1178,12 +1183,12 @@ int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock, ENTRY; cl_lock_trace(D_DLMTRACE, env, "enqueue lock", lock); do { - result = 0; - LINVRNT(cl_lock_is_mutexed(lock)); - if (lock->cll_error != 0) + result = lock->cll_error; + if (result != 0) break; + switch (lock->cll_state) { case CLS_NEW: cl_lock_state_set(env, lock, CLS_QUEUING); @@ -1216,9 +1221,7 @@ int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock, LBUG(); } } while (result == CLO_REPEAT); - if (result < 0) - cl_lock_error(env, lock, result); - RETURN(result ?: lock->cll_error); + RETURN(result); } EXPORT_SYMBOL(cl_enqueue_try); @@ -1247,6 +1250,7 @@ int cl_lock_enqueue_wait(const struct lu_env *env, LASSERT(cl_lock_nr_mutexed(env) == 0); cl_lock_mutex_get(env, conflict); + cl_lock_trace(D_DLMTRACE, env, "enqueue wait", conflict); cl_lock_cancel(env, conflict); cl_lock_delete(env, conflict); @@ -1291,10 +1295,8 @@ static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock, } break; } while (1); - if (result != 0) { - cl_lock_user_del(env, lock); - cl_lock_error(env, lock, result); - } + if (result != 0) + cl_unuse_try(env, lock); LASSERT(ergo(result == 0 && !(enqflags & CEF_AGL), lock->cll_state == CLS_ENQUEUED || lock->cll_state == CLS_HELD)); @@ -1332,13 +1334,11 @@ EXPORT_SYMBOL(cl_enqueue); /** * Tries to unlock a lock. * - * This function is called repeatedly by cl_unuse() until either lock is - * unlocked, or error occurs. - * cl_unuse_try is a one-shot operation, so it must NOT return CLO_WAIT. - * - * \pre lock->cll_state == CLS_HELD + * This function is called to release underlying resource: + * 1. for top lock, the resource is sublocks it held; + * 2. for sublock, the resource is the reference to dlmlock. * - * \post ergo(result == 0, lock->cll_state == CLS_CACHED) + * cl_unuse_try is a one-shot operation, so it must NOT return CLO_WAIT. * * \see cl_unuse() cl_lock_operations::clo_unuse() * \see cl_lock_state::CLS_CACHED @@ -1351,12 +1351,18 @@ int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock) ENTRY; cl_lock_trace(D_DLMTRACE, env, "unuse lock", lock); - LASSERT(lock->cll_state == CLS_HELD || lock->cll_state == CLS_ENQUEUED); if (lock->cll_users > 1) { cl_lock_user_del(env, lock); RETURN(0); } + /* Only if the lock is in CLS_HELD or CLS_ENQUEUED state, it can hold + * underlying resources. */ + if (!(lock->cll_state == CLS_HELD || lock->cll_state == CLS_ENQUEUED)) { + cl_lock_user_del(env, lock); + RETURN(0); + } + /* * New lock users (->cll_users) are not protecting unlocking * from proceeding. From this point, lock eventually reaches @@ -1397,13 +1403,10 @@ int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock) result = 0; } else { CERROR("result = %d, this is unlikely!\n", result); + state = CLS_NEW; cl_lock_extransit(env, lock, state); } - - result = result ?: lock->cll_error; - if (result < 0) - cl_lock_error(env, lock, result); - RETURN(result); + RETURN(result ?: lock->cll_error); } EXPORT_SYMBOL(cl_unuse_try); @@ -1459,8 +1462,8 @@ int cl_wait_try(const struct lu_env *env, struct cl_lock *lock) LASSERT(lock->cll_users > 0); LASSERT(lock->cll_holds > 0); - result = 0; - if (lock->cll_error != 0) + result = lock->cll_error; + if (result != 0) break; if (cl_lock_is_intransit(lock)) { @@ -1486,7 +1489,7 @@ int cl_wait_try(const struct lu_env *env, struct cl_lock *lock) cl_lock_state_set(env, lock, CLS_HELD); } } while (result == CLO_REPEAT); - RETURN(result ?: lock->cll_error); + RETURN(result); } EXPORT_SYMBOL(cl_wait_try); @@ -1521,8 +1524,7 @@ int cl_wait(const struct lu_env *env, struct cl_lock *lock) break; } while (1); if (result < 0) { - cl_lock_user_del(env, lock); - cl_lock_error(env, lock, result); + cl_unuse_try(env, lock); cl_lock_lockdep_release(env, lock); } cl_lock_trace(D_DLMTRACE, env, "wait lock", lock); @@ -1790,8 +1792,8 @@ void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error) LINVRNT(cl_lock_invariant(env, lock)); ENTRY; - cl_lock_trace(D_DLMTRACE, env, "set lock error", lock); if (lock->cll_error == 0 && error != 0) { + cl_lock_trace(D_DLMTRACE, env, "set lock error", lock); lock->cll_error = error; cl_lock_signal(env, lock); cl_lock_cancel(env, lock); diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index 4efae3c..6785e29 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -1548,7 +1548,7 @@ static void server_wait_finished(struct vfsmount *mnt) (mnt_get_count(mnt) == 1), cfs_time_seconds(3), rc); - cfs_block_sigs(blocked); + cfs_restore_sigs(blocked); if (rc < 0) { LCONSOLE_EMERG("Danger: interrupted umount %s with " "%d refs!\n", mnt->mnt_devname, diff --git a/lustre/osc/osc_lock.c b/lustre/osc/osc_lock.c index 2767c30..de06556 100644 --- a/lustre/osc/osc_lock.c +++ b/lustre/osc/osc_lock.c @@ -200,6 +200,7 @@ static int osc_lock_unuse(const struct lu_env *env, LASSERT(!ols->ols_hold); LASSERT(ols->ols_agl); return 0; + case OLS_ENQUEUED: case OLS_UPCALL_RECEIVED: LASSERT(!ols->ols_hold); ols->ols_state = OLS_NEW; @@ -1546,6 +1547,9 @@ static int osc_lock_fits_into(const struct lu_env *env, if (need->cld_enq_flags & CEF_NEVER) return 0; + if (ols->ols_state >= OLS_CANCELLED) + return 0; + if (need->cld_mode == CLM_PHANTOM) { if (ols->ols_agl) return !(ols->ols_state > OLS_RELEASED); diff --git a/lustre/ptlrpc/client.c b/lustre/ptlrpc/client.c index 2995e6a..71e8e3a 100644 --- a/lustre/ptlrpc/client.c +++ b/lustre/ptlrpc/client.c @@ -2040,7 +2040,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * reentrant from userspace again */ if (cfs_signal_pending()) ptlrpc_interrupted_set(set); - cfs_block_sigs(blocked_sigs); + cfs_restore_sigs(blocked_sigs); } LASSERT(rc == 0 || rc == -EINTR || rc == -ETIMEDOUT); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index c9bbf5a..8573580 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -9285,6 +9285,18 @@ test_226 () { } run_test 226 "call path2fid and fid2path on files of all type" +# LU-1299 Executing or running ldd on a truncated executable does not +# cause an out-of-memory condition. +test_227() { + dd if=`which date` of=$MOUNT/date bs=1k count=1 + chmod +x $MOUNT/date + + $MOUNT/date > /dev/null + ldd $MOUNT/date > /dev/null + rm -f $MOUNT/date +} +run_test 227 "running truncated executable does not cause OOM" + # # tests that do cleanup/setup should be run at the end # -- 1.8.3.1