Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 12 Jan 2009 23:54:27 +0000 (15:54 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 12 Jan 2009 23:54:27 +0000 (15:54 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm:
  dlm: change rsbtbl rwlock to spinlock
  dlm: fix seq_file usage in debugfs lock dump

fs/dlm/debug_fs.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lockspace.c
fs/dlm/recover.c

index 2f107d1a6a45937efe327eebf31b8cf0bc1c5aa5..1d1d27442235b9487c3db8a8490a6a0da7c6122c 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -25,19 +25,6 @@ static struct mutex debug_buf_lock;
 
 static struct dentry *dlm_root;
 
-struct rsb_iter {
-       int entry;
-       int format;
-       int header;
-       struct dlm_ls *ls;
-       struct list_head *next;
-       struct dlm_rsb *rsb;
-};
-
-/*
- * dump all rsb's in the lockspace hash table
- */
-
 static char *print_lockmode(int mode)
 {
        switch (mode) {
@@ -60,13 +47,13 @@ static char *print_lockmode(int mode)
        }
 }
 
-static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
-                              struct dlm_rsb *res)
+static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
+                             struct dlm_rsb *res)
 {
        seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
 
-       if (lkb->lkb_status == DLM_LKSTS_CONVERT
-           || lkb->lkb_status == DLM_LKSTS_WAITING)
+       if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
+           lkb->lkb_status == DLM_LKSTS_WAITING)
                seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
 
        if (lkb->lkb_nodeid) {
@@ -80,33 +67,42 @@ static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
        if (lkb->lkb_wait_type)
                seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
 
-       seq_printf(s, "\n");
+       return seq_printf(s, "\n");
 }
 
 static int print_format1(struct dlm_rsb *res, struct seq_file *s)
 {
        struct dlm_lkb *lkb;
        int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
+       int rv;
 
        lock_rsb(res);
 
-       seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
+       rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
+                       res, res->res_length);
+       if (rv)
+               goto out;
+
        for (i = 0; i < res->res_length; i++) {
                if (isprint(res->res_name[i]))
                        seq_printf(s, "%c", res->res_name[i]);
                else
                        seq_printf(s, "%c", '.');
        }
+
        if (res->res_nodeid > 0)
-               seq_printf(s, "\"  \nLocal Copy, Master is node %d\n",
-                          res->res_nodeid);
+               rv = seq_printf(s, "\"  \nLocal Copy, Master is node %d\n",
+                               res->res_nodeid);
        else if (res->res_nodeid == 0)
-               seq_printf(s, "\"  \nMaster Copy\n");
+               rv = seq_printf(s, "\"  \nMaster Copy\n");
        else if (res->res_nodeid == -1)
-               seq_printf(s, "\"  \nLooking up master (lkid %x)\n",
-                          res->res_first_lkid);
+               rv = seq_printf(s, "\"  \nLooking up master (lkid %x)\n",
+                               res->res_first_lkid);
        else
-               seq_printf(s, "\"  \nInvalid master %d\n", res->res_nodeid);
+               rv = seq_printf(s, "\"  \nInvalid master %d\n",
+                               res->res_nodeid);
+       if (rv)
+               goto out;
 
        /* Print the LVB: */
        if (res->res_lvbptr) {
@@ -119,52 +115,66 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
                }
                if (rsb_flag(res, RSB_VALNOTVALID))
                        seq_printf(s, " (INVALID)");
-               seq_printf(s, "\n");
+               rv = seq_printf(s, "\n");
+               if (rv)
+                       goto out;
        }
 
        root_list = !list_empty(&res->res_root_list);
        recover_list = !list_empty(&res->res_recover_list);
 
        if (root_list || recover_list) {
-               seq_printf(s, "Recovery: root %d recover %d flags %lx "
-                          "count %d\n", root_list, recover_list,
-                          res->res_flags, res->res_recover_locks_count);
+               rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
+                               "count %d\n", root_list, recover_list,
+                               res->res_flags, res->res_recover_locks_count);
+               if (rv)
+                       goto out;
        }
 
        /* Print the locks attached to this resource */
        seq_printf(s, "Granted Queue\n");
