aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosef Bacik2007-05-16 15:56:13 -0400
committerSteven Whitehouse2007-07-09 08:22:29 +0100
commit916297aad5de2363dccd531873eda55d4d6afb57 (patch)
treee8e5eabf529bd4a41d9ee225087e237581ce5ffd
parent2a87ab080607d009b8b2a8706f4e27d70402ca9c (diff)
[DLM] keep dlm from panicing when traversing rsb list in debugfs
This problem was originally reported against GFS6.1, but the same issue exists in upstream DLM. This patch keeps the rsb iterator assigning under the rsbtbl list lock. Each time we process an rsb we grab a reference to it to make sure it is not freed out from underneath us, and then put it when we get the next rsb in the list or move onto another list. Signed-off-by: Josef Bacik <jwhiter@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/dlm/debug_fs.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 61ba670b9e02..9e27a1675794 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include "dlm_internal.h"
+#include "lock.h"
#define DLM_DEBUG_BUF_LEN 4096
static char debug_buf[DLM_DEBUG_BUF_LEN];
@@ -166,6 +167,9 @@ static int rsb_iter_next(struct rsb_iter *ri)
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;
}
@@ -176,6 +180,7 @@ static int rsb_iter_next(struct rsb_iter *ri)
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;
@@ -184,11 +189,13 @@ static int rsb_iter_next(struct rsb_iter *ri)
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);
read_unlock(&ls->ls_rsbtbl[i].lock);
+ dlm_put_rsb(old);
}
- ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
return 0;
}