aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/debug_fs.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2009-01-07 17:48:52 -0500
committerDavid Teigland <teigland@redhat.com>2009-01-08 16:12:31 -0500
commit892c4467e335e9050c95e0d8409c136c4dadaca2 (patch)
treeaa5fda6f6f6db529212980def510edf8810debfc /fs/dlm/debug_fs.c
parent238c6d54830c624f34ac9cf123ac04aebfca5013 (diff)
dlm: fix seq_file usage in debugfs lock dump
The old code would leak iterators and leave reference counts on rsbs because it was ignoring the "stop" seq callback. The code followed an example that used the seq operations differently. This new code is based on actually understanding how the seq operations work. It also improves things by saving the hash bucket in the position to avoid cycling through completed buckets in start. Siged-off-by: Davd Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm/debug_fs.c')
-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