-       list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
-               print_format1_lock(s, lkb, res);
+       list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
+               rv = print_format1_lock(s, lkb, res);
+               if (rv)
+                       goto out;
+       }
 
        seq_printf(s, "Conversion Queue\n");
-       list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
-               print_format1_lock(s, lkb, res);
+       list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
+               rv = print_format1_lock(s, lkb, res);
+               if (rv)
+                       goto out;
+       }
 
        seq_printf(s, "Waiting Queue\n");
-       list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
-               print_format1_lock(s, lkb, res);
+       list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
+               rv = print_format1_lock(s, lkb, res);
+               if (rv)
+                       goto out;
+       }
 
        if (list_empty(&res->res_lookup))
                goto out;
 
        seq_printf(s, "Lookup Queue\n");
        list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
-               seq_printf(s, "%08x %s", lkb->lkb_id,
-                          print_lockmode(lkb->lkb_rqmode));
+               rv = seq_printf(s, "%08x %s", lkb->lkb_id,
+                               print_lockmode(lkb->lkb_rqmode));
                if (lkb->lkb_wait_type)
                        seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
-               seq_printf(s, "\n");
+               rv = seq_printf(s, "\n");
        }
  out:
        unlock_rsb(res);
-       return 0;
+       return rv;
 }
 
-static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
-                              struct dlm_rsb *r)
+static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
+                             struct dlm_rsb *r)
 {
        u64 xid = 0;
        u64 us;
+       int rv;
 
        if (lkb->lkb_flags & DLM_IFL_USER) {
                if (lkb->lkb_ua)
@@ -177,69 +187,82 @@ static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
        /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
           r_nodeid r_len r_name */
 
-       seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
-                  lkb->lkb_id,
-                  lkb->lkb_nodeid,
-                  lkb->lkb_remid,
-                  lkb->lkb_ownpid,
-                  (unsigned long long)xid,
-                  lkb->lkb_exflags,
-                  lkb->lkb_flags,
-                  lkb->lkb_status,
-                  lkb->lkb_grmode,
-                  lkb->lkb_rqmode,
-                  (unsigned long long)us,
-                  r->res_nodeid,
-                  r->res_length,
-                  r->res_name);
+       rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
+                       lkb->lkb_id,
+                       lkb->lkb_nodeid,
+                       lkb->lkb_remid,
+                       lkb->lkb_ownpid,
+                       (unsigned long long)xid,
+                       lkb->lkb_exflags,
+                       lkb->lkb_flags,
+                       lkb->lkb_status,
+                       lkb->lkb_grmode,
+                       lkb->lkb_rqmode,
+                       (unsigned long long)us,
+                       r->res_nodeid,
+                       r->res_length,
+                       r->res_name);
+       return rv;
 }
 
 static int print_format2(struct dlm_rsb *r, struct seq_file *s)
 {
        struct dlm_lkb *lkb;
+       int rv = 0;
 
        lock_rsb(r);
 
-       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
-               print_format2_lock(s, lkb, r);
-
-       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
-               print_format2_lock(s, lkb, r);
+       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
+               rv = print_format2_lock(s, lkb, r);
+               if (rv)
+                       goto out;
+       }
 
-       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
-               print_format2_lock(s, lkb, r);
+       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
+               rv = print_format2_lock(s, lkb, r);
+               if (rv)
+                       goto out;
+       }
 
+       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
+               rv = print_format2_lock(s, lkb, r);
+               if (rv)
+                       goto out;
+       }
+ out:
        unlock_rsb(r);
-       return 0;
+       return rv;
 }
 
