Merge branch 'for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck...
[linux-2.6-microblaze.git] / 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 <linux/sched.h>
17 #include <linux/uaccess.h>
18 #include "internal.h"
19
20 static inline struct afs_net *afs_proc2net(struct file *f)
21 {
22         return &__afs_net;
23 }
24
25 static inline struct afs_net *afs_seq2net(struct seq_file *m)
26 {
27         return &__afs_net; // TODO: use seq_file_net(m)
28 }
29
30 static int afs_proc_cells_open(struct inode *inode, struct file *file);
31 static void *afs_proc_cells_start(struct seq_file *p, loff_t *pos);
32 static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos);
33 static void afs_proc_cells_stop(struct seq_file *p, void *v);
34 static int afs_proc_cells_show(struct seq_file *m, void *v);
35 static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
36                                     size_t size, loff_t *_pos);
37
38 static const struct seq_operations afs_proc_cells_ops = {
39         .start  = afs_proc_cells_start,
40         .next   = afs_proc_cells_next,
41         .stop   = afs_proc_cells_stop,
42         .show   = afs_proc_cells_show,
43 };
44
45 static const struct file_operations afs_proc_cells_fops = {
46         .open           = afs_proc_cells_open,
47         .read           = seq_read,
48         .write          = afs_proc_cells_write,
49         .llseek         = seq_lseek,
50         .release        = seq_release,
51 };
52
53 static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
54                                       size_t size, loff_t *_pos);
55 static ssize_t afs_proc_rootcell_write(struct file *file,
56                                        const char __user *buf,
57                                        size_t size, loff_t *_pos);
58
59 static const struct file_operations afs_proc_rootcell_fops = {
60         .read           = afs_proc_rootcell_read,
61         .write          = afs_proc_rootcell_write,
62         .llseek         = no_llseek,
63 };
64
65 static int afs_proc_cell_volumes_open(struct inode *inode, 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 const 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        = seq_release,
84 };
85
86 static int afs_proc_cell_vlservers_open(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 const 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        = seq_release,
106 };
107
108 static int afs_proc_servers_open(struct inode *inode, struct file *file);
109 static void *afs_proc_servers_start(struct seq_file *p, loff_t *pos);
110 static void *afs_proc_servers_next(struct seq_file *p, void *v,
111                                         loff_t *pos);
112 static void afs_proc_servers_stop(struct seq_file *p, void *v);
113 static int afs_proc_servers_show(struct seq_file *m, void *v);
114
115 static const struct seq_operations afs_proc_servers_ops = {
116         .start  = afs_proc_servers_start,
117         .next   = afs_proc_servers_next,
118         .stop   = afs_proc_servers_stop,
119         .show   = afs_proc_servers_show,
120 };
121
122 static const struct file_operations afs_proc_servers_fops = {
123         .open           = afs_proc_servers_open,
124         .read           = seq_read,
125         .llseek         = seq_lseek,
126         .release        = seq_release,
127 };
128
129 static int afs_proc_sysname_open(struct inode *inode, struct file *file);
130 static int afs_proc_sysname_release(struct inode *inode, struct file *file);
131 static void *afs_proc_sysname_start(struct seq_file *p, loff_t *pos);
132 static void *afs_proc_sysname_next(struct seq_file *p, void *v,
133                                         loff_t *pos);
134 static void afs_proc_sysname_stop(struct seq_file *p, void *v);
135 static int afs_proc_sysname_show(struct seq_file *m, void *v);
136 static ssize_t afs_proc_sysname_write(struct file *file,
137                                       const char __user *buf,
138                                       size_t size, loff_t *_pos);
139
140 static const struct seq_operations afs_proc_sysname_ops = {
141         .start  = afs_proc_sysname_start,
142         .next   = afs_proc_sysname_next,
143         .stop   = afs_proc_sysname_stop,
144         .show   = afs_proc_sysname_show,
145 };
146
147 static const struct file_operations afs_proc_sysname_fops = {
148         .open           = afs_proc_sysname_open,
149         .read           = seq_read,
150         .llseek         = seq_lseek,
151         .release        = afs_proc_sysname_release,
152         .write          = afs_proc_sysname_write,
153 };
154
155 static const struct file_operations afs_proc_stats_fops;
156
157 /*
158  * initialise the /proc/fs/afs/ directory
159  */
160 int afs_proc_init(struct afs_net *net)
161 {
162         _enter("");
163
164         net->proc_afs = proc_mkdir("fs/afs", NULL);
165         if (!net->proc_afs)
166                 goto error_dir;
167
168         if (!proc_create("cells", 0644, net->proc_afs, &afs_proc_cells_fops) ||
169             !proc_create("rootcell", 0644, net->proc_afs, &afs_proc_rootcell_fops) ||
170             !proc_create("servers", 0644, net->proc_afs, &afs_proc_servers_fops) ||
171             !proc_create("stats", 0644, net->proc_afs, &afs_proc_stats_fops) ||
172             !proc_create("sysname", 0644, net->proc_afs, &afs_proc_sysname_fops))
173                 goto error_tree;
174
175         _leave(" = 0");
176         return 0;
177
178 error_tree:
179         proc_remove(net->proc_afs);
180 error_dir:
181         _leave(" = -ENOMEM");
182         return -ENOMEM;
183 }
184
185 /*
186  * clean up the /proc/fs/afs/ directory
187  */
188 void afs_proc_cleanup(struct afs_net *net)
189 {
190         proc_remove(net->proc_afs);
191         net->proc_afs = NULL;
192 }
193
194 /*
195  * open "/proc/fs/afs/cells" which provides a summary of extant cells
196  */
197 static int afs_proc_cells_open(struct inode *inode, struct file *file)
198 {
199         struct seq_file *m;
200         int ret;
201
202         ret = seq_open(file, &afs_proc_cells_ops);
203         if (ret < 0)
204                 return ret;
205
206         m = file->private_data;
207         m->private = PDE_DATA(inode);
208         return 0;
209 }
210
211 /*
212  * set up the iterator to start reading from the cells list and return the
213  * first item
214  */
215 static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
216         __acquires(rcu)
217 {
218         struct afs_net *net = afs_seq2net(m);
219
220         rcu_read_lock();
221         return seq_list_start_head(&net->proc_cells, *_pos);
222 }
223
224 /*
225  * move to next cell in cells list
226  */
227 static void *afs_proc_cells_next(struct seq_file *m, void *v, loff_t *pos)
228 {
229         struct afs_net *net = afs_seq2net(m);
230
231         return seq_list_next(v, &net->proc_cells, pos);
232 }
233
234 /*
235  * clean up after reading from the cells list
236  */
237 static void afs_proc_cells_stop(struct seq_file *m, void *v)
238         __releases(rcu)
239 {
240         rcu_read_unlock();
241 }
242
243 /*
244  * display a header line followed by a load of cell lines
245  */
246 static int afs_proc_cells_show(struct seq_file *m, void *v)
247 {
248         struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
249         struct afs_net *net = afs_seq2net(m);
250
251         if (v == &net->proc_cells) {
252                 /* display header on line 1 */
253                 seq_puts(m, "USE NAME\n");
254                 return 0;
255         }
256
257         /* display one cell per line on subsequent lines */
258         seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
259         return 0;
260 }
261
262 /*
263  * handle writes to /proc/fs/afs/cells
264  * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]"
265  */
266 static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
267                                     size_t size, loff_t *_pos)
268 {
269         struct afs_net *net = afs_proc2net(file);
270         char *kbuf, *name, *args;
271         int ret;
272
273         /* start by dragging the command into memory */
274         if (size <= 1 || size >= PAGE_SIZE)
275                 return -EINVAL;
276
277         kbuf = memdup_user_nul(buf, size);
278         if (IS_ERR(kbuf))
279                 return PTR_ERR(kbuf);
280
281         /* trim to first NL */
282         name = memchr(kbuf, '\n', size);
283         if (name)
284                 *name = 0;
285
286         /* split into command, name and argslist */
287         name = strchr(kbuf, ' ');
288         if (!name)
289                 goto inval;
290         do {
291                 *name++ = 0;
292         } while(*name == ' ');
293         if (!*name)
294                 goto inval;
295
296         args = strchr(name, ' ');
297         if (!args)
298                 goto inval;
299         do {
300                 *args++ = 0;
301         } while(*args == ' ');
302         if (!*args)
303                 goto inval;
304
305         /* determine command to perform */
306         _debug("cmd=%s name=%s args=%s", kbuf, name, args);
307
308         if (strcmp(kbuf, "add") == 0) {
309                 struct afs_cell *cell;
310
311                 cell = afs_lookup_cell(net, name, strlen(name), args, true);
312                 if (IS_ERR(cell)) {
313                         ret = PTR_ERR(cell);
314                         goto done;
315                 }
316
317                 if (test_and_set_bit(AFS_CELL_FL_NO_GC, &cell->flags))
318                         afs_put_cell(net, cell);
319                 printk("kAFS: Added new cell '%s'\n", name);
320         } else {
321                 goto inval;
322         }
323
324         ret = size;
325
326 done:
327         kfree(kbuf);
328         _leave(" = %d", ret);
329         return ret;
330
331 inval:
332         ret = -EINVAL;
333         printk("kAFS: Invalid Command on /proc/fs/afs/cells file\n");
334         goto done;
335 }
336
337 static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
338                                       size_t size, loff_t *_pos)
339 {
340         struct afs_cell *cell;
341         struct afs_net *net = afs_proc2net(file);
342         unsigned int seq = 0;
343         char name[AFS_MAXCELLNAME + 1];
344         int len;
345
346         if (*_pos > 0)
347                 return 0;
348         if (!net->ws_cell)
349                 return 0;
350
351         rcu_read_lock();
352         do {
353                 read_seqbegin_or_lock(&net->cells_lock, &seq);
354                 len = 0;
355                 cell = rcu_dereference_raw(net->ws_cell);
356                 if (cell) {
357                         len = cell->name_len;
358                         memcpy(name, cell->name, len);
359                 }
360         } while (need_seqretry(&net->cells_lock, seq));
361         done_seqretry(&net->cells_lock, seq);
362         rcu_read_unlock();
363
364         if (!len)
365                 return 0;
366
367         name[len++] = '\n';
368         if (len > size)
369                 len = size;
370         if (copy_to_user(buf, name, len) != 0)
371                 return -EFAULT;
372         *_pos = 1;
373         return len;
374 }
375
376 /*
377  * handle writes to /proc/fs/afs/rootcell
378  * - to initialize rootcell: echo "cell.name:192.168.231.14"
379  */
380 static ssize_t afs_proc_rootcell_write(struct file *file,
381                                        const char __user *buf,
382                                        size_t size, loff_t *_pos)
383 {
384         struct afs_net *net = afs_proc2net(file);
385         char *kbuf, *s;
386         int ret;
387
388         /* start by dragging the command into memory */
389         if (size <= 1 || size >= PAGE_SIZE)
390                 return -EINVAL;
391
392         kbuf = memdup_user_nul(buf, size);
393         if (IS_ERR(kbuf))
394                 return PTR_ERR(kbuf);
395
396         ret = -EINVAL;
397         if (kbuf[0] == '.')
398                 goto out;
399         if (memchr(kbuf, '/', size))
400                 goto out;
401
402         /* trim to first NL */
403         s = memchr(kbuf, '\n', size);
404         if (s)
405                 *s = 0;
406
407         /* determine command to perform */
408         _debug("rootcell=%s", kbuf);
409
410         ret = afs_cell_init(net, kbuf);
411         if (ret >= 0)
412                 ret = size;     /* consume everything, always */
413
414 out:
415         kfree(kbuf);
416         _leave(" = %d", ret);
417         return ret;
418 }
419
420 /*
421  * initialise /proc/fs/afs/<cell>/
422  */
423 int afs_proc_cell_setup(struct afs_net *net, struct afs_cell *cell)
424 {
425         struct proc_dir_entry *dir;
426
427         _enter("%p{%s},%p", cell, cell->name, net->proc_afs);
428
429         dir = proc_mkdir(cell->name, net->proc_afs);
430         if (!dir)
431                 goto error_dir;
432
433         if (!proc_create_data("vlservers", 0, dir,
434                               &afs_proc_cell_vlservers_fops, cell) ||
435             !proc_create_data("volumes", 0, dir,
436                               &afs_proc_cell_volumes_fops, cell))
437                 goto error_tree;
438
439         _leave(" = 0");
440         return 0;
441
442 error_tree:
443         remove_proc_subtree(cell->name, net->proc_afs);
444 error_dir:
445         _leave(" = -ENOMEM");
446         return -ENOMEM;
447 }
448
449 /*
450  * remove /proc/fs/afs/<cell>/
451  */
452 void afs_proc_cell_remove(struct afs_net *net, struct afs_cell *cell)
453 {
454         _enter("");
455
456         remove_proc_subtree(cell->name, net->proc_afs);
457
458         _leave("");
459 }
460
461 /*
462  * open "/proc/fs/afs/<cell>/volumes" which provides a summary of extant cells
463  */
464 static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file)
465 {
466         struct afs_cell *cell;
467         struct seq_file *m;
468         int ret;
469
470         cell = PDE_DATA(inode);
471         if (!cell)
472                 return -ENOENT;
473
474         ret = seq_open(file, &afs_proc_cell_volumes_ops);
475         if (ret < 0)
476                 return ret;
477
478         m = file->private_data;
479         m->private = cell;
480
481         return 0;
482 }
483
484 /*
485  * set up the iterator to start reading from the cells list and return the
486  * first item
487  */
488 static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
489         __acquires(cell->proc_lock)
490 {
491         struct afs_cell *cell = m->private;
492
493         _enter("cell=%p pos=%Ld", cell, *_pos);
494
495         read_lock(&cell->proc_lock);
496         return seq_list_start_head(&cell->proc_volumes, *_pos);
497 }
498
499 /*
500  * move to next cell in cells list
501  */
502 static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
503                                         loff_t *_pos)
504 {
505         struct afs_cell *cell = p->private;
506
507         _enter("cell=%p pos=%Ld", cell, *_pos);
508         return seq_list_next(v, &cell->proc_volumes, _pos);
509 }
510
511 /*
512  * clean up after reading from the cells list
513  */
514 static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
515         __releases(cell->proc_lock)
516 {
517         struct afs_cell *cell = p->private;
518
519         read_unlock(&cell->proc_lock);
520 }
521
522 static const char afs_vol_types[3][3] = {
523         [AFSVL_RWVOL]   = "RW",
524         [AFSVL_ROVOL]   = "RO",
525         [AFSVL_BACKVOL] = "BK",
526 };
527
528 /*
529  * display a header line followed by a load of volume lines
530  */
531 static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
532 {
533         struct afs_cell *cell = m->private;
534         struct afs_volume *vol = list_entry(v, struct afs_volume, proc_link);
535
536         /* Display header on line 1 */
537         if (v == &cell->proc_volumes) {
538                 seq_puts(m, "USE VID      TY\n");
539                 return 0;
540         }
541
542         seq_printf(m, "%3d %08x %s\n",
543                    atomic_read(&vol->usage), vol->vid,
544                    afs_vol_types[vol->type]);
545
546         return 0;
547 }
548
549 /*
550  * open "/proc/fs/afs/<cell>/vlservers" which provides a list of volume
551  * location server
552  */
553 static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file)
554 {
555         struct afs_cell *cell;
556         struct seq_file *m;
557         int ret;
558
559         cell = PDE_DATA(inode);
560         if (!cell)
561                 return -ENOENT;
562
563         ret = seq_open(file, &afs_proc_cell_vlservers_ops);
564         if (ret<0)
565                 return ret;
566
567         m = file->private_data;
568         m->private = cell;
569
570         return 0;
571 }
572
573 /*
574  * set up the iterator to start reading from the cells list and return the
575  * first item
576  */
577 static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
578         __acquires(rcu)
579 {
580         struct afs_addr_list *alist;
581         struct afs_cell *cell = m->private;
582         loff_t pos = *_pos;
583
584         rcu_read_lock();
585
586         alist = rcu_dereference(cell->vl_addrs);
587
588         /* allow for the header line */
589         if (!pos)
590                 return (void *) 1;
591         pos--;
592
593         if (!alist || pos >= alist->nr_addrs)
594                 return NULL;
595
596         return alist->addrs + pos;
597 }
598
599 /*
600  * move to next cell in cells list
601  */
602 static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
603                                           loff_t *_pos)
604 {
605         struct afs_addr_list *alist;
606         struct afs_cell *cell = p->private;
607         loff_t pos;
608
609         alist = rcu_dereference(cell->vl_addrs);
610
611         pos = *_pos;
612         (*_pos)++;
613         if (!alist || pos >= alist->nr_addrs)
614                 return NULL;
615
616         return alist->addrs + pos;
617 }
618
619 /*
620  * clean up after reading from the cells list
621  */
622 static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v)
623         __releases(rcu)
624 {
625         rcu_read_unlock();
626 }
627
628 /*
629  * display a header line followed by a load of volume lines
630  */
631 static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
632 {
633         struct sockaddr_rxrpc *addr = v;
634
635         /* display header on line 1 */
636         if (v == (void *)1) {
637                 seq_puts(m, "ADDRESS\n");
638                 return 0;
639         }
640
641         /* display one cell per line on subsequent lines */
642         seq_printf(m, "%pISp\n", &addr->transport);
643         return 0;
644 }
645
646 /*
647  * open "/proc/fs/afs/servers" which provides a summary of active
648  * servers
649  */
650 static int afs_proc_servers_open(struct inode *inode, struct file *file)
651 {
652         return seq_open(file, &afs_proc_servers_ops);
653 }
654
655 /*
656  * Set up the iterator to start reading from the server list and return the
657  * first item.
658  */
659 static void *afs_proc_servers_start(struct seq_file *m, loff_t *_pos)
660         __acquires(rcu)
661 {
662         struct afs_net *net = afs_seq2net(m);
663
664         rcu_read_lock();
665         return seq_hlist_start_head_rcu(&net->fs_proc, *_pos);
666 }
667
668 /*
669  * move to next cell in cells list
670  */
671 static void *afs_proc_servers_next(struct seq_file *m, void *v, loff_t *_pos)
672 {
673         struct afs_net *net = afs_seq2net(m);
674
675         return seq_hlist_next_rcu(v, &net->fs_proc, _pos);
676 }
677
678 /*
679  * clean up after reading from the cells list
680  */
681 static void afs_proc_servers_stop(struct seq_file *p, void *v)
682         __releases(rcu)
683 {
684         rcu_read_unlock();
685 }
686
687 /*
688  * display a header line followed by a load of volume lines
689  */
690 static int afs_proc_servers_show(struct seq_file *m, void *v)
691 {
692         struct afs_server *server;
693         struct afs_addr_list *alist;
694
695         if (v == SEQ_START_TOKEN) {
696                 seq_puts(m, "UUID                                 USE ADDR\n");
697                 return 0;
698         }
699
700         server = list_entry(v, struct afs_server, proc_link);
701         alist = rcu_dereference(server->addresses);
702         seq_printf(m, "%pU %3d %pISp\n",
703                    &server->uuid,
704                    atomic_read(&server->usage),
705                    &alist->addrs[alist->index].transport);
706         return 0;
707 }
708
709 void afs_put_sysnames(struct afs_sysnames *sysnames)
710 {
711         int i;
712
713         if (sysnames && refcount_dec_and_test(&sysnames->usage)) {
714                 for (i = 0; i < sysnames->nr; i++)
715                         if (sysnames->subs[i] != afs_init_sysname &&
716                             sysnames->subs[i] != sysnames->blank)
717                                 kfree(sysnames->subs[i]);
718         }
719 }
720
721 /*
722  * Handle opening of /proc/fs/afs/sysname.  If it is opened for writing, we
723  * assume the caller wants to change the substitution list and we allocate a
724  * buffer to hold the list.
725  */
726 static int afs_proc_sysname_open(struct inode *inode, struct file *file)
727 {
728         struct afs_sysnames *sysnames;
729         struct seq_file *m;
730         int ret;
731
732         ret = seq_open(file, &afs_proc_sysname_ops);
733         if (ret < 0)
734                 return ret;
735
736         if (file->f_mode & FMODE_WRITE) {
737                 sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
738                 if (!sysnames) {
739                         seq_release(inode, file);
740                         return -ENOMEM;
741                 }
742
743                 refcount_set(&sysnames->usage, 1);
744                 m = file->private_data;
745                 m->private = sysnames;
746         }
747
748         return 0;
749 }
750
751 /*
752  * Handle writes to /proc/fs/afs/sysname to set the @sys substitution.
753  */
754 static ssize_t afs_proc_sysname_write(struct file *file,
755                                       const char __user *buf,
756                                       size_t size, loff_t *_pos)
757 {
758         struct afs_sysnames *sysnames;
759         struct seq_file *m = file->private_data;
760         char *kbuf = NULL, *s, *p, *sub;
761         int ret, len;
762
763         sysnames = m->private;
764         if (!sysnames)
765                 return -EINVAL;
766         if (sysnames->error)
767                 return sysnames->error;
768
769         if (size >= PAGE_SIZE - 1) {
770                 sysnames->error = -EINVAL;
771                 return -EINVAL;
772         }
773         if (size == 0)
774                 return 0;
775
776         kbuf = memdup_user_nul(buf, size);
777         if (IS_ERR(kbuf))
778                 return PTR_ERR(kbuf);
779
780         inode_lock(file_inode(file));
781
782         p = kbuf;
783         while ((s = strsep(&p, " \t\n"))) {
784                 len = strlen(s);
785                 if (len == 0)
786                         continue;
787                 ret = -ENAMETOOLONG;
788                 if (len >= AFSNAMEMAX)
789                         goto error;
790
791                 if (len >= 4 &&
792                     s[len - 4] == '@' &&
793                     s[len - 3] == 's' &&
794                     s[len - 2] == 'y' &&
795                     s[len - 1] == 's')
796                         /* Protect against recursion */
797                         goto invalid;
798
799                 if (s[0] == '.' &&
800                     (len < 2 || (len == 2 && s[1] == '.')))
801                         goto invalid;
802
803                 if (memchr(s, '/', len))
804                         goto invalid;
805
806                 ret = -EFBIG;
807                 if (sysnames->nr >= AFS_NR_SYSNAME)
808                         goto out;
809
810                 if (strcmp(s, afs_init_sysname) == 0) {
811                         sub = (char *)afs_init_sysname;
812                 } else {
813                         ret = -ENOMEM;
814                         sub = kmemdup(s, len + 1, GFP_KERNEL);
815                         if (!sub)
816                                 goto out;
817                 }
818
819                 sysnames->subs[sysnames->nr] = sub;
820                 sysnames->nr++;
821         }
822
823         ret = size;     /* consume everything, always */
824 out:
825         inode_unlock(file_inode(file));
826         kfree(kbuf);
827         return ret;
828
829 invalid:
830         ret = -EINVAL;
831 error:
832         sysnames->error = ret;
833         goto out;
834 }
835
836 static int afs_proc_sysname_release(struct inode *inode, struct file *file)
837 {
838         struct afs_sysnames *sysnames, *kill = NULL;
839         struct seq_file *m = file->private_data;
840         struct afs_net *net = afs_seq2net(m);
841
842         sysnames = m->private;
843         if (sysnames) {
844                 if (!sysnames->error) {
845                         kill = sysnames;
846                         if (sysnames->nr == 0) {
847                                 sysnames->subs[0] = sysnames->blank;
848                                 sysnames->nr++;
849                         }
850                         write_lock(&net->sysnames_lock);
851                         kill = net->sysnames;
852                         net->sysnames = sysnames;
853                         write_unlock(&net->sysnames_lock);
854                 }
855                 afs_put_sysnames(kill);
856         }
857
858         return seq_release(inode, file);
859 }
860
861 static void *afs_proc_sysname_start(struct seq_file *m, loff_t *pos)
862         __acquires(&net->sysnames_lock)
863 {
864         struct afs_net *net = afs_seq2net(m);
865         struct afs_sysnames *names = net->sysnames;
866
867         read_lock(&net->sysnames_lock);
868
869         if (*pos >= names->nr)
870                 return NULL;
871         return (void *)(unsigned long)(*pos + 1);
872 }
873
874 static void *afs_proc_sysname_next(struct seq_file *m, void *v, loff_t *pos)
875 {
876         struct afs_net *net = afs_seq2net(m);
877         struct afs_sysnames *names = net->sysnames;
878
879         *pos += 1;
880         if (*pos >= names->nr)
881                 return NULL;
882         return (void *)(unsigned long)(*pos + 1);
883 }
884
885 static void afs_proc_sysname_stop(struct seq_file *m, void *v)
886         __releases(&net->sysnames_lock)
887 {
888         struct afs_net *net = afs_seq2net(m);
889
890         read_unlock(&net->sysnames_lock);
891 }
892
893 static int afs_proc_sysname_show(struct seq_file *m, void *v)
894 {
895         struct afs_net *net = afs_seq2net(m);
896         struct afs_sysnames *sysnames = net->sysnames;
897         unsigned int i = (unsigned long)v - 1;
898
899         if (i < sysnames->nr)
900                 seq_printf(m, "%s\n", sysnames->subs[i]);
901         return 0;
902 }
903
904 /*
905  * Display general per-net namespace statistics
906  */
907 static int afs_proc_stats_show(struct seq_file *m, void *v)
908 {
909         struct afs_net *net = afs_seq2net(m);
910
911         seq_puts(m, "kAFS statistics\n");
912
913         seq_printf(m, "dir-mgmt: look=%u reval=%u inval=%u relpg=%u\n",
914                    atomic_read(&net->n_lookup),
915                    atomic_read(&net->n_reval),
916                    atomic_read(&net->n_inval),
917                    atomic_read(&net->n_relpg));
918
919         seq_printf(m, "dir-data: rdpg=%u\n",
920                    atomic_read(&net->n_read_dir));
921
922         seq_printf(m, "dir-edit: cr=%u rm=%u\n",
923                    atomic_read(&net->n_dir_cr),
924                    atomic_read(&net->n_dir_rm));
925
926         seq_printf(m, "file-rd : n=%u nb=%lu\n",
927                    atomic_read(&net->n_fetches),
928                    atomic_long_read(&net->n_fetch_bytes));
929         seq_printf(m, "file-wr : n=%u nb=%lu\n",
930                    atomic_read(&net->n_stores),
931                    atomic_long_read(&net->n_store_bytes));
932         return 0;
933 }
934
935 /*
936  * Open "/proc/fs/afs/stats" to allow reading of the stat counters.
937  */
938 static int afs_proc_stats_open(struct inode *inode, struct file *file)
939 {
940         return single_open(file, afs_proc_stats_show, NULL);
941 }
942
943 static const struct file_operations afs_proc_stats_fops = {
944         .open           = afs_proc_stats_open,
945         .read           = seq_read,
946         .llseek         = seq_lseek,
947         .release        = single_release,
948 };