dlm: fix slow rsb search in dir recovery
David Teigland [Thu, 8 Mar 2012 18:37:12 +0000 (12:37 -0600)]
The function used to find an rsb during directory
recovery was searching the single linear list of
rsb's.  This wasted a lot of time compared to
using the standard hash table to find the rsb.

Signed-off-by: David Teigland <teigland@redhat.com>

fs/dlm/dir.c
fs/dlm/lock.c
fs/dlm/lock.h

index 8364157..dc5eb59 100644 (file)
@@ -351,11 +351,28 @@ int dlm_dir_lookup(struct dlm_ls *ls, int nodeid, char *name, int namelen,
 static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len)
 {
        struct dlm_rsb *r;
+       uint32_t hash, bucket;
+       int rv;
+
+       hash = jhash(name, len, 0);
+       bucket = hash & (ls->ls_rsbtbl_size - 1);
+
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
+       rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[bucket].keep, name, len, 0, &r);
+       if (rv)
+               rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[bucket].toss,
+                                        name, len, 0, &r);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+
+       if (!rv)
+               return r;
 
        down_read(&ls->ls_root_sem);
        list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
                if (len == r->res_length && !memcmp(name, r->res_name, len)) {
                        up_read(&ls->ls_root_sem);
+                       log_error(ls, "find_rsb_root revert to root_list %s",
+                                 r->res_name);
                        return r;
                }
        }
index d471830..fa5c07d 100644 (file)
@@ -411,8 +411,8 @@ static int rsb_cmp(struct dlm_rsb *r, const char *name, int nlen)
        return memcmp(r->res_name, maxname, DLM_RESNAME_MAXLEN);
 }
 
-static int search_rsb_tree(struct rb_root *tree, char *name, int len,
-                          unsigned int flags, struct dlm_rsb **r_ret)
+int dlm_search_rsb_tree(struct rb_root *tree, char *name, int len,
+                       unsigned int flags, struct dlm_rsb **r_ret)
 {
        struct rb_node *node = tree->rb_node;
        struct dlm_rsb *r;
@@ -474,12 +474,12 @@ static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b,
        struct dlm_rsb *r;
        int error;
 
-       error = search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, flags, &r);
+       error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, flags, &r);
        if (!error) {
                kref_get(&r->res_ref);
                goto out;
        }
-       error = search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, flags, &r);
+       error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, flags, &r);
        if (error)
                goto out;
 
index 265017a..1a25530 100644 (file)
@@ -28,6 +28,9 @@ void dlm_scan_waiters(struct dlm_ls *ls);
 void dlm_scan_timeout(struct dlm_ls *ls);
 void dlm_adjust_timeouts(struct dlm_ls *ls);
 
+int dlm_search_rsb_tree(struct rb_root *tree, char *name, int len,
+                       unsigned int flags, struct dlm_rsb **r_ret);
+
 int dlm_purge_locks(struct dlm_ls *ls);
 void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
 void dlm_grant_after_purge(struct dlm_ls *ls);