-static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
-                              int rsb_lookup)
+static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
+                             int rsb_lookup)
 {
        u64 xid = 0;
+       int rv;
 
        if (lkb->lkb_flags & DLM_IFL_USER) {
                if (lkb->lkb_ua)
                        xid = lkb->lkb_ua->xid;
        }
 
-       seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
-                  lkb->lkb_id,
-                  lkb->lkb_nodeid,
-                  lkb->lkb_remid,
-                  lkb->lkb_ownpid,
-                  (unsigned long long)xid,
-                  lkb->lkb_exflags,
-                  lkb->lkb_flags,
-                  lkb->lkb_status,
-                  lkb->lkb_grmode,
-                  lkb->lkb_rqmode,
-                  lkb->lkb_highbast,
-                  rsb_lookup,
-                  lkb->lkb_wait_type,
-                  lkb->lkb_lvbseq,
-                  (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
-                  (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
+       rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
+                       lkb->lkb_id,
+                       lkb->lkb_nodeid,
+                       lkb->lkb_remid,
+                       lkb->lkb_ownpid,
+                       (unsigned long long)xid,
+                       lkb->lkb_exflags,
+                       lkb->lkb_flags,
+                       lkb->lkb_status,
+                       lkb->lkb_grmode,
+                       lkb->lkb_rqmode,
+                       lkb->lkb_highbast,
+                       rsb_lookup,
+                       lkb->lkb_wait_type,
+                       lkb->lkb_lvbseq,
+                       (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
+                       (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
+       return rv;
 }
 
 static int print_format3(struct dlm_rsb *r, struct seq_file *s)
@@ -247,18 +270,21 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
        struct dlm_lkb *lkb;
        int i, lvblen = r->res_ls->ls_lvblen;
        int print_name = 1;
+       int rv;
 
        lock_rsb(r);
 
-       seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
-                  r,
-                  r->res_nodeid,
-                  r->res_first_lkid,
-                  r->res_flags,
-                  !list_empty(&r->res_root_list),
-                  !list_empty(&r->res_recover_list),
-                  r->res_recover_locks_count,
-                  r->res_length);
+       rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
+                       r,
+                       r->res_nodeid,
+                       r->res_first_lkid,
+                       r->res_flags,
+                       !list_empty(&r->res_root_list),
+                       !list_empty(&r->res_recover_list),
+                       r->res_recover_locks_count,
+                       r->res_length);
+       if (rv)
+               goto out;
 
        for (i = 0; i < r->res_length; i++) {
                if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
@@ -273,7 +299,9 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
                else
                        seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
        }
-       seq_printf(s, "\n");
+       rv = seq_printf(s, "\n");
+       if (rv)
+               goto out;
 
        if (!r->res_lvbptr)
                goto do_locks;
@@ -282,344 +310,294 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
 
        for (i = 0; i < lvblen; i++)
                seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
-       seq_printf(s, "\n");
+       rv = seq_printf(s, "\n");
+       if (rv)
+               goto out;
 
  do_locks:
-       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
-               print_format3_lock(s, lkb, 0);
-
-       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
-               print_format3_lock(s, lkb, 0);
-
-       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
-               print_format3_lock(s, lkb, 0);
-
-       list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
-               print_format3_lock(s, lkb, 1);
-
-       unlock_rsb(r);
-       return 0;
-}
-
-static int rsb_iter_next(struct rsb_iter *ri)
-{
-       struct dlm_ls *ls = ri->ls;
-       int i;
-
-       if (!ri->next) {
- top:
-               /* Find the next non-empty hash bucket */
-               for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
-                       read_lock(&ls->ls_rsbtbl[i].lock);
-                       if (!list_empty(&ls->ls_rsbtbl[i].list)) {
-                               ri->next = ls->ls_rsbtbl[i].list.next;
-                               ri->rsb = list_entry(ri->next, struct dlm_rsb,
-                                                       res_hashchain);
-                               dlm_hold_rsb(ri->rsb);
-                               read_unlock(&ls->ls_rsbtbl[i].lock);
-                               break;
-                       }
-                       read_unlock(&ls->ls_rsbtbl[i].lock);
-               }
-               ri->entry = i;
-
-               if (ri->entry >= ls->ls_rsbtbl_size)
-                       return 1;
-       } else {
-               struct dlm_rsb *old = ri->rsb;
-               i = ri->entry;
-               read_lock(&ls->ls_rsbtbl[i].lock);
-               ri->next = ri->next->next;
-               if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
-                       /* End of list - move to next bucket */
-                       ri->next = NULL;
-                       ri->entry++;
-                       read_unlock(&ls->ls_rsbtbl[i].lock);
-                       dlm_put_rsb(old);
-                       goto top;
-               }
-               ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
-               dlm_hold_rsb(ri->rsb);
-               read_unlock(&ls->ls_rsbtbl[i].lock);
-               dlm_put_rsb(old);
+       list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
+               rv = print_format3_lock(s, lkb, 0);
+               if (rv)
+                       goto out;
        }
 
