Skip to content

Commit 507df40

Browse files
committed
NFSD: Hoist rq_vec preparation into nfsd_read()
Accrue the following benefits: a) Deduplicate this common bit of code. b) Don't prepare rq_vec for NFSv2 and NFSv3 spliced reads, which don't use rq_vec. This is already the case for nfsd4_encode_read(). c) Eventually, converting NFSD's read path to use a bvec iterator will be simpler. In the next patch, nfsd_iter_read() will replace nfsd_readv() for all NFS versions. Signed-off-by: Chuck Lever <[email protected]>
1 parent ed4a567 commit 507df40

File tree

4 files changed

+68
-36
lines changed

4 files changed

+68
-36
lines changed

fs/nfsd/nfs3proc.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
151151
{
152152
struct nfsd3_readargs *argp = rqstp->rq_argp;
153153
struct nfsd3_readres *resp = rqstp->rq_resp;
154-
unsigned int len;
155-
int v;
156154

157155
dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
158156
SVCFH_fmt(&argp->fh),
@@ -166,17 +164,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
166164
if (argp->offset + argp->count > (u64)OFFSET_MAX)
167165
argp->count = (u64)OFFSET_MAX - argp->offset;
168166

169-
v = 0;
170-
len = argp->count;
171167
resp->pages = rqstp->rq_next_page;
172-
while (len > 0) {
173-
struct page *page = *(rqstp->rq_next_page++);
174-
175-
rqstp->rq_vec[v].iov_base = page_address(page);
176-
rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
177-
len -= rqstp->rq_vec[v].iov_len;
178-
v++;
179-
}
180168

181169
/* Obtain buffer pointer for payload.
182170
* 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
@@ -187,7 +175,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
187175

188176
fh_copy(&resp->fh, &argp->fh);
189177
resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
190-
rqstp->rq_vec, v, &resp->count, &resp->eof);
178+
&resp->count, &resp->eof);
191179
return rpc_success;
192180
}
193181

fs/nfsd/nfsproc.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
176176
{
177177
struct nfsd_readargs *argp = rqstp->rq_argp;
178178
struct nfsd_readres *resp = rqstp->rq_resp;
179-
unsigned int len;
180179
u32 eof;
181-
int v;
182180

183181
dprintk("nfsd: READ %s %d bytes at %d\n",
184182
SVCFH_fmt(&argp->fh),
@@ -187,17 +185,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
187185
argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);
188186
argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
189187

190-
v = 0;
191-
len = argp->count;
192188
resp->pages = rqstp->rq_next_page;
193-
while (len > 0) {
194-
struct page *page = *(rqstp->rq_next_page++);
195-
196-
rqstp->rq_vec[v].iov_base = page_address(page);
197-
rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
198-
len -= rqstp->rq_vec[v].iov_len;
199-
v++;
200-
}
201189

202190
/* Obtain buffer pointer for payload. 19 is 1 word for
203191
* status, 17 words for fattr, and 1 word for the byte count.
@@ -207,7 +195,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
207195
resp->count = argp->count;
208196
fh_copy(&resp->fh, &argp->fh);
209197
resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
210-
rqstp->rq_vec, v, &resp->count, &eof);
198+
&resp->count, &eof);
211199
if (resp->status == nfs_ok)
212200
resp->status = fh_getattr(&resp->fh, &resp->stat);
213201
else if (resp->status == nfserr_jukebox)

fs/nfsd/vfs.c

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,50 @@ __be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp,
10361036
return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err);
10371037
}
10381038

1039+
/**
1040+
* nfsd_iter_read - Perform a VFS read using an iterator
1041+
* @rqstp: RPC transaction context
1042+
* @fhp: file handle of file to be read
1043+
* @file: opened struct file of file to be read
1044+
* @offset: starting byte offset
1045+
* @count: IN: requested number of bytes; OUT: number of bytes read
1046+
* @base: offset in first page of read buffer
1047+
* @eof: OUT: set non-zero if operation reached the end of the file
1048+
*
1049+
* Some filesystems or situations cannot use nfsd_splice_read. This
1050+
* function is the slightly less-performant fallback for those cases.
1051+
*
1052+
* Returns nfs_ok on success, otherwise an nfserr stat value is
1053+
* returned.
1054+
*/
1055+
__be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
1056+
struct file *file, loff_t offset, unsigned long *count,
1057+
unsigned int base, u32 *eof)
1058+
{
1059+
unsigned long v, total;
1060+
struct iov_iter iter;
1061+
loff_t ppos = offset;
1062+
struct page *page;
1063+
ssize_t host_err;
1064+
1065+
v = 0;
1066+
total = *count;
1067+
while (total) {
1068+
page = *(rqstp->rq_next_page++);
1069+
rqstp->rq_vec[v].iov_base = page_address(page) + base;
1070+
rqstp->rq_vec[v].iov_len = min_t(size_t, total, PAGE_SIZE - base);
1071+
total -= rqstp->rq_vec[v].iov_len;
1072+
++v;
1073+
base = 0;
1074+
}
1075+
WARN_ON_ONCE(v > ARRAY_SIZE(rqstp->rq_vec));
1076+
1077+
trace_nfsd_read_vector(rqstp, fhp, offset, *count);
1078+
iov_iter_kvec(&iter, ITER_DEST, rqstp->rq_vec, v, *count);
1079+
host_err = vfs_iter_read(file, &iter, &ppos, 0);
1080+
return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err);
1081+
}
1082+
10391083
/*
10401084
* Gathered writes: If another process is currently writing to the file,
10411085
* there's a high chance this is another nfsd (triggered by a bulk write
@@ -1161,14 +1205,24 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
11611205
return nfserr;
11621206
}
11631207

1164-
/*
1165-
* Read data from a file. count must contain the requested read count
1166-
* on entry. On return, *count contains the number of bytes actually read.
1208+
/**
1209+
* nfsd_read - Read data from a file
1210+
* @rqstp: RPC transaction context
1211+
* @fhp: file handle of file to be read
1212+
* @offset: starting byte offset
1213+
* @count: IN: requested number of bytes; OUT: number of bytes read
1214+
* @eof: OUT: set non-zero if operation reached the end of the file
1215+
*
1216+
* The caller must verify that there is enough space in @rqstp.rq_res
1217+
* to perform this operation.
1218+
*
11671219
* N.B. After this call fhp needs an fh_put
1220+
*
1221+
* Returns nfs_ok on success, otherwise an nfserr stat value is
1222+
* returned.
11681223
*/
11691224
__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
1170-
loff_t offset, struct kvec *vec, int vlen, unsigned long *count,
1171-
u32 *eof)
1225+
loff_t offset, unsigned long *count, u32 *eof)
11721226
{
11731227
struct nfsd_file *nf;
11741228
struct file *file;
@@ -1183,12 +1237,10 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
11831237
if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags))
11841238
err = nfsd_splice_read(rqstp, fhp, file, offset, count, eof);
11851239
else
1186-
err = nfsd_readv(rqstp, fhp, file, offset, vec, vlen, count, eof);
1240+
err = nfsd_iter_read(rqstp, fhp, file, offset, count, 0, eof);
11871241

11881242
nfsd_file_put(nf);
1189-
11901243
trace_nfsd_read_done(rqstp, fhp, offset, *count);
1191-
11921244
return err;
11931245
}
11941246

fs/nfsd/vfs.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,12 @@ __be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp,
115115
struct kvec *vec, int vlen,
116116
unsigned long *count,
117117
u32 *eof);
118-
__be32 nfsd_read(struct svc_rqst *, struct svc_fh *,
119-
loff_t, struct kvec *, int, unsigned long *,
118+
__be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
119+
struct file *file, loff_t offset,
120+
unsigned long *count, unsigned int base,
121+
u32 *eof);
122+
__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
123+
loff_t offset, unsigned long *count,
120124
u32 *eof);
121125
__be32 nfsd_write(struct svc_rqst *, struct svc_fh *, loff_t,
122126
struct kvec *, int, unsigned long *,

0 commit comments

Comments
 (0)