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
nexedi
linux
Commits
52c9948b
Commit
52c9948b
authored
Dec 13, 2009
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'nfs-for-2.6.33'
parents
f4054253
190f38e5
Changes
30
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
1078 additions
and
469 deletions
+1078
-469
fs/nfs/callback.c
fs/nfs/callback.c
+1
-12
fs/nfs/callback.h
fs/nfs/callback.h
+15
-1
fs/nfs/callback_proc.c
fs/nfs/callback_proc.c
+63
-1
fs/nfs/callback_xdr.c
fs/nfs/callback_xdr.c
+33
-1
fs/nfs/client.c
fs/nfs/client.c
+12
-2
fs/nfs/delegation.c
fs/nfs/delegation.c
+53
-24
fs/nfs/delegation.h
fs/nfs/delegation.h
+5
-2
fs/nfs/dir.c
fs/nfs/dir.c
+29
-38
fs/nfs/dns_resolve.c
fs/nfs/dns_resolve.c
+2
-2
fs/nfs/internal.h
fs/nfs/internal.h
+26
-28
fs/nfs/nfs4_fs.h
fs/nfs/nfs4_fs.h
+10
-2
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+287
-171
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+156
-69
fs/nfs/nfs4xdr.c
fs/nfs/nfs4xdr.c
+116
-19
fs/nfs/read.c
fs/nfs/read.c
+3
-9
fs/nfs/super.c
fs/nfs/super.c
+82
-22
fs/nfs/unlink.c
fs/nfs/unlink.c
+1
-1
fs/nfs/write.c
fs/nfs/write.c
+4
-4
include/linux/nfs4.h
include/linux/nfs4.h
+3
-0
include/linux/nfs_fs_sb.h
include/linux/nfs_fs_sb.h
+1
-0
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+12
-1
include/linux/sunrpc/sched.h
include/linux/sunrpc/sched.h
+2
-0
net/sunrpc/addr.c
net/sunrpc/addr.c
+1
-9
net/sunrpc/auth.c
net/sunrpc/auth.c
+23
-16
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/auth_gss.c
+3
-3
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+46
-8
net/sunrpc/rpcb_clnt.c
net/sunrpc/rpcb_clnt.c
+81
-23
net/sunrpc/sunrpc_syms.c
net/sunrpc/sunrpc_syms.c
+3
-0
net/sunrpc/xprt.c
net/sunrpc/xprt.c
+4
-0
net/sunrpc/xprtsock.c
net/sunrpc/xprtsock.c
+1
-1
No files found.
fs/nfs/callback.c
View file @
52c9948b
...
...
@@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp)
set_freezable
();
/*
* FIXME: do we really need to run this under the BKL? If so, please
* add a comment about what it's intended to protect.
*/
lock_kernel
();
while
(
!
kthread_should_stop
())
{
/*
* Listen for a request on the socket
...
...
@@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp)
preverr
=
err
;
svc_process
(
rqstp
);
}
unlock_kernel
();
return
0
;
}
...
...
@@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp)
set_freezable
();
/*
* FIXME: do we really need to run this under the BKL? If so, please
* add a comment about what it's intended to protect.
*/
lock_kernel
();
while
(
!
kthread_should_stop
())
{
prepare_to_wait
(
&
serv
->
sv_cb_waitq
,
&
wq
,
TASK_INTERRUPTIBLE
);
spin_lock_bh
(
&
serv
->
sv_cb_lock
);
...
...
@@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp)
}
finish_wait
(
&
serv
->
sv_cb_waitq
,
&
wq
);
}
unlock_kernel
();
return
0
;
}
...
...
@@ -397,6 +385,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
*/
static
struct
svc_version
*
nfs4_callback_version
[]
=
{
[
1
]
=
&
nfs4_callback_version1
,
[
4
]
=
&
nfs4_callback_version4
,
};
static
struct
svc_stat
nfs4_callback_stats
;
...
...
fs/nfs/callback.h
View file @
52c9948b
...
...
@@ -106,6 +106,19 @@ struct cb_sequenceres {
extern
unsigned
nfs4_callback_sequence
(
struct
cb_sequenceargs
*
args
,
struct
cb_sequenceres
*
res
);
extern
int
nfs41_validate_delegation_stateid
(
struct
nfs_delegation
*
delegation
,
const
nfs4_stateid
*
stateid
);
#define RCA4_TYPE_MASK_RDATA_DLG 0
#define RCA4_TYPE_MASK_WDATA_DLG 1
struct
cb_recallanyargs
{
struct
sockaddr
*
craa_addr
;
uint32_t
craa_objs_to_keep
;
uint32_t
craa_type_mask
;
};
extern
unsigned
nfs4_callback_recallany
(
struct
cb_recallanyargs
*
args
,
void
*
dummy
);
#endif
/* CONFIG_NFS_V4_1 */
extern
__be32
nfs4_callback_getattr
(
struct
cb_getattrargs
*
args
,
struct
cb_getattrres
*
res
);
...
...
@@ -114,8 +127,9 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
#ifdef CONFIG_NFS_V4
extern
int
nfs_callback_up
(
u32
minorversion
,
struct
rpc_xprt
*
xprt
);
extern
void
nfs_callback_down
(
int
minorversion
);
extern
int
nfs4_validate_delegation_stateid
(
struct
nfs_delegation
*
delegation
,
const
nfs4_stateid
*
stateid
);
#endif
/* CONFIG_NFS_V4 */
/*
* nfs41: Callbacks are expected to not cause substantial latency,
* so we limit their concurrency to 1 by setting up the maximum number
...
...
fs/nfs/callback_proc.c
View file @
52c9948b
...
...
@@ -61,6 +61,16 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *
return
res
->
status
;
}
static
int
(
*
nfs_validate_delegation_stateid
(
struct
nfs_client
*
clp
))(
struct
nfs_delegation
*
,
const
nfs4_stateid
*
)
{
#if defined(CONFIG_NFS_V4_1)
if
(
clp
->
cl_minorversion
>
0
)
return
nfs41_validate_delegation_stateid
;
#endif
return
nfs4_validate_delegation_stateid
;
}
__be32
nfs4_callback_recall
(
struct
cb_recallargs
*
args
,
void
*
dummy
)
{
struct
nfs_client
*
clp
;
...
...
@@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
inode
=
nfs_delegation_find_inode
(
clp
,
&
args
->
fh
);
if
(
inode
!=
NULL
)
{
/* Set up a helper thread to actually return the delegation */
switch
(
nfs_async_inode_return_delegation
(
inode
,
&
args
->
stateid
))
{
switch
(
nfs_async_inode_return_delegation
(
inode
,
&
args
->
stateid
,
nfs_validate_delegation_stateid
(
clp
)))
{
case
0
:
res
=
0
;
break
;
...
...
@@ -102,8 +113,31 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
return
res
;
}
int
nfs4_validate_delegation_stateid
(
struct
nfs_delegation
*
delegation
,
const
nfs4_stateid
*
stateid
)
{
if
(
delegation
==
NULL
||
memcmp
(
delegation
->
stateid
.
data
,
stateid
->
data
,
sizeof
(
delegation
->
stateid
.
data
))
!=
0
)
return
0
;
return
1
;
}
#if defined(CONFIG_NFS_V4_1)
int
nfs41_validate_delegation_stateid
(
struct
nfs_delegation
*
delegation
,
const
nfs4_stateid
*
stateid
)
{
if
(
delegation
==
NULL
)
return
0
;
/* seqid is 4-bytes long */
if
(((
u32
*
)
&
stateid
->
data
)[
0
]
!=
0
)
return
0
;
if
(
memcmp
(
&
delegation
->
stateid
.
data
[
4
],
&
stateid
->
data
[
4
],
sizeof
(
stateid
->
data
)
-
4
))
return
0
;
return
1
;
}
/*
* Validate the sequenceID sent by the server.
* Return success if the sequenceID is one more than what we last saw on
...
...
@@ -227,4 +261,32 @@ unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
return
res
->
csr_status
;
}
unsigned
nfs4_callback_recallany
(
struct
cb_recallanyargs
*
args
,
void
*
dummy
)
{
struct
nfs_client
*
clp
;
int
status
;
fmode_t
flags
=
0
;
status
=
htonl
(
NFS4ERR_OP_NOT_IN_SESSION
);
clp
=
nfs_find_client
(
args
->
craa_addr
,
4
);
if
(
clp
==
NULL
)
goto
out
;
dprintk
(
"NFS: RECALL_ANY callback request from %s
\n
"
,
rpc_peeraddr2str
(
clp
->
cl_rpcclient
,
RPC_DISPLAY_ADDR
));
if
(
test_bit
(
RCA4_TYPE_MASK_RDATA_DLG
,
(
const
unsigned
long
*
)
&
args
->
craa_type_mask
))
flags
=
FMODE_READ
;
if
(
test_bit
(
RCA4_TYPE_MASK_WDATA_DLG
,
(
const
unsigned
long
*
)
&
args
->
craa_type_mask
))
flags
|=
FMODE_WRITE
;
if
(
flags
)
nfs_expire_all_delegation_types
(
clp
,
flags
);
status
=
htonl
(
NFS4_OK
);
out:
dprintk
(
"%s: exit with status = %d
\n
"
,
__func__
,
ntohl
(
status
));
return
status
;
}
#endif
/* CONFIG_NFS_V4_1 */
fs/nfs/callback_xdr.c
View file @
52c9948b
...
...
@@ -23,6 +23,7 @@
#if defined(CONFIG_NFS_V4_1)
#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
4 + 1 + 3)
#define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
#endif
/* CONFIG_NFS_V4_1 */
#define NFSDBG_FACILITY NFSDBG_CALLBACK
...
...
@@ -326,6 +327,25 @@ static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp,
goto
out
;
}
static
unsigned
decode_recallany_args
(
struct
svc_rqst
*
rqstp
,
struct
xdr_stream
*
xdr
,
struct
cb_recallanyargs
*
args
)
{
uint32_t
*
p
;
args
->
craa_addr
=
svc_addr
(
rqstp
);
p
=
read_buf
(
xdr
,
4
);
if
(
unlikely
(
p
==
NULL
))
return
htonl
(
NFS4ERR_BADXDR
);
args
->
craa_objs_to_keep
=
ntohl
(
*
p
++
);
p
=
read_buf
(
xdr
,
4
);
if
(
unlikely
(
p
==
NULL
))
return
htonl
(
NFS4ERR_BADXDR
);
args
->
craa_type_mask
=
ntohl
(
*
p
);
return
0
;
}
#endif
/* CONFIG_NFS_V4_1 */
static
__be32
encode_string
(
struct
xdr_stream
*
xdr
,
unsigned
int
len
,
const
char
*
str
)
...
...
@@ -533,6 +553,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
case
OP_CB_GETATTR
:
case
OP_CB_RECALL
:
case
OP_CB_SEQUENCE
:
case
OP_CB_RECALL_ANY
:
*
op
=
&
callback_ops
[
op_nr
];
break
;
...
...
@@ -540,7 +561,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
case
OP_CB_NOTIFY_DEVICEID
:
case
OP_CB_NOTIFY
:
case
OP_CB_PUSH_DELEG
:
case
OP_CB_RECALL_ANY
:
case
OP_CB_RECALLABLE_OBJ_AVAIL
:
case
OP_CB_RECALL_SLOT
:
case
OP_CB_WANTS_CANCELLED
:
...
...
@@ -688,6 +708,11 @@ static struct callback_op callback_ops[] = {
.
encode_res
=
(
callback_encode_res_t
)
encode_cb_sequence_res
,
.
res_maxsize
=
CB_OP_SEQUENCE_RES_MAXSZ
,
},
[
OP_CB_RECALL_ANY
]
=
{
.
process_op
=
(
callback_process_op_t
)
nfs4_callback_recallany
,
.
decode_args
=
(
callback_decode_arg_t
)
decode_recallany_args
,
.
res_maxsize
=
CB_OP_RECALLANY_RES_MAXSZ
,
},
#endif
/* CONFIG_NFS_V4_1 */
};
...
...
@@ -718,3 +743,10 @@ struct svc_version nfs4_callback_version1 = {
.
vs_dispatch
=
NULL
,
};
struct
svc_version
nfs4_callback_version4
=
{
.
vs_vers
=
4
,
.
vs_nproc
=
ARRAY_SIZE
(
nfs4_callback_procedures1
),
.
vs_proc
=
nfs4_callback_procedures1
,
.
vs_xdrsize
=
NFS4_CALLBACK_XDRSIZE
,
.
vs_dispatch
=
NULL
,
};
fs/nfs/client.c
View file @
52c9948b
...
...
@@ -1260,10 +1260,20 @@ static int nfs4_set_client(struct nfs_server *server,
static
void
nfs4_session_set_rwsize
(
struct
nfs_server
*
server
)
{
#ifdef CONFIG_NFS_V4_1
struct
nfs4_session
*
sess
;
u32
server_resp_sz
;
u32
server_rqst_sz
;
if
(
!
nfs4_has_session
(
server
->
nfs_client
))
return
;
server
->
rsize
=
server
->
nfs_client
->
cl_session
->
fc_attrs
.
max_resp_sz
;
server
->
wsize
=
server
->
nfs_client
->
cl_session
->
fc_attrs
.
max_rqst_sz
;
sess
=
server
->
nfs_client
->
cl_session
;
server_resp_sz
=
sess
->
fc_attrs
.
max_resp_sz
-
nfs41_maxread_overhead
;
server_rqst_sz
=
sess
->
fc_attrs
.
max_rqst_sz
-
nfs41_maxwrite_overhead
;
if
(
server
->
rsize
>
server_resp_sz
)
server
->
rsize
=
server_resp_sz
;
if
(
server
->
wsize
>
server_rqst_sz
)
server
->
wsize
=
server_rqst_sz
;
#endif
/* CONFIG_NFS_V4_1 */
}
...
...
fs/nfs/delegation.c
View file @
52c9948b
...
...
@@ -92,7 +92,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
return
status
;
}
static
void
nfs_delegation_claim_opens
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
)
static
int
nfs_delegation_claim_opens
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
struct
nfs_open_context
*
ctx
;
...
...
@@ -116,10 +116,11 @@ static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *
err
=
nfs_delegation_claim_locks
(
ctx
,
state
);
put_nfs_open_context
(
ctx
);
if
(
err
!=
0
)
return
;
return
err
;
goto
again
;
}
spin_unlock
(
&
inode
->
i_lock
);
return
0
;
}
/*
...
...
@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode)
/*
* Basic procedure for returning a delegation to the server
*/
static
int
__nfs_inode_return_delegation
(
struct
inode
*
inode
,
struct
nfs_delegation
*
delegation
)
static
int
__nfs_inode_return_delegation
(
struct
inode
*
inode
,
struct
nfs_delegation
*
delegation
,
int
issync
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
int
err
;
nfs_msync_inode
(
inode
);
/*
* Guard against new delegated open/lock/unlock calls and against
* state recovery
*/
down_write
(
&
nfsi
->
rwsem
);
nfs_delegation_claim_opens
(
inode
,
&
delegation
->
stateid
);
err
=
nfs_delegation_claim_opens
(
inode
,
&
delegation
->
stateid
);
up_write
(
&
nfsi
->
rwsem
);
nfs_msync_inode
(
inode
);
if
(
err
)
goto
out
;
return
nfs_do_return_delegation
(
inode
,
delegation
,
1
);
err
=
nfs_do_return_delegation
(
inode
,
delegation
,
issync
);
out:
return
err
;
}
/*
* Return all delegations that have been marked for return
*/
void
nfs_client_return_marked_delegations
(
struct
nfs_client
*
clp
)
int
nfs_client_return_marked_delegations
(
struct
nfs_client
*
clp
)
{
struct
nfs_delegation
*
delegation
;
struct
inode
*
inode
;
int
err
=
0
;
restart:
rcu_read_lock
();
...
...
@@ -298,12 +303,18 @@ void nfs_client_return_marked_delegations(struct nfs_client *clp)
delegation
=
nfs_detach_delegation_locked
(
NFS_I
(
inode
),
NULL
);
spin_unlock
(
&
clp
->
cl_lock
);
rcu_read_unlock
();
if
(
delegation
!=
NULL
)
__nfs_inode_return_delegation
(
inode
,
delegation
);
if
(
delegation
!=
NULL
)
{
filemap_flush
(
inode
->
i_mapping
);
err
=
__nfs_inode_return_delegation
(
inode
,
delegation
,
0
);
}
iput
(
inode
);
if
(
!
err
)
goto
restart
;
set_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
);
return
err
;
}
rcu_read_unlock
();
return
0
;
}
/*
...
...
@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode)
spin_lock
(
&
clp
->
cl_lock
);
delegation
=
nfs_detach_delegation_locked
(
nfsi
,
NULL
);
spin_unlock
(
&
clp
->
cl_lock
);
if
(
delegation
!=
NULL
)
err
=
__nfs_inode_return_delegation
(
inode
,
delegation
);
if
(
delegation
!=
NULL
)
{
nfs_msync_inode
(
inode
);
err
=
__nfs_inode_return_delegation
(
inode
,
delegation
,
1
);
}
}
return
err
;
}
...
...
@@ -368,33 +381,47 @@ void nfs_super_return_all_delegations(struct super_block *sb)
spin_unlock
(
&
delegation
->
lock
);
}
rcu_read_unlock
();
nfs_client_return_marked_delegations
(
clp
);
if
(
nfs_client_return_marked_delegations
(
clp
)
!=
0
)
nfs4_schedule_state_manager
(
clp
);
}
static
void
nfs_client_mark_return_all_delegations
(
struct
nfs_client
*
clp
)
static
void
nfs_client_mark_return_all_delegation_types
(
struct
nfs_client
*
clp
,
fmode_t
flags
)
{
struct
nfs_delegation
*
delegation
;
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
set_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
);
set_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
);
if
((
delegation
->
type
==
(
FMODE_READ
|
FMODE_WRITE
))
&&
!
(
flags
&
FMODE_WRITE
))
continue
;
if
(
delegation
->
type
&
flags
)
nfs_mark_return_delegation
(
clp
,
delegation
);
}
rcu_read_unlock
();
}
static
void
nfs_client_mark_return_all_delegations
(
struct
nfs_client
*
clp
)
{
nfs_client_mark_return_all_delegation_types
(
clp
,
FMODE_READ
|
FMODE_WRITE
);
}
static
void
nfs_delegation_run_state_manager
(
struct
nfs_client
*
clp
)
{
if
(
test_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
))
nfs4_schedule_state_manager
(
clp
);
}
void
nfs_expire_all_delegation
s
(
struct
nfs_client
*
clp
)
void
nfs_expire_all_delegation
_types
(
struct
nfs_client
*
clp
,
fmode_t
flags
)
{
nfs_client_mark_return_all_delegation
s
(
clp
);
nfs_client_mark_return_all_delegation
_types
(
clp
,
flags
);
nfs_delegation_run_state_manager
(
clp
);
}
void
nfs_expire_all_delegations
(
struct
nfs_client
*
clp
)
{
nfs_expire_all_delegation_types
(
clp
,
FMODE_READ
|
FMODE_WRITE
);
}
/*
* Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
*/
...
...
@@ -413,8 +440,7 @@ static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *c
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
if
(
test_and_clear_bit
(
NFS_DELEGATION_REFERENCED
,
&
delegation
->
flags
))
continue
;
set_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
);
set_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
);
nfs_mark_return_delegation
(
clp
,
delegation
);
}
rcu_read_unlock
();
}
...
...
@@ -428,18 +454,21 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
/*
* Asynchronous delegation recall!
*/
int
nfs_async_inode_return_delegation
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
)
int
nfs_async_inode_return_delegation
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
,
int
(
*
validate_stateid
)(
struct
nfs_delegation
*
delegation
,
const
nfs4_stateid
*
stateid
))
{
struct
nfs_client
*
clp
=
NFS_SERVER
(
inode
)
->
nfs_client
;
struct
nfs_delegation
*
delegation
;
rcu_read_lock
();
delegation
=
rcu_dereference
(
NFS_I
(
inode
)
->
delegation
);
if
(
delegation
==
NULL
||
memcmp
(
delegation
->
stateid
.
data
,
stateid
->
data
,
sizeof
(
delegation
->
stateid
.
data
))
!=
0
)
{
if
(
!
validate_stateid
(
delegation
,
stateid
)
)
{
rcu_read_unlock
();
return
-
ENOENT
;
}
nfs_mark_return_delegation
(
clp
,
delegation
);
rcu_read_unlock
();
nfs_delegation_run_state_manager
(
clp
);
...
...
fs/nfs/delegation.h
View file @
52c9948b
...
...
@@ -34,15 +34,18 @@ enum {
int
nfs_inode_set_delegation
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
struct
nfs_openres
*
res
);
void
nfs_inode_reclaim_delegation
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
struct
nfs_openres
*
res
);
int
nfs_inode_return_delegation
(
struct
inode
*
inode
);
int
nfs_async_inode_return_delegation
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
);
int
nfs_async_inode_return_delegation
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
,
int
(
*
validate_stateid
)(
struct
nfs_delegation
*
delegation
,
const
nfs4_stateid
*
stateid
));
void
nfs_inode_return_delegation_noreclaim
(
struct
inode
*
inode
);
struct
inode
*
nfs_delegation_find_inode
(
struct
nfs_client
*
clp
,
const
struct
nfs_fh
*
fhandle
);
void
nfs_super_return_all_delegations
(
struct
super_block
*
sb
);
void
nfs_expire_all_delegations
(
struct
nfs_client
*
clp
);
void
nfs_expire_all_delegation_types
(
struct
nfs_client
*
clp
,
fmode_t
flags
);
void
nfs_expire_unreferenced_delegations
(
struct
nfs_client
*
clp
);
void
nfs_handle_cb_pathdown
(
struct
nfs_client
*
clp
);
void
nfs_client_return_marked_delegations
(
struct
nfs_client
*
clp
);
int
nfs_client_return_marked_delegations
(
struct
nfs_client
*
clp
);
void
nfs_delegation_mark_reclaim
(
struct
nfs_client
*
clp
);
void
nfs_delegation_reap_unclaimed
(
struct
nfs_client
*
clp
);
...
...
fs/nfs/dir.c
View file @
52c9948b
...
...
@@ -1579,36 +1579,30 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct
dentry
*
dentry
=
NULL
,
*
rehash
=
NULL
;
int
error
=
-
EBUSY
;
/*
* To prevent any new references to the target during the rename,
* we unhash the dentry and free the inode in advance.
*/
if
(
!
d_unhashed
(
new_dentry
))
{
d_drop
(
new_dentry
);
rehash
=
new_dentry
;
}
dfprintk
(
VFS
,
"NFS: rename(%s/%s -> %s/%s, ct=%d)
\n
"
,
old_dentry
->
d_parent
->
d_name
.
name
,
old_dentry
->
d_name
.
name
,
new_dentry
->
d_parent
->
d_name
.
name
,
new_dentry
->
d_name
.
name
,
atomic_read
(
&
new_dentry
->
d_count
));
/*
* First check whether the target is busy ... we can't
* safely do _any_ rename if the target is in use.
*
* For files, make a copy of the dentry and then do a
* silly-rename. If the silly-rename succeeds, the
* copied dentry is hashed and becomes the new target.
* For non-directories, check whether the target is busy and if so,
* make a copy of the dentry and then do a silly-rename. If the
* silly-rename succeeds, the copied dentry is hashed and becomes
* the new target.
*/
if
(
!
new_inode
)
goto
go_ahead
;
if
(
S_ISDIR
(
new_inode
->
i_mode
))
{
error
=
-
EISDIR
;
if
(
!
S_ISDIR
(
old_inode
->
i_mode
))
goto
out
;
}
else
if
(
atomic_read
(
&
new_dentry
->
d_count
)
>
2
)
{
if
(
new_inode
&&
!
S_ISDIR
(
new_inode
->
i_mode
))
{
/*
* To prevent any new references to the target during the
* rename, we unhash the dentry in advance.
*/
if
(
!
d_unhashed
(
new_dentry
))
{
d_drop
(
new_dentry
);
rehash
=
new_dentry
;
}
if
(
atomic_read
(
&
new_dentry
->
d_count
)
>
2
)
{
int
err
;
/* copy the target dentry's name */
dentry
=
d_alloc
(
new_dentry
->
d_parent
,
&
new_dentry
->
d_name
);
...
...
@@ -1617,17 +1611,14 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* silly-rename the existing target ... */
err
=
nfs_sillyrename
(
new_dir
,
new_dentry
);
if
(
!
err
)
{
new_dentry
=
rehash
=
dentry
;
new_inode
=
NULL
;
/* instantiate the replacement target */
d_instantiate
(
new_dentry
,
NULL
);
}
else
if
(
atomic_read
(
&
new_dentry
->
d_count
)
>
1
)
/* dentry still busy? */
if
(
err
)
goto
out
;
new_dentry
=
dentry
;
new_inode
=
NULL
;
}
}
go_ahead:
/*
* ... prune child dentries and writebacks if needed.
*/
...
...
fs/nfs/dns_resolve.c
View file @
52c9948b
...
...
@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
return
0
;
}
struct
nfs_dns_ent
*
nfs_dns_lookup
(
struct
cache_detail
*
cd
,
st
atic
st
ruct
nfs_dns_ent
*
nfs_dns_lookup
(
struct
cache_detail
*
cd
,
struct
nfs_dns_ent
*
key
)
{
struct
cache_head
*
ch
;
...
...
@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
return
container_of
(
ch
,
struct
nfs_dns_ent
,
h
);
}
struct
nfs_dns_ent
*
nfs_dns_update
(
struct
cache_detail
*
cd
,
st
atic
st
ruct
nfs_dns_ent
*
nfs_dns_update
(
struct
cache_detail
*
cd
,
struct
nfs_dns_ent
*
new
,
struct
nfs_dns_ent
*
key
)
{
...
...
fs/nfs/internal.h
View file @
52c9948b
...
...
@@ -30,6 +30,15 @@ static inline int nfs4_has_session(const struct nfs_client *clp)
return
0
;
}
static
inline
int
nfs4_has_persistent_session
(
const
struct
nfs_client
*
clp
)
{
#ifdef CONFIG_NFS_V4_1
if
(
nfs4_has_session
(
clp
))
return
(
clp
->
cl_session
->
flags
&
SESSION4_PERSIST
);
#endif
/* CONFIG_NFS_V4_1 */
return
0
;
}
struct
nfs_clone_mount
{
const
struct
super_block
*
sb
;
const
struct
dentry
*
dentry
;
...
...
@@ -156,6 +165,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr
/* callback_xdr.c */
extern
struct
svc_version
nfs4_callback_version1
;
extern
struct
svc_version
nfs4_callback_version4
;
/* pagelist.c */
extern
int
__init
nfs_init_nfspagecache
(
void
);
...
...
@@ -177,24 +187,14 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
extern
struct
rpc_procinfo
nfs3_procedures
[];
extern
__be32
*
nfs3_decode_dirent
(
__be32
*
,
struct
nfs_entry
*
,
int
);
/* nfs4proc.c */
static
inline
void
nfs4_restart_rpc
(
struct
rpc_task
*
task
,
const
struct
nfs_client
*
clp
)
{
#ifdef CONFIG_NFS_V4_1
if
(
nfs4_has_session
(
clp
)
&&
test_bit
(
NFS4CLNT_SESSION_SETUP
,
&
clp
->
cl_state
))
{
rpc_restart_call_prepare
(
task
);
return
;
}
#endif
/* CONFIG_NFS_V4_1 */
rpc_restart_call
(
task
);
}
/* nfs4xdr.c */
#ifdef CONFIG_NFS_V4
extern
__be32
*
nfs4_decode_dirent
(
__be32
*
p
,
struct
nfs_entry
*
entry
,
int
plus
);
#endif
#ifdef CONFIG_NFS_V4_1
extern
const
u32
nfs41_maxread_overhead
;
extern
const
u32
nfs41_maxwrite_overhead
;
#endif
/* nfs4proc.c */
#ifdef CONFIG_NFS_V4
...
...
@@ -273,20 +273,6 @@ extern int _nfs4_call_sync_session(struct nfs_server *server,
struct
nfs4_sequence_res
*
res
,
int
cache_reply
);
#ifdef CONFIG_NFS_V4_1
extern
void
nfs41_sequence_free_slot
(
const
struct
nfs_client
*
,
struct
nfs4_sequence_res
*
res
);
#endif
/* CONFIG_NFS_V4_1 */
static
inline
void
nfs4_sequence_free_slot
(
const
struct
nfs_client
*
clp
,
struct
nfs4_sequence_res
*
res
)
{
#ifdef CONFIG_NFS_V4_1
if
(
nfs4_has_session
(
clp
))
nfs41_sequence_free_slot
(
clp
,
res
);
#endif
/* CONFIG_NFS_V4_1 */
}
/*
* Determine the device name as a string
*/
...
...
@@ -380,3 +366,15 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
return
((
unsigned
long
)
len
+
(
unsigned
long
)
base
+
PAGE_SIZE
-
1
)
>>
PAGE_SHIFT
;
}
/*
* Helper for restarting RPC calls in the possible presence of NFSv4.1
* sessions.
*/
static
inline
void
nfs_restart_rpc
(
struct
rpc_task
*
task
,
const
struct
nfs_client
*
clp
)
{
if
(
nfs4_has_session
(
clp
))
rpc_restart_call_prepare
(
task
);
else
rpc_restart_call
(
task
);
}
fs/nfs/nfs4_fs.h
View file @
52c9948b
...
...
@@ -44,7 +44,8 @@ enum nfs4_client_state {
NFS4CLNT_RECLAIM_REBOOT
,
NFS4CLNT_RECLAIM_NOGRACE
,
NFS4CLNT_DELEGRETURN
,
NFS4CLNT_SESSION_SETUP
,
NFS4CLNT_SESSION_RESET
,
NFS4CLNT_SESSION_DRAINING
,
};
/*
...
...
@@ -180,6 +181,7 @@ struct nfs4_state_recovery_ops {
int
(
*
recover_lock
)(
struct
nfs4_state
*
,
struct
file_lock
*
);
int
(
*
establish_clid
)(
struct
nfs_client
*
,
struct
rpc_cred
*
);
struct
rpc_cred
*
(
*
get_clid_cred
)(
struct
nfs_client
*
);
int
(
*
reclaim_complete
)(
struct
nfs_client
*
);
};
struct
nfs4_state_maintenance_ops
{
...
...
@@ -200,9 +202,11 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
/* nfs4proc.c */
extern
int
nfs4_proc_setclientid
(
struct
nfs_client
*
,
u32
,
unsigned
short
,
struct
rpc_cred
*
);
extern
int
nfs4_proc_setclientid_confirm
(
struct
nfs_client
*
,
struct
rpc_cred
*
);
extern
int
nfs4_proc_exchange_id
(
struct
nfs_client
*
clp
,
struct
rpc_cred
*
cred
);
extern
int
nfs4_proc_async_renew
(
struct
nfs_client
*
,
struct
rpc_cred
*
);
extern
int
nfs4_proc_renew
(
struct
nfs_client
*
,
struct
rpc_cred
*
);
extern
int
nfs4_init_clientid
(
struct
nfs_client
*
,
struct
rpc_cred
*
);
extern
int
nfs41_init_clientid
(
struct
nfs_client
*
,
struct
rpc_cred
*
);
extern
int
nfs4_do_close
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
int
wait
);
extern
struct
dentry
*
nfs4_atomic_open
(
struct
inode
*
,
struct
dentry
*
,
struct
nameidata
*
);
extern
int
nfs4_open_revalidate
(
struct
inode
*
,
struct
dentry
*
,
int
,
struct
nameidata
*
);
...
...
@@ -218,9 +222,11 @@ extern int nfs4_setup_sequence(struct nfs_client *clp,
int
cache_reply
,
struct
rpc_task
*
task
);
extern
void
nfs4_destroy_session
(
struct
nfs4_session
*
session
);
extern
struct
nfs4_session
*
nfs4_alloc_session
(
struct
nfs_client
*
clp
);
extern
int
nfs4_proc_create_session
(
struct
nfs_client
*
,
int
reset
);
extern
int
nfs4_proc_create_session
(
struct
nfs_client
*
);
extern
int
nfs4_proc_destroy_session
(
struct
nfs4_session
*
);
extern
int
nfs4_init_session
(
struct
nfs_server
*
server
);
extern
int
nfs4_proc_get_lease_time
(
struct
nfs_client
*
clp
,
struct
nfs_fsinfo
*
fsinfo
);
#else
/* CONFIG_NFS_v4_1 */
static
inline
int
nfs4_setup_sequence
(
struct
nfs_client
*
clp
,
struct
nfs4_sequence_args
*
args
,
struct
nfs4_sequence_res
*
res
,
...
...
@@ -267,6 +273,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
extern
void
nfs4_schedule_state_recovery
(
struct
nfs_client
*
);
extern
void
nfs4_schedule_state_manager
(
struct
nfs_client
*
);
extern
int
nfs4_state_mark_reclaim_nograce
(
struct
nfs_client
*
clp
,
struct
nfs4_state
*
state
);
extern
void
nfs41_handle_sequence_flag_errors
(
struct
nfs_client
*
clp
,
u32
flags
);
extern
void
nfs4_put_lock_state
(
struct
nfs4_lock_state
*
lsp
);
extern
int
nfs4_set_lock_state
(
struct
nfs4_state
*
state
,
struct
file_lock
*
fl
);
extern
void
nfs4_copy_stateid
(
nfs4_stateid
*
,
struct
nfs4_state
*
,
fl_owner_t
);
...
...
@@ -287,6 +294,7 @@ struct nfs4_mount_data;
/* callback_xdr.c */
extern
struct
svc_version
nfs4_callback_version1
;
extern
struct
svc_version
nfs4_callback_version4
;
#else
...
...
fs/nfs/nfs4proc.c
View file @
52c9948b
This diff is collapsed.
Click to expand it.
fs/nfs/nfs4state.c
View file @
52c9948b
This diff is collapsed.
Click to expand it.
fs/nfs/nfs4xdr.c
View file @
52c9948b
This diff is collapsed.
Click to expand it.
fs/nfs/read.c
View file @
52c9948b
...
...
@@ -356,25 +356,19 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
struct
nfs_readres
*
resp
=
&
data
->
res
;
if
(
resp
->
eof
||
resp
->
count
==
argp
->
count
)
goto
out
;
return
;
/* This is a short read! */
nfs_inc_stats
(
data
->
inode
,
NFSIOS_SHORTREAD
);
/* Has the server at least made some progress? */
if
(
resp
->
count
==
0
)
goto
out
;
return
;
/* Yes, so retry the read at the end of the data */
argp
->
offset
+=
resp
->
count
;
argp
->
pgbase
+=
resp
->
count
;
argp
->
count
-=
resp
->
count
;
nfs4_restart_rpc
(
task
,
NFS_SERVER
(
data
->
inode
)
->
nfs_client
);
return
;
out:
nfs4_sequence_free_slot
(
NFS_SERVER
(
data
->
inode
)
->
nfs_client
,
&
data
->
res
.
seq_res
);
return
;
nfs_restart_rpc
(
task
,
NFS_SERVER
(
data
->
inode
)
->
nfs_client
);
}
/*
...
...
fs/nfs/super.c
View file @
52c9948b
...
...
@@ -175,14 +175,16 @@ static const match_table_t nfs_mount_option_tokens = {
};
enum
{
Opt_xprt_udp
,
Opt_xprt_
tcp
,
Opt_xprt_rdma
,
Opt_xprt_udp
,
Opt_xprt_
udp6
,
Opt_xprt_tcp
,
Opt_xprt_tcp6
,
Opt_xprt_rdma
,
Opt_xprt_err
};
static
const
match_table_t
nfs_xprt_protocol_tokens
=
{
{
Opt_xprt_udp
,
"udp"
},
{
Opt_xprt_udp6
,
"udp6"
},
{
Opt_xprt_tcp
,
"tcp"
},
{
Opt_xprt_tcp6
,
"tcp6"
},
{
Opt_xprt_rdma
,
"rdma"
},
{
Opt_xprt_err
,
NULL
}
...
...
@@ -492,6 +494,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
return
sec_flavours
[
i
].
str
;
}
static
void
nfs_show_mountd_netid
(
struct
seq_file
*
m
,
struct
nfs_server
*
nfss
,
int
showdefaults
)
{
struct
sockaddr
*
sap
=
(
struct
sockaddr
*
)
&
nfss
->
mountd_address
;
seq_printf
(
m
,
",mountproto="
);
switch
(
sap
->
sa_family
)
{
case
AF_INET
:
switch
(
nfss
->
mountd_protocol
)
{
case
IPPROTO_UDP
:
seq_printf
(
m
,
RPCBIND_NETID_UDP
);
break
;
case
IPPROTO_TCP
:
seq_printf
(
m
,
RPCBIND_NETID_TCP
);
break
;
default:
if
(
showdefaults
)
seq_printf
(
m
,
"auto"
);
}
break
;
case
AF_INET6
:
switch
(
nfss
->
mountd_protocol
)
{
case
IPPROTO_UDP
:
seq_printf
(
m
,
RPCBIND_NETID_UDP6
);
break
;
case
IPPROTO_TCP
:
seq_printf
(
m
,
RPCBIND_NETID_TCP6
);
break
;
default:
if
(
showdefaults
)
seq_printf
(
m
,
"auto"
);
}
break
;
default:
if
(
showdefaults
)
seq_printf
(
m
,
"auto"
);
}
}
static
void
nfs_show_mountd_options
(
struct
seq_file
*
m
,
struct
nfs_server
*
nfss
,
int
showdefaults
)
{
...
...
@@ -505,7 +546,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
}
case
AF_INET6
:
{
struct
sockaddr_in6
*
sin6
=
(
struct
sockaddr_in6
*
)
sap
;
seq_printf
(
m
,
",mountaddr=%pI6"
,
&
sin6
->
sin6_addr
);
seq_printf
(
m
,
",mountaddr=%pI6
c
"
,
&
sin6
->
sin6_addr
);
break
;
}
default:
...
...
@@ -518,17 +559,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
if
(
nfss
->
mountd_port
||
showdefaults
)
seq_printf
(
m
,
",mountport=%u"
,
nfss
->
mountd_port
);
switch
(
nfss
->
mountd_protocol
)
{
case
IPPROTO_UDP
:
seq_printf
(
m
,
",mountproto=udp"
);
break
;
case
IPPROTO_TCP
:
seq_printf
(
m
,
",mountproto=tcp"
);
break
;
default:
if
(
showdefaults
)
seq_printf
(
m
,
",mountproto=auto"
);
}
nfs_show_mountd_netid
(
m
,
nfss
,
showdefaults
);
}
/*
...
...
@@ -578,7 +609,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
seq_puts
(
m
,
nfs_infop
->
nostr
);
}
seq_printf
(
m
,
",proto=%s"
,
rpc_peeraddr2str
(
nfss
->
client
,
RPC_DISPLAY_
PROTO
));
rpc_peeraddr2str
(
nfss
->
client
,
RPC_DISPLAY_
NETID
));
if
(
version
==
4
)
{
if
(
nfss
->
port
!=
NFS_PORT
)
seq_printf
(
m
,
",port=%u"
,
nfss
->
port
);
...
...
@@ -714,8 +745,6 @@ static void nfs_umount_begin(struct super_block *sb)
struct
nfs_server
*
server
;
struct
rpc_clnt
*
rpc
;
lock_kernel
();
server
=
NFS_SB
(
sb
);
/* -EIO all pending I/O */
rpc
=
server
->
client_acl
;
...
...
@@ -724,8 +753,6 @@ static void nfs_umount_begin(struct super_block *sb)
rpc
=
server
->
client
;
if
(
!
IS_ERR
(
rpc
))
rpc_killall_tasks
(
rpc
);
unlock_kernel
();
}
static
struct
nfs_parsed_mount_data
*
nfs_alloc_parsed_mount_data
(
unsigned
int
version
)
...
...
@@ -734,8 +761,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
data
=
kzalloc
(
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
data
)
{
data
->
rsize
=
NFS_MAX_FILE_IO_SIZE
;
data
->
wsize
=
NFS_MAX_FILE_IO_SIZE
;
data
->
acregmin
=
NFS_DEF_ACREGMIN
;
data
->
acregmax
=
NFS_DEF_ACREGMAX
;
data
->
acdirmin
=
NFS_DEF_ACDIRMIN
;
...
...
@@ -887,6 +912,8 @@ static int nfs_parse_mount_options(char *raw,
{
char
*
p
,
*
string
,
*
secdata
;
int
rc
,
sloppy
=
0
,
invalid_option
=
0
;
unsigned
short
protofamily
=
AF_UNSPEC
;
unsigned
short
mountfamily
=
AF_UNSPEC
;
if
(
!
raw
)
{
dfprintk
(
MOUNT
,
"NFS: mount options string was NULL.
\n
"
);
...
...
@@ -1232,12 +1259,17 @@ static int nfs_parse_mount_options(char *raw,
token
=
match_token
(
string
,
nfs_xprt_protocol_tokens
,
args
);
protofamily
=
AF_INET
;
switch
(
token
)
{
case
Opt_xprt_udp6
:
protofamily
=
AF_INET6
;
case
Opt_xprt_udp
:
mnt
->
flags
&=
~
NFS_MOUNT_TCP
;
mnt
->
nfs_server
.
protocol
=
XPRT_TRANSPORT_UDP
;
kfree
(
string
);
break
;
case
Opt_xprt_tcp6
:
protofamily
=
AF_INET6
;
case
Opt_xprt_tcp
:
mnt
->
flags
|=
NFS_MOUNT_TCP
;
mnt
->
nfs_server
.
protocol
=
XPRT_TRANSPORT_TCP
;
...
...
@@ -1265,10 +1297,15 @@ static int nfs_parse_mount_options(char *raw,
nfs_xprt_protocol_tokens
,
args
);
kfree
(
string
);
mountfamily
=
AF_INET
;
switch
(
token
)
{
case
Opt_xprt_udp6
:
mountfamily
=
AF_INET6
;
case
Opt_xprt_udp
:
mnt
->
mount_server
.
protocol
=
XPRT_TRANSPORT_UDP
;
break
;
case
Opt_xprt_tcp6
:
mountfamily
=
AF_INET6
;
case
Opt_xprt_tcp
:
mnt
->
mount_server
.
protocol
=
XPRT_TRANSPORT_TCP
;
break
;
...
...
@@ -1367,8 +1404,33 @@ static int nfs_parse_mount_options(char *raw,
if
(
!
sloppy
&&
invalid_option
)
return
0
;
/*
* verify that any proto=/mountproto= options match the address
* familiies in the addr=/mountaddr= options.
*/
if
(
protofamily
!=
AF_UNSPEC
&&
protofamily
!=
mnt
->
nfs_server
.
address
.
ss_family
)
goto
out_proto_mismatch
;
if
(
mountfamily
!=
AF_UNSPEC
)
{
if
(
mnt
->
mount_server
.
addrlen
)
{
if
(
mountfamily
!=
mnt
->
mount_server
.
address
.
ss_family
)
goto
out_mountproto_mismatch
;
}
else
{
if
(
mountfamily
!=
mnt
->
nfs_server
.
address
.
ss_family
)
goto
out_mountproto_mismatch
;
}
}
return
1
;
out_mountproto_mismatch:
printk
(
KERN_INFO
"NFS: mount server address does not match mountproto= "
"option
\n
"
);
return
0
;
out_proto_mismatch:
printk
(
KERN_INFO
"NFS: server address does not match proto= option
\n
"
);
return
0
;
out_invalid_address:
printk
(
KERN_INFO
"NFS: bad IP address specified: %s
\n
"
,
p
);
return
0
;
...
...
@@ -1881,7 +1943,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
if
(
data
==
NULL
)
return
-
ENOMEM
;
lock_kernel
();
/* fill out struct with values from existing mount */
data
->
flags
=
nfss
->
flags
;
data
->
rsize
=
nfss
->
rsize
;
...
...
@@ -1907,7 +1968,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
error
=
nfs_compare_remount_data
(
nfss
,
data
);
out:
kfree
(
data
);
unlock_kernel
();
return
error
;
}
...
...
fs/nfs/unlink.c
View file @
52c9948b
...
...
@@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
struct
inode
*
dir
=
data
->
dir
;
if
(
!
NFS_PROTO
(
dir
)
->
unlink_done
(
task
,
dir
))
nfs
4
_restart_rpc
(
task
,
NFS_SERVER
(
dir
)
->
nfs_client
);
nfs_restart_rpc
(
task
,
NFS_SERVER
(
dir
)
->
nfs_client
);
}
/**
...
...
fs/nfs/write.c
View file @
52c9948b
...
...
@@ -1216,7 +1216,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
*/
argp
->
stable
=
NFS_FILE_SYNC
;
}
nfs
4
_restart_rpc
(
task
,
server
->
nfs_client
);
nfs_restart_rpc
(
task
,
server
->
nfs_client
);
return
-
EAGAIN
;
}
if
(
time_before
(
complain
,
jiffies
))
{
...
...
@@ -1228,7 +1228,6 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
/* Can't do anything about it except throw an error. */
task
->
tk_status
=
-
EIO
;
}
nfs4_sequence_free_slot
(
server
->
nfs_client
,
&
data
->
res
.
seq_res
);
return
0
;
}
...
...
@@ -1612,15 +1611,16 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
if
(
ret
)
goto
out_unlock
;
page_cache_get
(
newpage
);
spin_lock
(
&
mapping
->
host
->
i_lock
);
req
->
wb_page
=
newpage
;
SetPagePrivate
(
newpage
);
set_page_private
(
newpage
,
page_private
(
page
)
);
set_page_private
(
newpage
,
(
unsigned
long
)
req
);
ClearPagePrivate
(
page
);
set_page_private
(
page
,
0
);
spin_unlock
(
&
mapping
->
host
->
i_lock
);
page_cache_release
(
page
);
out_unlock:
nfs_clear_page_tag_locked
(
req
);
nfs_release_request
(
req
);
out:
return
ret
;
}
...
...
include/linux/nfs4.h
View file @
52c9948b
...
...
@@ -128,6 +128,8 @@
#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040
#define SEQ4_STATUS_LEASE_MOVED 0x00000080
#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
#define SEQ4_STATUS_CB_PATH_DOWN_SESSION 0x00000200
#define SEQ4_STATUS_BACKCHANNEL_FAULT 0x00000400
#define NFS4_MAX_UINT64 (~(u64)0)
...
...
@@ -528,6 +530,7 @@ enum {
NFSPROC4_CLNT_DESTROY_SESSION
,
NFSPROC4_CLNT_SEQUENCE
,
NFSPROC4_CLNT_GET_LEASE_TIME
,
NFSPROC4_CLNT_RECLAIM_COMPLETE
,
};
/* nfs41 types */
...
...
include/linux/nfs_fs_sb.h
View file @
52c9948b
...
...
@@ -209,6 +209,7 @@ struct nfs4_session {
unsigned
long
session_state
;
u32
hash_alg
;
u32
ssv_len
;
struct
completion
complete
;
/* The fore and back channel */
struct
nfs4_channel_attrs
fc_attrs
;
...
...
include/linux/nfs_xdr.h
View file @
52c9948b
...
...
@@ -170,8 +170,9 @@ struct nfs4_sequence_args {
struct
nfs4_sequence_res
{
struct
nfs4_session
*
sr_session
;
u8
sr_slotid
;
/* slot used to send request */
unsigned
long
sr_renewal_time
;
int
sr_status
;
/* sequence operation status */
unsigned
long
sr_renewal_time
;
u32
sr_status_flags
;
};
struct
nfs4_get_lease_time_args
{
...
...
@@ -938,6 +939,16 @@ struct nfs41_create_session_args {
struct
nfs41_create_session_res
{
struct
nfs_client
*
client
;
};
struct
nfs41_reclaim_complete_args
{
/* In the future extend to include curr_fh for use with migration */
unsigned
char
one_fs
:
1
;
struct
nfs4_sequence_args
seq_args
;
};
struct
nfs41_reclaim_complete_res
{
struct
nfs4_sequence_res
seq_res
;
};
#endif
/* CONFIG_NFS_V4_1 */
struct
nfs_page
;
...
...
include/linux/sunrpc/sched.h
View file @
52c9948b
...
...
@@ -130,12 +130,14 @@ struct rpc_task_setup {
#define RPC_TASK_DYNAMIC 0x0080
/* task was kmalloc'ed */
#define RPC_TASK_KILLED 0x0100
/* task was killed */
#define RPC_TASK_SOFT 0x0200
/* Use soft timeouts */
#define RPC_TASK_SOFTCONN 0x0400
/* Fail if can't connect */
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
#define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
#define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED)
#define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT)
#define RPC_IS_SOFTCONN(t) ((t)->tk_flags & RPC_TASK_SOFTCONN)
#define RPC_TASK_RUNNING 0
#define RPC_TASK_QUEUED 1
...
...
net/sunrpc/addr.c
View file @
52c9948b
...
...
@@ -55,16 +55,8 @@ static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
/*
* RFC 4291, Section 2.2.1
*
* To keep the result as short as possible, especially
* since we don't shorthand, we don't want leading zeros
* in each halfword, so avoid %pI6.
*/
return
snprintf
(
buf
,
buflen
,
"%x:%x:%x:%x:%x:%x:%x:%x"
,
ntohs
(
addr
->
s6_addr16
[
0
]),
ntohs
(
addr
->
s6_addr16
[
1
]),
ntohs
(
addr
->
s6_addr16
[
2
]),
ntohs
(
addr
->
s6_addr16
[
3
]),
ntohs
(
addr
->
s6_addr16
[
4
]),
ntohs
(
addr
->
s6_addr16
[
5
]),
ntohs
(
addr
->
s6_addr16
[
6
]),
ntohs
(
addr
->
s6_addr16
[
7
]));
return
snprintf
(
buf
,
buflen
,
"%pI6c"
,
addr
);
}
static
size_t
rpc_ntop6
(
const
struct
sockaddr
*
sap
,
...
...
net/sunrpc/auth.c
View file @
52c9948b
...
...
@@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred)
clear_bit
(
RPCAUTH_CRED_HASHED
,
&
cred
->
cr_flags
);
}
static
void
static
int
rpcauth_unhash_cred
(
struct
rpc_cred
*
cred
)
{
spinlock_t
*
cache_lock
;
int
ret
;
cache_lock
=
&
cred
->
cr_auth
->
au_credcache
->
lock
;
spin_lock
(
cache_lock
);
if
(
atomic_read
(
&
cred
->
cr_count
)
==
0
)
ret
=
atomic_read
(
&
cred
->
cr_count
)
==
0
;
if
(
ret
)
rpcauth_unhash_cred_locked
(
cred
);
spin_unlock
(
cache_lock
);
return
ret
;
}
/*
...
...
@@ -446,31 +449,35 @@ void
put_rpccred
(
struct
rpc_cred
*
cred
)
{
/* Fast path for unhashed credentials */
if
(
test_bit
(
RPCAUTH_CRED_HASHED
,
&
cred
->
cr_flags
)
!=
0
)
goto
need_lock
;
if
(
!
atomic_dec_and_test
(
&
cred
->
cr_count
))
if
(
test_bit
(
RPCAUTH_CRED_HASHED
,
&
cred
->
cr_flags
)
==
0
)
{
if
(
atomic_dec_and_test
(
&
cred
->
cr_count
))
cred
->
cr_ops
->
crdestroy
(
cred
);
return
;
goto
out_destroy
;
need_lock:
}
if
(
!
atomic_dec_and_lock
(
&
cred
->
cr_count
,
&
rpc_credcache_lock
))
return
;
if
(
!
list_empty
(
&
cred
->
cr_lru
))
{
number_cred_unused
--
;
list_del_init
(
&
cred
->
cr_lru
);
}
if
(
test_bit
(
RPCAUTH_CRED_UPTODATE
,
&
cred
->
cr_flags
)
==
0
)
rpcauth_unhash_cred
(
cred
);
if
(
test_bit
(
RPCAUTH_CRED_HASHED
,
&
cred
->
cr_flags
)
!=
0
)
{
if
(
test_bit
(
RPCAUTH_CRED_UPTODATE
,
&
cred
->
cr_flags
)
!=
0
)
{
cred
->
cr_expire
=
jiffies
;
list_add_tail
(
&
cred
->
cr_lru
,
&
cred_unused
);
number_cred_unused
++
;
spin_unlock
(
&
rpc_credcache_lock
);
return
;
goto
out_nodestroy
;
}
if
(
!
rpcauth_unhash_cred
(
cred
))
{
/* We were hashed and someone looked us up... */
goto
out_nodestroy
;
}
}
spin_unlock
(
&
rpc_credcache_lock
);
out_destroy:
cred
->
cr_ops
->
crdestroy
(
cred
);
return
;
out_nodestroy:
spin_unlock
(
&
rpc_credcache_lock
);
}
EXPORT_SYMBOL_GPL
(
put_rpccred
);
...
...
net/sunrpc/auth_gss/auth_gss.c
View file @
52c9948b
...
...
@@ -304,7 +304,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
* to that upcall instead of adding the new upcall.
*/
static
inline
struct
gss_upcall_msg
*
gss_add_msg
(
struct
gss_
auth
*
gss_auth
,
struct
gss_
upcall_msg
*
gss_msg
)
gss_add_msg
(
struct
gss_upcall_msg
*
gss_msg
)
{
struct
rpc_inode
*
rpci
=
gss_msg
->
inode
;
struct
inode
*
inode
=
&
rpci
->
vfs_inode
;
...
...
@@ -445,7 +445,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
gss_new
=
gss_alloc_msg
(
gss_auth
,
uid
,
clnt
,
gss_cred
->
gc_machine_cred
);
if
(
IS_ERR
(
gss_new
))
return
gss_new
;
gss_msg
=
gss_add_msg
(
gss_
auth
,
gss_
new
);
gss_msg
=
gss_add_msg
(
gss_new
);
if
(
gss_msg
==
gss_new
)
{
struct
inode
*
inode
=
&
gss_new
->
inode
->
vfs_inode
;
int
res
=
rpc_queue_upcall
(
inode
,
&
gss_new
->
msg
);
...
...
@@ -485,7 +485,7 @@ gss_refresh_upcall(struct rpc_task *task)
dprintk
(
"RPC: %5u gss_refresh_upcall for uid %u
\n
"
,
task
->
tk_pid
,
cred
->
cr_uid
);
gss_msg
=
gss_setup_upcall
(
task
->
tk_client
,
gss_auth
,
cred
);
if
(
IS
_ERR
(
gss_msg
)
==
-
EAGAIN
)
{
if
(
PTR
_ERR
(
gss_msg
)
==
-
EAGAIN
)
{
/* XXX: warning on the first, under the assumption we
* shouldn't normally hit this case on a refresh. */
warn_gssd
();
...
...
net/sunrpc/clnt.c
View file @
52c9948b
...
...
@@ -79,7 +79,7 @@ static void call_connect_status(struct rpc_task *task);
static
__be32
*
rpc_encode_header
(
struct
rpc_task
*
task
);
static
__be32
*
rpc_verify_header
(
struct
rpc_task
*
task
);
static
int
rpc_ping
(
struct
rpc_clnt
*
clnt
,
int
flags
);
static
int
rpc_ping
(
struct
rpc_clnt
*
clnt
);
static
void
rpc_register_client
(
struct
rpc_clnt
*
clnt
)
{
...
...
@@ -340,7 +340,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
return
clnt
;
if
(
!
(
args
->
flags
&
RPC_CLNT_CREATE_NOPING
))
{
int
err
=
rpc_ping
(
clnt
,
RPC_TASK_SOFT
);
int
err
=
rpc_ping
(
clnt
);
if
(
err
!=
0
)
{
rpc_shutdown_client
(
clnt
);
return
ERR_PTR
(
err
);
...
...
@@ -528,7 +528,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
clnt
->
cl_prog
=
program
->
number
;
clnt
->
cl_vers
=
version
->
number
;
clnt
->
cl_stats
=
program
->
stats
;
err
=
rpc_ping
(
clnt
,
RPC_TASK_SOFT
);
err
=
rpc_ping
(
clnt
);
if
(
err
!=
0
)
{
rpc_shutdown_client
(
clnt
);
clnt
=
ERR_PTR
(
err
);
...
...
@@ -1060,7 +1060,7 @@ call_bind_status(struct rpc_task *task)
goto
retry_timeout
;
case
-
EPFNOSUPPORT
:
/* server doesn't support any rpcbind version we know of */
dprintk
(
"RPC: %5u
remote rpcbind service unavailabl
e
\n
"
,
dprintk
(
"RPC: %5u
unrecognized remote rpcbind servic
e
\n
"
,
task
->
tk_pid
);
break
;
case
-
EPROTONOSUPPORT
:
...
...
@@ -1069,6 +1069,21 @@ call_bind_status(struct rpc_task *task)
task
->
tk_status
=
0
;
task
->
tk_action
=
call_bind
;
return
;
case
-
ECONNREFUSED
:
/* connection problems */
case
-
ECONNRESET
:
case
-
ENOTCONN
:
case
-
EHOSTDOWN
:
case
-
EHOSTUNREACH
:
case
-
ENETUNREACH
:
case
-
EPIPE
:
dprintk
(
"RPC: %5u remote rpcbind unreachable: %d
\n
"
,
task
->
tk_pid
,
task
->
tk_status
);
if
(
!
RPC_IS_SOFTCONN
(
task
))
{
rpc_delay
(
task
,
5
*
HZ
);
goto
retry_timeout
;
}
status
=
task
->
tk_status
;
break
;
default:
dprintk
(
"RPC: %5u unrecognized rpcbind error (%d)
\n
"
,
task
->
tk_pid
,
-
task
->
tk_status
);
...
...
@@ -1180,11 +1195,25 @@ static void
call_transmit_status
(
struct
rpc_task
*
task
)
{
task
->
tk_action
=
call_status
;
/*
* Common case: success. Force the compiler to put this
* test first.
*/
if
(
task
->
tk_status
==
0
)
{
xprt_end_transmit
(
task
);
rpc_task_force_reencode
(
task
);
return
;
}
switch
(
task
->
tk_status
)
{
case
-
EAGAIN
:
break
;
default:
dprint_status
(
task
);
xprt_end_transmit
(
task
);
rpc_task_force_reencode
(
task
);
break
;
/*
* Special cases: if we've been waiting on the
* socket's write_space() callback, or if the
...
...
@@ -1192,11 +1221,16 @@ call_transmit_status(struct rpc_task *task)
* then hold onto the transport lock.
*/
case
-
ECONNREFUSED
:
case
-
ECONNRESET
:
case
-
ENOTCONN
:
case
-
EHOSTDOWN
:
case
-
EHOSTUNREACH
:
case
-
ENETUNREACH
:
if
(
RPC_IS_SOFTCONN
(
task
))
{
xprt_end_transmit
(
task
);
rpc_exit
(
task
,
task
->
tk_status
);
break
;
}
case
-
ECONNRESET
:
case
-
ENOTCONN
:
case
-
EPIPE
:
rpc_task_force_reencode
(
task
);
}
...
...
@@ -1346,6 +1380,10 @@ call_timeout(struct rpc_task *task)
dprintk
(
"RPC: %5u call_timeout (major)
\n
"
,
task
->
tk_pid
);
task
->
tk_timeouts
++
;
if
(
RPC_IS_SOFTCONN
(
task
))
{
rpc_exit
(
task
,
-
ETIMEDOUT
);
return
;
}
if
(
RPC_IS_SOFT
(
task
))
{
if
(
clnt
->
cl_chatty
)
printk
(
KERN_NOTICE
"%s: server %s not responding, timed out
\n
"
,
...
...
@@ -1675,14 +1713,14 @@ static struct rpc_procinfo rpcproc_null = {
.
p_decode
=
rpcproc_decode_null
,
};
static
int
rpc_ping
(
struct
rpc_clnt
*
clnt
,
int
flags
)
static
int
rpc_ping
(
struct
rpc_clnt
*
clnt
)
{
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
rpcproc_null
,
};
int
err
;
msg
.
rpc_cred
=
authnull_ops
.
lookup_cred
(
NULL
,
NULL
,
0
);
err
=
rpc_call_sync
(
clnt
,
&
msg
,
flags
);
err
=
rpc_call_sync
(
clnt
,
&
msg
,
RPC_TASK_SOFT
|
RPC_TASK_SOFTCONN
);
put_rpccred
(
msg
.
rpc_cred
);
return
err
;
}
...
...
net/sunrpc/rpcb_clnt.c
View file @
52c9948b
...
...
@@ -20,6 +20,7 @@
#include <linux/in6.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <net/ipv6.h>
#include <linux/sunrpc/clnt.h>
...
...
@@ -110,6 +111,9 @@ static void rpcb_getport_done(struct rpc_task *, void *);
static
void
rpcb_map_release
(
void
*
data
);
static
struct
rpc_program
rpcb_program
;
static
struct
rpc_clnt
*
rpcb_local_clnt
;
static
struct
rpc_clnt
*
rpcb_local_clnt4
;
struct
rpcbind_args
{
struct
rpc_xprt
*
r_xprt
;
...
...
@@ -163,21 +167,60 @@ static const struct sockaddr_in rpcb_inaddr_loopback = {
.
sin_port
=
htons
(
RPCBIND_PORT
),
};
static
struct
rpc_clnt
*
rpcb_create_local
(
struct
sockaddr
*
addr
,
size_t
addrlen
,
u32
version
)
static
DEFINE_MUTEX
(
rpcb_create_local_mutex
);
/*
* Returns zero on success, otherwise a negative errno value
* is returned.
*/
static
int
rpcb_create_local
(
void
)
{
struct
rpc_create_args
args
=
{
.
protocol
=
XPRT_TRANSPORT_
UD
P
,
.
address
=
addr
,
.
addrsize
=
addrlen
,
.
protocol
=
XPRT_TRANSPORT_
TC
P
,
.
address
=
(
struct
sockaddr
*
)
&
rpcb_inaddr_loopback
,
.
addrsize
=
sizeof
(
rpcb_inaddr_loopback
)
,
.
servername
=
"localhost"
,
.
program
=
&
rpcb_program
,
.
version
=
version
,
.
version
=
RPCBVERS_2
,
.
authflavor
=
RPC_AUTH_UNIX
,
.
flags
=
RPC_CLNT_CREATE_NOPING
,
};
struct
rpc_clnt
*
clnt
,
*
clnt4
;
int
result
=
0
;
return
rpc_create
(
&
args
);
if
(
rpcb_local_clnt
)
return
result
;
mutex_lock
(
&
rpcb_create_local_mutex
);
if
(
rpcb_local_clnt
)
goto
out
;
clnt
=
rpc_create
(
&
args
);
if
(
IS_ERR
(
clnt
))
{
dprintk
(
"RPC: failed to create local rpcbind "
"client (errno %ld).
\n
"
,
PTR_ERR
(
clnt
));
result
=
-
PTR_ERR
(
clnt
);
goto
out
;
}
/*
* This results in an RPC ping. On systems running portmapper,
* the v4 ping will fail. Proceed anyway, but disallow rpcb
* v4 upcalls.
*/
clnt4
=
rpc_bind_new_program
(
clnt
,
&
rpcb_program
,
RPCBVERS_4
);
if
(
IS_ERR
(
clnt4
))
{
dprintk
(
"RPC: failed to create local rpcbind v4 "
"cleint (errno %ld).
\n
"
,
PTR_ERR
(
clnt4
));
clnt4
=
NULL
;
}
rpcb_local_clnt
=
clnt
;
rpcb_local_clnt4
=
clnt4
;
out:
mutex_unlock
(
&
rpcb_create_local_mutex
);
return
result
;
}
static
struct
rpc_clnt
*
rpcb_create
(
char
*
hostname
,
struct
sockaddr
*
srvaddr
,
...
...
@@ -209,22 +252,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
return
rpc_create
(
&
args
);
}
static
int
rpcb_register_call
(
const
u32
version
,
struct
rpc_message
*
msg
)
static
int
rpcb_register_call
(
struct
rpc_clnt
*
clnt
,
struct
rpc_message
*
msg
)
{
struct
sockaddr
*
addr
=
(
struct
sockaddr
*
)
&
rpcb_inaddr_loopback
;
size_t
addrlen
=
sizeof
(
rpcb_inaddr_loopback
);
struct
rpc_clnt
*
rpcb_clnt
;
int
result
,
error
=
0
;
msg
->
rpc_resp
=
&
result
;
rpcb_clnt
=
rpcb_create_local
(
addr
,
addrlen
,
version
);
if
(
!
IS_ERR
(
rpcb_clnt
))
{
error
=
rpc_call_sync
(
rpcb_clnt
,
msg
,
0
);
rpc_shutdown_client
(
rpcb_clnt
);
}
else
error
=
PTR_ERR
(
rpcb_clnt
);
error
=
rpc_call_sync
(
clnt
,
msg
,
RPC_TASK_SOFTCONN
);
if
(
error
<
0
)
{
dprintk
(
"RPC: failed to contact local rpcbind "
"server (errno %d).
\n
"
,
-
error
);
...
...
@@ -279,6 +313,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
struct
rpc_message
msg
=
{
.
rpc_argp
=
&
map
,
};
int
error
;
error
=
rpcb_create_local
();
if
(
error
)
return
error
;
dprintk
(
"RPC: %sregistering (%u, %u, %d, %u) with local "
"rpcbind
\n
"
,
(
port
?
""
:
"un"
),
...
...
@@ -288,7 +327,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
if
(
port
)
msg
.
rpc_proc
=
&
rpcb_procedures2
[
RPCBPROC_SET
];
return
rpcb_register_call
(
RPCBVERS_2
,
&
msg
);
return
rpcb_register_call
(
rpcb_local_clnt
,
&
msg
);
}
/*
...
...
@@ -313,7 +352,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
if
(
port
)
msg
->
rpc_proc
=
&
rpcb_procedures4
[
RPCBPROC_SET
];
result
=
rpcb_register_call
(
RPCBVERS_
4
,
msg
);
result
=
rpcb_register_call
(
rpcb_local_clnt
4
,
msg
);
kfree
(
map
->
r_addr
);
return
result
;
}
...
...
@@ -340,7 +379,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
if
(
port
)
msg
->
rpc_proc
=
&
rpcb_procedures4
[
RPCBPROC_SET
];
result
=
rpcb_register_call
(
RPCBVERS_
4
,
msg
);
result
=
rpcb_register_call
(
rpcb_local_clnt
4
,
msg
);
kfree
(
map
->
r_addr
);
return
result
;
}
...
...
@@ -356,7 +395,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
map
->
r_addr
=
""
;
msg
->
rpc_proc
=
&
rpcb_procedures4
[
RPCBPROC_UNSET
];
return
rpcb_register_call
(
RPCBVERS_
4
,
msg
);
return
rpcb_register_call
(
rpcb_local_clnt
4
,
msg
);
}
/**
...
...
@@ -414,6 +453,13 @@ int rpcb_v4_register(const u32 program, const u32 version,
struct
rpc_message
msg
=
{
.
rpc_argp
=
&
map
,
};
int
error
;
error
=
rpcb_create_local
();
if
(
error
)
return
error
;
if
(
rpcb_local_clnt4
==
NULL
)
return
-
EPROTONOSUPPORT
;
if
(
address
==
NULL
)
return
rpcb_unregister_all_protofamilies
(
&
msg
);
...
...
@@ -491,7 +537,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
.
rpc_message
=
&
msg
,
.
callback_ops
=
&
rpcb_getport_ops
,
.
callback_data
=
map
,
.
flags
=
RPC_TASK_ASYNC
,
.
flags
=
RPC_TASK_ASYNC
|
RPC_TASK_SOFTCONN
,
};
return
rpc_run_task
(
&
task_setup_data
);
...
...
@@ -1027,3 +1073,15 @@ static struct rpc_program rpcb_program = {
.
version
=
rpcb_version
,
.
stats
=
&
rpcb_stats
,
};
/**
* cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
*
*/
void
cleanup_rpcb_clnt
(
void
)
{
if
(
rpcb_local_clnt4
)
rpc_shutdown_client
(
rpcb_local_clnt4
);
if
(
rpcb_local_clnt
)
rpc_shutdown_client
(
rpcb_local_clnt
);
}
net/sunrpc/sunrpc_syms.c
View file @
52c9948b
...
...
@@ -24,6 +24,8 @@
extern
struct
cache_detail
ip_map_cache
,
unix_gid_cache
;
extern
void
cleanup_rpcb_clnt
(
void
);
static
int
__init
init_sunrpc
(
void
)
{
...
...
@@ -53,6 +55,7 @@ init_sunrpc(void)
static
void
__exit
cleanup_sunrpc
(
void
)
{
cleanup_rpcb_clnt
();
rpcauth_remove_module
();
cleanup_socket_xprt
();
svc_cleanup_xprt_sock
();
...
...
net/sunrpc/xprt.c
View file @
52c9948b
...
...
@@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task)
}
if
(
!
xprt_lock_write
(
xprt
,
task
))
return
;
if
(
test_and_clear_bit
(
XPRT_CLOSE_WAIT
,
&
xprt
->
state
))
xprt
->
ops
->
close
(
xprt
);
if
(
xprt_connected
(
xprt
))
xprt_release_write
(
xprt
,
task
);
else
{
...
...
net/sunrpc/xprtsock.c
View file @
52c9948b
...
...
@@ -2019,7 +2019,7 @@ static void xs_connect(struct rpc_task *task)
if
(
xprt_test_and_set_connecting
(
xprt
))
return
;
if
(
transport
->
sock
!=
NULL
)
{
if
(
transport
->
sock
!=
NULL
&&
!
RPC_IS_SOFTCONN
(
task
)
)
{
dprintk
(
"RPC: xs_connect delayed xprt %p for %lu "
"seconds
\n
"
,
xprt
,
xprt
->
reestablish_timeout
/
HZ
);
...
...
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