[AFS]: Clean up the AFS sources
[safe/jmp/linux-2.6] / fs / afs / proc.c
1 /* /proc interface for AFS
2  *
3  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11
12 #include <linux/slab.h>
13 #include <linux/module.h>
14 #include <linux/proc_fs.h>
15 #include <linux/seq_file.h>
16 #include "cell.h"
17 #include "volume.h"
18 #include <asm/uaccess.h>
19 #include "internal.h"
20
21 static struct proc_dir_entry *proc_afs;
22
23
24 static int afs_proc_cells_open(struct inode *inode, struct file *file);
25 static void *afs_proc_cells_start(struct seq_file *p, loff_t *pos);
26 static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos);
27 static void afs_proc_cells_stop(struct seq_file *p, void *v);
28 static int afs_proc_cells_show(struct seq_file *m, void *v);
29 static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
30                                     size_t size, loff_t *_pos);
31
32 static struct seq_operations afs_proc_cells_ops = {
33         .start  = afs_proc_cells_start,
34         .next   = afs_proc_cells_next,
35         .stop   = afs_proc_cells_stop,
36         .show   = afs_proc_cells_show,
37 };
38
39 static const struct file_operations afs_proc_cells_fops = {
40         .open           = afs_proc_cells_open,
41         .read           = seq_read,
42         .write          = afs_proc_cells_write,
43         .llseek         = seq_lseek,
44         .release        = seq_release,
45 };
46
47 static int afs_proc_rootcell_open(struct inode *inode, struct file *file);
48 static int afs_proc_rootcell_release(struct inode *inode, struct file *file);
49 static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
50                                       size_t size, loff_t *_pos);
51 static ssize_t afs_proc_rootcell_write(struct file *file,
52                                        const char __user *buf,
53                                        size_t size, loff_t *_pos);
54
55 static const struct file_operations afs_proc_rootcell_fops = {
56         .open           = afs_proc_rootcell_open,
57         .read           = afs_proc_rootcell_read,
58         .write          = afs_proc_rootcell_write,
59         .llseek         = no_llseek,
60         .release        = afs_proc_rootcell_release
61 };
62
63 static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
64 static int afs_proc_cell_volumes_release(struct inode *inode,
65                                          struct file *file);
66 static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
67 static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
68                                         loff_t *pos);
69 static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v);
70 static int afs_proc_cell_volumes_show(struct seq_file *m, void *v);
71
72 static struct seq_operations afs_proc_cell_volumes_ops = {
73         .start  = afs_proc_cell_volumes_start,
74         .next   = afs_proc_cell_volumes_next,
75         .stop   = afs_proc_cell_volumes_stop,
76         .show   = afs_proc_cell_volumes_show,
77 };
78
79 static const struct file_operations afs_proc_cell_volumes_fops = {
80         .open           = afs_proc_cell_volumes_open,
81         .read           = seq_read,
82         .llseek         = seq_lseek,
83         .release        = afs_proc_cell_volumes_release,
84 };
85
86 static int afs_proc_cell_vlservers_open(struct inode *inode,
87                                         struct file *file);
88 static int afs_proc_cell_vlservers_release(struct inode *inode,
89                                            struct file *file);
90 static void *afs_proc_cell_vlservers_start(struct seq_file *p, loff_t *pos);
91 static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
92                                           loff_t *pos);
93 static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v);
94 static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v);
95
96 static struct seq_operations afs_proc_cell_vlservers_ops = {
97         .start  = afs_proc_cell_vlservers_start,
98         .next   = afs_proc_cell_vlservers_next,
99         .stop   = afs_proc_cell_vlservers_stop,
100         .show   = afs_proc_cell_vlservers_show,
101 };
102
103 static const struct file_operations afs_proc_cell_vlservers_fops = {
104         .open           = afs_proc_cell_vlservers_open,
105         .read           = seq_read,
106         .llseek         = seq_lseek,
107         .release        = afs_proc_cell_vlservers_release,
108 };
109
110 static int afs_proc_cell_servers_open(struct inode *inode, struct file *file);
111 static int afs_proc_cell_servers_release(struct inode *inode,
112                                          struct file *file);
113 static void *afs_proc_cell_servers_start(struct seq_file *p, loff_t *pos);
114 static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
115                                         loff_t *pos);
116 static void afs_proc_cell_servers_stop(struct seq_file *p, void *v);
117 static int afs_proc_cell_servers_show(struct seq_file *m, void *v);
118
119 static struct seq_operations afs_proc_cell_servers_ops = {
120         .start  = afs_proc_cell_servers_start,
121         .next   = afs_proc_cell_servers_next,
122         .stop   = afs_proc_cell_servers_stop,
123         .show   = afs_proc_cell_servers_show,
124 };
125
126 static const struct file_operations afs_proc_cell_servers_fops = {
127         .open           = afs_proc_cell_servers_open,
128         .read           = seq_read,
129         .llseek         = seq_lseek,
130         .release        = afs_proc_cell_servers_release,
131 };
132
133 /*
134  * initialise the /proc/fs/afs/ directory
135  */
136 int afs_proc_init(void)
137 {
138         struct proc_dir_entry *p;
139
140         _enter("");
141
142         proc_afs = proc_mkdir("fs/afs", NULL);
143         if (!proc_afs)
144                 goto error_dir;
145         proc_afs->owner = THIS_MODULE;
146
147         p = create_proc_entry("cells", 0, proc_afs);
148         if (!p)
149                 goto error_cells;
150         p->proc_fops = &afs_proc_cells_fops;
151         p->owner = THIS_MODULE;
152
153         p = create_proc_entry("rootcell", 0, proc_afs);
154         if (!p)
155                 goto error_rootcell;
156         p->proc_fops = &afs_proc_rootcell_fops;
157         p->owner = THIS_MODULE;
158
159         _leave(" = 0");
160         return 0;
161
162 error_rootcell:
163         remove_proc_entry("cells", proc_afs);
164 error_cells:
165         remove_proc_entry("fs/afs", NULL);
166 error_dir:
167         _leave(" = -ENOMEM");
168         return -ENOMEM;
169 }
170
171 /*
172  * clean up the /proc/fs/afs/ directory
173  */
174 void afs_proc_cleanup(void)
175 {
176         remove_proc_entry("rootcell", proc_afs);
177         remove_proc_entry("cells", proc_afs);
178         remove_proc_entry("fs/afs", NULL);
179 }
180
181 /*
182  * open "/proc/fs/afs/cells" which provides a summary of extant cells
183  */
184 static int afs_proc_cells_open(struct inode *inode, struct file *file)
185 {
186         struct seq_file *m;
187         int ret;
188
189         ret = seq_open(file, &afs_proc_cells_ops);
190         if (ret < 0)
191                 return ret;
192
193         m = file->private_data;
194         m->private = PDE(inode)->data;
195
196         return 0;
197 }
198
199 /*
200  * set up the iterator to start reading from the cells list and return the
201  * first item
202  */
203 static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
204 {
205         struct list_head *_p;
206         loff_t pos = *_pos;
207
208         /* lock the list against modification */
209         down_read(&afs_proc_cells_sem);
210
211         /* allow for the header line */
212         if (!pos)
213                 return (void *) 1;
214         pos--;
215
216         /* find the n'th element in the list */
217         list_for_each(_p, &afs_proc_cells)
218                 if (!pos--)
219                         break;
220
221         return _p != &afs_proc_cells ? _p : NULL;
222 }
223
224 /*
225  * move to next cell in cells list
226  */
227 static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos)
228 {
229         struct list_head *_p;
230
231         (*pos)++;
232
233         _p = v;
234         _p = v == (void *) 1 ? afs_proc_cells.next : _p->next;
235
236         return _p != &afs_proc_cells ? _p : NULL;
237 }
238
239 /*
240  * clean up after reading from the cells list
241  */
242 static void afs_proc_cells_stop(struct seq_file *p, void *v)
243 {
244         up_read(&afs_proc_cells_sem);
245 }
246
247 /*
248  * display a header line followed by a load of cell lines
249  */
250 static int afs_proc_cells_show(struct seq_file *m, void *v)
251 {
252         struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
253
254         if (v == (void *) 1) {
255                 /* display header on line 1 */
256                 seq_puts(m, "USE NAME\n");
257                 return 0;
258         }
259
260         /* display one cell per line on subsequent lines */
261         seq_printf(m, "%3d %s\n",
262                    atomic_read(&cell->usage), cell->name);
263         return 0;
264 }
265
266 /*
267  * handle writes to /proc/fs/afs/cells
268  * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]"
269  */
270 static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
271                                     size_t size, loff_t *_pos)
272 {
273         char *kbuf, *name, *args;
274         int ret;
275
276         /* start by dragging the command into memory */
277         if (size <= 1 || size >= PAGE_SIZE)
278                 return -EINVAL;
279
280         kbuf = kmalloc(size + 1, GFP_KERNEL);
281         if (!kbuf)
282                 return -ENOMEM;
283
284         ret = -EFAULT;
285         if (copy_from_user(kbuf, buf, size) != 0)
286                 goto done;
287         kbuf[size] = 0;
288
289         /* trim to first NL */
290         name = memchr(kbuf, '\n', size);
291         if (name)
292                 *name = 0;
293
294         /* split into command, name and argslist */
295         name = strchr(kbuf, ' ');
296         if (!name)
297                 goto inval;
298         do {
299                 *name++ = 0;
300         } while(*name == ' ');
301         if (!*name)
302                 goto inval;
303
304         args = strchr(name, ' ');
305         if (!args)
306                 goto inval;
307         do {
308                 *args++ = 0;
309         } while(*args == ' ');
310         if (!*args)
311                 goto inval;
312
313         /* determine command to perform */
314         _debug("cmd=%s name=%s args=%s", kbuf, name, args);
315
316         if (strcmp(kbuf, "add") == 0) {
317                 struct afs_cell *cell;
318                 ret = afs_cell_create(name, args, &cell);
319                 if (ret < 0)
320                         goto done;
321
322                 printk("kAFS: Added new cell '%s'\n", name);
323         } else {
324                 goto inval;
325         }
326
327         ret = size;
328
329 done:
330         kfree(kbuf);
331         _leave(" = %d", ret);
332         return ret;
333
334 inval:
335         ret = -EINVAL;
336         printk("kAFS: Invalid Command on /proc/fs/afs/cells file\n");
337         goto done;
338 }
339
340 /*
341  * Stubs for /proc/fs/afs/rootcell
342  */
343 static int afs_proc_rootcell_open(struct inode *inode, struct file *file)
344 {
345         return 0;
346 }
347
348 static int afs_proc_rootcell_release(struct inode *inode, struct file *file)
349 {
350         return 0;
351 }
352
353 static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
354                                       size_t size, loff_t *_pos)
355 {
356         return 0;
357 }
358
359 /*
360  * handle writes to /proc/fs/afs/rootcell
361  * - to initialize rootcell: echo "cell.name:192.168.231.14"
362  */
363 static ssize_t afs_proc_rootcell_write(struct file *file,
364                                        const char __user *buf,
365                                        size_t size, loff_t *_pos)
366 {
367         char *kbuf, *s;
368         int ret;
369
370         /* start by dragging the command into memory */
371         if (size <= 1 || size >= PAGE_SIZE)
372                 return -EINVAL;
373
374         ret = -ENOMEM;
375         kbuf = kmalloc(size + 1, GFP_KERNEL);
376         if (!kbuf)
377                 goto nomem;
378
379         ret = -EFAULT;
380         if (copy_from_user(kbuf, buf, size) != 0)
381                 goto infault;
382         kbuf[size] = 0;
383
384         /* trim to first NL */
385         s = memchr(kbuf, '\n', size);
386         if (s)
387                 *s = 0;
388
389         /* determine command to perform */
390         _debug("rootcell=%s", kbuf);
391
392         ret = afs_cell_init(kbuf);
393         if (ret >= 0)
394                 ret = size;     /* consume everything, always */
395
396 infault:
397         kfree(kbuf);
398 nomem:
399         _leave(" = %d", ret);
400         return ret;
401 }
402
403 /*
404  * initialise /proc/fs/afs/<cell>/
405  */
406 int afs_proc_cell_setup(struct afs_cell *cell)
407 {
408         struct proc_dir_entry *p;
409
410         _enter("%p{%s}", cell, cell->name);
411
412         cell->proc_dir = proc_mkdir(cell->name, proc_afs);
413         if (!cell->proc_dir)
414                 goto error_dir;
415
416         p = create_proc_entry("servers", 0, cell->proc_dir);
417         if (!p)
418                 goto error_servers;
419         p->proc_fops = &afs_proc_cell_servers_fops;
420         p->owner = THIS_MODULE;
421         p->data = cell;
422
423         p = create_proc_entry("vlservers", 0, cell->proc_dir);
424         if (!p)
425                 goto error_vlservers;
426         p->proc_fops = &afs_proc_cell_vlservers_fops;
427         p->owner = THIS_MODULE;
428         p->data = cell;
429
430         p = create_proc_entry("volumes", 0, cell->proc_dir);
431         if (!p)
432                 goto error_volumes;
433         p->proc_fops = &afs_proc_cell_volumes_fops;
434         p->owner = THIS_MODULE;
435         p->data = cell;
436
437         _leave(" = 0");
438         return 0;
439
440 error_volumes:
441         remove_proc_entry("vlservers", cell->proc_dir);
442 error_vlservers:
443         remove_proc_entry("servers", cell->proc_dir);
444 error_servers:
445         remove_proc_entry(cell->name, proc_afs);
446 error_dir:
447         _leave(" = -ENOMEM");
448         return -ENOMEM;
449 }
450
451 /*
452  * remove /proc/fs/afs/<cell>/
453  */
454 void afs_proc_cell_remove(struct afs_cell *cell)
455 {
456         _enter("");
457
458         remove_proc_entry("volumes", cell->proc_dir);
459         remove_proc_entry("vlservers", cell->proc_dir);
460         remove_proc_entry("servers", cell->proc_dir);
461         remove_proc_entry(cell->name, proc_afs);
462
463         _leave("");
464 }
465
466 /*
467  * open "/proc/fs/afs/<cell>/volumes" which provides a summary of extant cells
468  */
469 static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file)
470 {
471         struct afs_cell *cell;
472         struct seq_file *m;
473         int ret;
474
475         cell = afs_get_cell_maybe((struct afs_cell **) &PDE(inode)->data);
476         if (!cell)
477                 return -ENOENT;
478
479         ret = seq_open(file, &afs_proc_cell_volumes_ops);
480         if (ret < 0)
481                 return ret;
482
483         m = file->private_data;
484         m->private = cell;
485
486         return 0;
487 }
488
489 /*
490  * close the file and release the ref to the cell
491  */
492 static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file)
493 {
494         struct afs_cell *cell = PDE(inode)->data;
495         int ret;
496
497         ret = seq_release(inode, file);
498
499         afs_put_cell(cell);
500         return ret;
501 }
502
503 /*
504  * set up the iterator to start reading from the cells list and return the
505  * first item
506  */
507 static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
508 {
509         struct list_head *_p;
510         struct afs_cell *cell = m->private;
511         loff_t pos = *_pos;
512
513         _enter("cell=%p pos=%Ld", cell, *_pos);
514
515         /* lock the list against modification */
516         down_read(&cell->vl_sem);
517
518         /* allow for the header line */
519         if (!pos)
520                 return (void *) 1;
521         pos--;
522
523         /* find the n'th element in the list */
524         list_for_each(_p, &cell->vl_list)
525                 if (!pos--)
526                         break;
527
528         return _p != &cell->vl_list ? _p : NULL;
529 }
530
531 /*
532  * move to next cell in cells list
533  */
534 static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
535                                         loff_t *_pos)
536 {
537         struct list_head *_p;
538         struct afs_cell *cell = p->private;
539
540         _enter("cell=%p pos=%Ld", cell, *_pos);
541
542         (*_pos)++;
543
544         _p = v;
545         _p = (v == (void *) 1) ? cell->vl_list.next : _p->next;
546
547         return (_p != &cell->vl_list) ? _p : NULL;
548 }
549
550 /*
551  * clean up after reading from the cells list
552  */
553 static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
554 {
555         struct afs_cell *cell = p->private;
556
557         up_read(&cell->vl_sem);
558 }
559
560 /*
561  * display a header line followed by a load of volume lines
562  */
563 static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
564 {
565         struct afs_vlocation *vlocation =
566                 list_entry(v, struct afs_vlocation, link);
567
568         /* display header on line 1 */
569         if (v == (void *) 1) {
570                 seq_puts(m, "USE VLID[0]  VLID[1]  VLID[2]  NAME\n");
571                 return 0;
572         }
573
574         /* display one cell per line on subsequent lines */
575         seq_printf(m, "%3d %08x %08x %08x %s\n",
576                    atomic_read(&vlocation->usage),
577                    vlocation->vldb.vid[0],
578                    vlocation->vldb.vid[1],
579                    vlocation->vldb.vid[2],
580                    vlocation->vldb.name);
581
582         return 0;
583 }
584
585 /*
586  * open "/proc/fs/afs/<cell>/vlservers" which provides a list of volume
587  * location server
588  */
589 static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file)
590 {
591         struct afs_cell *cell;
592         struct seq_file *m;
593         int ret;
594
595         cell = afs_get_cell_maybe((struct afs_cell**)&PDE(inode)->data);
596         if (!cell)
597                 return -ENOENT;
598
599         ret = seq_open(file,&afs_proc_cell_vlservers_ops);
600         if (ret<0)
601                 return ret;
602
603         m = file->private_data;
604         m->private = cell;
605
606         return 0;
607 }
608
609 /*
610  * close the file and release the ref to the cell
611  */
612 static int afs_proc_cell_vlservers_release(struct inode *inode,
613                                            struct file *file)
614 {
615         struct afs_cell *cell = PDE(inode)->data;
616         int ret;
617
618         ret = seq_release(inode,file);
619
620         afs_put_cell(cell);
621         return ret;
622 }
623
624 /*
625  * set up the iterator to start reading from the cells list and return the
626  * first item
627  */
628 static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
629 {
630         struct afs_cell *cell = m->private;
631         loff_t pos = *_pos;
632
633         _enter("cell=%p pos=%Ld", cell, *_pos);
634
635         /* lock the list against modification */
636         down_read(&cell->vl_sem);
637
638         /* allow for the header line */
639         if (!pos)
640                 return (void *) 1;
641         pos--;
642
643         if (pos >= cell->vl_naddrs)
644                 return NULL;
645
646         return &cell->vl_addrs[pos];
647 }
648
649 /*
650  * move to next cell in cells list
651  */
652 static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
653                                           loff_t *_pos)
654 {
655         struct afs_cell *cell = p->private;
656         loff_t pos;
657
658         _enter("cell=%p{nad=%u} pos=%Ld", cell, cell->vl_naddrs, *_pos);
659
660         pos = *_pos;
661         (*_pos)++;
662         if (pos >= cell->vl_naddrs)
663                 return NULL;
664
665         return &cell->vl_addrs[pos];
666 }
667
668 /*
669  * clean up after reading from the cells list
670  */
671 static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v)
672 {
673         struct afs_cell *cell = p->private;
674
675         up_read(&cell->vl_sem);
676 }
677
678 /*
679  * display a header line followed by a load of volume lines
680  */
681 static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
682 {
683         struct in_addr *addr = v;
684
685         /* display header on line 1 */
686         if (v == (struct in_addr *) 1) {
687                 seq_puts(m, "ADDRESS\n");
688                 return 0;
689         }
690
691         /* display one cell per line on subsequent lines */
692         seq_printf(m, "%u.%u.%u.%u\n", NIPQUAD(addr->s_addr));
693         return 0;
694 }
695
696 /*
697  * open "/proc/fs/afs/<cell>/servers" which provides a summary of active
698  * servers
699  */
700 static int afs_proc_cell_servers_open(struct inode *inode, struct file *file)
701 {
702         struct afs_cell *cell;
703         struct seq_file *m;
704         int ret;
705
706         cell = afs_get_cell_maybe((struct afs_cell **) &PDE(inode)->data);
707         if (!cell)
708                 return -ENOENT;
709
710         ret = seq_open(file, &afs_proc_cell_servers_ops);
711         if (ret < 0)
712                 return ret;
713
714         m = file->private_data;
715         m->private = cell;
716         return 0;
717 }
718
719 /*
720  * close the file and release the ref to the cell
721  */
722 static int afs_proc_cell_servers_release(struct inode *inode,
723                                          struct file *file)
724 {
725         struct afs_cell *cell = PDE(inode)->data;
726         int ret;
727
728         ret = seq_release(inode, file);
729
730         afs_put_cell(cell);
731         return ret;
732 }
733
734 /*
735  * set up the iterator to start reading from the cells list and return the
736  * first item
737  */
738 static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
739         __acquires(m->private->sv_lock)
740 {
741         struct list_head *_p;
742         struct afs_cell *cell = m->private;
743         loff_t pos = *_pos;
744
745         _enter("cell=%p pos=%Ld", cell, *_pos);
746
747         /* lock the list against modification */
748         read_lock(&cell->sv_lock);
749
750         /* allow for the header line */
751         if (!pos)
752                 return (void *) 1;
753         pos--;
754
755         /* find the n'th element in the list */
756         list_for_each(_p, &cell->sv_list)
757                 if (!pos--)
758                         break;
759
760         return _p != &cell->sv_list ? _p : NULL;
761 }
762
763 /*
764  * move to next cell in cells list
765  */
766 static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
767                                         loff_t *_pos)
768 {
769         struct list_head *_p;
770         struct afs_cell *cell = p->private;
771
772         _enter("cell=%p pos=%Ld", cell, *_pos);
773
774         (*_pos)++;
775
776         _p = v;
777         _p = v == (void *) 1 ? cell->sv_list.next : _p->next;
778
779         return _p != &cell->sv_list ? _p : NULL;
780 }
781
782 /*
783  * clean up after reading from the cells list
784  */
785 static void afs_proc_cell_servers_stop(struct seq_file *p, void *v)
786         __releases(p->private->sv_lock)
787 {
788         struct afs_cell *cell = p->private;
789
790         read_unlock(&cell->sv_lock);
791 }
792
793 /*
794  * display a header line followed by a load of volume lines
795  */
796 static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
797 {
798         struct afs_server *server = list_entry(v, struct afs_server, link);
799         char ipaddr[20];
800
801         /* display header on line 1 */
802         if (v == (void *) 1) {
803                 seq_puts(m, "USE ADDR            STATE\n");
804                 return 0;
805         }
806
807         /* display one cell per line on subsequent lines */
808         sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(server->addr));
809         seq_printf(m, "%3d %-15.15s %5d\n",
810                    atomic_read(&server->usage), ipaddr, server->fs_state);
811
812         return 0;
813 }