|  | // 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 proc_ops lockd_end_grace_proc_ops = { | 
|  | .proc_write	= nlm_end_grace_write, | 
|  | .proc_read	= nlm_end_grace_read, | 
|  | .proc_lseek	= default_llseek, | 
|  | .proc_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_proc_ops); | 
|  | 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); | 
|  | } |