Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
52c9948b
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
156
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
52c9948b
编写于
12月 13, 2009
作者:
T
Trond Myklebust
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'nfs-for-2.6.33'
上级
f4054253
190f38e5
变更
30
展开全部
隐藏空白更改
内联
并排
Showing
30 changed file
with
1078 addition
and
469 deletion
+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
未找到文件。
fs/nfs/callback.c
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
);
goto
restart
;
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
浏览文件 @
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
浏览文件 @
52c9948b
...
...
@@ -1579,55 +1579,46 @@ 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
)
{
int
err
;
/* copy the target dentry's name */
dentry
=
d_alloc
(
new_dentry
->
d_parent
,
&
new_dentry
->
d_name
);
if
(
!
dentry
)
goto
out
;
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
);
if
(
!
dentry
)
goto
out
;
/* silly-rename the existing target ... */
err
=
nfs_sillyrename
(
new_dir
,
new_dentry
);
if
(
!
err
)
{
new_dentry
=
rehash
=
dentry
;
/* silly-rename the existing target ... */
err
=
nfs_sillyrename
(
new_dir
,
new_dentry
);
if
(
err
)
goto
out
;
new_dentry
=
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? */
goto
out
;
}
}
go_ahead:
/*
* ... prune child dentries and writebacks if needed.
*/
...
...
fs/nfs/dns_resolve.c
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
52c9948b
此差异已折叠。
点击以展开。
fs/nfs/nfs4state.c
浏览文件 @
52c9948b
...
...
@@ -116,6 +116,68 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp)
#if defined(CONFIG_NFS_V4_1)
static
int
nfs41_setup_state_renewal
(
struct
nfs_client
*
clp
)
{
int
status
;
struct
nfs_fsinfo
fsinfo
;
status
=
nfs4_proc_get_lease_time
(
clp
,
&
fsinfo
);
if
(
status
==
0
)
{
/* Update lease time and schedule renewal */
spin_lock
(
&
clp
->
cl_lock
);
clp
->
cl_lease_time
=
fsinfo
.
lease_time
*
HZ
;
clp
->
cl_last_renewal
=
jiffies
;
spin_unlock
(
&
clp
->
cl_lock
);
nfs4_schedule_state_renewal
(
clp
);
}
return
status
;
}
static
void
nfs41_end_drain_session
(
struct
nfs_client
*
clp
,
struct
nfs4_session
*
ses
)
{
if
(
test_and_clear_bit
(
NFS4CLNT_SESSION_DRAINING
,
&
clp
->
cl_state
))
rpc_wake_up
(
&
ses
->
fc_slot_table
.
slot_tbl_waitq
);
}
static
int
nfs41_begin_drain_session
(
struct
nfs_client
*
clp
,
struct
nfs4_session
*
ses
)
{
struct
nfs4_slot_table
*
tbl
=
&
ses
->
fc_slot_table
;
spin_lock
(
&
tbl
->
slot_tbl_lock
);
set_bit
(
NFS4CLNT_SESSION_DRAINING
,
&
clp
->
cl_state
);
if
(
tbl
->
highest_used_slotid
!=
-
1
)
{
INIT_COMPLETION
(
ses
->
complete
);
spin_unlock
(
&
tbl
->
slot_tbl_lock
);
return
wait_for_completion_interruptible
(
&
ses
->
complete
);
}
spin_unlock
(
&
tbl
->
slot_tbl_lock
);
return
0
;
}
int
nfs41_init_clientid
(
struct
nfs_client
*
clp
,
struct
rpc_cred
*
cred
)
{
int
status
;
status
=
nfs41_begin_drain_session
(
clp
,
clp
->
cl_session
);
if
(
status
!=
0
)
goto
out
;
status
=
nfs4_proc_exchange_id
(
clp
,
cred
);
if
(
status
!=
0
)
goto
out
;
status
=
nfs4_proc_create_session
(
clp
);
if
(
status
!=
0
)
goto
out
;
nfs41_end_drain_session
(
clp
,
clp
->
cl_session
);
nfs41_setup_state_renewal
(
clp
);
nfs_mark_client_ready
(
clp
,
NFS_CS_READY
);
out:
return
status
;
}
struct
rpc_cred
*
nfs4_get_exchange_id_cred
(
struct
nfs_client
*
clp
)
{
struct
rpc_cred
*
cred
;
...
...
@@ -877,6 +939,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
case
-
NFS4ERR_EXPIRED
:
case
-
NFS4ERR_NO_GRACE
:
case
-
NFS4ERR_STALE_CLIENTID
:
case
-
NFS4ERR_BADSESSION
:
case
-
NFS4ERR_BADSLOT
:
case
-
NFS4ERR_BAD_HIGH_SLOT
:
case
-
NFS4ERR_CONN_NOT_BOUND_TO_SESSION
:
goto
out
;
default:
printk
(
KERN_ERR
"%s: unhandled error %d. Zeroing state
\n
"
,
...
...
@@ -959,6 +1025,10 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
case
-
NFS4ERR_NO_GRACE
:
nfs4_state_mark_reclaim_nograce
(
sp
->
so_client
,
state
);
case
-
NFS4ERR_STALE_CLIENTID
:
case
-
NFS4ERR_BADSESSION
:
case
-
NFS4ERR_BADSLOT
:
case
-
NFS4ERR_BAD_HIGH_SLOT
:
case
-
NFS4ERR_CONN_NOT_BOUND_TO_SESSION
:
goto
out_err
;
}
nfs4_put_open_state
(
state
);
...
...
@@ -1011,6 +1081,14 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
nfs4_state_mark_reclaim_helper
(
clp
,
nfs4_state_mark_reclaim_reboot
);
}
static
void
nfs4_reclaim_complete
(
struct
nfs_client
*
clp
,
const
struct
nfs4_state_recovery_ops
*
ops
)
{
/* Notify the server we're done reclaiming our state */
if
(
ops
->
reclaim_complete
)
(
void
)
ops
->
reclaim_complete
(
clp
);
}
static
void
nfs4_state_end_reclaim_reboot
(
struct
nfs_client
*
clp
)
{
struct
nfs4_state_owner
*
sp
;
...
...
@@ -1020,6 +1098,9 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
if
(
!
test_and_clear_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
return
;
nfs4_reclaim_complete
(
clp
,
nfs4_reboot_recovery_ops
[
clp
->
cl_minorversion
]);
for
(
pos
=
rb_first
(
&
clp
->
cl_state_owners
);
pos
!=
NULL
;
pos
=
rb_next
(
pos
))
{
sp
=
rb_entry
(
pos
,
struct
nfs4_state_owner
,
so_client_node
);
spin_lock
(
&
sp
->
so_lock
);
...
...
@@ -1046,25 +1127,25 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
nfs4_state_mark_reclaim_helper
(
clp
,
nfs4_state_mark_reclaim_nograce
);
}
static
void
nfs4_state_end_reclaim_nograce
(
struct
nfs_client
*
clp
)
{
clear_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
);
}
static
void
nfs4_recovery_handle_error
(
struct
nfs_client
*
clp
,
int
error
)
static
int
nfs4_recovery_handle_error
(
struct
nfs_client
*
clp
,
int
error
)
{
switch
(
error
)
{
case
-
NFS4ERR_CB_PATH_DOWN
:
nfs_handle_cb_pathdown
(
clp
);
break
;
return
0
;
case
-
NFS4ERR_NO_GRACE
:
nfs4_state_end_reclaim_reboot
(
clp
);
return
0
;
case
-
NFS4ERR_STALE_CLIENTID
:
case
-
NFS4ERR_LEASE_MOVED
:
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
nfs4_state_end_reclaim_reboot
(
clp
);
nfs4_state_start_reclaim_reboot
(
clp
);
break
;
case
-
NFS4ERR_EXPIRED
:
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
nfs4_state_start_reclaim_nograce
(
clp
);
break
;
case
-
NFS4ERR_BADSESSION
:
case
-
NFS4ERR_BADSLOT
:
case
-
NFS4ERR_BAD_HIGH_SLOT
:
...
...
@@ -1072,8 +1153,11 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
case
-
NFS4ERR_CONN_NOT_BOUND_TO_SESSION
:
case
-
NFS4ERR_SEQ_FALSE_RETRY
:
case
-
NFS4ERR_SEQ_MISORDERED
:
set_bit
(
NFS4CLNT_SESSION_SETUP
,
&
clp
->
cl_state
);
set_bit
(
NFS4CLNT_SESSION_RESET
,
&
clp
->
cl_state
);
/* Zero session reset errors */
return
0
;
}
return
error
;
}
static
int
nfs4_do_reclaim
(
struct
nfs_client
*
clp
,
const
struct
nfs4_state_recovery_ops
*
ops
)
...
...
@@ -1093,8 +1177,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
if
(
status
<
0
)
{
set_bit
(
ops
->
owner_flag_bit
,
&
sp
->
so_flags
);
nfs4_put_state_owner
(
sp
);
nfs4_recovery_handle_error
(
clp
,
status
);
return
status
;
return
nfs4_recovery_handle_error
(
clp
,
status
);
}
nfs4_put_state_owner
(
sp
);
goto
restart
;
...
...
@@ -1124,8 +1207,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
status
=
ops
->
renew_lease
(
clp
,
cred
);
put_rpccred
(
cred
);
out:
nfs4_recovery_handle_error
(
clp
,
status
);
return
status
;
return
nfs4_recovery_handle_error
(
clp
,
status
);
}
static
int
nfs4_reclaim_lease
(
struct
nfs_client
*
clp
)
...
...
@@ -1151,55 +1233,65 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
}
#ifdef CONFIG_NFS_V4_1
static
void
nfs4_session_recovery_handle_error
(
struct
nfs_client
*
clp
,
int
err
)
void
nfs41_handle_sequence_flag_errors
(
struct
nfs_client
*
clp
,
u32
flags
)
{
switch
(
err
)
{
case
-
NFS4ERR_STALE_CLIENTID
:
if
(
!
flags
)
return
;
else
if
(
flags
&
SEQ4_STATUS_RESTART_RECLAIM_NEEDED
)
{
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
set_bit
(
NFS4CLNT_SESSION_SETUP
,
&
clp
->
cl_state
);
}
nfs4_state_start_reclaim_reboot
(
clp
);
nfs4_schedule_state_recovery
(
clp
);
}
else
if
(
flags
&
(
SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED
|
SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED
|
SEQ4_STATUS_ADMIN_STATE_REVOKED
|
SEQ4_STATUS_RECALLABLE_STATE_REVOKED
|
SEQ4_STATUS_LEASE_MOVED
))
{
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
nfs4_state_start_reclaim_nograce
(
clp
);
nfs4_schedule_state_recovery
(
clp
);
}
else
if
(
flags
&
(
SEQ4_STATUS_CB_PATH_DOWN
|
SEQ4_STATUS_BACKCHANNEL_FAULT
|
SEQ4_STATUS_CB_PATH_DOWN_SESSION
))
nfs_expire_all_delegations
(
clp
);
}
static
int
nfs4_reset_session
(
struct
nfs_client
*
clp
)
{
struct
nfs4_session
*
ses
=
clp
->
cl_session
;
int
status
;
status
=
nfs41_begin_drain_session
(
clp
,
ses
);
if
(
status
!=
0
)
return
status
;
status
=
nfs4_proc_destroy_session
(
clp
->
cl_session
);
if
(
status
&&
status
!=
-
NFS4ERR_BADSESSION
&&
status
!=
-
NFS4ERR_DEADSESSION
)
{
nfs4_session
_recovery_handle_error
(
clp
,
status
);
status
=
nfs4
_recovery_handle_error
(
clp
,
status
);
goto
out
;
}
memset
(
clp
->
cl_session
->
sess_id
.
data
,
0
,
NFS4_MAX_SESSIONID_LEN
);
status
=
nfs4_proc_create_session
(
clp
,
1
);
status
=
nfs4_proc_create_session
(
clp
);
if
(
status
)
nfs4_session_recovery_handle_error
(
clp
,
status
);
/* fall through*/
out:
/* Wake up the next rpc task even on error */
rpc_wake_up_next
(
&
clp
->
cl_session
->
fc_slot_table
.
slot_tbl_waitq
);
return
status
;
}
static
int
nfs4_initialize_session
(
struct
nfs_client
*
clp
)
{
int
status
;
status
=
nfs4_recovery_handle_error
(
clp
,
status
);
status
=
nfs4_proc_create_session
(
clp
,
0
);
if
(
!
status
)
{
nfs_mark_client_ready
(
clp
,
NFS_CS_READY
);
}
else
if
(
status
==
-
NFS4ERR_STALE_CLIENTID
)
{
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
set_bit
(
NFS4CLNT_SESSION_SETUP
,
&
clp
->
cl_state
);
}
else
{
nfs_mark_client_ready
(
clp
,
status
);
out:
/*
* Let the state manager reestablish state
* without waking other tasks yet.
*/
if
(
!
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
))
{
/* Wake up the next rpc task */
nfs41_end_drain_session
(
clp
,
ses
);
if
(
status
==
0
)
nfs41_setup_state_renewal
(
clp
);
}
return
status
;
}
#else
/* CONFIG_NFS_V4_1 */
static
int
nfs4_reset_session
(
struct
nfs_client
*
clp
)
{
return
0
;
}
static
int
nfs4_initialize_session
(
struct
nfs_client
*
clp
)
{
return
0
;
}
#endif
/* CONFIG_NFS_V4_1 */
/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
...
...
@@ -1234,7 +1326,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
status
=
nfs4_reclaim_lease
(
clp
);
if
(
status
)
{
nfs4_set_lease_expired
(
clp
,
status
);
if
(
status
==
-
EAGAIN
)
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
))
continue
;
if
(
clp
->
cl_cons_state
==
NFS_CS_SESSION_INITING
)
...
...
@@ -1242,55 +1335,51 @@ static void nfs4_state_manager(struct nfs_client *clp)
goto
out_error
;
}
clear_bit
(
NFS4CLNT_CHECK_LEASE
,
&
clp
->
cl_state
);
set_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
);
}
if
(
test_and_clear_bit
(
NFS4CLNT_CHECK_LEASE
,
&
clp
->
cl_state
))
{
status
=
nfs4_check_lease
(
clp
);
if
(
status
!=
0
)
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
)
)
continue
;
if
(
status
<
0
&&
status
!=
-
NFS4ERR_CB_PATH_DOWN
)
goto
out_error
;
}
/* Initialize or reset the session */
if
(
test_and_clear_bit
(
NFS4CLNT_SESSION_
SETUP
,
&
clp
->
cl_state
)
if
(
test_and_clear_bit
(
NFS4CLNT_SESSION_
RESET
,
&
clp
->
cl_state
)
&&
nfs4_has_session
(
clp
))
{
if
(
clp
->
cl_cons_state
==
NFS_CS_SESSION_INITING
)
status
=
nfs4_initialize_session
(
clp
);
else
status
=
nfs4_reset_session
(
clp
);
if
(
status
)
{
if
(
status
==
-
NFS4ERR_STALE_CLIENTID
)
continue
;
status
=
nfs4_reset_session
(
clp
);
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
))
continue
;
if
(
status
<
0
)
goto
out_error
;
}
}
/* First recover reboot state... */
if
(
test_
and_clear_
bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
{
if
(
test_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
{
status
=
nfs4_do_reclaim
(
clp
,
nfs4_reboot_recovery_ops
[
clp
->
cl_minorversion
]);
if
(
status
==
-
NFS4ERR_STALE_CLIENTID
)
continue
;
if
(
test_bit
(
NFS4CLNT_SESSION_SETUP
,
&
clp
->
cl_state
))
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
)
||
test_bit
(
NFS4CLNT_SESSION_RESET
,
&
clp
->
cl_state
))
continue
;
nfs4_state_end_reclaim_reboot
(
clp
);
continue
;
if
(
test_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
))
continue
;
if
(
status
<
0
)
goto
out_error
;
}
/* Now recover expired state... */
if
(
test_and_clear_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
))
{
status
=
nfs4_do_reclaim
(
clp
,
nfs4_nograce_recovery_ops
[
clp
->
cl_minorversion
]);
if
(
status
<
0
)
{
set_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
);
if
(
status
==
-
NFS4ERR_STALE_CLIENTID
)
continue
;
if
(
status
==
-
NFS4ERR_EXPIRED
)
continue
;
if
(
test_bit
(
NFS4CLNT_SESSION_SETUP
,
&
clp
->
cl_state
))
continue
;
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
)
||
test_bit
(
NFS4CLNT_SESSION_RESET
,
&
clp
->
cl_state
)
||
test_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
continue
;
if
(
status
<
0
)
goto
out_error
;
}
else
nfs4_state_end_reclaim_nograce
(
clp
);
continue
;
}
if
(
test_and_clear_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
))
{
...
...
@@ -1309,8 +1398,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
out_error:
printk
(
KERN_WARNING
"Error: state manager failed on NFSv4 server %s"
" with error %d
\n
"
,
clp
->
cl_hostname
,
-
status
);
if
(
test_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
nfs4_state_end_reclaim_reboot
(
clp
);
nfs4_clear_state_manager_bit
(
clp
);
}
...
...
fs/nfs/nfs4xdr.c
浏览文件 @
52c9948b
...
...
@@ -46,11 +46,13 @@
#include <linux/proc_fs.h>
#include <linux/kdev_t.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/nfs.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
#include "nfs4_fs.h"
#include "internal.h"
#define NFSDBG_FACILITY NFSDBG_XDR
...
...
@@ -134,7 +136,7 @@ static int nfs4_stat_to_errno(int);
#define decode_lookup_maxsz (op_decode_hdr_maxsz)
#define encode_share_access_maxsz \
(2)
#define encode_createmode_maxsz (1 + encode_attrs_maxsz)
#define encode_createmode_maxsz (1 + encode_attrs_maxsz
+ encode_verifier_maxsz
)
#define encode_opentype_maxsz (1 + encode_createmode_maxsz)
#define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
#define encode_open_maxsz (op_encode_hdr_maxsz + \
...
...
@@ -299,6 +301,8 @@ static int nfs4_stat_to_errno(int);
XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
#define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4)
#define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4)
#else
/* CONFIG_NFS_V4_1 */
#define encode_sequence_maxsz 0
#define decode_sequence_maxsz 0
...
...
@@ -676,6 +680,25 @@ static int nfs4_stat_to_errno(int);
decode_sequence_maxsz + \
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz)
#define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_reclaim_complete_maxsz)
#define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_reclaim_complete_maxsz)
const
u32
nfs41_maxwrite_overhead
=
((
RPC_MAX_HEADER_WITH_AUTH
+
compound_encode_hdr_maxsz
+
encode_sequence_maxsz
+
encode_putfh_maxsz
+
encode_getattr_maxsz
)
*
XDR_UNIT
);
const
u32
nfs41_maxread_overhead
=
((
RPC_MAX_HEADER_WITH_AUTH
+
compound_decode_hdr_maxsz
+
decode_sequence_maxsz
+
decode_putfh_maxsz
)
*
XDR_UNIT
);
#endif
/* CONFIG_NFS_V4_1 */
static
const
umode_t
nfs_type2fmt
[]
=
{
...
...
@@ -1140,6 +1163,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
static
inline
void
encode_createmode
(
struct
xdr_stream
*
xdr
,
const
struct
nfs_openargs
*
arg
)
{
__be32
*
p
;
struct
nfs_client
*
clp
;
p
=
reserve_space
(
xdr
,
4
);
switch
(
arg
->
open_flags
&
O_EXCL
)
{
...
...
@@ -1148,8 +1172,23 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
encode_attrs
(
xdr
,
arg
->
u
.
attrs
,
arg
->
server
);
break
;
default:
*
p
=
cpu_to_be32
(
NFS4_CREATE_EXCLUSIVE
);
encode_nfs4_verifier
(
xdr
,
&
arg
->
u
.
verifier
);
clp
=
arg
->
server
->
nfs_client
;
if
(
clp
->
cl_minorversion
>
0
)
{
if
(
nfs4_has_persistent_session
(
clp
))
{
*
p
=
cpu_to_be32
(
NFS4_CREATE_GUARDED
);
encode_attrs
(
xdr
,
arg
->
u
.
attrs
,
arg
->
server
);
}
else
{
struct
iattr
dummy
;
*
p
=
cpu_to_be32
(
NFS4_CREATE_EXCLUSIVE4_1
);
encode_nfs4_verifier
(
xdr
,
&
arg
->
u
.
verifier
);
dummy
.
ia_valid
=
0
;
encode_attrs
(
xdr
,
&
dummy
,
arg
->
server
);
}
}
else
{
*
p
=
cpu_to_be32
(
NFS4_CREATE_EXCLUSIVE
);
encode_nfs4_verifier
(
xdr
,
&
arg
->
u
.
verifier
);
}
}
}
...
...
@@ -1592,6 +1631,19 @@ static void encode_destroy_session(struct xdr_stream *xdr,
hdr
->
nops
++
;
hdr
->
replen
+=
decode_destroy_session_maxsz
;
}
static
void
encode_reclaim_complete
(
struct
xdr_stream
*
xdr
,
struct
nfs41_reclaim_complete_args
*
args
,
struct
compound_hdr
*
hdr
)
{
__be32
*
p
;
p
=
reserve_space
(
xdr
,
8
);
*
p
++
=
cpu_to_be32
(
OP_RECLAIM_COMPLETE
);
*
p
++
=
cpu_to_be32
(
args
->
one_fs
);
hdr
->
nops
++
;
hdr
->
replen
+=
decode_reclaim_complete_maxsz
;
}
#endif
/* CONFIG_NFS_V4_1 */
static
void
encode_sequence
(
struct
xdr_stream
*
xdr
,
...
...
@@ -2096,7 +2148,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
encode_compound_hdr
(
&
xdr
,
req
,
&
hdr
);
encode_sequence
(
&
xdr
,
&
args
->
seq_args
,
&
hdr
);
encode_putfh
(
&
xdr
,
args
->
fh
,
&
hdr
);
replen
=
hdr
.
replen
+
nfs4_fattr_bitmap_maxsz
+
1
;
replen
=
hdr
.
replen
+
op_decode_hdr_maxsz
+
nfs4_fattr_bitmap_maxsz
+
1
;
encode_getattr_two
(
&
xdr
,
FATTR4_WORD0_ACL
,
0
,
&
hdr
);
xdr_inline_pages
(
&
req
->
rq_rcv_buf
,
replen
<<
2
,
...
...
@@ -2420,6 +2472,26 @@ static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
encode_nops
(
&
hdr
);
return
0
;
}
/*
* a RECLAIM_COMPLETE request
*/
static
int
nfs4_xdr_enc_reclaim_complete
(
struct
rpc_rqst
*
req
,
uint32_t
*
p
,
struct
nfs41_reclaim_complete_args
*
args
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
=
{
.
minorversion
=
nfs4_xdr_minorversion
(
&
args
->
seq_args
)
};
xdr_init_encode
(
&
xdr
,
&
req
->
rq_snd_buf
,
p
);
encode_compound_hdr
(
&
xdr
,
req
,
&
hdr
);
encode_sequence
(
&
xdr
,
&
args
->
seq_args
,
&
hdr
);
encode_reclaim_complete
(
&
xdr
,
args
,
&
hdr
);
encode_nops
(
&
hdr
);
return
0
;
}
#endif
/* CONFIG_NFS_V4_1 */
static
void
print_overflow_msg
(
const
char
*
func
,
const
struct
xdr_stream
*
xdr
)
...
...
@@ -4528,6 +4600,11 @@ static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
{
return
decode_op_hdr
(
xdr
,
OP_DESTROY_SESSION
);
}
static
int
decode_reclaim_complete
(
struct
xdr_stream
*
xdr
,
void
*
dummy
)
{
return
decode_op_hdr
(
xdr
,
OP_RECLAIM_COMPLETE
);
}
#endif
/* CONFIG_NFS_V4_1 */
static
int
decode_sequence
(
struct
xdr_stream
*
xdr
,
...
...
@@ -4583,8 +4660,8 @@ static int decode_sequence(struct xdr_stream *xdr,
dummy
=
be32_to_cpup
(
p
++
);
/* target highest slot id - currently not processed */
dummy
=
be32_to_cpup
(
p
++
);
/* result flags
- currently not processed
*/
dummy
=
be32_to_cpup
(
p
);
/* result flags */
res
->
sr_status_flags
=
be32_to_cpup
(
p
);
status
=
0
;
out_err:
res
->
sr_status
=
status
;
...
...
@@ -5309,7 +5386,7 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
}
/*
*
FSINFO request
*
Decode FSINFO response
*/
static
int
nfs4_xdr_dec_fsinfo
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs4_fsinfo_res
*
res
)
...
...
@@ -5330,7 +5407,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
}
/*
*
PATHCONF request
*
Decode PATHCONF response
*/
static
int
nfs4_xdr_dec_pathconf
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs4_pathconf_res
*
res
)
...
...
@@ -5351,7 +5428,7 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
}
/*
*
STATFS request
*
Decode STATFS response
*/
static
int
nfs4_xdr_dec_statfs
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs4_statfs_res
*
res
)
...
...
@@ -5372,7 +5449,7 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
}
/*
*
GETATTR_BITMAP request
*
Decode GETATTR_BITMAP response
*/
static
int
nfs4_xdr_dec_server_caps
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs4_server_caps_res
*
res
)
{
...
...
@@ -5411,7 +5488,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
}
/*
*
a SETCLIENTID request
*
Decode SETCLIENTID response
*/
static
int
nfs4_xdr_dec_setclientid
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs_client
*
clp
)
...
...
@@ -5428,7 +5505,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
}
/*
*
a SETCLIENTID_CONFIRM request
*
Decode SETCLIENTID_CONFIRM response
*/
static
int
nfs4_xdr_dec_setclientid_confirm
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs_fsinfo
*
fsinfo
)
{
...
...
@@ -5448,7 +5525,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
}
/*
* D
ELEGRETURN request
* D
ecode DELEGRETURN response
*/
static
int
nfs4_xdr_dec_delegreturn
(
struct
rpc_rqst
*
rqstp
,
__be32
*
p
,
struct
nfs4_delegreturnres
*
res
)
{
...
...
@@ -5474,7 +5551,7 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
}
/*
*
FS_LOCATIONS request
*
Decode FS_LOCATIONS response
*/
static
int
nfs4_xdr_dec_fs_locations
(
struct
rpc_rqst
*
req
,
__be32
*
p
,
struct
nfs4_fs_locations_res
*
res
)
...
...
@@ -5504,7 +5581,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
#if defined(CONFIG_NFS_V4_1)
/*
*
EXCHANGE_ID request
*
Decode EXCHANGE_ID response
*/
static
int
nfs4_xdr_dec_exchange_id
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
void
*
res
)
...
...
@@ -5521,7 +5598,7 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
*
a CREATE_SESSION request
*
Decode CREATE_SESSION response
*/
static
int
nfs4_xdr_dec_create_session
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs41_create_session_res
*
res
)
...
...
@@ -5538,7 +5615,7 @@ static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
*
a DESTROY_SESSION request
*
Decode DESTROY_SESSION response
*/
static
int
nfs4_xdr_dec_destroy_session
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
void
*
dummy
)
...
...
@@ -5555,7 +5632,7 @@ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
*
a SEQUENCE request
*
Decode SEQUENCE response
*/
static
int
nfs4_xdr_dec_sequence
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs4_sequence_res
*
res
)
...
...
@@ -5572,7 +5649,7 @@ static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
*
a GET_LEASE_TIME request
*
Decode GET_LEASE_TIME response
*/
static
int
nfs4_xdr_dec_get_lease_time
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs4_get_lease_time_res
*
res
)
...
...
@@ -5591,6 +5668,25 @@ static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
status
=
decode_fsinfo
(
&
xdr
,
res
->
lr_fsinfo
);
return
status
;
}
/*
* Decode RECLAIM_COMPLETE response
*/
static
int
nfs4_xdr_dec_reclaim_complete
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs41_reclaim_complete_res
*
res
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
;
int
status
;
xdr_init_decode
(
&
xdr
,
&
rqstp
->
rq_rcv_buf
,
p
);
status
=
decode_compound_hdr
(
&
xdr
,
&
hdr
);
if
(
!
status
)
status
=
decode_sequence
(
&
xdr
,
&
res
->
seq_res
,
rqstp
);
if
(
!
status
)
status
=
decode_reclaim_complete
(
&
xdr
,
(
void
*
)
NULL
);
return
status
;
}
#endif
/* CONFIG_NFS_V4_1 */
__be32
*
nfs4_decode_dirent
(
__be32
*
p
,
struct
nfs_entry
*
entry
,
int
plus
)
...
...
@@ -5767,6 +5863,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC
(
DESTROY_SESSION
,
enc_destroy_session
,
dec_destroy_session
),
PROC
(
SEQUENCE
,
enc_sequence
,
dec_sequence
),
PROC
(
GET_LEASE_TIME
,
enc_get_lease_time
,
dec_get_lease_time
),
PROC
(
RECLAIM_COMPLETE
,
enc_reclaim_complete
,
dec_reclaim_complete
),
#endif
/* CONFIG_NFS_V4_1 */
};
...
...
fs/nfs/read.c
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
)
{
cred
->
cr_expire
=
jiffies
;
list_add_tail
(
&
cred
->
cr_lru
,
&
cred_unused
);
number_cred_unused
++
;
spin_unlock
(
&
rpc_credcache_lock
);
return
;
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
++
;
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
;
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
;
}
return
rpc_create
(
&
args
);
/*
* 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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录