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