Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
XianxinMao
Linux
提交
08cc36cb
L
Linux
项目概览
XianxinMao
/
Linux
12 个月 前同步成功
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
Linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
08cc36cb
编写于
12月 30, 2008
作者:
T
Trond Myklebust
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'devel' into next
上级
3c92ec8a
46f72f57
变更
43
展开全部
隐藏空白更改
内联
并排
Showing
43 changed file
with
1876 addition
and
1442 deletion
+1876
-1442
fs/lockd/clntlock.c
fs/lockd/clntlock.c
+16
-7
fs/lockd/host.c
fs/lockd/host.c
+9
-1
fs/lockd/svc.c
fs/lockd/svc.c
+3
-3
fs/nfs/callback.c
fs/nfs/callback.c
+31
-5
fs/nfs/client.c
fs/nfs/client.c
+61
-34
fs/nfs/delegation.c
fs/nfs/delegation.c
+132
-128
fs/nfs/delegation.h
fs/nfs/delegation.h
+15
-18
fs/nfs/dir.c
fs/nfs/dir.c
+14
-10
fs/nfs/inode.c
fs/nfs/inode.c
+3
-10
fs/nfs/internal.h
fs/nfs/internal.h
+14
-0
fs/nfs/mount_clnt.c
fs/nfs/mount_clnt.c
+15
-19
fs/nfs/nfs4_fs.h
fs/nfs/nfs4_fs.h
+24
-8
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+240
-191
fs/nfs/nfs4renewd.c
fs/nfs/nfs4renewd.c
+11
-11
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+294
-121
fs/nfs/nfs4xdr.c
fs/nfs/nfs4xdr.c
+543
-692
fs/nfs/nfsroot.c
fs/nfs/nfsroot.c
+17
-10
fs/nfs/read.c
fs/nfs/read.c
+0
-6
fs/nfs/super.c
fs/nfs/super.c
+28
-16
fs/nfs_common/nfsacl.c
fs/nfs_common/nfsacl.c
+2
-2
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4callback.c
+8
-1
fs/nfsd/nfs4state.c
fs/nfsd/nfs4state.c
+12
-0
include/linux/jiffies.h
include/linux/jiffies.h
+10
-0
include/linux/lockd/bind.h
include/linux/lockd/bind.h
+1
-0
include/linux/lockd/lockd.h
include/linux/lockd/lockd.h
+3
-1
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+7
-10
include/linux/nfs_fs_sb.h
include/linux/nfs_fs_sb.h
+0
-6
include/linux/nfs_mount.h
include/linux/nfs_mount.h
+2
-1
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+4
-3
include/linux/nfsd/state.h
include/linux/nfsd/state.h
+2
-0
include/linux/sunrpc/clnt.h
include/linux/sunrpc/clnt.h
+2
-0
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/sunrpc/rpc_pipe_fs.h
+1
-0
include/linux/sunrpc/svcauth_gss.h
include/linux/sunrpc/svcauth_gss.h
+1
-0
include/linux/sunrpc/xdr.h
include/linux/sunrpc/xdr.h
+0
-15
include/linux/sunrpc/xprt.h
include/linux/sunrpc/xprt.h
+1
-2
net/sunrpc/auth.c
net/sunrpc/auth.c
+3
-3
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/auth_gss.c
+239
-56
net/sunrpc/auth_gss/gss_generic_token.c
net/sunrpc/auth_gss/gss_generic_token.c
+3
-3
net/sunrpc/auth_gss/gss_mech_switch.c
net/sunrpc/auth_gss/gss_mech_switch.c
+9
-9
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_gss/svcauth_gss.c
+26
-2
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+16
-0
net/sunrpc/rpc_pipe.c
net/sunrpc/rpc_pipe.c
+29
-13
net/sunrpc/xdr.c
net/sunrpc/xdr.c
+25
-25
未找到文件。
fs/lockd/clntlock.c
浏览文件 @
08cc36cb
...
...
@@ -14,6 +14,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/lockd/lockd.h>
#include <linux/smp_lock.h>
#include <linux/kthread.h>
#define NLMDBG_FACILITY NLMDBG_CLIENT
...
...
@@ -60,7 +61,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
host
=
nlmclnt_lookup_host
(
nlm_init
->
address
,
nlm_init
->
addrlen
,
nlm_init
->
protocol
,
nlm_version
,
nlm_init
->
hostname
);
nlm_init
->
hostname
,
nlm_init
->
noresvport
);
if
(
host
==
NULL
)
{
lockd_down
();
return
ERR_PTR
(
-
ENOLCK
);
...
...
@@ -191,11 +192,15 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
void
nlmclnt_recovery
(
struct
nlm_host
*
host
)
{
struct
task_struct
*
task
;
if
(
!
host
->
h_reclaiming
++
)
{
nlm_get_host
(
host
);
__module_get
(
THIS_MODULE
);
if
(
kernel_thread
(
reclaimer
,
host
,
CLONE_FS
|
CLONE_FILES
)
<
0
)
module_put
(
THIS_MODULE
);
task
=
kthread_run
(
reclaimer
,
host
,
"%s-reclaim"
,
host
->
h_name
);
if
(
IS_ERR
(
task
))
printk
(
KERN_ERR
"lockd: unable to spawn reclaimer "
"thread. Locks for %s won't be reclaimed! "
"(%ld)
\n
"
,
host
->
h_name
,
PTR_ERR
(
task
));
}
}
...
...
@@ -207,7 +212,6 @@ reclaimer(void *ptr)
struct
file_lock
*
fl
,
*
next
;
u32
nsmstate
;
daemonize
(
"%s-reclaim"
,
host
->
h_name
);
allow_signal
(
SIGKILL
);
down_write
(
&
host
->
h_rwsem
);
...
...
@@ -233,7 +237,12 @@ reclaimer(void *ptr)
list_for_each_entry_safe
(
fl
,
next
,
&
host
->
h_reclaim
,
fl_u
.
nfs_fl
.
list
)
{
list_del_init
(
&
fl
->
fl_u
.
nfs_fl
.
list
);
/* Why are we leaking memory here? --okir */
/*
* sending this thread a SIGKILL will result in any unreclaimed
* locks being removed from the h_granted list. This means that
* the kernel will not attempt to reclaim them again if a new
* reclaimer thread is spawned for this host.
*/
if
(
signalled
())
continue
;
if
(
nlmclnt_reclaim
(
host
,
fl
)
!=
0
)
...
...
@@ -261,5 +270,5 @@ reclaimer(void *ptr)
nlm_release_host
(
host
);
lockd_down
();
unlock_kernel
();
module_put_and_exit
(
0
)
;
return
0
;
}
fs/lockd/host.c
浏览文件 @
08cc36cb
...
...
@@ -48,6 +48,7 @@ struct nlm_lookup_host_info {
const
size_t
hostname_len
;
/* it's length */
const
struct
sockaddr
*
src_sap
;
/* our address (optional) */
const
size_t
src_len
;
/* it's length */
const
int
noresvport
;
/* use non-priv port */
};
/*
...
...
@@ -222,6 +223,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
host
->
h_nsmstate
=
0
;
/* real NSM state */
host
->
h_nsmhandle
=
nsm
;
host
->
h_server
=
ni
->
server
;
host
->
h_noresvport
=
ni
->
noresvport
;
hlist_add_head
(
&
host
->
h_hash
,
chain
);
INIT_LIST_HEAD
(
&
host
->
h_lockowners
);
spin_lock_init
(
&
host
->
h_lock
);
...
...
@@ -272,6 +274,7 @@ nlm_destroy_host(struct nlm_host *host)
* @protocol: transport protocol to use
* @version: NLM protocol version
* @hostname: '\0'-terminated hostname of server
* @noresvport: 1 if non-privileged port should be used
*
* Returns an nlm_host structure that matches the passed-in
* [server address, transport protocol, NLM version, server hostname].
...
...
@@ -281,7 +284,9 @@ nlm_destroy_host(struct nlm_host *host)
struct
nlm_host
*
nlmclnt_lookup_host
(
const
struct
sockaddr
*
sap
,
const
size_t
salen
,
const
unsigned
short
protocol
,
const
u32
version
,
const
char
*
hostname
)
const
u32
version
,
const
char
*
hostname
,
int
noresvport
)
{
const
struct
sockaddr
source
=
{
.
sa_family
=
AF_UNSPEC
,
...
...
@@ -296,6 +301,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
.
hostname_len
=
strlen
(
hostname
),
.
src_sap
=
&
source
,
.
src_len
=
sizeof
(
source
),
.
noresvport
=
noresvport
,
};
dprintk
(
"lockd: %s(host='%s', vers=%u, proto=%s)
\n
"
,
__func__
,
...
...
@@ -417,6 +423,8 @@ nlm_bind_host(struct nlm_host *host)
*/
if
(
!
host
->
h_server
)
args
.
flags
|=
RPC_CLNT_CREATE_HARDRTRY
;
if
(
host
->
h_noresvport
)
args
.
flags
|=
RPC_CLNT_CREATE_NONPRIVPORT
;
clnt
=
rpc_create
(
&
args
);
if
(
!
IS_ERR
(
clnt
))
...
...
fs/lockd/svc.c
浏览文件 @
08cc36cb
...
...
@@ -45,7 +45,7 @@
static
struct
svc_program
nlmsvc_program
;
struct
nlmsvc_binding
*
nlmsvc_ops
;
EXPORT_SYMBOL
(
nlmsvc_ops
);
EXPORT_SYMBOL
_GPL
(
nlmsvc_ops
);
static
DEFINE_MUTEX
(
nlmsvc_mutex
);
static
unsigned
int
nlmsvc_users
;
...
...
@@ -300,7 +300,7 @@ int lockd_up(void)
mutex_unlock
(
&
nlmsvc_mutex
);
return
error
;
}
EXPORT_SYMBOL
(
lockd_up
);
EXPORT_SYMBOL
_GPL
(
lockd_up
);
/*
* Decrement the user count and bring down lockd if we're the last.
...
...
@@ -329,7 +329,7 @@ lockd_down(void)
out:
mutex_unlock
(
&
nlmsvc_mutex
);
}
EXPORT_SYMBOL
(
lockd_down
);
EXPORT_SYMBOL
_GPL
(
lockd_down
);
#ifdef CONFIG_SYSCTL
...
...
fs/nfs/callback.c
浏览文件 @
08cc36cb
...
...
@@ -16,6 +16,7 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <net/inet_sock.h>
...
...
@@ -182,10 +183,34 @@ void nfs_callback_down(void)
mutex_unlock
(
&
nfs_callback_mutex
);
}
static
int
check_gss_callback_principal
(
struct
nfs_client
*
clp
,
struct
svc_rqst
*
rqstp
)
{
struct
rpc_clnt
*
r
=
clp
->
cl_rpcclient
;
char
*
p
=
svc_gss_principal
(
rqstp
);
/*
* It might just be a normal user principal, in which case
* userspace won't bother to tell us the name at all.
*/
if
(
p
==
NULL
)
return
SVC_DENIED
;
/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
if
(
memcmp
(
p
,
"nfs@"
,
4
)
!=
0
)
return
SVC_DENIED
;
p
+=
4
;
if
(
strcmp
(
p
,
r
->
cl_server
)
!=
0
)
return
SVC_DENIED
;
return
SVC_OK
;
}
static
int
nfs_callback_authenticate
(
struct
svc_rqst
*
rqstp
)
{
struct
nfs_client
*
clp
;
RPC_IFDEBUG
(
char
buf
[
RPC_MAX_ADDRBUFLEN
]);
int
ret
=
SVC_OK
;
/* Don't talk to strangers */
clp
=
nfs_find_client
(
svc_addr
(
rqstp
),
4
);
...
...
@@ -194,21 +219,22 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
dprintk
(
"%s: %s NFSv4 callback!
\n
"
,
__func__
,
svc_print_addr
(
rqstp
,
buf
,
sizeof
(
buf
)));
nfs_put_client
(
clp
);
switch
(
rqstp
->
rq_authop
->
flavour
)
{
case
RPC_AUTH_NULL
:
if
(
rqstp
->
rq_proc
!=
CB_NULL
)
ret
urn
SVC_DENIED
;
ret
=
SVC_DENIED
;
break
;
case
RPC_AUTH_UNIX
:
break
;
case
RPC_AUTH_GSS
:
/* FIXME: RPCSEC_GSS handling? */
ret
=
check_gss_callback_principal
(
clp
,
rqstp
);
break
;
default:
ret
urn
SVC_DENIED
;
ret
=
SVC_DENIED
;
}
return
SVC_OK
;
nfs_put_client
(
clp
);
return
ret
;
}
/*
...
...
fs/nfs/client.c
浏览文件 @
08cc36cb
...
...
@@ -143,7 +143,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
clp
->
cl_proto
=
cl_init
->
proto
;
#ifdef CONFIG_NFS_V4
init_rwsem
(
&
clp
->
cl_sem
);
INIT_LIST_HEAD
(
&
clp
->
cl_delegations
);
spin_lock_init
(
&
clp
->
cl_lock
);
INIT_DELAYED_WORK
(
&
clp
->
cl_renewd
,
nfs4_renew_state
);
...
...
@@ -224,31 +223,54 @@ void nfs_put_client(struct nfs_client *clp)
}
}
static
int
nfs_sockaddr_match_ipaddr4
(
const
struct
sockaddr_in
*
sa1
,
const
struct
sockaddr_in
*
sa2
)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static
const
struct
in6_addr
*
nfs_map_ipv4_addr
(
const
struct
sockaddr
*
sa
,
struct
in6_addr
*
addr_mapped
)
{
return
sa1
->
sin_addr
.
s_addr
==
sa2
->
sin_addr
.
s_addr
;
switch
(
sa
->
sa_family
)
{
default:
return
NULL
;
case
AF_INET6
:
return
&
((
const
struct
sockaddr_in6
*
)
sa
)
->
sin6_addr
;
break
;
case
AF_INET
:
ipv6_addr_set_v4mapped
(((
const
struct
sockaddr_in
*
)
sa
)
->
sin_addr
.
s_addr
,
addr_mapped
);
return
addr_mapped
;
}
}
static
int
nfs_sockaddr_match_ipaddr6
(
const
struct
sockaddr_in6
*
sa1
,
const
struct
sockaddr_in6
*
sa2
)
static
int
nfs_sockaddr_match_ipaddr
(
const
struct
sockaddr
*
sa1
,
const
struct
sockaddr
*
sa2
)
{
const
struct
in6_addr
*
addr1
;
const
struct
in6_addr
*
addr2
;
struct
in6_addr
addr1_mapped
;
struct
in6_addr
addr2_mapped
;
addr1
=
nfs_map_ipv4_addr
(
sa1
,
&
addr1_mapped
);
if
(
likely
(
addr1
!=
NULL
))
{
addr2
=
nfs_map_ipv4_addr
(
sa2
,
&
addr2_mapped
);
if
(
likely
(
addr2
!=
NULL
))
return
ipv6_addr_equal
(
addr1
,
addr2
);
}
return
0
;
}
#else
static
int
nfs_sockaddr_match_ipaddr4
(
const
struct
sockaddr_in
*
sa1
,
const
struct
sockaddr_in
*
sa2
)
{
return
ipv6_addr_equal
(
&
sa1
->
sin6_addr
,
&
sa2
->
sin6_addr
)
;
return
sa1
->
sin_addr
.
s_addr
==
sa2
->
sin_addr
.
s_addr
;
}
static
int
nfs_sockaddr_match_ipaddr
(
const
struct
sockaddr
*
sa1
,
const
struct
sockaddr
*
sa2
)
{
switch
(
sa1
->
sa_family
)
{
case
AF_INET
:
return
nfs_sockaddr_match_ipaddr4
((
const
struct
sockaddr_in
*
)
sa1
,
(
const
struct
sockaddr_in
*
)
sa2
);
case
AF_INET6
:
return
nfs_sockaddr_match_ipaddr6
((
const
struct
sockaddr_in6
*
)
sa1
,
(
const
struct
sockaddr_in6
*
)
sa2
);
}
BUG
();
if
(
unlikely
(
sa1
->
sa_family
!=
AF_INET
||
sa2
->
sa_family
!=
AF_INET
))
return
0
;
return
nfs_sockaddr_match_ipaddr4
((
const
struct
sockaddr_in
*
)
sa1
,
(
const
struct
sockaddr_in
*
)
sa2
);
}
#endif
/*
* Find a client by IP address and protocol version
...
...
@@ -270,8 +292,6 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
if
(
clp
->
rpc_ops
->
version
!=
nfsversion
)
continue
;
if
(
addr
->
sa_family
!=
clap
->
sa_family
)
continue
;
/* Match only the IP address, not the port number */
if
(
!
nfs_sockaddr_match_ipaddr
(
addr
,
clap
))
continue
;
...
...
@@ -305,8 +325,6 @@ struct nfs_client *nfs_find_client_next(struct nfs_client *clp)
if
(
clp
->
rpc_ops
->
version
!=
nfsvers
)
continue
;
if
(
sap
->
sa_family
!=
clap
->
sa_family
)
continue
;
/* Match only the IP address, not the port number */
if
(
!
nfs_sockaddr_match_ipaddr
(
sap
,
clap
))
continue
;
...
...
@@ -470,7 +488,7 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
static
int
nfs_create_rpc_client
(
struct
nfs_client
*
clp
,
const
struct
rpc_timeout
*
timeparms
,
rpc_authflavor_t
flavor
,
int
flags
)
int
discrtry
,
int
noresvport
)
{
struct
rpc_clnt
*
clnt
=
NULL
;
struct
rpc_create_args
args
=
{
...
...
@@ -482,9 +500,13 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
.
program
=
&
nfs_program
,
.
version
=
clp
->
rpc_ops
->
version
,
.
authflavor
=
flavor
,
.
flags
=
flags
,
};
if
(
discrtry
)
args
.
flags
|=
RPC_CLNT_CREATE_DISCRTRY
;
if
(
noresvport
)
args
.
flags
|=
RPC_CLNT_CREATE_NONPRIVPORT
;
if
(
!
IS_ERR
(
clp
->
cl_rpcclient
))
return
0
;
...
...
@@ -522,6 +544,8 @@ static int nfs_start_lockd(struct nfs_server *server)
.
protocol
=
server
->
flags
&
NFS_MOUNT_TCP
?
IPPROTO_TCP
:
IPPROTO_UDP
,
.
nfs_version
=
clp
->
rpc_ops
->
version
,
.
noresvport
=
server
->
flags
&
NFS_MOUNT_NORESVPORT
?
1
:
0
,
};
if
(
nlm_init
.
nfs_version
>
3
)
...
...
@@ -623,7 +647,8 @@ static int nfs_init_client(struct nfs_client *clp,
* Create a client RPC handle for doing FSSTAT with UNIX auth only
* - RFC 2623, sec 2.3.2
*/
error
=
nfs_create_rpc_client
(
clp
,
timeparms
,
RPC_AUTH_UNIX
,
0
);
error
=
nfs_create_rpc_client
(
clp
,
timeparms
,
RPC_AUTH_UNIX
,
0
,
data
->
flags
&
NFS_MOUNT_NORESVPORT
);
if
(
error
<
0
)
goto
error
;
nfs_mark_client_ready
(
clp
,
NFS_CS_READY
);
...
...
@@ -965,7 +990,8 @@ struct nfs_server *nfs_create_server(const struct nfs_parsed_mount_data *data,
static
int
nfs4_init_client
(
struct
nfs_client
*
clp
,
const
struct
rpc_timeout
*
timeparms
,
const
char
*
ip_addr
,
rpc_authflavor_t
authflavour
)
rpc_authflavor_t
authflavour
,
int
flags
)
{
int
error
;
...
...
@@ -979,7 +1005,7 @@ static int nfs4_init_client(struct nfs_client *clp,
clp
->
rpc_ops
=
&
nfs_v4_clientops
;
error
=
nfs_create_rpc_client
(
clp
,
timeparms
,
authflavour
,
RPC_CLNT_CREATE_DISCRTRY
);
1
,
flags
&
NFS_MOUNT_NORESVPORT
);
if
(
error
<
0
)
goto
error
;
memcpy
(
clp
->
cl_ipaddr
,
ip_addr
,
sizeof
(
clp
->
cl_ipaddr
));
...
...
@@ -1030,7 +1056,8 @@ static int nfs4_set_client(struct nfs_server *server,
error
=
PTR_ERR
(
clp
);
goto
error
;
}
error
=
nfs4_init_client
(
clp
,
timeparms
,
ip_addr
,
authflavour
);
error
=
nfs4_init_client
(
clp
,
timeparms
,
ip_addr
,
authflavour
,
server
->
flags
);
if
(
error
<
0
)
goto
error_put
;
...
...
@@ -1059,6 +1086,10 @@ static int nfs4_init_server(struct nfs_server *server,
nfs_init_timeout_values
(
&
timeparms
,
data
->
nfs_server
.
protocol
,
data
->
timeo
,
data
->
retrans
);
/* Initialise the client representation from the mount data */
server
->
flags
=
data
->
flags
;
server
->
caps
|=
NFS_CAP_ATOMIC_OPEN
;
/* Get a client record */
error
=
nfs4_set_client
(
server
,
data
->
nfs_server
.
hostname
,
...
...
@@ -1071,10 +1102,6 @@ static int nfs4_init_server(struct nfs_server *server,
if
(
error
<
0
)
goto
error
;
/* Initialise the client representation from the mount data */
server
->
flags
=
data
->
flags
;
server
->
caps
|=
NFS_CAP_ATOMIC_OPEN
;
if
(
data
->
rsize
)
server
->
rsize
=
nfs_block_size
(
data
->
rsize
,
NULL
);
if
(
data
->
wsize
)
...
...
@@ -1177,6 +1204,10 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
parent_server
=
NFS_SB
(
data
->
sb
);
parent_client
=
parent_server
->
nfs_client
;
/* Initialise the client representation from the parent server */
nfs_server_copy_userdata
(
server
,
parent_server
);
server
->
caps
|=
NFS_CAP_ATOMIC_OPEN
;
/* Get a client representation.
* Note: NFSv4 always uses TCP, */
error
=
nfs4_set_client
(
server
,
data
->
hostname
,
...
...
@@ -1189,10 +1220,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
if
(
error
<
0
)
goto
error
;
/* Initialise the client representation from the parent server */
nfs_server_copy_userdata
(
server
,
parent_server
);
server
->
caps
|=
NFS_CAP_ATOMIC_OPEN
;
error
=
nfs_init_server_rpcclient
(
server
,
parent_server
->
client
->
cl_timeout
,
data
->
authflavor
);
if
(
error
<
0
)
goto
error
;
...
...
fs/nfs/delegation.c
浏览文件 @
08cc36cb
...
...
@@ -43,6 +43,27 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
put_rpccred
(
cred
);
}
void
nfs_mark_delegation_referenced
(
struct
nfs_delegation
*
delegation
)
{
set_bit
(
NFS_DELEGATION_REFERENCED
,
&
delegation
->
flags
);
}
int
nfs_have_delegation
(
struct
inode
*
inode
,
fmode_t
flags
)
{
struct
nfs_delegation
*
delegation
;
int
ret
=
0
;
flags
&=
FMODE_READ
|
FMODE_WRITE
;
rcu_read_lock
();
delegation
=
rcu_dereference
(
NFS_I
(
inode
)
->
delegation
);
if
(
delegation
!=
NULL
&&
(
delegation
->
type
&
flags
)
==
flags
)
{
nfs_mark_delegation_referenced
(
delegation
);
ret
=
1
;
}
rcu_read_unlock
();
return
ret
;
}
static
int
nfs_delegation_claim_locks
(
struct
nfs_open_context
*
ctx
,
struct
nfs4_state
*
state
)
{
struct
inode
*
inode
=
state
->
inode
;
...
...
@@ -119,7 +140,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
delegation
->
maxsize
=
res
->
maxsize
;
oldcred
=
delegation
->
cred
;
delegation
->
cred
=
get_rpccred
(
cred
);
delegation
->
flags
&=
~
NFS_DELEGATION_NEED_RECLAIM
;
clear_bit
(
NFS_DELEGATION_NEED_RECLAIM
,
&
delegation
->
flags
)
;
NFS_I
(
inode
)
->
delegation_state
=
delegation
->
type
;
smp_wmb
();
put_rpccred
(
oldcred
);
...
...
@@ -134,19 +155,35 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
return
res
;
}
static
struct
inode
*
nfs_delegation_grab_inode
(
struct
nfs_delegation
*
delegation
)
{
struct
inode
*
inode
=
NULL
;
spin_lock
(
&
delegation
->
lock
);
if
(
delegation
->
inode
!=
NULL
)
inode
=
igrab
(
delegation
->
inode
);
spin_unlock
(
&
delegation
->
lock
);
return
inode
;
}
static
struct
nfs_delegation
*
nfs_detach_delegation_locked
(
struct
nfs_inode
*
nfsi
,
const
nfs4_stateid
*
stateid
)
{
struct
nfs_delegation
*
delegation
=
rcu_dereference
(
nfsi
->
delegation
);
if
(
delegation
==
NULL
)
goto
nomatch
;
spin_lock
(
&
delegation
->
lock
);
if
(
stateid
!=
NULL
&&
memcmp
(
delegation
->
stateid
.
data
,
stateid
->
data
,
sizeof
(
delegation
->
stateid
.
data
))
!=
0
)
goto
nomatch
;
goto
nomatch
_unlock
;
list_del_rcu
(
&
delegation
->
super_list
);
delegation
->
inode
=
NULL
;
nfsi
->
delegation_state
=
0
;
rcu_assign_pointer
(
nfsi
->
delegation
,
NULL
);
spin_unlock
(
&
delegation
->
lock
);
return
delegation
;
nomatch_unlock:
spin_unlock
(
&
delegation
->
lock
);
nomatch:
return
NULL
;
}
...
...
@@ -172,6 +209,8 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
delegation
->
change_attr
=
nfsi
->
change_attr
;
delegation
->
cred
=
get_rpccred
(
cred
);
delegation
->
inode
=
inode
;
delegation
->
flags
=
1
<<
NFS_DELEGATION_REFERENCED
;
spin_lock_init
(
&
delegation
->
lock
);
spin_lock
(
&
clp
->
cl_lock
);
if
(
rcu_dereference
(
nfsi
->
delegation
)
!=
NULL
)
{
...
...
@@ -226,21 +265,46 @@ static void nfs_msync_inode(struct inode *inode)
*/
static
int
__nfs_inode_return_delegation
(
struct
inode
*
inode
,
struct
nfs_delegation
*
delegation
)
{
struct
nfs_client
*
clp
=
NFS_SERVER
(
inode
)
->
nfs_client
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
nfs_msync_inode
(
inode
);
down_read
(
&
clp
->
cl_sem
);
/* Guard against new delegated open calls */
down_write
(
&
nfsi
->
rwsem
);
nfs_delegation_claim_opens
(
inode
,
&
delegation
->
stateid
);
up_write
(
&
nfsi
->
rwsem
);
up_read
(
&
clp
->
cl_sem
);
nfs_msync_inode
(
inode
);
return
nfs_do_return_delegation
(
inode
,
delegation
,
1
);
}
/*
* Return all delegations that have been marked for return
*/
void
nfs_client_return_marked_delegations
(
struct
nfs_client
*
clp
)
{
struct
nfs_delegation
*
delegation
;
struct
inode
*
inode
;
restart:
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
if
(
!
test_and_clear_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
))
continue
;
inode
=
nfs_delegation_grab_inode
(
delegation
);
if
(
inode
==
NULL
)
continue
;
spin_lock
(
&
clp
->
cl_lock
);
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
);
iput
(
inode
);
goto
restart
;
}
rcu_read_unlock
();
}
/*
* This function returns the delegation without reclaiming opens
* or protecting against delegation reclaims.
...
...
@@ -279,83 +343,55 @@ int nfs_inode_return_delegation(struct inode *inode)
return
err
;
}
static
void
nfs_mark_return_delegation
(
struct
nfs_client
*
clp
,
struct
nfs_delegation
*
delegation
)
{
set_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
);
set_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
);
}
/*
* Return all delegations associated to a super block
*/
void
nfs_return_all_delegations
(
struct
super_block
*
sb
)
void
nfs_
super_
return_all_delegations
(
struct
super_block
*
sb
)
{
struct
nfs_client
*
clp
=
NFS_SB
(
sb
)
->
nfs_client
;
struct
nfs_delegation
*
delegation
;
struct
inode
*
inode
;
if
(
clp
==
NULL
)
return
;
restart:
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
if
(
delegation
->
inode
->
i_sb
!=
sb
)
continue
;
inode
=
igrab
(
delegation
->
inode
);
if
(
inode
==
NULL
)
continue
;
spin_lock
(
&
clp
->
cl_lock
);
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
);
iput
(
inode
);
goto
restart
;
spin_lock
(
&
delegation
->
lock
);
if
(
delegation
->
inode
!=
NULL
&&
delegation
->
inode
->
i_sb
==
sb
)
set_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
);
spin_unlock
(
&
delegation
->
lock
);
}
rcu_read_unlock
();
nfs_client_return_marked_delegations
(
clp
);
}
static
int
nfs_do_expire_all_delegations
(
void
*
ptr
)
static
void
nfs_client_mark_return_all_delegations
(
struct
nfs_client
*
clp
)
{
struct
nfs_client
*
clp
=
ptr
;
struct
nfs_delegation
*
delegation
;
struct
inode
*
inode
;
allow_signal
(
SIGKILL
);
restart:
if
(
test_bit
(
NFS4CLNT_STATE_RECOVER
,
&
clp
->
cl_state
)
!=
0
)
goto
out
;
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
)
==
0
)
goto
out
;
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
inode
=
igrab
(
delegation
->
inode
);
if
(
inode
==
NULL
)
continue
;
spin_lock
(
&
clp
->
cl_lock
);
delegation
=
nfs_detach_delegation_locked
(
NFS_I
(
inode
),
NULL
);
spin_unlock
(
&
clp
->
cl_lock
);
rcu_read_unlock
();
if
(
delegation
)
__nfs_inode_return_delegation
(
inode
,
delegation
);
iput
(
inode
);
goto
restart
;
set_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
);
set_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
);
}
rcu_read_unlock
();
out:
nfs_put_client
(
clp
);
module_put_and_exit
(
0
);
}
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_delegations
(
struct
nfs_client
*
clp
)
{
struct
task_struct
*
task
;
__module_get
(
THIS_MODULE
);
atomic_inc
(
&
clp
->
cl_count
);
task
=
kthread_run
(
nfs_do_expire_all_delegations
,
clp
,
"%s-delegreturn"
,
rpc_peeraddr2str
(
clp
->
cl_rpcclient
,
RPC_DISPLAY_ADDR
));
if
(
!
IS_ERR
(
task
))
return
;
nfs_put_client
(
clp
);
module_put
(
THIS_MODULE
);
nfs_client_mark_return_all_delegations
(
clp
);
nfs_delegation_run_state_manager
(
clp
);
}
/*
...
...
@@ -363,68 +399,29 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
*/
void
nfs_handle_cb_pathdown
(
struct
nfs_client
*
clp
)
{
struct
nfs_delegation
*
delegation
;
struct
inode
*
inode
;
if
(
clp
==
NULL
)
return
;
restart:
nfs_client_mark_return_all_delegations
(
clp
);
}
static
void
nfs_client_mark_return_unreferenced_delegations
(
struct
nfs_client
*
clp
)
{
struct
nfs_delegation
*
delegation
;
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
inode
=
igrab
(
delegation
->
inode
);
if
(
inode
==
NULL
)
if
(
test_and_clear_bit
(
NFS_DELEGATION_REFERENCED
,
&
delegation
->
flags
))
continue
;
spin_lock
(
&
clp
->
cl_lock
);
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
);
iput
(
inode
);
goto
restart
;
set_bit
(
NFS_DELEGATION_RETURN
,
&
delegation
->
flags
);
set_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
);
}
rcu_read_unlock
();
}
struct
recall_threadargs
{
struct
inode
*
inode
;
struct
nfs_client
*
clp
;
const
nfs4_stateid
*
stateid
;
struct
completion
started
;
int
result
;
};
static
int
recall_thread
(
void
*
data
)
void
nfs_expire_unreferenced_delegations
(
struct
nfs_client
*
clp
)
{
struct
recall_threadargs
*
args
=
(
struct
recall_threadargs
*
)
data
;
struct
inode
*
inode
=
igrab
(
args
->
inode
);
struct
nfs_client
*
clp
=
NFS_SERVER
(
inode
)
->
nfs_client
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
struct
nfs_delegation
*
delegation
;
daemonize
(
"nfsv4-delegreturn"
);
nfs_msync_inode
(
inode
);
down_read
(
&
clp
->
cl_sem
);
down_write
(
&
nfsi
->
rwsem
);
spin_lock
(
&
clp
->
cl_lock
);
delegation
=
nfs_detach_delegation_locked
(
nfsi
,
args
->
stateid
);
if
(
delegation
!=
NULL
)
args
->
result
=
0
;
else
args
->
result
=
-
ENOENT
;
spin_unlock
(
&
clp
->
cl_lock
);
complete
(
&
args
->
started
);
nfs_delegation_claim_opens
(
inode
,
args
->
stateid
);
up_write
(
&
nfsi
->
rwsem
);
up_read
(
&
clp
->
cl_sem
);
nfs_msync_inode
(
inode
);
if
(
delegation
!=
NULL
)
nfs_do_return_delegation
(
inode
,
delegation
,
1
);
iput
(
inode
);
module_put_and_exit
(
0
);
nfs_client_mark_return_unreferenced_delegations
(
clp
);
nfs_delegation_run_state_manager
(
clp
);
}
/*
...
...
@@ -432,22 +429,20 @@ static int recall_thread(void *data)
*/
int
nfs_async_inode_return_delegation
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
)
{
struct
recall_threadargs
data
=
{
.
inode
=
inode
,
.
stateid
=
stateid
,
};
int
status
;
struct
nfs_client
*
clp
=
NFS_SERVER
(
inode
)
->
nfs_client
;
struct
nfs_delegation
*
delegation
;
init_completion
(
&
data
.
started
);
__module_get
(
THIS_MODULE
);
status
=
kernel_thread
(
recall_thread
,
&
data
,
CLONE_KERNEL
);
if
(
status
<
0
)
goto
out_module_put
;
wait_for_completion
(
&
data
.
started
);
return
data
.
result
;
out_module_put:
module_put
(
THIS_MODULE
);
return
status
;
rcu_read_lock
();
delegation
=
rcu_dereference
(
NFS_I
(
inode
)
->
delegation
);
if
(
delegation
==
NULL
||
memcmp
(
delegation
->
stateid
.
data
,
stateid
->
data
,
sizeof
(
delegation
->
stateid
.
data
))
!=
0
)
{
rcu_read_unlock
();
return
-
ENOENT
;
}
nfs_mark_return_delegation
(
clp
,
delegation
);
rcu_read_unlock
();
nfs_delegation_run_state_manager
(
clp
);
return
0
;
}
/*
...
...
@@ -459,10 +454,14 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
struct
inode
*
res
=
NULL
;
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
if
(
nfs_compare_fh
(
fhandle
,
&
NFS_I
(
delegation
->
inode
)
->
fh
)
==
0
)
{
spin_lock
(
&
delegation
->
lock
);
if
(
delegation
->
inode
!=
NULL
&&
nfs_compare_fh
(
fhandle
,
&
NFS_I
(
delegation
->
inode
)
->
fh
)
==
0
)
{
res
=
igrab
(
delegation
->
inode
);
break
;
}
spin_unlock
(
&
delegation
->
lock
);
if
(
res
!=
NULL
)
break
;
}
rcu_read_unlock
();
return
res
;
...
...
@@ -476,7 +475,7 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
struct
nfs_delegation
*
delegation
;
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
delegation
->
flags
|=
NFS_DELEGATION_NEED_RECLAIM
;
set_bit
(
NFS_DELEGATION_NEED_RECLAIM
,
&
delegation
->
flags
)
;
rcu_read_unlock
();
}
...
...
@@ -486,17 +485,22 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
void
nfs_delegation_reap_unclaimed
(
struct
nfs_client
*
clp
)
{
struct
nfs_delegation
*
delegation
;
struct
inode
*
inode
;
restart:
rcu_read_lock
();
list_for_each_entry_rcu
(
delegation
,
&
clp
->
cl_delegations
,
super_list
)
{
if
((
delegation
->
flags
&
NFS_DELEGATION_NEED_RECLAIM
)
==
0
)
if
(
test_bit
(
NFS_DELEGATION_NEED_RECLAIM
,
&
delegation
->
flags
)
==
0
)
continue
;
inode
=
nfs_delegation_grab_inode
(
delegation
);
if
(
inode
==
NULL
)
continue
;
spin_lock
(
&
clp
->
cl_lock
);
delegation
=
nfs_detach_delegation_locked
(
NFS_I
(
delegation
->
inode
),
NULL
);
delegation
=
nfs_detach_delegation_locked
(
NFS_I
(
inode
),
NULL
);
spin_unlock
(
&
clp
->
cl_lock
);
rcu_read_unlock
();
if
(
delegation
!=
NULL
)
nfs_free_delegation
(
delegation
);
iput
(
inode
);
goto
restart
;
}
rcu_read_unlock
();
...
...
fs/nfs/delegation.h
浏览文件 @
08cc36cb
...
...
@@ -17,14 +17,20 @@ struct nfs_delegation {
struct
rpc_cred
*
cred
;
struct
inode
*
inode
;
nfs4_stateid
stateid
;
int
type
;
#define NFS_DELEGATION_NEED_RECLAIM 1
long
flags
;
fmode_t
type
;
loff_t
maxsize
;
__u64
change_attr
;
unsigned
long
flags
;
spinlock_t
lock
;
struct
rcu_head
rcu
;
};
enum
{
NFS_DELEGATION_NEED_RECLAIM
=
0
,
NFS_DELEGATION_RETURN
,
NFS_DELEGATION_REFERENCED
,
};
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
);
...
...
@@ -32,9 +38,11 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
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_return_all_delegations
(
struct
super_block
*
sb
);
void
nfs_
super_
return_all_delegations
(
struct
super_block
*
sb
);
void
nfs_expire_all_delegations
(
struct
nfs_client
*
clp
);
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
);
void
nfs_delegation_mark_reclaim
(
struct
nfs_client
*
clp
);
void
nfs_delegation_reap_unclaimed
(
struct
nfs_client
*
clp
);
...
...
@@ -45,22 +53,11 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
int
nfs4_lock_delegation_recall
(
struct
nfs4_state
*
state
,
struct
file_lock
*
fl
);
int
nfs4_copy_delegation_stateid
(
nfs4_stateid
*
dst
,
struct
inode
*
inode
);
static
inline
int
nfs_have_delegation
(
struct
inode
*
inode
,
int
flags
)
{
struct
nfs_delegation
*
delegation
;
int
ret
=
0
;
flags
&=
FMODE_READ
|
FMODE_WRITE
;
rcu_read_lock
();
delegation
=
rcu_dereference
(
NFS_I
(
inode
)
->
delegation
);
if
(
delegation
!=
NULL
&&
(
delegation
->
type
&
flags
)
==
flags
)
ret
=
1
;
rcu_read_unlock
();
return
ret
;
}
void
nfs_mark_delegation_referenced
(
struct
nfs_delegation
*
delegation
);
int
nfs_have_delegation
(
struct
inode
*
inode
,
fmode_t
flags
);
#else
static
inline
int
nfs_have_delegation
(
struct
inode
*
inode
,
in
t
flags
)
static
inline
int
nfs_have_delegation
(
struct
inode
*
inode
,
fmode_
t
flags
)
{
return
0
;
}
...
...
fs/nfs/dir.c
浏览文件 @
08cc36cb
...
...
@@ -799,6 +799,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
goto
out_bad
;
}
if
(
nfs_have_delegation
(
inode
,
FMODE_READ
))
goto
out_set_verifier
;
/* Force a full look up iff the parent directory has changed */
if
(
!
nfs_is_exclusive_create
(
dir
,
nd
)
&&
nfs_check_verifier
(
dir
,
dentry
))
{
if
(
nfs_lookup_verify_inode
(
inode
,
nd
))
...
...
@@ -817,6 +820,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
if
((
error
=
nfs_refresh_inode
(
inode
,
&
fattr
))
!=
0
)
goto
out_bad
;
out_set_verifier:
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dir
));
out_valid:
dput
(
parent
);
...
...
@@ -973,7 +977,7 @@ struct dentry_operations nfs4_dentry_operations = {
* Use intent information to determine whether we need to substitute
* the NFSv4-style stateful OPEN for the LOOKUP call
*/
static
int
is_atomic_open
(
struct
inode
*
dir
,
struct
nameidata
*
nd
)
static
int
is_atomic_open
(
struct
nameidata
*
nd
)
{
if
(
nd
==
NULL
||
nfs_lookup_check_intent
(
nd
,
LOOKUP_OPEN
)
==
0
)
return
0
;
...
...
@@ -996,7 +1000,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
dir
->
i_sb
->
s_id
,
dir
->
i_ino
,
dentry
->
d_name
.
name
);
/* Check that we are indeed trying to open this file */
if
(
!
is_atomic_open
(
dir
,
nd
))
if
(
!
is_atomic_open
(
nd
))
goto
no_open
;
if
(
dentry
->
d_name
.
len
>
NFS_SERVER
(
dir
)
->
namelen
)
{
...
...
@@ -1047,10 +1051,10 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
struct
inode
*
dir
;
int
openflags
,
ret
=
0
;
if
(
!
is_atomic_open
(
nd
))
goto
no_open
;
parent
=
dget_parent
(
dentry
);
dir
=
parent
->
d_inode
;
if
(
!
is_atomic_open
(
dir
,
nd
))
goto
no_open
;
/* We can't create new files in nfs_open_revalidate(), so we
* optimize away revalidation of negative dentries.
*/
...
...
@@ -1062,11 +1066,11 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
/* NFS only supports OPEN on regular files */
if
(
!
S_ISREG
(
inode
->
i_mode
))
goto
no_open
;
goto
no_open
_dput
;
openflags
=
nd
->
intent
.
open
.
flags
;
/* We cannot do exclusive creation on a positive dentry */
if
((
openflags
&
(
O_CREAT
|
O_EXCL
))
==
(
O_CREAT
|
O_EXCL
))
goto
no_open
;
goto
no_open
_dput
;
/* We can't create new files, or truncate existing ones here */
openflags
&=
~
(
O_CREAT
|
O_TRUNC
);
...
...
@@ -1081,10 +1085,9 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
if
(
!
ret
)
d_drop
(
dentry
);
return
ret
;
no_open:
no_open
_dput
:
dput
(
parent
);
if
(
inode
!=
NULL
&&
nfs_have_delegation
(
inode
,
FMODE_READ
))
return
1
;
no_open:
return
nfs_lookup_revalidate
(
dentry
,
nd
);
}
#endif
/* CONFIG_NFSV4 */
...
...
@@ -1794,7 +1797,8 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str
cache
=
nfs_access_search_rbtree
(
inode
,
cred
);
if
(
cache
==
NULL
)
goto
out
;
if
(
!
time_in_range
(
jiffies
,
cache
->
jiffies
,
cache
->
jiffies
+
nfsi
->
attrtimeo
))
if
(
!
nfs_have_delegation
(
inode
,
FMODE_READ
)
&&
!
time_in_range_open
(
jiffies
,
cache
->
jiffies
,
cache
->
jiffies
+
nfsi
->
attrtimeo
))
goto
out_stale
;
res
->
jiffies
=
cache
->
jiffies
;
res
->
cred
=
cache
->
cred
;
...
...
fs/nfs/inode.c
浏览文件 @
08cc36cb
...
...
@@ -592,7 +592,7 @@ static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context
/*
* Given an inode, search for an open context with the desired characteristics
*/
struct
nfs_open_context
*
nfs_find_open_context
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
in
t
mode
)
struct
nfs_open_context
*
nfs_find_open_context
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
fmode_
t
mode
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
struct
nfs_open_context
*
pos
,
*
ctx
=
NULL
;
...
...
@@ -712,14 +712,7 @@ int nfs_attribute_timeout(struct inode *inode)
if
(
nfs_have_delegation
(
inode
,
FMODE_READ
))
return
0
;
/*
* Special case: if the attribute timeout is set to 0, then always
* treat the cache as having expired (unless holding
* a delegation).
*/
if
(
nfsi
->
attrtimeo
==
0
)
return
1
;
return
!
time_in_range
(
jiffies
,
nfsi
->
read_cache_jiffies
,
nfsi
->
read_cache_jiffies
+
nfsi
->
attrtimeo
);
return
!
time_in_range_open
(
jiffies
,
nfsi
->
read_cache_jiffies
,
nfsi
->
read_cache_jiffies
+
nfsi
->
attrtimeo
);
}
/**
...
...
@@ -1182,7 +1175,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfsi
->
attrtimeo_timestamp
=
now
;
nfsi
->
attr_gencount
=
nfs_inc_attr_generation_counter
();
}
else
{
if
(
!
time_in_range
(
now
,
nfsi
->
attrtimeo_timestamp
,
nfsi
->
attrtimeo_timestamp
+
nfsi
->
attrtimeo
))
{
if
(
!
time_in_range
_open
(
now
,
nfsi
->
attrtimeo_timestamp
,
nfsi
->
attrtimeo_timestamp
+
nfsi
->
attrtimeo
))
{
if
((
nfsi
->
attrtimeo
<<=
1
)
>
NFS_MAXATTRTIMEO
(
inode
))
nfsi
->
attrtimeo
=
NFS_MAXATTRTIMEO
(
inode
);
nfsi
->
attrtimeo_timestamp
=
now
;
...
...
fs/nfs/internal.h
浏览文件 @
08cc36cb
...
...
@@ -63,6 +63,20 @@ struct nfs_parsed_mount_data {
struct
security_mnt_opts
lsm_opts
;
};
/* mount_clnt.c */
struct
nfs_mount_request
{
struct
sockaddr
*
sap
;
size_t
salen
;
char
*
hostname
;
char
*
dirpath
;
u32
version
;
unsigned
short
protocol
;
struct
nfs_fh
*
fh
;
int
noresvport
;
};
extern
int
nfs_mount
(
struct
nfs_mount_request
*
info
);
/* client.c */
extern
struct
rpc_program
nfs_program
;
...
...
fs/nfs/mount_clnt.c
浏览文件 @
08cc36cb
...
...
@@ -29,47 +29,43 @@ struct mnt_fhstatus {
/**
* nfs_mount - Obtain an NFS file handle for the given host and path
* @addr: pointer to server's address
* @len: size of server's address
* @hostname: name of server host, or NULL
* @path: pointer to string containing export path to mount
* @version: mount version to use for this request
* @protocol: transport protocol to use for thie request
* @fh: pointer to location to place returned file handle
* @info: pointer to mount request arguments
*
* Uses default timeout parameters specified by underlying transport.
*/
int
nfs_mount
(
struct
sockaddr
*
addr
,
size_t
len
,
char
*
hostname
,
char
*
path
,
int
version
,
int
protocol
,
struct
nfs_fh
*
fh
)
int
nfs_mount
(
struct
nfs_mount_request
*
info
)
{
struct
mnt_fhstatus
result
=
{
.
fh
=
fh
.
fh
=
info
->
fh
};
struct
rpc_message
msg
=
{
.
rpc_argp
=
path
,
.
rpc_argp
=
info
->
dir
path
,
.
rpc_resp
=
&
result
,
};
struct
rpc_create_args
args
=
{
.
protocol
=
protocol
,
.
address
=
addr
,
.
addrsize
=
len
,
.
servername
=
hostname
,
.
protocol
=
info
->
protocol
,
.
address
=
info
->
sap
,
.
addrsize
=
info
->
sa
len
,
.
servername
=
info
->
hostname
,
.
program
=
&
mnt_program
,
.
version
=
version
,
.
version
=
info
->
version
,
.
authflavor
=
RPC_AUTH_UNIX
,
.
flags
=
0
,
};
struct
rpc_clnt
*
mnt_clnt
;
int
status
;
dprintk
(
"NFS: sending MNT request for %s:%s
\n
"
,
(
hostname
?
hostname
:
"server"
),
path
);
(
info
->
hostname
?
info
->
hostname
:
"server"
),
info
->
dirpath
);
if
(
info
->
noresvport
)
args
.
flags
|=
RPC_CLNT_CREATE_NONPRIVPORT
;
mnt_clnt
=
rpc_create
(
&
args
);
if
(
IS_ERR
(
mnt_clnt
))
goto
out_clnt_err
;
if
(
version
==
NFS_MNT3_VERSION
)
if
(
info
->
version
==
NFS_MNT3_VERSION
)
msg
.
rpc_proc
=
&
mnt_clnt
->
cl_procinfo
[
MOUNTPROC3_MNT
];
else
msg
.
rpc_proc
=
&
mnt_clnt
->
cl_procinfo
[
MNTPROC_MNT
];
...
...
fs/nfs/nfs4_fs.h
浏览文件 @
08cc36cb
...
...
@@ -38,8 +38,12 @@ struct idmap;
((err) != NFSERR_NOFILEHANDLE))
enum
nfs4_client_state
{
NFS4CLNT_STATE_RECOVER
=
0
,
NFS4CLNT_MANAGER_RUNNING
=
0
,
NFS4CLNT_CHECK_LEASE
,
NFS4CLNT_LEASE_EXPIRED
,
NFS4CLNT_RECLAIM_REBOOT
,
NFS4CLNT_RECLAIM_NOGRACE
,
NFS4CLNT_DELEGRETURN
,
};
/*
...
...
@@ -90,12 +94,18 @@ struct nfs4_state_owner {
spinlock_t
so_lock
;
atomic_t
so_count
;
unsigned
long
so_flags
;
struct
list_head
so_states
;
struct
list_head
so_delegations
;
struct
nfs_seqid_counter
so_seqid
;
struct
rpc_sequence
so_sequence
;
};
enum
{
NFS_OWNER_RECLAIM_REBOOT
,
NFS_OWNER_RECLAIM_NOGRACE
};
/*
* struct nfs4_state maintains the client-side state for a given
* (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
...
...
@@ -128,6 +138,8 @@ enum {
NFS_O_RDONLY_STATE
,
/* OPEN stateid has read-only state */
NFS_O_WRONLY_STATE
,
/* OPEN stateid has write-only state */
NFS_O_RDWR_STATE
,
/* OPEN stateid has read/write state */
NFS_STATE_RECLAIM_REBOOT
,
/* OPEN stateid server rebooted */
NFS_STATE_RECLAIM_NOGRACE
,
/* OPEN stateid needs to recover state */
};
struct
nfs4_state
{
...
...
@@ -149,7 +161,7 @@ struct nfs4_state {
unsigned
int
n_rdonly
;
/* Number of read-only references */
unsigned
int
n_wronly
;
/* Number of write-only references */
unsigned
int
n_rdwr
;
/* Number of read/write references */
in
t
state
;
/* State on the server (R,W, or RW) */
fmode_
t
state
;
/* State on the server (R,W, or RW) */
atomic_t
count
;
};
...
...
@@ -157,9 +169,12 @@ struct nfs4_state {
struct
nfs4_exception
{
long
timeout
;
int
retry
;
struct
nfs4_state
*
state
;
};
struct
nfs4_state_recovery_ops
{
int
owner_flag_bit
;
int
state_flag_bit
;
int
(
*
recover_open
)(
struct
nfs4_state_owner
*
,
struct
nfs4_state
*
);
int
(
*
recover_lock
)(
struct
nfs4_state
*
,
struct
file_lock
*
);
};
...
...
@@ -174,7 +189,6 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
/* nfs4proc.c */
extern
int
nfs4_map_errors
(
int
err
);
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_async_renew
(
struct
nfs_client
*
,
struct
rpc_cred
*
);
...
...
@@ -187,7 +201,7 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
struct
nfs4_fs_locations
*
fs_locations
,
struct
page
*
page
);
extern
struct
nfs4_state_recovery_ops
nfs4_reboot_recovery_ops
;
extern
struct
nfs4_state_recovery_ops
nfs4_n
etwork_partition
_recovery_ops
;
extern
struct
nfs4_state_recovery_ops
nfs4_n
ograce
_recovery_ops
;
extern
const
u32
nfs4_fattr_bitmap
[
2
];
extern
const
u32
nfs4_statfs_bitmap
[
2
];
...
...
@@ -202,16 +216,18 @@ extern void nfs4_kill_renewd(struct nfs_client *);
extern
void
nfs4_renew_state
(
struct
work_struct
*
);
/* nfs4state.c */
struct
rpc_cred
*
nfs4_get_renew_cred
(
struct
nfs_client
*
clp
);
struct
rpc_cred
*
nfs4_get_renew_cred
_locked
(
struct
nfs_client
*
clp
);
extern
struct
nfs4_state_owner
*
nfs4_get_state_owner
(
struct
nfs_server
*
,
struct
rpc_cred
*
);
extern
void
nfs4_put_state_owner
(
struct
nfs4_state_owner
*
);
extern
struct
nfs4_state
*
nfs4_get_open_state
(
struct
inode
*
,
struct
nfs4_state_owner
*
);
extern
void
nfs4_put_open_state
(
struct
nfs4_state
*
);
extern
void
nfs4_close_state
(
struct
path
*
,
struct
nfs4_state
*
,
mode_t
);
extern
void
nfs4_close_sync
(
struct
path
*
,
struct
nfs4_state
*
,
mode_t
);
extern
void
nfs4_state_set_mode_locked
(
struct
nfs4_state
*
,
mode_t
);
extern
void
nfs4_close_state
(
struct
path
*
,
struct
nfs4_state
*
,
f
mode_t
);
extern
void
nfs4_close_sync
(
struct
path
*
,
struct
nfs4_state
*
,
f
mode_t
);
extern
void
nfs4_state_set_mode_locked
(
struct
nfs4_state
*
,
f
mode_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
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
);
...
...
fs/nfs/nfs4proc.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
fs/nfs/nfs4renewd.c
浏览文件 @
08cc36cb
...
...
@@ -65,7 +65,6 @@ nfs4_renew_state(struct work_struct *work)
long
lease
,
timeout
;
unsigned
long
last
,
now
;
down_read
(
&
clp
->
cl_sem
);
dprintk
(
"%s: start
\n
"
,
__func__
);
/* Are there any active superblocks? */
if
(
list_empty
(
&
clp
->
cl_superblocks
))
...
...
@@ -77,17 +76,19 @@ nfs4_renew_state(struct work_struct *work)
timeout
=
(
2
*
lease
)
/
3
+
(
long
)
last
-
(
long
)
now
;
/* Are we close to a lease timeout? */
if
(
time_after
(
now
,
last
+
lease
/
3
))
{
cred
=
nfs4_get_renew_cred
(
clp
);
cred
=
nfs4_get_renew_cred_locked
(
clp
);
spin_unlock
(
&
clp
->
cl_lock
);
if
(
cred
==
NULL
)
{
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
spin_unlock
(
&
clp
->
cl_lock
);
if
(
list_empty
(
&
clp
->
cl_delegations
))
{
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
goto
out
;
}
nfs_expire_all_delegations
(
clp
);
goto
out
;
}
else
{
/* Queue an asynchronous RENEW. */
nfs4_proc_async_renew
(
clp
,
cred
);
put_rpccred
(
cred
);
}
spin_unlock
(
&
clp
->
cl_lock
);
/* Queue an asynchronous RENEW. */
nfs4_proc_async_renew
(
clp
,
cred
);
put_rpccred
(
cred
);
timeout
=
(
2
*
lease
)
/
3
;
spin_lock
(
&
clp
->
cl_lock
);
}
else
...
...
@@ -100,12 +101,11 @@ nfs4_renew_state(struct work_struct *work)
cancel_delayed_work
(
&
clp
->
cl_renewd
);
schedule_delayed_work
(
&
clp
->
cl_renewd
,
timeout
);
spin_unlock
(
&
clp
->
cl_lock
);
nfs_expire_unreferenced_delegations
(
clp
);
out:
up_read
(
&
clp
->
cl_sem
);
dprintk
(
"%s: done
\n
"
,
__func__
);
}
/* Must be called with clp->cl_sem locked for writes */
void
nfs4_schedule_state_renewal
(
struct
nfs_client
*
clp
)
{
...
...
fs/nfs/nfs4state.c
浏览文件 @
08cc36cb
...
...
@@ -71,14 +71,12 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
return
status
;
}
static
struct
rpc_cred
*
nfs4_get_machine_cred
(
struct
nfs_client
*
clp
)
static
struct
rpc_cred
*
nfs4_get_machine_cred
_locked
(
struct
nfs_client
*
clp
)
{
struct
rpc_cred
*
cred
=
NULL
;
spin_lock
(
&
clp
->
cl_lock
);
if
(
clp
->
cl_machine_cred
!=
NULL
)
cred
=
get_rpccred
(
clp
->
cl_machine_cred
);
spin_unlock
(
&
clp
->
cl_lock
);
return
cred
;
}
...
...
@@ -94,7 +92,7 @@ static void nfs4_clear_machine_cred(struct nfs_client *clp)
put_rpccred
(
cred
);
}
struct
rpc_cred
*
nfs4_get_renew_cred
(
struct
nfs_client
*
clp
)
struct
rpc_cred
*
nfs4_get_renew_cred
_locked
(
struct
nfs_client
*
clp
)
{
struct
nfs4_state_owner
*
sp
;
struct
rb_node
*
pos
;
...
...
@@ -110,13 +108,24 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
return
cred
;
}
static
struct
rpc_cred
*
nfs4_get_renew_cred
(
struct
nfs_client
*
clp
)
{
struct
rpc_cred
*
cred
;
spin_lock
(
&
clp
->
cl_lock
);
cred
=
nfs4_get_renew_cred_locked
(
clp
);
spin_unlock
(
&
clp
->
cl_lock
);
return
cred
;
}
static
struct
rpc_cred
*
nfs4_get_setclientid_cred
(
struct
nfs_client
*
clp
)
{
struct
nfs4_state_owner
*
sp
;
struct
rb_node
*
pos
;
struct
rpc_cred
*
cred
;
cred
=
nfs4_get_machine_cred
(
clp
);
spin_lock
(
&
clp
->
cl_lock
);
cred
=
nfs4_get_machine_cred_locked
(
clp
);
if
(
cred
!=
NULL
)
goto
out
;
pos
=
rb_first
(
&
clp
->
cl_state_owners
);
...
...
@@ -125,6 +134,7 @@ static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
cred
=
get_rpccred
(
sp
->
so_cred
);
}
out:
spin_unlock
(
&
clp
->
cl_lock
);
return
cred
;
}
...
...
@@ -295,10 +305,6 @@ nfs4_drop_state_owner(struct nfs4_state_owner *sp)
}
}
/*
* Note: must be called with clp->cl_sem held in order to prevent races
* with reboot recovery!
*/
struct
nfs4_state_owner
*
nfs4_get_state_owner
(
struct
nfs_server
*
server
,
struct
rpc_cred
*
cred
)
{
struct
nfs_client
*
clp
=
server
->
nfs_client
;
...
...
@@ -327,10 +333,6 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
return
sp
;
}
/*
* Must be called with clp->cl_sem held in order to avoid races
* with state recovery...
*/
void
nfs4_put_state_owner
(
struct
nfs4_state_owner
*
sp
)
{
struct
nfs_client
*
clp
=
sp
->
so_client
;
...
...
@@ -361,18 +363,18 @@ nfs4_alloc_open_state(void)
}
void
nfs4_state_set_mode_locked
(
struct
nfs4_state
*
state
,
mode_t
mode
)
nfs4_state_set_mode_locked
(
struct
nfs4_state
*
state
,
fmode_t
f
mode
)
{
if
(
state
->
state
==
mode
)
if
(
state
->
state
==
f
mode
)
return
;
/* NB! List reordering - see the reclaim code for why. */
if
((
mode
&
FMODE_WRITE
)
!=
(
state
->
state
&
FMODE_WRITE
))
{
if
(
mode
&
FMODE_WRITE
)
if
((
f
mode
&
FMODE_WRITE
)
!=
(
state
->
state
&
FMODE_WRITE
))
{
if
(
f
mode
&
FMODE_WRITE
)
list_move
(
&
state
->
open_states
,
&
state
->
owner
->
so_states
);
else
list_move_tail
(
&
state
->
open_states
,
&
state
->
owner
->
so_states
);
}
state
->
state
=
mode
;
state
->
state
=
f
mode
;
}
static
struct
nfs4_state
*
...
...
@@ -432,10 +434,6 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
return
state
;
}
/*
* Beware! Caller must be holding exactly one
* reference to clp->cl_sem!
*/
void
nfs4_put_open_state
(
struct
nfs4_state
*
state
)
{
struct
inode
*
inode
=
state
->
inode
;
...
...
@@ -456,16 +454,16 @@ void nfs4_put_open_state(struct nfs4_state *state)
/*
* Close the current file.
*/
static
void
__nfs4_close
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
mode_t
mode
,
int
wait
)
static
void
__nfs4_close
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
fmode_t
f
mode
,
int
wait
)
{
struct
nfs4_state_owner
*
owner
=
state
->
owner
;
int
call_close
=
0
;
in
t
newstate
;
fmode_
t
newstate
;
atomic_inc
(
&
owner
->
so_count
);
/* Protect against nfs4_find_state() */
spin_lock
(
&
owner
->
so_lock
);
switch
(
mode
&
(
FMODE_READ
|
FMODE_WRITE
))
{
switch
(
f
mode
&
(
FMODE_READ
|
FMODE_WRITE
))
{
case
FMODE_READ
:
state
->
n_rdonly
--
;
break
;
...
...
@@ -500,14 +498,14 @@ static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mod
nfs4_do_close
(
path
,
state
,
wait
);
}
void
nfs4_close_state
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
mode_t
mode
)
void
nfs4_close_state
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
fmode_t
f
mode
)
{
__nfs4_close
(
path
,
state
,
mode
,
0
);
__nfs4_close
(
path
,
state
,
f
mode
,
0
);
}
void
nfs4_close_sync
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
mode_t
mode
)
void
nfs4_close_sync
(
struct
path
*
path
,
struct
nfs4_state
*
state
,
fmode_t
f
mode
)
{
__nfs4_close
(
path
,
state
,
mode
,
1
);
__nfs4_close
(
path
,
state
,
f
mode
,
1
);
}
/*
...
...
@@ -568,7 +566,6 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
*
* The caller must be holding clp->cl_sem
*/
static
struct
nfs4_lock_state
*
nfs4_get_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
owner
)
{
...
...
@@ -770,32 +767,34 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
return
status
;
}
static
int
reclaim
er
(
void
*
);
static
int
nfs4_run_state_manag
er
(
void
*
);
static
inline
void
nfs4_clear_recov
er_bit
(
struct
nfs_client
*
clp
)
static
void
nfs4_clear_state_manag
er_bit
(
struct
nfs_client
*
clp
)
{
smp_mb__before_clear_bit
();
clear_bit
(
NFS4CLNT_
STATE_RECOVER
,
&
clp
->
cl_state
);
clear_bit
(
NFS4CLNT_
MANAGER_RUNNING
,
&
clp
->
cl_state
);
smp_mb__after_clear_bit
();
wake_up_bit
(
&
clp
->
cl_state
,
NFS4CLNT_
STATE_RECOVER
);
wake_up_bit
(
&
clp
->
cl_state
,
NFS4CLNT_
MANAGER_RUNNING
);
rpc_wake_up
(
&
clp
->
cl_rpcwaitq
);
}
/*
* S
tate recovery
routine
* S
chedule the nfs_client asynchronous state management
routine
*/
static
void
nfs4_recover_state
(
struct
nfs_client
*
clp
)
void
nfs4_schedule_state_manager
(
struct
nfs_client
*
clp
)
{
struct
task_struct
*
task
;
if
(
test_and_set_bit
(
NFS4CLNT_MANAGER_RUNNING
,
&
clp
->
cl_state
)
!=
0
)
return
;
__module_get
(
THIS_MODULE
);
atomic_inc
(
&
clp
->
cl_count
);
task
=
kthread_run
(
reclaimer
,
clp
,
"%s-reclaim
"
,
task
=
kthread_run
(
nfs4_run_state_manager
,
clp
,
"%s-manager
"
,
rpc_peeraddr2str
(
clp
->
cl_rpcclient
,
RPC_DISPLAY_ADDR
));
if
(
!
IS_ERR
(
task
))
return
;
nfs4_clear_
recov
er_bit
(
clp
);
nfs4_clear_
state_manag
er_bit
(
clp
);
nfs_put_client
(
clp
);
module_put
(
THIS_MODULE
);
}
...
...
@@ -807,16 +806,42 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
{
if
(
!
clp
)
return
;
if
(
test_and_set_bit
(
NFS4CLNT_STATE_RECOVER
,
&
clp
->
cl_state
)
==
0
)
nfs4_recover_state
(
clp
);
if
(
!
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
))
set_bit
(
NFS4CLNT_CHECK_LEASE
,
&
clp
->
cl_state
);
nfs4_schedule_state_manager
(
clp
);
}
static
int
nfs4_reclaim_locks
(
struct
nfs4_state_recovery_ops
*
ops
,
struct
nfs4_state
*
state
)
static
int
nfs4_state_mark_reclaim_reboot
(
struct
nfs_client
*
clp
,
struct
nfs4_state
*
state
)
{
set_bit
(
NFS_STATE_RECLAIM_REBOOT
,
&
state
->
flags
);
/* Don't recover state that expired before the reboot */
if
(
test_bit
(
NFS_STATE_RECLAIM_NOGRACE
,
&
state
->
flags
))
{
clear_bit
(
NFS_STATE_RECLAIM_REBOOT
,
&
state
->
flags
);
return
0
;
}
set_bit
(
NFS_OWNER_RECLAIM_REBOOT
,
&
state
->
owner
->
so_flags
);
set_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
);
return
1
;
}
int
nfs4_state_mark_reclaim_nograce
(
struct
nfs_client
*
clp
,
struct
nfs4_state
*
state
)
{
set_bit
(
NFS_STATE_RECLAIM_NOGRACE
,
&
state
->
flags
);
clear_bit
(
NFS_STATE_RECLAIM_REBOOT
,
&
state
->
flags
);
set_bit
(
NFS_OWNER_RECLAIM_NOGRACE
,
&
state
->
owner
->
so_flags
);
set_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
);
return
1
;
}
static
int
nfs4_reclaim_locks
(
struct
nfs4_state
*
state
,
const
struct
nfs4_state_recovery_ops
*
ops
)
{
struct
inode
*
inode
=
state
->
inode
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
struct
file_lock
*
fl
;
int
status
=
0
;
down_write
(
&
nfsi
->
rwsem
);
for
(
fl
=
inode
->
i_flock
;
fl
!=
NULL
;
fl
=
fl
->
fl_next
)
{
if
(
!
(
fl
->
fl_flags
&
(
FL_POSIX
|
FL_FLOCK
)))
continue
;
...
...
@@ -839,12 +864,14 @@ static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_s
goto
out_err
;
}
}
up_write
(
&
nfsi
->
rwsem
);
return
0
;
out_err:
up_write
(
&
nfsi
->
rwsem
);
return
status
;
}
static
int
nfs4_reclaim_open_state
(
struct
nfs4_state_
recovery_ops
*
ops
,
struct
nfs4_state_owner
*
sp
)
static
int
nfs4_reclaim_open_state
(
struct
nfs4_state_
owner
*
sp
,
const
struct
nfs4_state_recovery_ops
*
ops
)
{
struct
nfs4_state
*
state
;
struct
nfs4_lock_state
*
lock
;
...
...
@@ -858,28 +885,34 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
* recovering after a network partition or a reboot from a
* server that doesn't support a grace period.
*/
restart:
spin_lock
(
&
sp
->
so_lock
);
list_for_each_entry
(
state
,
&
sp
->
so_states
,
open_states
)
{
if
(
!
test_and_clear_bit
(
ops
->
state_flag_bit
,
&
state
->
flags
))
continue
;
if
(
state
->
state
==
0
)
continue
;
atomic_inc
(
&
state
->
count
);
spin_unlock
(
&
sp
->
so_lock
);
status
=
ops
->
recover_open
(
sp
,
state
);
if
(
status
>=
0
)
{
status
=
nfs4_reclaim_locks
(
ops
,
state
);
if
(
status
<
0
)
goto
out_err
;
list_for_each_entry
(
lock
,
&
state
->
lock_states
,
ls_locks
)
{
if
(
!
(
lock
->
ls_flags
&
NFS_LOCK_INITIALIZED
))
printk
(
"%s: Lock reclaim failed!
\n
"
,
status
=
nfs4_reclaim_locks
(
state
,
ops
);
if
(
status
>=
0
)
{
list_for_each_entry
(
lock
,
&
state
->
lock_states
,
ls_locks
)
{
if
(
!
(
lock
->
ls_flags
&
NFS_LOCK_INITIALIZED
))
printk
(
"%s: Lock reclaim failed!
\n
"
,
__func__
);
}
nfs4_put_open_state
(
state
);
goto
restart
;
}
continue
;
}
switch
(
status
)
{
default:
printk
(
KERN_ERR
"%s: unhandled error %d. Zeroing state
\n
"
,
__func__
,
status
);
case
-
ENOENT
:
case
-
NFS4ERR_RECLAIM_BAD
:
case
-
NFS4ERR_RECLAIM_CONFLICT
:
case
-
ESTALE
:
/*
* Open state on this file cannot be recovered
* All we can do is revert to using the zero stateid.
...
...
@@ -889,84 +922,176 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n
/* Mark the file as being 'closed' */
state
->
state
=
0
;
break
;
case
-
NFS4ERR_RECLAIM_BAD
:
case
-
NFS4ERR_RECLAIM_CONFLICT
:
nfs4_state_mark_reclaim_nograce
(
sp
->
so_client
,
state
);
break
;
case
-
NFS4ERR_EXPIRED
:
case
-
NFS4ERR_NO_GRACE
:
nfs4_state_mark_reclaim_nograce
(
sp
->
so_client
,
state
);
case
-
NFS4ERR_STALE_CLIENTID
:
goto
out_err
;
}
nfs4_put_open_state
(
state
);
goto
restart
;
}
spin_unlock
(
&
sp
->
so_lock
);
return
0
;
out_err:
nfs4_put_open_state
(
state
);
return
status
;
}
static
void
nfs4_state_mark_reclaim
(
struct
nfs_client
*
clp
)
static
void
nfs4_clear_open_state
(
struct
nfs4_state
*
state
)
{
struct
nfs4_lock_state
*
lock
;
clear_bit
(
NFS_DELEGATED_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
list_for_each_entry
(
lock
,
&
state
->
lock_states
,
ls_locks
)
{
lock
->
ls_seqid
.
flags
=
0
;
lock
->
ls_flags
&=
~
NFS_LOCK_INITIALIZED
;
}
}
static
void
nfs4_state_mark_reclaim_helper
(
struct
nfs_client
*
clp
,
int
(
*
mark_reclaim
)(
struct
nfs_client
*
clp
,
struct
nfs4_state
*
state
))
{
struct
nfs4_state_owner
*
sp
;
struct
rb_node
*
pos
;
struct
nfs4_state
*
state
;
struct
nfs4_lock_state
*
lock
;
/* Reset all sequence ids to zero */
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
);
sp
->
so_seqid
.
counter
=
0
;
sp
->
so_seqid
.
flags
=
0
;
spin_lock
(
&
sp
->
so_lock
);
list_for_each_entry
(
state
,
&
sp
->
so_states
,
open_states
)
{
clear_bit
(
NFS_DELEGATED_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
list_for_each_entry
(
lock
,
&
state
->
lock_states
,
ls_locks
)
{
lock
->
ls_seqid
.
counter
=
0
;
lock
->
ls_seqid
.
flags
=
0
;
lock
->
ls_flags
&=
~
NFS_LOCK_INITIALIZED
;
}
if
(
mark_reclaim
(
clp
,
state
))
nfs4_clear_open_state
(
state
);
}
spin_unlock
(
&
sp
->
so_lock
);
}
}
static
int
reclaimer
(
void
*
ptr
)
static
void
nfs4_state_start_reclaim_reboot
(
struct
nfs_client
*
clp
)
{
/* Mark all delegations for reclaim */
nfs_delegation_mark_reclaim
(
clp
);
nfs4_state_mark_reclaim_helper
(
clp
,
nfs4_state_mark_reclaim_reboot
);
}
static
void
nfs4_state_end_reclaim_reboot
(
struct
nfs_client
*
clp
)
{
struct
nfs_client
*
clp
=
ptr
;
struct
nfs4_state_owner
*
sp
;
struct
rb_node
*
pos
;
struct
nfs4_state_recovery_ops
*
ops
;
struct
rpc_cred
*
cred
;
struct
nfs4_state
*
state
;
if
(
!
test_and_clear_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
return
;
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
);
list_for_each_entry
(
state
,
&
sp
->
so_states
,
open_states
)
{
if
(
!
test_and_clear_bit
(
NFS_STATE_RECLAIM_REBOOT
,
&
state
->
flags
))
continue
;
nfs4_state_mark_reclaim_nograce
(
clp
,
state
);
}
spin_unlock
(
&
sp
->
so_lock
);
}
nfs_delegation_reap_unclaimed
(
clp
);
}
static
void
nfs_delegation_clear_all
(
struct
nfs_client
*
clp
)
{
nfs_delegation_mark_reclaim
(
clp
);
nfs_delegation_reap_unclaimed
(
clp
);
}
static
void
nfs4_state_start_reclaim_nograce
(
struct
nfs_client
*
clp
)
{
nfs_delegation_clear_all
(
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
)
{
switch
(
error
)
{
case
-
NFS4ERR_CB_PATH_DOWN
:
nfs_handle_cb_pathdown
(
clp
);
break
;
case
-
NFS4ERR_STALE_CLIENTID
:
case
-
NFS4ERR_LEASE_MOVED
:
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
nfs4_state_start_reclaim_reboot
(
clp
);
break
;
case
-
NFS4ERR_EXPIRED
:
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
nfs4_state_start_reclaim_nograce
(
clp
);
}
}
static
int
nfs4_do_reclaim
(
struct
nfs_client
*
clp
,
const
struct
nfs4_state_recovery_ops
*
ops
)
{
struct
rb_node
*
pos
;
int
status
=
0
;
allow_signal
(
SIGKILL
);
restart:
spin_lock
(
&
clp
->
cl_lock
);
for
(
pos
=
rb_first
(
&
clp
->
cl_state_owners
);
pos
!=
NULL
;
pos
=
rb_next
(
pos
))
{
struct
nfs4_state_owner
*
sp
=
rb_entry
(
pos
,
struct
nfs4_state_owner
,
so_client_node
);
if
(
!
test_and_clear_bit
(
ops
->
owner_flag_bit
,
&
sp
->
so_flags
))
continue
;
atomic_inc
(
&
sp
->
so_count
);
spin_unlock
(
&
clp
->
cl_lock
);
status
=
nfs4_reclaim_open_state
(
sp
,
ops
);
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
;
}
nfs4_put_state_owner
(
sp
);
goto
restart
;
}
spin_unlock
(
&
clp
->
cl_lock
);
return
status
;
}
/* Ensure exclusive access to NFSv4 state */
down_write
(
&
clp
->
cl_sem
);
/* Are there any NFS mounts out there? */
i
f
(
list_empty
(
&
clp
->
cl_superblocks
))
goto
out
;
restart_loop:
ops
=
&
nfs4_network_partition_recovery_ops
;
/* Are there any open files on this volume? */
static
int
nfs4_check_lease
(
struct
nfs_client
*
clp
)
{
struct
rpc_cred
*
cred
;
i
nt
status
=
-
NFS4ERR_EXPIRED
;
/* Is the client already known to have an expired lease? */
if
(
test_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
))
return
0
;
cred
=
nfs4_get_renew_cred
(
clp
);
if
(
cred
!=
NULL
)
{
/* Yes there are: try to renew the old lease */
status
=
nfs4_proc_renew
(
clp
,
cred
);
put_rpccred
(
cred
);
switch
(
status
)
{
case
0
:
case
-
NFS4ERR_CB_PATH_DOWN
:
goto
out
;
case
-
NFS4ERR_STALE_CLIENTID
:
case
-
NFS4ERR_LEASE_MOVED
:
ops
=
&
nfs4_reboot_recovery_ops
;
}
}
else
{
/* "reboot" to ensure we clear all state on the server */
clp
->
cl_boot_time
=
CURRENT_TIME
;
if
(
cred
==
NULL
)
{
cred
=
nfs4_get_setclientid_cred
(
clp
);
if
(
cred
==
NULL
)
goto
out
;
}
/* We're going to have to re-establish a clientid */
nfs4_state_mark_reclaim
(
clp
);
status
=
-
ENOENT
;
status
=
nfs4_proc_renew
(
clp
,
cred
);
put_rpccred
(
cred
);
out:
nfs4_recovery_handle_error
(
clp
,
status
);
return
status
;
}
static
int
nfs4_reclaim_lease
(
struct
nfs_client
*
clp
)
{
struct
rpc_cred
*
cred
;
int
status
=
-
ENOENT
;
cred
=
nfs4_get_setclientid_cred
(
clp
);
if
(
cred
!=
NULL
)
{
status
=
nfs4_init_client
(
clp
,
cred
);
...
...
@@ -974,42 +1099,90 @@ static int reclaimer(void *ptr)
/* Handle case where the user hasn't set up machine creds */
if
(
status
==
-
EACCES
&&
cred
==
clp
->
cl_machine_cred
)
{
nfs4_clear_machine_cred
(
clp
);
goto
restart_loop
;
status
=
-
EAGAIN
;
}
}
if
(
status
)
goto
out_error
;
/* Mark all delegations for reclaim */
nfs_delegation_mark_reclaim
(
clp
);
/* Note: list is protected by exclusive lock on cl->cl_sem */
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
);
status
=
nfs4_reclaim_open_state
(
ops
,
sp
);
if
(
status
<
0
)
{
if
(
status
==
-
NFS4ERR_NO_GRACE
)
{
ops
=
&
nfs4_network_partition_recovery_ops
;
status
=
nfs4_reclaim_open_state
(
ops
,
sp
);
return
status
;
}
static
void
nfs4_state_manager
(
struct
nfs_client
*
clp
)
{
int
status
=
0
;
/* Ensure exclusive access to NFSv4 state */
for
(;;)
{
if
(
test_and_clear_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
))
{
/* We're going to have to re-establish a clientid */
status
=
nfs4_reclaim_lease
(
clp
);
if
(
status
)
{
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
if
(
status
==
-
EAGAIN
)
continue
;
goto
out_error
;
}
clear_bit
(
NFS4CLNT_CHECK_LEASE
,
&
clp
->
cl_state
);
}
if
(
test_and_clear_bit
(
NFS4CLNT_CHECK_LEASE
,
&
clp
->
cl_state
))
{
status
=
nfs4_check_lease
(
clp
);
if
(
status
!=
0
)
continue
;
}
/* First recover reboot state... */
if
(
test_and_clear_bit
(
NFS4CLNT_RECLAIM_REBOOT
,
&
clp
->
cl_state
))
{
status
=
nfs4_do_reclaim
(
clp
,
&
nfs4_reboot_recovery_ops
);
if
(
status
==
-
NFS4ERR_STALE_CLIENTID
)
goto
restart_loop
;
if
(
status
==
-
NFS4ERR_EXPIRED
)
goto
restart_loop
;
continue
;
nfs4_state_end_reclaim_reboot
(
clp
);
continue
;
}
/* Now recover expired state... */
if
(
test_and_clear_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
))
{
status
=
nfs4_do_reclaim
(
clp
,
&
nfs4_nograce_recovery_ops
);
if
(
status
<
0
)
{
set_bit
(
NFS4CLNT_RECLAIM_NOGRACE
,
&
clp
->
cl_state
);
if
(
status
==
-
NFS4ERR_STALE_CLIENTID
)
continue
;
if
(
status
==
-
NFS4ERR_EXPIRED
)
continue
;
goto
out_error
;
}
else
nfs4_state_end_reclaim_nograce
(
clp
);
continue
;
}
if
(
test_and_clear_bit
(
NFS4CLNT_DELEGRETURN
,
&
clp
->
cl_state
))
{
nfs_client_return_marked_delegations
(
clp
);
continue
;
}
nfs4_clear_state_manager_bit
(
clp
);
/* Did we race with an attempt to give us more work? */
if
(
clp
->
cl_state
==
0
)
break
;
if
(
test_and_set_bit
(
NFS4CLNT_MANAGER_RUNNING
,
&
clp
->
cl_state
)
!=
0
)
break
;
}
nfs_delegation_reap_unclaimed
(
clp
);
out:
up_write
(
&
clp
->
cl_sem
);
if
(
status
==
-
NFS4ERR_CB_PATH_DOWN
)
nfs_handle_cb_pathdown
(
clp
);
nfs4_clear_recover_bit
(
clp
);
return
;
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
);
}
static
int
nfs4_run_state_manager
(
void
*
ptr
)
{
struct
nfs_client
*
clp
=
ptr
;
allow_signal
(
SIGKILL
);
nfs4_state_manager
(
clp
);
nfs_put_client
(
clp
);
module_put_and_exit
(
0
);
return
0
;
out_error:
printk
(
KERN_WARNING
"Error: state recovery failed on NFSv4 server %s"
" with error %d
\n
"
,
clp
->
cl_hostname
,
-
status
);
set_bit
(
NFS4CLNT_LEASE_EXPIRED
,
&
clp
->
cl_state
);
goto
out
;
}
/*
...
...
fs/nfs/nfs4xdr.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
fs/nfs/nfsroot.c
浏览文件 @
08cc36cb
...
...
@@ -86,6 +86,8 @@
#include <net/ipconfig.h>
#include <linux/parser.h>
#include "internal.h"
/* Define this to allow debugging output */
#undef NFSROOT_DEBUG
#define NFSDBG_FACILITY NFSDBG_ROOT
...
...
@@ -100,7 +102,7 @@ static char nfs_root_name[256] __initdata = "";
static
__be32
servaddr
__initdata
=
0
;
/* Name of directory to mount */
static
char
nfs_path
[
NFS_MAXPATHLEN
]
__initdata
=
{
0
,
};
static
char
nfs_
export_
path
[
NFS_MAXPATHLEN
]
__initdata
=
{
0
,
};
/* NFS-related data */
static
struct
nfs_mount_data
nfs_data
__initdata
=
{
0
,
};
/* NFS mount info */
...
...
@@ -312,7 +314,7 @@ static int __init root_nfs_name(char *name)
printk
(
KERN_ERR
"Root-NFS: Pathname for remote directory too long.
\n
"
);
return
-
1
;
}
sprintf
(
nfs_path
,
buf
,
cp
);
sprintf
(
nfs_
export_
path
,
buf
,
cp
);
return
1
;
}
...
...
@@ -340,7 +342,7 @@ static int __init root_nfs_addr(void)
static
void
__init
root_nfs_print
(
void
)
{
printk
(
KERN_NOTICE
"Root-NFS: Mounting %s on server %s as root
\n
"
,
nfs_path
,
nfs_data
.
hostname
);
nfs_
export_
path
,
nfs_data
.
hostname
);
printk
(
KERN_NOTICE
"Root-NFS: rsize = %d, wsize = %d, timeo = %d, retrans = %d
\n
"
,
nfs_data
.
rsize
,
nfs_data
.
wsize
,
nfs_data
.
timeo
,
nfs_data
.
retrans
);
printk
(
KERN_NOTICE
"Root-NFS: acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)
\n
"
,
...
...
@@ -485,18 +487,23 @@ static int __init root_nfs_get_handle(void)
{
struct
nfs_fh
fh
;
struct
sockaddr_in
sin
;
struct
nfs_mount_request
request
=
{
.
sap
=
(
struct
sockaddr
*
)
&
sin
,
.
salen
=
sizeof
(
sin
),
.
dirpath
=
nfs_export_path
,
.
version
=
(
nfs_data
.
flags
&
NFS_MOUNT_VER3
)
?
NFS_MNT3_VERSION
:
NFS_MNT_VERSION
,
.
protocol
=
(
nfs_data
.
flags
&
NFS_MOUNT_TCP
)
?
XPRT_TRANSPORT_TCP
:
XPRT_TRANSPORT_UDP
,
.
fh
=
&
fh
,
};
int
status
;
int
protocol
=
(
nfs_data
.
flags
&
NFS_MOUNT_TCP
)
?
XPRT_TRANSPORT_TCP
:
XPRT_TRANSPORT_UDP
;
int
version
=
(
nfs_data
.
flags
&
NFS_MOUNT_VER3
)
?
NFS_MNT3_VERSION
:
NFS_MNT_VERSION
;
set_sockaddr
(
&
sin
,
servaddr
,
htons
(
mount_port
));
status
=
nfs_mount
((
struct
sockaddr
*
)
&
sin
,
sizeof
(
sin
),
NULL
,
nfs_path
,
version
,
protocol
,
&
fh
);
status
=
nfs_mount
(
&
request
);
if
(
status
<
0
)
printk
(
KERN_ERR
"Root-NFS: Server returned error %d "
"while mounting %s
\n
"
,
status
,
nfs_path
);
"while mounting %s
\n
"
,
status
,
nfs_
export_
path
);
else
{
nfs_data
.
root
.
size
=
fh
.
size
;
memcpy
(
nfs_data
.
root
.
data
,
fh
.
data
,
fh
.
size
);
...
...
fs/nfs/read.c
浏览文件 @
08cc36cb
...
...
@@ -533,12 +533,6 @@ readpage_async_filler(void *data, struct page *page)
unsigned
int
len
;
int
error
;
error
=
nfs_wb_page
(
inode
,
page
);
if
(
error
)
goto
out_unlock
;
if
(
PageUptodate
(
page
))
goto
out_unlock
;
len
=
nfs_page_length
(
page
);
if
(
len
==
0
)
return
nfs_return_empty_page
(
page
);
...
...
fs/nfs/super.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
fs/nfs_common/nfsacl.c
浏览文件 @
08cc36cb
...
...
@@ -29,8 +29,8 @@
MODULE_LICENSE
(
"GPL"
);
EXPORT_SYMBOL
(
nfsacl_encode
);
EXPORT_SYMBOL
(
nfsacl_decode
);
EXPORT_SYMBOL
_GPL
(
nfsacl_encode
);
EXPORT_SYMBOL
_GPL
(
nfsacl_decode
);
struct
nfsacl_encode_desc
{
struct
xdr_array2_desc
desc
;
...
...
fs/nfsd/nfs4callback.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
fs/nfsd/nfs4state.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/jiffies.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/lockd/bind.h
浏览文件 @
08cc36cb
...
...
@@ -41,6 +41,7 @@ struct nlmclnt_initdata {
size_t
addrlen
;
unsigned
short
protocol
;
u32
nfs_version
;
int
noresvport
;
};
/*
...
...
include/linux/lockd/lockd.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/nfs_fs.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/nfs_fs_sb.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/nfs_mount.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/nfs_xdr.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/nfsd/state.h
浏览文件 @
08cc36cb
...
...
@@ -124,6 +124,8 @@ struct nfs4_client {
nfs4_verifier
cl_verifier
;
/* generated by client */
time_t
cl_time
;
/* time of last lease renewal */
__be32
cl_addr
;
/* client ipaddress */
u32
cl_flavor
;
/* setclientid pseudoflavor */
char
*
cl_principal
;
/* setclientid principal name */
struct
svc_cred
cl_cred
;
/* setclientid principal */
clientid_t
cl_clientid
;
/* generated by server */
nfs4_verifier
cl_confirm
;
/* generated by server */
...
...
include/linux/sunrpc/clnt.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/sunrpc/rpc_pipe_fs.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/sunrpc/svcauth_gss.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/sunrpc/xdr.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
include/linux/sunrpc/xprt.h
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/auth.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/auth_gss/auth_gss.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/auth_gss/gss_generic_token.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/auth_gss/gss_mech_switch.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/auth_gss/svcauth_gss.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/clnt.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/rpc_pipe.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
net/sunrpc/xdr.c
浏览文件 @
08cc36cb
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录