Whamcloud - gitweb
b=23518 adjust a locktrace place.
[fs/lustre-release.git] / lustre / obdclass / cl_lock.c
index 575a54d..f842af3 100644 (file)
@@ -26,7 +26,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -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);
@@ -1927,6 +1975,7 @@ int cl_lock_page_out(const struct lu_env *env, struct cl_lock *lock,
         struct cl_2queue      *queue = &info->clt_queue;
         struct cl_lock_descr  *descr = &lock->cll_descr;
         long page_count;
+        int nonblock = 1, resched;
         int result;
 
         LINVRNT(cl_lock_invariant(env, lock));
@@ -1934,13 +1983,14 @@ int cl_lock_page_out(const struct lu_env *env, struct cl_lock *lock,
 
         io->ci_obj = cl_object_top(descr->cld_obj);
         result = cl_io_init(env, io, CIT_MISC, io->ci_obj);
-        if (result == 0) {
-                int nonblock = 1;
+        if (result != 0)
+                GOTO(out, result);
 
-restart:
+        do {
                 cl_2queue_init(queue);
                 cl_page_gang_lookup(env, descr->cld_obj, io, descr->cld_start,
-                                    descr->cld_end, &queue->c2_qin, nonblock);
+                                    descr->cld_end, &queue->c2_qin, nonblock,
+                                    &resched);
                 page_count = queue->c2_qin.pl_nr;
                 if (page_count > 0) {
                         result = cl_page_list_unmap(env, io, &queue->c2_qin);
@@ -1963,11 +2013,10 @@ restart:
                 }
                 cl_2queue_fini(env, queue);
 
-                if (nonblock) {
-                        nonblock = 0;
-                        goto restart;
-                }
-        }
+                if (resched)
+                        cfs_cond_resched();
+        } while (resched || nonblock--);
+out:
         cl_io_fini(env, io);
         RETURN(result);
 }
@@ -2092,14 +2141,10 @@ struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io,
                                 const char *scope, const void *source)
 {
         struct cl_lock       *lock;
-        const struct lu_fid  *fid;
         int                   rc;
-        int                   iter;
         __u32                 enqflags = need->cld_enq_flags;
 
         ENTRY;
-        fid = lu_object_fid(&io->ci_obj->co_lu);
-        iter = 0;
         do {
                 lock = cl_lock_hold_mutex(env, io, need, scope, source);
                 if (!IS_ERR(lock)) {
@@ -2121,7 +2166,6 @@ struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io,
                         lock = ERR_PTR(rc);
                 } else
                         rc = PTR_ERR(lock);
-                iter++;
         } while (rc == 0);
         RETURN(lock);
 }