]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/dlm-fix-seq_file-usage-in-debugfs-lock-dump.patch
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / dlm-fix-seq_file-usage-in-debugfs-lock-dump.patch
1 From: David Teigland <teigland@redhat.com>
2 commit 892c4467e335e9050c95e0d8409c136c4dadaca2
3 Author: David Teigland <teigland@redhat.com>
4 Date: Wed Jan 7 16:48:52 2009 -0600
5 Subject: dlm: fix seq_file usage in debugfs lock dump
6
7 The old code would leak iterators and leave reference counts on
8 rsbs because it was ignoring the "stop" seq callback. The code
9 followed an example that used the seq operations differently.
10 This new code is based on actually understanding how the seq
11 operations work. It also improves things by saving the hash bucket
12 in the position to avoid cycling through completed buckets in start.
13
14 Siged-off-by: Davd Teigland <teigland@redhat.com>
15 Signed-off-by: Coly Li <coly.li@suse.de>
16
17 diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
18 index 2f107d1..bc4af3e 100644
19 --- a/fs/dlm/debug_fs.c
20 +++ b/fs/dlm/debug_fs.c
21 @@ -1,7 +1,7 @@
22 /******************************************************************************
23 *******************************************************************************
24 **
25 -** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
26 +** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
27 **
28 ** This copyrighted material is made available to anyone wishing to use,
29 ** modify, copy, or redistribute it subject to the terms and conditions
30 @@ -25,19 +25,6 @@ static struct mutex debug_buf_lock;
31
32 static struct dentry *dlm_root;
33
34 -struct rsb_iter {
35 - int entry;
36 - int format;
37 - int header;
38 - struct dlm_ls *ls;
39 - struct list_head *next;
40 - struct dlm_rsb *rsb;
41 -};
42 -
43 -/*
44 - * dump all rsb's in the lockspace hash table
45 - */
46 -
47 static char *print_lockmode(int mode)
48 {
49 switch (mode) {
50 @@ -60,13 +47,13 @@ static char *print_lockmode(int mode)
51 }
52 }
53
54 -static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
55 - struct dlm_rsb *res)
56 +static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
57 + struct dlm_rsb *res)
58 {
59 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
60
61 - if (lkb->lkb_status == DLM_LKSTS_CONVERT
62 - || lkb->lkb_status == DLM_LKSTS_WAITING)
63 + if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
64 + lkb->lkb_status == DLM_LKSTS_WAITING)
65 seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
66
67 if (lkb->lkb_nodeid) {
68 @@ -80,33 +67,42 @@ static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
69 if (lkb->lkb_wait_type)
70 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
71
72 - seq_printf(s, "\n");
73 + return seq_printf(s, "\n");
74 }
75
76 static int print_format1(struct dlm_rsb *res, struct seq_file *s)
77 {
78 struct dlm_lkb *lkb;
79 int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
80 + int rv;
81
82 lock_rsb(res);
83
84 - seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
85 + rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
86 + res, res->res_length);
87 + if (rv)
88 + goto out;
89 +
90 for (i = 0; i < res->res_length; i++) {
91 if (isprint(res->res_name[i]))
92 seq_printf(s, "%c", res->res_name[i]);
93 else
94 seq_printf(s, "%c", '.');
95 }
96 +
97 if (res->res_nodeid > 0)
98 - seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
99 - res->res_nodeid);
100 + rv = seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
101 + res->res_nodeid);
102 else if (res->res_nodeid == 0)
103 - seq_printf(s, "\" \nMaster Copy\n");
104 + rv = seq_printf(s, "\" \nMaster Copy\n");
105 else if (res->res_nodeid == -1)
106 - seq_printf(s, "\" \nLooking up master (lkid %x)\n",
107 - res->res_first_lkid);
108 + rv = seq_printf(s, "\" \nLooking up master (lkid %x)\n",
109 + res->res_first_lkid);
110 else
111 - seq_printf(s, "\" \nInvalid master %d\n", res->res_nodeid);
112 + rv = seq_printf(s, "\" \nInvalid master %d\n",
113 + res->res_nodeid);
114 + if (rv)
115 + goto out;
116
117 /* Print the LVB: */
118 if (res->res_lvbptr) {
119 @@ -119,52 +115,66 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
120 }
121 if (rsb_flag(res, RSB_VALNOTVALID))
122 seq_printf(s, " (INVALID)");
123 - seq_printf(s, "\n");
124 + rv = seq_printf(s, "\n");
125 + if (rv)
126 + goto out;
127 }
128
129 root_list = !list_empty(&res->res_root_list);
130 recover_list = !list_empty(&res->res_recover_list);
131
132 if (root_list || recover_list) {
133 - seq_printf(s, "Recovery: root %d recover %d flags %lx "
134 - "count %d\n", root_list, recover_list,
135 - res->res_flags, res->res_recover_locks_count);
136 + rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
137 + "count %d\n", root_list, recover_list,
138 + res->res_flags, res->res_recover_locks_count);
139 + if (rv)
140 + goto out;
141 }
142
143 /* Print the locks attached to this resource */
144 seq_printf(s, "Granted Queue\n");
145 - list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
146 - print_format1_lock(s, lkb, res);
147 + list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
148 + rv = print_format1_lock(s, lkb, res);
149 + if (rv)
150 + goto out;
151 + }
152
153 seq_printf(s, "Conversion Queue\n");
154 - list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
155 - print_format1_lock(s, lkb, res);
156 + list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
157 + rv = print_format1_lock(s, lkb, res);
158 + if (rv)
159 + goto out;
160 + }
161
162 seq_printf(s, "Waiting Queue\n");
163 - list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
164 - print_format1_lock(s, lkb, res);
165 + list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
166 + rv = print_format1_lock(s, lkb, res);
167 + if (rv)
168 + goto out;
169 + }
170
171 if (list_empty(&res->res_lookup))
172 goto out;
173
174 seq_printf(s, "Lookup Queue\n");
175 list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
176 - seq_printf(s, "%08x %s", lkb->lkb_id,
177 - print_lockmode(lkb->lkb_rqmode));
178 + rv = seq_printf(s, "%08x %s", lkb->lkb_id,
179 + print_lockmode(lkb->lkb_rqmode));
180 if (lkb->lkb_wait_type)
181 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
182 - seq_printf(s, "\n");
183 + rv = seq_printf(s, "\n");
184 }
185 out:
186 unlock_rsb(res);
187 - return 0;
188 + return rv;
189 }
190
191 -static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
192 - struct dlm_rsb *r)
193 +static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
194 + struct dlm_rsb *r)
195 {
196 u64 xid = 0;
197 u64 us;
198 + int rv;
199
200 if (lkb->lkb_flags & DLM_IFL_USER) {
201 if (lkb->lkb_ua)
202 @@ -177,69 +187,82 @@ static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
203 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
204 r_nodeid r_len r_name */
205
206 - seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
207 - lkb->lkb_id,
208 - lkb->lkb_nodeid,
209 - lkb->lkb_remid,
210 - lkb->lkb_ownpid,
211 - (unsigned long long)xid,
212 - lkb->lkb_exflags,
213 - lkb->lkb_flags,
214 - lkb->lkb_status,
215 - lkb->lkb_grmode,
216 - lkb->lkb_rqmode,
217 - (unsigned long long)us,
218 - r->res_nodeid,
219 - r->res_length,
220 - r->res_name);
221 + rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
222 + lkb->lkb_id,
223 + lkb->lkb_nodeid,
224 + lkb->lkb_remid,
225 + lkb->lkb_ownpid,
226 + (unsigned long long)xid,
227 + lkb->lkb_exflags,
228 + lkb->lkb_flags,
229 + lkb->lkb_status,
230 + lkb->lkb_grmode,
231 + lkb->lkb_rqmode,
232 + (unsigned long long)us,
233 + r->res_nodeid,
234 + r->res_length,
235 + r->res_name);
236 + return rv;
237 }
238
239 static int print_format2(struct dlm_rsb *r, struct seq_file *s)
240 {
241 struct dlm_lkb *lkb;
242 + int rv = 0;
243
244 lock_rsb(r);
245
246 - list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
247 - print_format2_lock(s, lkb, r);
248 -
249 - list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
250 - print_format2_lock(s, lkb, r);
251 + list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
252 + rv = print_format2_lock(s, lkb, r);
253 + if (rv)
254 + goto out;
255 + }
256
257 - list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
258 - print_format2_lock(s, lkb, r);
259 + list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
260 + rv = print_format2_lock(s, lkb, r);
261 + if (rv)
262 + goto out;
263 + }
264
265 + list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
266 + rv = print_format2_lock(s, lkb, r);
267 + if (rv)
268 + goto out;
269 + }
270 + out:
271 unlock_rsb(r);
272 - return 0;
273 + return rv;
274 }
275
276 -static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
277 - int rsb_lookup)
278 +static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
279 + int rsb_lookup)
280 {
281 u64 xid = 0;
282 + int rv;
283
284 if (lkb->lkb_flags & DLM_IFL_USER) {
285 if (lkb->lkb_ua)
286 xid = lkb->lkb_ua->xid;
287 }
288
289 - seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
290 - lkb->lkb_id,
291 - lkb->lkb_nodeid,
292 - lkb->lkb_remid,
293 - lkb->lkb_ownpid,
294 - (unsigned long long)xid,
295 - lkb->lkb_exflags,
296 - lkb->lkb_flags,
297 - lkb->lkb_status,
298 - lkb->lkb_grmode,
299 - lkb->lkb_rqmode,
300 - lkb->lkb_highbast,
301 - rsb_lookup,
302 - lkb->lkb_wait_type,
303 - lkb->lkb_lvbseq,
304 - (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
305 - (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
306 + rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
307 + lkb->lkb_id,
308 + lkb->lkb_nodeid,
309 + lkb->lkb_remid,
310 + lkb->lkb_ownpid,
311 + (unsigned long long)xid,
312 + lkb->lkb_exflags,
313 + lkb->lkb_flags,
314 + lkb->lkb_status,
315 + lkb->lkb_grmode,
316 + lkb->lkb_rqmode,
317 + lkb->lkb_highbast,
318 + rsb_lookup,
319 + lkb->lkb_wait_type,
320 + lkb->lkb_lvbseq,
321 + (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
322 + (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
323 + return rv;
324 }
325
326 static int print_format3(struct dlm_rsb *r, struct seq_file *s)
327 @@ -247,18 +270,21 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
328 struct dlm_lkb *lkb;
329 int i, lvblen = r->res_ls->ls_lvblen;
330 int print_name = 1;
331 + int rv;
332
333 lock_rsb(r);
334
335 - seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
336 - r,
337 - r->res_nodeid,
338 - r->res_first_lkid,
339 - r->res_flags,
340 - !list_empty(&r->res_root_list),
341 - !list_empty(&r->res_recover_list),
342 - r->res_recover_locks_count,
343 - r->res_length);
344 + rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
345 + r,
346 + r->res_nodeid,
347 + r->res_first_lkid,
348 + r->res_flags,
349 + !list_empty(&r->res_root_list),
350 + !list_empty(&r->res_recover_list),
351 + r->res_recover_locks_count,
352 + r->res_length);
353 + if (rv)
354 + goto out;
355
356 for (i = 0; i < r->res_length; i++) {
357 if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
358 @@ -273,7 +299,9 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
359 else
360 seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
361 }
362 - seq_printf(s, "\n");
363 + rv = seq_printf(s, "\n");
364 + if (rv)
365 + goto out;
366
367 if (!r->res_lvbptr)
368 goto do_locks;
369 @@ -282,344 +310,294 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
370
371 for (i = 0; i < lvblen; i++)
372 seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
373 - seq_printf(s, "\n");
374 + rv = seq_printf(s, "\n");
375 + if (rv)
376 + goto out;
377
378 do_locks:
379 - list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
380 - print_format3_lock(s, lkb, 0);
381 -
382 - list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
383 - print_format3_lock(s, lkb, 0);
384 -
385 - list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
386 - print_format3_lock(s, lkb, 0);
387 -
388 - list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
389 - print_format3_lock(s, lkb, 1);
390 -
391 - unlock_rsb(r);
392 - return 0;
393 -}
394 -
395 -static int rsb_iter_next(struct rsb_iter *ri)
396 -{
397 - struct dlm_ls *ls = ri->ls;
398 - int i;
399 -
400 - if (!ri->next) {
401 - top:
402 - /* Find the next non-empty hash bucket */
403 - for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
404 - read_lock(&ls->ls_rsbtbl[i].lock);
405 - if (!list_empty(&ls->ls_rsbtbl[i].list)) {
406 - ri->next = ls->ls_rsbtbl[i].list.next;
407 - ri->rsb = list_entry(ri->next, struct dlm_rsb,
408 - res_hashchain);
409 - dlm_hold_rsb(ri->rsb);
410 - read_unlock(&ls->ls_rsbtbl[i].lock);
411 - break;
412 - }
413 - read_unlock(&ls->ls_rsbtbl[i].lock);
414 - }
415 - ri->entry = i;
416 -
417 - if (ri->entry >= ls->ls_rsbtbl_size)
418 - return 1;
419 - } else {
420 - struct dlm_rsb *old = ri->rsb;
421 - i = ri->entry;
422 - read_lock(&ls->ls_rsbtbl[i].lock);
423 - ri->next = ri->next->next;
424 - if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
425 - /* End of list - move to next bucket */
426 - ri->next = NULL;
427 - ri->entry++;
428 - read_unlock(&ls->ls_rsbtbl[i].lock);
429 - dlm_put_rsb(old);
430 - goto top;
431 - }
432 - ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
433 - dlm_hold_rsb(ri->rsb);
434 - read_unlock(&ls->ls_rsbtbl[i].lock);
435 - dlm_put_rsb(old);
436 + list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
437 + rv = print_format3_lock(s, lkb, 0);
438 + if (rv)
439 + goto out;
440 }
441
442 - return 0;
443 -}
444 -
445 -static void rsb_iter_free(struct rsb_iter *ri)
446 -{
447 - kfree(ri);
448 -}
449 -
450 -static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
451 -{
452 - struct rsb_iter *ri;
453 -
454 - ri = kzalloc(sizeof *ri, GFP_KERNEL);
455 - if (!ri)
456 - return NULL;
457 -
458 - ri->ls = ls;
459 - ri->entry = 0;
460 - ri->next = NULL;
461 - ri->format = 1;
462 -
463 - if (rsb_iter_next(ri)) {
464 - rsb_iter_free(ri);
465 - return NULL;
466 + list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
467 + rv = print_format3_lock(s, lkb, 0);
468 + if (rv)
469 + goto out;
470 }
471
472 - return ri;
473 -}
474 -
475 -static void *rsb_seq_start(struct seq_file *file, loff_t *pos)
476 -{
477 - struct rsb_iter *ri;
478 - loff_t n = *pos;
479 -
480 - ri = rsb_iter_init(file->private);
481 - if (!ri)
482 - return NULL;
483 -
484 - while (n--) {
485 - if (rsb_iter_next(ri)) {
486 - rsb_iter_free(ri);
487 - return NULL;
488 - }
489 + list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
490 + rv = print_format3_lock(s, lkb, 0);
491 + if (rv)
492 + goto out;
493 }
494
495 - return ri;
496 -}
497 -
498 -static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos)
499 -{
500 - struct rsb_iter *ri = iter_ptr;
501 -
502 - (*pos)++;
503 -
504 - if (rsb_iter_next(ri)) {
505 - rsb_iter_free(ri);
506 - return NULL;
507 + list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
508 + rv = print_format3_lock(s, lkb, 1);
509 + if (rv)
510 + goto out;
511 }
512 -
513 - return ri;
514 + out:
515 + unlock_rsb(r);
516 + return rv;
517 }
518
519 -static void rsb_seq_stop(struct seq_file *file, void *iter_ptr)
520 -{
521 - /* nothing for now */
522 -}
523 +struct rsbtbl_iter {
524 + struct dlm_rsb *rsb;
525 + unsigned bucket;
526 + int format;
527 + int header;
528 +};
529
530 -static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
531 +/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
532 + If the buffer is full, seq_printf can be called again, but it
533 + does nothing and just returns -1. So, the these printing routines
534 + periodically check the return value to avoid wasting too much time
535 + trying to print to a full buffer. */
536 +
537 +static int table_seq_show(struct seq_file *seq, void *iter_ptr)
538 {
539 - struct rsb_iter *ri = iter_ptr;
540 + struct rsbtbl_iter *ri = iter_ptr;
541 + int rv = 0;
542
543 switch (ri->format) {
544 case 1:
545 - print_format1(ri->rsb, file);
546 + rv = print_format1(ri->rsb, seq);
547 break;
548 case 2:
549 if (ri->header) {
550 - seq_printf(file, "id nodeid remid pid xid exflags "
551 - "flags sts grmode rqmode time_ms "
552 - "r_nodeid r_len r_name\n");
553 + seq_printf(seq, "id nodeid remid pid xid exflags "
554 + "flags sts grmode rqmode time_ms "
555 + "r_nodeid r_len r_name\n");
556 ri->header = 0;
557 }
558 - print_format2(ri->rsb, file);
559 + rv = print_format2(ri->rsb, seq);
560 break;
561 case 3:
562 if (ri->header) {
563 - seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
564 + seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
565 ri->header = 0;
566 }
567 - print_format3(ri->rsb, file);
568 + rv = print_format3(ri->rsb, seq);
569 break;
570 }
571
572 - return 0;
573 + return rv;
574 }
575
576 -static struct seq_operations rsb_seq_ops = {
577 - .start = rsb_seq_start,
578 - .next = rsb_seq_next,
579 - .stop = rsb_seq_stop,
580 - .show = rsb_seq_show,
581 -};
582 +static struct seq_operations format1_seq_ops;
583 +static struct seq_operations format2_seq_ops;
584 +static struct seq_operations format3_seq_ops;
585
586 -static int rsb_open(struct inode *inode, struct file *file)
587 +static void *table_seq_start(struct seq_file *seq, loff_t *pos)
588 {
589 - struct seq_file *seq;
590 - int ret;
591 -
592 - ret = seq_open(file, &rsb_seq_ops);
593 - if (ret)
594 - return ret;
595 -
596 - seq = file->private_data;
597 - seq->private = inode->i_private;
598 -
599 - return 0;
600 -}
601 -
602 -static const struct file_operations rsb_fops = {
603 - .owner = THIS_MODULE,
604 - .open = rsb_open,
605 - .read = seq_read,
606 - .llseek = seq_lseek,
607 - .release = seq_release
608 -};
609 + struct dlm_ls *ls = seq->private;
610 + struct rsbtbl_iter *ri;
611 + struct dlm_rsb *r;
612 + loff_t n = *pos;
613 + unsigned bucket, entry;
614
615 -/*
616 - * Dump state in compact per-lock listing
617 - */
618 + bucket = n >> 32;
619 + entry = n & ((1LL << 32) - 1);
620
621 -static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
622 -{
623 - struct rsb_iter *ri;
624 + if (bucket >= ls->ls_rsbtbl_size)
625 + return NULL;
626
627 - ri = kzalloc(sizeof *ri, GFP_KERNEL);
628 + ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
629 if (!ri)
630 return NULL;
631 -
632 - ri->ls = ls;
633 - ri->entry = 0;
634 - ri->next = NULL;
635 - ri->format = 2;
636 -
637 - if (*pos == 0)
638 + if (n == 0)
639 ri->header = 1;
640 -
641 - if (rsb_iter_next(ri)) {
642 - rsb_iter_free(ri);
643 - return NULL;
644 + if (seq->op == &format1_seq_ops)
645 + ri->format = 1;
646 + if (seq->op == &format2_seq_ops)
647 + ri->format = 2;
648 + if (seq->op == &format3_seq_ops)
649 + ri->format = 3;
650 +
651 + read_lock(&ls->ls_rsbtbl[bucket].lock);
652 + if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
653 + list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list,
654 + res_hashchain) {
655 + if (!entry--) {
656 + dlm_hold_rsb(r);
657 + ri->rsb = r;
658 + ri->bucket = bucket;
659 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
660 + return ri;
661 + }
662 + }
663 }
664 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
665
666 - return ri;
667 -}
668 + /*
669 + * move to the first rsb in the next non-empty bucket
670 + */
671
672 -static void *locks_seq_start(struct seq_file *file, loff_t *pos)
673 -{
674 - struct rsb_iter *ri;
675 - loff_t n = *pos;
676 + /* zero the entry */
677 + n &= ~((1LL << 32) - 1);
678
679 - ri = locks_iter_init(file->private, pos);
680 - if (!ri)
681 - return NULL;
682 + while (1) {
683 + bucket++;
684 + n += 1LL << 32;
685
686 - while (n--) {
687 - if (rsb_iter_next(ri)) {
688 - rsb_iter_free(ri);
689 + if (bucket >= ls->ls_rsbtbl_size) {
690 + kfree(ri);
691 return NULL;
692 }
693 - }
694
695 - return ri;
696 + read_lock(&ls->ls_rsbtbl[bucket].lock);
697 + if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
698 + r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
699 + struct dlm_rsb, res_hashchain);
700 + dlm_hold_rsb(r);
701 + ri->rsb = r;
702 + ri->bucket = bucket;
703 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
704 + *pos = n;
705 + return ri;
706 + }
707 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
708 + }
709 }
710
711 -static struct seq_operations locks_seq_ops = {
712 - .start = locks_seq_start,
713 - .next = rsb_seq_next,
714 - .stop = rsb_seq_stop,
715 - .show = rsb_seq_show,
716 -};
717 -
718 -static int locks_open(struct inode *inode, struct file *file)
719 +static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
720 {
721 - struct seq_file *seq;
722 - int ret;
723 -
724 - ret = seq_open(file, &locks_seq_ops);
725 - if (ret)
726 - return ret;
727 -
728 - seq = file->private_data;
729 - seq->private = inode->i_private;
730 -
731 - return 0;
732 -}
733 -
734 -static const struct file_operations locks_fops = {
735 - .owner = THIS_MODULE,
736 - .open = locks_open,
737 - .read = seq_read,
738 - .llseek = seq_lseek,
739 - .release = seq_release
740 -};
741 -
742 -/*
743 - * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks
744 - * This can replace both formats 1 and 2 eventually.
745 - */
746 + struct dlm_ls *ls = seq->private;
747 + struct rsbtbl_iter *ri = iter_ptr;
748 + struct list_head *next;
749 + struct dlm_rsb *r, *rp;
750 + loff_t n = *pos;
751 + unsigned bucket;
752 +
753 + bucket = n >> 32;
754 +
755 + /*
756 + * move to the next rsb in the same bucket
757 + */
758 +
759 + read_lock(&ls->ls_rsbtbl[bucket].lock);
760 + rp = ri->rsb;
761 + next = rp->res_hashchain.next;
762 +
763 + if (next != &ls->ls_rsbtbl[bucket].list) {
764 + r = list_entry(next, struct dlm_rsb, res_hashchain);
765 + dlm_hold_rsb(r);
766 + ri->rsb = r;
767 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
768 + dlm_put_rsb(rp);
769 + ++*pos;
770 + return ri;
771 + }
772 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
773 + dlm_put_rsb(rp);
774
775 -static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos)
776 -{
777 - struct rsb_iter *ri;
778 + /*
779 + * move to the first rsb in the next non-empty bucket
780 + */
781
782 - ri = kzalloc(sizeof *ri, GFP_KERNEL);
783 - if (!ri)
784 - return NULL;
785 + /* zero the entry */
786 + n &= ~((1LL << 32) - 1);
787
788 - ri->ls = ls;
789 - ri->entry = 0;
790 - ri->next = NULL;
791 - ri->format = 3;
792 + while (1) {
793 + bucket++;
794 + n += 1LL << 32;
795
796 - if (*pos == 0)
797 - ri->header = 1;
798 + if (bucket >= ls->ls_rsbtbl_size) {
799 + kfree(ri);
800 + return NULL;
801 + }
802
803 - if (rsb_iter_next(ri)) {
804 - rsb_iter_free(ri);
805 - return NULL;
806 + read_lock(&ls->ls_rsbtbl[bucket].lock);
807 + if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
808 + r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
809 + struct dlm_rsb, res_hashchain);
810 + dlm_hold_rsb(r);
811 + ri->rsb = r;
812 + ri->bucket = bucket;
813 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
814 + *pos = n;
815 + return ri;
816 + }
817 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
818 }
819 -
820 - return ri;
821 }
822
823 -static void *all_seq_start(struct seq_file *file, loff_t *pos)
824 +static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
825 {
826 - struct rsb_iter *ri;
827 - loff_t n = *pos;
828 -
829 - ri = all_iter_init(file->private, pos);
830 - if (!ri)
831 - return NULL;
832 + struct rsbtbl_iter *ri = iter_ptr;
833
834 - while (n--) {
835 - if (rsb_iter_next(ri)) {
836 - rsb_iter_free(ri);
837 - return NULL;
838 - }
839 + if (ri) {
840 + dlm_put_rsb(ri->rsb);
841 + kfree(ri);
842 }
843 -
844 - return ri;
845 }
846
847 -static struct seq_operations all_seq_ops = {
848 - .start = all_seq_start,
849 - .next = rsb_seq_next,
850 - .stop = rsb_seq_stop,
851 - .show = rsb_seq_show,
852 +static struct seq_operations format1_seq_ops = {
853 + .start = table_seq_start,
854 + .next = table_seq_next,
855 + .stop = table_seq_stop,
856 + .show = table_seq_show,
857 };
858
859 -static int all_open(struct inode *inode, struct file *file)
860 +static struct seq_operations format2_seq_ops = {
861 + .start = table_seq_start,
862 + .next = table_seq_next,
863 + .stop = table_seq_stop,
864 + .show = table_seq_show,
865 +};
866 +
867 +static struct seq_operations format3_seq_ops = {
868 + .start = table_seq_start,
869 + .next = table_seq_next,
870 + .stop = table_seq_stop,
871 + .show = table_seq_show,
872 +};
873 +
874 +static const struct file_operations format1_fops;
875 +static const struct file_operations format2_fops;
876 +static const struct file_operations format3_fops;
877 +
878 +static int table_open(struct inode *inode, struct file *file)
879 {
880 struct seq_file *seq;
881 - int ret;
882 + int ret = -1;
883 +
884 + if (file->f_op == &format1_fops)
885 + ret = seq_open(file, &format1_seq_ops);
886 + else if (file->f_op == &format2_fops)
887 + ret = seq_open(file, &format2_seq_ops);
888 + else if (file->f_op == &format3_fops)
889 + ret = seq_open(file, &format3_seq_ops);
890
891 - ret = seq_open(file, &all_seq_ops);
892 if (ret)
893 return ret;
894
895 seq = file->private_data;
896 - seq->private = inode->i_private;
897 -
898 + seq->private = inode->i_private; /* the dlm_ls */
899 return 0;
900 }
901
902 -static const struct file_operations all_fops = {
903 +static const struct file_operations format1_fops = {
904 + .owner = THIS_MODULE,
905 + .open = table_open,
906 + .read = seq_read,
907 + .llseek = seq_lseek,
908 + .release = seq_release
909 +};
910 +
911 +static const struct file_operations format2_fops = {
912 + .owner = THIS_MODULE,
913 + .open = table_open,
914 + .read = seq_read,
915 + .llseek = seq_lseek,
916 + .release = seq_release
917 +};
918 +
919 +static const struct file_operations format3_fops = {
920 .owner = THIS_MODULE,
921 - .open = all_open,
922 + .open = table_open,
923 .read = seq_read,
924 .llseek = seq_lseek,
925 .release = seq_release
926 @@ -689,7 +667,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
927 S_IFREG | S_IRUGO,
928 dlm_root,
929 ls,
930 - &rsb_fops);
931 + &format1_fops);
932 if (!ls->ls_debug_rsb_dentry)
933 goto fail;
934
935 @@ -702,7 +680,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
936 S_IFREG | S_IRUGO,
937 dlm_root,
938 ls,
939 - &locks_fops);
940 + &format2_fops);
941 if (!ls->ls_debug_locks_dentry)
942 goto fail;
943
944 @@ -715,7 +693,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
945 S_IFREG | S_IRUGO,
946 dlm_root,
947 ls,
948 - &all_fops);
949 + &format3_fops);
950 if (!ls->ls_debug_all_dentry)
951 goto fail;
952