162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Procfs support for lockd
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/fs.h>
962306a36Sopenharmony_ci#include <linux/proc_fs.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/nsproxy.h>
1262306a36Sopenharmony_ci#include <net/net_namespace.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "netns.h"
1562306a36Sopenharmony_ci#include "procfs.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * We only allow strings that start with 'Y', 'y', or '1'.
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_cistatic ssize_t
2162306a36Sopenharmony_cinlm_end_grace_write(struct file *file, const char __user *buf, size_t size,
2262306a36Sopenharmony_ci		    loff_t *pos)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	char *data;
2562306a36Sopenharmony_ci	struct lockd_net *ln = net_generic(current->nsproxy->net_ns,
2662306a36Sopenharmony_ci					   lockd_net_id);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	if (size < 1)
2962306a36Sopenharmony_ci		return -EINVAL;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	data = simple_transaction_get(file, buf, size);
3262306a36Sopenharmony_ci	if (IS_ERR(data))
3362306a36Sopenharmony_ci		return PTR_ERR(data);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	switch(data[0]) {
3662306a36Sopenharmony_ci	case 'Y':
3762306a36Sopenharmony_ci	case 'y':
3862306a36Sopenharmony_ci	case '1':
3962306a36Sopenharmony_ci		locks_end_grace(&ln->lockd_manager);
4062306a36Sopenharmony_ci		break;
4162306a36Sopenharmony_ci	default:
4262306a36Sopenharmony_ci		return -EINVAL;
4362306a36Sopenharmony_ci	}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	return size;
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic ssize_t
4962306a36Sopenharmony_cinlm_end_grace_read(struct file *file, char __user *buf, size_t size,
5062306a36Sopenharmony_ci		   loff_t *pos)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	struct lockd_net *ln = net_generic(current->nsproxy->net_ns,
5362306a36Sopenharmony_ci					   lockd_net_id);
5462306a36Sopenharmony_ci	char resp[3];
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	resp[0] = list_empty(&ln->lockd_manager.list) ? 'Y' : 'N';
5762306a36Sopenharmony_ci	resp[1] = '\n';
5862306a36Sopenharmony_ci	resp[2] = '\0';
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp));
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic const struct proc_ops lockd_end_grace_proc_ops = {
6462306a36Sopenharmony_ci	.proc_write	= nlm_end_grace_write,
6562306a36Sopenharmony_ci	.proc_read	= nlm_end_grace_read,
6662306a36Sopenharmony_ci	.proc_lseek	= default_llseek,
6762306a36Sopenharmony_ci	.proc_release	= simple_transaction_release,
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ciint __init
7162306a36Sopenharmony_cilockd_create_procfs(void)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct proc_dir_entry *entry;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	entry = proc_mkdir("fs/lockd", NULL);
7662306a36Sopenharmony_ci	if (!entry)
7762306a36Sopenharmony_ci		return -ENOMEM;
7862306a36Sopenharmony_ci	entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry,
7962306a36Sopenharmony_ci			    &lockd_end_grace_proc_ops);
8062306a36Sopenharmony_ci	if (!entry) {
8162306a36Sopenharmony_ci		remove_proc_entry("fs/lockd", NULL);
8262306a36Sopenharmony_ci		return -ENOMEM;
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci	return 0;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_civoid __exit
8862306a36Sopenharmony_cilockd_remove_procfs(void)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	remove_proc_entry("fs/lockd/nlm_end_grace", NULL);
9162306a36Sopenharmony_ci	remove_proc_entry("fs/lockd", NULL);
9262306a36Sopenharmony_ci}
93