Whamcloud - gitweb
b=15346
authorvs <vs>
Wed, 28 May 2008 23:49:03 +0000 (23:49 +0000)
committervs <vs>
Wed, 28 May 2008 23:49:03 +0000 (23:49 +0000)
i=green,shadow,vitaly

skiplists are used to group compatible locks on granted list
that was implemented as tracking first and last lock of each lock group
the patch changes that to using doubly linked circular lists

lustre/ChangeLog
lustre/include/lustre_dlm.h
lustre/ldlm/ldlm_inodebits.c
lustre/ldlm/ldlm_lock.c
lustre/ldlm/ldlm_plain.c
lustre/mdc/mdc_locks.c

index 1112ee6..de18065 100644 (file)
@@ -1059,6 +1059,13 @@ Details    : If there are additional extended attributes stored on the MDS,
             external attribute block (e.g. ACL growing in size) for file
             data to be lost.
 
+Severity   : normal
+Bugzilla   : 15346
+Description: skiplist implementation simplification
+Details    : skiplists are used to group compatible locks on granted list
+             that was implemented as tracking first and last lock of each lock group
+             the patch changes that to using doubly linked lists
+
 --------------------------------------------------------------------------------
 
 2007-08-10         Cluster File Systems, Inc. <info@clusterfs.com>
index b8f95c0..9ddb35b 100644 (file)
@@ -156,12 +156,6 @@ typedef enum {
 #define LDLM_CB_BLOCKING    1
 #define LDLM_CB_CANCELING   2
 
-/* position flag of skip list pointers */
-#define LDLM_SL_HEAD(skip_list)   ((skip_list)->next != NULL)
-#define LDLM_SL_TAIL(skip_list)   ((skip_list)->prev != NULL)
-#define LDLM_SL_EMPTY(skip_list)  ((skip_list)->next == NULL && \
-                                   (skip_list)->prev == NULL)
-
 /* compatibility matrix */
 #define LCK_COMPAT_EX  LCK_NL
 #define LCK_COMPAT_PW  (LCK_COMPAT_EX | LCK_CR)
