aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/debug_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm/debug_fs.c')
-rw-r--r--fs/dlm/debug_fs.c700
1 files changed, 437 insertions, 263 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 8fc24f4507a3..1d1d27442235 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 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 locks;
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_resource_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_resource_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_resource(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,329 +115,489 @@ static int print_resource(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_resource_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_resource_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_resource_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_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r) 172static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
173 struct dlm_rsb *r)
164{ 174{
165 unsigned int waiting = 0; 175 u64 xid = 0;
166 uint64_t xid = 0; 176 u64 us;
177 int rv;
167 178
168 if (lkb->lkb_flags & DLM_IFL_USER) { 179 if (lkb->lkb_flags & DLM_IFL_USER) {
169 if (lkb->lkb_ua) 180 if (lkb->lkb_ua)
170 xid = lkb->lkb_ua->xid; 181 xid = lkb->lkb_ua->xid;
171 } 182 }
172 183
173 if (lkb->lkb_timestamp) 184 /* microseconds since lkb was added to current queue */
174 waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp); 185 us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
175 186
176 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms 187 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
177 r_nodeid r_len r_name */ 188 r_nodeid r_len r_name */
178 189
179 seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n", 190 rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
180 lkb->lkb_id, 191 lkb->lkb_id,
181 lkb->lkb_nodeid, 192 lkb->lkb_nodeid,
182 lkb->lkb_remid, 193 lkb->lkb_remid,
183 lkb->lkb_ownpid, 194 lkb->lkb_ownpid,
184 (unsigned long long)xid, 195 (unsigned long long)xid,
185 lkb->lkb_exflags, 196 lkb->lkb_exflags,
186 lkb->lkb_flags, 197 lkb->lkb_flags,
187 lkb->lkb_status, 198 lkb->lkb_status,
188 lkb->lkb_grmode, 199 lkb->lkb_grmode,
189 lkb->lkb_rqmode, 200 lkb->lkb_rqmode,
190 waiting, 201 (unsigned long long)us,
191 r->res_nodeid, 202 r->res_nodeid,
192 r->res_length, 203 r->res_length,
193 r->res_name); 204 r->res_name);
205 return rv;
194} 206}
195 207
196static int print_locks(struct dlm_rsb *r, struct seq_file *s) 208static int print_format2(struct dlm_rsb *r, struct seq_file *s)
197{ 209{
198 struct dlm_lkb *lkb; 210 struct dlm_lkb *lkb;
211 int rv = 0;
199 212
200 lock_rsb(r); 213 lock_rsb(r);
201 214
202 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) 215 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
203 print_lock(s, lkb, r); 216 rv = print_format2_lock(s, lkb, r);
204 217 if (rv)
205 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) 218 goto out;
206 print_lock(s, lkb, r); 219 }
207 220
208 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) 221 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
209 print_lock(s, lkb, r); 222 rv = print_format2_lock(s, lkb, r);
223 if (rv)
224 goto out;
225 }
210 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:
211 unlock_rsb(r); 233 unlock_rsb(r);
212 return 0; 234 return rv;
213} 235}
214 236
215static int rsb_iter_next(struct rsb_iter *ri) 237static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
238 int rsb_lookup)
216{ 239{
217 struct dlm_ls *ls = ri->ls; 240 u64 xid = 0;
218 int i; 241 int rv;
219
220 if (!ri->next) {
221 top:
222 /* Find the next non-empty hash bucket */
223 for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
224 read_lock(&ls->ls_rsbtbl[i].lock);
225 if (!list_empty(&ls->ls_rsbtbl[i].list)) {
226 ri->next = ls->ls_rsbtbl[i].list.next;
227 ri->rsb = list_entry(ri->next, struct dlm_rsb,
228 res_hashchain);
229 dlm_hold_rsb(ri->rsb);
230 read_unlock(&ls->ls_rsbtbl[i].lock);
231 break;
232 }
233 read_unlock(&ls->ls_rsbtbl[i].lock);
234 }
235 ri->entry = i;
236
237 if (ri->entry >= ls->ls_rsbtbl_size)
238 return 1;
239 } else {
240 struct dlm_rsb *old = ri->rsb;
241 i = ri->entry;
242 read_lock(&ls->ls_rsbtbl[i].lock);
243 ri->next = ri->next->next;
244 if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
245 /* End of list - move to next bucket */
246 ri->next = NULL;
247 ri->entry++;
248 read_unlock(&ls->ls_rsbtbl[i].lock);
249 dlm_put_rsb(old);
250 goto top;
251 }
252 ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
253 dlm_hold_rsb(ri->rsb);
254 read_unlock(&ls->ls_rsbtbl[i].lock);
255 dlm_put_rsb(old);
256 }
257 242
258 return 0; 243 if (lkb->lkb_flags & DLM_IFL_USER) {
259} 244 if (lkb->lkb_ua)
245 xid = lkb->lkb_ua->xid;
246 }
260 247
261static void rsb_iter_free(struct rsb_iter *ri) 248 rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
262{ 249 lkb->lkb_id,
263 kfree(ri); 250 lkb->lkb_nodeid,
251 lkb->lkb_remid,
252 lkb->lkb_ownpid,
253 (unsigned long long)xid,
254 lkb->lkb_exflags,
255 lkb->lkb_flags,
256 lkb->lkb_status,
257 lkb->lkb_grmode,
258 lkb->lkb_rqmode,
259 lkb->lkb_highbast,
260 rsb_lookup,
261 lkb->lkb_wait_type,
262 lkb->lkb_lvbseq,
263 (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
264 (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
265 return rv;
264} 266}
265 267
266static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls) 268static int print_format3(struct dlm_rsb *r, struct seq_file *s)
267{ 269{
268 struct rsb_iter *ri; 270 struct dlm_lkb *lkb;
271 int i, lvblen = r->res_ls->ls_lvblen;
272 int print_name = 1;
273 int rv;
269 274
270 ri = kzalloc(sizeof *ri, GFP_KERNEL); 275 lock_rsb(r);
271 if (!ri)
272 return NULL;
273 276
274 ri->ls = ls; 277 rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
275 ri->entry = 0; 278 r,
276 ri->next = NULL; 279 r->res_nodeid,
280 r->res_first_lkid,
281 r->res_flags,
282 !list_empty(&r->res_root_list),
283 !list_empty(&r->res_recover_list),
284 r->res_recover_locks_count,
285 r->res_length);
286 if (rv)
287 goto out;
277 288
278 if (rsb_iter_next(ri)) { 289 for (i = 0; i < r->res_length; i++) {
279 rsb_iter_free(ri); 290 if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
280 return NULL; 291 print_name = 0;
281 } 292 }
282 293
283 return ri; 294 seq_printf(s, "%s", print_name ? "str " : "hex");
284}
285 295
286static void *rsb_seq_start(struct seq_file *file, loff_t *pos) 296 for (i = 0; i < r->res_length; i++) {
287{ 297 if (print_name)
288 struct rsb_iter *ri; 298 seq_printf(s, "%c", r->res_name[i]);
289 loff_t n = *pos; 299 else
300 seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
301 }
302 rv = seq_printf(s, "\n");
303 if (rv)
304 goto out;
290 305
291 ri = rsb_iter_init(file->private); 306 if (!r->res_lvbptr)
292 if (!ri) 307 goto do_locks;
293 return NULL;
294 308
295 while (n--) { 309 seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
296 if (rsb_iter_next(ri)) {
297 rsb_iter_free(ri);
298 return NULL;
299 }
300 }
301 310
302 return ri; 311 for (i = 0; i < lvblen; i++)
303} 312 seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
313 rv = seq_printf(s, "\n");
314 if (rv)
315 goto out;
304 316
305static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos) 317 do_locks:
306{ 318 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
307 struct rsb_iter *ri = iter_ptr; 319 rv = print_format3_lock(s, lkb, 0);
320 if (rv)
321 goto out;
322 }
308 323
309 (*pos)++; 324 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
325 rv = print_format3_lock(s, lkb, 0);
326 if (rv)
327 goto out;
328 }
310 329
311 if (rsb_iter_next(ri)) { 330 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
312 rsb_iter_free(ri); 331 rv = print_format3_lock(s, lkb, 0);
313 return NULL; 332 if (rv)
333 goto out;
314 } 334 }
315 335
316 return ri; 336 list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
337 rv = print_format3_lock(s, lkb, 1);
338 if (rv)
339 goto out;
340 }
341 out:
342 unlock_rsb(r);
343 return rv;
317} 344}
318 345
319static void rsb_seq_stop(struct seq_file *file, void *iter_ptr) 346struct rsbtbl_iter {
320{ 347 struct dlm_rsb *rsb;
321 /* nothing for now */ 348 unsigned bucket;
322} 349 int format;
350 int header;
351};
323 352
324static int rsb_seq_show(struct seq_file *file, void *iter_ptr) 353/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
325{ 354 If the buffer is full, seq_printf can be called again, but it
326 struct rsb_iter *ri = iter_ptr; 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. */
327 358
328 if (ri->locks) { 359static int table_seq_show(struct seq_file *seq, void *iter_ptr)
360{
361 struct rsbtbl_iter *ri = iter_ptr;
362 int rv = 0;
363
364 switch (ri->format) {
365 case 1:
366 rv = print_format1(ri->rsb, seq);
367 break;
368 case 2:
329 if (ri->header) { 369 if (ri->header) {
330 seq_printf(file, "id nodeid remid pid xid exflags flags " 370 seq_printf(seq, "id nodeid remid pid xid exflags "
331 "sts grmode rqmode time_ms r_nodeid " 371 "flags sts grmode rqmode time_ms "
332 "r_len r_name\n"); 372 "r_nodeid r_len r_name\n");
333 ri->header = 0; 373 ri->header = 0;
334 } 374 }
335 print_locks(ri->rsb, file); 375 rv = print_format2(ri->rsb, seq);
336 } else { 376 break;
337 print_resource(ri->rsb, file); 377 case 3:
378 if (ri->header) {
379 seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
380 ri->header = 0;
381 }
382 rv = print_format3(ri->rsb, seq);
383 break;
338 } 384 }
339 385
340 return 0; 386 return rv;
341} 387}
342 388
343static struct seq_operations rsb_seq_ops = { 389static struct seq_operations format1_seq_ops;
344 .start = rsb_seq_start, 390static struct seq_operations format2_seq_ops;
345 .next = rsb_seq_next, 391static struct seq_operations format3_seq_ops;
346 .stop = rsb_seq_stop,
347 .show = rsb_seq_show,
348};
349 392
350static int rsb_open(struct inode *inode, struct file *file) 393static void *table_seq_start(struct seq_file *seq, loff_t *pos)
351{ 394{
352 struct seq_file *seq; 395 struct dlm_ls *ls = seq->private;
353 int ret; 396 struct rsbtbl_iter *ri;
354 397 struct dlm_rsb *r;
355 ret = seq_open(file, &rsb_seq_ops); 398 loff_t n = *pos;
356 if (ret) 399 unsigned bucket, entry;
357 return ret;
358
359 seq = file->private_data;
360 seq->private = inode->i_private;
361
362 return 0;
363}
364
365static const struct file_operations rsb_fops = {
366 .owner = THIS_MODULE,
367 .open = rsb_open,
368 .read = seq_read,
369 .llseek = seq_lseek,
370 .release = seq_release
371};
372 400
373/* 401 bucket = n >> 32;
374 * Dump state in compact per-lock listing 402 entry = n & ((1LL << 32) - 1);
375 */
376 403
377static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos) 404 if (bucket >= ls->ls_rsbtbl_size)
378{ 405 return NULL;
379 struct rsb_iter *ri;
380 406
381 ri = kzalloc(sizeof *ri, GFP_KERNEL); 407 ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
382 if (!ri) 408 if (!ri)
383 return NULL; 409 return NULL;
410 if (n == 0)
411 ri->header = 1;
412 if (seq->op == &format1_seq_ops)
413 ri->format = 1;
414 if (seq->op == &format2_seq_ops)
415 ri->format = 2;
416 if (seq->op == &format3_seq_ops)
417 ri->format = 3;
418
419 spin_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 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
428 return ri;
429 }
430 }
431 }
432 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
384 433
385 ri->ls = ls; 434 /*
386 ri->entry = 0; 435 * move to the first rsb in the next non-empty bucket
387 ri->next = NULL; 436 */
388 ri->locks = 1;
389 437
390 if (*pos == 0) 438 /* zero the entry */
391 ri->header = 1; 439 n &= ~((1LL << 32) - 1);
392 440
393 if (rsb_iter_next(ri)) { 441 while (1) {
394 rsb_iter_free(ri); 442 bucket++;
395 return NULL; 443 n += 1LL << 32;
396 } 444
445 if (bucket >= ls->ls_rsbtbl_size) {
446 kfree(ri);
447 return NULL;
448 }
397 449
398 return ri; 450 spin_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 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
458 *pos = n;
459 return ri;
460 }
461 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
462 }
399} 463}
400 464
401static void *locks_seq_start(struct seq_file *file, loff_t *pos) 465static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
402{ 466{
403 struct rsb_iter *ri; 467 struct dlm_ls *ls = seq->private;
468 struct rsbtbl_iter *ri = iter_ptr;
469 struct list_head *next;
470 struct dlm_rsb *r, *rp;
404 loff_t n = *pos; 471 loff_t n = *pos;
472 unsigned bucket;
473
474 bucket = n >> 32;
475
476 /*
477 * move to the next rsb in the same bucket
478 */
479
480 spin_lock(&ls->ls_rsbtbl[bucket].lock);
481 rp = ri->rsb;
482 next = rp->res_hashchain.next;
483
484 if (next != &ls->ls_rsbtbl[bucket].list) {
485 r = list_entry(next, struct dlm_rsb, res_hashchain);
486 dlm_hold_rsb(r);
487 ri->rsb = r;
488 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
489 dlm_put_rsb(rp);
490 ++*pos;
491 return ri;
492 }
493 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
494 dlm_put_rsb(rp);
405 495
406 ri = locks_iter_init(file->private, pos); 496 /*
407 if (!ri) 497 * move to the first rsb in the next non-empty bucket
408 return NULL; 498 */
499
500 /* zero the entry */
501 n &= ~((1LL << 32) - 1);
409 502
410 while (n--) { 503 while (1) {
411 if (rsb_iter_next(ri)) { 504 bucket++;
412 rsb_iter_free(ri); 505 n += 1LL << 32;
506
507 if (bucket >= ls->ls_rsbtbl_size) {
508 kfree(ri);
413 return NULL; 509 return NULL;
414 } 510 }
511
512 spin_lock(&ls->ls_rsbtbl[bucket].lock);
513 if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
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 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
520 *pos = n;
521 return ri;
522 }
523 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
415 } 524 }
525}
526
527static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
528{
529 struct rsbtbl_iter *ri = iter_ptr;
416 530
417 return ri; 531 if (ri) {
532 dlm_put_rsb(ri->rsb);
533 kfree(ri);
534 }
418} 535}
419 536
420static struct seq_operations locks_seq_ops = { 537static struct seq_operations format1_seq_ops = {
421 .start = locks_seq_start, 538 .start = table_seq_start,
422 .next = rsb_seq_next, 539 .next = table_seq_next,
423 .stop = rsb_seq_stop, 540 .stop = table_seq_stop,
424 .show = rsb_seq_show, 541 .show = table_seq_show,
542};
543
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,
425}; 549};
426 550
427static int locks_open(struct inode *inode, struct file *file) 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)
428{ 563{
429 struct seq_file *seq; 564 struct seq_file *seq;
430 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);
431 573
432 ret = seq_open(file, &locks_seq_ops);
433 if (ret) 574 if (ret)
434 return ret; 575 return ret;
435 576
436 seq = file->private_data; 577 seq = file->private_data;
437 seq->private = inode->i_private; 578 seq->private = inode->i_private; /* the dlm_ls */
438
439 return 0; 579 return 0;
440} 580}
441 581
442static const struct file_operations locks_fops = { 582static const struct file_operations format1_fops = {
443 .owner = THIS_MODULE, 583 .owner = THIS_MODULE,
444 .open = locks_open, 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 = {
599 .owner = THIS_MODULE,
600 .open = table_open,
445 .read = seq_read, 601 .read = seq_read,
446 .llseek = seq_lseek, 602 .llseek = seq_lseek,
447 .release = seq_release 603 .release = seq_release
@@ -489,30 +645,33 @@ static const struct file_operations waiters_fops = {
489 .read = waiters_read 645 .read = waiters_read
490}; 646};
491 647
648void dlm_delete_debug_file(struct dlm_ls *ls)
649{
650 if (ls->ls_debug_rsb_dentry)
651 debugfs_remove(ls->ls_debug_rsb_dentry);
652 if (ls->ls_debug_waiters_dentry)
653 debugfs_remove(ls->ls_debug_waiters_dentry);
654 if (ls->ls_debug_locks_dentry)
655 debugfs_remove(ls->ls_debug_locks_dentry);
656 if (ls->ls_debug_all_dentry)
657 debugfs_remove(ls->ls_debug_all_dentry);
658}
659
492int dlm_create_debug_file(struct dlm_ls *ls) 660int dlm_create_debug_file(struct dlm_ls *ls)
493{ 661{
494 char name[DLM_LOCKSPACE_LEN+8]; 662 char name[DLM_LOCKSPACE_LEN+8];
495 663
664 /* format 1 */
665
496 ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name, 666 ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
497 S_IFREG | S_IRUGO, 667 S_IFREG | S_IRUGO,
498 dlm_root, 668 dlm_root,
499 ls, 669 ls,
500 &rsb_fops); 670 &format1_fops);
501 if (!ls->ls_debug_rsb_dentry) 671 if (!ls->ls_debug_rsb_dentry)
502 return -ENOMEM; 672 goto fail;
503 673
504 memset(name, 0, sizeof(name)); 674 /* format 2 */
505 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
506
507 ls->ls_debug_waiters_dentry = debugfs_create_file(name,
508 S_IFREG | S_IRUGO,
509 dlm_root,
510 ls,
511 &waiters_fops);
512 if (!ls->ls_debug_waiters_dentry) {
513 debugfs_remove(ls->ls_debug_rsb_dentry);
514 return -ENOMEM;
515 }
516 675
517 memset(name, 0, sizeof(name)); 676 memset(name, 0, sizeof(name));
518 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name); 677 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
@@ -521,24 +680,39 @@ int dlm_create_debug_file(struct dlm_ls *ls)
521 S_IFREG | S_IRUGO, 680 S_IFREG | S_IRUGO,
522 dlm_root, 681 dlm_root,
523 ls, 682 ls,
524 &locks_fops); 683 &format2_fops);
525 if (!ls->ls_debug_locks_dentry) { 684 if (!ls->ls_debug_locks_dentry)
526 debugfs_remove(ls->ls_debug_waiters_dentry); 685 goto fail;
527 debugfs_remove(ls->ls_debug_rsb_dentry); 686
528 return -ENOMEM; 687 /* format 3 */
529 } 688
689 memset(name, 0, sizeof(name));
690 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name);
691
692 ls->ls_debug_all_dentry = debugfs_create_file(name,
693 S_IFREG | S_IRUGO,
694 dlm_root,
695 ls,
696 &format3_fops);
697 if (!ls->ls_debug_all_dentry)
698 goto fail;
699
700 memset(name, 0, sizeof(name));
701 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
702
703 ls->ls_debug_waiters_dentry = debugfs_create_file(name,
704 S_IFREG | S_IRUGO,
705 dlm_root,
706 ls,
707 &waiters_fops);
708 if (!ls->ls_debug_waiters_dentry)
709 goto fail;
530 710
531 return 0; 711 return 0;
532}
533 712
534void dlm_delete_debug_file(struct dlm_ls *ls) 713 fail:
535{ 714 dlm_delete_debug_file(ls);
536 if (ls->ls_debug_rsb_dentry) 715 return -ENOMEM;
537 debugfs_remove(ls->ls_debug_rsb_dentry);
538 if (ls->ls_debug_waiters_dentry)
539 debugfs_remove(ls->ls_debug_waiters_dentry);
540 if (ls->ls_debug_locks_dentry)
541 debugfs_remove(ls->ls_debug_locks_dentry);
542} 716}
543 717
544int __init dlm_register_debugfs(void) 718int __init dlm_register_debugfs(void)