Skip to content

Commit 6304aff

Browse files
Mike Snitzerchucklever
authored andcommitted
NFSD: Add io_cache_{read,write} controls to debugfs
Add 'io_cache_read' to NFSD's debugfs interface so that any data read by NFSD will either be: - cached using page cache (NFSD_IO_BUFFERED=0) - cached but removed from the page cache upon completion (NFSD_IO_DONTCACHE=1). io_cache_read may be set by writing to: /sys/kernel/debug/nfsd/io_cache_read Add 'io_cache_write' to NFSD's debugfs interface so that any data written by NFSD will either be: - cached using page cache (NFSD_IO_BUFFERED=0) - cached but removed from the page cache upon completion (NFSD_IO_DONTCACHE=1). io_cache_write may be set by writing to: /sys/kernel/debug/nfsd/io_cache_write The default value for both settings is NFSD_IO_BUFFERED, which is NFSD's existing behavior for both read and write. Changes to these settings take immediate effect for all exports and NFS versions. Currently only xfs and ext4 implement RWF_DONTCACHE. For file systems that do not implement RWF_DONTCACHE, NFSD use only buffered I/O when the io_cache setting is NFSD_IO_DONTCACHE. Signed-off-by: Mike Snitzer <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent d6e80d4 commit 6304aff

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

fs/nfsd/debugfs.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,98 @@ static int nfsd_dsr_get(void *data, u64 *val)
2727
static int nfsd_dsr_set(void *data, u64 val)
2828
{
2929
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+
}
3036
return 0;
3137
}
3238

3339
DEFINE_DEBUGFS_ATTRIBUTE(nfsd_dsr_fops, nfsd_dsr_get, nfsd_dsr_set, "%llu\n");
3440

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+
52+
static int nfsd_io_cache_read_get(void *data, u64 *val)
53+
{
54+
*val = nfsd_io_cache_read;
55+
return 0;
56+
}
57+
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+
96+
static int nfsd_io_cache_write_get(void *data, u64 *val)
97+
{
98+
*val = nfsd_io_cache_write;
99+
return 0;
100+
}
101+
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+
35122
void nfsd_debugfs_exit(void)
36123
{
37124
debugfs_remove_recursive(nfsd_top_dir);
@@ -44,4 +131,10 @@ void nfsd_debugfs_init(void)
44131

45132
debugfs_create_file("disable-splice-read", S_IWUSR | S_IRUGO,
46133
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);
47140
}

fs/nfsd/nfsd.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ static inline void nfsd_debugfs_exit(void) {}
153153

154154
extern bool nfsd_disable_splice_read __read_mostly;
155155

156+
enum {
157+
/* Any new NFSD_IO enum value must be added at the end */
158+
NFSD_IO_BUFFERED,
159+
NFSD_IO_DONTCACHE,
160+
};
161+
162+
extern u64 nfsd_io_cache_read __read_mostly;
163+
extern u64 nfsd_io_cache_write __read_mostly;
164+
156165
extern int nfsd_max_blksize;
157166

158167
static inline int nfsd_v4client(struct svc_rqst *rq)

fs/nfsd/vfs.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
5050

5151
bool nfsd_disable_splice_read __read_mostly;
52+
u64 nfsd_io_cache_read __read_mostly = NFSD_IO_BUFFERED;
53+
u64 nfsd_io_cache_write __read_mostly = NFSD_IO_BUFFERED;
5254

5355
/**
5456
* nfserrno - Map Linux errnos to NFS errnos
@@ -1099,6 +1101,16 @@ __be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
10991101
size_t len;
11001102

11011103
init_sync_kiocb(&kiocb, file);
1104+
1105+
switch (nfsd_io_cache_read) {
1106+
case NFSD_IO_BUFFERED:
1107+
break;
1108+
case NFSD_IO_DONTCACHE:
1109+
if (file->f_op->fop_flags & FOP_DONTCACHE)
1110+
kiocb.ki_flags = IOCB_DONTCACHE;
1111+
break;
1112+
}
1113+
11021114
kiocb.ki_pos = offset;
11031115

11041116
v = 0;
@@ -1224,6 +1236,15 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,
12241236
since = READ_ONCE(file->f_wb_err);
12251237
if (verf)
12261238
nfsd_copy_write_verifier(verf, nn);
1239+
1240+
switch (nfsd_io_cache_write) {
1241+
case NFSD_IO_BUFFERED:
1242+
break;
1243+
case NFSD_IO_DONTCACHE:
1244+
if (file->f_op->fop_flags & FOP_DONTCACHE)
1245+
kiocb.ki_flags |= IOCB_DONTCACHE;
1246+
break;
1247+
}
12271248
host_err = vfs_iocb_iter_write(file, &kiocb, &iter);
12281249
if (host_err < 0) {
12291250
commit_reset_write_verifier(nn, rqstp, host_err);

0 commit comments

Comments
 (0)