@@ -416,11 +410,8 @@ struct ldlm_lock {
         /* protected by ns_hash_lock. FIXME */
         struct list_head      l_lru;
 
-        /* protected by lr_lock */
-        struct list_head      l_res_link; // position in one of three res lists
-
-        struct list_head      l_sl_mode;        // skip pointer for request mode
-        struct list_head      l_sl_policy;      // skip pointer for inodebits
+        /* protected by lr_lock, linkage to resource's lock queues */
+        struct list_head      l_res_link;
 
         struct ldlm_interval *l_tree_node;      /* tree node for ldlm_extent */
 
@@ -475,6 +466,10 @@ struct ldlm_lock {
         struct list_head      l_cp_ast;
         struct ldlm_lock     *l_blocking_lock;
         int                   l_bl_ast_run;
+
+        /* protected by lr_lock, linkages to "skip lists" */
+        struct list_head      l_sl_mode;
+        struct list_head      l_sl_policy;
 };
 
 struct ldlm_resource {
index 9755425..66622f7 100644 (file)
@@ -37,7 +37,7 @@ static int
 ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                             struct list_head *work_list)
 {
-        struct list_head *tmp, *tmp_tail;
+        struct list_head *tmp;
         struct ldlm_lock *lock;
         ldlm_mode_t req_mode = req->l_req_mode;
         __u64 req_bits = req->l_policy_data.l_inodebits.bits;
@@ -47,28 +47,36 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
         LASSERT(req_bits); /* There is no sense in lock with no bits set,
                               I think. Also such a lock would be compatible
                                with any other bit lock */
+
         list_for_each(tmp, queue) {
+                struct list_head *mode_tail;
+
                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
 
                 if (req == lock)
                         RETURN(compat);
 
+                /* last lock in mode group */
+                LASSERT(lock->l_sl_mode.prev != NULL);
+                mode_tail = &list_entry(lock->l_sl_mode.prev,
+                                        struct ldlm_lock,
+                                        l_sl_mode)->l_res_link;
+
                 /* locks are compatible, bits don't matter */
                 if (lockmode_compat(lock->l_req_mode, req_mode)) {
-                        /* jump to next mode group */
-                        if (LDLM_SL_HEAD(&lock->l_sl_mode))
-                                tmp = &list_entry(lock->l_sl_mode.next, 
-                                                  struct ldlm_lock,
-                                                  l_sl_mode)->l_res_link;
+                        /* jump to last lock in mode group */
+                        tmp = mode_tail;
                         continue;
                 }
                 
-                tmp_tail = tmp;
-                if (LDLM_SL_HEAD(&lock->l_sl_mode))
-                        tmp_tail = &list_entry(lock->l_sl_mode.next,
-                                               struct ldlm_lock,
-                                               l_sl_mode)->l_res_link;
                 for (;;) {
+                        struct list_head *head;
+
+                        /* last lock in policy group */
+                        tmp = &list_entry(lock->l_sl_policy.prev,
+                                          struct ldlm_lock,
+                                          l_sl_policy)->l_res_link;
+
                         /* locks with bits overlapped are conflicting locks */
                         if (lock->l_policy_data.l_inodebits.bits & req_bits) {
                                 /* conflicting policy */
@@ -76,36 +84,26 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                                         RETURN(0);
 
                                 compat = 0;
+
+                                /* add locks of the policy group to
+                                 * @work_list as blocking locks for
+                                 * @req */
                                 if (lock->l_blocking_ast)
-                                        ldlm_add_ast_work_item(lock, req, 
+                                        ldlm_add_ast_work_item(lock, req,
                                                                work_list);
-                                /* add all members of the policy group */
-                                if (LDLM_SL_HEAD(&lock->l_sl_policy)) {
-                                        do {
-                                                tmp = lock->l_res_link.next;
-                                                lock = list_entry(tmp,
-                                                            struct ldlm_lock,
-                                                            l_res_link);
-                                                if (lock->l_blocking_ast)
-                                                        ldlm_add_ast_work_item(
-                                                                     lock,
-                                                                     req,
-                                                                     work_list);
-                                        } while (!LDLM_SL_TAIL(&lock->l_sl_policy));
-                                }
-                        } else if (LDLM_SL_HEAD(&lock->l_sl_policy)) {
-                                /* jump to next policy group */
-                                tmp = &list_entry(lock->l_sl_policy.next,
-                                                  struct ldlm_lock,
-                                                  l_sl_policy)->l_res_link;
+                                head = &lock->l_sl_policy;
+                                list_for_each_entry(lock, head, l_sl_policy)
+                                        if (lock->l_blocking_ast)
+                                                ldlm_add_ast_work_item(lock, req,
+                                                                       work_list);
                         }
-                        if (tmp == tmp_tail)
+                        if (tmp == mode_tail)
                                 break;
-                        else
-                                tmp = tmp->next;
+
+                        tmp = tmp->next;
                         lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-                }       /* for locks in a mode group */
-        }       /* for each lock in the queue */
+                } /* loop over policy groups within one mode group */
+        } /* loop over mode groups within @queue */
 
         RETURN(compat);
 }
index 606a8fe..286197f 100644 (file)
 #include <obd_class.h>
 #include "ldlm_internal.h"
 
-/* lock's skip list pointers fix mode */
-#define LDLM_JOIN_NONE          0
-#define LDLM_MODE_JOIN_RIGHT    1
-#define LDLM_MODE_JOIN_LEFT     (1 << 1)
-#define LDLM_POLICY_JOIN_RIGHT  (1 << 2)
-#define LDLM_POLICY_JOIN_LEFT   (1 << 3)
-
 /* lock types */
 char *ldlm_lockname[] = {
         [0] "--",
@@ -341,10 +334,8 @@ static struct ldlm_lock *ldlm_lock_new(struct ldlm_resource *resource)
         CFS_INIT_LIST_HEAD(&lock->l_cp_ast);
         cfs_waitq_init(&lock->l_waitq);
         lock->l_blocking_lock = NULL;
-        lock->l_sl_mode.prev = NULL;
-        lock->l_sl_mode.next = NULL;
-        lock->l_sl_policy.prev = NULL;
-        lock->l_sl_policy.next = NULL;
+        CFS_INIT_LIST_HEAD(&lock->l_sl_mode);
+        CFS_INIT_LIST_HEAD(&lock->l_sl_policy);
 
         atomic_inc(&resource->lr_namespace->ns_locks);
         CFS_INIT_LIST_HEAD(&lock->l_handle.h_link);
@@ -670,6 +661,12 @@ void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode)
         LDLM_LOCK_PUT(lock);
 }
 
+struct sl_insert_point {
+        struct list_head *res_link;
+        struct list_head *mode_link;
+        struct list_head *policy_link;
+};
+
 /*
  * search_granted_lock
  *
@@ -678,109 +675,98 @@ void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode)
  * Parameters:
  *      queue [input]:  the granted list where search acts on;
  *      req [input]:    the lock whose position to be located;
- *      lockp [output]: the position where the lock should be inserted before, or
- *                      NULL indicating @req should be appended to @queue.
- * Return Values:
- *      Bit-masks combination of following values indicating in which way the 
- *      lock need to be inserted.
- *      - LDLM_JOIN_NONE:       noting about skip list needs to be fixed;
- *      - LDLM_MODE_JOIN_RIGHT: @req needs join right becoming the head of a 
- *                              mode group;
- *      - LDLM_POLICY_JOIN_RIGHT: @req needs join right becoming the head of
- *                                a policy group.
+ *      prev [output]:  positions within 3 lists to insert @req to
+ * Return Value:
+ *      filled @prev
  * NOTE: called by
  *  - ldlm_grant_lock_with_skiplist
  */
-static int search_granted_lock(struct list_head *queue, 
-                        struct ldlm_lock *req,
-                        struct ldlm_lock **lockp)
+static void search_granted_lock(struct list_head *queue,
+                                struct ldlm_lock *req,
+                                struct sl_insert_point *prev)
 {
-        struct list_head *tmp, *tmp_tail;
-        struct ldlm_lock *lock, *mode_head_lock;
-        int rc = LDLM_JOIN_NONE;
+        struct list_head *tmp;
+        struct ldlm_lock *lock, *mode_end, *policy_end;
         ENTRY;
 
         list_for_each(tmp, queue) {
                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
 
+                mode_end = list_entry(lock->l_sl_mode.prev, struct ldlm_lock,
+                                      l_sl_mode);
+
                 if (lock->l_req_mode != req->l_req_mode) {
-                        if (LDLM_SL_HEAD(&lock->l_sl_mode))
-                                tmp = &list_entry(lock->l_sl_mode.next,
-                                                  struct ldlm_lock,
-                                                  l_sl_mode)->l_res_link;
+                        /* jump to last lock of mode group */
+                        tmp = &mode_end->l_res_link;
                         continue;
                 }
-                
-                /* found the same mode group */
+
+                /* suitable mode group is found */
                 if (lock->l_resource->lr_type == LDLM_PLAIN) {
-                        *lockp = lock;
-                        rc = LDLM_MODE_JOIN_RIGHT;
-                        GOTO(out, rc);
+                        /* insert point is last lock of the mode group */
+                        prev->res_link = &mode_end->l_res_link;
+                        prev->mode_link = &mode_end->l_sl_mode;
+                        prev->policy_link = &req->l_sl_policy;
+                        EXIT;
+                        return;
                 } else if (lock->l_resource->lr_type == LDLM_IBITS) {
-                        tmp_tail = tmp;
-                        if (LDLM_SL_HEAD(&lock->l_sl_mode))
-                                tmp_tail = &list_entry(lock->l_sl_mode.next,
-                                                       struct ldlm_lock,
-                                                       l_sl_mode)->l_res_link;
-                        mode_head_lock = lock;
                         for (;;) {
+                                policy_end = list_entry(lock->l_sl_policy.prev,
+                                                        struct ldlm_lock,
+                                                        l_sl_policy);
+
                                 if (lock->l_policy_data.l_inodebits.bits ==
                                     req->l_policy_data.l_inodebits.bits) {
-                                        /* matched policy lock is found */
-                                        *lockp = lock;
-                                        rc |= LDLM_POLICY_JOIN_RIGHT;
-
-                                        /* if the policy group head is also a 
-                                         * mode group head or a single mode
-                                         * group lock */
-                                        if (LDLM_SL_HEAD(&lock->l_sl_mode) ||
-                                            (tmp == tmp_tail &&
-                                             LDLM_SL_EMPTY(&lock->l_sl_mode)))
-                                                rc |= LDLM_MODE_JOIN_RIGHT;
-                                        GOTO(out, rc);
+                                        /* insert point is last lock of
+                                         * the policy group */
+                                        prev->res_link =
+                                                &policy_end->l_res_link;
+                                        prev->mode_link =
+                                                &policy_end->l_sl_mode;
+                                        prev->policy_link =
+                                                &policy_end->l_sl_policy;
+                                        EXIT;
+                                        return;
                                 }
 
-                                if (LDLM_SL_HEAD(&lock->l_sl_policy))
-                                        tmp = &list_entry(lock->l_sl_policy.next,
-                                                          struct ldlm_lock,
-                                                          l_sl_policy)->l_res_link;
-
-                                if (tmp == tmp_tail)
+                                if (policy_end == mode_end)
+                                        /* done with mode group */
                                         break;
-                                else
-                                        tmp = tmp->next;
+
+                                /* jump to next policy group within the mode group */
+                                tmp = policy_end->l_res_link.next;
                                 lock = list_entry(tmp, struct ldlm_lock, 
                                                   l_res_link);
-                        }  /* for all locks in the matched mode group */
-
-                        /* no matched policy group is found, insert before
-                         * the mode group head lock */
-                        *lockp = mode_head_lock;
-                        rc = LDLM_MODE_JOIN_RIGHT;
-                        GOTO(out, rc);
+                        }  /* loop over policy groups within the mode group */
+
+                        /* insert point is last lock of the mode group,
+                         * new policy group is started */
+                        prev->res_link = &mode_end->l_res_link;
+                        prev->mode_link = &mode_end->l_sl_mode;
+                        prev->policy_link = &req->l_sl_policy;
+                        EXIT;
+                        return;
                 } else {
                         LDLM_ERROR(lock, "is not LDLM_PLAIN or LDLM_IBITS lock");
                         LBUG();
                 }
         }
 