-       return 0;
-}
-
-static void rsb_iter_free(struct rsb_iter *ri)
-{
-       kfree(ri);
-}
-
-static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
-{
-       struct rsb_iter *ri;
-
-       ri = kzalloc(sizeof *ri, GFP_KERNEL);
-       if (!ri)
-               return NULL;
-
-       ri->ls = ls;
-       ri->entry = 0;
-       ri->next = NULL;
-       ri->format = 1;
-
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+       list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
+               rv = print_format3_lock(s, lkb, 0);
+               if (rv)
+                       goto out;
        }
 
-       return ri;
-}
-
-static void *rsb_seq_start(struct seq_file *file, loff_t *pos)
-{
-       struct rsb_iter *ri;
-       loff_t n = *pos;
-
-       ri = rsb_iter_init(file->private);
-       if (!ri)
-               return NULL;
-
-       while (n--) {
-               if (rsb_iter_next(ri)) {
-                       rsb_iter_free(ri);
-                       return NULL;
-               }
+       list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
+               rv = print_format3_lock(s, lkb, 0);
+               if (rv)
+                       goto out;
        }
 
-       return ri;
-}
-
-static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos)
-{
-       struct rsb_iter *ri = iter_ptr;
-
-       (*pos)++;
-
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+       list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
+               rv = print_format3_lock(s, lkb, 1);
+               if (rv)
+                       goto out;
        }
-
-       return ri;
+ out:
+       unlock_rsb(r);
+       return rv;
 }
 
-static void rsb_seq_stop(struct seq_file *file, void *iter_ptr)
-{
-       /* nothing for now */
-}
+struct rsbtbl_iter {
+       struct dlm_rsb *rsb;
+       unsigned bucket;
+       int format;
+       int header;
+};
 
-static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
+/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
+   If the buffer is full, seq_printf can be called again, but it
+   does nothing and just returns -1.  So, the these printing routines
+   periodically check the return value to avoid wasting too much time
+   trying to print to a full buffer. */
+
+static int table_seq_show(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsb_iter *ri = iter_ptr;
+       struct rsbtbl_iter *ri = iter_ptr;
+       int rv = 0;
 
        switch (ri->format) {
        case 1:
-               print_format1(ri->rsb, file);
+               rv = print_format1(ri->rsb, seq);
                break;
        case 2:
                if (ri->header) {
-                       seq_printf(file, "id nodeid remid pid xid exflags "
-                                        "flags sts grmode rqmode time_ms "
-                                        "r_nodeid r_len r_name\n");
+                       seq_printf(seq, "id nodeid remid pid xid exflags "
+                                       "flags sts grmode rqmode time_ms "
+                                       "r_nodeid r_len r_name\n");
                        ri->header = 0;
                }
-               print_format2(ri->rsb, file);
+               rv = print_format2(ri->rsb, seq);
                break;
        case 3:
                if (ri->header) {
-                       seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
+                       seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
                        ri->header = 0;
                }
-               print_format3(ri->rsb, file);
+               rv = print_format3(ri->rsb, seq);
                break;
        }
 
-       return 0;
+       return rv;
 }
 
-static struct seq_operations rsb_seq_ops = {
-       .start = rsb_seq_start,
-       .next  = rsb_seq_next,
-       .stop  = rsb_seq_stop,
-       .show  = rsb_seq_show,
-};
+static struct seq_operations format1_seq_ops;
+static struct seq_operations format2_seq_ops;
+static struct seq_operations format3_seq_ops;
 
