| // SPDX-License-Identifier: GPL-2.0 | 
 | /* | 
 |  * Procfs support for lockd | 
 |  * | 
 |  * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com> | 
 |  */ | 
 |  | 
 | #include <linux/fs.h> | 
 | #include <linux/proc_fs.h> | 
 | #include <linux/module.h> | 
 | #include <linux/nsproxy.h> | 
 | #include <net/net_namespace.h> | 
 |  | 
 | #include "netns.h" | 
 | #include "procfs.h" | 
 |  | 
 | /* | 
 |  * We only allow strings that start with 'Y', 'y', or '1'. | 
 |  */ | 
 | static ssize_t | 
 | nlm_end_grace_write(struct file *file, const char __user *buf, size_t size, | 
 | 		    loff_t *pos) | 
 | { | 
 | 	char *data; | 
 | 	struct lockd_net *ln = net_generic(current->nsproxy->net_ns, | 
 | 					   lockd_net_id); | 
 |  | 
 | 	if (size < 1) | 
 | 		return -EINVAL; | 
 |  | 
 | 	data = simple_transaction_get(file, buf, size); | 
 | 	if (IS_ERR(data)) | 
 | 		return PTR_ERR(data); | 
 |  | 
 | 	switch(data[0]) { | 
 | 	case 'Y': | 
 | 	case 'y': | 
 | 	case '1': | 
 | 		locks_end_grace(&ln->lockd_manager); | 
 | 		break; | 
 | 	default: | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	return size; | 
 | } | 
 |  | 
 | static ssize_t | 
 | nlm_end_grace_read(struct file *file, char __user *buf, size_t size, | 
 | 		   loff_t *pos) | 
 | { | 
 | 	struct lockd_net *ln = net_generic(current->nsproxy->net_ns, | 
 | 					   lockd_net_id); | 
 | 	char resp[3]; | 
 |  | 
 | 	resp[0] = list_empty(&ln->lockd_manager.list) ? 'Y' : 'N'; | 
 | 	resp[1] = '\n'; | 
 | 	resp[2] = '\0'; | 
 |  | 
 | 	return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp)); | 
 | } | 
 |  | 
 | static const struct file_operations lockd_end_grace_operations = { | 
 | 	.write		= nlm_end_grace_write, | 
 | 	.read		= nlm_end_grace_read, | 
 | 	.llseek		= default_llseek, | 
 | 	.release	= simple_transaction_release, | 
 | }; | 
 |  | 
 | int __init | 
 | lockd_create_procfs(void) | 
 | { | 
 | 	struct proc_dir_entry *entry; | 
 |  | 
 | 	entry = proc_mkdir("fs/lockd", NULL); | 
 | 	if (!entry) | 
 | 		return -ENOMEM; | 
 | 	entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry, | 
 | 				 &lockd_end_grace_operations); | 
 | 	if (!entry) { | 
 | 		remove_proc_entry("fs/lockd", NULL); | 
 | 		return -ENOMEM; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | void __exit | 
 | lockd_remove_procfs(void) | 
 | { | 
 | 	remove_proc_entry("fs/lockd/nlm_end_grace", NULL); | 
 | 	remove_proc_entry("fs/lockd", NULL); | 
 | } |