Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
5cd3322f
Commit
5cd3322f
authored
Sep 15, 2009
by
Stephen Rothwell
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'nfsd/nfsd-next'
parents
bd997572
b5a14d78
Changes
37
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1523 additions
and
837 deletions
+1523
-837
fs/lockd/clntlock.c
fs/lockd/clntlock.c
+1
-1
fs/lockd/host.c
fs/lockd/host.c
+2
-2
fs/lockd/mon.c
fs/lockd/mon.c
+1
-1
fs/lockd/svcsubs.c
fs/lockd/svcsubs.c
+1
-1
fs/nfsd/export.c
fs/nfsd/export.c
+2
-0
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs3xdr.c
+36
-39
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4acl.c
+2
-2
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4callback.c
+211
-19
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4proc.c
+45
-44
fs/nfsd/nfs4state.c
fs/nfsd/nfs4state.c
+305
-355
fs/nfsd/nfs4xdr.c
fs/nfsd/nfs4xdr.c
+18
-24
fs/nfsd/nfsctl.c
fs/nfsd/nfsctl.c
+3
-5
fs/nfsd/nfsfh.c
fs/nfsd/nfsfh.c
+86
-72
fs/nfsd/nfssvc.c
fs/nfsd/nfssvc.c
+37
-13
include/linux/lockd/lockd.h
include/linux/lockd/lockd.h
+0
-43
include/linux/nfs4.h
include/linux/nfs4.h
+1
-1
include/linux/nfsd/nfsd.h
include/linux/nfsd/nfsd.h
+3
-0
include/linux/nfsd/state.h
include/linux/nfsd/state.h
+53
-22
include/linux/nfsd/xdr4.h
include/linux/nfsd/xdr4.h
+3
-16
include/linux/sunrpc/clnt.h
include/linux/sunrpc/clnt.h
+114
-0
include/linux/sunrpc/svc.h
include/linux/sunrpc/svc.h
+0
-2
include/linux/sunrpc/svc_xprt.h
include/linux/sunrpc/svc_xprt.h
+1
-0
include/linux/sunrpc/svcsock.h
include/linux/sunrpc/svcsock.h
+1
-0
include/linux/sunrpc/xprt.h
include/linux/sunrpc/xprt.h
+19
-0
include/linux/sunrpc/xprtrdma.h
include/linux/sunrpc/xprtrdma.h
+0
-5
include/linux/sunrpc/xprtsock.h
include/linux/sunrpc/xprtsock.h
+0
-11
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_gss/svcauth_gss.c
+4
-2
net/sunrpc/cache.c
net/sunrpc/cache.c
+50
-37
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+1
-0
net/sunrpc/sched.c
net/sunrpc/sched.c
+2
-5
net/sunrpc/sunrpc.h
net/sunrpc/sunrpc.h
+14
-0
net/sunrpc/svc_xprt.c
net/sunrpc/svc_xprt.c
+9
-16
net/sunrpc/svcauth_unix.c
net/sunrpc/svcauth_unix.c
+1
-0
net/sunrpc/svcsock.c
net/sunrpc/svcsock.c
+244
-91
net/sunrpc/xprt.c
net/sunrpc/xprt.c
+11
-4
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
+2
-2
net/sunrpc/xprtsock.c
net/sunrpc/xprtsock.c
+240
-2
No files found.
fs/lockd/clntlock.c
View file @
5cd3322f
...
...
@@ -166,7 +166,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
*/
if
(
fl_blocked
->
fl_u
.
nfs_fl
.
owner
->
pid
!=
lock
->
svid
)
continue
;
if
(
!
nlm
_cmp_addr
(
nlm_addr
(
block
->
b_host
),
addr
))
if
(
!
rpc
_cmp_addr
(
nlm_addr
(
block
->
b_host
),
addr
))
continue
;
if
(
nfs_compare_fh
(
NFS_FH
(
fl_blocked
->
fl_file
->
f_path
.
dentry
->
d_inode
)
,
fh
)
!=
0
)
continue
;
...
...
fs/lockd/host.c
View file @
5cd3322f
...
...
@@ -111,7 +111,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
*/
chain
=
&
nlm_hosts
[
nlm_hash_address
(
ni
->
sap
)];
hlist_for_each_entry
(
host
,
pos
,
chain
,
h_hash
)
{
if
(
!
nlm
_cmp_addr
(
nlm_addr
(
host
),
ni
->
sap
))
if
(
!
rpc
_cmp_addr
(
nlm_addr
(
host
),
ni
->
sap
))
continue
;
/* See if we have an NSM handle for this client */
...
...
@@ -125,7 +125,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
if
(
host
->
h_server
!=
ni
->
server
)
continue
;
if
(
ni
->
server
&&
!
nlm
_cmp_addr
(
nlm_srcaddr
(
host
),
ni
->
src_sap
))
!
rpc
_cmp_addr
(
nlm_srcaddr
(
host
),
ni
->
src_sap
))
continue
;
/* Move to head of hash chain. */
...
...
fs/lockd/mon.c
View file @
5cd3322f
...
...
@@ -209,7 +209,7 @@ static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap)
struct
nsm_handle
*
nsm
;
list_for_each_entry
(
nsm
,
&
nsm_handles
,
sm_link
)
if
(
nlm
_cmp_addr
(
nsm_addr
(
nsm
),
sap
))
if
(
rpc
_cmp_addr
(
nsm_addr
(
nsm
),
sap
))
return
nsm
;
return
NULL
;
}
...
...
fs/lockd/svcsubs.c
View file @
5cd3322f
...
...
@@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
static
int
nlmsvc_match_ip
(
void
*
datap
,
struct
nlm_host
*
host
)
{
return
nlm
_cmp_addr
(
nlm_srcaddr
(
host
),
datap
);
return
rpc
_cmp_addr
(
nlm_srcaddr
(
host
),
datap
);
}
/**
...
...
fs/nfsd/export.c
View file @
5cd3322f
...
...
@@ -1341,6 +1341,8 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
if
(
rv
)
goto
out
;
rv
=
check_nfsd_access
(
exp
,
rqstp
);
if
(
rv
)
fh_put
(
fhp
);
out:
exp_put
(
exp
);
return
rv
;
...
...
fs/nfsd/nfs3xdr.c
View file @
5cd3322f
...
...
@@ -814,17 +814,6 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
return
p
;
}
static
__be32
*
encode_entryplus_baggage
(
struct
nfsd3_readdirres
*
cd
,
__be32
*
p
,
struct
svc_fh
*
fhp
)
{
p
=
encode_post_op_attr
(
cd
->
rqstp
,
p
,
fhp
);
*
p
++
=
xdr_one
;
/* yes, a file handle follows */
p
=
encode_fh
(
p
,
fhp
);
fh_put
(
fhp
);
return
p
;
}
static
int
compose_entry_fh
(
struct
nfsd3_readdirres
*
cd
,
struct
svc_fh
*
fhp
,
const
char
*
name
,
int
namlen
)
...
...
@@ -836,29 +825,54 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
dparent
=
cd
->
fh
.
fh_dentry
;
exp
=
cd
->
fh
.
fh_export
;
fh_init
(
fhp
,
NFS3_FHSIZE
);
if
(
isdotent
(
name
,
namlen
))
{
if
(
namlen
==
2
)
{
dchild
=
dget_parent
(
dparent
);
if
(
dchild
==
dparent
)
{
/* filesystem root - cannot return filehandle for ".." */
dput
(
dchild
);
return
1
;
return
-
ENOENT
;
}
}
else
dchild
=
dget
(
dparent
);
}
else
dchild
=
lookup_one_len
(
name
,
dparent
,
namlen
);
if
(
IS_ERR
(
dchild
))
return
1
;
if
(
d_mountpoint
(
dchild
)
||
fh_compose
(
fhp
,
exp
,
dchild
,
&
cd
->
fh
)
!=
0
||
!
dchild
->
d_inode
)
rv
=
1
;
return
-
ENOENT
;
rv
=
-
ENOENT
;
if
(
d_mountpoint
(
dchild
))
goto
out
;
rv
=
fh_compose
(
fhp
,
exp
,
dchild
,
&
cd
->
fh
);
if
(
rv
)
goto
out
;
if
(
!
dchild
->
d_inode
)
goto
out
;
rv
=
0
;
out:
dput
(
dchild
);
return
rv
;
}
__be32
*
encode_entryplus_baggage
(
struct
nfsd3_readdirres
*
cd
,
__be32
*
p
,
const
char
*
name
,
int
namlen
)
{
struct
svc_fh
fh
;
int
err
;
fh_init
(
&
fh
,
NFS3_FHSIZE
);
err
=
compose_entry_fh
(
cd
,
&
fh
,
name
,
namlen
);
if
(
err
)
{
*
p
++
=
0
;
*
p
++
=
0
;
goto
out
;
}
p
=
encode_post_op_attr
(
cd
->
rqstp
,
p
,
&
fh
);
*
p
++
=
xdr_one
;
/* yes, a file handle follows */
p
=
encode_fh
(
p
,
&
fh
);
out:
fh_put
(
&
fh
);
return
p
;
}
/*
* Encode a directory entry. This one works for both normal readdir
* and readdirplus.
...
...
@@ -929,16 +943,8 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
p
=
encode_entry_baggage
(
cd
,
p
,
name
,
namlen
,
ino
);
/* throw in readdirplus baggage */
if
(
plus
)
{
struct
svc_fh
fh
;
if
(
compose_entry_fh
(
cd
,
&
fh
,
name
,
namlen
)
>
0
)
{
*
p
++
=
0
;
*
p
++
=
0
;
}
else
p
=
encode_entryplus_baggage
(
cd
,
p
,
&
fh
);
}
if
(
plus
)
p
=
encode_entryplus_baggage
(
cd
,
p
,
name
,
namlen
);
num_entry_words
=
p
-
cd
->
buffer
;
}
else
if
(
cd
->
rqstp
->
rq_respages
[
pn
+
1
]
!=
NULL
)
{
/* temporarily encode entry into next page, then move back to
...
...
@@ -951,17 +957,8 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
p1
=
encode_entry_baggage
(
cd
,
p1
,
name
,
namlen
,
ino
);
/* throw in readdirplus baggage */
if
(
plus
)
{
struct
svc_fh
fh
;
if
(
compose_entry_fh
(
cd
,
&
fh
,
name
,
namlen
)
>
0
)
{
/* zero out the filehandle */
*
p1
++
=
0
;
*
p1
++
=
0
;
}
else
p1
=
encode_entryplus_baggage
(
cd
,
p1
,
&
fh
);
}
if
(
plus
)
p
=
encode_entryplus_baggage
(
cd
,
p1
,
name
,
namlen
);
/* determine entry word length and lengths to go in pages */
num_entry_words
=
p1
-
tmp
;
...
...
fs/nfsd/nfs4acl.c
View file @
5cd3322f
...
...
@@ -321,7 +321,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
deny
=
~
pas
.
group
&
pas
.
other
;
if
(
deny
)
{
ace
->
type
=
NFS4_ACE_ACCESS_DENIED_ACE_TYPE
;
ace
->
flag
=
eflag
|
NFS4_ACE_IDENTIFIER_GROUP
;
ace
->
flag
=
eflag
;
ace
->
access_mask
=
deny_mask_from_posix
(
deny
,
flags
);
ace
->
whotype
=
NFS4_ACL_WHO_GROUP
;
ace
++
;
...
...
@@ -335,7 +335,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
if
(
deny
)
{
ace
->
type
=
NFS4_ACE_ACCESS_DENIED_ACE_TYPE
;
ace
->
flag
=
eflag
|
NFS4_ACE_IDENTIFIER_GROUP
;
ace
->
access_mask
=
mask_from_posix
(
deny
,
flags
);
ace
->
access_mask
=
deny_
mask_from_posix
(
deny
,
flags
);
ace
->
whotype
=
NFS4_ACL_WHO_NAMED
;
ace
->
who
=
pa
->
e_id
;
ace
++
;
...
...
fs/nfsd/nfs4callback.c
View file @
5cd3322f
This diff is collapsed.
Click to expand it.
fs/nfsd/nfs4proc.c
View file @
5cd3322f
...
...
@@ -68,7 +68,6 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
u32
*
bmval
,
u32
*
writable
)
{
struct
dentry
*
dentry
=
cstate
->
current_fh
.
fh_dentry
;
struct
svc_export
*
exp
=
cstate
->
current_fh
.
fh_export
;
/*
* Check about attributes are supported by the NFSv4 server or not.
...
...
@@ -80,17 +79,13 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return
nfserr_attrnotsupp
;
/*
* Check FATTR4_WORD0_ACL
& FATTR4_WORD0_FS_LOCATIONS
can be supported
* Check FATTR4_WORD0_ACL can be supported
* in current environment or not.
*/
if
(
bmval
[
0
]
&
FATTR4_WORD0_ACL
)
{
if
(
!
IS_POSIXACL
(
dentry
->
d_inode
))
return
nfserr_attrnotsupp
;
}
if
(
bmval
[
0
]
&
FATTR4_WORD0_FS_LOCATIONS
)
{
if
(
exp
->
ex_fslocs
.
locations
==
NULL
)
return
nfserr_attrnotsupp
;
}
/*
* According to spec, read-only attributes return ERR_INVAL.
...
...
@@ -123,6 +118,35 @@ nfsd4_check_open_attributes(struct svc_rqst *rqstp,
return
status
;
}
static
int
is_create_with_attrs
(
struct
nfsd4_open
*
open
)
{
return
open
->
op_create
==
NFS4_OPEN_CREATE
&&
(
open
->
op_createmode
==
NFS4_CREATE_UNCHECKED
||
open
->
op_createmode
==
NFS4_CREATE_GUARDED
||
open
->
op_createmode
==
NFS4_CREATE_EXCLUSIVE4_1
);
}
/*
* if error occurs when setting the acl, just clear the acl bit
* in the returned attr bitmap.
*/
static
void
do_set_nfs4_acl
(
struct
svc_rqst
*
rqstp
,
struct
svc_fh
*
fhp
,
struct
nfs4_acl
*
acl
,
u32
*
bmval
)
{
__be32
status
;
status
=
nfsd4_set_nfs4_acl
(
rqstp
,
fhp
,
acl
);
if
(
status
)
/*
* We should probably fail the whole open at this point,
* but we've already created the file, so it's too late;
* So this seems the least of evils:
*/
bmval
[
0
]
&=
~
FATTR4_WORD0_ACL
;
}
static
inline
void
fh_dup2
(
struct
svc_fh
*
dst
,
struct
svc_fh
*
src
)
{
...
...
@@ -206,6 +230,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
if
(
status
)
goto
out
;
if
(
is_create_with_attrs
(
open
)
&&
open
->
op_acl
!=
NULL
)
do_set_nfs4_acl
(
rqstp
,
&
resfh
,
open
->
op_acl
,
open
->
op_bmval
);
set_change_info
(
&
open
->
op_cinfo
,
current_fh
);
fh_dup2
(
current_fh
,
&
resfh
);
...
...
@@ -536,12 +563,17 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
status
=
nfserr_badtype
;
}
if
(
!
status
)
{
fh_unlock
(
&
cstate
->
current_fh
);
set_change_info
(
&
create
->
cr_cinfo
,
&
cstate
->
current_fh
);
fh_dup2
(
&
cstate
->
current_fh
,
&
resfh
);
}
if
(
status
)
goto
out
;
if
(
create
->
cr_acl
!=
NULL
)
do_set_nfs4_acl
(
rqstp
,
&
resfh
,
create
->
cr_acl
,
create
->
cr_bmval
);
fh_unlock
(
&
cstate
->
current_fh
);
set_change_info
(
&
create
->
cr_cinfo
,
&
cstate
->
current_fh
);
fh_dup2
(
&
cstate
->
current_fh
,
&
resfh
);
out:
fh_put
(
&
resfh
);
return
status
;
}
...
...
@@ -946,34 +978,6 @@ static struct nfsd4_operation nfsd4_ops[];
static
const
char
*
nfsd4_op_name
(
unsigned
opnum
);
/*
* This is a replay of a compound for which no cache entry pages
* were used. Encode the sequence operation, and if cachethis is FALSE
* encode the uncache rep error on the next operation.
*/
static
__be32
nfsd4_enc_uncached_replay
(
struct
nfsd4_compoundargs
*
args
,
struct
nfsd4_compoundres
*
resp
)
{
struct
nfsd4_op
*
op
;
dprintk
(
"--> %s resp->opcnt %d ce_cachethis %u
\n
"
,
__func__
,
resp
->
opcnt
,
resp
->
cstate
.
slot
->
sl_cache_entry
.
ce_cachethis
);
/* Encode the replayed sequence operation */
BUG_ON
(
resp
->
opcnt
!=
1
);
op
=
&
args
->
ops
[
resp
->
opcnt
-
1
];
nfsd4_encode_operation
(
resp
,
op
);
/*return nfserr_retry_uncached_rep in next operation. */
if
(
resp
->
cstate
.
slot
->
sl_cache_entry
.
ce_cachethis
==
0
)
{
op
=
&
args
->
ops
[
resp
->
opcnt
++
];
op
->
status
=
nfserr_retry_uncached_rep
;
nfsd4_encode_operation
(
resp
,
op
);
}
return
op
->
status
;
}
/*
* Enforce NFSv4.1 COMPOUND ordering rules.
*
...
...
@@ -1083,13 +1087,10 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
BUG_ON
(
op
->
status
==
nfs_ok
);
encode_op:
/* Only from SEQUENCE
or CREATE_SESSION
*/
/* Only from SEQUENCE */
if
(
resp
->
cstate
.
status
==
nfserr_replay_cache
)
{
dprintk
(
"%s NFS4.1 replay from cache
\n
"
,
__func__
);
if
(
nfsd4_not_cached
(
resp
))
status
=
nfsd4_enc_uncached_replay
(
args
,
resp
);
else
status
=
op
->
status
;
status
=
op
->
status
;
goto
out
;
}
if
(
op
->
status
==
nfserr_replay_me
)
{
...
...
fs/nfsd/nfs4state.c
View file @
5cd3322f
This diff is collapsed.
Click to expand it.
fs/nfsd/nfs4xdr.c
View file @
5cd3322f
...
...
@@ -1599,7 +1599,8 @@ static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
static
char
*
nfsd4_path
(
struct
svc_rqst
*
rqstp
,
struct
svc_export
*
exp
,
__be32
*
stat
)
{
struct
svc_fh
tmp_fh
;
char
*
path
,
*
rootpath
;
char
*
path
=
NULL
,
*
rootpath
;
size_t
rootlen
;
fh_init
(
&
tmp_fh
,
NFS4_FHSIZE
);
*
stat
=
exp_pseudoroot
(
rqstp
,
&
tmp_fh
);
...
...
@@ -1609,14 +1610,18 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *
path
=
exp
->
ex_pathname
;
if
(
strncmp
(
path
,
rootpath
,
strlen
(
rootpath
)))
{
rootlen
=
strlen
(
rootpath
);
if
(
strncmp
(
path
,
rootpath
,
rootlen
))
{
dprintk
(
"nfsd: fs_locations failed;"
"%s is not contained in %s
\n
"
,
path
,
rootpath
);
*
stat
=
nfserr_notsupp
;
return
NULL
;
path
=
NULL
;
goto
out
;
}
return
path
+
strlen
(
rootpath
);
path
+=
rootlen
;
out:
fh_put
(
&
tmp_fh
);
return
path
;
}
/*
...
...
@@ -1793,11 +1798,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
goto
out_nfserr
;
}
}
if
(
bmval0
&
FATTR4_WORD0_FS_LOCATIONS
)
{
if
(
exp
->
ex_fslocs
.
locations
==
NULL
)
{
bmval0
&=
~
FATTR4_WORD0_FS_LOCATIONS
;
}
}
if
((
buflen
-=
16
)
<
0
)
goto
out_resource
;
...
...
@@ -1825,8 +1825,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
goto
out_resource
;
if
(
!
aclsupport
)
word0
&=
~
FATTR4_WORD0_ACL
;
if
(
!
exp
->
ex_fslocs
.
locations
)
word0
&=
~
FATTR4_WORD0_FS_LOCATIONS
;
if
(
!
word2
)
{
WRITE32
(
2
);
WRITE32
(
word0
);
...
...
@@ -3064,6 +3062,7 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
WRITE32
(
0
);
ADJUST_ARGS
();
resp
->
cstate
.
datap
=
p
;
/* DRC cache data pointer */
return
0
;
}
...
...
@@ -3166,7 +3165,7 @@ static int nfsd4_check_drc_limit(struct nfsd4_compoundres *resp)
return
status
;
session
=
resp
->
cstate
.
session
;
if
(
session
==
NULL
||
slot
->
sl_cache
_entry
.
ce_cache
this
==
0
)
if
(
session
==
NULL
||
slot
->
sl_cachethis
==
0
)
return
status
;
if
(
resp
->
opcnt
>=
args
->
opcnt
)
...
...
@@ -3291,6 +3290,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
/*
* All that remains is to write the tag and operation count...
*/
struct
nfsd4_compound_state
*
cs
=
&
resp
->
cstate
;
struct
kvec
*
iov
;
p
=
resp
->
tagp
;
*
p
++
=
htonl
(
resp
->
taglen
);
...
...
@@ -3304,17 +3304,11 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
iov
=
&
rqstp
->
rq_res
.
head
[
0
];
iov
->
iov_len
=
((
char
*
)
resp
->
p
)
-
(
char
*
)
iov
->
iov_base
;
BUG_ON
(
iov
->
iov_len
>
PAGE_SIZE
);
if
(
nfsd4_has_session
(
&
resp
->
cstate
))
{
if
(
resp
->
cstate
.
status
==
nfserr_replay_cache
&&
!
nfsd4_not_cached
(
resp
))
{
iov
->
iov_len
=
resp
->
cstate
.
iovlen
;
}
else
{
nfsd4_store_cache_entry
(
resp
);
dprintk
(
"%s: SET SLOT STATE TO AVAILABLE
\n
"
,
__func__
);
resp
->
cstate
.
slot
->
sl_inuse
=
0
;
}
if
(
resp
->
cstate
.
session
)
nfsd4_put_session
(
resp
->
cstate
.
session
);
if
(
nfsd4_has_session
(
cs
)
&&
cs
->
status
!=
nfserr_replay_cache
)
{
nfsd4_store_cache_entry
(
resp
);
dprintk
(
"%s: SET SLOT STATE TO AVAILABLE
\n
"
,
__func__
);
resp
->
cstate
.
slot
->
sl_inuse
=
false
;
nfsd4_put_session
(
resp
->
cstate
.
session
);
}
return
1
;
}
...
...
fs/nfsd/nfsctl.c
View file @
5cd3322f
...
...
@@ -174,12 +174,13 @@ static const struct file_operations exports_operations = {
};
extern
int
nfsd_pool_stats_open
(
struct
inode
*
inode
,
struct
file
*
file
);
extern
int
nfsd_pool_stats_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
struct
file_operations
pool_stats_operations
=
{
.
open
=
nfsd_pool_stats_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq
_release
,
.
release
=
nfsd_pool_stats
_release
,
.
owner
=
THIS_MODULE
,
};
...
...
@@ -776,10 +777,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
size
-=
len
;
mesg
+=
len
;
}
mutex_unlock
(
&
nfsd_mutex
);
return
(
mesg
-
buf
);
rv
=
mesg
-
buf
;
out_free:
kfree
(
nthreads
);
mutex_unlock
(
&
nfsd_mutex
);
...
...
fs/nfsd/nfsfh.c
View file @
5cd3322f
...
...
@@ -397,44 +397,51 @@ static inline void _fh_update_old(struct dentry *dentry,
fh
->
ofh_dirino
=
0
;
}
__be32
fh_compose
(
struct
svc_fh
*
fhp
,
struct
svc_export
*
exp
,
struct
dentry
*
dentry
,
struct
svc_fh
*
ref_fh
)
static
bool
is_root_export
(
struct
svc_export
*
exp
)
{
/* ref_fh is a reference file handle.
* if it is non-null and for the same filesystem, then we should compose
* a filehandle which is of the same version, where possible.
* Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
* Then create a 32byte filehandle using nfs_fhbase_old
*
*/
return
exp
->
ex_path
.
dentry
==
exp
->
ex_path
.
dentry
->
d_sb
->
s_root
;
}
u8
version
;
u8
fsid_type
=
0
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
dentry
*
parent
=
dentry
->
d_parent
;
__u32
*
datap
;
dev_t
ex_dev
=
exp
->
ex_path
.
dentry
->
d_inode
->
i_sb
->
s_dev
;
int
root_export
=
(
exp
->
ex_path
.
dentry
==
exp
->
ex_path
.
dentry
->
d_sb
->
s_root
);
static
struct
super_block
*
exp_sb
(
struct
svc_export
*
exp
)
{
return
exp
->
ex_path
.
dentry
->
d_inode
->
i_sb
;
}
dprintk
(
"nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)
\n
"
,
MAJOR
(
ex_dev
),
MINOR
(
ex_dev
),
(
long
)
exp
->
ex_path
.
dentry
->
d_inode
->
i_ino
,
parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
(
inode
?
inode
->
i_ino
:
0
));
static
bool
fsid_type_ok_for_exp
(
u8
fsid_type
,
struct
svc_export
*
exp
)
{
switch
(
fsid_type
)
{
case
FSID_DEV
:
if
(
!
old_valid_dev
(
exp_sb
(
exp
)
->
s_dev
))
return
0
;
/* FALL THROUGH */
case
FSID_MAJOR_MINOR
:
case
FSID_ENCODE_DEV
:
return
exp_sb
(
exp
)
->
s_type
->
fs_flags
&
FS_REQUIRES_DEV
;
case
FSID_NUM
:
return
exp
->
ex_flags
&
NFSEXP_FSID
;
case
FSID_UUID8
:
case
FSID_UUID16
:
if
(
!
is_root_export
(
exp
))
return
0
;
/* fall through */
case
FSID_UUID4_INUM
:
case
FSID_UUID16_INUM
:
return
exp
->
ex_uuid
!=
NULL
;
}
return
1
;
}
/* Choose filehandle version and fsid type based on
* the reference filehandle (if it is in the same export)
* or the export options.
*/
retry:
static
void
set_version_and_fsid_type
(
struct
svc_fh
*
fhp
,
struct
svc_export
*
exp
,
struct
svc_fh
*
ref_fh
)
{
u8
version
;
u8
fsid_type
;
retry:
version
=
1
;
if
(
ref_fh
&&
ref_fh
->
fh_export
==
exp
)
{
version
=
ref_fh
->
fh_handle
.
fh_version
;
fsid_type
=
ref_fh
->
fh_handle
.
fh_fsid_type
;
if
(
ref_fh
==
fhp
)
fh_put
(
ref_fh
);
ref_fh
=
NULL
;
switch
(
version
)
{
...
...
@@ -447,58 +454,66 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
goto
retry
;
}
/* Need to check that this type works for this
* export point. As the fsid -> filesystem mapping
* was guided by user-space, there is no guarantee
* that the filesystem actually supports that fsid
* type. If it doesn't we loop around again without
* ref_fh set.
/*
* As the fsid -> filesystem mapping was guided by
* user-space, there is no guarantee that the filesystem
* actually supports that fsid type. If it doesn't we
* loop around again without ref_fh set.
*/
switch
(
fsid_type
)
{
case
FSID_DEV
:
if
(
!
old_valid_dev
(
ex_dev
))
goto
retry
;
/* FALL THROUGH */
case
FSID_MAJOR_MINOR
:
case
FSID_ENCODE_DEV
:
if
(
!
(
exp
->
ex_path
.
dentry
->
d_inode
->
i_sb
->
s_type
->
fs_flags
&
FS_REQUIRES_DEV
))
goto
retry
;
break
;
case
FSID_NUM
:
if
(
!
(
exp
->
ex_flags
&
NFSEXP_FSID
))
goto
retry
;
break
;
case
FSID_UUID8
:
case
FSID_UUID16
:
if
(
!
root_export
)
goto
retry
;
/* fall through */
case
FSID_UUID4_INUM
:
case
FSID_UUID16_INUM
:
if
(
exp
->
ex_uuid
==
NULL
)
goto
retry
;
break
;
}
if
(
!
fsid_type_ok_for_exp
(
fsid_type
,
exp
))
goto
retry
;
}
else
if
(
exp
->
ex_flags
&
NFSEXP_FSID
)
{
fsid_type
=
FSID_NUM
;
}
else
if
(
exp
->
ex_uuid
)
{
if
(
fhp
->
fh_maxsize
>=
64
)
{
if
(
root_export
)
if
(
is_root_export
(
exp
)
)
fsid_type
=
FSID_UUID16
;
else
fsid_type
=
FSID_UUID16_INUM
;
}
else
{
if
(
root_export
)
if
(
is_root_export
(
exp
)
)
fsid_type
=
FSID_UUID8
;
else
fsid_type
=
FSID_UUID4_INUM
;
}
}
else
if
(
!
old_valid_dev
(
ex_dev
))
}
else
if
(
!
old_valid_dev
(
ex
p_sb
(
exp
)
->
s
_dev
))
/* for newer device numbers, we must use a newer fsid format */
fsid_type
=
FSID_ENCODE_DEV
;
else
fsid_type
=
FSID_DEV
;
fhp
->
fh_handle
.
fh_version
=
version
;
if
(
version
)
fhp
->
fh_handle
.
fh_fsid_type
=
fsid_type
;
}
__be32
fh_compose
(
struct
svc_fh
*
fhp
,
struct
svc_export
*
exp
,
struct
dentry
*
dentry
,
struct
svc_fh
*
ref_fh
)
{
/* ref_fh is a reference file handle.
* if it is non-null and for the same filesystem, then we should compose
* a filehandle which is of the same version, where possible.
* Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
* Then create a 32byte filehandle using nfs_fhbase_old
*
*/
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
dentry
*
parent
=
dentry
->
d_parent
;
__u32
*
datap
;
dev_t
ex_dev
=
exp_sb
(
exp
)
->
s_dev
;
dprintk
(
"nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)
\n
"
,
MAJOR
(
ex_dev
),
MINOR
(
ex_dev
),
(
long
)
exp
->
ex_path
.
dentry
->
d_inode
->
i_ino
,
parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
(
inode
?
inode
->
i_ino
:
0
));
/* Choose filehandle version and fsid type based on
* the reference filehandle (if it is in the same export)
* or the export options.
*/
set_version_and_fsid_type
(
fhp
,
exp
,
ref_fh
);
if
(
ref_fh
==
fhp
)
fh_put
(
ref_fh
);
...
...
@@ -516,7 +531,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
fhp
->
fh_export
=
exp
;
cache_get
(
&
exp
->
h
);
if
(
version
==
0xca
)
{
if
(
fhp
->
fh_handle
.
fh_
version
==
0xca
)
{
/* old style filehandle please */
memset
(
&
fhp
->
fh_handle
.
fh_base
,
0
,
NFS_FHSIZE
);
fhp
->
fh_handle
.
fh_size
=
NFS_FHSIZE
;
...
...
@@ -530,22 +545,22 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
_fh_update_old
(
dentry
,
exp
,
&
fhp
->
fh_handle
);
}
else
{
int
len
;
fhp
->
fh_handle
.
fh_version
=
1
;
fhp
->
fh_handle
.
fh_auth_type
=
0
;
datap
=
fhp
->
fh_handle
.
fh_auth
+
0
;
fhp
->
fh_handle
.
fh_fsid_type
=
fsid_type
;
mk_fsid
(
fsid_type
,
datap
,
ex_dev
,
mk_fsid
(
fhp
->
fh_handle
.
fh_fsid_type
,
datap
,
ex_dev
,
exp
->
ex_path
.
dentry
->
d_inode
->
i_ino
,
exp
->
ex_fsid
,
exp
->
ex_uuid
);
len
=
key_len
(
fsid_type
);
len
=
key_len
(
f
hp
->
fh_handle
.
fh_f
sid_type
);
datap
+=
len
/
4
;
fhp
->
fh_handle
.
fh_size
=
4
+
len
;
if
(
inode
)
_fh_update
(
fhp
,
exp
,
dentry
);
if
(
fhp
->
fh_handle
.
fh_fileid_type
==
255
)
if
(
fhp
->
fh_handle
.
fh_fileid_type
==
255
)
{
fh_put
(
fhp
);
return
nfserr_opnotsupp
;
}
}
return
0
;
...
...
@@ -639,8 +654,7 @@ enum fsid_source fsid_source(struct svc_fh *fhp)
case
FSID_DEV
:
case
FSID_ENCODE_DEV
:
case
FSID_MAJOR_MINOR
:
if
(
fhp
->
fh_export
->
ex_path
.
dentry
->
d_inode
->
i_sb
->
s_type
->
fs_flags
&
FS_REQUIRES_DEV
)
if
(
exp_sb
(
fhp
->
fh_export
)
->
s_type
->
fs_flags
&
FS_REQUIRES_DEV
)
return
FSIDSOURCE_DEV
;
break
;
case
FSID_NUM
:
...
...
fs/nfsd/nfssvc.c
View file @
5cd3322f
...
...
@@ -34,6 +34,7 @@
#include <linux/nfsd/syscall.h>
#include <linux/lockd/bind.h>
#include <linux/nfsacl.h>
#include <linux/seq_file.h>
#define NFSDDBG_FACILITY NFSDDBG_SVC
...
...
@@ -66,6 +67,16 @@ struct timeval nfssvc_boot;
DEFINE_MUTEX
(
nfsd_mutex
);
struct
svc_serv
*
nfsd_serv
;
/*
* nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
* nfsd_drc_max_pages limits the total amount of memory available for
* version 4.1 DRC caches.
* nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage.
*/
spinlock_t
nfsd_drc_lock
;
unsigned
int
nfsd_drc_max_mem
;
unsigned
int
nfsd_drc_mem_used
;
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
static
struct
svc_stat
nfsd_acl_svcstats
;
static
struct
svc_version
*
nfsd_acl_version
[]
=
{
...
...
@@ -235,13 +246,12 @@ void nfsd_reset_versions(void)
*/
static
void
set_max_drc
(
void
)
{
/* The percent of nr_free_buffer_pages used by the V4.1 server DRC */
#define NFSD_DRC_SIZE_SHIFT 7
nfsd_serv
->
sv_drc_max_pages
=
nr_free_buffer_pages
()
>>
NFSD_DRC_SIZE_SHIFT
;
nfsd_serv
->
sv_drc_pages_used
=
0
;
dprintk
(
"%s svc_drc_max_pages %u
\n
"
,
__func__
,
nfsd_serv
->
sv_drc_max_pages
);
#define NFSD_DRC_SIZE_SHIFT 10
nfsd_drc_max_mem
=
(
nr_free_buffer_pages
()
>>
NFSD_DRC_SIZE_SHIFT
)
*
PAGE_SIZE
;
nfsd_drc_mem_used
=
0
;
spin_lock_init
(
&
nfsd_drc_lock
);
dprintk
(
"%s nfsd_drc_max_mem %u
\n
"
,
__func__
,
nfsd_drc_max_mem
);
}
int
nfsd_create_serv
(
void
)
...
...
@@ -569,10 +579,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
+
rqstp
->
rq_res
.
head
[
0
].
iov_len
;
rqstp
->
rq_res
.
head
[
0
].
iov_len
+=
sizeof
(
__be32
);
/* NFSv4.1 DRC requires statp */
if
(
rqstp
->
rq_vers
==
4
)
nfsd4_set_statp
(
rqstp
,
statp
);
/* Now call the procedure handler, and encode NFS status. */
nfserr
=
proc
->
pc_func
(
rqstp
,
rqstp
->
rq_argp
,
rqstp
->
rq_resp
);
nfserr
=
map_new_errors
(
rqstp
->
rq_vers
,
nfserr
);
...
...
@@ -607,7 +613,25 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
int
nfsd_pool_stats_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
nfsd_serv
==
NULL
)
int
ret
;
mutex_lock
(
&
nfsd_mutex
);
if
(
nfsd_serv
==
NULL
)
{
mutex_unlock
(
&
nfsd_mutex
);
return
-
ENODEV
;
return
svc_pool_stats_open
(
nfsd_serv
,
file
);
}
/* bump up the psudo refcount while traversing */
svc_get
(
nfsd_serv
);
ret
=
svc_pool_stats_open
(
nfsd_serv
,
file
);
mutex_unlock
(
&
nfsd_mutex
);
return
ret
;
}
int
nfsd_pool_stats_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
ret
=
seq_release
(
inode
,
file
);
mutex_lock
(
&
nfsd_mutex
);
/* this function really, really should have been called svc_put() */
svc_destroy
(
nfsd_serv
);
mutex_unlock
(
&
nfsd_mutex
);
return
ret
;
}
include/linux/lockd/lockd.h
View file @
5cd3322f
...
...
@@ -338,49 +338,6 @@ static inline int nlm_privileged_requester(const struct svc_rqst *rqstp)
}
}
static
inline
int
__nlm_cmp_addr4
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
const
struct
sockaddr_in
*
sin1
=
(
const
struct
sockaddr_in
*
)
sap1
;
const
struct
sockaddr_in
*
sin2
=
(
const
struct
sockaddr_in
*
)
sap2
;
return
sin1
->
sin_addr
.
s_addr
==
sin2
->
sin_addr
.
s_addr
;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static
inline
int
__nlm_cmp_addr6
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
const
struct
sockaddr_in6
*
sin1
=
(
const
struct
sockaddr_in6
*
)
sap1
;
const
struct
sockaddr_in6
*
sin2
=
(
const
struct
sockaddr_in6
*
)
sap2
;
return
ipv6_addr_equal
(
&
sin1
->
sin6_addr
,
&
sin2
->
sin6_addr
);
}
#else
/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
static
inline
int
__nlm_cmp_addr6
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
return
0
;
}
#endif
/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
/*
* Compare two host addresses
*
* Return TRUE if the addresses are the same; otherwise FALSE.
*/
static
inline
int
nlm_cmp_addr
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
if
(
sap1
->
sa_family
==
sap2
->
sa_family
)
{
switch
(
sap1
->
sa_family
)
{
case
AF_INET
:
return
__nlm_cmp_addr4
(
sap1
,
sap2
);
case
AF_INET6
:
return
__nlm_cmp_addr6
(
sap1
,
sap2
);
}
}
return
0
;
}
/*
* Compare two NLM locks.
* When the second lock is of type F_UNLCK, this acts like a wildcard.
...
...
include/linux/nfs4.h
View file @
5cd3322f
...
...
@@ -234,7 +234,7 @@ enum nfs_opnum4 {
Needs to be updated if more operations are defined in future.*/
#define FIRST_NFS4_OP OP_ACCESS
#define LAST_NFS4_OP OP_RE
LEASE_LOCKOWNER
#define LAST_NFS4_OP OP_RE
CLAIM_COMPLETE
enum
nfsstat4
{
NFS4_OK
=
0
,
...
...
include/linux/nfsd/nfsd.h
View file @
5cd3322f
...
...
@@ -56,6 +56,9 @@ extern struct svc_version nfsd_version2, nfsd_version3,
extern
u32
nfsd_supported_minorversion
;
extern
struct
mutex
nfsd_mutex
;
extern
struct
svc_serv
*
nfsd_serv
;
extern
spinlock_t
nfsd_drc_lock
;
extern
unsigned
int
nfsd_drc_max_mem
;
extern
unsigned
int
nfsd_drc_mem_used
;
extern
struct
seq_operations
nfs_exports_op
;
...
...
include/linux/nfsd/state.h
View file @
5cd3322f
...
...
@@ -60,6 +60,12 @@ typedef struct {
#define si_stateownerid si_opaque.so_stateownerid
#define si_fileid si_opaque.so_fileid
struct
nfsd4_cb_sequence
{
/* args/res */
u32
cbs_minorversion
;
struct
nfs4_client
*
cbs_clp
;
};
struct
nfs4_delegation
{
struct
list_head
dl_perfile
;
struct
list_head
dl_perclnt
;
...
...
@@ -81,8 +87,8 @@ struct nfs4_delegation {
/* client delegation callback info */
struct
nfs4_cb_conn
{
/* SETCLIENTID info */
u32
cb_addr
;
unsigned
short
cb_port
;
struct
sockaddr_storage
cb_addr
;
size_t
cb_addrlen
;
u32
cb_prog
;
u32
cb_minorversion
;
u32
cb_ident
;
/* minorversion 0 only */
...
...
@@ -92,27 +98,25 @@ struct nfs4_cb_conn {
struct
rpc_cred
*
cb_cred
;
};
/* Maximum number of slots per session. 128 is useful for long haul TCP */
#define NFSD_MAX_SLOTS_PER_SESSION 128
/* Maximum number of pages per slot cache entry */
#define NFSD_PAGES_PER_SLOT 1
/* Maximum number of slots per session. 160 is useful for long haul TCP */
#define NFSD_MAX_SLOTS_PER_SESSION 160
/* Maximum number of operations per session compound */
#define NFSD_MAX_OPS_PER_COMPOUND 16
struct
nfsd4_cache_entry
{
__be32
ce_status
;
struct
kvec
ce_datav
;
/* encoded NFSv4.1 data in rq_res.head[0] */
struct
page
*
ce_respages
[
NFSD_PAGES_PER_SLOT
+
1
];
int
ce_cachethis
;
short
ce_resused
;
int
ce_opcnt
;
int
ce_rpchdrlen
;
};
/* Maximum session per slot cache size */
#define NFSD_SLOT_CACHE_SIZE 1024
/* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */
#define NFSD_CACHE_SIZE_SLOTS_PER_SESSION 32
#define NFSD_MAX_MEM_PER_SESSION \
(NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE)
struct
nfsd4_slot
{
bool
sl_inuse
;
u32
sl_seqid
;
struct
nfsd4_cache_entry
sl_cache_entry
;
bool
sl_inuse
;
bool
sl_cachethis
;
u16
sl_opcnt
;
u32
sl_seqid
;
__be32
sl_status
;
u32
sl_datalen
;
char
sl_data
[];
};
struct
nfsd4_channel_attrs
{
...
...
@@ -126,6 +130,25 @@ struct nfsd4_channel_attrs {
u32
rdma_attrs
;
};
struct
nfsd4_create_session
{
clientid_t
clientid
;
struct
nfs4_sessionid
sessionid
;
u32
seqid
;
u32
flags
;
struct
nfsd4_channel_attrs
fore_channel
;
struct
nfsd4_channel_attrs
back_channel
;
u32
callback_prog
;
u32
uid
;
u32
gid
;
};
/* The single slot clientid cache structure */
struct
nfsd4_clid_slot
{
u32
sl_seqid
;
__be32
sl_status
;
struct
nfsd4_create_session
sl_cr_ses
;
};
struct
nfsd4_session
{
struct
kref
se_ref
;
struct
list_head
se_hash
;
/* hash by sessionid */
...
...
@@ -135,7 +158,7 @@ struct nfsd4_session {
struct
nfs4_sessionid
se_sessionid
;
struct
nfsd4_channel_attrs
se_fchannel
;
struct
nfsd4_channel_attrs
se_bchannel
;
struct
nfsd4_slot
se_slots
[];
/* forward channel slots */
struct
nfsd4_slot
*
se_slots
[];
/* forward channel slots */
};
static
inline
void
...
...
@@ -180,7 +203,7 @@ struct nfs4_client {
char
cl_recdir
[
HEXDIR_LEN
];
/* recovery dir */
nfs4_verifier
cl_verifier
;
/* generated by client */
time_t
cl_time
;
/* time of last lease renewal */
__be32
cl_addr
;
/* client ipaddress */
struct
sockaddr_storage
cl_addr
;
/* client ipaddress */
u32
cl_flavor
;
/* setclientid pseudoflavor */
char
*
cl_principal
;
/* setclientid principal name */
struct
svc_cred
cl_cred
;
/* setclientid principal */
...
...
@@ -192,9 +215,17 @@ struct nfs4_client {
/* for nfs41 */
struct
list_head
cl_sessions
;
struct
nfsd4_
slot
cl
_slot
;
/* create_session slot */
struct
nfsd4_
clid_slot
cl_cs
_slot
;
/* create_session slot */
u32
cl_exchange_flags
;
struct
nfs4_sessionid
cl_sessionid
;
/* for nfs41 callbacks */
/* We currently support a single back channel with a single slot */
unsigned
long
cl_cb_slot_busy
;
u32
cl_cb_seq_nr
;
struct
svc_xprt
*
cl_cb_xprt
;
/* 4.1 callback transport */
struct
rpc_wait_queue
cl_cb_waitq
;
/* backchannel callers may */
/* wait here for slots */
};
/* struct nfs4_client_reset
...
...
include/linux/nfsd/xdr4.h
View file @
5cd3322f
...
...
@@ -51,7 +51,7 @@ struct nfsd4_compound_state {
/* For sessions DRC */
struct
nfsd4_session
*
session
;
struct
nfsd4_slot
*
slot
;
__be32
*
stat
p
;
__be32
*
data
p
;
size_t
iovlen
;
u32
minorversion
;
u32
status
;
...
...
@@ -366,18 +366,6 @@ struct nfsd4_exchange_id {
int
spa_how
;
};
struct
nfsd4_create_session
{
clientid_t
clientid
;
struct
nfs4_sessionid
sessionid
;
u32
seqid
;
u32
flags
;
struct
nfsd4_channel_attrs
fore_channel
;
struct
nfsd4_channel_attrs
back_channel
;
u32
callback_prog
;
u32
uid
;
u32
gid
;
};
struct
nfsd4_sequence
{
struct
nfs4_sessionid
sessionid
;
/* request/response */
u32
seqid
;
/* request/response */
...
...
@@ -479,13 +467,12 @@ struct nfsd4_compoundres {
static
inline
bool
nfsd4_is_solo_sequence
(
struct
nfsd4_compoundres
*
resp
)
{
struct
nfsd4_compoundargs
*
args
=
resp
->
rqstp
->
rq_argp
;
return
args
->
opcnt
==
1
;
return
resp
->
opcnt
==
1
&&
args
->
ops
[
0
].
opnum
==
OP_SEQUENCE
;
}
static
inline
bool
nfsd4_not_cached
(
struct
nfsd4_compoundres
*
resp
)
{
return
!
resp
->
cstate
.
slot
->
sl_cache_entry
.
ce_cachethis
||
nfsd4_is_solo_sequence
(
resp
);
return
!
resp
->
cstate
.
slot
->
sl_cachethis
||
nfsd4_is_solo_sequence
(
resp
);
}
#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
...
...
include/linux/sunrpc/clnt.h
View file @
5cd3322f
...
...
@@ -22,6 +22,7 @@
#include <linux/sunrpc/timer.h>
#include <asm/signal.h>
#include <linux/path.h>
#include <net/ipv6.h>
struct
rpc_inode
;
...
...
@@ -113,6 +114,7 @@ struct rpc_create_args {
rpc_authflavor_t
authflavor
;
unsigned
long
flags
;
char
*
client_name
;
struct
svc_xprt
*
bc_xprt
;
/* NFSv4.1 backchannel */
};
/* Values for "flags" field */
...
...
@@ -188,5 +190,117 @@ static inline void rpc_set_port(struct sockaddr *sap,
#define IPV6_SCOPE_DELIMITER '%'
#define IPV6_SCOPE_ID_LEN sizeof("%nnnnnnnnnn")
static
inline
bool
__rpc_cmp_addr4
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
const
struct
sockaddr_in
*
sin1
=
(
const
struct
sockaddr_in
*
)
sap1
;
const
struct
sockaddr_in
*
sin2
=
(
const
struct
sockaddr_in
*
)
sap2
;
return
sin1
->
sin_addr
.
s_addr
==
sin2
->
sin_addr
.
s_addr
;
}
static
inline
bool
__rpc_copy_addr4
(
struct
sockaddr
*
dst
,
const
struct
sockaddr
*
src
)
{
const
struct
sockaddr_in
*
ssin
=
(
struct
sockaddr_in
*
)
src
;
struct
sockaddr_in
*
dsin
=
(
struct
sockaddr_in
*
)
dst
;
dsin
->
sin_family
=
ssin
->
sin_family
;
dsin
->
sin_addr
.
s_addr
=
ssin
->
sin_addr
.
s_addr
;
return
true
;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static
inline
bool
__rpc_cmp_addr6
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
const
struct
sockaddr_in6
*
sin1
=
(
const
struct
sockaddr_in6
*
)
sap1
;
const
struct
sockaddr_in6
*
sin2
=
(
const
struct
sockaddr_in6
*
)
sap2
;
return
ipv6_addr_equal
(
&
sin1
->
sin6_addr
,
&
sin2
->
sin6_addr
);
}
static
inline
bool
__rpc_copy_addr6
(
struct
sockaddr
*
dst
,
const
struct
sockaddr
*
src
)
{
const
struct
sockaddr_in6
*
ssin6
=
(
const
struct
sockaddr_in6
*
)
src
;
struct
sockaddr_in6
*
dsin6
=
(
struct
sockaddr_in6
*
)
dst
;
dsin6
->
sin6_family
=
ssin6
->
sin6_family
;
ipv6_addr_copy
(
&
dsin6
->
sin6_addr
,
&
ssin6
->
sin6_addr
);
return
true
;
}
#else
/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
static
inline
bool
__rpc_cmp_addr6
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
return
false
;
}
static
inline
bool
__rpc_copy_addr6
(
struct
sockaddr
*
dst
,
const
struct
sockaddr
*
src
)
{
return
false
;
}
#endif
/* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */
/**
* rpc_cmp_addr - compare the address portion of two sockaddrs.
* @sap1: first sockaddr
* @sap2: second sockaddr
*
* Just compares the family and address portion. Ignores port, scope, etc.
* Returns true if the addrs are equal, false if they aren't.
*/
static
inline
bool
rpc_cmp_addr
(
const
struct
sockaddr
*
sap1
,
const
struct
sockaddr
*
sap2
)
{
if
(
sap1
->
sa_family
==
sap2
->
sa_family
)
{
switch
(
sap1
->
sa_family
)
{
case
AF_INET
:
return
__rpc_cmp_addr4
(
sap1
,
sap2
);
case
AF_INET6
:
return
__rpc_cmp_addr6
(
sap1
,
sap2
);
}
}
return
false
;
}
/**
* rpc_copy_addr - copy the address portion of one sockaddr to another
* @dst: destination sockaddr
* @src: source sockaddr
*
* Just copies the address portion and family. Ignores port, scope, etc.
* Caller is responsible for making certain that dst is large enough to hold
* the address in src. Returns true if address family is supported. Returns
* false otherwise.
*/
static
inline
bool
rpc_copy_addr
(
struct
sockaddr
*
dst
,
const
struct
sockaddr
*
src
)
{
switch
(
src
->
sa_family
)
{
case
AF_INET
:
return
__rpc_copy_addr4
(
dst
,
src
);
case
AF_INET6
:
return
__rpc_copy_addr6
(
dst
,
src
);
}
return
false
;
}
/**
* rpc_get_scope_id - return scopeid for a given sockaddr
* @sa: sockaddr to get scopeid from
*
* Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if
* not an AF_INET6 address.
*/
static
inline
u32
rpc_get_scope_id
(
const
struct
sockaddr
*
sa
)
{
if
(
sa
->
sa_family
!=
AF_INET6
)
return
0
;
return
((
struct
sockaddr_in6
*
)
sa
)
->
sin6_scope_id
;
}
#endif
/* __KERNEL__ */
#endif
/* _LINUX_SUNRPC_CLNT_H */
include/linux/sunrpc/svc.h
View file @
5cd3322f
...
...
@@ -94,8 +94,6 @@ struct svc_serv {
struct
module
*
sv_module
;
/* optional module to count when
* adding threads */
svc_thread_fn
sv_function
;
/* main function for threads */
unsigned
int
sv_drc_max_pages
;
/* Total pages for DRC */
unsigned
int
sv_drc_pages_used
;
/* DRC pages used */
#if defined(CONFIG_NFS_V4_1)
struct
list_head
sv_cb_list
;
/* queue for callback requests
* that arrive over the same
...
...
include/linux/sunrpc/svc_xprt.h
View file @
5cd3322f
...
...
@@ -65,6 +65,7 @@ struct svc_xprt {
size_t
xpt_locallen
;
/* length of address */
struct
sockaddr_storage
xpt_remote
;
/* remote peer's address */
size_t
xpt_remotelen
;
/* length of address */
struct
rpc_wait_queue
xpt_bc_pending
;
/* backchannel wait queue */
};
int
svc_reg_xprt_class
(
struct
svc_xprt_class
*
);
...
...
include/linux/sunrpc/svcsock.h
View file @
5cd3322f
...
...
@@ -28,6 +28,7 @@ struct svc_sock {
/* private TCP part */
u32
sk_reclen
;
/* length of record */
u32
sk_tcplen
;
/* current read length */
struct
rpc_xprt
*
sk_bc_xprt
;
/* NFSv4.1 backchannel xprt */
};
/*
...
...
include/linux/sunrpc/xprt.h
View file @
5cd3322f
...
...
@@ -124,6 +124,23 @@ struct rpc_xprt_ops {
void
(
*
print_stats
)(
struct
rpc_xprt
*
xprt
,
struct
seq_file
*
seq
);
};
/*
* RPC transport identifiers
*
* To preserve compatibility with the historical use of raw IP protocol
* id's for transport selection, UDP and TCP identifiers are specified
* with the previous values. No such restriction exists for new transports,
* except that they may not collide with these values (17 and 6,
* respectively).
*/
#define XPRT_TRANSPORT_BC (1 << 31)
enum
xprt_transports
{
XPRT_TRANSPORT_UDP
=
IPPROTO_UDP
,
XPRT_TRANSPORT_TCP
=
IPPROTO_TCP
,
XPRT_TRANSPORT_BC_TCP
=
IPPROTO_TCP
|
XPRT_TRANSPORT_BC
,
XPRT_TRANSPORT_RDMA
=
256
};
struct
rpc_xprt
{
struct
kref
kref
;
/* Reference count */
struct
rpc_xprt_ops
*
ops
;
/* transport methods */
...
...
@@ -179,6 +196,7 @@ struct rpc_xprt {
spinlock_t
reserve_lock
;
/* lock slot table */
u32
xid
;
/* Next XID value to use */
struct
rpc_task
*
snd_task
;
/* Task blocked in send */
struct
svc_xprt
*
bc_xprt
;
/* NFSv4.1 backchannel */
#if defined(CONFIG_NFS_V4_1)
struct
svc_serv
*
bc_serv
;
/* The RPC service which will */
/* process the callback */
...
...
@@ -231,6 +249,7 @@ struct xprt_create {
struct
sockaddr
*
srcaddr
;
/* optional local address */
struct
sockaddr
*
dstaddr
;
/* remote peer address */
size_t
addrlen
;
struct
svc_xprt
*
bc_xprt
;
/* NFSv4.1 backchannel */
};
struct
xprt_class
{
...
...
include/linux/sunrpc/xprtrdma.h
View file @
5cd3322f
...
...
@@ -40,11 +40,6 @@
#ifndef _LINUX_SUNRPC_XPRTRDMA_H
#define _LINUX_SUNRPC_XPRTRDMA_H
/*
* RPC transport identifier for RDMA
*/
#define XPRT_TRANSPORT_RDMA 256
/*
* rpcbind (v3+) RDMA netid.
*/
...
...
include/linux/sunrpc/xprtsock.h
View file @
5cd3322f
...
...
@@ -12,17 +12,6 @@
int
init_socket_xprt
(
void
);
void
cleanup_socket_xprt
(
void
);
/*
* RPC transport identifiers for UDP, TCP
*
* To preserve compatibility with the historical use of raw IP protocol
* id's for transport selection, these are specified with the previous
* values. No such restriction exists for new transports, except that
* they may not collide with these values (17 and 6, respectively).
*/
#define XPRT_TRANSPORT_UDP IPPROTO_UDP
#define XPRT_TRANSPORT_TCP IPPROTO_TCP
/*
* RPC slot table sizes for UDP, TCP transports
*/
...
...
net/sunrpc/auth_gss/svcauth_gss.c
View file @
5cd3322f
...
...
@@ -1374,8 +1374,10 @@ svcauth_gss_release(struct svc_rqst *rqstp)
if
(
stat
)
goto
out_err
;
break
;
default:
goto
out_err
;
/*
* For any other gc_svc value, svcauth_gss_accept() already set
* the auth_error appropriately; just fall through:
*/
}
out:
...
...
net/sunrpc/cache.c
View file @
5cd3322f
...
...
@@ -103,23 +103,21 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
EXPORT_SYMBOL_GPL
(
sunrpc_cache_lookup
);
static
void
queue_loos
e
(
struct
cache_detail
*
detail
,
struct
cache_head
*
ch
);
static
void
cache_dequeu
e
(
struct
cache_detail
*
detail
,
struct
cache_head
*
ch
);
static
int
cache_fresh_locked
(
struct
cache_head
*
head
,
time_t
expiry
)
static
void
cache_fresh_locked
(
struct
cache_head
*
head
,
time_t
expiry
)
{
head
->
expiry_time
=
expiry
;
head
->
last_refresh
=
get_seconds
();
return
!
test_and_
set_bit
(
CACHE_VALID
,
&
head
->
flags
);
set_bit
(
CACHE_VALID
,
&
head
->
flags
);
}
static
void
cache_fresh_unlocked
(
struct
cache_head
*
head
,
struct
cache_detail
*
detail
,
int
new
)
struct
cache_detail
*
detail
)
{
if
(
new
)
cache_revisit_request
(
head
);
if
(
test_and_clear_bit
(
CACHE_PENDING
,
&
head
->
flags
))
{
cache_revisit_request
(
head
);
queue_loos
e
(
detail
,
head
);
cache_dequeu
e
(
detail
,
head
);
}
}
...
...
@@ -132,7 +130,6 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
*/
struct
cache_head
**
head
;
struct
cache_head
*
tmp
;
int
is_new
;
if
(
!
test_bit
(
CACHE_VALID
,
&
old
->
flags
))
{
write_lock
(
&
detail
->
hash_lock
);
...
...
@@ -141,9 +138,9 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
set_bit
(
CACHE_NEGATIVE
,
&
old
->
flags
);
else
detail
->
update
(
old
,
new
);
is_new
=
cache_fresh_locked
(
old
,
new
->
expiry_time
);
cache_fresh_locked
(
old
,
new
->
expiry_time
);
write_unlock
(
&
detail
->
hash_lock
);
cache_fresh_unlocked
(
old
,
detail
,
is_new
);
cache_fresh_unlocked
(
old
,
detail
);
return
old
;
}
write_unlock
(
&
detail
->
hash_lock
);
...
...
@@ -167,11 +164,11 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
*
head
=
tmp
;
detail
->
entries
++
;
cache_get
(
tmp
);
is_new
=
cache_fresh_locked
(
tmp
,
new
->
expiry_time
);
cache_fresh_locked
(
tmp
,
new
->
expiry_time
);
cache_fresh_locked
(
old
,
0
);
write_unlock
(
&
detail
->
hash_lock
);
cache_fresh_unlocked
(
tmp
,
detail
,
is_new
);
cache_fresh_unlocked
(
old
,
detail
,
0
);
cache_fresh_unlocked
(
tmp
,
detail
);
cache_fresh_unlocked
(
old
,
detail
);
cache_put
(
old
,
detail
);
return
tmp
;
}
...
...
@@ -184,6 +181,22 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)
return
cd
->
cache_upcall
(
cd
,
h
);
}
static
inline
int
cache_is_valid
(
struct
cache_detail
*
detail
,
struct
cache_head
*
h
)
{
if
(
!
test_bit
(
CACHE_VALID
,
&
h
->
flags
)
||
h
->
expiry_time
<
get_seconds
())
return
-
EAGAIN
;
else
if
(
detail
->
flush_time
>
h
->
last_refresh
)
return
-
EAGAIN
;
else
{
/* entry is valid */
if
(
test_bit
(
CACHE_NEGATIVE
,
&
h
->
flags
))
return
-
ENOENT
;
else
return
0
;
}
}
/*
* This is the generic cache management routine for all
* the authentication caches.
...
...
@@ -192,8 +205,10 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)
*
*
* Returns 0 if the cache_head can be used, or cache_puts it and returns
* -EAGAIN if upcall is pending,
* -ETIMEDOUT if upcall failed and should be retried,
* -EAGAIN if upcall is pending and request has been queued
* -ETIMEDOUT if upcall failed or request could not be queue or
* upcall completed but item is still invalid (implying that
* the cache item has been replaced with a newer one).
* -ENOENT if cache entry was negative
*/
int
cache_check
(
struct
cache_detail
*
detail
,
...
...
@@ -203,17 +218,7 @@ int cache_check(struct cache_detail *detail,
long
refresh_age
,
age
;
/* First decide return status as best we can */
if
(
!
test_bit
(
CACHE_VALID
,
&
h
->
flags
)
||
h
->
expiry_time
<
get_seconds
())
rv
=
-
EAGAIN
;
else
if
(
detail
->
flush_time
>
h
->
last_refresh
)
rv
=
-
EAGAIN
;
else
{
/* entry is valid */
if
(
test_bit
(
CACHE_NEGATIVE
,
&
h
->
flags
))
rv
=
-
ENOENT
;
else
rv
=
0
;
}
rv
=
cache_is_valid
(
detail
,
h
);
/* now see if we want to start an upcall */
refresh_age
=
(
h
->
expiry_time
-
h
->
last_refresh
);
...
...
@@ -229,10 +234,11 @@ int cache_check(struct cache_detail *detail,
switch
(
cache_make_upcall
(
detail
,
h
))
{
case
-
EINVAL
:
clear_bit
(
CACHE_PENDING
,
&
h
->
flags
);
cache_revisit_request
(
h
);
if
(
rv
==
-
EAGAIN
)
{
set_bit
(
CACHE_NEGATIVE
,
&
h
->
flags
);
cache_fresh_
unlocked
(
h
,
detail
,
cache_fresh_locked
(
h
,
get_seconds
()
+
CACHE_NEW_EXPIRY
)
);
cache_fresh_
locked
(
h
,
get_seconds
()
+
CACHE_NEW_EXPIRY
);
cache_fresh_unlocked
(
h
,
detail
);
rv
=
-
ENOENT
;
}
break
;
...
...
@@ -245,10 +251,14 @@ int cache_check(struct cache_detail *detail,
}
}
if
(
rv
==
-
EAGAIN
)
if
(
cache_defer_req
(
rqstp
,
h
)
!=
0
)
rv
=
-
ETIMEDOUT
;
if
(
rv
==
-
EAGAIN
)
{
if
(
cache_defer_req
(
rqstp
,
h
)
<
0
)
{
/* Request is not deferred */
rv
=
cache_is_valid
(
detail
,
h
);
if
(
rv
==
-
EAGAIN
)
rv
=
-
ETIMEDOUT
;
}
}
if
(
rv
)
cache_put
(
h
,
detail
);
return
rv
;
...
...
@@ -396,7 +406,7 @@ static int cache_clean(void)
)
continue
;
if
(
test_and_clear_bit
(
CACHE_PENDING
,
&
ch
->
flags
))
queue_loos
e
(
current_detail
,
ch
);
cache_dequeu
e
(
current_detail
,
ch
);
if
(
atomic_read
(
&
ch
->
ref
.
refcount
)
==
1
)
break
;
...
...
@@ -412,8 +422,10 @@ static int cache_clean(void)
if
(
!
ch
)
current_index
++
;
spin_unlock
(
&
cache_list_lock
);
if
(
ch
)
if
(
ch
)
{
cache_revisit_request
(
ch
);
cache_put
(
ch
,
d
);
}
}
else
spin_unlock
(
&
cache_list_lock
);
...
...
@@ -496,11 +508,11 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
* or continue and drop the oldest below
*/
if
(
net_random
()
&
1
)
return
-
E
TIMEDOUT
;
return
-
E
NOMEM
;
}
dreq
=
req
->
defer
(
req
);
if
(
dreq
==
NULL
)
return
-
E
TIMEDOUT
;
return
-
E
NOMEM
;
dreq
->
item
=
item
;
...
...
@@ -530,6 +542,7 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
if
(
!
test_bit
(
CACHE_PENDING
,
&
item
->
flags
))
{
/* must have just been validated... */
cache_revisit_request
(
item
);
return
-
EAGAIN
;
}
return
0
;
}
...
...
@@ -887,7 +900,7 @@ static int cache_release(struct inode *inode, struct file *filp,
static
void
queue_loos
e
(
struct
cache_detail
*
detail
,
struct
cache_head
*
ch
)
static
void
cache_dequeu
e
(
struct
cache_detail
*
detail
,
struct
cache_head
*
ch
)
{
struct
cache_queue
*
cq
;
spin_lock
(
&
queue_lock
);
...
...
net/sunrpc/clnt.c
View file @
5cd3322f
...
...
@@ -288,6 +288,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
.
srcaddr
=
args
->
saddress
,
.
dstaddr
=
args
->
address
,
.
addrlen
=
args
->
addrsize
,
.
bc_xprt
=
args
->
bc_xprt
,
};
char
servername
[
48
];
...
...
net/sunrpc/sched.c
View file @
5cd3322f
...
...
@@ -21,6 +21,8 @@
#include <linux/sunrpc/clnt.h>
#include "sunrpc.h"
#ifdef RPC_DEBUG
#define RPCDBG_FACILITY RPCDBG_SCHED
#define RPC_TASK_MAGIC_ID 0xf00baa
...
...
@@ -711,11 +713,6 @@ static void rpc_async_schedule(struct work_struct *work)
__rpc_execute
(
container_of
(
work
,
struct
rpc_task
,
u
.
tk_work
));
}
struct
rpc_buffer
{
size_t
len
;
char
data
[];
};
/**
* rpc_malloc - allocate an RPC buffer
* @task: RPC task that will use this buffer
...
...
net/sunrpc/sunrpc.h
View file @
5cd3322f
...
...
@@ -27,11 +27,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _NET_SUNRPC_SUNRPC_H
#define _NET_SUNRPC_SUNRPC_H
#include <linux/net.h>
/*
* Header for dynamically allocated rpc buffers.
*/
struct
rpc_buffer
{
size_t
len
;
char
data
[];
};
static
inline
int
rpc_reply_expected
(
struct
rpc_task
*
task
)
{
return
(
task
->
tk_msg
.
rpc_proc
!=
NULL
)
&&
(
task
->
tk_msg
.
rpc_proc
->
p_decode
!=
NULL
);
}
int
svc_send_common
(
struct
socket
*
sock
,
struct
xdr_buf
*
xdr
,
struct
page
*
headpage
,
unsigned
long
headoffset
,
struct
page
*
tailpage
,
unsigned
long
tailoffset
);
#endif
/* _NET_SUNRPC_SUNRPC_H */
net/sunrpc/svc_xprt.c
View file @
5cd3322f
...
...
@@ -160,6 +160,7 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
mutex_init
(
&
xprt
->
xpt_mutex
);
spin_lock_init
(
&
xprt
->
xpt_lock
);
set_bit
(
XPT_BUSY
,
&
xprt
->
xpt_flags
);
rpc_init_wait_queue
(
&
xprt
->
xpt_bc_pending
,
"xpt_bc_pending"
);
}
EXPORT_SYMBOL_GPL
(
svc_xprt_init
);
...
...
@@ -710,10 +711,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
spin_unlock_bh
(
&
pool
->
sp_lock
);
len
=
0
;
if
(
test_bit
(
XPT_CLOSE
,
&
xprt
->
xpt_flags
))
{
dprintk
(
"svc_recv: found XPT_CLOSE
\n
"
);
svc_delete_xprt
(
xprt
);
}
else
if
(
test_bit
(
XPT_LISTENER
,
&
xprt
->
xpt_flags
))
{
if
(
test_bit
(
XPT_LISTENER
,
&
xprt
->
xpt_flags
))
{
struct
svc_xprt
*
newxpt
;
newxpt
=
xprt
->
xpt_ops
->
xpo_accept
(
xprt
);
if
(
newxpt
)
{
...
...
@@ -739,7 +737,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
svc_xprt_received
(
newxpt
);
}
svc_xprt_received
(
xprt
);
}
else
{
}
else
if
(
!
test_bit
(
XPT_CLOSE
,
&
xprt
->
xpt_flags
))
{
dprintk
(
"svc: server %p, pool %u, transport %p, inuse=%d
\n
"
,
rqstp
,
pool
->
sp_id
,
xprt
,
atomic_read
(
&
xprt
->
xpt_ref
.
refcount
));
...
...
@@ -752,6 +750,11 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
dprintk
(
"svc: got len=%d
\n
"
,
len
);
}
if
(
test_bit
(
XPT_CLOSE
,
&
xprt
->
xpt_flags
))
{
dprintk
(
"svc_recv: found XPT_CLOSE
\n
"
);
svc_delete_xprt
(
xprt
);
}
/* No data, incomplete (TCP) read, or accept() */
if
(
len
==
0
||
len
==
-
EAGAIN
)
{
rqstp
->
rq_res
.
len
=
0
;
...
...
@@ -808,6 +811,7 @@ int svc_send(struct svc_rqst *rqstp)
else
len
=
xprt
->
xpt_ops
->
xpo_sendto
(
rqstp
);
mutex_unlock
(
&
xprt
->
xpt_mutex
);
rpc_wake_up
(
&
xprt
->
xpt_bc_pending
);
svc_xprt_release
(
rqstp
);
if
(
len
==
-
ECONNREFUSED
||
len
==
-
ENOTCONN
||
len
==
-
EAGAIN
)
...
...
@@ -1166,11 +1170,6 @@ static void *svc_pool_stats_start(struct seq_file *m, loff_t *pos)
dprintk
(
"svc_pool_stats_start, *pidx=%u
\n
"
,
pidx
);
lock_kernel
();
/* bump up the pseudo refcount while traversing */
svc_get
(
serv
);
unlock_kernel
();
if
(
!
pidx
)
return
SEQ_START_TOKEN
;
return
(
pidx
>
serv
->
sv_nrpools
?
NULL
:
&
serv
->
sv_pools
[
pidx
-
1
]);
...
...
@@ -1198,12 +1197,6 @@ static void *svc_pool_stats_next(struct seq_file *m, void *p, loff_t *pos)
static
void
svc_pool_stats_stop
(
struct
seq_file
*
m
,
void
*
p
)
{
struct
svc_serv
*
serv
=
m
->
private
;
lock_kernel
();
/* this function really, really should have been called svc_put() */
svc_destroy
(
serv
);
unlock_kernel
();
}
static
int
svc_pool_stats_show
(
struct
seq_file
*
m
,
void
*
p
)
...
...
net/sunrpc/svcauth_unix.c
View file @
5cd3322f
...
...
@@ -668,6 +668,7 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
case
0
:
*
gip
=
ug
->
gi
;
get_group_info
(
*
gip
);
cache_put
(
&
ug
->
h
,
&
unix_gid_cache
);
return
0
;
default:
return
-
EAGAIN
;
...
...
net/sunrpc/svcsock.c
View file @
5cd3322f
This diff is collapsed.
Click to expand it.
net/sunrpc/xprt.c
View file @
5cd3322f
...
...
@@ -832,6 +832,11 @@ static void xprt_timer(struct rpc_task *task)
spin_unlock_bh
(
&
xprt
->
transport_lock
);
}
static
inline
int
xprt_has_timer
(
struct
rpc_xprt
*
xprt
)
{
return
xprt
->
idle_timeout
!=
0
;
}
/**
* xprt_prepare_transmit - reserve the transport before sending a request
* @task: RPC task about to send a request
...
...
@@ -1013,7 +1018,7 @@ void xprt_release(struct rpc_task *task)
if
(
!
list_empty
(
&
req
->
rq_list
))
list_del
(
&
req
->
rq_list
);
xprt
->
last_used
=
jiffies
;
if
(
list_empty
(
&
xprt
->
recv
))
if
(
list_empty
(
&
xprt
->
recv
)
&&
xprt_has_timer
(
xprt
)
)
mod_timer
(
&
xprt
->
timer
,
xprt
->
last_used
+
xprt
->
idle_timeout
);
spin_unlock_bh
(
&
xprt
->
transport_lock
);
...
...
@@ -1082,8 +1087,11 @@ found:
#endif
/* CONFIG_NFS_V4_1 */
INIT_WORK
(
&
xprt
->
task_cleanup
,
xprt_autoclose
);
setup_timer
(
&
xprt
->
timer
,
xprt_init_autodisconnect
,
(
unsigned
long
)
xprt
);
if
(
xprt_has_timer
(
xprt
))
setup_timer
(
&
xprt
->
timer
,
xprt_init_autodisconnect
,
(
unsigned
long
)
xprt
);
else
init_timer
(
&
xprt
->
timer
);
xprt
->
last_used
=
jiffies
;
xprt
->
cwnd
=
RPC_INITCWND
;
xprt
->
bind_index
=
0
;
...
...
@@ -1102,7 +1110,6 @@ found:
dprintk
(
"RPC: created transport %p with %u slots
\n
"
,
xprt
,
xprt
->
max_reqs
);
return
xprt
;
}
...
...
net/sunrpc/xprtrdma/svc_rdma_transport.c
View file @
5cd3322f
...
...
@@ -730,12 +730,12 @@ static struct svc_rdma_fastreg_mr *rdma_alloc_frmr(struct svcxprt_rdma *xprt)
goto
err
;
mr
=
ib_alloc_fast_reg_mr
(
xprt
->
sc_pd
,
RPCSVC_MAXPAGES
);
if
(
!
mr
)
if
(
IS_ERR
(
mr
)
)
goto
err_free_frmr
;
pl
=
ib_alloc_fast_reg_page_list
(
xprt
->
sc_cm_id
->
device
,
RPCSVC_MAXPAGES
);
if
(
!
pl
)
if
(
IS_ERR
(
pl
)
)
goto
err_free_mr
;
frmr
->
mr
=
mr
;
...
...
net/sunrpc/xprtsock.c
View file @
5cd3322f
...
...
@@ -32,6 +32,7 @@
#include <linux/tcp.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/xprtsock.h>
#include <linux/file.h>
#ifdef CONFIG_NFS_V4_1
...
...
@@ -43,6 +44,7 @@
#include <net/udp.h>
#include <net/tcp.h>
#include "sunrpc.h"
/*
* xprtsock tunables
*/
...
...
@@ -2098,6 +2100,134 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
xprt
->
stat
.
bklog_u
);
}
/*
* Allocate a bunch of pages for a scratch buffer for the rpc code. The reason
* we allocate pages instead doing a kmalloc like rpc_malloc is because we want
* to use the server side send routines.
*/
void
*
bc_malloc
(
struct
rpc_task
*
task
,
size_t
size
)
{
struct
page
*
page
;
struct
rpc_buffer
*
buf
;
BUG_ON
(
size
>
PAGE_SIZE
-
sizeof
(
struct
rpc_buffer
));
page
=
alloc_page
(
GFP_KERNEL
);
if
(
!
page
)
return
NULL
;
buf
=
page_address
(
page
);
buf
->
len
=
PAGE_SIZE
;
return
buf
->
data
;
}
/*
* Free the space allocated in the bc_alloc routine
*/
void
bc_free
(
void
*
buffer
)
{
struct
rpc_buffer
*
buf
;
if
(
!
buffer
)
return
;
buf
=
container_of
(
buffer
,
struct
rpc_buffer
,
data
);
free_page
((
unsigned
long
)
buf
);
}
/*
* Use the svc_sock to send the callback. Must be called with svsk->sk_mutex
* held. Borrows heavily from svc_tcp_sendto and xs_tcp_send_request.
*/
static
int
bc_sendto
(
struct
rpc_rqst
*
req
)
{
int
len
;
struct
xdr_buf
*
xbufp
=
&
req
->
rq_snd_buf
;
struct
rpc_xprt
*
xprt
=
req
->
rq_xprt
;
struct
sock_xprt
*
transport
=
container_of
(
xprt
,
struct
sock_xprt
,
xprt
);
struct
socket
*
sock
=
transport
->
sock
;
unsigned
long
headoff
;
unsigned
long
tailoff
;
/*
* Set up the rpc header and record marker stuff
*/
xs_encode_tcp_record_marker
(
xbufp
);
tailoff
=
(
unsigned
long
)
xbufp
->
tail
[
0
].
iov_base
&
~
PAGE_MASK
;
headoff
=
(
unsigned
long
)
xbufp
->
head
[
0
].
iov_base
&
~
PAGE_MASK
;
len
=
svc_send_common
(
sock
,
xbufp
,
virt_to_page
(
xbufp
->
head
[
0
].
iov_base
),
headoff
,
xbufp
->
tail
[
0
].
iov_base
,
tailoff
);
if
(
len
!=
xbufp
->
len
)
{
printk
(
KERN_NOTICE
"Error sending entire callback!
\n
"
);
len
=
-
EAGAIN
;
}
return
len
;
}
/*
* The send routine. Borrows from svc_send
*/
static
int
bc_send_request
(
struct
rpc_task
*
task
)
{
struct
rpc_rqst
*
req
=
task
->
tk_rqstp
;
struct
svc_xprt
*
xprt
;
struct
svc_sock
*
svsk
;
u32
len
;
dprintk
(
"sending request with xid: %08x
\n
"
,
ntohl
(
req
->
rq_xid
));
/*
* Get the server socket associated with this callback xprt
*/
xprt
=
req
->
rq_xprt
->
bc_xprt
;
svsk
=
container_of
(
xprt
,
struct
svc_sock
,
sk_xprt
);
/*
* Grab the mutex to serialize data as the connection is shared
* with the fore channel
*/
if
(
!
mutex_trylock
(
&
xprt
->
xpt_mutex
))
{
rpc_sleep_on
(
&
xprt
->
xpt_bc_pending
,
task
,
NULL
);
if
(
!
mutex_trylock
(
&
xprt
->
xpt_mutex
))
return
-
EAGAIN
;
rpc_wake_up_queued_task
(
&
xprt
->
xpt_bc_pending
,
task
);
}
if
(
test_bit
(
XPT_DEAD
,
&
xprt
->
xpt_flags
))
len
=
-
ENOTCONN
;
else
len
=
bc_sendto
(
req
);
mutex_unlock
(
&
xprt
->
xpt_mutex
);
if
(
len
>
0
)
len
=
0
;
return
len
;
}
/*
* The close routine. Since this is client initiated, we do nothing
*/
static
void
bc_close
(
struct
rpc_xprt
*
xprt
)
{
return
;
}
/*
* The xprt destroy routine. Again, because this connection is client
* initiated, we do nothing
*/
static
void
bc_destroy
(
struct
rpc_xprt
*
xprt
)
{
return
;
}
static
struct
rpc_xprt_ops
xs_udp_ops
=
{
.
set_buffer_size
=
xs_udp_set_buffer_size
,
.
reserve_xprt
=
xprt_reserve_xprt_cong
,
...
...
@@ -2134,6 +2264,22 @@ static struct rpc_xprt_ops xs_tcp_ops = {
.
print_stats
=
xs_tcp_print_stats
,
};
/*
* The rpc_xprt_ops for the server backchannel
*/
static
struct
rpc_xprt_ops
bc_tcp_ops
=
{
.
reserve_xprt
=
xprt_reserve_xprt
,
.
release_xprt
=
xprt_release_xprt
,
.
buf_alloc
=
bc_malloc
,
.
buf_free
=
bc_free
,
.
send_request
=
bc_send_request
,
.
set_retrans_timeout
=
xprt_set_retrans_timeout_def
,
.
close
=
bc_close
,
.
destroy
=
bc_destroy
,
.
print_stats
=
xs_tcp_print_stats
,
};
static
struct
rpc_xprt
*
xs_setup_xprt
(
struct
xprt_create
*
args
,
unsigned
int
slot_table_size
)
{
...
...
@@ -2322,11 +2468,93 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
return
ERR_PTR
(
-
EINVAL
);
}
/**
* xs_setup_bc_tcp - Set up transport to use a TCP backchannel socket
* @args: rpc transport creation arguments
*
*/
static
struct
rpc_xprt
*
xs_setup_bc_tcp
(
struct
xprt_create
*
args
)
{
struct
sockaddr
*
addr
=
args
->
dstaddr
;
struct
rpc_xprt
*
xprt
;
struct
sock_xprt
*
transport
;
struct
svc_sock
*
bc_sock
;
if
(
!
args
->
bc_xprt
)
ERR_PTR
(
-
EINVAL
);
xprt
=
xs_setup_xprt
(
args
,
xprt_tcp_slot_table_entries
);
if
(
IS_ERR
(
xprt
))
return
xprt
;
transport
=
container_of
(
xprt
,
struct
sock_xprt
,
xprt
);
xprt
->
prot
=
IPPROTO_TCP
;
xprt
->
tsh_size
=
sizeof
(
rpc_fraghdr
)
/
sizeof
(
u32
);
xprt
->
max_payload
=
RPC_MAX_FRAGMENT_SIZE
;
xprt
->
timeout
=
&
xs_tcp_default_timeout
;
/* backchannel */
xprt_set_bound
(
xprt
);
xprt
->
bind_timeout
=
0
;
xprt
->
connect_timeout
=
0
;
xprt
->
reestablish_timeout
=
0
;
xprt
->
idle_timeout
=
0
;
/*
* The backchannel uses the same socket connection as the
* forechannel
*/
xprt
->
bc_xprt
=
args
->
bc_xprt
;
bc_sock
=
container_of
(
args
->
bc_xprt
,
struct
svc_sock
,
sk_xprt
);
bc_sock
->
sk_bc_xprt
=
xprt
;
transport
->
sock
=
bc_sock
->
sk_sock
;
transport
->
inet
=
bc_sock
->
sk_sk
;
xprt
->
ops
=
&
bc_tcp_ops
;
switch
(
addr
->
sa_family
)
{
case
AF_INET
:
xs_format_peer_addresses
(
xprt
,
"tcp"
,
RPCBIND_NETID_TCP
);
break
;
case
AF_INET6
:
xs_format_peer_addresses
(
xprt
,
"tcp"
,
RPCBIND_NETID_TCP6
);
break
;
default:
kfree
(
xprt
);
return
ERR_PTR
(
-
EAFNOSUPPORT
);
}
if
(
xprt_bound
(
xprt
))
dprintk
(
"RPC: set up xprt to %s (port %s) via %s
\n
"
,
xprt
->
address_strings
[
RPC_DISPLAY_ADDR
],
xprt
->
address_strings
[
RPC_DISPLAY_PORT
],
xprt
->
address_strings
[
RPC_DISPLAY_PROTO
]);
else
dprintk
(
"RPC: set up xprt to %s (autobind) via %s
\n
"
,
xprt
->
address_strings
[
RPC_DISPLAY_ADDR
],
xprt
->
address_strings
[
RPC_DISPLAY_PROTO
]);
/*
* Since we don't want connections for the backchannel, we set
* the xprt status to connected
*/
xprt_set_connected
(
xprt
);
if
(
try_module_get
(
THIS_MODULE
))
return
xprt
;
kfree
(
xprt
->
slot
);
kfree
(
xprt
);
return
ERR_PTR
(
-
EINVAL
);
}
static
struct
xprt_class
xs_udp_transport
=
{
.
list
=
LIST_HEAD_INIT
(
xs_udp_transport
.
list
),
.
name
=
"udp"
,
.
owner
=
THIS_MODULE
,
.
ident
=
IPPROTO
_UDP
,
.
ident
=
XPRT_TRANSPORT
_UDP
,
.
setup
=
xs_setup_udp
,
};
...
...
@@ -2334,10 +2562,18 @@ static struct xprt_class xs_tcp_transport = {
.
list
=
LIST_HEAD_INIT
(
xs_tcp_transport
.
list
),
.
name
=
"tcp"
,
.
owner
=
THIS_MODULE
,
.
ident
=
IPPROTO
_TCP
,
.
ident
=
XPRT_TRANSPORT
_TCP
,
.
setup
=
xs_setup_tcp
,
};
static
struct
xprt_class
xs_bc_tcp_transport
=
{
.
list
=
LIST_HEAD_INIT
(
xs_bc_tcp_transport
.
list
),
.
name
=
"tcp NFSv4.1 backchannel"
,
.
owner
=
THIS_MODULE
,
.
ident
=
XPRT_TRANSPORT_BC_TCP
,
.
setup
=
xs_setup_bc_tcp
,
};
/**
* init_socket_xprt - set up xprtsock's sysctls, register with RPC client
*
...
...
@@ -2351,6 +2587,7 @@ int init_socket_xprt(void)
xprt_register_transport
(
&
xs_udp_transport
);
xprt_register_transport
(
&
xs_tcp_transport
);
xprt_register_transport
(
&
xs_bc_tcp_transport
);
return
0
;
}
...
...
@@ -2370,6 +2607,7 @@ void cleanup_socket_xprt(void)
xprt_unregister_transport
(
&
xs_udp_transport
);
xprt_unregister_transport
(
&
xs_tcp_transport
);
xprt_unregister_transport
(
&
xs_bc_tcp_transport
);
}
static
int
param_set_uint_minmax
(
const
char
*
val
,
struct
kernel_param
*
kp
,
...
...
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