-static int rsb_open(struct inode *inode, struct file *file)
+static void *table_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct seq_file *seq;
-       int ret;
-
-       ret = seq_open(file, &rsb_seq_ops);
-       if (ret)
-               return ret;
-
-       seq = file->private_data;
-       seq->private = inode->i_private;
-
-       return 0;
-}
-
-static const struct file_operations rsb_fops = {
-       .owner   = THIS_MODULE,
-       .open    = rsb_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release
-};
+       struct dlm_ls *ls = seq->private;
+       struct rsbtbl_iter *ri;
+       struct dlm_rsb *r;
+       loff_t n = *pos;
+       unsigned bucket, entry;
 
-/*
- * Dump state in compact per-lock listing
- */
+       bucket = n >> 32;
+       entry = n & ((1LL << 32) - 1);
 
-static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
-{
-       struct rsb_iter *ri;
+       if (bucket >= ls->ls_rsbtbl_size)
+               return NULL;
 
-       ri = kzalloc(sizeof *ri, GFP_KERNEL);
+       ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
        if (!ri)
                return NULL;
-
-       ri->ls = ls;
-       ri->entry = 0;
-       ri->next = NULL;
-       ri->format = 2;
-
-       if (*pos == 0)
+       if (n == 0)
                ri->header = 1;
-
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+       if (seq->op == &format1_seq_ops)
+               ri->format = 1;
+       if (seq->op == &format2_seq_ops)
+               ri->format = 2;
+       if (seq->op == &format3_seq_ops)
+               ri->format = 3;
+
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
+       if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
+               list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list,
+                                   res_hashchain) {
+                       if (!entry--) {
+                               dlm_hold_rsb(r);
+                               ri->rsb = r;
+                               ri->bucket = bucket;
+                               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+                               return ri;
+                       }
+               }
        }
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 
-       return ri;
-}
+       /*
+        * move to the first rsb in the next non-empty bucket
+        */
 
-static void *locks_seq_start(struct seq_file *file, loff_t *pos)
-{
-       struct rsb_iter *ri;
-       loff_t n = *pos;
+       /* zero the entry */
+       n &= ~((1LL << 32) - 1);
 
-       ri = locks_iter_init(file->private, pos);
-       if (!ri)
-               return NULL;
+       while (1) {
+               bucket++;
+               n += 1LL << 32;
 
-       while (n--) {
-               if (rsb_iter_next(ri)) {
-                       rsb_iter_free(ri);
+               if (bucket >= ls->ls_rsbtbl_size) {
+                       kfree(ri);
                        return NULL;
                }
-       }
 
-       return ri;
+               spin_lock(&ls->ls_rsbtbl[bucket].lock);
+               if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
+                       r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
+                                            struct dlm_rsb, res_hashchain);
+                       dlm_hold_rsb(r);
+                       ri->rsb = r;
+                       ri->bucket = bucket;
+                       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+                       *pos = n;
+                       return ri;
+               }
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+       }
 }
 
-static struct seq_operations locks_seq_ops = {
-       .start = locks_seq_start,
-       .next  = rsb_seq_next,
-       .stop  = rsb_seq_stop,
-       .show  = rsb_seq_show,
-};
-
-static int locks_open(struct inode *inode, struct file *file)
+static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
 {
-       struct seq_file *seq;
-       int ret;
-
-       ret = seq_open(file, &locks_seq_ops);
-       if (ret)
-               return ret;
-
-       seq = file->private_data;
-       seq->private = inode->i_private;
-
-       return 0;
-}
-
-static const struct file_operations locks_fops = {
-       .owner   = THIS_MODULE,
-       .open    = locks_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release
-};
-
-/*
- * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks
- * This can replace both formats 1 and 2 eventually.
- */
+       struct dlm_ls *ls = seq->private;
+       struct rsbtbl_iter *ri = iter_ptr;
+       struct list_head *next;
+       struct dlm_rsb *r, *rp;
+       loff_t n = *pos;
+       unsigned bucket;
+
+       bucket = n >> 32;
+
+       /*
+        * move to the next rsb in the same bucket
+        */
+
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
+       rp = ri->rsb;
+       next = rp->res_hashchain.next;
+
+       if (next != &ls->ls_rsbtbl[bucket].list) {
+               r = list_entry(next, struct dlm_rsb, res_hashchain);
+               dlm_hold_rsb(r);
+               ri->rsb = r;
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+               dlm_put_rsb(rp);
+               ++*pos;
+               return ri;
+       }
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+       dlm_put_rsb(rp);
 
