1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/debugfs.h>
4
5 #include "nfsd.h"
6
7 static struct dentry *nfsd_top_dir __read_mostly;
8
9 /*
10 * /sys/kernel/debug/nfsd/disable-splice-read
11 *
12 * Contents:
13 * %0: NFS READ is allowed to use page splicing
14 * %1: NFS READ uses only iov iter read
15 *
16 * The default value of this setting is zero (page splicing is
17 * allowed). This setting takes immediate effect for all NFS
18 * versions, all exports, and in all NFSD net namespaces.
19 */
20
nfsd_dsr_get(void * data,u64 * val)21 static int nfsd_dsr_get(void *data, u64 *val)
22 {
23 *val = nfsd_disable_splice_read ? 1 : 0;
24 return 0;
25 }
26
nfsd_dsr_set(void * data,u64 val)27 static int nfsd_dsr_set(void *data, u64 val)
28 {
29 nfsd_disable_splice_read = (val > 0);
30 if (!nfsd_disable_splice_read) {
31 /*
32 * Must use buffered I/O if splice_read is enabled.
33 */
34 nfsd_io_cache_read = NFSD_IO_BUFFERED;
35 }
36 return 0;
37 }
38
39 DEFINE_DEBUGFS_ATTRIBUTE(nfsd_dsr_fops, nfsd_dsr_get, nfsd_dsr_set, "%llu\n");
40
41 /*
42 * /sys/kernel/debug/nfsd/io_cache_read
43 *
44 * Contents:
45 * %0: NFS READ will use buffered IO
46 * %1: NFS READ will use dontcache (buffered IO w/ dropbehind)
47 *
48 * This setting takes immediate effect for all NFS versions,
49 * all exports, and in all NFSD net namespaces.
50 */
51
nfsd_io_cache_read_get(void * data,u64 * val)52 static int nfsd_io_cache_read_get(void *data, u64 *val)
53 {
54 *val = nfsd_io_cache_read;
55 return 0;
56 }
57
nfsd_io_cache_read_set(void * data,u64 val)58 static int nfsd_io_cache_read_set(void *data, u64 val)
59 {
60 int ret = 0;
61
62 switch (val) {
63 case NFSD_IO_BUFFERED:
64 nfsd_io_cache_read = NFSD_IO_BUFFERED;
65 break;
66 case NFSD_IO_DONTCACHE:
67 /*
68 * Must disable splice_read when enabling
69 * NFSD_IO_DONTCACHE.
70 */
71 nfsd_disable_splice_read = true;
72 nfsd_io_cache_read = val;
73 break;
74 default:
75 ret = -EINVAL;
76 break;
77 }
78
79 return ret;
80 }
81
82 DEFINE_DEBUGFS_ATTRIBUTE(nfsd_io_cache_read_fops, nfsd_io_cache_read_get,
83 nfsd_io_cache_read_set, "%llu\n");
84
85 /*
86 * /sys/kernel/debug/nfsd/io_cache_write
87 *
88 * Contents:
89 * %0: NFS WRITE will use buffered IO
90 * %1: NFS WRITE will use dontcache (buffered IO w/ dropbehind)
91 *
92 * This setting takes immediate effect for all NFS versions,
93 * all exports, and in all NFSD net namespaces.
94 */
95
nfsd_io_cache_write_get(void * data,u64 * val)96 static int nfsd_io_cache_write_get(void *data, u64 *val)
97 {
98 *val = nfsd_io_cache_write;
99 return 0;
100 }
101
nfsd_io_cache_write_set(void * data,u64 val)102 static int nfsd_io_cache_write_set(void *data, u64 val)
103 {
104 int ret = 0;
105
106 switch (val) {
107 case NFSD_IO_BUFFERED:
108 case NFSD_IO_DONTCACHE:
109 nfsd_io_cache_write = val;
110 break;
111 default:
112 ret = -EINVAL;
113 break;
114 }
115
116 return ret;
117 }
118
119 DEFINE_DEBUGFS_ATTRIBUTE(nfsd_io_cache_write_fops, nfsd_io_cache_write_get,
120 nfsd_io_cache_write_set, "%llu\n");
121
nfsd_debugfs_exit(void)122 void nfsd_debugfs_exit(void)
123 {
124 debugfs_remove_recursive(nfsd_top_dir);
125 nfsd_top_dir = NULL;
126 }
127
nfsd_debugfs_init(void)128 void nfsd_debugfs_init(void)
129 {
130 nfsd_top_dir = debugfs_create_dir("nfsd", NULL);
131
132 debugfs_create_file("disable-splice-read", S_IWUSR | S_IRUGO,
133 nfsd_top_dir, NULL, &nfsd_dsr_fops);
134
135 debugfs_create_file("io_cache_read", 0644, nfsd_top_dir, NULL,
136 &nfsd_io_cache_read_fops);
137
138 debugfs_create_file("io_cache_write", 0644, nfsd_top_dir, NULL,
139 &nfsd_io_cache_write_fops);
140 }
141