-        /* no matched mode group is found, append to the end */
-        *lockp = NULL;
-        rc = LDLM_JOIN_NONE;
+        /* insert point is last lock on the queue,
+         * new mode group and new policy group are started */
+        prev->res_link = queue->prev;
+        prev->mode_link = &req->l_sl_mode;
+        prev->policy_link = &req->l_sl_policy;
         EXIT;
-out:
-        return rc;
+        return;
 }
 
 static void ldlm_granted_list_add_lock(struct ldlm_lock *lock, 
-                                       struct ldlm_lock *lockp,
-                                       int join)
+                                       struct sl_insert_point *prev)
 {
         struct ldlm_resource *res = lock->l_resource;
         ENTRY;
 
-        LASSERT(lockp || join == LDLM_JOIN_NONE);
-
         check_res_locked(res);
 
         ldlm_resource_dump(D_OTHER, res);
@@ -793,72 +779,25 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock,
         }
 
         LASSERT(list_empty(&lock->l_res_link));
+        LASSERT(list_empty(&lock->l_sl_mode));
+        LASSERT(list_empty(&lock->l_sl_policy));
 
-        if (!lockp)
-                list_add_tail(&lock->l_res_link, &lock->l_resource->lr_granted);
-        else if ((join & LDLM_MODE_JOIN_LEFT) || (join & LDLM_POLICY_JOIN_LEFT))
-                list_add(&lock->l_res_link, &lockp->l_res_link);
-        else
-                list_add_tail(&lock->l_res_link, &lockp->l_res_link);
-
-        /* fix skip lists */
-        if (join & LDLM_MODE_JOIN_RIGHT) {
-                LASSERT(! LDLM_SL_TAIL(&lockp->l_sl_mode));
-                if (LDLM_SL_EMPTY(&lockp->l_sl_mode)) {
-                        lock->l_sl_mode.next = &lockp->l_sl_mode;
-                        lockp->l_sl_mode.prev = &lock->l_sl_mode;
-                } else if (LDLM_SL_HEAD(&lockp->l_sl_mode)) {
-                        lock->l_sl_mode.next = lockp->l_sl_mode.next;
-                        lockp->l_sl_mode.next = NULL;
-                        lock->l_sl_mode.next->prev = &lock->l_sl_mode;
-                }
-        } else if (join & LDLM_MODE_JOIN_LEFT) {
-                LASSERT(! LDLM_SL_HEAD(&lockp->l_sl_mode));
-               if (LDLM_SL_EMPTY(&lockp->l_sl_mode)) {
-                        lock->l_sl_mode.prev = &lockp->l_sl_mode;
-                        lockp->l_sl_mode.next = &lock->l_sl_mode;
-                } else if (LDLM_SL_TAIL(&lockp->l_sl_mode)) {
-                        lock->l_sl_mode.prev = lockp->l_sl_mode.prev;
-                        lockp->l_sl_mode.prev = NULL;
-                        lock->l_sl_mode.prev->next = &lock->l_sl_mode;
-                }
-        }
-        
-        if (join & LDLM_POLICY_JOIN_RIGHT) {
-                LASSERT(! LDLM_SL_TAIL(&lockp->l_sl_policy));
-                if (LDLM_SL_EMPTY(&lockp->l_sl_policy)) {
-                        lock->l_sl_policy.next = &lockp->l_sl_policy;
-                        lockp->l_sl_policy.prev = &lock->l_sl_policy;
-                } else if (LDLM_SL_HEAD(&lockp->l_sl_policy)) {
-                        lock->l_sl_policy.next = lockp->l_sl_policy.next;
-                        lockp->l_sl_policy.next = NULL;
-                        lock->l_sl_policy.next->prev = &lock->l_sl_policy;
-                }
-        } else if (join & LDLM_POLICY_JOIN_LEFT) {
-                LASSERT(! LDLM_SL_HEAD(&lockp->l_sl_policy));
-                if (LDLM_SL_EMPTY(&lockp->l_sl_policy)) {
-                        lock->l_sl_policy.prev = &lockp->l_sl_policy;
-                        lockp->l_sl_policy.next = &lock->l_sl_policy;
-                } else if (LDLM_SL_TAIL(&lockp->l_sl_policy)) {
-                        lock->l_sl_policy.prev = lockp->l_sl_policy.prev;
-                        lockp->l_sl_policy.prev = NULL;
-                        lock->l_sl_policy.prev->next = &lock->l_sl_policy;
-                }
-        }
+        list_add(&lock->l_res_link, prev->res_link);
+        list_add(&lock->l_sl_mode, prev->mode_link);
+        list_add(&lock->l_sl_policy, prev->policy_link);
 
         EXIT;
 }
 
 static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock)
 {
-        int join = LDLM_JOIN_NONE;
-        struct ldlm_lock *lockp = NULL;
+        struct sl_insert_point prev;
         ENTRY;
 
         LASSERT(lock->l_req_mode == lock->l_granted_mode);
 
-        join = search_granted_lock(&lock->l_resource->lr_granted, lock, &lockp);
-        ldlm_granted_list_add_lock(lock, lockp, join);
+        search_granted_lock(&lock->l_resource->lr_granted, lock, &prev);
+        ldlm_granted_list_add_lock(lock, &prev);
         EXIT;
 }
 