-static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos)
-{
-       struct rsb_iter *ri;
+       /*
+        * move to the first rsb in the next non-empty bucket
+        */
 
-       ri = kzalloc(sizeof *ri, GFP_KERNEL);
-       if (!ri)
-               return NULL;
+       /* zero the entry */
+       n &= ~((1LL << 32) - 1);
 
-       ri->ls = ls;
-       ri->entry = 0;
-       ri->next = NULL;
-       ri->format = 3;
+       while (1) {
+               bucket++;
+               n += 1LL << 32;
 
-       if (*pos == 0)
-               ri->header = 1;
+               if (bucket >= ls->ls_rsbtbl_size) {
+                       kfree(ri);
+                       return NULL;
+               }
 
-       if (rsb_iter_next(ri)) {
-               rsb_iter_free(ri);
-               return NULL;
+               spin_lock(&ls->ls_rsbtbl[bucket].lock);
+               if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
+                       r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
+                                            struct dlm_rsb, res_hashchain);
+                       dlm_hold_rsb(r);
+                       ri->rsb = r;
+                       ri->bucket = bucket;
+                       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
+                       *pos = n;
+                       return ri;
+               }
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
        }
-
-       return ri;
 }
 
-static void *all_seq_start(struct seq_file *file, loff_t *pos)
+static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
 {
-       struct rsb_iter *ri;
-       loff_t n = *pos;
-
-       ri = all_iter_init(file->private, pos);
-       if (!ri)
-               return NULL;
+       struct rsbtbl_iter *ri = iter_ptr;
 
-       while (n--) {
-               if (rsb_iter_next(ri)) {
-                       rsb_iter_free(ri);
-                       return NULL;
-               }
+       if (ri) {
+               dlm_put_rsb(ri->rsb);
+               kfree(ri);
        }
-
-       return ri;
 }
 
-static struct seq_operations all_seq_ops = {
-       .start = all_seq_start,
-       .next  = rsb_seq_next,
-       .stop  = rsb_seq_stop,
-       .show  = rsb_seq_show,
+static struct seq_operations format1_seq_ops = {
+       .start = table_seq_start,
+       .next  = table_seq_next,
+       .stop  = table_seq_stop,
+       .show  = table_seq_show,
 };
 
-static int all_open(struct inode *inode, struct file *file)
+static struct seq_operations format2_seq_ops = {
+       .start = table_seq_start,
+       .next  = table_seq_next,
+       .stop  = table_seq_stop,
+       .show  = table_seq_show,
+};
+
+static struct seq_operations format3_seq_ops = {
+       .start = table_seq_start,
+       .next  = table_seq_next,
+       .stop  = table_seq_stop,
+       .show  = table_seq_show,
+};
+
+static const struct file_operations format1_fops;
+static const struct file_operations format2_fops;
+static const struct file_operations format3_fops;
+
+static int table_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
-       int ret;
+       int ret = -1;
+
+       if (file->f_op == &format1_fops)
+               ret = seq_open(file, &format1_seq_ops);
+       else if (file->f_op == &format2_fops)
+               ret = seq_open(file, &format2_seq_ops);
+       else if (file->f_op == &format3_fops)
+               ret = seq_open(file, &format3_seq_ops);
 
-       ret = seq_open(file, &all_seq_ops);
        if (ret)
                return ret;
 
        seq = file->private_data;
-       seq->private = inode->i_private;
-
+       seq->private = inode->i_private; /* the dlm_ls */
        return 0;
 }
 
-static const struct file_operations all_fops = {
+static const struct file_operations format1_fops = {
+       .owner   = THIS_MODULE,
+       .open    = table_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+static const struct file_operations format2_fops = {
+       .owner   = THIS_MODULE,
+       .open    = table_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release
+};
+
+static const struct file_operations format3_fops = {
        .owner   = THIS_MODULE,
-       .open    = all_open,
+       .open    = table_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
        .release = seq_release
@@ -689,7 +667,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
                                                      S_IFREG | S_IRUGO,
                                                      dlm_root,
                                                      ls,
-                                                     &rsb_fops);
+                                                     &format1_fops);
        if (!ls->ls_debug_rsb_dentry)
                goto fail;
 
@@ -702,7 +680,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
                                                        S_IFREG | S_IRUGO,
                                                        dlm_root,
                                                        ls,
-                                                       &locks_fops);
+                                                       &format2_fops);
        if (!ls->ls_debug_locks_dentry)
                goto fail;
 
