X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdclass%2Fcl_lock.c;h=f842af30bc0addb6440055540551762779272e3e;hb=ec57f72913a3f9fb1464d8430ffb2e907098fbcc;hp=ad244e4789aae551cb4f2e9c9ac571c7f9deacce;hpb=f95393b0d0a59cf3dc2f29cffc35dcc4cc9d7728;p=fs%2Flustre-release.git diff --git a/lustre/obdclass/cl_lock.c b/lustre/obdclass/cl_lock.c index ad244e4..f842af3 100644 --- a/lustre/obdclass/cl_lock.c +++ b/lustre/obdclass/cl_lock.c @@ -132,8 +132,8 @@ static void cl_lock_trace0(int level, const struct lu_env *env, const char *func, const int line) { struct cl_object_header *h = cl_object_header(lock->cll_descr.cld_obj); - CDEBUG(level, "%s: %p@(%i %p %i %d %d %d %d %lx)" - "(%p/%d/%i) at %s():%d\n", + CDEBUG(level, "%s: %p@(%d %p %d %d %d %d %d %lx)" + "(%p/%d/%d) at %s():%d\n", prefix, lock, cfs_atomic_read(&lock->cll_ref), lock->cll_guarder, lock->cll_depth, lock->cll_state, lock->cll_error, lock->cll_holds, @@ -519,7 +519,7 @@ static struct cl_lock *cl_lock_lookup(const struct lu_env *env, lock->cll_error == 0 && !(lock->cll_flags & CLF_CANCELLED) && cl_lock_fits_into(env, lock, need, io); - CDEBUG(D_DLMTRACE, "has: "DDESCR"(%i) need: "DDESCR": %d\n", + CDEBUG(D_DLMTRACE, "has: "DDESCR"(%d) need: "DDESCR": %d\n", PDESCR(&lock->cll_descr), lock->cll_state, PDESCR(need), matched); if (matched) { @@ -1225,6 +1225,51 @@ int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock, } EXPORT_SYMBOL(cl_enqueue_try); +/** + * Cancel the conflicting lock found during previous enqueue. + * + * \retval 0 conflicting lock has been canceled. + * \retval -ve error code. + */ +int cl_lock_enqueue_wait(const struct lu_env *env, + struct cl_lock *lock, + int keep_mutex) +{ + struct cl_lock *conflict; + int rc = 0; + ENTRY; + + LASSERT(cl_lock_is_mutexed(lock)); + LASSERT(lock->cll_state == CLS_QUEUING); + LASSERT(lock->cll_conflict != NULL); + + conflict = lock->cll_conflict; + lock->cll_conflict = NULL; + + cl_lock_mutex_put(env, lock); + LASSERT(cl_lock_nr_mutexed(env) == 0); + + cl_lock_mutex_get(env, conflict); + cl_lock_cancel(env, conflict); + cl_lock_delete(env, conflict); + + while (conflict->cll_state != CLS_FREEING) { + rc = cl_lock_state_wait(env, conflict); + if (rc != 0) + break; + } + cl_lock_mutex_put(env, conflict); + lu_ref_del(&conflict->cll_reference, "cancel-wait", lock); + cl_lock_put(env, conflict); + + if (keep_mutex) + cl_lock_mutex_get(env, lock); + + LASSERT(rc <= 0); + RETURN(rc); +} +EXPORT_SYMBOL(cl_lock_enqueue_wait); + static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock, struct cl_io *io, __u32 enqflags) { @@ -1240,7 +1285,10 @@ static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock, do { result = cl_enqueue_try(env, lock, io, enqflags); if (result == CLO_WAIT) { - result = cl_lock_state_wait(env, lock); + if (lock->cll_conflict != NULL) + result = cl_lock_enqueue_wait(env, lock, 1); + else + result = cl_lock_state_wait(env, lock); if (result == 0) continue; } @@ -1464,7 +1512,6 @@ int cl_wait(const struct lu_env *env, struct cl_lock *lock) LASSERTF(lock->cll_state == CLS_ENQUEUED || lock->cll_state == CLS_HELD, "Wrong state %d \n", lock->cll_state); LASSERT(lock->cll_holds > 0); - cl_lock_trace(D_DLMTRACE, env, "wait lock", lock); do { result = cl_wait_try(env, lock); @@ -1480,6 +1527,7 @@ int cl_wait(const struct lu_env *env, struct cl_lock *lock) cl_lock_error(env, lock, result); cl_lock_lockdep_release(env, lock); } + cl_lock_trace(D_DLMTRACE, env, "wait lock", lock); cl_lock_mutex_put(env, lock); LASSERT(ergo(result == 0, lock->cll_state == CLS_HELD)); RETURN(result);