@@ -910,7 +849,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue,
                 lock = list_entry(tmp, struct ldlm_lock, l_res_link);
 
                 if (lock == old_lock)
-                        continue;
+                        break;
 
                 /* llite sometimes wants to match locks that will be
                  * canceled when their users drop, but we allow it to match
@@ -1551,55 +1490,12 @@ void ldlm_cancel_callback(struct ldlm_lock *lock)
 
 void ldlm_unlink_lock_skiplist(struct ldlm_lock *req)
 {
-        struct ldlm_lock *lock;
-
         if (req->l_resource->lr_type != LDLM_PLAIN &&
             req->l_resource->lr_type != LDLM_IBITS)
                 return;
-        
-        if (LDLM_SL_HEAD(&req->l_sl_mode)) {
-                lock = list_entry(req->l_res_link.next, struct ldlm_lock,
-                                  l_res_link);
-                if (req->l_sl_mode.next == &lock->l_sl_mode) {
-                        lock->l_sl_mode.prev = NULL;
-                } else {
-                        lock->l_sl_mode.next = req->l_sl_mode.next;
-                        lock->l_sl_mode.next->prev = &lock->l_sl_mode;
-                }
-                req->l_sl_mode.next = NULL;
-        } else if (LDLM_SL_TAIL(&req->l_sl_mode)) {
-                lock = list_entry(req->l_res_link.prev, struct ldlm_lock,
-                                  l_res_link);
-                if (req->l_sl_mode.prev == &lock->l_sl_mode) {
-                        lock->l_sl_mode.next = NULL;
-                } else {
-                        lock->l_sl_mode.prev = req->l_sl_mode.prev;
-                        lock->l_sl_mode.prev->next = &lock->l_sl_mode;
-                }
-                req->l_sl_mode.prev = NULL;
-        }
 
-        if (LDLM_SL_HEAD(&req->l_sl_policy)) {
-                lock = list_entry(req->l_res_link.next, struct ldlm_lock,
-                                  l_res_link);
-                if (req->l_sl_policy.next == &lock->l_sl_policy) {
-                        lock->l_sl_policy.prev = NULL;
-                } else {
-                        lock->l_sl_policy.next = req->l_sl_policy.next;
-                        lock->l_sl_policy.next->prev = &lock->l_sl_policy;
-                }
-                req->l_sl_policy.next = NULL;
-        } else if (LDLM_SL_TAIL(&req->l_sl_policy)) {
-                lock = list_entry(req->l_res_link.prev, struct ldlm_lock,
-                                  l_res_link);
-                if (req->l_sl_policy.prev == &lock->l_sl_policy) {
-                        lock->l_sl_policy.next = NULL;
-                } else {
-                        lock->l_sl_policy.prev = req->l_sl_policy.prev;
-                        lock->l_sl_policy.prev->next = &lock->l_sl_policy;
-                }
-                req->l_sl_policy.prev = NULL;
-        }
+        list_del_init(&req->l_sl_policy);
+        list_del_init(&req->l_sl_mode);
 }
 
 void ldlm_lock_cancel(struct ldlm_lock *lock)
@@ -1689,8 +1585,7 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
         struct ldlm_namespace *ns;
         int granted = 0;
         int old_mode, rc;
-        struct ldlm_lock *mark_lock = NULL;
-        int join = LDLM_JOIN_NONE;
+        struct sl_insert_point prev;
         ldlm_error_t err;
         struct ldlm_interval *node;
         ENTRY;
@@ -1720,27 +1615,10 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
                 /* remember the lock position where the lock might be 
                  * added back to the granted list later and also 
                  * remember the join mode for skiplist fixing. */