@@ -715,7 +693,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
                                                      S_IFREG | S_IRUGO,
                                                      dlm_root,
                                                      ls,
-                                                     &all_fops);
+                                                     &format3_fops);
        if (!ls->ls_debug_all_dentry)
                goto fail;
 
index ef2f1e353966d85ef15d9a9dd0cf8b273df51f4b..076e86f38bc84a4a6e247b7fb184658592e7f732 100644 (file)
@@ -105,7 +105,7 @@ struct dlm_dirtable {
 struct dlm_rsbtable {
        struct list_head        list;
        struct list_head        toss;
-       rwlock_t                lock;
+       spinlock_t              lock;
 };
 
 struct dlm_lkbtable {
index 6cfe65bbf4a2e16daaf1aec41638430174b407db..01e7d39c5fba8d55a4fa1a4bd8f64e13d4c32a95 100644 (file)
@@ -412,9 +412,9 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
                      unsigned int flags, struct dlm_rsb **r_ret)
 {
        int error;
-       write_lock(&ls->ls_rsbtbl[b].lock);
+       spin_lock(&ls->ls_rsbtbl[b].lock);
        error = _search_rsb(ls, name, len, b, flags, r_ret);
-       write_unlock(&ls->ls_rsbtbl[b].lock);
+       spin_unlock(&ls->ls_rsbtbl[b].lock);
        return error;
 }
 
@@ -478,16 +478,16 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
                r->res_nodeid = nodeid;
        }
 
-       write_lock(&ls->ls_rsbtbl[bucket].lock);
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
        error = _search_rsb(ls, name, namelen, bucket, 0, &tmp);
        if (!error) {
-               write_unlock(&ls->ls_rsbtbl[bucket].lock);
+               spin_unlock(&ls->ls_rsbtbl[bucket].lock);
                dlm_free_rsb(r);
                r = tmp;
                goto out;
        }
        list_add(&r->res_hashchain, &ls->ls_rsbtbl[bucket].list);
-       write_unlock(&ls->ls_rsbtbl[bucket].lock);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
        error = 0;
  out:
        *r_ret = r;
@@ -530,9 +530,9 @@ static void put_rsb(struct dlm_rsb *r)
        struct dlm_ls *ls = r->res_ls;
        uint32_t bucket = r->res_bucket;
 
-       write_lock(&ls->ls_rsbtbl[bucket].lock);
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
        kref_put(&r->res_ref, toss_rsb);
-       write_unlock(&ls->ls_rsbtbl[bucket].lock);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
 }
 
 void dlm_put_rsb(struct dlm_rsb *r)
