xref: /openbmc/linux/fs/afs/proc.c (revision e0f6d1a5)
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 };
949