| 1 | // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | /* | 
|---|
| 3 | * Procfs support for lockd | 
|---|
| 4 | * | 
|---|
| 5 | * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com> | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | #include <linux/fs.h> | 
|---|
| 9 | #include <linux/proc_fs.h> | 
|---|
| 10 | #include <linux/module.h> | 
|---|
| 11 | #include <linux/nsproxy.h> | 
|---|
| 12 | #include <net/net_namespace.h> | 
|---|
| 13 |  | 
|---|
| 14 | #include "netns.h" | 
|---|
| 15 | #include "procfs.h" | 
|---|
| 16 |  | 
|---|
| 17 | /* | 
|---|
| 18 | * We only allow strings that start with 'Y', 'y', or '1'. | 
|---|
| 19 | */ | 
|---|
| 20 | static ssize_t | 
|---|
| 21 | nlm_end_grace_write(struct file *file, const char __user *buf, size_t size, | 
|---|
| 22 | loff_t *pos) | 
|---|
| 23 | { | 
|---|
| 24 | char *data; | 
|---|
| 25 | struct lockd_net *ln = net_generic(current->nsproxy->net_ns, | 
|---|
| 26 | id: lockd_net_id); | 
|---|
| 27 |  | 
|---|
| 28 | if (size < 1) | 
|---|
| 29 | return -EINVAL; | 
|---|
| 30 |  | 
|---|
| 31 | data = simple_transaction_get(file, buf, size); | 
|---|
| 32 | if (IS_ERR(ptr: data)) | 
|---|
| 33 | return PTR_ERR(ptr: data); | 
|---|
| 34 |  | 
|---|
| 35 | switch(data[0]) { | 
|---|
| 36 | case 'Y': | 
|---|
| 37 | case 'y': | 
|---|
| 38 | case '1': | 
|---|
| 39 | locks_end_grace(&ln->lockd_manager); | 
|---|
| 40 | break; | 
|---|
| 41 | default: | 
|---|
| 42 | return -EINVAL; | 
|---|
| 43 | } | 
|---|
| 44 |  | 
|---|
| 45 | return size; | 
|---|
| 46 | } | 
|---|
| 47 |  | 
|---|
| 48 | static ssize_t | 
|---|
| 49 | nlm_end_grace_read(struct file *file, char __user *buf, size_t size, | 
|---|
| 50 | loff_t *pos) | 
|---|
| 51 | { | 
|---|
| 52 | struct lockd_net *ln = net_generic(current->nsproxy->net_ns, | 
|---|
| 53 | id: lockd_net_id); | 
|---|
| 54 | char resp[3]; | 
|---|
| 55 |  | 
|---|
| 56 | resp[0] = list_empty(head: &ln->lockd_manager.list) ? 'Y' : 'N'; | 
|---|
| 57 | resp[1] = '\n'; | 
|---|
| 58 | resp[2] = '\0'; | 
|---|
| 59 |  | 
|---|
| 60 | return simple_read_from_buffer(to: buf, count: size, ppos: pos, from: resp, available: sizeof(resp)); | 
|---|
| 61 | } | 
|---|
| 62 |  | 
|---|
| 63 | static const struct proc_ops lockd_end_grace_proc_ops = { | 
|---|
| 64 | .proc_write	= nlm_end_grace_write, | 
|---|
| 65 | .proc_read	= nlm_end_grace_read, | 
|---|
| 66 | .proc_lseek	= default_llseek, | 
|---|
| 67 | .proc_release	= simple_transaction_release, | 
|---|
| 68 | }; | 
|---|
| 69 |  | 
|---|
| 70 | int __init | 
|---|
| 71 | lockd_create_procfs(void) | 
|---|
| 72 | { | 
|---|
| 73 | struct proc_dir_entry *entry; | 
|---|
| 74 |  | 
|---|
| 75 | entry = proc_mkdir( "fs/lockd", NULL); | 
|---|
| 76 | if (!entry) | 
|---|
| 77 | return -ENOMEM; | 
|---|
| 78 | entry = proc_create(name: "nlm_end_grace", S_IRUGO|S_IWUSR, parent: entry, | 
|---|
| 79 | proc_ops: &lockd_end_grace_proc_ops); | 
|---|
| 80 | if (!entry) { | 
|---|
| 81 | remove_proc_entry( "fs/lockd", NULL); | 
|---|
| 82 | return -ENOMEM; | 
|---|
| 83 | } | 
|---|
| 84 | return 0; | 
|---|
| 85 | } | 
|---|
| 86 |  | 
|---|
| 87 | void __exit | 
|---|
| 88 | lockd_remove_procfs(void) | 
|---|
| 89 | { | 
|---|
| 90 | remove_proc_entry( "fs/lockd/nlm_end_grace", NULL); | 
|---|
| 91 | remove_proc_entry( "fs/lockd", NULL); | 
|---|
| 92 | } | 
|---|
| 93 |  | 
|---|