@@ -967,7 +967,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b)
 
        for (;;) {
                found = 0;
-               write_lock(&ls->ls_rsbtbl[b].lock);
+               spin_lock(&ls->ls_rsbtbl[b].lock);
                list_for_each_entry_reverse(r, &ls->ls_rsbtbl[b].toss,
                                            res_hashchain) {
                        if (!time_after_eq(jiffies, r->res_toss_time +
@@ -978,20 +978,20 @@ static int shrink_bucket(struct dlm_ls *ls, int b)
                }
 
                if (!found) {
-                       write_unlock(&ls->ls_rsbtbl[b].lock);
+                       spin_unlock(&ls->ls_rsbtbl[b].lock);
                        break;
                }
 
                if (kref_put(&r->res_ref, kill_rsb)) {
                        list_del(&r->res_hashchain);
-                       write_unlock(&ls->ls_rsbtbl[b].lock);
+                       spin_unlock(&ls->ls_rsbtbl[b].lock);
 
                        if (is_master(r))
                                dir_remove(r);
                        dlm_free_rsb(r);
                        count++;
                } else {
-                       write_unlock(&ls->ls_rsbtbl[b].lock);
+                       spin_unlock(&ls->ls_rsbtbl[b].lock);
                        log_error(ls, "tossed rsb in use %s", r->res_name);
                }
        }
@@ -4224,7 +4224,7 @@ static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
 {
        struct dlm_rsb *r, *r_ret = NULL;
 
-       read_lock(&ls->ls_rsbtbl[bucket].lock);
+       spin_lock(&ls->ls_rsbtbl[bucket].lock);
        list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list, res_hashchain) {
                if (!rsb_flag(r, RSB_LOCKS_PURGED))
                        continue;
@@ -4233,7 +4233,7 @@ static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
                r_ret = r;
                break;
        }
-       read_unlock(&ls->ls_rsbtbl[bucket].lock);
+       spin_unlock(&ls->ls_rsbtbl[bucket].lock);
        return r_ret;
 }
 
index 8d86b7960f0df7527fed5494230676b137b4f63b..aa32e5f02493656ef461099a024337793437e245 100644 (file)
@@ -464,7 +464,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
        for (i = 0; i < size; i++) {
                INIT_LIST_HEAD(&ls->ls_rsbtbl[i].list);
                INIT_LIST_HEAD(&ls->ls_rsbtbl[i].toss);
-               rwlock_init(&ls->ls_rsbtbl[i].lock);
+               spin_lock_init(&ls->ls_rsbtbl[i].lock);
        }
 
        size = dlm_config.ci_lkbtbl_size;
index 80aba5bdd4a4b72b0949fe4f0516c02f7d7f25ad..eda43f3626169ec9b08ad03fdecfd9b5aef7e821 100644 (file)
@@ -726,7 +726,7 @@ int dlm_create_root_list(struct dlm_ls *ls)
        }
 
        for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               read_lock(&ls->ls_rsbtbl[i].lock);
+               spin_lock(&ls->ls_rsbtbl[i].lock);
                list_for_each_entry(r, &ls->ls_rsbtbl[i].list, res_hashchain) {
                        list_add(&r->res_root_list, &ls->ls_root_list);
                        dlm_hold_rsb(r);
@@ -737,7 +737,7 @@ int dlm_create_root_list(struct dlm_ls *ls)
                   but no other recovery steps should do anything with them. */
 
                if (dlm_no_directory(ls)) {
-                       read_unlock(&ls->ls_rsbtbl[i].lock);
+                       spin_unlock(&ls->ls_rsbtbl[i].lock);
                        continue;
                }
 
@@ -745,7 +745,7 @@ int dlm_create_root_list(struct dlm_ls *ls)
                        list_add(&r->res_root_list, &ls->ls_root_list);
                        dlm_hold_rsb(r);
                }
-               read_unlock(&ls->ls_rsbtbl[i].lock);
+               spin_unlock(&ls->ls_rsbtbl[i].lock);
        }
  out:
        up_write(&ls->ls_root_sem);
@@ -775,7 +775,7 @@ void dlm_clear_toss_list(struct dlm_ls *ls)
        int i;
 
        for (i = 0; i < ls->ls_rsbtbl_size; i++) {
-               write_lock(&ls->ls_rsbtbl[i].lock);
+               spin_lock(&ls->ls_rsbtbl[i].lock);
                list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss,
                                         res_hashchain) {
                        if (dlm_no_directory(ls) || !is_master(r)) {
@@ -783,7 +783,7 @@ void dlm_clear_toss_list(struct dlm_ls *ls)
                                dlm_free_rsb(r);
                        }
                }
-               write_unlock(&ls->ls_rsbtbl[i].lock);
+               spin_unlock(&ls->ls_rsbtbl[i].lock);
        }
 }