diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-13 02:54:27 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-13 02:54:27 +0300 |
commit | c69e8839c230c60d3c5f62c8f88bd23d8d6519ee (patch) | |
tree | 8d4a28c589b8df9020561e19766bb9ba9edfebbf | |
parent | 3e55f1a292583b11ff85952eec77d65a459da2dd (diff) | |
parent | c7be761a8163d2f1ac0b606c21e4316b7abc5af7 (diff) | |
download | linux-c69e8839c230c60d3c5f62c8f88bd23d8d6519ee.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
* '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
-rw-r--r-- | fs/dlm/debug_fs.c | 696 | ||||
-rw-r--r-- | fs/dlm/dlm_internal.h | 2 | ||||
-rw-r--r-- | fs/dlm/lock.c | 26 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 2 | ||||
-rw-r--r-- | fs/dlm/recover.c | 10 |
5 files changed, 357 insertions, 379 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 2f107d1a6a45..1d1d27442235 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -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; diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index ef2f1e353966..076e86f38bc8 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -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 { diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 6cfe65bbf4a2..01e7d39c5fba 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -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; } diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 8d86b7960f0d..aa32e5f02493 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -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; diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index 80aba5bdd4a4..eda43f362616 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c @@ -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); } } |