18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Procfs support for lockd
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/fs.h>
98c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/nsproxy.h>
128c2ecf20Sopenharmony_ci#include <net/net_namespace.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "netns.h"
158c2ecf20Sopenharmony_ci#include "procfs.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * We only allow strings that start with 'Y', 'y', or '1'.
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_cistatic ssize_t
218c2ecf20Sopenharmony_cinlm_end_grace_write(struct file *file, const char __user *buf, size_t size,
228c2ecf20Sopenharmony_ci		    loff_t *pos)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	char *data;
258c2ecf20Sopenharmony_ci	struct lockd_net *ln = net_generic(current->nsproxy->net_ns,
268c2ecf20Sopenharmony_ci					   lockd_net_id);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	if (size < 1)
298c2ecf20Sopenharmony_ci		return -EINVAL;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	data = simple_transaction_get(file, buf, size);
328c2ecf20Sopenharmony_ci	if (IS_ERR(data))
338c2ecf20Sopenharmony_ci		return PTR_ERR(data);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	switch(data[0]) {
368c2ecf20Sopenharmony_ci	case 'Y':
378c2ecf20Sopenharmony_ci	case 'y':
388c2ecf20Sopenharmony_ci	case '1':
398c2ecf20Sopenharmony_ci		locks_end_grace(&ln->lockd_manager);
408c2ecf20Sopenharmony_ci		break;
418c2ecf20Sopenharmony_ci	default:
428c2ecf20Sopenharmony_ci		return -EINVAL;
438c2ecf20Sopenharmony_ci	}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	return size;
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic ssize_t
498c2ecf20Sopenharmony_cinlm_end_grace_read(struct file *file, char __user *buf, size_t size,
508c2ecf20Sopenharmony_ci		   loff_t *pos)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	struct lockd_net *ln = net_generic(current->nsproxy->net_ns,
538c2ecf20Sopenharmony_ci					   lockd_net_id);
548c2ecf20Sopenharmony_ci	char resp[3];
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	resp[0] = list_empty(&ln->lockd_manager.list) ? 'Y' : 'N';
578c2ecf20Sopenharmony_ci	resp[1] = '\n';
588c2ecf20Sopenharmony_ci	resp[2] = '\0';
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp));
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic const struct proc_ops lockd_end_grace_proc_ops = {
648c2ecf20Sopenharmony_ci	.proc_write	= nlm_end_grace_write,
658c2ecf20Sopenharmony_ci	.proc_read	= nlm_end_grace_read,
668c2ecf20Sopenharmony_ci	.proc_lseek	= default_llseek,
678c2ecf20Sopenharmony_ci	.proc_release	= simple_transaction_release,
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciint __init
718c2ecf20Sopenharmony_cilockd_create_procfs(void)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	struct proc_dir_entry *entry;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	entry = proc_mkdir("fs/lockd", NULL);
768c2ecf20Sopenharmony_ci	if (!entry)
778c2ecf20Sopenharmony_ci		return -ENOMEM;
788c2ecf20Sopenharmony_ci	entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry,
798c2ecf20Sopenharmony_ci			    &lockd_end_grace_proc_ops);
808c2ecf20Sopenharmony_ci	if (!entry) {
818c2ecf20Sopenharmony_ci		remove_proc_entry("fs/lockd", NULL);
828c2ecf20Sopenharmony_ci		return -ENOMEM;
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci	return 0;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_civoid __exit
888c2ecf20Sopenharmony_cilockd_remove_procfs(void)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	remove_proc_entry("fs/lockd/nlm_end_grace", NULL);
918c2ecf20Sopenharmony_ci	remove_proc_entry("fs/lockd", NULL);
928c2ecf20Sopenharmony_ci}
93