diff options
author | David Teigland <teigland@redhat.com> | 2006-07-25 14:44:31 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-07-26 08:41:37 -0400 |
commit | 5de6319b1839300ba6b461ed19531cdab90db9fc (patch) | |
tree | 99184cb3f935d2520be7739354a1b11eb0c278b0 /fs/dlm | |
parent | a9e5f4d0780ec9cda7a70b08294d7718431b62a1 (diff) |
[DLM] more info through debugfs
Display more information from debugfs, particularly locks waiting for
a master lookup or operations waiting for a remote reply.
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r-- | fs/dlm/debug_fs.c | 132 | ||||
-rw-r--r-- | fs/dlm/dlm_internal.h | 3 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 3 |
3 files changed, 114 insertions, 24 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 49deca845dba..5faa747c7ca1 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
@@ -18,6 +18,9 @@ | |||
18 | 18 | ||
19 | #include "dlm_internal.h" | 19 | #include "dlm_internal.h" |
20 | 20 | ||
21 | #define DLM_DEBUG_BUF_LEN 4096 | ||
22 | static char debug_buf[DLM_DEBUG_BUF_LEN]; | ||
23 | static struct mutex debug_buf_lock; | ||
21 | 24 | ||
22 | static struct dentry *dlm_root; | 25 | static struct dentry *dlm_root; |
23 | 26 | ||
@@ -28,6 +31,10 @@ struct rsb_iter { | |||
28 | struct dlm_rsb *rsb; | 31 | struct dlm_rsb *rsb; |
29 | }; | 32 | }; |
30 | 33 | ||
34 | /* | ||
35 | * dump all rsb's in the lockspace hash table | ||
36 | */ | ||
37 | |||
31 | static char *print_lockmode(int mode) | 38 | static char *print_lockmode(int mode) |
32 | { | 39 | { |
33 | switch (mode) { | 40 | switch (mode) { |
@@ -76,7 +83,7 @@ static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, | |||
76 | static int print_resource(struct dlm_rsb *res, struct seq_file *s) | 83 | static int print_resource(struct dlm_rsb *res, struct seq_file *s) |
77 | { | 84 | { |
78 | struct dlm_lkb *lkb; | 85 | struct dlm_lkb *lkb; |
79 | int i, lvblen = res->res_ls->ls_lvblen; | 86 | int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; |
80 | 87 | ||
81 | seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); | 88 | seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); |
82 | for (i = 0; i < res->res_length; i++) { | 89 | for (i = 0; i < res->res_length; i++) { |
@@ -110,6 +117,15 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
110 | seq_printf(s, "\n"); | 117 | seq_printf(s, "\n"); |
111 | } | 118 | } |
112 | 119 | ||
120 | root_list = !list_empty(&res->res_root_list); | ||
121 | recover_list = !list_empty(&res->res_recover_list); | ||
122 | |||
123 | if (root_list || recover_list) { | ||
124 | seq_printf(s, "Recovery: root %d recover %d flags %lx " | ||
125 | "count %d\n", root_list, recover_list, | ||
126 | res->flags, res->res_recover_locks_count); | ||
127 | } | ||
128 | |||
113 | /* Print the locks attached to this resource */ | 129 | /* Print the locks attached to this resource */ |
114 | seq_printf(s, "Granted Queue\n"); | 130 | seq_printf(s, "Granted Queue\n"); |
115 | list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) | 131 | list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) |
@@ -123,6 +139,18 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
123 | list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) | 139 | list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) |
124 | print_lock(s, lkb, res); | 140 | print_lock(s, lkb, res); |
125 | 141 | ||
142 | if (list_empty(&res->res_lookup)) | ||
143 | goto out; | ||
144 | |||
145 | seq_printf(s, "Lookup Queue\n"); | ||
146 | list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) { | ||
147 | seq_printf(s, "%08x %s", lkb->lkb_id, | ||
148 | print_lockmode(lkb->lkb_rqmode)); | ||
149 | if (lkb->lkb_wait_type) | ||
150 | seq_printf(s, " wait_type: %d", lkb->lkb_wait_type); | ||
151 | seq_printf(s, "\n"); | ||
152 | } | ||
153 | out: | ||
126 | return 0; | 154 | return 0; |
127 | } | 155 | } |
128 | 156 | ||
@@ -190,7 +218,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls) | |||
190 | return ri; | 218 | return ri; |
191 | } | 219 | } |
192 | 220 | ||
193 | static void *seq_start(struct seq_file *file, loff_t *pos) | 221 | static void *rsb_seq_start(struct seq_file *file, loff_t *pos) |
194 | { | 222 | { |
195 | struct rsb_iter *ri; | 223 | struct rsb_iter *ri; |
196 | loff_t n = *pos; | 224 | loff_t n = *pos; |
@@ -209,7 +237,7 @@ static void *seq_start(struct seq_file *file, loff_t *pos) | |||
209 | return ri; | 237 | return ri; |
210 | } | 238 | } |
211 | 239 | ||
212 | static void *seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos) | 240 | static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos) |
213 | { | 241 | { |
214 | struct rsb_iter *ri = iter_ptr; | 242 | struct rsb_iter *ri = iter_ptr; |
215 | 243 | ||
@@ -223,12 +251,12 @@ static void *seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos) | |||
223 | return ri; | 251 | return ri; |
224 | } | 252 | } |
225 | 253 | ||
226 | static void seq_stop(struct seq_file *file, void *iter_ptr) | 254 | static void rsb_seq_stop(struct seq_file *file, void *iter_ptr) |
227 | { | 255 | { |
228 | /* nothing for now */ | 256 | /* nothing for now */ |
229 | } | 257 | } |
230 | 258 | ||
231 | static int seq_show(struct seq_file *file, void *iter_ptr) | 259 | static int rsb_seq_show(struct seq_file *file, void *iter_ptr) |
232 | { | 260 | { |
233 | struct rsb_iter *ri = iter_ptr; | 261 | struct rsb_iter *ri = iter_ptr; |
234 | 262 | ||
@@ -237,19 +265,19 @@ static int seq_show(struct seq_file *file, void *iter_ptr) | |||
237 | return 0; | 265 | return 0; |
238 | } | 266 | } |
239 | 267 | ||
240 | static struct seq_operations dlm_seq_ops = { | 268 | static struct seq_operations rsb_seq_ops = { |
241 | .start = seq_start, | 269 | .start = rsb_seq_start, |
242 | .next = seq_next, | 270 | .next = rsb_seq_next, |
243 | .stop = seq_stop, | 271 | .stop = rsb_seq_stop, |
244 | .show = seq_show, | 272 | .show = rsb_seq_show, |
245 | }; | 273 | }; |
246 | 274 | ||
247 | static int do_open(struct inode *inode, struct file *file) | 275 | static int rsb_open(struct inode *inode, struct file *file) |
248 | { | 276 | { |
249 | struct seq_file *seq; | 277 | struct seq_file *seq; |
250 | int ret; | 278 | int ret; |
251 | 279 | ||
252 | ret = seq_open(file, &dlm_seq_ops); | 280 | ret = rsb_seq_open(file, &rsb_seq_ops); |
253 | if (ret) | 281 | if (ret) |
254 | return ret; | 282 | return ret; |
255 | 283 | ||
@@ -259,32 +287,92 @@ static int do_open(struct inode *inode, struct file *file) | |||
259 | return 0; | 287 | return 0; |
260 | } | 288 | } |
261 | 289 | ||
262 | static struct file_operations dlm_fops = { | 290 | static struct file_operations rsb_fops = { |
263 | .owner = THIS_MODULE, | 291 | .owner = THIS_MODULE, |
264 | .open = do_open, | 292 | .open = rsb_open, |
265 | .read = seq_read, | 293 | .read = seq_read, |
266 | .llseek = seq_lseek, | 294 | .llseek = seq_lseek, |
267 | .release = seq_release | 295 | .release = seq_release |
268 | }; | 296 | }; |
269 | 297 | ||
298 | /* | ||
299 | * dump lkb's on the ls_waiters list | ||
300 | */ | ||
301 | |||
302 | static int waiters_open(struct inode *inode, struct file *file) | ||
303 | { | ||
304 | file->private_data = inode->i_private; | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static ssize_t waiters_read(struct file *file, char __user *userbuf, | ||
309 | size_t count, loff_t *ppos) | ||
310 | { | ||
311 | struct dlm_ls *ls = file->private_data; | ||
312 | struct dlm_lkb *lkb; | ||
313 | size_t len = DLM_DEBUG_BUF_LEN, pos = 0, rv; | ||
314 | |||
315 | mutex_lock(&debug_buf_lock); | ||
316 | mutex_lock(&ls->ls_waiters_mutex); | ||
317 | memset(debug_buf, 0, sizeof(debug_buf)); | ||
318 | |||
319 | list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { | ||
320 | pos += snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n", | ||
321 | lkb->lkb_id, lkb->lkb_wait_type, | ||
322 | lkb->lkb_nodeid, lkb->lkb_resource->res_name); | ||
323 | } | ||
324 | mutex_unlock(&ls->ls_waiters_mutex); | ||
325 | |||
326 | rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos); | ||
327 | mutex_unlock(&debug_buf_lock); | ||
328 | return rv; | ||
329 | } | ||
330 | |||
331 | static struct file_operations waiters_fops = { | ||
332 | .owner = THIS_MODULE, | ||
333 | .open = waiters_open, | ||
334 | .read = waiters_read | ||
335 | }; | ||
336 | |||
270 | int dlm_create_debug_file(struct dlm_ls *ls) | 337 | int dlm_create_debug_file(struct dlm_ls *ls) |
271 | { | 338 | { |
272 | ls->ls_debug_dentry = debugfs_create_file(ls->ls_name, | 339 | char name[DLM_LOCKSPACE_LEN+8]; |
273 | S_IFREG | S_IRUGO, | 340 | |
274 | dlm_root, | 341 | ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name, |
275 | ls, | 342 | S_IFREG | S_IRUGO, |
276 | &dlm_fops); | 343 | dlm_root, |
277 | return ls->ls_debug_dentry ? 0 : -ENOMEM; | 344 | ls, |
345 | &rsb_fops); | ||
346 | if (!ls->ls_rsb_debug_dentry) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | memset(name, 0, sizeof(name)); | ||
350 | snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name); | ||
351 | |||
352 | ls->ls_debug_waiters_dentry = debugfs_create_file(name, | ||
353 | S_IFREG | S_IRUGO, | ||
354 | dlm_root, | ||
355 | ls, | ||
356 | &waiters_fops); | ||
357 | if (!ls->ls_debug_waiters_dentry) { | ||
358 | debugfs_remove(ls->ls_debug_rsb_dentry); | ||
359 | return -ENOMEM; | ||
360 | } | ||
361 | |||
362 | return 0; | ||
278 | } | 363 | } |
279 | 364 | ||
280 | void dlm_delete_debug_file(struct dlm_ls *ls) | 365 | void dlm_delete_debug_file(struct dlm_ls *ls) |
281 | { | 366 | { |
282 | if (ls->ls_debug_dentry) | 367 | if (ls->ls_debug_rsb_dentry) |
283 | debugfs_remove(ls->ls_debug_dentry); | 368 | debugfs_remove(ls->ls_debug_rsb_dentry); |
369 | if (ls->ls_debug_waiters_dentry) | ||
370 | debugfs_remove(ls->ls_debug_waiters_dentry); | ||
284 | } | 371 | } |
285 | 372 | ||
286 | int dlm_register_debugfs(void) | 373 | int dlm_register_debugfs(void) |
287 | { | 374 | { |
375 | mutex_init(&debug_buf_lock); | ||
288 | dlm_root = debugfs_create_dir("dlm", NULL); | 376 | dlm_root = debugfs_create_dir("dlm", NULL); |
289 | return dlm_root ? 0 : -ENOMEM; | 377 | return dlm_root ? 0 : -ENOMEM; |
290 | } | 378 | } |
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index db080de2a7e9..7c3c2d27c012 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -446,7 +446,8 @@ struct dlm_ls { | |||
446 | struct dlm_lkb ls_stub_lkb; /* for returning errors */ | 446 | struct dlm_lkb ls_stub_lkb; /* for returning errors */ |
447 | struct dlm_message ls_stub_ms; /* for faking a reply */ | 447 | struct dlm_message ls_stub_ms; /* for faking a reply */ |
448 | 448 | ||
449 | struct dentry *ls_debug_dentry; /* debugfs */ | 449 | struct dentry *ls_debug_rsb_dentry; /* debugfs */ |
450 | struct dentry *ls_debug_waiters_dentry; /* debugfs */ | ||
450 | 451 | ||
451 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ | 452 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ |
452 | int ls_uevent_result; | 453 | int ls_uevent_result; |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 3f6cb422ac4b..31ed0fe16a31 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -446,7 +446,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
446 | memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb)); | 446 | memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb)); |
447 | ls->ls_stub_rsb.res_ls = ls; | 447 | ls->ls_stub_rsb.res_ls = ls; |
448 | 448 | ||
449 | ls->ls_debug_dentry = NULL; | 449 | ls->ls_debug_rsb_dentry = NULL; |
450 | ls->ls_debug_waiters_dentry = NULL; | ||
450 | 451 | ||
451 | init_waitqueue_head(&ls->ls_uevent_wait); | 452 | init_waitqueue_head(&ls->ls_uevent_wait); |
452 | ls->ls_uevent_result = 0; | 453 | ls->ls_uevent_result = 0; |