Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
f5dcccd6
Commit
f5dcccd6
authored
Nov 14, 2020
by
Chuck Lever
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NFSD: Update the NFSv2 READDIR entry encoder to use struct xdr_stream
Signed-off-by:
Chuck Lever
<
chuck.lever@oracle.com
>
parent
94c8f8c6
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
103 additions
and
11 deletions
+103
-11
fs/nfsd/nfsproc.c
fs/nfsd/nfsproc.c
+19
-7
fs/nfsd/nfsxdr.c
fs/nfsd/nfsxdr.c
+77
-4
fs/nfsd/xdr.h
fs/nfsd/xdr.h
+7
-0
No files found.
fs/nfsd/nfsproc.c
View file @
f5dcccd6
...
...
@@ -559,14 +559,27 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,
struct
nfsd_readdirres
*
resp
,
int
count
)
{
struct
xdr_buf
*
buf
=
&
resp
->
dirlist
;
struct
xdr_stream
*
xdr
=
&
resp
->
xdr
;
count
=
min_t
(
u32
,
count
,
PAGE_SIZE
);
/* Convert byte count to number of words (i.e. >> 2),
* and reserve room for the NULL ptr & eof flag (-2 words) */
resp
->
buflen
=
(
count
>>
2
)
-
2
;
memset
(
buf
,
0
,
sizeof
(
*
buf
));
resp
->
buffer
=
page_address
(
*
rqstp
->
rq_next_page
);
/* Reserve room for the NULL ptr & eof flag (-2 words) */
buf
->
buflen
=
count
-
sizeof
(
__be32
)
*
2
;
buf
->
pages
=
rqstp
->
rq_next_page
;
rqstp
->
rq_next_page
++
;
/* This is xdr_init_encode(), but it assumes that
* the head kvec has already been consumed. */
xdr_set_scratch_buffer
(
xdr
,
NULL
,
0
);
xdr
->
buf
=
buf
;
xdr
->
page_ptr
=
buf
->
pages
;
xdr
->
iov
=
NULL
;
xdr
->
p
=
page_address
(
*
buf
->
pages
);
xdr
->
end
=
xdr
->
p
+
(
PAGE_SIZE
>>
2
);
xdr
->
rqst
=
NULL
;
}
/*
...
...
@@ -585,12 +598,11 @@ nfsd_proc_readdir(struct svc_rqst *rqstp)
nfsd_init_dirlist_pages
(
rqstp
,
resp
,
argp
->
count
);
resp
->
offset
=
NULL
;
resp
->
common
.
err
=
nfs_ok
;
/* Read directory and encode entries on the fly */
resp
->
cookie_offset
=
0
;
offset
=
argp
->
cookie
;
resp
->
status
=
nfsd_readdir
(
rqstp
,
&
argp
->
fh
,
&
offset
,
&
resp
->
common
,
nfssvc_encode_entry
);
&
resp
->
common
,
nfs
2
svc_encode_entry
);
nfssvc_encode_nfscookie
(
resp
,
offset
);
fh_put
(
&
argp
->
fh
);
...
...
fs/nfsd/nfsxdr.c
View file @
f5dcccd6
...
...
@@ -576,12 +576,13 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
{
struct
xdr_stream
*
xdr
=
&
rqstp
->
rq_res_stream
;
struct
nfsd_readdirres
*
resp
=
rqstp
->
rq_resp
;
struct
xdr_buf
*
dirlist
=
&
resp
->
dirlist
;
if
(
!
svcxdr_encode_stat
(
xdr
,
resp
->
status
))
return
0
;
switch
(
resp
->
status
)
{
case
nfs_ok
:
xdr_write_pages
(
xdr
,
&
resp
->
page
,
0
,
resp
->
count
<<
2
);
xdr_write_pages
(
xdr
,
dirlist
->
pages
,
0
,
dirlist
->
len
);
/* no more entries */
if
(
xdr_stream_encode_item_absent
(
xdr
)
<
0
)
return
0
;
...
...
@@ -623,14 +624,86 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
* @resp: readdir result context
* @offset: offset cookie to encode
*
* The buffer space for the offset cookie has already been reserved
* by svcxdr_encode_entry_common().
*/
void
nfssvc_encode_nfscookie
(
struct
nfsd_readdirres
*
resp
,
u32
offset
)
{
if
(
!
resp
->
offset
)
__be32
cookie
=
cpu_to_be32
(
offset
);
if
(
!
resp
->
cookie_offset
)
return
;
*
resp
->
offset
=
cpu_to_be32
(
offset
);
resp
->
offset
=
NULL
;
write_bytes_to_xdr_buf
(
&
resp
->
dirlist
,
resp
->
cookie_offset
,
&
cookie
,
sizeof
(
cookie
));
resp
->
cookie_offset
=
0
;
}
static
bool
svcxdr_encode_entry_common
(
struct
nfsd_readdirres
*
resp
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
)
{
struct
xdr_buf
*
dirlist
=
&
resp
->
dirlist
;
struct
xdr_stream
*
xdr
=
&
resp
->
xdr
;
if
(
xdr_stream_encode_item_present
(
xdr
)
<
0
)
return
false
;
/* fileid */
if
(
xdr_stream_encode_u32
(
xdr
,
(
u32
)
ino
)
<
0
)
return
false
;
/* name */
if
(
xdr_stream_encode_opaque
(
xdr
,
name
,
min
(
namlen
,
NFS2_MAXNAMLEN
))
<
0
)
return
false
;
/* cookie */
resp
->
cookie_offset
=
dirlist
->
len
;
if
(
xdr_stream_encode_u32
(
xdr
,
~
0U
)
<
0
)
return
false
;
return
true
;
}
/**
* nfs2svc_encode_entry - encode one NFSv2 READDIR entry
* @data: directory context
* @name: name of the object to be encoded
* @namlen: length of that name, in bytes
* @offset: the offset of the previous entry
* @ino: the fileid of this entry
* @d_type: unused
*
* Return values:
* %0: Entry was successfully encoded.
* %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
*
* On exit, the following fields are updated:
* - resp->xdr
* - resp->common.err
* - resp->cookie_offset
*/
int
nfs2svc_encode_entry
(
void
*
data
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
d_type
)
{
struct
readdir_cd
*
ccd
=
data
;
struct
nfsd_readdirres
*
resp
=
container_of
(
ccd
,
struct
nfsd_readdirres
,
common
);
unsigned
int
starting_length
=
resp
->
dirlist
.
len
;
/* The offset cookie for the previous entry */
nfssvc_encode_nfscookie
(
resp
,
offset
);
if
(
!
svcxdr_encode_entry_common
(
resp
,
name
,
namlen
,
offset
,
ino
))
goto
out_toosmall
;
xdr_commit_encode
(
&
resp
->
xdr
);
resp
->
common
.
err
=
nfs_ok
;
return
0
;
out_toosmall:
resp
->
cookie_offset
=
0
;
resp
->
common
.
err
=
nfserr_toosmall
;
resp
->
dirlist
.
len
=
starting_length
;
return
-
EINVAL
;
}
int
...
...
fs/nfsd/xdr.h
View file @
f5dcccd6
...
...
@@ -106,15 +106,20 @@ struct nfsd_readres {
};
struct
nfsd_readdirres
{
/* Components of the reply */
__be32
status
;
int
count
;
/* Used to encode the reply's entry list */
struct
xdr_stream
xdr
;
struct
xdr_buf
dirlist
;
struct
readdir_cd
common
;
__be32
*
buffer
;
int
buflen
;
__be32
*
offset
;
struct
page
*
page
;
unsigned
int
cookie_offset
;
};
struct
nfsd_statfsres
{
...
...
@@ -159,6 +164,8 @@ int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *);
int
nfssvc_encode_readdirres
(
struct
svc_rqst
*
,
__be32
*
);
void
nfssvc_encode_nfscookie
(
struct
nfsd_readdirres
*
resp
,
u32
offset
);
int
nfs2svc_encode_entry
(
void
*
data
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
d_type
);
int
nfssvc_encode_entry
(
void
*
,
const
char
*
name
,
int
namlen
,
loff_t
offset
,
u64
ino
,
unsigned
int
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment