aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dlm/debug_fs.c696
1 files changed, 337 insertions, 359 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 2f107d1a6a45..bc4af3ef65a3 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -1,7 +1,7 @@
1/****************************************************************************** 1/******************************************************************************
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. 4** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
5** 5**
6** This copyrighted material is made available to anyone wishing to use, 6** This copyrighted material is made available to anyone wishing to use,
7** modify, copy, or redistribute it subject to the terms and conditions 7** modify, copy, or redistribute it subject to the terms and conditions
@@ -25,19 +25,6 @@ static struct mutex debug_buf_lock;
25 25
26static struct dentry *dlm_root; 26static struct dentry *dlm_root;
27 27
28struct rsb_iter {
29 int entry;
30 int format;
31 int header;
32 struct dlm_ls *ls;
33 struct list_head *next;
34 struct dlm_rsb *rsb;
35};
36
37/*
38 * dump all rsb's in the lockspace hash table
39 */
40
41static char *print_lockmode(int mode) 28static char *print_lockmode(int mode)
42{ 29{
43 switch (mode) { 30 switch (mode) {
@@ -60,13 +47,13 @@ static char *print_lockmode(int mode)
60 } 47 }
61} 48}
62 49
63static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb, 50static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
64 struct dlm_rsb *res) 51 struct dlm_rsb *res)
65{ 52{
66 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode)); 53 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
67 54
68 if (lkb->lkb_status == DLM_LKSTS_CONVERT 55 if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
69 || lkb->lkb_status == DLM_LKSTS_WAITING) 56 lkb->lkb_status == DLM_LKSTS_WAITING)
70 seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode)); 57 seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
71 58
72 if (lkb->lkb_nodeid) { 59 if (lkb->lkb_nodeid) {
@@ -80,33 +67,42 @@ static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
80 if (lkb->lkb_wait_type) 67 if (lkb->lkb_wait_type)
81 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type); 68 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
82 69
83 seq_printf(s, "\n"); 70 return seq_printf(s, "\n");
84} 71}
85 72
86static int print_format1(struct dlm_rsb *res, struct seq_file *s) 73static int print_format1(struct dlm_rsb *res, struct seq_file *s)
87{ 74{
88 struct dlm_lkb *lkb; 75 struct dlm_lkb *lkb;
89 int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; 76 int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
77 int rv;
90 78
91 lock_rsb(res); 79 lock_rsb(res);
92 80
93 seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); 81 rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
82 res, res->res_length);
83 if (rv)
84 goto out;
85
94 for (i = 0; i < res->res_length; i++) { 86 for (i = 0; i < res->res_length; i++) {
95 if (isprint(res->res_name[i])) 87 if (isprint(res->res_name[i]))
96 seq_printf(s, "%c", res->res_name[i]); 88 seq_printf(s, "%c", res->res_name[i]);
97 else 89 else
98 seq_printf(s, "%c", '.'); 90 seq_printf(s, "%c", '.');
99 } 91 }
92
100 if (res->res_nodeid > 0) 93 if (res->res_nodeid > 0)
101 seq_printf(s, "\" \nLocal Copy, Master is node %d\n", 94 rv = seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
102 res->res_nodeid); 95 res->res_nodeid);
103 else if (res->res_nodeid == 0) 96 else if (res->res_nodeid == 0)
104 seq_printf(s, "\" \nMaster Copy\n"); 97 rv = seq_printf(s, "\" \nMaster Copy\n");
105 else if (res->res_nodeid == -1) 98 else if (res->res_nodeid == -1)
106 seq_printf(s, "\" \nLooking up master (lkid %x)\n", 99 rv = seq_printf(s, "\" \nLooking up master (lkid %x)\n",
107 res->res_first_lkid); 100 res->res_first_lkid);
108 else 101 else
109 seq_printf(s, "\" \nInvalid master %d\n", res->res_nodeid); 102 rv = seq_printf(s, "\" \nInvalid master %d\n",
103 res->res_nodeid);
104 if (rv)
105 goto out;
110 106
111 /* Print the LVB: */ 107 /* Print the LVB: */
112 if (res->res_lvbptr) { 108 if (res->res_lvbptr) {
@@ -119,52 +115,66 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
119 } 115 }
120 if (rsb_flag(res, RSB_VALNOTVALID)) 116 if (rsb_flag(res, RSB_VALNOTVALID))
121 seq_printf(s, " (INVALID)"); 117 seq_printf(s, " (INVALID)");
122 seq_printf(s, "\n"); 118 rv = seq_printf(s, "\n");
119 if (rv)
120 goto out;
123 } 121 }
124 122
125 root_list = !list_empty(&res->res_root_list); 123 root_list = !list_empty(&res->res_root_list);
126 recover_list = !list_empty(&res->res_recover_list); 124 recover_list = !list_empty(&res->res_recover_list);
127 125
128 if (root_list || recover_list) { 126 if (root_list || recover_list) {
129 seq_printf(s, "Recovery: root %d recover %d flags %lx " 127 rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
130 "count %d\n", root_list, recover_list, 128 "count %d\n", root_list, recover_list,
131 res->res_flags, res->res_recover_locks_count); 129 res->res_flags, res->res_recover_locks_count);
130 if (rv)
131 goto out;
132 } 132 }
133 133
134 /* Print the locks attached to this resource */ 134 /* Print the locks attached to this resource */
135 seq_printf(s, "Granted Queue\n"); 135 seq_printf(s, "Granted Queue\n");
136 list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) 136 list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
137 print_format1_lock(s, lkb, res); 137 rv = print_format1_lock(s, lkb, res);
138 if (rv)
139 goto out;
140 }
138 141
139 seq_printf(s, "Conversion Queue\n"); 142 seq_printf(s, "Conversion Queue\n");
140 list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) 143 list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
141 print_format1_lock(s, lkb, res); 144 rv = print_format1_lock(s, lkb, res);
145 if (rv)
146 goto out;
147 }
142 148
143 seq_printf(s, "Waiting Queue\n"); 149 seq_printf(s, "Waiting Queue\n");
144 list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) 150 list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
145 print_format1_lock(s, lkb, res); 151 rv = print_format1_lock(s, lkb, res);
152 if (rv)
153 goto out;
154 }
146 155
147 if (list_empty(&res->res_lookup)) 156 if (list_empty(&res->res_lookup))
148 goto out; 157 goto out;
149 158
150 seq_printf(s, "Lookup Queue\n"); 159 seq_printf(s, "Lookup Queue\n");
151 list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) { 160 list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
152 seq_printf(s, "%08x %s", lkb->lkb_id, 161 rv = seq_printf(s, "%08x %s", lkb->lkb_id,
153 print_lockmode(lkb->lkb_rqmode)); 162 print_lockmode(lkb->lkb_rqmode));
154 if (lkb->lkb_wait_type) 163 if (lkb->lkb_wait_type)
155 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type); 164 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
156 seq_printf(s, "\n"); 165 rv = seq_printf(s, "\n");
157 } 166 }
158 out: 167 out:
159 unlock_rsb(res); 168 unlock_rsb(res);
160 return 0; 169 return rv;
161} 170}
162 171
163static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb, 172static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
164 struct dlm_rsb *r) 173 struct dlm_rsb *r)
165{ 174{
166 u64 xid = 0; 175 u64 xid = 0;
167 u64 us; 176 u64 us;
177 int rv;
168 178
169 if (lkb->lkb_flags & DLM_IFL_USER) { 179 if (lkb->lkb_flags & DLM_IFL_USER) {
170 if (lkb->lkb_ua) 180 if (lkb->lkb_ua)
@@ -177,69 +187,82 @@ static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
177 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us 187 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
178 r_nodeid r_len r_name */ 188 r_nodeid r_len r_name */
179 189
180 seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n", 190 rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
181 lkb->lkb_id, 191 lkb->lkb_id,
182 lkb->lkb_nodeid, 192 lkb->lkb_nodeid,
183 lkb->lkb_remid, 193 lkb->lkb_remid,
184 lkb->lkb_ownpid, 194 lkb->lkb_ownpid,
185 (unsigned long long)xid, 195 (unsigned long long)xid,
186 lkb->lkb_exflags, 196 lkb->lkb_exflags,
187 lkb->lkb_flags, 197 lkb->lkb_flags,
188 lkb->lkb_status, 198 lkb->lkb_status,
189 lkb->lkb_grmode, 199 lkb->lkb_grmode,
190 lkb->lkb_rqmode, 200 lkb->lkb_rqmode,
191 (unsigned long long)us, 201 (unsigned long long)us,
192 r->res_nodeid, 202 r->res_nodeid,
193 r->res_length, 203 r->res_length,
194 r->res_name); 204 r->res_name);
205 return rv;
195} 206}
196 207
197static int print_format2(struct dlm_rsb *r, struct seq_file *s) 208static int print_format2(struct dlm_rsb *r, struct seq_file *s)
198{ 209{
199 struct dlm_lkb *lkb; 210 struct dlm_lkb *lkb;
211 int rv = 0;
200 212
201 lock_rsb(r); 213 lock_rsb(r);
202 214
203 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) 215 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
204 print_format2_lock(s, lkb, r); 216 rv = print_format2_lock(s, lkb, r);
205 217 if (rv)
206 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) 218 goto out;
207 print_format2_lock(s, lkb, r); 219 }
208 220
209 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) 221 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
210 print_format2_lock(s, lkb, r); 222 rv = print_format2_lock(s, lkb, r);
223 if (rv)
224 goto out;
225 }
211 226
227 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
228 rv = print_format2_lock(s, lkb, r);
229 if (rv)
230 goto out;
231 }
232 out:
212 unlock_rsb(r); 233 unlock_rsb(r);
213 return 0; 234 return rv;
214} 235}
215 236
216static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb, 237static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
217 int rsb_lookup) 238 int rsb_lookup)
218{ 239{
219 u64 xid = 0; 240 u64 xid = 0;
241 int rv;
220 242
221 if (lkb->lkb_flags & DLM_IFL_USER) { 243 if (lkb->lkb_flags & DLM_IFL_USER) {
222 if (lkb->lkb_ua) 244 if (lkb->lkb_ua)
223 xid = lkb->lkb_ua->xid; 245 xid = lkb->lkb_ua->xid;
224 } 246 }
225 247
226 seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n", 248 rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
227 lkb->lkb_id, 249 lkb->lkb_id,
228 lkb->lkb_nodeid, 250 lkb->lkb_nodeid,
229 lkb->lkb_remid, 251 lkb->lkb_remid,
230 lkb->lkb_ownpid, 252 lkb->lkb_ownpid,
231 (unsigned long long)xid, 253 (unsigned long long)xid,
232 lkb->lkb_exflags, 254 lkb->lkb_exflags,
233 lkb->lkb_flags, 255 lkb->lkb_flags,
234 lkb->lkb_status, 256 lkb->lkb_status,
235 lkb->lkb_grmode, 257 lkb->lkb_grmode,
236 lkb->lkb_rqmode, 258 lkb->lkb_rqmode,
237 lkb->lkb_highbast, 259 lkb->lkb_highbast,
238 rsb_lookup, 260 rsb_lookup,
239 lkb->lkb_wait_type, 261 lkb->lkb_wait_type,
240 lkb->lkb_lvbseq, 262 lkb->lkb_lvbseq,
241 (unsigned long long)ktime_to_ns(lkb->lkb_timestamp), 263 (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
242 (unsigned long long)ktime_to_ns(lkb->lkb_time_bast)); 264 (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
265 return rv;
243} 266}
244 267
245static int print_format3(struct dlm_rsb *r, struct seq_file *s) 268static 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)
247 struct dlm_lkb *lkb; 270 struct dlm_lkb *lkb;
248 int i, lvblen = r->res_ls->ls_lvblen; 271 int i, lvblen = r->res_ls->ls_lvblen;
249 int print_name = 1; 272 int print_name = 1;
273 int rv;
250 274
251 lock_rsb(r); 275 lock_rsb(r);
252 276
253 seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ", 277 rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
254 r, 278 r,
255 r->res_nodeid, 279 r->res_nodeid,
256 r->res_first_lkid, 280 r->res_first_lkid,
257 r->res_flags, 281 r->res_flags,
258 !list_empty(&r->res_root_list), 282 !list_empty(&r->res_root_list),
259 !list_empty(&r->res_recover_list), 283 !list_empty(&r->res_recover_list),
260 r->res_recover_locks_count, 284 r->res_recover_locks_count,
261 r->res_length); 285 r->res_length);
286 if (rv)
287 goto out;
262 288
263 for (i = 0; i < r->res_length; i++) { 289 for (i = 0; i < r->res_length; i++) {
264 if (!isascii(r->res_name[i]) || !isprint(r->res_name[i])) 290 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)
273 else 299 else
274 seq_printf(s, " %02x", (unsigned char)r->res_name[i]); 300 seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
275 } 301 }
276 seq_printf(s, "\n"); 302 rv = seq_printf(s, "\n");
303 if (rv)
304 goto out;
277 305
278 if (!r->res_lvbptr) 306 if (!r->res_lvbptr)
279 goto do_locks; 307 goto do_locks;
@@ -282,344 +310,294 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
282 310
283 for (i = 0; i < lvblen; i++) 311 for (i = 0; i < lvblen; i++)
284 seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]); 312 seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
285 seq_printf(s, "\n"); 313 rv = seq_printf(s, "\n");
314 if (rv)
315 goto out;
286 316
287 do_locks: 317 do_locks:
288 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) 318 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
289 print_format3_lock(s, lkb, 0); 319 rv = print_format3_lock(s, lkb, 0);
290 320 if (rv)
291 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) 321 goto out;
292 print_format3_lock(s, lkb, 0);
293
294 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
295 print_format3_lock(s, lkb, 0);
296
297 list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
298 print_format3_lock(s, lkb, 1);
299
300 unlock_rsb(r);
301 return 0;
302}
303
304static int rsb_iter_next(struct rsb_iter *ri)
305{
306 struct dlm_ls *ls = ri->ls;
307 int i;
308
309 if (!ri->next) {
310 top:
311 /* Find the next non-empty hash bucket */
312 for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
313 read_lock(&ls->ls_rsbtbl[i].lock);
314 if (!list_empty(&ls->ls_rsbtbl[i].list)) {
315 ri->next = ls->ls_rsbtbl[i].list.next;
316 ri->rsb = list_entry(ri->next, struct dlm_rsb,
317 res_hashchain);
318 dlm_hold_rsb(ri->rsb);
319 read_unlock(&ls->ls_rsbtbl[i].lock);
320 break;
321 }
322 read_unlock(&ls->ls_rsbtbl[i].lock);
323 }
324 ri->entry = i;
325
326 if (ri->entry >= ls->ls_rsbtbl_size)
327 return 1;
328 } else {
329 struct dlm_rsb *old = ri->rsb;
330 i = ri->entry;
331 read_lock(&ls->ls_rsbtbl[i].lock);
332 ri->next = ri->next->next;
333 if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
334 /* End of list - move to next bucket */
335 ri->next = NULL;
336 ri->entry++;
337 read_unlock(&ls->ls_rsbtbl[i].lock);
338 dlm_put_rsb(old);
339 goto top;
340 }
341 ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
342 dlm_hold_rsb(ri->rsb);
343 read_unlock(&ls->ls_rsbtbl[i].lock);
344 dlm_put_rsb(old);
345 } 322 }
346 323
347 return 0; 324 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
348} 325 rv = print_format3_lock(s, lkb, 0);
349 326 if (rv)
350static void rsb_iter_free(struct rsb_iter *ri) 327 goto out;
351{
352 kfree(ri);
353}
354
355static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
356{
357 struct rsb_iter *ri;
358
359 ri = kzalloc(sizeof *ri, GFP_KERNEL);
360 if (!ri)
361 return NULL;
362
363 ri->ls = ls;
364 ri->entry = 0;
365 ri->next = NULL;
366 ri->format = 1;
367
368 if (rsb_iter_next(ri)) {
369 rsb_iter_free(ri);
370 return NULL;
371 } 328 }
372 329
373 return ri; 330 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
374} 331 rv = print_format3_lock(s, lkb, 0);
375 332 if (rv)
376static void *rsb_seq_start(struct seq_file *file, loff_t *pos) 333 goto out;
377{
378 struct rsb_iter *ri;
379 loff_t n = *pos;
380
381 ri = rsb_iter_init(file->private);
382 if (!ri)
383 return NULL;
384
385 while (n--) {
386 if (rsb_iter_next(ri)) {
387 rsb_iter_free(ri);
388 return NULL;
389 }
390 } 334 }
391 335
392 return ri; 336 list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
393} 337 rv = print_format3_lock(s, lkb, 1);
394 338 if (rv)
395static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos) 339 goto out;
396{
397 struct rsb_iter *ri = iter_ptr;
398
399 (*pos)++;
400
401 if (rsb_iter_next(ri)) {
402 rsb_iter_free(ri);
403 return NULL;
404 } 340 }
405 341 out:
406 return ri; 342 unlock_rsb(r);
343 return rv;
407} 344}
408 345
409static void rsb_seq_stop(struct seq_file *file, void *iter_ptr) 346struct rsbtbl_iter {
410{ 347 struct dlm_rsb *rsb;
411 /* nothing for now */ 348 unsigned bucket;
412} 349 int format;
350 int header;
351};
413 352
414static int rsb_seq_show(struct seq_file *file, void *iter_ptr) 353/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
354 If the buffer is full, seq_printf can be called again, but it
355 does nothing and just returns -1. So, the these printing routines
356 periodically check the return value to avoid wasting too much time
357 trying to print to a full buffer. */
358
359static int table_seq_show(struct seq_file *seq, void *iter_ptr)
415{ 360{
416 struct rsb_iter *ri = iter_ptr; 361 struct rsbtbl_iter *ri = iter_ptr;
362 int rv = 0;
417 363
418 switch (ri->format) { 364 switch (ri->format) {
419 case 1: 365 case 1:
420 print_format1(ri->rsb, file); 366 rv = print_format1(ri->rsb, seq);
421 break; 367 break;
422 case 2: 368 case 2:
423 if (ri->header) { 369 if (ri->header) {
424 seq_printf(file, "id nodeid remid pid xid exflags " 370 seq_printf(seq, "id nodeid remid pid xid exflags "
425 "flags sts grmode rqmode time_ms " 371 "flags sts grmode rqmode time_ms "
426 "r_nodeid r_len r_name\n"); 372 "r_nodeid r_len r_name\n");
427 ri->header = 0; 373 ri->header = 0;
428 } 374 }
429 print_format2(ri->rsb, file); 375 rv = print_format2(ri->rsb, seq);
430 break; 376 break;
431 case 3: 377 case 3:
432 if (ri->header) { 378 if (ri->header) {
433 seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n"); 379 seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
434 ri->header = 0; 380 ri->header = 0;
435 } 381 }
436 print_format3(ri->rsb, file); 382 rv = print_format3(ri->rsb, seq);
437 break; 383 break;
438 } 384 }
439 385
440 return 0; 386 return rv;
441} 387}
442 388
443static struct seq_operations rsb_seq_ops = { 389static struct seq_operations format1_seq_ops;
444 .start = rsb_seq_start, 390static struct seq_operations format2_seq_ops;
445 .next = rsb_seq_next, 391static struct seq_operations format3_seq_ops;
446 .stop = rsb_seq_stop,
447 .show = rsb_seq_show,
448};
449 392
450static int rsb_open(struct inode *inode, struct file *file) 393static void *table_seq_start(struct seq_file *seq, loff_t *pos)
451{ 394{
452 struct seq_file *seq; 395 struct dlm_ls *ls = seq->private;
453 int ret; 396 struct rsbtbl_iter *ri;
454 397 struct dlm_rsb *r;
455 ret = seq_open(file, &rsb_seq_ops); 398 loff_t n = *pos;
456 if (ret) 399 unsigned bucket, entry;
457 return ret;
458
459 seq = file->private_data;
460 seq->private = inode->i_private;
461
462 return 0;
463}
464
465static const struct file_operations rsb_fops = {
466 .owner = THIS_MODULE,
467 .open = rsb_open,
468 .read = seq_read,
469 .llseek = seq_lseek,
470 .release = seq_release
471};
472 400
473/* 401 bucket = n >> 32;
474 * Dump state in compact per-lock listing 402 entry = n & ((1LL << 32) - 1);
475 */
476 403
477static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos) 404 if (bucket >= ls->ls_rsbtbl_size)
478{ 405 return NULL;
479 struct rsb_iter *ri;
480 406
481 ri = kzalloc(sizeof *ri, GFP_KERNEL); 407 ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
482 if (!ri) 408 if (!ri)
483 return NULL; 409 return NULL;
484 410 if (n == 0)
485 ri->ls = ls;
486 ri->entry = 0;
487 ri->next = NULL;
488 ri->format = 2;
489
490 if (*pos == 0)
491 ri->header = 1; 411 ri->header = 1;
492 412 if (seq->op == &format1_seq_ops)
493 if (rsb_iter_next(ri)) { 413 ri->format = 1;
494 rsb_iter_free(ri); 414 if (seq->op == &format2_seq_ops)
495 return NULL; 415 ri->format = 2;
416 if (seq->op == &format3_seq_ops)
417 ri->format = 3;
418
419 read_lock(&ls->ls_rsbtbl[bucket].lock);
420 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
421 list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list,
422 res_hashchain) {
423 if (!entry--) {
424 dlm_hold_rsb(r);
425 ri->rsb = r;
426 ri->bucket = bucket;
427 read_unlock(&ls->ls_rsbtbl[bucket].lock);
428 return ri;
429 }
430 }
496 } 431 }
432 read_unlock(&ls->ls_rsbtbl[bucket].lock);
497 433
498 return ri; 434 /*
499} 435 * move to the first rsb in the next non-empty bucket
436 */
500 437
501static void *locks_seq_start(struct seq_file *file, loff_t *pos) 438 /* zero the entry */
502{ 439 n &= ~((1LL << 32) - 1);
503 struct rsb_iter *ri;
504 loff_t n = *pos;
505 440
506 ri = locks_iter_init(file->private, pos); 441 while (1) {
507 if (!ri) 442 bucket++;
508 return NULL; 443 n += 1LL << 32;
509 444
510 while (n--) { 445 if (bucket >= ls->ls_rsbtbl_size) {
511 if (rsb_iter_next(ri)) { 446 kfree(ri);
512 rsb_iter_free(ri);
513 return NULL; 447 return NULL;
514 } 448 }
515 }
516 449
517 return ri; 450 read_lock(&ls->ls_rsbtbl[bucket].lock);
451 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
452 r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
453 struct dlm_rsb, res_hashchain);
454 dlm_hold_rsb(r);
455 ri->rsb = r;
456 ri->bucket = bucket;
457 read_unlock(&ls->ls_rsbtbl[bucket].lock);
458 *pos = n;
459 return ri;
460 }
461 read_unlock(&ls->ls_rsbtbl[bucket].lock);
462 }
518} 463}
519 464
520static struct seq_operations locks_seq_ops = { 465static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
521 .start = locks_seq_start,
522 .next = rsb_seq_next,
523 .stop = rsb_seq_stop,
524 .show = rsb_seq_show,
525};
526
527static int locks_open(struct inode *inode, struct file *file)
528{ 466{
529 struct seq_file *seq; 467 struct dlm_ls *ls = seq->private;
530 int ret; 468 struct rsbtbl_iter *ri = iter_ptr;
531 469 struct list_head *next;
532 ret = seq_open(file, &locks_seq_ops); 470 struct dlm_rsb *r, *rp;
533 if (ret) 471 loff_t n = *pos;
534 return ret; 472 unsigned bucket;
535 473
536 seq = file->private_data; 474 bucket = n >> 32;
537 seq->private = inode->i_private; 475
538 476 /*
539 return 0; 477 * move to the next rsb in the same bucket
540} 478 */
541 479
542static const struct file_operations locks_fops = { 480 read_lock(&ls->ls_rsbtbl[bucket].lock);
543 .owner = THIS_MODULE, 481 rp = ri->rsb;
544 .open = locks_open, 482 next = rp->res_hashchain.next;
545 .read = seq_read, 483
546 .llseek = seq_lseek, 484 if (next != &ls->ls_rsbtbl[bucket].list) {
547 .release = seq_release 485 r = list_entry(next, struct dlm_rsb, res_hashchain);
548}; 486 dlm_hold_rsb(r);
549 487 ri->rsb = r;
550/* 488 read_unlock(&ls->ls_rsbtbl[bucket].lock);
551 * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks 489 dlm_put_rsb(rp);
552 * This can replace both formats 1 and 2 eventually. 490 ++*pos;
553 */ 491 return ri;
492 }
493 read_unlock(&ls->ls_rsbtbl[bucket].lock);
494 dlm_put_rsb(rp);
554 495
555static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos) 496 /*
556{ 497 * move to the first rsb in the next non-empty bucket
557 struct rsb_iter *ri; 498 */
558 499
559 ri = kzalloc(sizeof *ri, GFP_KERNEL); 500 /* zero the entry */
560 if (!ri) 501 n &= ~((1LL << 32) - 1);
561 return NULL;
562 502
563 ri->ls = ls; 503 while (1) {
564 ri->entry = 0; 504 bucket++;
565 ri->next = NULL; 505 n += 1LL << 32;
566 ri->format = 3;
567 506
568 if (*pos == 0) 507 if (bucket >= ls->ls_rsbtbl_size) {
569 ri->header = 1; 508 kfree(ri);
509 return NULL;
510 }
570 511
571 if (rsb_iter_next(ri)) { 512 read_lock(&ls->ls_rsbtbl[bucket].lock);
572 rsb_iter_free(ri); 513 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
573 return NULL; 514 r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
515 struct dlm_rsb, res_hashchain);
516 dlm_hold_rsb(r);
517 ri->rsb = r;
518 ri->bucket = bucket;
519 read_unlock(&ls->ls_rsbtbl[bucket].lock);
520 *pos = n;
521 return ri;
522 }
523 read_unlock(&ls->ls_rsbtbl[bucket].lock);
574 } 524 }
575
576 return ri;
577} 525}
578 526
579static void *all_seq_start(struct seq_file *file, loff_t *pos) 527static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
580{ 528{
581 struct rsb_iter *ri; 529 struct rsbtbl_iter *ri = iter_ptr;
582 loff_t n = *pos;
583
584 ri = all_iter_init(file->private, pos);
585 if (!ri)
586 return NULL;
587 530
588 while (n--) { 531 if (ri) {
589 if (rsb_iter_next(ri)) { 532 dlm_put_rsb(ri->rsb);
590 rsb_iter_free(ri); 533 kfree(ri);
591 return NULL;
592 }
593 } 534 }
594
595 return ri;
596} 535}
597 536
598static struct seq_operations all_seq_ops = { 537static struct seq_operations format1_seq_ops = {
599 .start = all_seq_start, 538 .start = table_seq_start,
600 .next = rsb_seq_next, 539 .next = table_seq_next,
601 .stop = rsb_seq_stop, 540 .stop = table_seq_stop,
602 .show = rsb_seq_show, 541 .show = table_seq_show,
603}; 542};
604 543
605static int all_open(struct inode *inode, struct file *file) 544static struct seq_operations format2_seq_ops = {
545 .start = table_seq_start,
546 .next = table_seq_next,
547 .stop = table_seq_stop,
548 .show = table_seq_show,
549};
550
551static struct seq_operations format3_seq_ops = {
552 .start = table_seq_start,
553 .next = table_seq_next,
554 .stop = table_seq_stop,
555 .show = table_seq_show,
556};
557
558static const struct file_operations format1_fops;
559static const struct file_operations format2_fops;
560static const struct file_operations format3_fops;
561
562static int table_open(struct inode *inode, struct file *file)
606{ 563{
607 struct seq_file *seq; 564 struct seq_file *seq;
608 int ret; 565 int ret = -1;
566
567 if (file->f_op == &format1_fops)
568 ret = seq_open(file, &format1_seq_ops);
569 else if (file->f_op == &format2_fops)
570 ret = seq_open(file, &format2_seq_ops);
571 else if (file->f_op == &format3_fops)
572 ret = seq_open(file, &format3_seq_ops);
609 573
610 ret = seq_open(file, &all_seq_ops);
611 if (ret) 574 if (ret)
612 return ret; 575 return ret;
613 576
614 seq = file->private_data; 577 seq = file->private_data;
615 seq->private = inode->i_private; 578 seq->private = inode->i_private; /* the dlm_ls */
616
617 return 0; 579 return 0;
618} 580}
619 581
620static const struct file_operations all_fops = { 582static const struct file_operations format1_fops = {
583 .owner = THIS_MODULE,
584 .open = table_open,
585 .read = seq_read,
586 .llseek = seq_lseek,
587 .release = seq_release
588};
589
590static const struct file_operations format2_fops = {
591 .owner = THIS_MODULE,
592 .open = table_open,
593 .read = seq_read,
594 .llseek = seq_lseek,
595 .release = seq_release
596};
597
598static const struct file_operations format3_fops = {
621 .owner = THIS_MODULE, 599 .owner = THIS_MODULE,
622 .open = all_open, 600 .open = table_open,
623 .read = seq_read, 601 .read = seq_read,
624 .llseek = seq_lseek, 602 .llseek = seq_lseek,
625 .release = seq_release 603 .release = seq_release
@@ -689,7 +667,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
689 S_IFREG | S_IRUGO, 667 S_IFREG | S_IRUGO,
690 dlm_root, 668 dlm_root,
691 ls, 669 ls,
692 &rsb_fops); 670 &format1_fops);
693 if (!ls->ls_debug_rsb_dentry) 671 if (!ls->ls_debug_rsb_dentry)
694 goto fail; 672 goto fail;
695 673
@@ -702,7 +680,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
702 S_IFREG | S_IRUGO, 680 S_IFREG | S_IRUGO,
703 dlm_root, 681 dlm_root,
704 ls, 682 ls,
705 &locks_fops); 683 &format2_fops);
706 if (!ls->ls_debug_locks_dentry) 684 if (!ls->ls_debug_locks_dentry)
707 goto fail; 685 goto fail;
708 686
@@ -715,7 +693,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
715 S_IFREG | S_IRUGO, 693 S_IFREG | S_IRUGO,
716 dlm_root, 694 dlm_root,
717 ls, 695 ls,
718 &all_fops); 696 &format3_fops);
719 if (!ls->ls_debug_all_dentry) 697 if (!ls->ls_debug_all_dentry)
720 goto fail; 698 goto fail;
721 699