-                if (LDLM_SL_HEAD(&lock->l_sl_mode))
-                        join = LDLM_MODE_JOIN_RIGHT;
-                else if (LDLM_SL_TAIL(&lock->l_sl_mode))
-                        join = LDLM_MODE_JOIN_LEFT;
-                if (LDLM_SL_HEAD(&lock->l_sl_policy))
-                        join |= LDLM_POLICY_JOIN_RIGHT;
-                else if (LDLM_SL_TAIL(&lock->l_sl_policy))
-                        join |= LDLM_POLICY_JOIN_LEFT;
-
-                LASSERT(!((join & LDLM_MODE_JOIN_RIGHT) &&
-                          (join & LDLM_POLICY_JOIN_LEFT)));
-                LASSERT(!((join & LDLM_MODE_JOIN_LEFT) &&
-                          (join & LDLM_POLICY_JOIN_RIGHT)));
-
-                if ((join & LDLM_MODE_JOIN_LEFT) ||
-                    (join & LDLM_POLICY_JOIN_LEFT))
-                        mark_lock = list_entry(lock->l_res_link.prev,
-                                               struct ldlm_lock, l_res_link);
-                else if (lock->l_res_link.next != &res->lr_granted)
-                        mark_lock = list_entry(lock->l_res_link.next,
-                                               struct ldlm_lock, l_res_link);
+                prev.res_link = lock->l_res_link.prev;
+                prev.mode_link = lock->l_sl_mode.prev;
+                prev.policy_link = lock->l_sl_policy.prev;
+                ldlm_resource_unlink_lock(lock);
         } else {
                 ldlm_resource_unlink_lock(lock);
                 if (res->lr_type == LDLM_EXTENT) {
@@ -1780,8 +1658,8 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
                         if (res->lr_type == LDLM_EXTENT)
                                 ldlm_extent_add_lock(res, lock);
                         else
-                                ldlm_granted_list_add_lock(lock, mark_lock,
-                                                           join);
+                                ldlm_granted_list_add_lock(lock, &prev);
+
                         res = NULL;
                 } else {
                         *flags |= LDLM_FL_BLOCK_GRANTED;
index bfa086b..4e985e1 100644 (file)
@@ -54,32 +54,32 @@ ldlm_plain_compat_queue(struct list_head *queue, struct ldlm_lock *req,
                 if (req == lock)
                         RETURN(compat);
 
-                if (lockmode_compat(lock->l_req_mode, req_mode)) {
-                        /* jump to next mode group */
-                        if (LDLM_SL_HEAD(&lock->l_sl_mode))
-                                tmp = &list_entry(lock->l_sl_mode.next, 
-                                                  struct ldlm_lock,
-                                                  l_sl_mode)->l_res_link;
+                 /* last lock in mode group */
+                 tmp = &list_entry(lock->l_sl_mode.prev,
+                                   struct ldlm_lock,
+                                   l_sl_mode)->l_res_link;
+
+                 if (lockmode_compat(lock->l_req_mode, req_mode))
                         continue;
-                }
 
                 if (!work_list)
                         RETURN(0);
 
                 compat = 0;
+
+                /* add locks of the mode group to @work_list as
+                 * blocking locks for @req */
                 if (lock->l_blocking_ast)
                         ldlm_add_ast_work_item(lock, req, work_list);
 
-                if (LDLM_SL_HEAD(&lock->l_sl_mode)) {
-                        /* add all members of the mode group */
-                        do {
-                                tmp = lock->l_res_link.next;
-                                lock = list_entry(tmp, struct ldlm_lock, 
-                                                  l_res_link);
+                {
+                        struct list_head *head;
+
+                        head = &lock->l_sl_mode;
+                        list_for_each_entry(lock, head, l_sl_mode)
                                 if (lock->l_blocking_ast)
-                                        ldlm_add_ast_work_item(
-                                                        lock, req, work_list);
-                        } while (!LDLM_SL_TAIL(&lock->l_sl_mode));
+                                        ldlm_add_ast_work_item(lock, req,
+                                                               work_list);
                 }
         }
 
index fdf6fe9..de5f409 100644 (file)
@@ -828,6 +828,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
                PFID(&op_data->op_fid1), ldlm_it2str(it->it_op),
                it->it_flags);
 
+        lockh.cookie = 0;
         if (fid_is_sane(&op_data->op_fid2) &&
             (it->it_op & (IT_LOOKUP | IT_GETATTR))) {
                 /* We could just return 1 immediately, but since we should only