Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
aeb08fc0
Commit
aeb08fc0
authored
Mar 14, 2004
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://nfsclient.bkbits.net/linux-2.5
into fys.uio.no:/home/linux/bitkeeper/nfsclient-2.5
parents
fa9fcf5f
b67cfdb8
Changes
44
Show whitespace changes
Inline
Side-by-side
Showing
44 changed files
with
1312 additions
and
1041 deletions
+1312
-1041
fs/Kconfig
fs/Kconfig
+19
-20
fs/inode.c
fs/inode.c
+2
-0
fs/lockd/clntproc.c
fs/lockd/clntproc.c
+1
-1
fs/lockd/host.c
fs/lockd/host.c
+2
-2
fs/lockd/mon.c
fs/lockd/mon.c
+8
-8
fs/lockd/svc4proc.c
fs/lockd/svc4proc.c
+19
-2
fs/lockd/svclock.c
fs/lockd/svclock.c
+18
-10
fs/lockd/svcproc.c
fs/lockd/svcproc.c
+17
-2
fs/nfs/dir.c
fs/nfs/dir.c
+137
-44
fs/nfs/direct.c
fs/nfs/direct.c
+3
-0
fs/nfs/file.c
fs/nfs/file.c
+7
-2
fs/nfs/inode.c
fs/nfs/inode.c
+276
-254
fs/nfs/mount_clnt.c
fs/nfs/mount_clnt.c
+8
-6
fs/nfs/nfs2xdr.c
fs/nfs/nfs2xdr.c
+27
-27
fs/nfs/nfs3proc.c
fs/nfs/nfs3proc.c
+17
-25
fs/nfs/nfs3xdr.c
fs/nfs/nfs3xdr.c
+43
-45
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+54
-66
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+16
-8
fs/nfs/nfs4xdr.c
fs/nfs/nfs4xdr.c
+112
-104
fs/nfs/nfsroot.c
fs/nfs/nfsroot.c
+1
-32
fs/nfs/pagelist.c
fs/nfs/pagelist.c
+0
-5
fs/nfs/proc.c
fs/nfs/proc.c
+41
-25
fs/nfs/read.c
fs/nfs/read.c
+6
-1
fs/nfs/unlink.c
fs/nfs/unlink.c
+2
-1
fs/nfs/write.c
fs/nfs/write.c
+105
-100
include/linux/fs.h
include/linux/fs.h
+2
-0
include/linux/lockd/debug.h
include/linux/lockd/debug.h
+1
-1
include/linux/lockd/lockd.h
include/linux/lockd/lockd.h
+1
-0
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+80
-47
include/linux/nfs_page.h
include/linux/nfs_page.h
+1
-1
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+1
-1
include/linux/sunrpc/debug.h
include/linux/sunrpc/debug.h
+3
-1
include/linux/sunrpc/timer.h
include/linux/sunrpc/timer.h
+10
-1
include/linux/sunrpc/xdr.h
include/linux/sunrpc/xdr.h
+1
-1
include/linux/sunrpc/xprt.h
include/linux/sunrpc/xprt.h
+23
-12
net/ipv4/ipconfig.c
net/ipv4/ipconfig.c
+39
-0
net/sunrpc/auth_unix.c
net/sunrpc/auth_unix.c
+2
-5
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+12
-15
net/sunrpc/pmap_clnt.c
net/sunrpc/pmap_clnt.c
+17
-11
net/sunrpc/sched.c
net/sunrpc/sched.c
+14
-9
net/sunrpc/sunrpc_syms.c
net/sunrpc/sunrpc_syms.c
+2
-0
net/sunrpc/sysctl.c
net/sunrpc/sysctl.c
+27
-1
net/sunrpc/xdr.c
net/sunrpc/xdr.c
+1
-1
net/sunrpc/xprt.c
net/sunrpc/xprt.c
+134
-144
No files found.
fs/Kconfig
View file @
aeb08fc0
...
...
@@ -1305,15 +1305,18 @@ config NFS_V3
Say Y here if you want your NFS client to be able to speak the newer
version 3 of the NFS protocol.
If unsure, say
N
.
If unsure, say
Y
.
config NFS_V4
bool "Provide NFSv4 client support (EXPERIMENTAL)"
depends on NFS_FS && EXPERIMENTAL
select RPCSEC_GSS_KRB5
help
Say Y here if you want your NFS client to be able to speak the newer
version 4 of the NFS protocol. This feature is experimental, and
should only be used if you are interested in helping to test NFSv4.
version 4 of the NFS protocol.
Note: Requires auxiliary userspace daemons which may be found on
http://www.citi.umich.edu/projects/nfsv4/
If unsure, say N.
...
...
@@ -1422,28 +1425,24 @@ config SUNRPC
tristate
config SUNRPC_GSS
tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
tristate
config RPCSEC_GSS_KRB5
tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
depends on SUNRPC && EXPERIMENTAL
default SUNRPC if NFS_V4=y
select SUNRPC_GSS
select CRYPTO
select CRYPTO_MD5
select CRYPTO_DES
help
Provides cryptographic authentication for NFS rpc requests. To
make this useful, you must also select at least one rpcsec_gss
mechanism.
Note: You should always select this option if you wish to use
Provides for secure RPC calls by means of a gss-api
mechanism based on Kerberos V5. This is required for
NFSv4.
config RPCSEC_GSS_KRB5
tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)"
depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5
default SUNRPC_GSS if NFS_V4=y
help
Provides a gss-api mechanism based on Kerberos V5 (this is
mandatory for RFC3010-compliant NFSv4 implementations).
Requires a userspace daemon;
see http://www.citi.umich.edu/projects/nfsv4/.
Note: Requires an auxiliary userspace daemon which may be found on
http://www.citi.umich.edu/projects/nfsv4/
Note: If you select this option, please ensure that you also
enable the MD5 and DES crypto ciphers.
If unsure, say N.
config SMB_FS
tristate "SMB file system support (to mount Windows shares etc.)"
...
...
fs/inode.c
View file @
aeb08fc0
...
...
@@ -1178,6 +1178,8 @@ void inode_update_time(struct inode *inode, int ctime_too)
struct
timespec
now
;
int
sync_it
=
0
;
if
(
IS_NOCMTIME
(
inode
))
return
;
if
(
IS_RDONLY
(
inode
))
return
;
...
...
fs/lockd/clntproc.c
View file @
aeb08fc0
...
...
@@ -443,7 +443,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
}
if
(
status
<
0
)
return
status
;
}
while
(
resp
->
status
==
NLM_LCK_BLOCKED
);
}
while
(
resp
->
status
==
NLM_LCK_BLOCKED
&&
req
->
a_args
.
block
);
if
(
resp
->
status
==
NLM_LCK_GRANTED
)
{
fl
->
fl_u
.
nfs_fl
.
state
=
host
->
h_state
;
...
...
fs/lockd/host.c
View file @
aeb08fc0
...
...
@@ -188,14 +188,14 @@ nlm_bind_host(struct nlm_host *host)
}
}
else
{
xprt
=
xprt_create_proto
(
host
->
h_proto
,
&
host
->
h_addr
,
NULL
);
if
(
xprt
==
NULL
)
if
(
IS_ERR
(
xprt
)
)
goto
forgetit
;
xprt_set_timeout
(
&
xprt
->
timeout
,
5
,
nlmsvc_timeout
);
clnt
=
rpc_create_client
(
xprt
,
host
->
h_name
,
&
nlm_program
,
host
->
h_version
,
host
->
h_authflavor
);
if
(
clnt
==
NULL
)
{
if
(
IS_ERR
(
clnt
)
)
{
xprt_destroy
(
xprt
);
goto
forgetit
;
}
...
...
fs/lockd/mon.c
View file @
aeb08fc0
...
...
@@ -36,10 +36,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
int
status
;
struct
nsm_args
args
;
status
=
-
EACCES
;
clnt
=
nsm_create
();
if
(
!
clnt
)
if
(
IS_ERR
(
clnt
))
{
status
=
PTR_ERR
(
clnt
);
goto
out
;
}
args
.
addr
=
host
->
h_addr
.
sin_addr
.
s_addr
;
args
.
proto
=
(
host
->
h_proto
<<
1
)
|
host
->
h_server
;
...
...
@@ -104,7 +105,7 @@ static struct rpc_clnt *
nsm_create
(
void
)
{
struct
rpc_xprt
*
xprt
;
struct
rpc_clnt
*
clnt
=
NULL
;
struct
rpc_clnt
*
clnt
;
struct
sockaddr_in
sin
;
sin
.
sin_family
=
AF_INET
;
...
...
@@ -112,24 +113,23 @@ nsm_create(void)
sin
.
sin_port
=
0
;
xprt
=
xprt_create_proto
(
IPPROTO_UDP
,
&
sin
,
NULL
);
if
(
!
xprt
)
goto
ou
t
;
if
(
IS_ERR
(
xprt
)
)
return
(
struct
rpc_clnt
*
)
xpr
t
;
clnt
=
rpc_create_client
(
xprt
,
"localhost"
,
&
nsm_program
,
SM_VERSION
,
RPC_AUTH_NULL
);
if
(
!
clnt
)
if
(
IS_ERR
(
clnt
)
)
goto
out_destroy
;
clnt
->
cl_softrtry
=
1
;
clnt
->
cl_chatty
=
1
;
clnt
->
cl_oneshot
=
1
;
xprt
->
resvport
=
1
;
/* NSM requires a reserved port */
out:
return
clnt
;
out_destroy:
xprt_destroy
(
xprt
);
goto
ou
t
;
return
cln
t
;
}
/*
...
...
fs/lockd/svc4proc.c
View file @
aeb08fc0
...
...
@@ -452,6 +452,24 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
return
rpc_success
;
}
/*
* client sent a GRANTED_RES, let's remove the associated block
*/
static
int
nlm4svc_proc_granted_res
(
struct
svc_rqst
*
rqstp
,
struct
nlm_res
*
argp
,
void
*
resp
)
{
if
(
!
nlmsvc_ops
)
return
rpc_success
;
dprintk
(
"lockd: GRANTED_RES called
\n
"
);
nlmsvc_grant_reply
(
rqstp
,
&
argp
->
cookie
,
argp
->
status
);
return
rpc_success
;
}
/*
* This is the generic lockd callback for async RPC calls
*/
...
...
@@ -515,7 +533,6 @@ nlm4svc_callback_exit(struct rpc_task *task)
#define nlm4svc_proc_lock_res nlm4svc_proc_null
#define nlm4svc_proc_cancel_res nlm4svc_proc_null
#define nlm4svc_proc_unlock_res nlm4svc_proc_null
#define nlm4svc_proc_granted_res nlm4svc_proc_null
struct
nlm_void
{
int
dummy
;
};
...
...
@@ -548,7 +565,7 @@ struct svc_procedure nlmsvc_procedures4[] = {
PROC
(
lock_res
,
lockres
,
norep
,
res
,
void
,
1
),
PROC
(
cancel_res
,
cancelres
,
norep
,
res
,
void
,
1
),
PROC
(
unlock_res
,
unlockres
,
norep
,
res
,
void
,
1
),
PROC
(
granted_res
,
grantedres
,
norep
,
res
,
void
,
1
),
PROC
(
granted_res
,
res
,
norep
,
res
,
void
,
1
),
/* statd callback */
PROC
(
sm_notify
,
reboot
,
void
,
reboot
,
void
,
1
),
PROC
(
none
,
void
,
void
,
void
,
void
,
0
),
...
...
fs/lockd/svclock.c
View file @
aeb08fc0
...
...
@@ -64,7 +64,7 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
if
(
when
!=
NLM_NEVER
)
{
if
((
when
+=
jiffies
)
==
NLM_NEVER
)
when
++
;
while
((
b
=
*
bp
)
&&
time_before_eq
(
b
->
b_when
,
when
))
while
((
b
=
*
bp
)
&&
time_before_eq
(
b
->
b_when
,
when
)
&&
b
->
b_when
!=
NLM_NEVER
)
bp
=
&
b
->
b_next
;
}
else
while
((
b
=
*
bp
))
...
...
@@ -143,14 +143,15 @@ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
* Find a block with a given NLM cookie.
*/
static
inline
struct
nlm_block
*
nlmsvc_find_block
(
struct
nlm_cookie
*
cookie
)
nlmsvc_find_block
(
struct
nlm_cookie
*
cookie
,
struct
sockaddr_in
*
sin
)
{
struct
nlm_block
*
block
;
for
(
block
=
nlm_blocked
;
block
;
block
=
block
->
b_next
)
{
dprintk
(
"cookie: head of blocked queue %p, block %p
\n
"
,
nlm_blocked
,
block
);
if
(
nlm_cookie_match
(
&
block
->
b_call
.
a_args
.
cookie
,
cookie
))
if
(
nlm_cookie_match
(
&
block
->
b_call
.
a_args
.
cookie
,
cookie
)
&&
nlm_cmp_addr
(
sin
,
&
block
->
b_host
->
h_addr
))
break
;
}
...
...
@@ -566,12 +567,16 @@ nlmsvc_grant_callback(struct rpc_task *task)
struct
nlm_rqst
*
call
=
(
struct
nlm_rqst
*
)
task
->
tk_calldata
;
struct
nlm_block
*
block
;
unsigned
long
timeout
;
struct
sockaddr_in
*
peer_addr
=
RPC_PEERADDR
(
task
->
tk_client
);
dprintk
(
"lockd: GRANT_MSG RPC callback
\n
"
);
dprintk
(
"callback: looking for cookie %x
\n
"
,
*
(
unsigned
int
*
)(
call
->
a_args
.
cookie
.
data
));
if
(
!
(
block
=
nlmsvc_find_block
(
&
call
->
a_args
.
cookie
)))
{
dprintk
(
"lockd: no block for cookie %x
\n
"
,
*
(
u32
*
)(
call
->
a_args
.
cookie
.
data
));
dprintk
(
"callback: looking for cookie %x, host (%08x)
\n
"
,
*
(
unsigned
int
*
)(
call
->
a_args
.
cookie
.
data
),
ntohl
(
peer_addr
->
sin_addr
.
s_addr
));
if
(
!
(
block
=
nlmsvc_find_block
(
&
call
->
a_args
.
cookie
,
peer_addr
)))
{
dprintk
(
"lockd: no block for cookie %x, host (%08x)
\n
"
,
*
(
u32
*
)(
call
->
a_args
.
cookie
.
data
),
ntohl
(
peer_addr
->
sin_addr
.
s_addr
));
return
;
}
...
...
@@ -600,18 +605,21 @@ nlmsvc_grant_callback(struct rpc_task *task)
* block.
*/
void
nlmsvc_grant_reply
(
struct
nlm_cookie
*
cookie
,
u32
status
)
nlmsvc_grant_reply
(
struct
svc_rqst
*
rqstp
,
struct
nlm_cookie
*
cookie
,
u32
status
)
{
struct
nlm_block
*
block
;
struct
nlm_file
*
file
;
if
(
!
(
block
=
nlmsvc_find_block
(
cookie
)))
dprintk
(
"grant_reply: looking for cookie %x, host (%08x), s=%d
\n
"
,
*
(
unsigned
int
*
)(
cookie
->
data
),
ntohl
(
rqstp
->
rq_addr
.
sin_addr
.
s_addr
),
status
);
if
(
!
(
block
=
nlmsvc_find_block
(
cookie
,
&
rqstp
->
rq_addr
)))
return
;
file
=
block
->
b_file
;
file
->
f_count
++
;
down
(
&
file
->
f_sema
);
if
((
block
=
nlmsvc_find_block
(
cookie
))
!=
NULL
)
{
if
((
block
=
nlmsvc_find_block
(
cookie
,
&
rqstp
->
rq_addr
))
!=
NULL
)
{
if
(
status
==
NLM_LCK_DENIED_GRACE_PERIOD
)
{
/* Try again in a couple of seconds */
nlmsvc_insert_block
(
block
,
10
*
HZ
);
...
...
fs/lockd/svcproc.c
View file @
aeb08fc0
...
...
@@ -478,6 +478,22 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
return
rpc_success
;
}
/*
* client sent a GRANTED_RES, let's remove the associated block
*/
static
int
nlmsvc_proc_granted_res
(
struct
svc_rqst
*
rqstp
,
struct
nlm_res
*
argp
,
void
*
resp
)
{
if
(
!
nlmsvc_ops
)
return
rpc_success
;
dprintk
(
"lockd: GRANTED_RES called
\n
"
);
nlmsvc_grant_reply
(
rqstp
,
&
argp
->
cookie
,
argp
->
status
);
return
rpc_success
;
}
/*
* This is the generic lockd callback for async RPC calls
*/
...
...
@@ -541,7 +557,6 @@ nlmsvc_callback_exit(struct rpc_task *task)
#define nlmsvc_proc_lock_res nlmsvc_proc_null
#define nlmsvc_proc_cancel_res nlmsvc_proc_null
#define nlmsvc_proc_unlock_res nlmsvc_proc_null
#define nlmsvc_proc_granted_res nlmsvc_proc_null
struct
nlm_void
{
int
dummy
;
};
...
...
@@ -576,7 +591,7 @@ struct svc_procedure nlmsvc_procedures[] = {
PROC
(
lock_res
,
lockres
,
norep
,
res
,
void
,
1
),
PROC
(
cancel_res
,
cancelres
,
norep
,
res
,
void
,
1
),
PROC
(
unlock_res
,
unlockres
,
norep
,
res
,
void
,
1
),
PROC
(
granted_res
,
grantedres
,
norep
,
res
,
void
,
1
),
PROC
(
granted_res
,
res
,
norep
,
res
,
void
,
1
),
/* statd callback */
PROC
(
sm_notify
,
reboot
,
void
,
reboot
,
void
,
1
),
PROC
(
none
,
void
,
void
,
void
,
void
,
1
),
...
...
fs/nfs/dir.c
View file @
aeb08fc0
...
...
@@ -139,11 +139,13 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
struct
file
*
file
=
desc
->
file
;
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
struct
rpc_cred
*
cred
=
nfs_file_cred
(
file
);
unsigned
long
timestamp
;
int
error
;
dfprintk
(
VFS
,
"NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.
\n
"
,
(
long
long
)
desc
->
entry
->
cookie
,
page
->
index
);
again:
timestamp
=
jiffies
;
error
=
NFS_PROTO
(
inode
)
->
readdir
(
file
->
f_dentry
,
cred
,
desc
->
entry
->
cookie
,
page
,
NFS_SERVER
(
inode
)
->
dtsize
,
desc
->
plus
);
if
(
error
<
0
)
{
...
...
@@ -157,18 +159,21 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
goto
error
;
}
SetPageUptodate
(
page
);
NFS_FLAGS
(
inode
)
|=
NFS_INO_INVALID_ATIME
;
/* Ensure consistent page alignment of the data.
* Note: assumes we have exclusive access to this mapping either
* throught inode->i_sem or some other mechanism.
*/
if
(
page
->
index
==
0
)
if
(
page
->
index
==
0
)
{
invalidate_inode_pages
(
inode
->
i_mapping
);
NFS_I
(
inode
)
->
readdir_timestamp
=
timestamp
;
}
unlock_page
(
page
);
return
0
;
error:
SetPageError
(
page
);
unlock_page
(
page
);
invalidate_inode_pages
(
inode
->
i_mapping
);
nfs_zap_caches
(
inode
);
desc
->
error
=
error
;
return
-
EIO
;
}
...
...
@@ -381,6 +386,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
page
,
NFS_SERVER
(
inode
)
->
dtsize
,
desc
->
plus
);
NFS_FLAGS
(
inode
)
|=
NFS_INO_INVALID_ATIME
;
desc
->
page
=
page
;
desc
->
ptr
=
kmap
(
page
);
/* matching kunmap in nfs_do_filldir */
if
(
desc
->
error
>=
0
)
{
...
...
@@ -459,7 +465,15 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
res
=
0
;
break
;
}
else
if
(
res
<
0
)
}
if
(
res
==
-
ETOOSMALL
&&
desc
->
plus
)
{
NFS_FLAGS
(
inode
)
&=
~
NFS_INO_ADVISE_RDPLUS
;
nfs_zap_caches
(
inode
);
desc
->
plus
=
0
;
desc
->
entry
->
eof
=
0
;
continue
;
}
if
(
res
<
0
)
break
;
res
=
nfs_do_filldir
(
desc
,
dirent
,
filldir
);
...
...
@@ -481,14 +495,19 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
* In the case it has, we assume that the dentries are untrustworthy
* and may need to be looked up again.
*/
static
inline
int
nfs_check_verifier
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
static
inline
int
nfs_check_verifier
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
if
(
IS_ROOT
(
dentry
))
return
1
;
if
(
nfs_revalidate_inode
(
NFS_SERVER
(
dir
),
dir
))
if
((
NFS_FLAGS
(
dir
)
&
NFS_INO_INVALID_ATTR
)
!=
0
||
nfs_attribute_timeout
(
dir
))
return
0
;
return
time_after
(
dentry
->
d_time
,
NFS_MTIME_UPDATE
(
dir
));
return
nfs_verify_change_attribute
(
dir
,
(
unsigned
long
)
dentry
->
d_fsdata
);
}
static
inline
void
nfs_set_verifier
(
struct
dentry
*
dentry
,
unsigned
long
verf
)
{
dentry
->
d_fsdata
=
(
void
*
)
verf
;
}
/*
...
...
@@ -528,9 +547,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
/* Don't revalidate a negative dentry if we're creating a new file */
if
((
ndflags
&
LOOKUP_CREATE
)
&&
!
(
ndflags
&
LOOKUP_CONTINUE
))
return
0
;
if
(
!
nfs_check_verifier
(
dir
,
dentry
))
return
1
;
return
time_after
(
jiffies
,
dentry
->
d_time
+
NFS_ATTRTIMEO
(
dir
));
return
!
nfs_check_verifier
(
dir
,
dentry
);
}
/*
...
...
@@ -552,6 +569,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
int
error
;
struct
nfs_fh
fhandle
;
struct
nfs_fattr
fattr
;
unsigned
long
verifier
;
int
isopen
=
0
;
parent
=
dget_parent
(
dentry
);
...
...
@@ -574,6 +592,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
goto
out_bad
;
}
/* Revalidate parent directory attribute cache */
nfs_revalidate_inode
(
NFS_SERVER
(
dir
),
dir
);
/* Force a full look up iff the parent directory has changed */
if
(
nfs_check_verifier
(
dir
,
dentry
))
{
if
(
nfs_lookup_verify_inode
(
inode
,
isopen
))
...
...
@@ -581,6 +602,12 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
goto
out_valid
;
}
/*
* Note: we're not holding inode->i_sem and so may be racing with
* operations that change the directory. We therefore save the
* change attribute *before* we do the RPC call.
*/
verifier
=
nfs_save_change_attribute
(
dir
);
error
=
nfs_cached_lookup
(
dir
,
dentry
,
&
fhandle
,
&
fattr
);
if
(
!
error
)
{
if
(
memcmp
(
NFS_FH
(
inode
),
&
fhandle
,
sizeof
(
struct
nfs_fh
))
!=
0
)
...
...
@@ -603,6 +630,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
out_valid_renew:
nfs_renew_times
(
dentry
);
nfs_set_verifier
(
dentry
,
verifier
);
out_valid:
unlock_kernel
();
dput
(
parent
);
...
...
@@ -638,6 +666,11 @@ static int nfs_dentry_delete(struct dentry *dentry)
/* Unhash it, so that ->d_iput() would be called */
return
1
;
}
if
(
!
(
dentry
->
d_sb
->
s_flags
&
MS_ACTIVE
))
{
/* Unhash it, so that ancestors of killed async unlink
* files will be cleaned up during umount */
return
1
;
}
return
0
;
}
...
...
@@ -693,6 +726,8 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
dentry
->
d_op
=
NFS_PROTO
(
dir
)
->
dentry_ops
;
lock_kernel
();
/* Revalidate parent directory attribute cache */
nfs_revalidate_inode
(
NFS_SERVER
(
dir
),
dir
);
/* If we're doing an exclusive create, optimize away the lookup */
if
(
nfs_is_exclusive_create
(
dir
,
nd
))
...
...
@@ -715,6 +750,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
error
=
0
;
d_add
(
dentry
,
inode
);
nfs_renew_times
(
dentry
);
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dir
));
out_unlock:
unlock_kernel
();
out:
...
...
@@ -768,6 +804,14 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
/* Open the file on the server */
lock_kernel
();
/* Revalidate parent directory attribute cache */
nfs_revalidate_inode
(
NFS_SERVER
(
dir
),
dir
);
if
(
nd
->
intent
.
open
.
flags
&
O_CREAT
)
{
nfs_begin_data_update
(
dir
);
inode
=
nfs4_atomic_open
(
dir
,
dentry
,
nd
);
nfs_end_data_update
(
dir
);
}
else
inode
=
nfs4_atomic_open
(
dir
,
dentry
,
nd
);
unlock_kernel
();
if
(
IS_ERR
(
inode
))
{
...
...
@@ -790,6 +834,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
no_entry:
d_add
(
dentry
,
inode
);
nfs_renew_times
(
dentry
);
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dir
));
out:
BUG_ON
(
error
>
0
);
return
ERR_PTR
(
error
);
...
...
@@ -801,13 +846,16 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct
dentry
*
parent
=
NULL
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
inode
*
dir
;
unsigned
long
verifier
;
int
openflags
,
ret
=
0
;
/* NFS only supports OPEN for regular files */
if
(
inode
&&
!
S_ISREG
(
inode
->
i_mode
))
goto
no_open
;
parent
=
dget_parent
(
dentry
);
if
(
!
is_atomic_open
(
parent
->
d_inode
,
nd
))
dir
=
parent
->
d_inode
;
if
(
!
is_atomic_open
(
dir
,
nd
))
goto
no_open
;
openflags
=
nd
->
intent
.
open
.
flags
;
if
(
openflags
&
O_CREAT
)
{
...
...
@@ -821,8 +869,16 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
/* We can't create new files, or truncate existing ones here */
openflags
&=
~
(
O_CREAT
|
O_TRUNC
);
/*
* Note: we're not holding inode->i_sem and so may be racing with
* operations that change the directory. We therefore save the
* change attribute *before* we do the RPC call.
*/
lock_kernel
();
ret
=
nfs4_open_revalidate
(
parent
->
d_inode
,
dentry
,
openflags
);
verifier
=
nfs_save_change_attribute
(
dir
);
ret
=
nfs4_open_revalidate
(
dir
,
dentry
,
openflags
);
if
(
!
ret
)
nfs_set_verifier
(
dentry
,
verifier
);
unlock_kernel
();
out:
dput
(
parent
);
...
...
@@ -869,15 +925,20 @@ int nfs_cached_lookup(struct inode *dir, struct dentry *dentry,
struct
nfs_server
*
server
;
struct
nfs_entry
entry
;
struct
page
*
page
;
unsigned
long
timestamp
=
NFS_MTIME_UPDATE
(
dir
)
;
unsigned
long
timestamp
;
int
res
;
if
(
!
NFS_USE_READDIRPLUS
(
dir
))
return
-
ENOENT
;
server
=
NFS_SERVER
(
dir
);
if
(
server
->
flags
&
NFS_MOUNT_NOAC
)
/* Don't use readdirplus unless the cache is stable */
if
((
server
->
flags
&
NFS_MOUNT_NOAC
)
!=
0
||
nfs_caches_unstable
(
dir
)
||
nfs_attribute_timeout
(
dir
))
return
-
ENOENT
;
if
((
NFS_FLAGS
(
dir
)
&
(
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
))
!=
0
)
return
-
ENOENT
;
nfs_revalidate_inode
(
server
,
dir
)
;
timestamp
=
NFS_I
(
dir
)
->
readdir_timestamp
;
entry
.
fh
=
fh
;
entry
.
fattr
=
fattr
;
...
...
@@ -931,9 +992,10 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
if
(
inode
)
{
d_instantiate
(
dentry
,
inode
);
nfs_renew_times
(
dentry
);
error
=
0
;
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dentry
->
d_parent
->
d_inode
));
return
0
;
}
return
error
;
error
=
-
ENOMEM
;
out_err:
d_drop
(
dentry
);
return
error
;
...
...
@@ -969,11 +1031,13 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
* does not pass the create flags.
*/
lock_kernel
();
nfs_
zap_caches
(
dir
);
nfs_
begin_data_update
(
dir
);
inode
=
NFS_PROTO
(
dir
)
->
create
(
dir
,
&
dentry
->
d_name
,
&
attr
,
open_flags
);
nfs_end_data_update
(
dir
);
if
(
!
IS_ERR
(
inode
))
{
d_instantiate
(
dentry
,
inode
);
nfs_renew_times
(
dentry
);
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dir
));
error
=
0
;
}
else
{
error
=
PTR_ERR
(
inode
);
...
...
@@ -1004,9 +1068,10 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
attr
.
ia_valid
=
ATTR_MODE
;
lock_kernel
();
nfs_
zap_caches
(
dir
);
nfs_
begin_data_update
(
dir
);
error
=
NFS_PROTO
(
dir
)
->
mknod
(
dir
,
&
dentry
->
d_name
,
&
attr
,
rdev
,
&
fhandle
,
&
fattr
);
nfs_end_data_update
(
dir
);
if
(
!
error
)
error
=
nfs_instantiate
(
dentry
,
&
fhandle
,
&
fattr
);
else
...
...
@@ -1041,9 +1106,10 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
*/
d_drop(dentry);
#endif
nfs_
zap_caches
(
dir
);
nfs_
begin_data_update
(
dir
);
error
=
NFS_PROTO
(
dir
)
->
mkdir
(
dir
,
&
dentry
->
d_name
,
&
attr
,
&
fhandle
,
&
fattr
);
nfs_end_data_update
(
dir
);
if
(
!
error
)
error
=
nfs_instantiate
(
dentry
,
&
fhandle
,
&
fattr
);
else
...
...
@@ -1060,10 +1126,12 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
dir
->
i_ino
,
dentry
->
d_name
.
name
);
lock_kernel
();
nfs_
zap_caches
(
dir
);
nfs_
begin_data_update
(
dir
);
error
=
NFS_PROTO
(
dir
)
->
rmdir
(
dir
,
&
dentry
->
d_name
);
if
(
!
error
)
/* Ensure the VFS deletes this inode */
if
(
error
==
0
&&
dentry
->
d_inode
!=
NULL
)
dentry
->
d_inode
->
i_nlink
=
0
;
nfs_end_data_update
(
dir
);
unlock_kernel
();
return
error
;
...
...
@@ -1119,12 +1187,21 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
goto
out
;
}
while
(
sdentry
->
d_inode
!=
NULL
);
/* need negative lookup */
nfs_zap_caches
(
dir
);
qsilly
.
name
=
silly
;
qsilly
.
len
=
strlen
(
silly
);
error
=
NFS_PROTO
(
dir
)
->
rename
(
dir
,
&
dentry
->
d_name
,
dir
,
&
qsilly
);
nfs_begin_data_update
(
dir
);
if
(
dentry
->
d_inode
)
{
nfs_begin_data_update
(
dentry
->
d_inode
);
error
=
NFS_PROTO
(
dir
)
->
rename
(
dir
,
&
dentry
->
d_name
,
dir
,
&
qsilly
);
nfs_end_data_update
(
dentry
->
d_inode
);
}
else
error
=
NFS_PROTO
(
dir
)
->
rename
(
dir
,
&
dentry
->
d_name
,
dir
,
&
qsilly
);
nfs_end_data_update
(
dir
);
if
(
!
error
)
{
nfs_renew_times
(
dentry
);
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dir
));
d_move
(
dentry
,
sdentry
);
error
=
nfs_async_unlink
(
dentry
);
/* If we return 0 we don't unlink */
...
...
@@ -1156,14 +1233,17 @@ static int nfs_safe_remove(struct dentry *dentry)
goto
out
;
}
nfs_
zap_caches
(
dir
);
if
(
inode
)
NFS_CACHEINV
(
inode
);
nfs_
begin_data_update
(
dir
);
if
(
inode
!=
NULL
)
{
nfs_begin_data_update
(
inode
);
error
=
NFS_PROTO
(
dir
)
->
remove
(
dir
,
&
dentry
->
d_name
);
if
(
error
<
0
)
goto
out
;
if
(
inode
)
/* The VFS may want to delete this inode */
if
(
error
==
0
)
inode
->
i_nlink
--
;
nfs_end_data_update
(
inode
);
}
else
error
=
NFS_PROTO
(
dir
)
->
remove
(
dir
,
&
dentry
->
d_name
);
nfs_end_data_update
(
dir
);
out:
return
error
;
}
...
...
@@ -1198,9 +1278,10 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
spin_unlock
(
&
dentry
->
d_lock
);
spin_unlock
(
&
dcache_lock
);
error
=
nfs_safe_remove
(
dentry
);
if
(
!
error
)
if
(
!
error
)
{
nfs_renew_times
(
dentry
);
else
if
(
need_rehash
)
nfs_set_verifier
(
dentry
,
nfs_save_change_attribute
(
dir
));
}
else
if
(
need_rehash
)
d_rehash
(
dentry
);
unlock_kernel
();
return
error
;
...
...
@@ -1247,9 +1328,10 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
qsymname
.
len
=
strlen
(
symname
);
lock_kernel
();
nfs_
zap_caches
(
dir
);
nfs_
begin_data_update
(
dir
);
error
=
NFS_PROTO
(
dir
)
->
symlink
(
dir
,
&
dentry
->
d_name
,
&
qsymname
,
&
attr
,
&
sym_fh
,
&
sym_attr
);
nfs_end_data_update
(
dir
);
if
(
!
error
)
{
error
=
nfs_instantiate
(
dentry
,
&
sym_fh
,
&
sym_attr
);
}
else
{
...
...
@@ -1281,9 +1363,12 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
*/
lock_kernel
();
d_drop
(
dentry
);
nfs_zap_caches
(
dir
);
NFS_CACHEINV
(
inode
);
nfs_begin_data_update
(
dir
);
nfs_begin_data_update
(
inode
);
error
=
NFS_PROTO
(
dir
)
->
link
(
inode
,
dir
,
&
dentry
->
d_name
);
nfs_end_data_update
(
inode
);
nfs_end_data_update
(
dir
);
unlock_kernel
();
return
error
;
}
...
...
@@ -1388,16 +1473,23 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if
(
new_inode
)
d_delete
(
new_dentry
);
nfs_zap_caches
(
new_dir
);
nfs_zap_caches
(
old_dir
);
nfs_begin_data_update
(
old_dir
);
nfs_begin_data_update
(
new_dir
);
nfs_begin_data_update
(
old_inode
);
error
=
NFS_PROTO
(
old_dir
)
->
rename
(
old_dir
,
&
old_dentry
->
d_name
,
new_dir
,
&
new_dentry
->
d_name
);
nfs_end_data_update
(
old_inode
);
nfs_end_data_update
(
new_dir
);
nfs_end_data_update
(
old_dir
);
out:
if
(
rehash
)
d_rehash
(
rehash
);
if
(
!
error
&&
!
S_ISDIR
(
old_inode
->
i_mode
))
if
(
!
error
)
{
if
(
!
S_ISDIR
(
old_inode
->
i_mode
))
d_move
(
old_dentry
,
new_dentry
);
nfs_renew_times
(
new_dentry
);
nfs_set_verifier
(
new_dentry
,
nfs_save_change_attribute
(
new_dir
));
}
/* new dentry created? */
if
(
dentry
)
...
...
@@ -1451,7 +1543,8 @@ nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
cred
=
rpcauth_lookupcred
(
NFS_CLIENT
(
inode
)
->
cl_auth
,
0
);
if
(
cache
->
cred
==
cred
&&
time_before
(
jiffies
,
cache
->
jiffies
+
NFS_ATTRTIMEO
(
inode
)))
{
&&
time_before
(
jiffies
,
cache
->
jiffies
+
NFS_ATTRTIMEO
(
inode
))
&&
!
(
NFS_FLAGS
(
inode
)
&
NFS_INO_INVALID_ATTR
))
{
if
(
!
(
res
=
cache
->
err
))
{
/* Is the mask a subset of an accepted mask? */
if
((
cache
->
mask
&
mask
)
==
mask
)
...
...
fs/nfs/direct.c
View file @
aeb08fc0
...
...
@@ -269,6 +269,7 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
if
(
IS_SYNC
(
inode
)
||
NFS_PROTO
(
inode
)
->
version
==
2
||
count
<=
wsize
)
wdata
.
args
.
stable
=
NFS_FILE_SYNC
;
nfs_begin_data_update
(
inode
);
retry:
need_commit
=
0
;
tot_bytes
=
0
;
...
...
@@ -334,6 +335,8 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
VERF_SIZE
)
!=
0
)
goto
sync_retry
;
}
nfs_end_data_update
(
inode
);
NFS_FLAGS
(
inode
)
|=
NFS_INO_INVALID_DATA
;
return
tot_bytes
;
...
...
fs/nfs/file.c
View file @
aeb08fc0
...
...
@@ -104,11 +104,16 @@ nfs_file_flush(struct file *file)
dfprintk
(
VFS
,
"nfs: flush(%s/%ld)
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
if
((
file
->
f_mode
&
FMODE_WRITE
)
==
0
)
return
0
;
lock_kernel
();
status
=
nfs_wb_file
(
inode
,
file
);
/* Ensure that data+attribute caches are up to date after close() */
status
=
nfs_wb_all
(
inode
);
if
(
!
status
)
{
status
=
file
->
f_error
;
file
->
f_error
=
0
;
if
(
!
status
)
__nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
}
unlock_kernel
();
return
status
;
...
...
@@ -179,7 +184,7 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
dfprintk
(
VFS
,
"nfs: fsync(%s/%ld)
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
lock_kernel
();
status
=
nfs_wb_
file
(
inode
,
fil
e
);
status
=
nfs_wb_
all
(
inod
e
);
if
(
!
status
)
{
status
=
file
->
f_error
;
file
->
f_error
=
0
;
...
...
fs/nfs/inode.c
View file @
aeb08fc0
...
...
@@ -47,14 +47,11 @@
* their needs. People that do NFS over a slow network, might for
* instance want to reduce it to something closer to 1 for improved
* interactive response.
*
* For the moment, though, we instead set it to RPC_MAXREQS, which
* is the maximum number of simultaneous RPC requests on the wire.
*/
#define NFS_MAX_READAHEAD
RPC_MAXREQS
#define NFS_MAX_READAHEAD
(RPC_DEF_SLOT_TABLE - 1)
void
nfs_zap_caches
(
struct
inode
*
);
static
void
nfs_invalidate_inode
(
struct
inode
*
);
static
int
nfs_update_inode
(
struct
inode
*
,
struct
nfs_fattr
*
,
unsigned
long
);
static
struct
inode
*
nfs_alloc_inode
(
struct
super_block
*
sb
);
static
void
nfs_destroy_inode
(
struct
inode
*
);
...
...
@@ -118,7 +115,7 @@ nfs_write_inode(struct inode *inode, int sync)
{
int
flags
=
sync
?
FLUSH_WAIT
:
0
;
nfs_commit_
file
(
inode
,
NULL
,
0
,
0
,
flags
);
nfs_commit_
inode
(
inode
,
0
,
0
,
flags
);
}
static
void
...
...
@@ -151,6 +148,7 @@ nfs_clear_inode(struct inode *inode)
cred
=
nfsi
->
cache_access
.
cred
;
if
(
cred
)
put_rpccred
(
cred
);
BUG_ON
(
atomic_read
(
&
nfsi
->
data_updates
)
!=
0
);
}
void
...
...
@@ -230,50 +228,23 @@ nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
/*
* Obtain the root inode of the file system.
*/
static
int
nfs_get_root
(
struct
inode
**
rooti
,
rpc_authflavor_t
authflavor
,
struct
super_block
*
sb
,
struct
nfs_fh
*
rootfh
)
static
struct
inode
*
nfs_get_root
(
struct
super_block
*
sb
,
struct
nfs_fh
*
rootfh
,
struct
nfs_fsinfo
*
fsinfo
)
{
struct
nfs_server
*
server
=
NFS_SB
(
sb
);
struct
nfs_fattr
fattr
=
{
}
;
struct
inode
*
rooti
;
int
error
;
error
=
server
->
rpc_ops
->
getroot
(
server
,
rootfh
,
&
fattr
);
if
(
error
==
-
EACCES
&&
authflavor
>
RPC_AUTH_MAXFLAVOR
)
{
/*
* Some authentication types (gss/krb5, most notably)
* are such that root won't be able to present a
* credential for GETATTR (ie, getroot()).
*
* We still want the mount to succeed.
*
* So we fake the attr values and mark the inode as such.
* On the first succesful traversal, we fix everything.
* The auth type test isn't quite correct, but whatever.
*/
dfprintk
(
VFS
,
"NFS: faking root inode
\n
"
);
fattr
.
fileid
=
1
;
fattr
.
nlink
=
2
;
/* minimum for a dir */
fattr
.
type
=
NFDIR
;
fattr
.
mode
=
S_IFDIR
|
S_IRUGO
|
S_IXUGO
;
fattr
.
size
=
4096
;
fattr
.
du
.
nfs3
.
used
=
1
;
fattr
.
valid
=
NFS_ATTR_FATTR
|
NFS_ATTR_FATTR_V3
;
}
else
if
(
error
<
0
)
{
error
=
server
->
rpc_ops
->
getroot
(
server
,
rootfh
,
fsinfo
);
if
(
error
<
0
)
{
printk
(
KERN_NOTICE
"nfs_get_root: getattr error = %d
\n
"
,
-
error
);
*
rooti
=
NULL
;
/* superfluous ... but safe */
return
error
;
return
ERR_PTR
(
error
);
}
*
rooti
=
nfs_fhget
(
sb
,
rootfh
,
&
fattr
);
if
(
error
==
-
EACCES
&&
authflavor
>
RPC_AUTH_MAXFLAVOR
)
{
if
(
*
rooti
)
{
NFS_FLAGS
(
*
rooti
)
|=
NFS_INO_FAKE_ROOT
;
NFS_CACHEINV
((
*
rooti
));
error
=
0
;
}
}
return
error
;
rooti
=
nfs_fhget
(
sb
,
rootfh
,
fsinfo
->
fattr
);
if
(
!
rooti
)
return
ERR_PTR
(
-
ENOMEM
);
return
rooti
;
}
/*
...
...
@@ -283,7 +254,7 @@ static int
nfs_sb_init
(
struct
super_block
*
sb
,
rpc_authflavor_t
authflavor
)
{
struct
nfs_server
*
server
;
struct
inode
*
root_inode
=
NULL
;
struct
inode
*
root_inode
;
struct
nfs_fattr
fattr
;
struct
nfs_fsinfo
fsinfo
=
{
.
fattr
=
&
fattr
,
...
...
@@ -299,8 +270,9 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
sb
->
s_magic
=
NFS_SUPER_MAGIC
;
root_inode
=
nfs_get_root
(
sb
,
&
server
->
fh
,
&
fsinfo
);
/* Did getting the root inode fail? */
if
(
nfs_get_root
(
&
root_inode
,
authflavor
,
sb
,
&
server
->
fh
)
<
0
)
if
(
IS_ERR
(
root_inode
)
)
goto
out_no_root
;
sb
->
s_root
=
d_alloc_root
(
root_inode
);
if
(
!
sb
->
s_root
)
...
...
@@ -309,10 +281,6 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
sb
->
s_root
->
d_op
=
server
->
rpc_ops
->
dentry_ops
;
/* Get some general file system info */
if
(
server
->
rpc_ops
->
fsinfo
(
server
,
&
server
->
fh
,
&
fsinfo
)
<
0
)
{
printk
(
KERN_NOTICE
"NFS: cannot retrieve file system info.
\n
"
);
goto
out_no_root
;
}
if
(
server
->
namelen
==
0
&&
server
->
rpc_ops
->
pathconf
(
server
,
&
server
->
fh
,
&
pathinfo
)
>=
0
)
server
->
namelen
=
pathinfo
.
max_namelen
;
...
...
@@ -368,13 +336,11 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
rpc_setbufsize
(
server
->
client
,
server
->
wsize
+
100
,
server
->
rsize
+
100
);
return
0
;
/* Yargs. It didn't work out. */
out_free_all:
if
(
root_inode
)
iput
(
root_inode
);
return
-
EINVAL
;
out_no_root:
printk
(
"nfs_read_super: get root inode failed
\n
"
);
goto
out_free_all
;
if
(
!
IS_ERR
(
root_inode
))
iput
(
root_inode
);
return
-
EINVAL
;
}
/*
...
...
@@ -402,13 +368,13 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
/* create transport and client */
xprt
=
xprt_create_proto
(
tcp
?
IPPROTO_TCP
:
IPPROTO_UDP
,
&
server
->
addr
,
&
timeparms
);
if
(
xprt
==
NULL
)
{
if
(
IS_ERR
(
xprt
)
)
{
printk
(
KERN_WARNING
"NFS: cannot create RPC transport.
\n
"
);
goto
out_fail
;
return
(
struct
rpc_clnt
*
)
xprt
;
}
clnt
=
rpc_create_client
(
xprt
,
server
->
hostname
,
&
nfs_program
,
server
->
rpc_ops
->
version
,
data
->
pseudoflavor
);
if
(
clnt
==
NULL
)
{
if
(
IS_ERR
(
clnt
)
)
{
printk
(
KERN_WARNING
"NFS: cannot create RPC client.
\n
"
);
goto
out_fail
;
}
...
...
@@ -421,9 +387,8 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
return
clnt
;
out_fail:
if
(
xprt
)
xprt_destroy
(
xprt
);
return
NULL
;
return
clnt
;
}
/*
...
...
@@ -627,13 +592,17 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
void
nfs_zap_caches
(
struct
inode
*
inode
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
int
mode
=
inode
->
i_mode
;
NFS_ATTRTIMEO
(
inode
)
=
NFS_MINATTRTIMEO
(
inode
);
NFS_ATTRTIMEO_UPDATE
(
inode
)
=
jiffies
;
invalidate_remote_inode
(
inode
);
memset
(
NFS_COOKIEVERF
(
inode
),
0
,
sizeof
(
NFS_COOKIEVERF
(
inode
)));
NFS_CACHEINV
(
inode
);
if
(
S_ISREG
(
mode
)
||
S_ISDIR
(
mode
)
||
S_ISLNK
(
mode
))
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
;
else
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
}
/*
...
...
@@ -673,9 +642,6 @@ nfs_find_actor(struct inode *inode, void *opaque)
return
0
;
if
(
is_bad_inode
(
inode
))
return
0
;
/* Force an attribute cache update if inode->i_count == 0 */
if
(
!
atomic_read
(
&
inode
->
i_count
))
NFS_CACHEINV
(
inode
);
return
1
;
}
...
...
@@ -729,7 +695,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
inode
->
i_ino
=
hash
;
/* We can't support update_atime(), since the server will reset it */
inode
->
i_flags
|=
S_NOATIME
;
inode
->
i_flags
|=
S_NOATIME
|
S_NOCMTIME
;
inode
->
i_mode
=
fattr
->
mode
;
/* Why so? Because we want revalidate for devices/FIFOs, and
* that's precisely what we have in nfs_file_inode_operations.
...
...
@@ -754,10 +720,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
inode
->
i_atime
=
fattr
->
atime
;
inode
->
i_mtime
=
fattr
->
mtime
;
inode
->
i_ctime
=
fattr
->
ctime
;
nfsi
->
read_cache_ctime
=
fattr
->
ctime
;
nfsi
->
read_cache_mtime
=
fattr
->
mtime
;
nfsi
->
cache_mtime_jiffies
=
fattr
->
timestamp
;
nfsi
->
read_cache_isize
=
fattr
->
size
;
if
(
fattr
->
valid
&
NFS_ATTR_FATTR_V4
)
nfsi
->
change_attr
=
fattr
->
change_attr
;
inode
->
i_size
=
nfs_size_to_loff_t
(
fattr
->
size
);
...
...
@@ -804,70 +766,50 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
struct
nfs_fattr
fattr
;
int
error
;
if
(
attr
->
ia_valid
&
ATTR_SIZE
)
{
if
(
!
S_ISREG
(
inode
->
i_mode
)
||
attr
->
ia_size
==
i_size_read
(
inode
))
attr
->
ia_valid
&=
~
ATTR_SIZE
;
}
/* Optimization: if the end result is no change, don't RPC */
attr
->
ia_valid
&=
NFS_VALID_ATTRS
;
if
(
attr
->
ia_valid
==
0
)
return
0
;
lock_kernel
();
/*
* Make sure the inode is up-to-date.
*/
error
=
nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
if
(
error
)
{
#ifdef NFS_PARANOIA
printk
(
"nfs_setattr: revalidate failed, error=%d
\n
"
,
error
);
#endif
goto
out
;
}
if
(
!
S_ISREG
(
inode
->
i_mode
))
{
attr
->
ia_valid
&=
~
ATTR_SIZE
;
if
(
attr
->
ia_valid
==
0
)
goto
out
;
}
else
{
filemap_fdatawrite
(
inode
->
i_mapping
);
error
=
nfs_wb_all
(
inode
);
nfs_begin_data_update
(
inode
);
/* Write all dirty data if we're changing file permissions or size */
if
((
attr
->
ia_valid
&
(
ATTR_MODE
|
ATTR_UID
|
ATTR_GID
|
ATTR_SIZE
))
!=
0
)
{
if
(
filemap_fdatawrite
(
inode
->
i_mapping
)
==
0
)
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
error
)
goto
out
;
/* Optimize away unnecessary truncates */
if
((
attr
->
ia_valid
&
ATTR_SIZE
)
&&
i_size_read
(
inode
)
==
attr
->
ia_size
)
attr
->
ia_valid
&=
~
ATTR_SIZE
;
nfs_wb_all
(
inode
);
}
if
(
!
attr
->
ia_valid
)
goto
out
;
error
=
NFS_PROTO
(
inode
)
->
setattr
(
dentry
,
&
fattr
,
attr
);
if
(
error
)
goto
out
;
/*
* If we changed the size or mtime, update the inode
* now to avoid invalidating the page cache.
*/
if
(
attr
->
ia_valid
&
ATTR_SIZE
)
{
if
(
attr
->
ia_size
!=
fattr
.
size
)
printk
(
"nfs_setattr: attr=%Ld, fattr=%Ld??
\n
"
,
(
long
long
)
attr
->
ia_size
,
(
long
long
)
fattr
.
size
);
if
(
error
==
0
)
{
nfs_refresh_inode
(
inode
,
&
fattr
);
if
((
attr
->
ia_valid
&
ATTR_MODE
)
!=
0
)
{
int
mode
;
mode
=
inode
->
i_mode
&
~
S_IALLUGO
;
mode
|=
attr
->
ia_mode
&
S_IALLUGO
;
inode
->
i_mode
=
mode
;
}
if
((
attr
->
ia_valid
&
ATTR_UID
)
!=
0
)
inode
->
i_uid
=
attr
->
ia_uid
;
if
((
attr
->
ia_valid
&
ATTR_GID
)
!=
0
)
inode
->
i_gid
=
attr
->
ia_gid
;
if
((
attr
->
ia_valid
&
ATTR_SIZE
)
!=
0
)
{
inode
->
i_size
=
attr
->
ia_size
;
vmtruncate
(
inode
,
attr
->
ia_size
);
}
/*
* If we changed the size or mtime, update the inode
* now to avoid invalidating the page cache.
*/
if
(
!
(
fattr
.
valid
&
NFS_ATTR_WCC
))
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
fattr
.
pre_size
=
nfsi
->
read_cache_isize
;
fattr
.
pre_mtime
=
nfsi
->
read_cache_mtime
;
fattr
.
pre_ctime
=
nfsi
->
read_cache_ctime
;
fattr
.
valid
|=
NFS_ATTR_WCC
;
}
/* Force an attribute cache update */
NFS_CACHEINV
(
inode
);
error
=
nfs_refresh_inode
(
inode
,
&
fattr
);
out:
}
if
((
attr
->
ia_valid
&
(
ATTR_MODE
|
ATTR_UID
|
ATTR_GID
))
!=
0
)
{
struct
rpc_cred
**
cred
=
&
NFS_I
(
inode
)
->
cache_access
.
cred
;
if
(
*
cred
)
{
put_rpccred
(
*
cred
);
*
cred
=
NULL
;
}
}
nfs_end_data_update
(
inode
);
unlock_kernel
();
return
error
;
}
...
...
@@ -895,7 +837,19 @@ nfs_wait_on_inode(struct inode *inode, int flag)
int
nfs_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
struct
kstat
*
stat
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
int
err
=
nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
int
need_atime
=
nfsi
->
flags
&
NFS_INO_INVALID_ATIME
;
int
err
;
if
(
__IS_FLG
(
inode
,
MS_NOATIME
))
need_atime
=
0
;
else
if
(
__IS_FLG
(
inode
,
MS_NODIRATIME
)
&&
S_ISDIR
(
inode
->
i_mode
))
need_atime
=
0
;
/* We may force a getattr if the user cares about atime */
if
(
need_atime
)
err
=
__nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
else
err
=
nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
if
(
!
err
)
generic_fillattr
(
inode
,
stat
);
return
err
;
...
...
@@ -930,8 +884,10 @@ int nfs_open(struct inode *inode, struct file *filp)
auth
=
NFS_CLIENT
(
inode
)
->
cl_auth
;
cred
=
rpcauth_lookupcred
(
auth
,
0
);
filp
->
private_data
=
cred
;
if
(
filp
->
f_mode
&
FMODE_WRITE
)
if
(
(
filp
->
f_mode
&
FMODE_WRITE
)
!=
0
)
{
nfs_set_mmcred
(
inode
,
cred
);
nfs_begin_data_update
(
inode
);
}
return
0
;
}
...
...
@@ -940,6 +896,8 @@ int nfs_release(struct inode *inode, struct file *filp)
struct
rpc_cred
*
cred
;
lock_kernel
();
if
((
filp
->
f_mode
&
FMODE_WRITE
)
!=
0
)
nfs_end_data_update
(
inode
);
cred
=
nfs_file_cred
(
filp
);
if
(
cred
)
put_rpccred
(
cred
);
...
...
@@ -956,6 +914,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
int
status
=
-
ESTALE
;
struct
nfs_fattr
fattr
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
unsigned
long
verifier
;
unsigned
int
flags
;
dfprintk
(
PAGECACHE
,
"NFS: revalidating (%s/%Ld)
\n
"
,
inode
->
i_sb
->
s_id
,
(
long
long
)
NFS_FILEID
(
inode
));
...
...
@@ -965,23 +926,22 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto
out_nowait
;
if
(
NFS_STALE
(
inode
)
&&
inode
!=
inode
->
i_sb
->
s_root
->
d_inode
)
goto
out_nowait
;
if
(
NFS_FAKE_ROOT
(
inode
))
{
dfprintk
(
VFS
,
"NFS: not revalidating fake root
\n
"
);
status
=
0
;
goto
out_nowait
;
}
while
(
NFS_REVALIDATING
(
inode
))
{
status
=
nfs_wait_on_inode
(
inode
,
NFS_INO_REVALIDATING
);
if
(
status
<
0
)
goto
out_nowait
;
if
(
time_before
(
jiffies
,
NFS_READTIME
(
inode
)
+
NFS_ATTRTIMEO
(
inode
)))
{
if
(
NFS_SERVER
(
inode
)
->
flags
&
NFS_MOUNT_NOAC
)
continue
;
if
(
NFS_FLAGS
(
inode
)
&
(
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
|
NFS_INO_INVALID_ATIME
))
continue
;
status
=
NFS_STALE
(
inode
)
?
-
ESTALE
:
0
;
goto
out_nowait
;
}
}
NFS_FLAGS
(
inode
)
|=
NFS_INO_REVALIDATING
;
/* Protect against RPC races by saving the change attribute */
verifier
=
nfs_save_change_attribute
(
inode
);
status
=
NFS_PROTO
(
inode
)
->
getattr
(
inode
,
&
fattr
);
if
(
status
)
{
dfprintk
(
PAGECACHE
,
"nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d
\n
"
,
...
...
@@ -995,13 +955,36 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto
out
;
}
status
=
nfs_
refresh_inode
(
inode
,
&
fatt
r
);
status
=
nfs_
update_inode
(
inode
,
&
fattr
,
verifie
r
);
if
(
status
)
{
dfprintk
(
PAGECACHE
,
"nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d
\n
"
,
inode
->
i_sb
->
s_id
,
(
long
long
)
NFS_FILEID
(
inode
),
status
);
goto
out
;
}
flags
=
nfsi
->
flags
;
/*
* We may need to keep the attributes marked as invalid if
* we raced with nfs_end_attr_update().
*/
if
(
verifier
==
nfsi
->
cache_change_attribute
)
nfsi
->
flags
&=
~
(
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_ATIME
);
/* Do the page cache invalidation */
if
(
flags
&
NFS_INO_INVALID_DATA
)
{
if
(
S_ISREG
(
inode
->
i_mode
))
{
if
(
filemap_fdatawrite
(
inode
->
i_mapping
)
==
0
)
filemap_fdatawait
(
inode
->
i_mapping
);
nfs_wb_all
(
inode
);
}
nfsi
->
flags
&=
~
NFS_INO_INVALID_DATA
;
invalidate_inode_pages2
(
inode
->
i_mapping
);
memset
(
NFS_COOKIEVERF
(
inode
),
0
,
sizeof
(
NFS_COOKIEVERF
(
inode
)));
dfprintk
(
PAGECACHE
,
"NFS: (%s/%Ld) data cache invalidated
\n
"
,
inode
->
i_sb
->
s_id
,
(
long
long
)
NFS_FILEID
(
inode
));
/* This ensures we revalidate dentries */
nfsi
->
cache_change_attribute
++
;
}
dfprintk
(
PAGECACHE
,
"NFS: (%s/%Ld) revalidation complete
\n
"
,
inode
->
i_sb
->
s_id
,
(
long
long
)
NFS_FILEID
(
inode
));
...
...
@@ -1009,41 +992,107 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
NFS_FLAGS
(
inode
)
&=
~
NFS_INO_STALE
;
out:
NFS_FLAGS
(
inode
)
&=
~
NFS_INO_REVALIDATING
;
wake_up
(
&
NFS_I
(
inode
)
->
nfs_i_wait
);
wake_up
(
&
nfsi
->
nfs_i_wait
);
out_nowait:
unlock_kernel
();
return
status
;
}
/*
* nfs_fattr_obsolete - Test if attribute data is newer than cached data
* @inode: inode
* @fattr: attributes to test
/**
* nfs_begin_data_update
* @inode - pointer to inode
* Declare that a set of operations will update file data on the server
*/
void
nfs_begin_data_update
(
struct
inode
*
inode
)
{
atomic_inc
(
&
NFS_I
(
inode
)
->
data_updates
);
}
/**
* nfs_end_data_update
* @inode - pointer to inode
* Declare end of the operations that will update file data
*/
void
nfs_end_data_update
(
struct
inode
*
inode
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
/* Mark the attribute cache for revalidation */
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
/* Directories and symlinks: invalidate page cache too */
if
(
S_ISDIR
(
inode
->
i_mode
)
||
S_ISLNK
(
inode
->
i_mode
))
nfsi
->
flags
|=
NFS_INO_INVALID_DATA
;
nfsi
->
cache_change_attribute
++
;
atomic_dec
(
&
nfsi
->
data_updates
);
}
/**
* nfs_refresh_inode - verify consistency of the inode attribute cache
* @inode - pointer to inode
* @fattr - updated attributes
*
* Avoid stuffing the attribute cache with obsolete information.
* We always accept updates if the attribute cache timed out, or if
* fattr->ctime is newer than our cached value.
* If fattr->ctime matches the cached value, we still accept the update
* if it increases the file size.
* Verifies the attribute cache. If we have just changed the attributes,
* so that fattr carries weak cache consistency data, then it may
* also update the ctime/mtime/change_attribute.
*/
static
inline
int
nfs_fattr_obsolete
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
int
nfs_refresh_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
long
cdif
;
if
(
time_after
(
jiffies
,
nfsi
->
read_cache_jiffies
+
nfsi
->
attrtimeo
))
goto
out_valid
;
cdif
=
fattr
->
ctime
.
tv_sec
-
nfsi
->
read_cache_ctime
.
tv_sec
;
if
(
cdif
==
0
)
cdif
=
fattr
->
ctime
.
tv_nsec
-
nfsi
->
read_cache_ctime
.
tv_nsec
;
if
(
cdif
>
0
)
goto
out_valid
;
/* Ugh... */
if
(
cdif
==
0
&&
fattr
->
size
>
nfsi
->
read_cache_isize
)
goto
out_valid
;
return
-
1
;
out_valid:
loff_t
cur_size
,
new_isize
;
int
data_unstable
;
/* Are we in the process of updating data on the server? */
data_unstable
=
nfs_caches_unstable
(
inode
);
if
(
fattr
->
valid
&
NFS_ATTR_FATTR_V4
)
{
if
((
fattr
->
valid
&
NFS_ATTR_PRE_CHANGE
)
!=
0
&&
nfsi
->
change_attr
==
fattr
->
pre_change_attr
)
nfsi
->
change_attr
=
fattr
->
change_attr
;
if
(
!
data_unstable
&&
nfsi
->
change_attr
!=
fattr
->
change_attr
)
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
}
if
((
fattr
->
valid
&
NFS_ATTR_FATTR
)
==
0
)
return
0
;
/* Has the inode gone and changed behind our back? */
if
(
nfsi
->
fileid
!=
fattr
->
fileid
||
(
inode
->
i_mode
&
S_IFMT
)
!=
(
fattr
->
mode
&
S_IFMT
))
return
-
EIO
;
cur_size
=
i_size_read
(
inode
);
new_isize
=
nfs_size_to_loff_t
(
fattr
->
size
);
/* If we have atomic WCC data, we may update some attributes */
if
((
fattr
->
valid
&
NFS_ATTR_WCC
)
!=
0
)
{
if
(
timespec_equal
(
&
inode
->
i_ctime
,
&
fattr
->
pre_ctime
))
memcpy
(
&
inode
->
i_ctime
,
&
fattr
->
ctime
,
sizeof
(
inode
->
i_ctime
));
if
(
timespec_equal
(
&
inode
->
i_mtime
,
&
fattr
->
pre_mtime
))
memcpy
(
&
inode
->
i_mtime
,
&
fattr
->
mtime
,
sizeof
(
inode
->
i_mtime
));
}
/* Verify a few of the more important attributes */
if
(
!
data_unstable
)
{
if
(
!
timespec_equal
(
&
inode
->
i_mtime
,
&
fattr
->
mtime
)
||
cur_size
!=
new_isize
)
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
}
else
if
(
S_ISREG
(
inode
->
i_mode
)
&&
new_isize
>
cur_size
)
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
/* Have any file permissions changed? */
if
((
inode
->
i_mode
&
S_IALLUGO
)
!=
(
fattr
->
mode
&
S_IALLUGO
)
||
inode
->
i_uid
!=
fattr
->
uid
||
inode
->
i_gid
!=
fattr
->
gid
)
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
/* Has the link count changed? */
if
(
inode
->
i_nlink
!=
fattr
->
nlink
)
nfsi
->
flags
|=
NFS_INO_INVALID_ATTR
;
if
(
!
timespec_equal
(
&
inode
->
i_atime
,
&
fattr
->
atime
))
nfsi
->
flags
|=
NFS_INO_INVALID_ATIME
;
nfsi
->
read_cache_jiffies
=
fattr
->
timestamp
;
return
0
;
}
...
...
@@ -1059,65 +1108,66 @@ int nfs_fattr_obsolete(struct inode *inode, struct nfs_fattr *fattr)
*
* A very similar scenario holds for the dir cache.
*/
int
__nfs_refresh_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
static
int
nfs_update_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
,
unsigned
long
verifier
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
__u64
new_size
;
loff_t
new_isize
;
int
invalid
=
0
;
int
mtime_update
=
0
;
unsigned
int
invalid
=
0
;
loff_t
cur_isize
;
int
data_unstable
;
dfprintk
(
VFS
,
"NFS:
refresh_inode
(%s/%ld ct=%d info=0x%x)
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
,
dfprintk
(
VFS
,
"NFS:
%s
(%s/%ld ct=%d info=0x%x)
\n
"
,
__FUNCTION__
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
,
atomic_read
(
&
inode
->
i_count
),
fattr
->
valid
);
/* First successful call after mount, fill real data. */
if
(
NFS_FAKE_ROOT
(
inode
))
{
dfprintk
(
VFS
,
"NFS: updating fake root
\n
"
);
nfsi
->
fileid
=
fattr
->
fileid
;
NFS_FLAGS
(
inode
)
&=
~
NFS_INO_FAKE_ROOT
;
}
if
((
fattr
->
valid
&
NFS_ATTR_FATTR
)
==
0
)
return
0
;
if
(
nfsi
->
fileid
!=
fattr
->
fileid
)
{
printk
(
KERN_ERR
"
nfs_refresh_inode
: inode number mismatch
\n
"
printk
(
KERN_ERR
"
%s
: inode number mismatch
\n
"
"expected (%s/0x%Lx), got (%s/0x%Lx)
\n
"
,
__FUNCTION__
,
inode
->
i_sb
->
s_id
,
(
long
long
)
nfsi
->
fileid
,
inode
->
i_sb
->
s_id
,
(
long
long
)
fattr
->
fileid
);
goto
out_err
;
}
/* Throw out obsolete READDIRPLUS attributes */
if
(
time_before
(
fattr
->
timestamp
,
NFS_READTIME
(
inode
)))
return
0
;
/*
* Make sure the inode's type hasn't changed.
*/
if
((
inode
->
i_mode
&
S_IFMT
)
!=
(
fattr
->
mode
&
S_IFMT
))
goto
out_changed
;
new_size
=
fattr
->
size
;
new_isize
=
nfs_size_to_loff_t
(
fattr
->
size
);
/* Avoid races */
if
(
nfs_fattr_obsolete
(
inode
,
fattr
))
goto
out_nochange
;
/*
* Update the read time so we don't revalidate too often.
*/
nfsi
->
read_cache_jiffies
=
fattr
->
timestamp
;
/*
* Note: NFS_CACHE_ISIZE(inode) reflects the state of the cache.
* NOT inode->i_size!!!
*/
if
(
nfsi
->
read_cache_isize
!=
new_size
)
{
/* Are we racing with known updates of the metadata on the server? */
data_unstable
=
!
nfs_verify_change_attribute
(
inode
,
verifier
);
/* Check if the file size agrees */
new_size
=
fattr
->
size
;
new_isize
=
nfs_size_to_loff_t
(
fattr
->
size
);
cur_isize
=
i_size_read
(
inode
);
if
(
cur_isize
!=
new_size
)
{
#ifdef NFS_DEBUG_VERBOSE
printk
(
KERN_DEBUG
"NFS: isize change on %s/%ld
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
#endif
invalid
=
1
;
/*
* If we have pending writebacks, things can get
* messy.
*/
if
(
S_ISREG
(
inode
->
i_mode
)
&&
data_unstable
)
{
if
(
new_isize
>
cur_isize
)
{
inode
->
i_size
=
new_isize
;
invalid
|=
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
;
}
}
else
{
inode
->
i_size
=
new_isize
;
invalid
|=
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
;
}
}
/*
...
...
@@ -1125,12 +1175,13 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
* can change this value in VFS without requiring a
* cache revalidation.
*/
if
(
!
timespec_equal
(
&
nfsi
->
read_cache_mtime
,
&
fattr
->
mtime
))
{
if
(
!
timespec_equal
(
&
inode
->
i_mtime
,
&
fattr
->
mtime
))
{
memcpy
(
&
inode
->
i_mtime
,
&
fattr
->
mtime
,
sizeof
(
inode
->
i_mtime
));
#ifdef NFS_DEBUG_VERBOSE
printk
(
KERN_DEBUG
"NFS: mtime change on %s/%ld
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
#endif
i
nvalid
=
1
;
mtime_update
=
1
;
i
f
(
!
data_unstable
)
invalid
|=
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
;
}
if
((
fattr
->
valid
&
NFS_ATTR_FATTR_V4
)
...
...
@@ -1139,47 +1190,15 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
printk
(
KERN_DEBUG
"NFS: change_attr change on %s/%ld
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
#endif
invalid
=
1
;
}
/* Check Weak Cache Consistency data.
* If size and mtime match the pre-operation values, we can
* assume that any attribute changes were caused by our NFS
* operation, so there's no need to invalidate the caches.
*/
if
((
fattr
->
valid
&
NFS_ATTR_PRE_CHANGE
)
&&
nfsi
->
change_attr
==
fattr
->
pre_change_attr
)
{
invalid
=
0
;
}
else
if
((
fattr
->
valid
&
NFS_ATTR_WCC
)
&&
nfsi
->
read_cache_isize
==
fattr
->
pre_size
&&
timespec_equal
(
&
nfsi
->
read_cache_mtime
,
&
fattr
->
pre_mtime
))
{
invalid
=
0
;
}
/*
* If we have pending writebacks, things can get
* messy.
*/
cur_isize
=
i_size_read
(
inode
);
if
(
nfs_have_writebacks
(
inode
)
&&
new_isize
<
cur_isize
)
new_isize
=
cur_isize
;
nfsi
->
read_cache_ctime
=
fattr
->
ctime
;
inode
->
i_ctime
=
fattr
->
ctime
;
inode
->
i_atime
=
fattr
->
atime
;
if
(
mtime_update
)
{
if
(
invalid
)
nfsi
->
cache_mtime_jiffies
=
fattr
->
timestamp
;
nfsi
->
read_cache_mtime
=
fattr
->
mtime
;
inode
->
i_mtime
=
fattr
->
mtime
;
nfsi
->
change_attr
=
fattr
->
change_attr
;
if
(
!
data_unstable
)
invalid
|=
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
;
}
nfsi
->
read_cache_isize
=
new_size
;
i_size_write
(
inode
,
new_isize
);
memcpy
(
&
inode
->
i_ctime
,
&
fattr
->
ctime
,
sizeof
(
inode
->
i_ctime
))
;
memcpy
(
&
inode
->
i_atime
,
&
fattr
->
atime
,
sizeof
(
inode
->
i_atime
)
);
if
(
inode
->
i_mode
!=
fattr
->
mode
||
if
(
(
inode
->
i_mode
&
S_IALLUGO
)
!=
(
fattr
->
mode
&
S_IALLUGO
)
||
inode
->
i_uid
!=
fattr
->
uid
||
inode
->
i_gid
!=
fattr
->
gid
)
{
struct
rpc_cred
**
cred
=
&
NFS_I
(
inode
)
->
cache_access
.
cred
;
...
...
@@ -1187,11 +1206,9 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
put_rpccred
(
*
cred
);
*
cred
=
NULL
;
}
invalid
|=
NFS_INO_INVALID_ATTR
;
}
if
(
fattr
->
valid
&
NFS_ATTR_FATTR_V4
)
nfsi
->
change_attr
=
fattr
->
change_attr
;
inode
->
i_mode
=
fattr
->
mode
;
inode
->
i_nlink
=
fattr
->
nlink
;
inode
->
i_uid
=
fattr
->
uid
;
...
...
@@ -1208,30 +1225,29 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
inode
->
i_blksize
=
fattr
->
du
.
nfs2
.
blocksize
;
}
/* Update attrtimeo value */
if
(
invalid
)
{
/* Update attrtimeo value
if we're out of the unstable period
*/
if
(
invalid
&
NFS_INO_INVALID_ATTR
)
{
nfsi
->
attrtimeo
=
NFS_MINATTRTIMEO
(
inode
);
nfsi
->
attrtimeo_timestamp
=
jiffies
;
invalidate_remote_inode
(
inode
);
memset
(
NFS_COOKIEVERF
(
inode
),
0
,
sizeof
(
NFS_COOKIEVERF
(
inode
)));
}
else
if
(
time_after
(
jiffies
,
nfsi
->
attrtimeo_timestamp
+
nfsi
->
attrtimeo
))
{
if
((
nfsi
->
attrtimeo
<<=
1
)
>
NFS_MAXATTRTIMEO
(
inode
))
nfsi
->
attrtimeo
=
NFS_MAXATTRTIMEO
(
inode
);
nfsi
->
attrtimeo_timestamp
=
jiffies
;
}
/* Don't invalidate the data if we were to blame */
if
(
!
(
S_ISREG
(
inode
->
i_mode
)
||
S_ISDIR
(
inode
->
i_mode
)
||
S_ISLNK
(
inode
->
i_mode
)))
invalid
&=
~
NFS_INO_INVALID_DATA
;
nfsi
->
flags
|=
invalid
;
return
0
;
out_nochange:
if
(
!
timespec_equal
(
&
fattr
->
atime
,
&
inode
->
i_atime
))
inode
->
i_atime
=
fattr
->
atime
;
return
0
;
out_changed:
/*
* Big trouble! The inode has become a different object.
*/
#ifdef NFS_PARANOIA
printk
(
KERN_DEBUG
"
nfs_refresh_inode
: inode %ld mode changed, %07o to %07o
\n
"
,
inode
->
i_ino
,
inode
->
i_mode
,
fattr
->
mode
);
printk
(
KERN_DEBUG
"
%s
: inode %ld mode changed, %07o to %07o
\n
"
,
__FUNCTION__
,
inode
->
i_ino
,
inode
->
i_mode
,
fattr
->
mode
);
#endif
/*
* No need to worry about unhashing the dentry, as the
...
...
@@ -1391,8 +1407,8 @@ static void nfs4_clear_inode(struct inode *inode)
inode
->
i_sb
->
s_id
,
(
long
long
)
NFS_FILEID
(
inode
),
state
);
list_del
(
&
state
->
inode_states
);
nfs4_
put_open_state
(
state
);
BUG_ON
(
atomic_read
(
&
state
->
count
)
!=
1
);
nfs4_
close_state
(
state
,
state
->
state
);
}
/* Now call standard NFS clear_inode() code */
nfs_clear_inode
(
inode
);
...
...
@@ -1472,17 +1488,19 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
down_write
(
&
clp
->
cl_sem
);
if
(
clp
->
cl_rpcclient
==
NULL
)
{
xprt
=
xprt_create_proto
(
proto
,
&
server
->
addr
,
&
timeparms
);
if
(
xprt
==
NULL
)
{
if
(
IS_ERR
(
xprt
)
)
{
up_write
(
&
clp
->
cl_sem
);
printk
(
KERN_WARNING
"NFS: cannot create RPC transport.
\n
"
);
err
=
PTR_ERR
(
xprt
);
goto
out_fail
;
}
clnt
=
rpc_create_client
(
xprt
,
server
->
hostname
,
&
nfs_program
,
server
->
rpc_ops
->
version
,
authflavour
);
if
(
clnt
==
NULL
)
{
if
(
IS_ERR
(
clnt
)
)
{
up_write
(
&
clp
->
cl_sem
);
printk
(
KERN_WARNING
"NFS: cannot create RPC client.
\n
"
);
xprt_destroy
(
xprt
);
err
=
PTR_ERR
(
clnt
);
goto
out_fail
;
}
clnt
->
cl_chatty
=
1
;
...
...
@@ -1495,14 +1513,17 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
clear_bit
(
NFS4CLNT_OK
,
&
clp
->
cl_state
);
list_add_tail
(
&
server
->
nfs4_siblings
,
&
clp
->
cl_superblocks
);
clnt
=
rpc_clone_client
(
clp
->
cl_rpcclient
);
if
(
!
IS_ERR
(
clnt
))
server
->
nfs4_state
=
clp
;
up_write
(
&
clp
->
cl_sem
);
clp
=
NULL
;
if
(
clnt
==
NULL
)
{
if
(
IS_ERR
(
clnt
)
)
{
printk
(
KERN_WARNING
"NFS: cannot create RPC client.
\n
"
);
err
=
PTR_ERR
(
clnt
);
goto
out_remove_list
;
}
err
=
-
ENOMEM
;
if
(
server
->
nfs4_state
->
cl_idmap
==
NULL
)
{
printk
(
KERN_WARNING
"NFS: failed to create idmapper.
\n
"
);
goto
out_shutdown
;
...
...
@@ -1601,7 +1622,7 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
if
(
data
->
version
!=
NFS4_MOUNT_VERSION
)
{
printk
(
"nfs warning: mount version %s than kernel
\n
"
,
data
->
version
<
NFS_MOUNT_VERSION
?
"older"
:
"newer"
);
data
->
version
<
NFS
4
_MOUNT_VERSION
?
"older"
:
"newer"
);
}
p
=
nfs_copy_user_string
(
NULL
,
&
data
->
hostname
,
256
);
...
...
@@ -1718,6 +1739,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
INIT_LIST_HEAD
(
&
nfsi
->
dirty
);
INIT_LIST_HEAD
(
&
nfsi
->
commit
);
INIT_RADIX_TREE
(
&
nfsi
->
nfs_page_tree
,
GFP_ATOMIC
);
atomic_set
(
&
nfsi
->
data_updates
,
0
);
nfsi
->
ndirty
=
0
;
nfsi
->
ncommit
=
0
;
nfsi
->
npages
=
0
;
...
...
fs/nfs/mount_clnt.c
View file @
aeb08fc0
...
...
@@ -57,8 +57,9 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
(
unsigned
)
ntohl
(
addr
->
sin_addr
.
s_addr
),
path
);
sprintf
(
hostname
,
"%u.%u.%u.%u"
,
NIPQUAD
(
addr
->
sin_addr
.
s_addr
));
if
(
!
(
mnt_clnt
=
mnt_create
(
hostname
,
addr
,
version
,
protocol
)))
return
-
EACCES
;
mnt_clnt
=
mnt_create
(
hostname
,
addr
,
version
,
protocol
);
if
(
IS_ERR
(
mnt_clnt
))
return
PTR_ERR
(
mnt_clnt
);
call
=
(
version
==
NFS_MNT3_VERSION
)
?
MOUNTPROC3_MNT
:
MNTPROC_MNT
;
status
=
rpc_call
(
mnt_clnt
,
call
,
path
,
&
result
,
0
);
...
...
@@ -72,13 +73,14 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
struct
rpc_xprt
*
xprt
;
struct
rpc_clnt
*
clnt
;
if
(
!
(
xprt
=
xprt_create_proto
(
protocol
,
srvaddr
,
NULL
)))
return
NULL
;
xprt
=
xprt_create_proto
(
protocol
,
srvaddr
,
NULL
);
if
(
IS_ERR
(
xprt
))
return
(
struct
rpc_clnt
*
)
xprt
;
clnt
=
rpc_create_client
(
xprt
,
hostname
,
&
mnt_program
,
version
,
RPC_AUTH_
NULL
);
if
(
!
clnt
)
{
RPC_AUTH_
UNIX
);
if
(
IS_ERR
(
clnt
)
)
{
xprt_destroy
(
xprt
);
}
else
{
clnt
->
cl_softrtry
=
1
;
...
...
fs/nfs/nfs2xdr.c
View file @
aeb08fc0
...
...
@@ -36,33 +36,33 @@ extern int nfs_stat_to_errno(int stat);
* Declare the space requirements for NFS arguments and replies as
* number of 32bit-words
*/
#define NFS_fhandle_sz
8
#define NFS_sattr_sz
8
#define NFS_filename_sz
1+(NFS2_MAXNAMLEN>>2
)
#define NFS_path_sz
1+(NFS2_MAXPATHLEN>>2
)
#define NFS_fattr_sz
17
#define NFS_info_sz
5
#define NFS_entry_sz
NFS_filename_sz+3
#define NFS_diropargs_sz
NFS_fhandle_sz+NFS_filename_sz
#define NFS_sattrargs_sz
NFS_fhandle_sz+NFS_sattr_sz
#define NFS_readlinkargs_sz
NFS_fhandle_sz
#define NFS_readargs_sz
NFS_fhandle_sz+3
#define NFS_writeargs_sz
NFS_fhandle_sz+4
#define NFS_createargs_sz
NFS_diropargs_sz+NFS_sattr_sz
#define NFS_renameargs_sz
NFS_diropargs_sz+NFS_diropargs_sz
#define NFS_linkargs_sz
NFS_fhandle_sz+NFS_diropargs_sz
#define NFS_symlinkargs_sz
NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz
#define NFS_readdirargs_sz
NFS_fhandle_sz+2
#define NFS_attrstat_sz
1+NFS_fattr_sz
#define NFS_diropres_sz
1+NFS_fhandle_sz+NFS_fattr_sz
#define NFS_readlinkres_sz
1
#define NFS_readres_sz
1+NFS_fattr_sz+1
#define NFS_writeres_sz
NFS_attrstat_sz
#define NFS_stat_sz
1
#define NFS_readdirres_sz
1
#define NFS_statfsres_sz
1+NFS_info_sz
#define NFS_fhandle_sz
(8)
#define NFS_sattr_sz
(8)
#define NFS_filename_sz
(1+(NFS2_MAXNAMLEN>>2)
)
#define NFS_path_sz
(1+(NFS2_MAXPATHLEN>>2)
)
#define NFS_fattr_sz
(17)
#define NFS_info_sz
(5)
#define NFS_entry_sz
(NFS_filename_sz+3)
#define NFS_diropargs_sz
(NFS_fhandle_sz+NFS_filename_sz)
#define NFS_sattrargs_sz
(NFS_fhandle_sz+NFS_sattr_sz)
#define NFS_readlinkargs_sz
(NFS_fhandle_sz)
#define NFS_readargs_sz
(NFS_fhandle_sz+3)
#define NFS_writeargs_sz
(NFS_fhandle_sz+4)
#define NFS_createargs_sz
(NFS_diropargs_sz+NFS_sattr_sz)
#define NFS_renameargs_sz
(NFS_diropargs_sz+NFS_diropargs_sz)
#define NFS_linkargs_sz
(NFS_fhandle_sz+NFS_diropargs_sz)
#define NFS_symlinkargs_sz
(NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz)
#define NFS_readdirargs_sz
(NFS_fhandle_sz+2)
#define NFS_attrstat_sz
(1+NFS_fattr_sz)
#define NFS_diropres_sz
(1+NFS_fhandle_sz+NFS_fattr_sz)
#define NFS_readlinkres_sz
(1)
#define NFS_readres_sz
(1+NFS_fattr_sz+1)
#define NFS_writeres_sz
(NFS_attrstat_sz)
#define NFS_stat_sz
(1)
#define NFS_readdirres_sz
(1)
#define NFS_statfsres_sz
(1+NFS_info_sz)
/*
* Common NFS XDR functions as inlines
...
...
fs/nfs/nfs3proc.c
View file @
aeb08fc0
...
...
@@ -68,20 +68,6 @@ nfs3_async_handle_jukebox(struct rpc_task *task)
return
1
;
}
static
void
nfs3_write_refresh_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
{
if
(
fattr
->
valid
&
NFS_ATTR_FATTR
)
{
if
(
!
(
fattr
->
valid
&
NFS_ATTR_WCC
))
{
fattr
->
pre_size
=
NFS_CACHE_ISIZE
(
inode
);
fattr
->
pre_mtime
=
NFS_CACHE_MTIME
(
inode
);
fattr
->
pre_ctime
=
NFS_CACHE_CTIME
(
inode
);
fattr
->
valid
|=
NFS_ATTR_WCC
;
}
nfs_refresh_inode
(
inode
,
fattr
);
}
}
static
struct
rpc_cred
*
nfs_cred
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
...
...
@@ -99,14 +85,18 @@ nfs_cred(struct inode *inode, struct file *filp)
*/
static
int
nfs3_proc_get_root
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
struct
nfs_f
attr
*
fattr
)
struct
nfs_f
sinfo
*
info
)
{
int
status
;
dprintk
(
"NFS call getroot
\n
"
);
fattr
->
valid
=
0
;
status
=
rpc_call
(
server
->
client
,
NFS3PROC_GETATTR
,
fhandle
,
fattr
,
0
);
dprintk
(
"NFS reply getroot
\n
"
);
dprintk
(
"%s: call fsinfo
\n
"
,
__FUNCTION__
);
info
->
fattr
->
valid
=
0
;
status
=
rpc_call
(
server
->
client_sys
,
NFS3PROC_FSINFO
,
fhandle
,
info
,
0
);
dprintk
(
"%s: reply fsinfo %d
\n
"
,
__FUNCTION__
,
status
);
if
(
!
(
info
->
fattr
->
valid
&
NFS_ATTR_FATTR
))
{
status
=
rpc_call
(
server
->
client_sys
,
NFS3PROC_GETATTR
,
fhandle
,
info
->
fattr
,
0
);
dprintk
(
"%s: reply getattr %d
\n
"
,
__FUNCTION__
,
status
);
}
return
status
;
}
...
...
@@ -280,7 +270,7 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
msg
.
rpc_cred
=
nfs_cred
(
inode
,
filp
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
inode
),
&
msg
,
rpcflags
);
if
(
status
>=
0
)
nfs
3_write
_refresh_inode
(
inode
,
fattr
);
nfs_refresh_inode
(
inode
,
fattr
);
dprintk
(
"NFS reply write: %d
\n
"
,
status
);
return
status
<
0
?
status
:
wdata
->
res
.
count
;
}
...
...
@@ -303,7 +293,7 @@ nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
msg
.
rpc_cred
=
nfs_cred
(
inode
,
filp
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
inode
),
&
msg
,
0
);
if
(
status
>=
0
)
nfs
3_write
_refresh_inode
(
inode
,
fattr
);
nfs_refresh_inode
(
inode
,
fattr
);
dprintk
(
"NFS reply commit: %d
\n
"
,
status
);
return
status
;
}
...
...
@@ -777,12 +767,13 @@ nfs3_proc_read_setup(struct nfs_read_data *data, unsigned int count)
static
void
nfs3_write_done
(
struct
rpc_task
*
task
)
{
struct
nfs_write_data
*
data
=
(
struct
nfs_write_data
*
)
task
->
tk_calldata
;
struct
nfs_write_data
*
data
;
if
(
nfs3_async_handle_jukebox
(
task
))
return
;
data
=
(
struct
nfs_write_data
*
)
task
->
tk_calldata
;
if
(
task
->
tk_status
>=
0
)
nfs
3_write
_refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
nfs_refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
nfs_writeback_done
(
task
);
}
...
...
@@ -835,12 +826,13 @@ nfs3_proc_write_setup(struct nfs_write_data *data, unsigned int count, int how)
static
void
nfs3_commit_done
(
struct
rpc_task
*
task
)
{
struct
nfs_write_data
*
data
=
(
struct
nfs_write_data
*
)
task
->
tk_calldata
;
struct
nfs_write_data
*
data
;
if
(
nfs3_async_handle_jukebox
(
task
))
return
;
data
=
(
struct
nfs_write_data
*
)
task
->
tk_calldata
;
if
(
task
->
tk_status
>=
0
)
nfs
3_write
_refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
nfs_refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
nfs_commit_done
(
task
);
}
...
...
fs/nfs/nfs3xdr.c
View file @
aeb08fc0
...
...
@@ -33,51 +33,51 @@ extern int nfs_stat_to_errno(int);
* Declare the space requirements for NFS arguments and replies as
* number of 32bit-words
*/
#define NFS3_fhandle_sz
1+16
#define NFS3_fh_sz
NFS3_fhandle_sz
/* shorthand */
#define NFS3_sattr_sz
15
#define NFS3_filename_sz
1+(NFS3_MAXNAMLEN>>2
)
#define NFS3_path_sz
1+(NFS3_MAXPATHLEN>>2
)
#define NFS3_fattr_sz
21
#define NFS3_wcc_attr_sz
6
#define NFS3_pre_op_attr_sz
1+NFS3_wcc_attr_sz
#define NFS3_post_op_attr_sz
1+NFS3_fattr_sz
#define NFS3_wcc_data_sz
NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz
#define NFS3_fhandle_sz
(1+16)
#define NFS3_fh_sz
(NFS3_fhandle_sz)
/* shorthand */
#define NFS3_sattr_sz
(15)
#define NFS3_filename_sz
(1+(NFS3_MAXNAMLEN>>2)
)
#define NFS3_path_sz
(1+(NFS3_MAXPATHLEN>>2)
)
#define NFS3_fattr_sz
(21)
#define NFS3_wcc_attr_sz
(6)
#define NFS3_pre_op_attr_sz
(1+NFS3_wcc_attr_sz)
#define NFS3_post_op_attr_sz
(1+NFS3_fattr_sz)
#define NFS3_wcc_data_sz
(NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
#define NFS3_fsstat_sz
#define NFS3_fsinfo_sz
#define NFS3_pathconf_sz
#define NFS3_entry_sz
NFS3_filename_sz+3
#define NFS3_sattrargs_sz
NFS3_fh_sz+NFS3_sattr_sz+3
#define NFS3_diropargs_sz
NFS3_fh_sz+NFS3_filename_sz
#define NFS3_accessargs_sz
NFS3_fh_sz+1
#define NFS3_readlinkargs_sz
NFS3_fh_sz
#define NFS3_readargs_sz
NFS3_fh_sz+3
#define NFS3_writeargs_sz
NFS3_fh_sz+5
#define NFS3_createargs_sz
NFS3_diropargs_sz+NFS3_sattr_sz
#define NFS3_mkdirargs_sz
NFS3_diropargs_sz+NFS3_sattr_sz
#define NFS3_symlinkargs_sz
NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz
#define NFS3_mknodargs_sz
NFS3_diropargs_sz+2+NFS3_sattr_sz
#define NFS3_renameargs_sz
NFS3_diropargs_sz+NFS3_diropargs_sz
#define NFS3_linkargs_sz
NFS3_fh_sz+NFS3_diropargs_sz
#define NFS3_readdirargs_sz
NFS3_fh_sz+2
#define NFS3_commitargs_sz
NFS3_fh_sz+3
#define NFS3_attrstat_sz
1+NFS3_fattr_sz
#define NFS3_wccstat_sz
1+NFS3_wcc_data_sz
#define NFS3_lookupres_sz
1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz
)
#define NFS3_accessres_sz
1+NFS3_post_op_attr_sz+1
#define NFS3_readlinkres_sz
1+NFS3_post_op_attr_sz
#define NFS3_readres_sz
1+NFS3_post_op_attr_sz+3
#define NFS3_writeres_sz
1+NFS3_wcc_data_sz+4
#define NFS3_createres_sz
1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
#define NFS3_renameres_sz
1+(2 * NFS3_wcc_data_sz
)
#define NFS3_linkres_sz
1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
#define NFS3_readdirres_sz
1+NFS3_post_op_attr_sz+2
#define NFS3_fsstatres_sz
1+NFS3_post_op_attr_sz+13
#define NFS3_fsinfores_sz
1+NFS3_post_op_attr_sz+12
#define NFS3_pathconfres_sz
1+NFS3_post_op_attr_sz+6
#define NFS3_commitres_sz
1+NFS3_wcc_data_sz+2
#define NFS3_entry_sz
(NFS3_filename_sz+3)
#define NFS3_sattrargs_sz
(NFS3_fh_sz+NFS3_sattr_sz+3)
#define NFS3_diropargs_sz
(NFS3_fh_sz+NFS3_filename_sz)
#define NFS3_accessargs_sz
(NFS3_fh_sz+1)
#define NFS3_readlinkargs_sz
(NFS3_fh_sz)
#define NFS3_readargs_sz
(NFS3_fh_sz+3)
#define NFS3_writeargs_sz
(NFS3_fh_sz+5)
#define NFS3_createargs_sz
(NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_mkdirargs_sz
(NFS3_diropargs_sz+NFS3_sattr_sz)
#define NFS3_symlinkargs_sz
(NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz)
#define NFS3_mknodargs_sz
(NFS3_diropargs_sz+2+NFS3_sattr_sz)
#define NFS3_renameargs_sz
(NFS3_diropargs_sz+NFS3_diropargs_sz)
#define NFS3_linkargs_sz
(NFS3_fh_sz+NFS3_diropargs_sz)
#define NFS3_readdirargs_sz
(NFS3_fh_sz+2)
#define NFS3_commitargs_sz
(NFS3_fh_sz+3)
#define NFS3_attrstat_sz
(1+NFS3_fattr_sz)
#define NFS3_wccstat_sz
(1+NFS3_wcc_data_sz)
#define NFS3_lookupres_sz
(1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)
)
#define NFS3_accessres_sz
(1+NFS3_post_op_attr_sz+1)
#define NFS3_readlinkres_sz
(1+NFS3_post_op_attr_sz)
#define NFS3_readres_sz
(1+NFS3_post_op_attr_sz+3)
#define NFS3_writeres_sz
(1+NFS3_wcc_data_sz+4)
#define NFS3_createres_sz
(1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
#define NFS3_renameres_sz
(1+(2 * NFS3_wcc_data_sz)
)
#define NFS3_linkres_sz
(1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
#define NFS3_readdirres_sz
(1+NFS3_post_op_attr_sz+2)
#define NFS3_fsstatres_sz
(1+NFS3_post_op_attr_sz+13)
#define NFS3_fsinfores_sz
(1+NFS3_post_op_attr_sz+12)
#define NFS3_pathconfres_sz
(1+NFS3_post_op_attr_sz+6)
#define NFS3_commitres_sz
(1+NFS3_wcc_data_sz+2)
/*
* Map file type to S_IFMT bits
...
...
@@ -103,9 +103,7 @@ static struct {
static
inline
u32
*
xdr_encode_fhandle
(
u32
*
p
,
struct
nfs_fh
*
fh
)
{
*
p
++
=
htonl
(
fh
->
size
);
memcpy
(
p
,
fh
->
data
,
fh
->
size
);
return
p
+
XDR_QUADLEN
(
fh
->
size
);
return
xdr_encode_array
(
p
,
fh
->
data
,
fh
->
size
);
}
static
inline
u32
*
...
...
fs/nfs/nfs4proc.c
View file @
aeb08fc0
...
...
@@ -54,12 +54,24 @@
#define GET_OP(cp,name) &cp->ops[cp->req_nops].u.name
#define OPNUM(cp) cp->ops[cp->req_nops].opnum
static
int
nfs4_proc_fsinfo
(
struct
nfs_server
*
,
struct
nfs_fh
*
,
struct
nfs_fsinfo
*
);
static
int
nfs4_async_handle_error
(
struct
rpc_task
*
,
struct
nfs_server
*
);
extern
u32
*
nfs4_decode_dirent
(
u32
*
p
,
struct
nfs_entry
*
entry
,
int
plus
);
extern
struct
rpc_procinfo
nfs4_procedures
[];
extern
nfs4_stateid
zero_stateid
;
/* Prevent leaks of NFSv4 errors into userland */
static
inline
int
nfs4_map_errors
(
int
err
)
{
if
(
err
<
-
1000
)
{
printk
(
KERN_WARNING
"%s could not handle NFSv4 error %d
\n
"
,
__FUNCTION__
,
-
err
);
return
-
EIO
;
}
return
err
;
}
static
void
nfs4_setup_compound
(
struct
nfs4_compound
*
cp
,
struct
nfs4_op
*
ops
,
struct
nfs_server
*
server
,
char
*
tag
)
...
...
@@ -505,6 +517,8 @@ nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
nfs4_increment_seqid
(
status
,
sp
);
if
(
status
==
0
)
memcpy
(
&
state
->
stateid
,
&
o_res
.
stateid
,
sizeof
(
state
->
stateid
));
/* Update the inode attributes */
nfs_refresh_inode
(
inode
,
&
fattr
);
return
status
;
...
...
@@ -689,7 +703,7 @@ nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
retry:
fattr
->
valid
=
0
;
if
(
s
tate
)
if
(
s
attr
->
ia_valid
&
ATTR_SIZE
)
nfs4_copy_stateid
(
&
arg
.
stateid
,
state
,
0
);
else
memcpy
(
&
arg
.
stateid
,
&
zero_stateid
,
sizeof
(
arg
.
stateid
));
...
...
@@ -822,10 +836,11 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
static
int
nfs4_proc_get_root
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
struct
nfs_f
attr
*
fattr
)
struct
nfs_f
sinfo
*
info
)
{
struct
nfs4_compound
compound
;
struct
nfs4_op
ops
[
4
];
struct
nfs_fattr
*
fattr
=
info
->
fattr
;
unsigned
char
*
p
;
struct
qstr
q
;
int
status
;
...
...
@@ -869,7 +884,9 @@ nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
break
;
}
out:
return
status
;
if
(
status
)
return
nfs4_map_errors
(
status
);
return
nfs4_proc_fsinfo
(
server
,
fhandle
,
info
);
}
static
int
...
...
@@ -883,7 +900,7 @@ nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
nfs4_setup_compound
(
&
compound
,
ops
,
NFS_SERVER
(
inode
),
"getattr"
);
nfs4_setup_putfh
(
&
compound
,
NFS_FH
(
inode
));
nfs4_setup_getattr
(
&
compound
,
fattr
);
return
nfs4_
call_compound
(
&
compound
,
NULL
,
0
);
return
nfs4_
map_errors
(
nfs4_call_compound
(
&
compound
,
NULL
,
0
)
);
}
/*
...
...
@@ -969,7 +986,7 @@ nfs4_proc_lookup(struct inode *dir, struct qstr *name,
if
(
status
>=
0
)
status
=
nfs_refresh_inode
(
dir
,
&
dir_attr
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1016,7 +1033,7 @@ nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
else
if
(
req_access
!=
resp_access
)
status
=
-
EACCES
;
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
/*
...
...
@@ -1052,7 +1069,7 @@ nfs4_proc_readlink(struct inode *inode, struct page *page)
nfs4_setup_compound
(
&
compound
,
ops
,
NFS_SERVER
(
inode
),
"readlink"
);
nfs4_setup_putfh
(
&
compound
,
NFS_FH
(
inode
));
nfs4_setup_readlink
(
&
compound
,
PAGE_CACHE_SIZE
,
&
page
);
return
nfs4_
call_compound
(
&
compound
,
NULL
,
0
);
return
nfs4_
map_errors
(
nfs4_call_compound
(
&
compound
,
NULL
,
0
)
);
}
static
int
...
...
@@ -1088,14 +1105,10 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
fattr
->
valid
=
0
;
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
flags
);
if
(
!
status
)
{
if
(
!
status
)
renew_lease
(
server
,
timestamp
);
/* Check cache consistency */
if
(
fattr
->
change_attr
!=
NFS_CHANGE_ATTR
(
inode
))
nfs_zap_caches
(
inode
);
}
dprintk
(
"NFS reply read: %d
\n
"
,
status
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1130,9 +1143,8 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
fattr
->
valid
=
0
;
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
rpcflags
);
NFS_CACHEINV
(
inode
);
dprintk
(
"NFS reply write: %d
\n
"
,
status
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1167,7 +1179,7 @@ nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
fattr
->
valid
=
0
;
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
dprintk
(
"NFS reply commit: %d
\n
"
,
status
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
/*
...
...
@@ -1234,7 +1246,7 @@ nfs4_proc_remove(struct inode *dir, struct qstr *name)
process_cinfo
(
&
dir_cinfo
,
&
dir_attr
);
nfs_refresh_inode
(
dir
,
&
dir_attr
);
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
struct
unlink_desc
{
...
...
@@ -1312,7 +1324,7 @@ nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
nfs_refresh_inode
(
old_dir
,
&
old_dir_attr
);
nfs_refresh_inode
(
new_dir
,
&
new_dir_attr
);
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1342,7 +1354,7 @@ nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
nfs_refresh_inode
(
dir
,
&
dir_attr
);
nfs_refresh_inode
(
inode
,
&
fattr
);
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1373,7 +1385,7 @@ nfs4_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
process_cinfo
(
&
dir_cinfo
,
&
dir_attr
);
nfs_refresh_inode
(
dir
,
&
dir_attr
);
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1403,7 +1415,7 @@ nfs4_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
process_cinfo
(
&
dir_cinfo
,
&
dir_attr
);
nfs_refresh_inode
(
dir
,
&
dir_attr
);
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1421,9 +1433,11 @@ nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
nfs4_setup_putfh
(
&
compound
,
NFS_FH
(
dir
));
nfs4_setup_readdir
(
&
compound
,
cookie
,
NFS_COOKIEVERF
(
dir
),
&
page
,
count
,
dentry
);
status
=
nfs4_call_compound
(
&
compound
,
cred
,
0
);
if
(
status
==
0
)
memcpy
(
NFS_COOKIEVERF
(
dir
),
ops
[
1
].
u
.
readdir
.
rd_resp_verifier
.
data
,
NFS4_VERIFIER_SIZE
);
unlock_kernel
();
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1453,7 +1467,7 @@ nfs4_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
process_cinfo
(
&
dir_cinfo
,
&
dir_attr
);
nfs_refresh_inode
(
dir
,
&
dir_attr
);
}
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -1463,11 +1477,10 @@ nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
struct
nfs4_compound
compound
;
struct
nfs4_op
ops
[
2
];
memset
(
fsstat
,
0
,
sizeof
(
*
fsstat
));
nfs4_setup_compound
(
&
compound
,
ops
,
server
,
"statfs"
);
nfs4_setup_putfh
(
&
compound
,
fhandle
);
nfs4_setup_statfs
(
&
compound
,
fsstat
);
return
nfs4_
call_compound
(
&
compound
,
NULL
,
0
);
return
nfs4_
map_errors
(
nfs4_call_compound
(
&
compound
,
NULL
,
0
)
);
}
static
int
...
...
@@ -1480,8 +1493,7 @@ nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
.
rpc_resp
=
fsinfo
,
};
memset
(
fsinfo
,
0
,
sizeof
(
*
fsinfo
));
return
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
return
nfs4_map_errors
(
rpc_call_sync
(
server
->
client
,
&
msg
,
0
));
}
static
int
...
...
@@ -1491,11 +1503,10 @@ nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
struct
nfs4_compound
compound
;
struct
nfs4_op
ops
[
2
];
memset
(
pathconf
,
0
,
sizeof
(
*
pathconf
));
nfs4_setup_compound
(
&
compound
,
ops
,
server
,
"statfs"
);
nfs4_setup_putfh
(
&
compound
,
fhandle
);
nfs4_setup_pathconf
(
&
compound
,
pathconf
);
return
nfs4_
call_compound
(
&
compound
,
NULL
,
0
);
return
nfs4_
map_errors
(
nfs4_call_compound
(
&
compound
,
NULL
,
0
)
);
}
static
void
...
...
@@ -1517,7 +1528,6 @@ nfs4_read_done(struct rpc_task *task)
{
struct
nfs_read_data
*
data
=
(
struct
nfs_read_data
*
)
task
->
tk_calldata
;
struct
inode
*
inode
=
data
->
inode
;
struct
nfs_fattr
*
fattr
=
data
->
res
.
fattr
;
if
(
nfs4_async_handle_error
(
task
,
NFS_SERVER
(
inode
))
==
-
EAGAIN
)
{
task
->
tk_action
=
nfs4_restart_read
;
...
...
@@ -1525,11 +1535,6 @@ nfs4_read_done(struct rpc_task *task)
}
if
(
task
->
tk_status
>
0
)
renew_lease
(
NFS_SERVER
(
inode
),
data
->
timestamp
);
/* Check cache consistency */
if
(
fattr
->
change_attr
!=
NFS_CHANGE_ATTR
(
inode
))
nfs_zap_caches
(
inode
);
if
(
fattr
->
bitmap
[
1
]
&
FATTR4_WORD1_TIME_ACCESS
)
inode
->
i_atime
=
fattr
->
atime
;
/* Call back common NFS readpage processing */
nfs_readpage_result
(
task
);
}
...
...
@@ -1576,21 +1581,6 @@ nfs4_proc_read_setup(struct nfs_read_data *data, unsigned int count)
rpc_call_setup
(
task
,
&
msg
,
0
);
}
static
void
nfs4_write_refresh_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
{
/* Check cache consistency */
if
(
fattr
->
pre_change_attr
!=
NFS_CHANGE_ATTR
(
inode
))
nfs_zap_caches
(
inode
);
NFS_CHANGE_ATTR
(
inode
)
=
fattr
->
change_attr
;
if
(
fattr
->
bitmap
[
1
]
&
FATTR4_WORD1_SPACE_USED
)
inode
->
i_blocks
=
(
fattr
->
du
.
nfs3
.
used
+
511
)
>>
9
;
if
(
fattr
->
bitmap
[
1
]
&
FATTR4_WORD1_TIME_METADATA
)
inode
->
i_ctime
=
fattr
->
ctime
;
if
(
fattr
->
bitmap
[
1
]
&
FATTR4_WORD1_TIME_MODIFY
)
inode
->
i_mtime
=
fattr
->
mtime
;
}
static
void
nfs4_restart_write
(
struct
rpc_task
*
task
)
{
...
...
@@ -1617,7 +1607,6 @@ nfs4_write_done(struct rpc_task *task)
}
if
(
task
->
tk_status
>=
0
)
renew_lease
(
NFS_SERVER
(
inode
),
data
->
timestamp
);
nfs4_write_refresh_inode
(
inode
,
data
->
res
.
fattr
);
/* Call back common NFS writeback processing */
nfs_writeback_done
(
task
);
}
...
...
@@ -1684,7 +1673,6 @@ nfs4_commit_done(struct rpc_task *task)
task
->
tk_action
=
nfs4_restart_write
;
return
;
}
nfs4_write_refresh_inode
(
inode
,
data
->
res
.
fattr
);
/* Call back common NFS writeback processing */
nfs_commit_done
(
task
);
}
...
...
@@ -1807,6 +1795,7 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
if
(
filp
->
f_mode
&
FMODE_WRITE
)
{
lock_kernel
();
nfs_set_mmcred
(
inode
,
state
->
owner
->
so_cred
);
nfs_begin_data_update
(
inode
);
unlock_kernel
();
}
filp
->
private_data
=
state
;
...
...
@@ -1823,6 +1812,11 @@ nfs4_proc_file_release(struct inode *inode, struct file *filp)
if
(
state
)
nfs4_close_state
(
state
,
filp
->
f_mode
);
if
(
filp
->
f_mode
&
FMODE_WRITE
)
{
lock_kernel
();
nfs_end_data_update
(
inode
);
unlock_kernel
();
}
return
0
;
}
...
...
@@ -1850,7 +1844,7 @@ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
{
struct
nfs4_client
*
clp
=
server
->
nfs4_state
;
if
(
!
clp
)
if
(
!
clp
||
task
->
tk_status
>=
0
)
return
0
;
switch
(
task
->
tk_status
)
{
case
-
NFS4ERR_STALE_CLIENTID
:
...
...
@@ -1869,6 +1863,7 @@ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
task
->
tk_status
=
0
;
return
-
EAGAIN
;
}
task
->
tk_status
=
nfs4_map_errors
(
task
->
tk_status
);
return
0
;
}
...
...
@@ -1946,16 +1941,9 @@ nfs4_handle_error(struct nfs_server *server, int errorcode)
break
;
case
-
NFS4ERR_OLD_STATEID
:
ret
=
0
;
break
;
default:
if
(
errorcode
<=
-
1000
)
{
printk
(
KERN_WARNING
"%s could not handle NFSv4 error %d
\n
"
,
__FUNCTION__
,
-
errorcode
);
ret
=
-
EIO
;
}
}
/* We failed to handle the error */
return
ret
;
return
nfs4_map_errors
(
ret
)
;
}
...
...
@@ -2130,7 +2118,7 @@ nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
if
(
lsp
)
nfs4_put_lock_state
(
lsp
);
up
(
&
state
->
lock_sema
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
int
...
...
@@ -2175,7 +2163,7 @@ nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
nfs4_put_lock_state
(
lsp
);
out:
up
(
&
state
->
lock_sema
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
@@ -2251,7 +2239,7 @@ nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
nfs4_put_lock_state
(
lsp
);
out:
up
(
&
state
->
lock_sema
);
return
status
;
return
nfs4_map_errors
(
status
)
;
}
static
int
...
...
fs/nfs/nfs4state.c
View file @
aeb08fc0
...
...
@@ -411,18 +411,20 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
return
state
;
}
void
nfs4_put_open_state
(
struct
nfs4_state
*
state
)
static
void
__
nfs4_put_open_state
(
struct
nfs4_state
*
state
)
{
struct
inode
*
inode
=
state
->
inode
;
struct
nfs4_state_owner
*
owner
=
state
->
owner
;
int
status
=
0
;
if
(
!
atomic_dec_and_lock
(
&
state
->
count
,
&
inode
->
i_lock
))
if
(
!
atomic_dec_and_lock
(
&
state
->
count
,
&
inode
->
i_lock
))
{
up
(
&
owner
->
so_sema
);
return
;
}
if
(
!
list_empty
(
&
state
->
inode_states
))
list_del
(
&
state
->
inode_states
);
spin_unlock
(
&
inode
->
i_lock
);
down
(
&
owner
->
so_sema
);
list_del
(
&
state
->
open_states
);
if
(
state
->
state
!=
0
)
{
do
{
...
...
@@ -439,6 +441,13 @@ nfs4_put_open_state(struct nfs4_state *state)
nfs4_put_state_owner
(
owner
);
}
void
nfs4_put_open_state
(
struct
nfs4_state
*
state
)
{
down
(
&
state
->
owner
->
so_sema
);
__nfs4_put_open_state
(
state
);
}
void
nfs4_close_state
(
struct
nfs4_state
*
state
,
mode_t
mode
)
{
...
...
@@ -479,8 +488,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
status
=
nfs4_handle_error
(
NFS_SERVER
(
inode
),
status
);
down
(
&
owner
->
so_sema
);
}
while
(
!
status
);
up
(
&
owner
->
so_sema
);
nfs4_put_open_state
(
state
);
__nfs4_put_open_state
(
state
);
}
/*
...
...
@@ -790,7 +798,7 @@ reclaimer(void *ptr)
restart_loop:
spin_lock
(
&
clp
->
cl_lock
);
list_for_each_entry
(
sp
,
&
clp
->
cl_state_owners
,
so_list
)
{
if
(
sp
->
so_generation
-
generation
<
=
0
)
if
(
sp
->
so_generation
-
generation
>
=
0
)
continue
;
atomic_inc
(
&
sp
->
so_count
);
spin_unlock
(
&
clp
->
cl_lock
);
...
...
fs/nfs/nfs4xdr.c
View file @
aeb08fc0
...
...
@@ -69,84 +69,84 @@ static int nfs_stat_to_errno(int);
/* lock,open owner id:
* we currently use size 1 (u32) out of (NFS4_OPAQUE_LIMIT >> 2)
*/
#define owner_id_maxsz
1 + 1
#define compound_encode_hdr_maxsz
3 + (NFS4_MAXTAGLEN >> 2
)
#define compound_decode_hdr_maxsz
2 + (NFS4_MAXTAGLEN >> 2
)
#define op_encode_hdr_maxsz
1
#define op_decode_hdr_maxsz
2
#define encode_putfh_maxsz op_encode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2)
#define decode_putfh_maxsz
op_decode_hdr_maxsz
#define encode_putrootfh_maxsz
op_encode_hdr_maxsz
#define decode_putrootfh_maxsz
op_decode_hdr_maxsz
#define encode_getfh_maxsz
op_encode_hdr_maxsz
#define decode_getfh_maxsz op_decode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2)
#define encode_getattr_maxsz
op_encode_hdr_maxsz + 3
#define nfs4_fattr_bitmap_maxsz
26 + 2 * ((NFS4_MAXNAMLEN +1) >> 2
)
#define decode_getattr_maxsz op_decode_hdr_maxsz + 3 + \
nfs4_fattr_bitmap_maxsz
#define encode_savefh_maxsz
op_encode_hdr_maxsz
#define decode_savefh_maxsz
op_decode_hdr_maxsz
#define encode_restorefh_maxsz
op_encode_hdr_maxsz
#define decode_restorefh_maxsz
op_decode_hdr_maxsz
#define encode_read_getattr_maxsz
op_encode_hdr_maxsz + 2
#define decode_read_getattr_maxsz
op_decode_hdr_maxsz + 8
#define encode_pre_write_getattr_maxsz
op_encode_hdr_maxsz + 2
#define decode_pre_write_getattr_maxsz
op_decode_hdr_maxsz + 5
#define encode_post_write_getattr_maxsz
op_encode_hdr_maxsz + 2
#define decode_post_write_getattr_maxsz
op_decode_hdr_maxsz + 13
#define encode_fsinfo_maxsz
op_encode_hdr_maxsz + 2
#define decode_fsinfo_maxsz
op_decode_hdr_maxsz + 11
#define encode_renew_maxsz
op_encode_hdr_maxsz + 3
#define decode_renew_maxsz
op_decode_hdr_maxsz
#define owner_id_maxsz
(1 + 1)
#define compound_encode_hdr_maxsz
(3 + (NFS4_MAXTAGLEN >> 2)
)
#define compound_decode_hdr_maxsz
(3 + (NFS4_MAXTAGLEN >> 2)
)
#define op_encode_hdr_maxsz
(1)
#define op_decode_hdr_maxsz
(2)
#define encode_putfh_maxsz
(
op_encode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2)
)
#define decode_putfh_maxsz
(op_decode_hdr_maxsz)
#define encode_putrootfh_maxsz
(op_encode_hdr_maxsz)
#define decode_putrootfh_maxsz
(op_decode_hdr_maxsz)
#define encode_getfh_maxsz
(op_encode_hdr_maxsz)
#define decode_getfh_maxsz
(
op_decode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2)
)
#define encode_getattr_maxsz
(op_encode_hdr_maxsz + 3)
#define nfs4_fattr_bitmap_maxsz
(26 + 2 * ((NFS4_MAXNAMLEN +1) >> 2)
)
#define decode_getattr_maxsz
(
op_decode_hdr_maxsz + 3 + \
nfs4_fattr_bitmap_maxsz
)
#define encode_savefh_maxsz
(op_encode_hdr_maxsz)
#define decode_savefh_maxsz
(op_decode_hdr_maxsz)
#define encode_restorefh_maxsz
(op_encode_hdr_maxsz)
#define decode_restorefh_maxsz
(op_decode_hdr_maxsz)
#define encode_read_getattr_maxsz
(op_encode_hdr_maxsz + 2)
#define decode_read_getattr_maxsz
(op_decode_hdr_maxsz + 8)
#define encode_pre_write_getattr_maxsz
(op_encode_hdr_maxsz + 2)
#define decode_pre_write_getattr_maxsz
(op_decode_hdr_maxsz + 5)
#define encode_post_write_getattr_maxsz
(op_encode_hdr_maxsz + 2)
#define decode_post_write_getattr_maxsz
(op_decode_hdr_maxsz + 13)
#define encode_fsinfo_maxsz
(op_encode_hdr_maxsz + 2)
#define decode_fsinfo_maxsz
(op_decode_hdr_maxsz + 11)
#define encode_renew_maxsz
(op_encode_hdr_maxsz + 3)
#define decode_renew_maxsz
(op_decode_hdr_maxsz)
#define encode_setclientid_maxsz \
op_encode_hdr_maxsz + \
(
op_encode_hdr_maxsz + \
4
/*server->ip_addr*/
+ \
1
/*Netid*/
+ \
6
/*uaddr*/
+ \
6 + (NFS4_VERIFIER_SIZE >> 2)
6 + (NFS4_VERIFIER_SIZE >> 2)
)
#define decode_setclientid_maxsz \
op_decode_hdr_maxsz + \
(
op_decode_hdr_maxsz + \
2 + \
1024
/* large value for CLID_INUSE */
1024
)
/* large value for CLID_INUSE */
#define encode_setclientid_confirm_maxsz \
op_encode_hdr_maxsz + \
3 + (NFS4_VERIFIER_SIZE >> 2)
(
op_encode_hdr_maxsz + \
3 + (NFS4_VERIFIER_SIZE >> 2)
)
#define decode_setclientid_confirm_maxsz \
op_decode_hdr_maxsz
(op_decode_hdr_maxsz)
#define NFS4_enc_compound_sz
1024
/* XXX: large enough? */
#define NFS4_dec_compound_sz
1024
/* XXX: large enough? */
#define NFS4_enc_read_sz compound_encode_hdr_maxsz + \
#define NFS4_enc_compound_sz
(1024)
/* XXX: large enough? */
#define NFS4_dec_compound_sz
(1024)
/* XXX: large enough? */
#define NFS4_enc_read_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_read_getattr_maxsz + \
op_encode_hdr_maxsz + 7
#define NFS4_dec_read_sz compound_decode_hdr_maxsz + \
op_encode_hdr_maxsz + 7
)
#define NFS4_dec_read_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_read_getattr_maxsz + \
op_decode_hdr_maxsz + 2
#define NFS4_enc_write_sz compound_encode_hdr_maxsz + \
op_decode_hdr_maxsz + 2
)
#define NFS4_enc_write_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_pre_write_getattr_maxsz + \
op_encode_hdr_maxsz + 8 + \
encode_post_write_getattr_maxsz
#define NFS4_dec_write_sz compound_decode_hdr_maxsz + \
encode_post_write_getattr_maxsz
)
#define NFS4_dec_write_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_pre_write_getattr_maxsz + \
op_decode_hdr_maxsz + 4 + \
decode_post_write_getattr_maxsz
#define NFS4_enc_commit_sz compound_encode_hdr_maxsz + \
decode_post_write_getattr_maxsz
)
#define NFS4_enc_commit_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_pre_write_getattr_maxsz + \
op_encode_hdr_maxsz + 3 + \
encode_post_write_getattr_maxsz
#define NFS4_dec_commit_sz compound_decode_hdr_maxsz + \
encode_post_write_getattr_maxsz
)
#define NFS4_dec_commit_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_pre_write_getattr_maxsz + \
op_decode_hdr_maxsz + 2 + \
decode_post_write_getattr_maxsz
#define NFS4_enc_open_sz compound_encode_hdr_maxsz + \
decode_post_write_getattr_maxsz
)
#define NFS4_enc_open_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
op_encode_hdr_maxsz + \
...
...
@@ -154,107 +154,107 @@ static int nfs_stat_to_errno(int);
encode_getattr_maxsz + \
encode_getfh_maxsz + \
encode_restorefh_maxsz + \
encode_getattr_maxsz
#define NFS4_dec_open_sz compound_decode_hdr_maxsz + \
encode_getattr_maxsz
)
#define NFS4_dec_open_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
op_decode_hdr_maxsz + 4 + 5 + 2 + 3 + \
decode_getattr_maxsz + \
decode_getfh_maxsz + \
decode_restorefh_maxsz + \
decode_getattr_maxsz
decode_getattr_maxsz
)
#define NFS4_enc_open_confirm_sz \
compound_encode_hdr_maxsz + \
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 5
#define NFS4_dec_open_confirm_sz compound_decode_hdr_maxsz + \
op_encode_hdr_maxsz + 5
)
#define NFS4_dec_open_confirm_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 4
#define NFS4_enc_open_reclaim_sz compound_encode_hdr_maxsz + \
op_decode_hdr_maxsz + 4
)
#define NFS4_enc_open_reclaim_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + \
11 + \
encode_getattr_maxsz
#define NFS4_dec_open_reclaim_sz compound_decode_hdr_maxsz + \
encode_getattr_maxsz
)
#define NFS4_dec_open_reclaim_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + \
4 + 5 + 2 + 3 + \
decode_getattr_maxsz
decode_getattr_maxsz
)
#define NFS4_enc_open_downgrade_sz \
compound_encode_hdr_maxsz + \
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 7
op_encode_hdr_maxsz + 7
)
#define NFS4_dec_open_downgrade_sz \
compound_decode_hdr_maxsz + \
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 4
#define NFS4_enc_close_sz compound_encode_hdr_maxsz + \
op_decode_hdr_maxsz + 4
)
#define NFS4_enc_close_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 5
#define NFS4_dec_close_sz compound_decode_hdr_maxsz + \
op_encode_hdr_maxsz + 5
)
#define NFS4_dec_close_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 4
#define NFS4_enc_setattr_sz compound_encode_hdr_maxsz + \
op_decode_hdr_maxsz + 4
)
#define NFS4_enc_setattr_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 4 + \
nfs4_fattr_bitmap_maxsz + \
encode_getattr_maxsz
#define NFS4_dec_setattr_sz compound_decode_hdr_maxsz + \
encode_getattr_maxsz
)
#define NFS4_dec_setattr_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 3
#define NFS4_enc_fsinfo_sz compound_encode_hdr_maxsz + \
op_decode_hdr_maxsz + 3
)
#define NFS4_enc_fsinfo_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_fsinfo_maxsz
#define NFS4_dec_fsinfo_sz compound_decode_hdr_maxsz + \
encode_fsinfo_maxsz
)
#define NFS4_dec_fsinfo_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_fsinfo_maxsz
#define NFS4_enc_renew_sz compound_encode_hdr_maxsz + \
encode_renew_maxsz
#define NFS4_dec_renew_sz compound_decode_hdr_maxsz + \
decode_renew_maxsz
#define NFS4_enc_setclientid_sz compound_encode_hdr_maxsz + \
encode_setclientid_maxsz
#define NFS4_dec_setclientid_sz compound_decode_hdr_maxsz + \
decode_setclientid_maxsz
decode_fsinfo_maxsz
)
#define NFS4_enc_renew_sz
(
compound_encode_hdr_maxsz + \
encode_renew_maxsz
)
#define NFS4_dec_renew_sz
(
compound_decode_hdr_maxsz + \
decode_renew_maxsz
)
#define NFS4_enc_setclientid_sz
(
compound_encode_hdr_maxsz + \
encode_setclientid_maxsz
)
#define NFS4_dec_setclientid_sz
(
compound_decode_hdr_maxsz + \
decode_setclientid_maxsz
)
#define NFS4_enc_setclientid_confirm_sz \
compound_encode_hdr_maxsz + \
(
compound_encode_hdr_maxsz + \
encode_setclientid_confirm_maxsz + \
encode_putrootfh_maxsz + \
encode_fsinfo_maxsz
encode_fsinfo_maxsz
)
#define NFS4_dec_setclientid_confirm_sz \
compound_decode_hdr_maxsz + \
(
compound_decode_hdr_maxsz + \
decode_setclientid_confirm_maxsz + \
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz
#define NFS4_enc_lock_sz compound_encode_hdr_maxsz + \
decode_fsinfo_maxsz
)
#define NFS4_enc_lock_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 1 + 2 + 2 + \
1 + 4 + 1 + 2 + \
owner_id_maxsz
#define NFS4_dec_lock_sz compound_decode_hdr_maxsz + \
owner_id_maxsz
)
#define NFS4_dec_lock_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz + \
op_decode_hdr_maxsz + \
2 + 2 + 1 + 2 + \
owner_id_maxsz
#define NFS4_enc_lockt_sz compound_encode_hdr_maxsz + \
owner_id_maxsz
)
#define NFS4_enc_lockt_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 2 + 2 + 2 + \
owner_id_maxsz
#define NFS4_dec_lockt_sz
NFS4_dec_lock_sz
#define NFS4_enc_locku_sz compound_encode_hdr_maxsz + \
owner_id_maxsz
)
#define NFS4_dec_lockt_sz
(NFS4_dec_lock_sz)
#define NFS4_enc_locku_sz
(
compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 1 + 4 + 2 + 2
#define NFS4_dec_locku_sz compound_decode_hdr_maxsz + \
1 + 1 + 4 + 2 + 2
)
#define NFS4_dec_locku_sz
(
compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz + \
op_decode_hdr_maxsz + 4
op_decode_hdr_maxsz + 4
)
...
...
@@ -324,7 +324,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
dprintk
(
"encode_compound: tag=%.*s
\n
"
,
(
int
)
hdr
->
taglen
,
hdr
->
tag
);
BUG_ON
(
hdr
->
taglen
>
NFS4_MAXTAGLEN
);
RESERVE_SPACE
(
12
+
XDR_QUADLEN
(
hdr
->
taglen
));
RESERVE_SPACE
(
12
+
(
XDR_QUADLEN
(
hdr
->
taglen
)
<<
2
));
WRITE32
(
hdr
->
taglen
);
WRITEMEM
(
hdr
->
tag
,
hdr
->
taglen
);
WRITE32
(
NFS4_MINOR_VERSION
);
...
...
@@ -3165,6 +3165,10 @@ static struct {
{
NFS4ERR_SYMLINK
,
ELOOP
},
{
NFS4ERR_OP_ILLEGAL
,
EOPNOTSUPP
},
{
NFS4ERR_DEADLOCK
,
EDEADLK
},
{
NFS4ERR_WRONGSEC
,
EPERM
},
/* FIXME: this needs
* to be handled by a
* middle-layer.
*/
{
-
1
,
EIO
}
};
...
...
@@ -3180,6 +3184,10 @@ nfs_stat_to_errno(int stat)
if
(
nfs_errtbl
[
i
].
stat
==
stat
)
return
nfs_errtbl
[
i
].
errno
;
}
if
(
stat
<
0
)
{
/* The server is looney tunes. */
return
ESERVERFAULT
;
}
/* If we cannot translate the error, the recovery routines should
* handle it.
* Note: remaining NFSv4 error codes have values > 10000, so should
...
...
fs/nfs/nfsroot.c
View file @
aeb08fc0
...
...
@@ -165,37 +165,6 @@ static struct nfs_bool_opts {
};
/*
* Extract IP address from the parameter string if needed. Note that we
* need to have root_server_addr set _before_ IPConfig gets called as it
* can override it.
*/
static
void
__init
root_nfs_parse_addr
(
char
*
name
)
{
int
octets
=
0
;
char
*
cp
,
*
cq
;
cp
=
cq
=
name
;
while
(
octets
<
4
)
{
while
(
*
cp
>=
'0'
&&
*
cp
<=
'9'
)
cp
++
;
if
(
cp
==
cq
||
cp
-
cq
>
3
)
break
;
if
(
*
cp
==
'.'
||
octets
==
3
)
octets
++
;
if
(
octets
<
4
)
cp
++
;
cq
=
cp
;
}
if
(
octets
==
4
&&
(
*
cp
==
':'
||
*
cp
==
'\0'
))
{
if
(
*
cp
==
':'
)
*
cp
++
=
'\0'
;
root_server_addr
=
in_aton
(
name
);
strcpy
(
name
,
cp
);
}
}
/*
* Parse option string.
*/
...
...
@@ -345,7 +314,7 @@ int __init nfs_root_setup(char *line)
line
[
sizeof
(
nfs_root_name
)
-
strlen
(
NFS_ROOT
)
-
1
]
=
'\0'
;
sprintf
(
nfs_root_name
,
NFS_ROOT
,
line
);
}
root_nfs_parse_addr
(
nfs_root_name
);
root_
server_addr
=
root_
nfs_parse_addr
(
nfs_root_name
);
return
1
;
}
...
...
fs/nfs/pagelist.c
View file @
aeb08fc0
...
...
@@ -246,7 +246,6 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
* nfs_scan_list - Scan a list for matching requests
* @head: One of the NFS inode request lists
* @dst: Destination list
* @file: if set, ensure we match requests from this file
* @idx_start: lower bound of page->index to scan
* @npages: idx_start + npages sets the upper bound to scan.
*
...
...
@@ -258,7 +257,6 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
*/
int
nfs_scan_list
(
struct
list_head
*
head
,
struct
list_head
*
dst
,
struct
file
*
file
,
unsigned
long
idx_start
,
unsigned
int
npages
)
{
struct
list_head
*
pos
,
*
tmp
;
...
...
@@ -276,9 +274,6 @@ nfs_scan_list(struct list_head *head, struct list_head *dst,
req
=
nfs_list_entry
(
pos
);
if
(
file
&&
req
->
wb_file
!=
file
)
continue
;
if
(
req
->
wb_index
<
idx_start
)
continue
;
if
(
req
->
wb_index
>
idx_end
)
...
...
fs/nfs/proc.c
View file @
aeb08fc0
...
...
@@ -49,18 +49,6 @@
extern
struct
rpc_procinfo
nfs_procedures
[];
static
void
nfs_write_refresh_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
{
if
(
!
(
fattr
->
valid
&
NFS_ATTR_WCC
))
{
fattr
->
pre_size
=
NFS_CACHE_ISIZE
(
inode
);
fattr
->
pre_mtime
=
NFS_CACHE_MTIME
(
inode
);
fattr
->
pre_ctime
=
NFS_CACHE_CTIME
(
inode
);
fattr
->
valid
|=
NFS_ATTR_WCC
;
}
nfs_refresh_inode
(
inode
,
fattr
);
}
static
struct
rpc_cred
*
nfs_cred
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
...
...
@@ -78,15 +66,33 @@ nfs_cred(struct inode *inode, struct file *filp)
*/
static
int
nfs_proc_get_root
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
struct
nfs_f
attr
*
fattr
)
struct
nfs_f
sinfo
*
info
)
{
struct
nfs_fattr
*
fattr
=
info
->
fattr
;
struct
nfs2_fsstat
fsinfo
;
int
status
;
dprintk
(
"
NFS call getroot
\n
"
);
dprintk
(
"
%s: call getattr
\n
"
,
__FUNCTION__
);
fattr
->
valid
=
0
;
status
=
rpc_call
(
server
->
client
,
NFSPROC_GETATTR
,
fhandle
,
fattr
,
0
);
dprintk
(
"NFS reply getroot
\n
"
);
status
=
rpc_call
(
server
->
client_sys
,
NFSPROC_GETATTR
,
fhandle
,
fattr
,
0
);
dprintk
(
"%s: reply getattr %d
\n
"
,
__FUNCTION__
,
status
);
if
(
status
)
return
status
;
dprintk
(
"%s: call statfs
\n
"
,
__FUNCTION__
);
status
=
rpc_call
(
server
->
client_sys
,
NFSPROC_STATFS
,
fhandle
,
&
fsinfo
,
0
);
dprintk
(
"%s: reply statfs %d
\n
"
,
__FUNCTION__
,
status
);
if
(
status
)
return
status
;
info
->
rtmax
=
NFS_MAXDATA
;
info
->
rtpref
=
fsinfo
.
tsize
;
info
->
rtmult
=
fsinfo
.
bsize
;
info
->
wtmax
=
NFS_MAXDATA
;
info
->
wtpref
=
fsinfo
.
tsize
;
info
->
wtmult
=
fsinfo
.
bsize
;
info
->
dtpref
=
fsinfo
.
tsize
;
info
->
maxfilesize
=
0x7FFFFFFF
;
info
->
lease_time
=
0
;
return
0
;
}
/*
...
...
@@ -180,8 +186,14 @@ nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
msg
.
rpc_cred
=
nfs_cred
(
inode
,
filp
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
inode
),
&
msg
,
flags
);
if
(
status
>=
0
)
if
(
status
>=
0
)
{
nfs_refresh_inode
(
inode
,
fattr
);
/* Emulate the eof flag, which isn't normally needed in NFSv2
* as it is guaranteed to always return the file attributes
*/
if
(
rdata
->
args
.
offset
+
rdata
->
args
.
count
>=
fattr
->
size
)
rdata
->
res
.
eof
=
1
;
}
dprintk
(
"NFS reply read: %d
\n
"
,
status
);
return
status
;
}
...
...
@@ -205,7 +217,7 @@ nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
msg
.
rpc_cred
=
nfs_cred
(
inode
,
filp
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
inode
),
&
msg
,
flags
);
if
(
status
>=
0
)
{
nfs_
write_
refresh_inode
(
inode
,
fattr
);
nfs_refresh_inode
(
inode
,
fattr
);
wdata
->
res
.
count
=
wdata
->
args
.
count
;
wdata
->
verf
.
committed
=
NFS_FILE_SYNC
;
}
...
...
@@ -331,10 +343,8 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
{
struct
rpc_message
*
msg
=
&
task
->
tk_msg
;
if
(
msg
->
rpc_argp
)
{
NFS_CACHEINV
(
dir
->
d_inode
);
if
(
msg
->
rpc_argp
)
kfree
(
msg
->
rpc_argp
);
}
return
0
;
}
...
...
@@ -537,8 +547,14 @@ nfs_read_done(struct rpc_task *task)
{
struct
nfs_read_data
*
data
=
(
struct
nfs_read_data
*
)
task
->
tk_calldata
;
if
(
task
->
tk_status
>=
0
)
if
(
task
->
tk_status
>=
0
)
{
nfs_refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
/* Emulate the eof flag, which isn't normally needed in NFSv2
* as it is guaranteed to always return the file attributes
*/
if
(
data
->
args
.
offset
+
data
->
args
.
count
>=
data
->
res
.
fattr
->
size
)
data
->
res
.
eof
=
1
;
}
nfs_readpage_result
(
task
);
}
...
...
@@ -584,7 +600,7 @@ nfs_write_done(struct rpc_task *task)
struct
nfs_write_data
*
data
=
(
struct
nfs_write_data
*
)
task
->
tk_calldata
;
if
(
task
->
tk_status
>=
0
)
nfs_
write_
refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
nfs_refresh_inode
(
data
->
inode
,
data
->
res
.
fattr
);
nfs_writeback_done
(
task
);
}
...
...
fs/nfs/read.c
View file @
aeb08fc0
...
...
@@ -121,9 +121,13 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
}
count
-=
result
;
rdata
.
args
.
pgbase
+=
result
;
if
(
result
<
rdata
.
args
.
count
)
/* NFSv2ism */
/* Note: result == 0 should only happen if we're caching
* a write that extends the file and punches a hole.
*/
if
(
rdata
.
res
.
eof
!=
0
||
result
==
0
)
break
;
}
while
(
count
);
NFS_FLAGS
(
inode
)
|=
NFS_INO_INVALID_ATIME
;
if
(
count
)
memclear_highpage_flush
(
page
,
rdata
.
args
.
pgbase
,
count
);
...
...
@@ -266,6 +270,7 @@ nfs_readpage_result(struct rpc_task *task)
dprintk
(
"NFS: %4d nfs_readpage_result, (status %d)
\n
"
,
task
->
tk_pid
,
task
->
tk_status
);
NFS_FLAGS
(
data
->
inode
)
|=
NFS_INO_INVALID_ATIME
;
while
(
!
list_empty
(
&
data
->
pages
))
{
struct
nfs_page
*
req
=
nfs_list_entry
(
data
->
pages
.
next
);
struct
page
*
page
=
req
->
wb_page
;
...
...
fs/nfs/unlink.c
View file @
aeb08fc0
...
...
@@ -104,6 +104,7 @@ nfs_async_unlink_init(struct rpc_task *task)
status
=
NFS_PROTO
(
dir
->
d_inode
)
->
unlink_setup
(
&
msg
,
dir
,
&
data
->
name
);
if
(
status
<
0
)
goto
out_err
;
nfs_begin_data_update
(
dir
->
d_inode
);
rpc_call_setup
(
task
,
&
msg
,
0
);
return
;
out_err:
...
...
@@ -126,7 +127,7 @@ nfs_async_unlink_done(struct rpc_task *task)
if
(
!
dir
)
return
;
dir_i
=
dir
->
d_inode
;
nfs_
zap_caches
(
dir_i
);
nfs_
end_data_update
(
dir_i
);
if
(
NFS_PROTO
(
dir_i
)
->
unlink_done
(
dir
,
task
))
return
;
put_rpccred
(
data
->
cred
);
...
...
fs/nfs/write.c
View file @
aeb08fc0
...
...
@@ -74,7 +74,6 @@
static
struct
nfs_page
*
nfs_update_request
(
struct
file
*
,
struct
inode
*
,
struct
page
*
,
unsigned
int
,
unsigned
int
);
static
void
nfs_strategy
(
struct
inode
*
inode
);
static
kmem_cache_t
*
nfs_wdata_cachep
;
static
mempool_t
*
nfs_wdata_mempool
;
...
...
@@ -124,6 +123,52 @@ void nfs_commit_release(struct rpc_task *task)
nfs_commit_free
(
wdata
);
}
/* Adjust the file length if we're writing beyond the end */
static
void
nfs_grow_file
(
struct
page
*
page
,
unsigned
int
offset
,
unsigned
int
count
)
{
struct
inode
*
inode
=
page
->
mapping
->
host
;
loff_t
end
,
i_size
=
i_size_read
(
inode
);
unsigned
long
end_index
=
(
i_size
-
1
)
>>
PAGE_CACHE_SHIFT
;
if
(
i_size
>
0
&&
page
->
index
<
end_index
)
return
;
end
=
((
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
((
loff_t
)
offset
+
count
);
if
(
i_size
>=
end
)
return
;
i_size_write
(
inode
,
end
);
}
/* We can set the PG_uptodate flag if we see that a write request
* covers the full page.
*/
static
void
nfs_mark_uptodate
(
struct
page
*
page
,
unsigned
int
base
,
unsigned
int
count
)
{
loff_t
end_offs
;
if
(
PageUptodate
(
page
))
return
;
if
(
base
!=
0
)
return
;
if
(
count
==
PAGE_CACHE_SIZE
)
{
SetPageUptodate
(
page
);
return
;
}
end_offs
=
i_size_read
(
page
->
mapping
->
host
)
-
1
;
if
(
end_offs
<
0
)
return
;
/* Is this the last page? */
if
(
page
->
index
!=
(
unsigned
long
)(
end_offs
>>
PAGE_CACHE_SHIFT
))
return
;
/* This is the last page: set PG_uptodate if we cover the entire
* extent of the data, then zero the rest of the page.
*/
if
(
count
==
(
unsigned
int
)(
end_offs
&
(
PAGE_CACHE_SIZE
-
1
))
+
1
)
{
memclear_highpage_flush
(
page
,
count
,
PAGE_CACHE_SIZE
-
count
);
SetPageUptodate
(
page
);
}
}
/*
* Write a page synchronously.
* Offset is the data offset within the page.
...
...
@@ -157,6 +202,7 @@ nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
(
long
long
)
NFS_FILEID
(
inode
),
count
,
(
long
long
)(
page_offset
(
page
)
+
offset
));
nfs_begin_data_update
(
inode
);
do
{
if
(
count
<
wsize
&&
!
swapfile
)
wdata
.
args
.
count
=
count
;
...
...
@@ -177,43 +223,38 @@ nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
wdata
.
args
.
pgbase
+=
result
;
written
+=
result
;
count
-=
result
;
/*
* If we've extended the file, update the inode
* now so we don't invalidate the cache.
*/
if
(
wdata
.
args
.
offset
>
i_size_read
(
inode
))
i_size_write
(
inode
,
wdata
.
args
.
offset
);
}
while
(
count
);
/* Update file length */
nfs_grow_file
(
page
,
offset
,
written
);
/* Set the PG_uptodate flag? */
nfs_mark_uptodate
(
page
,
offset
,
written
);
if
(
PageError
(
page
))
ClearPageError
(
page
);
io_error:
nfs_end_data_update
(
inode
);
if
(
wdata
.
cred
)
put_rpccred
(
wdata
.
cred
);
return
written
?
written
:
result
;
}
static
int
nfs_writepage_async
(
struct
file
*
file
,
struct
inode
*
inode
,
struct
page
*
page
,
unsigned
int
offset
,
unsigned
int
count
)
static
int
nfs_writepage_async
(
struct
file
*
file
,
struct
inode
*
inode
,
struct
page
*
page
,
unsigned
int
offset
,
unsigned
int
count
)
{
struct
nfs_page
*
req
;
loff_t
end
;
int
status
;
req
=
nfs_update_request
(
file
,
inode
,
page
,
offset
,
count
);
status
=
(
IS_ERR
(
req
))
?
PTR_ERR
(
req
)
:
0
;
if
(
status
<
0
)
goto
out
;
/* Update file length */
nfs_grow_file
(
page
,
offset
,
count
);
/* Set the PG_uptodate flag? */
nfs_mark_uptodate
(
page
,
offset
,
count
);
nfs_unlock_request
(
req
);
nfs_strategy
(
inode
);
end
=
((
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
(
loff_t
)(
offset
+
count
);
if
(
i_size_read
(
inode
)
<
end
)
i_size_write
(
inode
,
end
);
out:
return
status
;
}
...
...
@@ -286,7 +327,7 @@ nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
err
=
generic_writepages
(
mapping
,
wbc
);
if
(
err
)
goto
out
;
err
=
nfs_flush_
file
(
inode
,
NULL
,
0
,
0
,
0
);
err
=
nfs_flush_
inode
(
inode
,
0
,
0
,
0
);
if
(
err
<
0
)
goto
out
;
if
(
wbc
->
sync_mode
==
WB_SYNC_HOLD
)
...
...
@@ -294,7 +335,7 @@ nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
if
(
is_sync
&&
wbc
->
sync_mode
==
WB_SYNC_ALL
)
{
err
=
nfs_wb_all
(
inode
);
}
else
nfs_commit_
file
(
inode
,
NULL
,
0
,
0
,
0
);
nfs_commit_
inode
(
inode
,
0
,
0
,
0
);
out:
return
err
;
}
...
...
@@ -312,8 +353,10 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
BUG_ON
(
error
==
-
EEXIST
);
if
(
error
)
return
error
;
if
(
!
nfsi
->
npages
)
if
(
!
nfsi
->
npages
)
{
igrab
(
inode
);
nfs_begin_data_update
(
inode
);
}
nfsi
->
npages
++
;
req
->
wb_count
++
;
return
0
;
...
...
@@ -336,6 +379,7 @@ nfs_inode_remove_request(struct nfs_page *req)
nfsi
->
npages
--
;
if
(
!
nfsi
->
npages
)
{
spin_unlock
(
&
nfs_wreq_lock
);
nfs_end_data_update
(
inode
);
iput
(
inode
);
}
else
spin_unlock
(
&
nfs_wreq_lock
);
...
...
@@ -421,7 +465,7 @@ nfs_mark_request_commit(struct nfs_page *req)
* Interruptible by signals only if mounted with intr flag.
*/
static
int
nfs_wait_on_requests
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
long
idx_start
,
unsigned
int
npages
)
nfs_wait_on_requests
(
struct
inode
*
inode
,
unsigned
long
idx_start
,
unsigned
int
npages
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
struct
nfs_page
*
req
;
...
...
@@ -441,8 +485,6 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
break
;
next
=
req
->
wb_index
+
1
;
if
(
file
&&
req
->
wb_file
!=
file
)
continue
;
if
(
!
NFS_WBACK_BUSY
(
req
))
continue
;
...
...
@@ -453,7 +495,6 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
if
(
error
<
0
)
return
error
;
spin_lock
(
&
nfs_wreq_lock
);
next
=
idx_start
;
res
++
;
}
spin_unlock
(
&
nfs_wreq_lock
);
...
...
@@ -464,7 +505,6 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
* nfs_scan_dirty - Scan an inode for dirty requests
* @inode: NFS inode to scan
* @dst: destination list
* @file: if set, ensure we match requests from this file
* @idx_start: lower bound of page->index to scan.
* @npages: idx_start + npages sets the upper bound to scan.
*
...
...
@@ -472,11 +512,11 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
* The requests are *not* checked to ensure that they form a contiguous set.
*/
static
int
nfs_scan_dirty
(
struct
inode
*
inode
,
struct
list_head
*
dst
,
struct
file
*
file
,
unsigned
long
idx_start
,
unsigned
int
npages
)
nfs_scan_dirty
(
struct
inode
*
inode
,
struct
list_head
*
dst
,
unsigned
long
idx_start
,
unsigned
int
npages
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
int
res
;
res
=
nfs_scan_list
(
&
nfsi
->
dirty
,
dst
,
file
,
idx_start
,
npages
);
res
=
nfs_scan_list
(
&
nfsi
->
dirty
,
dst
,
idx_start
,
npages
);
nfsi
->
ndirty
-=
res
;
sub_page_state
(
nr_dirty
,
res
);
if
((
nfsi
->
ndirty
==
0
)
!=
list_empty
(
&
nfsi
->
dirty
))
...
...
@@ -489,7 +529,6 @@ nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, un
* nfs_scan_commit - Scan an inode for commit requests
* @inode: NFS inode to scan
* @dst: destination list
* @file: if set, ensure we collect requests from this file only.
* @idx_start: lower bound of page->index to scan.
* @npages: idx_start + npages sets the upper bound to scan.
*
...
...
@@ -497,11 +536,11 @@ nfs_scan_dirty(struct inode *inode, struct list_head *dst, struct file *file, un
* The requests are *not* checked to ensure that they form a contiguous set.
*/
static
int
nfs_scan_commit
(
struct
inode
*
inode
,
struct
list_head
*
dst
,
struct
file
*
file
,
unsigned
long
idx_start
,
unsigned
int
npages
)
nfs_scan_commit
(
struct
inode
*
inode
,
struct
list_head
*
dst
,
unsigned
long
idx_start
,
unsigned
int
npages
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
int
res
;
res
=
nfs_scan_list
(
&
nfsi
->
commit
,
dst
,
file
,
idx_start
,
npages
);
res
=
nfs_scan_list
(
&
nfsi
->
commit
,
dst
,
idx_start
,
npages
);
nfsi
->
ncommit
-=
res
;
if
((
nfsi
->
ncommit
==
0
)
!=
list_empty
(
&
nfsi
->
commit
))
printk
(
KERN_ERR
"NFS: desynchronized value of nfs_i.ncommit.
\n
"
);
...
...
@@ -600,46 +639,6 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
return
req
;
}
/*
* This is the strategy routine for NFS.
* It is called by nfs_updatepage whenever the user wrote up to the end
* of a page.
*
* We always try to submit a set of requests in parallel so that the
* server's write code can gather writes. This is mainly for the benefit
* of NFSv2.
*
* We never submit more requests than we think the remote can handle.
* For UDP sockets, we make sure we don't exceed the congestion window;
* for TCP, we limit the number of requests to 8.
*
* NFS_STRATEGY_PAGES gives the minimum number of requests for NFSv2 that
* should be sent out in one go. This is for the benefit of NFSv2 servers
* that perform write gathering.
*
* FIXME: Different servers may have different sweet spots.
* Record the average congestion window in server struct?
*/
#define NFS_STRATEGY_PAGES 8
static
void
nfs_strategy
(
struct
inode
*
inode
)
{
unsigned
int
dirty
,
wpages
;
dirty
=
NFS_I
(
inode
)
->
ndirty
;
wpages
=
NFS_SERVER
(
inode
)
->
wpages
;
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if
(
NFS_PROTO
(
inode
)
->
version
==
2
)
{
if
(
dirty
>=
NFS_STRATEGY_PAGES
*
wpages
)
nfs_flush_file
(
inode
,
NULL
,
0
,
0
,
0
);
}
else
if
(
dirty
>=
wpages
)
nfs_flush_file
(
inode
,
NULL
,
0
,
0
,
0
);
#else
if
(
dirty
>=
NFS_STRATEGY_PAGES
*
wpages
)
nfs_flush_file
(
inode
,
NULL
,
0
,
0
,
0
);
#endif
}
int
nfs_flush_incompatible
(
struct
file
*
file
,
struct
page
*
page
)
{
...
...
@@ -675,7 +674,6 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
inode
*
inode
=
page
->
mapping
->
host
;
struct
nfs_page
*
req
;
loff_t
end
;
int
status
=
0
;
dprintk
(
"NFS: nfs_updatepage(%s/%s %d@%Ld)
\n
"
,
...
...
@@ -696,6 +694,27 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
return
status
;
}
/* If we're not using byte range locks, and we know the page
* is entirely in cache, it may be more efficient to avoid
* fragmenting write requests.
*/
if
(
PageUptodate
(
page
)
&&
inode
->
i_flock
==
NULL
)
{
loff_t
end_offs
=
i_size_read
(
inode
)
-
1
;
unsigned
long
end_index
=
end_offs
>>
PAGE_CACHE_SHIFT
;
count
+=
offset
;
offset
=
0
;
if
(
unlikely
(
end_offs
<
0
))
{
/* Do nothing */
}
else
if
(
page
->
index
==
end_index
)
{
unsigned
int
pglen
;
pglen
=
(
unsigned
int
)(
end_offs
&
(
PAGE_CACHE_SIZE
-
1
))
+
1
;
if
(
count
<
pglen
)
count
=
pglen
;
}
else
if
(
page
->
index
<
end_index
)
count
=
PAGE_CACHE_SIZE
;
}
/*
* Try to find an NFS request corresponding to this page
* and update it.
...
...
@@ -714,19 +733,11 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
goto
done
;
status
=
0
;
end
=
((
loff_t
)
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
(
loff_t
)(
offset
+
count
);
if
(
i_size_read
(
inode
)
<
end
)
i_size_write
(
inode
,
end
);
/* If we wrote past the end of the page.
* Call the strategy routine so it can send out a bunch
* of requests.
*/
if
(
req
->
wb_pgbase
==
0
&&
req
->
wb_bytes
==
PAGE_CACHE_SIZE
)
{
SetPageUptodate
(
page
);
nfs_unlock_request
(
req
);
nfs_strategy
(
inode
);
}
else
/* Update file length */
nfs_grow_file
(
page
,
offset
,
count
);
/* Set the PG_uptodate flag? */
nfs_mark_uptodate
(
page
,
req
->
wb_pgbase
,
req
->
wb_bytes
);
nfs_unlock_request
(
req
);
done:
dprintk
(
"NFS: nfs_updatepage returns %d (isize %Ld)
\n
"
,
...
...
@@ -891,10 +902,7 @@ nfs_writeback_done(struct rpc_task *task)
#endif
/*
* Update attributes as result of writeback.
* FIXME: There is an inherent race with invalidate_inode_pages and
* writebacks since the page->count is kept > 1 for as long
* as the page has a write request pending.
* Process the nfs_page list
*/
while
(
!
list_empty
(
&
data
->
pages
))
{
req
=
nfs_list_entry
(
data
->
pages
.
next
);
...
...
@@ -1061,7 +1069,7 @@ nfs_commit_done(struct rpc_task *task)
}
#endif
int
nfs_flush_
file
(
struct
inode
*
inode
,
struct
file
*
fil
e
,
unsigned
long
idx_start
,
int
nfs_flush_
inode
(
struct
inode
*
inod
e
,
unsigned
long
idx_start
,
unsigned
int
npages
,
int
how
)
{
LIST_HEAD
(
head
);
...
...
@@ -1069,7 +1077,7 @@ int nfs_flush_file(struct inode *inode, struct file *file, unsigned long idx_sta
error
=
0
;
spin_lock
(
&
nfs_wreq_lock
);
res
=
nfs_scan_dirty
(
inode
,
&
head
,
file
,
idx_start
,
npages
);
res
=
nfs_scan_dirty
(
inode
,
&
head
,
idx_start
,
npages
);
spin_unlock
(
&
nfs_wreq_lock
);
if
(
res
)
error
=
nfs_flush_list
(
&
head
,
NFS_SERVER
(
inode
)
->
wpages
,
how
);
...
...
@@ -1079,7 +1087,7 @@ int nfs_flush_file(struct inode *inode, struct file *file, unsigned long idx_sta
}
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
int
nfs_commit_
file
(
struct
inode
*
inode
,
struct
file
*
fil
e
,
unsigned
long
idx_start
,
int
nfs_commit_
inode
(
struct
inode
*
inod
e
,
unsigned
long
idx_start
,
unsigned
int
npages
,
int
how
)
{
LIST_HEAD
(
head
);
...
...
@@ -1087,9 +1095,9 @@ int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_st
error
=
0
;
spin_lock
(
&
nfs_wreq_lock
);
res
=
nfs_scan_commit
(
inode
,
&
head
,
file
,
idx_start
,
npages
);
res
=
nfs_scan_commit
(
inode
,
&
head
,
idx_start
,
npages
);
if
(
res
)
{
res
+=
nfs_scan_commit
(
inode
,
&
head
,
NULL
,
0
,
0
);
res
+=
nfs_scan_commit
(
inode
,
&
head
,
0
,
0
);
spin_unlock
(
&
nfs_wreq_lock
);
error
=
nfs_commit_list
(
&
head
,
how
);
}
else
...
...
@@ -1100,7 +1108,7 @@ int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_st
}
#endif
int
nfs_sync_
file
(
struct
inode
*
inode
,
struct
file
*
fil
e
,
unsigned
long
idx_start
,
int
nfs_sync_
inode
(
struct
inode
*
inod
e
,
unsigned
long
idx_start
,
unsigned
int
npages
,
int
how
)
{
int
error
,
...
...
@@ -1109,18 +1117,15 @@ int nfs_sync_file(struct inode *inode, struct file *file, unsigned long idx_star
wait
=
how
&
FLUSH_WAIT
;
how
&=
~
FLUSH_WAIT
;
if
(
!
inode
&&
file
)
inode
=
file
->
f_dentry
->
d_inode
;
do
{
error
=
0
;
if
(
wait
)
error
=
nfs_wait_on_requests
(
inode
,
file
,
idx_start
,
npages
);
error
=
nfs_wait_on_requests
(
inode
,
idx_start
,
npages
);
if
(
error
==
0
)
error
=
nfs_flush_
file
(
inode
,
fil
e
,
idx_start
,
npages
,
how
);
error
=
nfs_flush_
inode
(
inod
e
,
idx_start
,
npages
,
how
);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if
(
error
==
0
)
error
=
nfs_commit_
file
(
inode
,
fil
e
,
idx_start
,
npages
,
how
);
error
=
nfs_commit_
inode
(
inod
e
,
idx_start
,
npages
,
how
);
#endif
}
while
(
error
>
0
);
return
error
;
...
...
include/linux/fs.h
View file @
aeb08fc0
...
...
@@ -138,6 +138,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define S_DEAD 32
/* removed, but still open directory */
#define S_NOQUOTA 64
/* Inode is not counted to quota */
#define S_DIRSYNC 128
/* Directory modifications are synchronous */
#define S_NOCMTIME 256
/* Do not update file c/mtime */
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
...
...
@@ -171,6 +172,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#define IS_ONE_SECOND(inode) __IS_FLG(inode, MS_ONE_SECOND)
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
...
...
include/linux/lockd/debug.h
View file @
aeb08fc0
...
...
@@ -23,7 +23,7 @@
#undef ifdebug
#if defined(RPC_DEBUG) && defined(LOCKD_DEBUG)
# define ifdebug(flag) if (
nlm_debug & NLMDBG_##flag
)
# define ifdebug(flag) if (
unlikely(nlm_debug & NLMDBG_##flag)
)
#else
# define ifdebug(flag) if (0)
#endif
...
...
include/linux/lockd/lockd.h
View file @
aeb08fc0
...
...
@@ -165,6 +165,7 @@ u32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
unsigned
long
nlmsvc_retry_blocked
(
void
);
int
nlmsvc_traverse_blocks
(
struct
nlm_host
*
,
struct
nlm_file
*
,
int
action
);
void
nlmsvc_grant_reply
(
struct
svc_rqst
*
,
struct
nlm_cookie
*
,
u32
);
/*
* File handling for the server personality
...
...
include/linux/nfs_fs.h
View file @
aeb08fc0
...
...
@@ -99,7 +99,7 @@ struct nfs_inode {
/*
* Various flags
*/
unsigned
shor
t
flags
;
unsigned
in
t
flags
;
/*
* read_cache_jiffies is when we started read-caching this inode,
...
...
@@ -118,19 +118,22 @@ struct nfs_inode {
*
* mtime != read_cache_mtime
*/
unsigned
long
readdir_timestamp
;
unsigned
long
read_cache_jiffies
;
struct
timespec
read_cache_ctime
;
struct
timespec
read_cache_mtime
;
__u64
read_cache_isize
;
unsigned
long
attrtimeo
;
unsigned
long
attrtimeo_timestamp
;
__u64
change_attr
;
/* v4 only */
/* "Generation counter" for the attribute cache. This is
* bumped whenever we update the metadata on the
* server.
*/
unsigned
long
cache_change_attribute
;
/*
*
Timestamp that dates the change made to read_cache_mtime.
*
This is of use for dentry revalidation
*
Counter indicating the number of outstanding requests that
*
will cause a file data update.
*/
unsigned
long
cache_mtime_jiffi
es
;
atomic_t
data_updat
es
;
struct
nfs_access_cache
cache_access
;
...
...
@@ -170,8 +173,9 @@ struct nfs_inode {
#define NFS_INO_STALE 0x0001
/* possible stale inode */
#define NFS_INO_ADVISE_RDPLUS 0x0002
/* advise readdirplus */
#define NFS_INO_REVALIDATING 0x0004
/* revalidating attrs */
#define NFS_INO_FLUSH 0x0008
/* inode is due for flushing */
#define NFS_INO_FAKE_ROOT 0x0080
/* root inode placeholder */
#define NFS_INO_INVALID_ATTR 0x0008
/* cached attrs are invalid */
#define NFS_INO_INVALID_DATA 0x0010
/* cached data is invalid */
#define NFS_INO_INVALID_ATIME 0x0020
/* cached atime is invalid */
static
inline
struct
nfs_inode
*
NFS_I
(
struct
inode
*
inode
)
{
...
...
@@ -186,15 +190,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)
#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode)))
#define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf)
#define NFS_READTIME(inode) (NFS_I(inode)->read_cache_jiffies)
#define NFS_MTIME_UPDATE(inode) (NFS_I(inode)->cache_mtime_jiffies)
#define NFS_CACHE_CTIME(inode) (NFS_I(inode)->read_cache_ctime)
#define NFS_CACHE_MTIME(inode) (NFS_I(inode)->read_cache_mtime)
#define NFS_CACHE_ISIZE(inode) (NFS_I(inode)->read_cache_isize)
#define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr)
#define NFS_CACHEINV(inode) \
do { \
NFS_READTIME(inode) = jiffies - NFS_MAXATTRTIMEO(inode) - 1; \
} while (0)
#define NFS_ATTRTIMEO(inode) (NFS_I(inode)->attrtimeo)
#define NFS_MINATTRTIMEO(inode) \
(S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \
...
...
@@ -207,10 +203,20 @@ do { \
#define NFS_FLAGS(inode) (NFS_I(inode)->flags)
#define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
#define NFS_STALE(inode) (NFS_FLAGS(inode) & NFS_INO_STALE)
#define NFS_FAKE_ROOT(inode) (NFS_FLAGS(inode) & NFS_INO_FAKE_ROOT)
#define NFS_FILEID(inode) (NFS_I(inode)->fileid)
static
inline
int
nfs_caches_unstable
(
struct
inode
*
inode
)
{
return
atomic_read
(
&
NFS_I
(
inode
)
->
data_updates
)
!=
0
;
}
static
inline
void
NFS_CACHEINV
(
struct
inode
*
inode
)
{
if
(
!
nfs_caches_unstable
(
inode
))
NFS_FLAGS
(
inode
)
|=
NFS_INO_INVALID_ATTR
;
}
static
inline
int
nfs_server_capable
(
struct
inode
*
inode
,
int
cap
)
{
return
NFS_SERVER
(
inode
)
->
caps
&
cap
;
...
...
@@ -227,13 +233,37 @@ loff_t page_offset(struct page *page)
return
((
loff_t
)
page
->
index
)
<<
PAGE_CACHE_SHIFT
;
}
/**
* nfs_save_change_attribute - Returns the inode attribute change cookie
* @inode - pointer to inode
* The "change attribute" is updated every time we finish an operation
* that will result in a metadata change on the server.
*/
static
inline
long
nfs_save_change_attribute
(
struct
inode
*
inode
)
{
return
NFS_I
(
inode
)
->
cache_change_attribute
;
}
/**
* nfs_verify_change_attribute - Detects NFS inode cache updates
* @inode - pointer to inode
* @chattr - previously saved change attribute
* Return "false" if metadata has been updated (or is in the process of
* being updated) since the change attribute was saved.
*/
static
inline
int
nfs_verify_change_attribute
(
struct
inode
*
inode
,
unsigned
long
chattr
)
{
return
!
nfs_caches_unstable
(
inode
)
&&
chattr
==
NFS_I
(
inode
)
->
cache_change_attribute
;
}
/*
* linux/fs/nfs/inode.c
*/
extern
void
nfs_zap_caches
(
struct
inode
*
);
extern
struct
inode
*
nfs_fhget
(
struct
super_block
*
,
struct
nfs_fh
*
,
struct
nfs_fattr
*
);
extern
int
__
nfs_refresh_inode
(
struct
inode
*
,
struct
nfs_fattr
*
);
extern
int
nfs_refresh_inode
(
struct
inode
*
,
struct
nfs_fattr
*
);
extern
int
nfs_getattr
(
struct
vfsmount
*
,
struct
dentry
*
,
struct
kstat
*
);
extern
int
nfs_permission
(
struct
inode
*
,
int
,
struct
nameidata
*
);
extern
void
nfs_set_mmcred
(
struct
inode
*
,
struct
rpc_cred
*
);
...
...
@@ -241,6 +271,13 @@ extern int nfs_open(struct inode *, struct file *);
extern
int
nfs_release
(
struct
inode
*
,
struct
file
*
);
extern
int
__nfs_revalidate_inode
(
struct
nfs_server
*
,
struct
inode
*
);
extern
int
nfs_setattr
(
struct
dentry
*
,
struct
iattr
*
);
extern
void
nfs_begin_attr_update
(
struct
inode
*
);
extern
void
nfs_end_attr_update
(
struct
inode
*
);
extern
void
nfs_begin_data_update
(
struct
inode
*
);
extern
void
nfs_end_data_update
(
struct
inode
*
);
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern
u32
root_nfs_parse_addr
(
char
*
name
);
/*__init*/
/*
* linux/fs/nfs/file.c
...
...
@@ -309,16 +346,15 @@ extern void nfs_commit_done(struct rpc_task *);
* Try to write back everything synchronously (but check the
* return value!)
*/
extern
int
nfs_sync_
file
(
struct
inode
*
,
struct
fil
e
*
,
unsigned
long
,
unsigned
int
,
int
);
extern
int
nfs_flush_
file
(
struct
inode
*
,
struct
fil
e
*
,
unsigned
long
,
unsigned
int
,
int
);
extern
int
nfs_sync_
inode
(
struct
inod
e
*
,
unsigned
long
,
unsigned
int
,
int
);
extern
int
nfs_flush_
inode
(
struct
inod
e
*
,
unsigned
long
,
unsigned
int
,
int
);
extern
int
nfs_flush_list
(
struct
list_head
*
,
int
,
int
);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern
int
nfs_commit_
file
(
struct
inode
*
,
struct
fil
e
*
,
unsigned
long
,
unsigned
int
,
int
);
extern
int
nfs_commit_
inode
(
struct
inod
e
*
,
unsigned
long
,
unsigned
int
,
int
);
extern
int
nfs_commit_list
(
struct
list_head
*
,
int
);
#else
static
inline
int
nfs_commit_file
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
long
offset
,
unsigned
int
len
,
int
flags
)
nfs_commit_inode
(
struct
inode
*
inode
,
unsigned
long
idx_start
,
unsigned
int
npages
,
int
how
)
{
return
0
;
}
...
...
@@ -333,7 +369,7 @@ nfs_have_writebacks(struct inode *inode)
static
inline
int
nfs_wb_all
(
struct
inode
*
inode
)
{
int
error
=
nfs_sync_
file
(
inode
,
0
,
0
,
0
,
FLUSH_WAIT
);
int
error
=
nfs_sync_
inode
(
inode
,
0
,
0
,
FLUSH_WAIT
);
return
(
error
<
0
)
?
error
:
0
;
}
...
...
@@ -343,21 +379,11 @@ nfs_wb_all(struct inode *inode)
static
inline
int
nfs_wb_page
(
struct
inode
*
inode
,
struct
page
*
page
)
{
int
error
=
nfs_sync_
file
(
inode
,
0
,
page
->
index
,
1
,
int
error
=
nfs_sync_
inode
(
inode
,
page
->
index
,
1
,
FLUSH_WAIT
|
FLUSH_STABLE
);
return
(
error
<
0
)
?
error
:
0
;
}
/*
* Write back all pending writes for one user..
*/
static
inline
int
nfs_wb_file
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
error
=
nfs_sync_file
(
inode
,
file
,
0
,
0
,
FLUSH_WAIT
);
return
(
error
<
0
)
?
error
:
0
;
}
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
...
...
@@ -383,20 +409,27 @@ extern int nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
/*
* inline functions
*/
static
inline
int
nfs_revalidate_inode
(
struct
nfs_server
*
server
,
struct
inode
*
inode
)
static
inline
int
nfs_attribute_timeout
(
struct
inode
*
inode
)
{
if
(
time_before
(
jiffies
,
NFS_READTIME
(
inode
)
+
NFS_ATTRTIMEO
(
inode
)))
return
NFS_STALE
(
inode
)
?
-
ESTALE
:
0
;
return
__nfs_revalidate_inode
(
server
,
inode
);
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
return
time_after
(
jiffies
,
nfsi
->
read_cache_jiffies
+
nfsi
->
attrtimeo
);
}
static
inline
int
nfs_refresh_inode
(
struct
inode
*
inode
,
struct
nfs_fattr
*
fattr
)
/**
* nfs_revalidate_inode - Revalidate the inode attributes
* @server - pointer to nfs_server struct
* @inode - pointer to inode struct
*
* Updates inode attribute information by retrieving the data from the server.
*/
static
inline
int
nfs_revalidate_inode
(
struct
nfs_server
*
server
,
struct
inode
*
inode
)
{
if
((
fattr
->
valid
&
NFS_ATTR_FATTR
)
==
0
)
return
0
;
return
__nfs_refresh_inode
(
inode
,
fattr
);
if
(
!
(
NFS_FLAGS
(
inode
)
&
(
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_DATA
))
&&
!
nfs_attribute_timeout
(
inode
))
return
NFS_STALE
(
inode
)
?
-
ESTALE
:
0
;
return
__nfs_revalidate_inode
(
server
,
inode
);
}
static
inline
loff_t
...
...
@@ -661,7 +694,7 @@ struct nfs4_mount_data;
#ifdef __KERNEL__
# undef ifdebug
# ifdef NFS_DEBUG
# define ifdebug(fac) if (
nfs_debug & NFSDBG_##fac
)
# define ifdebug(fac) if (
unlikely(nfs_debug & NFSDBG_##fac)
)
# else
# define ifdebug(fac) if (0)
# endif
...
...
include/linux/nfs_page.h
View file @
aeb08fc0
...
...
@@ -53,7 +53,7 @@ extern void nfs_release_request(struct nfs_page *req);
extern
void
nfs_list_add_request
(
struct
nfs_page
*
,
struct
list_head
*
);
extern
int
nfs_scan_list
(
struct
list_head
*
,
struct
list_head
*
,
struct
file
*
,
unsigned
long
,
unsigned
int
);
unsigned
long
,
unsigned
int
);
extern
int
nfs_coalesce_requests
(
struct
list_head
*
,
struct
list_head
*
,
unsigned
int
);
extern
int
nfs_wait_on_request
(
struct
nfs_page
*
);
...
...
include/linux/nfs_xdr.h
View file @
aeb08fc0
...
...
@@ -700,7 +700,7 @@ struct nfs_rpc_ops {
struct
inode_operations
*
dir_inode_ops
;
int
(
*
getroot
)
(
struct
nfs_server
*
,
struct
nfs_fh
*
,
struct
nfs_f
attr
*
);
struct
nfs_f
sinfo
*
);
int
(
*
getattr
)
(
struct
inode
*
,
struct
nfs_fattr
*
);
int
(
*
setattr
)
(
struct
dentry
*
,
struct
nfs_fattr
*
,
struct
iattr
*
);
...
...
include/linux/sunrpc/debug.h
View file @
aeb08fc0
...
...
@@ -54,7 +54,7 @@ extern unsigned int nlm_debug;
#undef ifdebug
#ifdef RPC_DEBUG
# define ifdebug(fac) if (
rpc_debug & RPCDBG_##fac
)
# define ifdebug(fac) if (
unlikely(rpc_debug & RPCDBG_##fac)
)
# define dfprintk(fac, args...) do { ifdebug(fac) printk(args); } while(0)
# define RPC_IFDEBUG(x) x
#else
...
...
@@ -92,6 +92,8 @@ enum {
CTL_NFSDEBUG
,
CTL_NFSDDEBUG
,
CTL_NLMDEBUG
,
CTL_SLOTTABLE_UDP
,
CTL_SLOTTABLE_TCP
,
};
#endif
/* _LINUX_SUNRPC_DEBUG_H_ */
include/linux/sunrpc/timer.h
View file @
aeb08fc0
...
...
@@ -25,9 +25,18 @@ extern unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned timer);
static
inline
void
rpc_set_timeo
(
struct
rpc_rtt
*
rt
,
int
timer
,
int
ntimeo
)
{
int
*
t
;
if
(
!
timer
)
return
;
rt
->
ntimeouts
[
timer
-
1
]
=
ntimeo
;
t
=
&
rt
->
ntimeouts
[
timer
-
1
];
if
(
ntimeo
<
*
t
)
{
if
(
*
t
>
0
)
(
*
t
)
--
;
}
else
{
if
(
ntimeo
>
8
)
ntimeo
=
8
;
*
t
=
ntimeo
;
}
}
static
inline
int
rpc_ntimeo
(
struct
rpc_rtt
*
rt
,
int
timer
)
...
...
include/linux/sunrpc/xdr.h
View file @
aeb08fc0
...
...
@@ -87,7 +87,7 @@ struct xdr_buf {
/*
* Miscellaneous XDR helper functions
*/
u32
*
xdr_encode_array
(
u32
*
p
,
const
char
*
s
,
unsigned
int
len
);
u32
*
xdr_encode_array
(
u32
*
p
,
const
void
*
s
,
unsigned
int
len
);
u32
*
xdr_encode_string
(
u32
*
p
,
const
char
*
s
);
u32
*
xdr_decode_string
(
u32
*
p
,
char
**
sp
,
int
*
lenp
,
int
maxlen
);
u32
*
xdr_decode_string_inplace
(
u32
*
p
,
char
**
sp
,
int
*
lenp
,
int
maxlen
);
...
...
include/linux/sunrpc/xprt.h
View file @
aeb08fc0
...
...
@@ -28,16 +28,18 @@
*
* Upper procedures may check whether a request would block waiting for
* a free RPC slot by using the RPC_CONGESTED() macro.
*
* Note: on machines with low memory we should probably use a smaller
* MAXREQS value: At 32 outstanding reqs with 8 megs of RAM, fragment
* reassembly will frequently run out of memory.
*/
#define RPC_MAXCONG (16)
#define RPC_MAXREQS RPC_MAXCONG
#define RPC_CWNDSCALE (256)
#define RPC_MAXCWND (RPC_MAXCONG * RPC_CWNDSCALE)
*/
extern
unsigned
int
xprt_udp_slot_table_entries
;
extern
unsigned
int
xprt_tcp_slot_table_entries
;
#define RPC_MIN_SLOT_TABLE (2U)
#define RPC_DEF_SLOT_TABLE (16U)
#define RPC_MAX_SLOT_TABLE (128U)
#define RPC_CWNDSHIFT (8U)
#define RPC_CWNDSCALE (1U << RPC_CWNDSHIFT)
#define RPC_INITCWND RPC_CWNDSCALE
#define RPC_MAXCWND(xprt) ((xprt)->max_reqs << RPC_CWNDSHIFT)
#define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
/* Default timeout values */
...
...
@@ -92,7 +94,6 @@ struct rpc_rqst {
*/
struct
rpc_task
*
rq_task
;
/* RPC task data */
__u32
rq_xid
;
/* request XID */
struct
rpc_rqst
*
rq_next
;
/* free list */
int
rq_cong
;
/* has incremented xprt->cong */
int
rq_received
;
/* receive completed */
u32
rq_seqno
;
/* gss seq no. used on req. */
...
...
@@ -102,7 +103,6 @@ struct rpc_rqst {
struct
xdr_buf
rq_private_buf
;
/* The receive buffer
* used in the softirq.
*/
/*
* For authentication (e.g. auth_des)
*/
...
...
@@ -146,14 +146,20 @@ struct rpc_xprt {
struct
rpc_wait_queue
resend
;
/* requests waiting to resend */
struct
rpc_wait_queue
pending
;
/* requests in flight */
struct
rpc_wait_queue
backlog
;
/* waiting for slot */
struct
rpc_rqst
*
free
;
/* free slots */
struct
rpc_rqst
slot
[
RPC_MAXREQS
];
struct
list_head
free
;
/* free slots */
struct
rpc_rqst
*
slot
;
/* slot table storage */
unsigned
int
max_reqs
;
/* total slots */
unsigned
long
sockstate
;
/* Socket state */
unsigned
char
shutdown
:
1
,
/* being shut down */
nocong
:
1
,
/* no congestion control */
resvport
:
1
,
/* use a reserved port */
stream
:
1
;
/* TCP */
/*
* XID
*/
__u32
xid
;
/* Next XID value to use */
/*
* State of TCP reply receive stuff
*/
...
...
@@ -163,6 +169,11 @@ struct rpc_xprt {
tcp_offset
;
/* fragment offset */
unsigned
long
tcp_copied
,
/* copied to request */
tcp_flags
;
/*
* Connection of sockets
*/
struct
work_struct
sock_connect
;
unsigned
short
port
;
/*
* Disconnection of idle sockets
*/
...
...
net/ipv4/ipconfig.c
View file @
aeb08fc0
...
...
@@ -1188,6 +1188,40 @@ static struct file_operations pnp_seq_fops = {
};
#endif
/* CONFIG_PROC_FS */
/*
* Extract IP address from the parameter string if needed. Note that we
* need to have root_server_addr set _before_ IPConfig gets called as it
* can override it.
*/
u32
__init
root_nfs_parse_addr
(
char
*
name
)
{
u32
addr
;
int
octets
=
0
;
char
*
cp
,
*
cq
;
cp
=
cq
=
name
;
while
(
octets
<
4
)
{
while
(
*
cp
>=
'0'
&&
*
cp
<=
'9'
)
cp
++
;
if
(
cp
==
cq
||
cp
-
cq
>
3
)
break
;
if
(
*
cp
==
'.'
||
octets
==
3
)
octets
++
;
if
(
octets
<
4
)
cp
++
;
cq
=
cp
;
}
if
(
octets
==
4
&&
(
*
cp
==
':'
||
*
cp
==
'\0'
))
{
if
(
*
cp
==
':'
)
*
cp
++
=
'\0'
;
addr
=
in_aton
(
name
);
strcpy
(
name
,
cp
);
}
else
addr
=
INADDR_NONE
;
return
addr
;
}
/*
* IP Autoconfig dispatcher.
*/
...
...
@@ -1195,6 +1229,7 @@ static struct file_operations pnp_seq_fops = {
static
int
__init
ip_auto_config
(
void
)
{
unsigned
long
jiff
;
u32
addr
;
#ifdef CONFIG_PROC_FS
proc_net_fops_create
(
"pnp"
,
S_IRUGO
,
&
pnp_seq_fops
);
...
...
@@ -1283,6 +1318,10 @@ static int __init ip_auto_config(void)
ic_dev
=
ic_first_dev
->
dev
;
}
addr
=
root_nfs_parse_addr
(
root_server_path
);
if
(
root_server_addr
==
INADDR_NONE
)
root_server_addr
=
addr
;
/*
* Use defaults whereever applicable.
*/
...
...
net/sunrpc/auth_unix.c
View file @
aeb08fc0
...
...
@@ -149,7 +149,7 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
struct
rpc_clnt
*
clnt
=
task
->
tk_client
;
struct
unx_cred
*
cred
=
(
struct
unx_cred
*
)
task
->
tk_msg
.
rpc_cred
;
u32
*
base
,
*
hold
;
int
i
,
n
;
int
i
;
*
p
++
=
htonl
(
RPC_AUTH_UNIX
);
base
=
p
++
;
...
...
@@ -158,10 +158,7 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
/*
* Copy the UTS nodename captured when the client was created.
*/
n
=
clnt
->
cl_nodelen
;
*
p
++
=
htonl
(
n
);
memcpy
(
p
,
clnt
->
cl_nodename
,
n
);
p
+=
(
n
+
3
)
>>
2
;
p
=
xdr_encode_array
(
p
,
clnt
->
cl_nodename
,
clnt
->
cl_nodelen
);
/* Note: we don't use real uid if it involves raising privilege */
if
(
ruid
&&
cred
->
uc_puid
!=
0
&&
cred
->
uc_pgid
!=
0
)
{
...
...
net/sunrpc/clnt.c
View file @
aeb08fc0
...
...
@@ -102,19 +102,22 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
{
struct
rpc_version
*
version
;
struct
rpc_clnt
*
clnt
=
NULL
;
int
err
;
int
len
;
dprintk
(
"RPC: creating %s client for %s (xprt %p)
\n
"
,
program
->
name
,
servname
,
xprt
);
err
=
-
EINVAL
;
if
(
!
xprt
)
goto
out
;
goto
out
_err
;
if
(
vers
>=
program
->
nrvers
||
!
(
version
=
program
->
version
[
vers
]))
goto
out
;
goto
out
_err
;
err
=
-
ENOMEM
;
clnt
=
(
struct
rpc_clnt
*
)
kmalloc
(
sizeof
(
*
clnt
),
GFP_KERNEL
);
if
(
!
clnt
)
goto
out_
no_clnt
;
goto
out_
err
;
memset
(
clnt
,
0
,
sizeof
(
*
clnt
));
atomic_set
(
&
clnt
->
cl_users
,
0
);
atomic_set
(
&
clnt
->
cl_count
,
1
);
...
...
@@ -149,9 +152,11 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
clnt
->
cl_rtt
=
&
clnt
->
cl_rtt_default
;
rpc_init_rtt
(
&
clnt
->
cl_rtt_default
,
xprt
->
timeout
.
to_initval
);
if
(
rpc_setup_pipedir
(
clnt
,
program
->
pipe_dir_name
)
<
0
)
err
=
rpc_setup_pipedir
(
clnt
,
program
->
pipe_dir_name
);
if
(
err
<
0
)
goto
out_no_path
;
err
=
-
ENOMEM
;
if
(
!
rpcauth_create
(
flavor
,
clnt
))
{
printk
(
KERN_INFO
"RPC: Couldn't create auth handle (flavor %u)
\n
"
,
flavor
);
...
...
@@ -163,20 +168,16 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
if
(
clnt
->
cl_nodelen
>
UNX_MAXNODENAME
)
clnt
->
cl_nodelen
=
UNX_MAXNODENAME
;
memcpy
(
clnt
->
cl_nodename
,
system_utsname
.
nodename
,
clnt
->
cl_nodelen
);
out:
return
clnt
;
out_no_clnt:
printk
(
KERN_INFO
"RPC: out of memory in rpc_create_client
\n
"
);
goto
out
;
out_no_auth:
rpc_rmdir
(
clnt
->
cl_pathname
);
out_no_path:
if
(
clnt
->
cl_server
!=
clnt
->
cl_inline_name
)
kfree
(
clnt
->
cl_server
);
kfree
(
clnt
);
clnt
=
NULL
;
goto
out
;
out_err:
return
ERR_PTR
(
err
)
;
}
/*
...
...
@@ -198,11 +199,10 @@ rpc_clone_client(struct rpc_clnt *clnt)
atomic_inc
(
&
new
->
cl_parent
->
cl_count
);
if
(
new
->
cl_auth
)
atomic_inc
(
&
new
->
cl_auth
->
au_count
);
out:
return
new
;
out_no_clnt:
printk
(
KERN_INFO
"RPC: out of memory in %s
\n
"
,
__FUNCTION__
);
goto
out
;
return
ERR_PTR
(
-
ENOMEM
)
;
}
/*
...
...
@@ -611,9 +611,6 @@ call_encode(struct rpc_task *task)
rcvbuf
->
page_len
=
0
;
rcvbuf
->
len
=
bufsiz
;
/* Zero buffer so we have automatic zero-padding of opaque & string */
memset
(
task
->
tk_buffer
,
0
,
bufsiz
);
/* Encode header and provided arguments */
encode
=
task
->
tk_msg
.
rpc_proc
->
p_encode
;
if
(
!
(
p
=
call_header
(
task
)))
{
...
...
net/sunrpc/pmap_clnt.c
View file @
aeb08fc0
...
...
@@ -65,9 +65,11 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
map
->
pm_binding
=
1
;
spin_unlock
(
&
pmap_lock
);
task
->
tk_status
=
-
EACCES
;
/* why set this? returns -EIO below */
if
(
!
(
pmap_clnt
=
pmap_create
(
clnt
->
cl_server
,
sap
,
map
->
pm_prot
)))
pmap_clnt
=
pmap_create
(
clnt
->
cl_server
,
sap
,
map
->
pm_prot
);
if
(
IS_ERR
(
pmap_clnt
))
{
task
->
tk_status
=
PTR_ERR
(
pmap_clnt
);
goto
bailout
;
}
task
->
tk_status
=
0
;
/*
...
...
@@ -110,8 +112,9 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
NIPQUAD
(
sin
->
sin_addr
.
s_addr
),
prog
,
vers
,
prot
);
sprintf
(
hostname
,
"%u.%u.%u.%u"
,
NIPQUAD
(
sin
->
sin_addr
.
s_addr
));
if
(
!
(
pmap_clnt
=
pmap_create
(
hostname
,
sin
,
prot
)))
return
-
EACCES
;
pmap_clnt
=
pmap_create
(
hostname
,
sin
,
prot
);
if
(
IS_ERR
(
pmap_clnt
))
return
PTR_ERR
(
pmap_clnt
);
/* Setup the call info struct */
status
=
rpc_call
(
pmap_clnt
,
PMAP_GETPORT
,
&
map
,
&
map
.
pm_port
,
0
);
...
...
@@ -161,16 +164,18 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
struct
sockaddr_in
sin
;
struct
rpc_portmap
map
;
struct
rpc_clnt
*
pmap_clnt
;
unsigned
int
error
=
0
;
int
error
=
0
;
dprintk
(
"RPC: registering (%d, %d, %d, %d) with portmapper.
\n
"
,
prog
,
vers
,
prot
,
port
);
sin
.
sin_family
=
AF_INET
;
sin
.
sin_addr
.
s_addr
=
htonl
(
INADDR_LOOPBACK
);
if
(
!
(
pmap_clnt
=
pmap_create
(
"localhost"
,
&
sin
,
IPPROTO_UDP
)))
{
dprintk
(
"RPC: couldn't create pmap client
\n
"
);
return
-
EACCES
;
pmap_clnt
=
pmap_create
(
"localhost"
,
&
sin
,
IPPROTO_UDP
);
if
(
IS_ERR
(
pmap_clnt
))
{
error
=
PTR_ERR
(
pmap_clnt
);
dprintk
(
"RPC: couldn't create pmap client. Error = %d
\n
"
,
error
);
return
error
;
}
map
.
pm_prog
=
prog
;
...
...
@@ -199,15 +204,16 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
struct
rpc_clnt
*
clnt
;
/* printk("pmap: create xprt\n"); */
if
(
!
(
xprt
=
xprt_create_proto
(
proto
,
srvaddr
,
NULL
)))
return
NULL
;
xprt
=
xprt_create_proto
(
proto
,
srvaddr
,
NULL
);
if
(
IS_ERR
(
xprt
))
return
(
struct
rpc_clnt
*
)
xprt
;
xprt
->
addr
.
sin_port
=
htons
(
RPC_PMAP_PORT
);
/* printk("pmap: create clnt\n"); */
clnt
=
rpc_create_client
(
xprt
,
hostname
,
&
pmap_program
,
RPC_PMAP_VERSION
,
RPC_AUTH_NULL
);
if
(
!
clnt
)
{
if
(
IS_ERR
(
clnt
)
)
{
xprt_destroy
(
xprt
);
}
else
{
clnt
->
cl_softrtry
=
1
;
...
...
net/sunrpc/sched.c
View file @
aeb08fc0
...
...
@@ -530,6 +530,9 @@ __rpc_execute(struct rpc_task *task)
if
(
!
task
->
tk_action
)
break
;
task
->
tk_action
(
task
);
/* micro-optimization to avoid spinlock */
if
(
RPC_IS_RUNNING
(
task
))
continue
;
}
/*
...
...
@@ -545,29 +548,31 @@ __rpc_execute(struct rpc_task *task)
}
spin_unlock_bh
(
&
rpc_queue_lock
);
while
(
RPC_IS_SLEEPING
(
task
))
{
if
(
!
RPC_IS_SLEEPING
(
task
))
continue
;
/* sync task: sleep here */
dprintk
(
"RPC: %4d sync task going to sleep
\n
"
,
task
->
tk_pid
);
dprintk
(
"RPC: %4d sync task going to sleep
\n
"
,
task
->
tk_pid
);
if
(
current
->
pid
==
rpciod_pid
)
printk
(
KERN_ERR
"RPC: rpciod waiting on sync task!
\n
"
);
if
(
!
task
->
tk_client
->
cl_intr
)
{
__wait_event
(
task
->
tk_wait
,
!
RPC_IS_SLEEPING
(
task
));
dprintk
(
"RPC: %4d sync task resuming
\n
"
,
task
->
tk_pid
);
}
else
{
__wait_event_interruptible
(
task
->
tk_wait
,
!
RPC_IS_SLEEPING
(
task
),
status
);
/*
* When a sync task receives a signal, it exits with
* -ERESTARTSYS. In order to catch any callbacks that
* clean up after sleeping on some queue, we don't
* break the loop here, but go around once more.
*/
if
(
task
->
tk_client
->
cl_intr
&&
signalled
()
)
{
if
(
status
==
-
ERESTARTSYS
)
{
dprintk
(
"RPC: %4d got signal
\n
"
,
task
->
tk_pid
);
task
->
tk_flags
|=
RPC_TASK_KILLED
;
rpc_exit
(
task
,
-
ERESTARTSYS
);
rpc_wake_up_task
(
task
);
}
}
dprintk
(
"RPC: %4d sync task resuming
\n
"
,
task
->
tk_pid
);
}
if
(
task
->
tk_exit
)
{
...
...
net/sunrpc/sunrpc_syms.c
View file @
aeb08fc0
...
...
@@ -63,6 +63,8 @@ EXPORT_SYMBOL(rpc_mkpipe);
EXPORT_SYMBOL
(
xprt_create_proto
);
EXPORT_SYMBOL
(
xprt_destroy
);
EXPORT_SYMBOL
(
xprt_set_timeout
);
EXPORT_SYMBOL
(
xprt_udp_slot_table_entries
);
EXPORT_SYMBOL
(
xprt_tcp_slot_table_entries
);
/* Client credential cache */
EXPORT_SYMBOL
(
rpcauth_register
);
...
...
net/sunrpc/sysctl.c
View file @
aeb08fc0
/*
* linux/net/sunrpc/sysctl.c
*
* Sysctl interface to sunrpc module.
This is for debugging only now.
* Sysctl interface to sunrpc module.
*
* I would prefer to register the sunrpc table below sys/net, but that's
* impossible at the moment.
...
...
@@ -19,6 +19,7 @@
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/xprt.h>
/*
* Declare the debug flags here
...
...
@@ -117,6 +118,9 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
return
0
;
}
static
unsigned
int
min_slot_table_size
=
RPC_MIN_SLOT_TABLE
;
static
unsigned
int
max_slot_table_size
=
RPC_MAX_SLOT_TABLE
;
static
ctl_table
debug_table
[]
=
{
{
.
ctl_name
=
CTL_RPCDEBUG
,
...
...
@@ -150,6 +154,28 @@ static ctl_table debug_table[] = {
.
mode
=
0644
,
.
proc_handler
=
&
proc_dodebug
},
{
.
ctl_name
=
CTL_SLOTTABLE_UDP
,
.
procname
=
"udp_slot_table_entries"
,
.
data
=
&
xprt_udp_slot_table_entries
,
.
maxlen
=
sizeof
(
unsigned
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_slot_table_size
,
.
extra2
=
&
max_slot_table_size
},
{
.
ctl_name
=
CTL_SLOTTABLE_TCP
,
.
procname
=
"tcp_slot_table_entries"
,
.
data
=
&
xprt_tcp_slot_table_entries
,
.
maxlen
=
sizeof
(
unsigned
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_slot_table_size
,
.
extra2
=
&
max_slot_table_size
},
{
.
ctl_name
=
0
}
};
...
...
net/sunrpc/xdr.c
View file @
aeb08fc0
...
...
@@ -54,7 +54,7 @@ xdr_decode_netobj(u32 *p, struct xdr_netobj *obj)
}
u32
*
xdr_encode_array
(
u32
*
p
,
const
char
*
array
,
unsigned
int
len
)
xdr_encode_array
(
u32
*
p
,
const
void
*
array
,
unsigned
int
len
)
{
int
quadlen
=
XDR_QUADLEN
(
len
);
...
...
net/sunrpc/xprt.c
View file @
aeb08fc0
...
...
@@ -57,6 +57,7 @@
#include <linux/sunrpc/clnt.h>
#include <linux/file.h>
#include <linux/workqueue.h>
#include <linux/random.h>
#include <net/sock.h>
#include <net/checksum.h>
...
...
@@ -74,6 +75,7 @@
#define XPRT_MAX_BACKOFF (8)
#define XPRT_IDLE_TIMEOUT (5*60*HZ)
#define XPRT_MAX_RESVPORT (800)
/*
* Local functions
...
...
@@ -84,7 +86,7 @@ static void xprt_disconnect(struct rpc_xprt *);
static
void
xprt_connect_status
(
struct
rpc_task
*
task
);
static
struct
rpc_xprt
*
xprt_setup
(
int
proto
,
struct
sockaddr_in
*
ap
,
struct
rpc_timeout
*
to
);
static
struct
socket
*
xprt_create_socket
(
int
,
struct
rpc_timeout
*
,
int
);
static
struct
socket
*
xprt_create_socket
(
struct
rpc_xprt
*
,
int
,
int
);
static
void
xprt_bind_socket
(
struct
rpc_xprt
*
,
struct
socket
*
);
static
int
__xprt_get_cong
(
struct
rpc_xprt
*
,
struct
rpc_task
*
);
...
...
@@ -336,8 +338,8 @@ xprt_adjust_cwnd(struct rpc_xprt *xprt, int result)
/* The (cwnd >> 1) term makes sure
* the result gets rounded properly. */
cwnd
+=
(
RPC_CWNDSCALE
*
RPC_CWNDSCALE
+
(
cwnd
>>
1
))
/
cwnd
;
if
(
cwnd
>
RPC_MAXCWND
)
cwnd
=
RPC_MAXCWND
;
if
(
cwnd
>
RPC_MAXCWND
(
xprt
)
)
cwnd
=
RPC_MAXCWND
(
xprt
)
;
__xprt_lock_write_next
(
xprt
);
}
else
if
(
result
==
-
ETIMEDOUT
)
{
cwnd
>>=
1
;
...
...
@@ -452,110 +454,97 @@ xprt_init_autodisconnect(unsigned long data)
spin_unlock
(
&
xprt
->
sock_lock
);
}
/*
* Attempt to connect a TCP socket.
*
*/
void
xprt_connect
(
struct
rpc_task
*
task
)
static
void
xprt_socket_connect
(
void
*
args
)
{
struct
rpc_xprt
*
xprt
=
task
->
tk_xprt
;
struct
rpc_xprt
*
xprt
=
(
struct
rpc_xprt
*
)
args
;
struct
socket
*
sock
=
xprt
->
sock
;
struct
sock
*
inet
;
int
status
;
dprintk
(
"RPC: %4d xprt_connect xprt %p %s connected
\n
"
,
task
->
tk_pid
,
xprt
,
(
xprt_connected
(
xprt
)
?
"is"
:
"is not"
));
int
status
=
-
EIO
;
if
(
xprt
->
shutdown
)
{
task
->
tk_status
=
-
EIO
;
return
;
}
if
(
!
xprt
->
addr
.
sin_port
)
{
task
->
tk_status
=
-
EIO
;
rpc_wake_up_status
(
&
xprt
->
pending
,
-
EIO
);
return
;
}
if
(
!
xprt_lock_write
(
xprt
,
task
))
return
;
if
(
xprt_connected
(
xprt
))
goto
out_write
;
if
(
task
->
tk_rqstp
)
task
->
tk_rqstp
->
rq_bytes_sent
=
0
;
if
(
!
xprt
->
addr
.
sin_port
)
goto
out_err
;
/*
* We're here because the xprt was marked disconnected.
* Start by resetting any existing state.
* Start by resetting any existing state
*/
xprt_close
(
xprt
);
if
(
!
(
sock
=
xprt_create_socket
(
xprt
->
prot
,
&
xprt
->
timeout
,
xprt
->
resvport
)))
{
sock
=
xprt_create_socket
(
xprt
,
xprt
->
prot
,
xprt
->
resvport
);
if
(
sock
==
NULL
)
{
/* couldn't create socket or bind to reserved port;
* this is likely a permanent error, so cause an abort */
task
->
tk_status
=
-
EIO
;
goto
out_write
;
goto
out_err
;
return
;
}
xprt_bind_socket
(
xprt
,
sock
);
xprt_sock_setbufsize
(
xprt
);
if
(
!
xprt
->
stream
)
goto
out_write
;
inet
=
sock
->
sk
;
goto
out
;
/*
* Tell the socket layer to start connecting...
*/
status
=
sock
->
ops
->
connect
(
sock
,
(
struct
sockaddr
*
)
&
xprt
->
addr
,
sizeof
(
xprt
->
addr
),
O_NONBLOCK
);
dprintk
(
"RPC: %4d connect status %d connected %d sock state %d
\n
"
,
task
->
tk_pid
,
-
status
,
xprt_connected
(
xprt
),
inet
->
sk_state
);
dprintk
(
"RPC: %p connect status %d connected %d sock state %d
\n
"
,
xprt
,
-
status
,
xprt_connected
(
xprt
),
sock
->
sk
->
sk_state
);
if
(
status
>=
0
)
return
;
goto
out
;
switch
(
status
)
{
case
-
EINPROGRESS
:
case
-
EALREADY
:
/* Protect against TCP socket state changes */
lock_sock
(
inet
);
if
(
inet
->
sk_state
!=
TCP_ESTABLISHED
)
{
dprintk
(
"RPC: %4d waiting for connection
\n
"
,
task
->
tk_pid
);
task
->
tk_timeout
=
RPC_CONNECT_TIMEOUT
;
/* if the socket is already closing, delay briefly */
if
((
1
<<
inet
->
sk_state
)
&
~
(
TCPF_SYN_SENT
|
TCPF_SYN_RECV
))
task
->
tk_timeout
=
RPC_REESTABLISH_TIMEOUT
;
rpc_sleep_on
(
&
xprt
->
pending
,
task
,
xprt_connect_status
,
NULL
);
return
;
default:
goto
out_err
;
}
release_sock
(
inet
);
break
;
case
-
ECONNREFUSED
:
case
-
ECONNRESET
:
case
-
ENOTCONN
:
if
(
!
RPC_IS_SOFT
(
task
))
{
rpc_delay
(
task
,
RPC_REESTABLISH_TIMEOUT
);
task
->
tk_status
=
-
ENOTCONN
;
break
;
out:
spin_lock_bh
(
&
xprt
->
sock_lock
);
if
(
xprt
->
snd_task
)
rpc_wake_up_task
(
xprt
->
snd_task
);
spin_unlock_bh
(
&
xprt
->
sock_lock
);
return
;
out_err:
spin_lock_bh
(
&
xprt
->
sock_lock
);
if
(
xprt
->
snd_task
)
{
xprt
->
snd_task
->
tk_status
=
status
;
rpc_wake_up_task
(
xprt
->
snd_task
);
}
default:
/* Report myriad other possible returns. If this file
* system is soft mounted, just error out, like Solaris. */
if
(
RPC_IS_SOFT
(
task
))
{
printk
(
KERN_WARNING
"RPC: error %d connecting to server %s, exiting
\n
"
,
-
status
,
task
->
tk_client
->
cl_server
);
spin_unlock_bh
(
&
xprt
->
sock_lock
);
}
/*
* Attempt to connect a TCP socket.
*
*/
void
xprt_connect
(
struct
rpc_task
*
task
)
{
struct
rpc_xprt
*
xprt
=
task
->
tk_xprt
;
dprintk
(
"RPC: %4d xprt_connect xprt %p %s connected
\n
"
,
task
->
tk_pid
,
xprt
,
(
xprt_connected
(
xprt
)
?
"is"
:
"is not"
));
if
(
xprt
->
shutdown
)
{
task
->
tk_status
=
-
EIO
;
goto
out_write
;
return
;
}
printk
(
KERN_WARNING
"RPC: error %d connecting to server %s
\n
"
,
-
status
,
task
->
tk_client
->
cl_server
);
/* This will prevent anybody else from reconnecting */
rpc_delay
(
task
,
RPC_REESTABLISH_TIMEOUT
);
task
->
tk_status
=
status
;
break
;
if
(
!
xprt
->
addr
.
sin_port
)
{
task
->
tk_status
=
-
EIO
;
return
;
}
if
(
!
xprt_lock_write
(
xprt
,
task
))
return
;
if
(
xprt_connected
(
xprt
))
goto
out_write
;
if
(
task
->
tk_rqstp
)
task
->
tk_rqstp
->
rq_bytes_sent
=
0
;
task
->
tk_timeout
=
RPC_CONNECT_TIMEOUT
;
rpc_sleep_on
(
&
xprt
->
pending
,
task
,
xprt_connect_status
,
NULL
);
schedule_work
(
&
xprt
->
sock_connect
);
return
;
out_write:
xprt_release_write
(
xprt
,
task
);
...
...
@@ -580,6 +569,8 @@ xprt_connect_status(struct rpc_task *task)
task
->
tk_status
=
-
EIO
;
switch
(
task
->
tk_status
)
{
case
-
ECONNREFUSED
:
case
-
ECONNRESET
:
case
-
ENOTCONN
:
rpc_delay
(
task
,
RPC_REESTABLISH_TIMEOUT
);
return
;
...
...
@@ -1313,10 +1304,9 @@ do_xprt_reserve(struct rpc_task *task)
task
->
tk_status
=
0
;
if
(
task
->
tk_rqstp
)
return
;
if
(
xprt
->
free
)
{
struct
rpc_rqst
*
req
=
xprt
->
free
;
xprt
->
free
=
req
->
rq_next
;
req
->
rq_next
=
NULL
;
if
(
!
list_empty
(
&
xprt
->
free
))
{
struct
rpc_rqst
*
req
=
list_entry
(
xprt
->
free
.
next
,
struct
rpc_rqst
,
rq_list
);
list_del_init
(
&
req
->
rq_list
);
task
->
tk_rqstp
=
req
;
xprt_request_init
(
task
,
xprt
);
return
;
...
...
@@ -1330,22 +1320,14 @@ do_xprt_reserve(struct rpc_task *task)
/*
* Allocate a 'unique' XID
*/
static
u32
xprt_alloc_xid
(
void
)
static
inline
u32
xprt_alloc_xid
(
struct
rpc_xprt
*
xprt
)
{
return
xprt
->
xid
++
;
}
static
inline
void
xprt_init_xid
(
struct
rpc_xprt
*
xprt
)
{
static
spinlock_t
xid_lock
=
SPIN_LOCK_UNLOCKED
;
static
int
need_init
=
1
;
static
u32
xid
;
u32
ret
;
spin_lock
(
&
xid_lock
);
if
(
unlikely
(
need_init
))
{
xid
=
get_seconds
()
<<
12
;
need_init
=
0
;
}
ret
=
xid
++
;
spin_unlock
(
&
xid_lock
);
return
ret
;
get_random_bytes
(
&
xprt
->
xid
,
sizeof
(
xprt
->
xid
));
}
/*
...
...
@@ -1359,8 +1341,7 @@ xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
req
->
rq_timeout
=
xprt
->
timeout
;
req
->
rq_task
=
task
;
req
->
rq_xprt
=
xprt
;
req
->
rq_xid
=
xprt_alloc_xid
();
INIT_LIST_HEAD
(
&
req
->
rq_list
);
req
->
rq_xid
=
xprt_alloc_xid
(
xprt
);
dprintk
(
"RPC: %4d reserved req %p xid %08x
\n
"
,
task
->
tk_pid
,
req
,
req
->
rq_xid
);
}
...
...
@@ -1391,9 +1372,7 @@ xprt_release(struct rpc_task *task)
dprintk
(
"RPC: %4d release request %p
\n
"
,
task
->
tk_pid
,
req
);
spin_lock
(
&
xprt
->
xprt_lock
);
req
->
rq_next
=
xprt
->
free
;
xprt
->
free
=
req
;
list_add
(
&
req
->
rq_list
,
&
xprt
->
free
);
xprt_clear_backlog
(
xprt
);
spin_unlock
(
&
xprt
->
xprt_lock
);
}
...
...
@@ -1424,6 +1403,9 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
to
->
to_exponential
=
0
;
}
unsigned
int
xprt_udp_slot_table_entries
=
RPC_DEF_SLOT_TABLE
;
unsigned
int
xprt_tcp_slot_table_entries
=
RPC_DEF_SLOT_TABLE
;
/*
* Initialize an RPC client
*/
...
...
@@ -1431,21 +1413,33 @@ static struct rpc_xprt *
xprt_setup
(
int
proto
,
struct
sockaddr_in
*
ap
,
struct
rpc_timeout
*
to
)
{
struct
rpc_xprt
*
xprt
;
unsigned
int
entries
;
size_t
slot_table_size
;
struct
rpc_rqst
*
req
;
int
i
;
dprintk
(
"RPC: setting up %s transport...
\n
"
,
proto
==
IPPROTO_UDP
?
"UDP"
:
"TCP"
);
entries
=
(
proto
==
IPPROTO_TCP
)
?
xprt_tcp_slot_table_entries
:
xprt_udp_slot_table_entries
;
if
((
xprt
=
kmalloc
(
sizeof
(
struct
rpc_xprt
),
GFP_KERNEL
))
==
NULL
)
return
NULL
;
return
ERR_PTR
(
-
ENOMEM
)
;
memset
(
xprt
,
0
,
sizeof
(
*
xprt
));
/* Nnnngh! */
xprt
->
max_reqs
=
entries
;
slot_table_size
=
entries
*
sizeof
(
xprt
->
slot
[
0
]);
xprt
->
slot
=
kmalloc
(
slot_table_size
,
GFP_KERNEL
);
if
(
xprt
->
slot
==
NULL
)
{
kfree
(
xprt
);
return
ERR_PTR
(
-
ENOMEM
);
}
memset
(
xprt
->
slot
,
0
,
slot_table_size
);
xprt
->
addr
=
*
ap
;
xprt
->
prot
=
proto
;
xprt
->
stream
=
(
proto
==
IPPROTO_TCP
)
?
1
:
0
;
if
(
xprt
->
stream
)
{
xprt
->
cwnd
=
RPC_MAXCWND
;
xprt
->
cwnd
=
RPC_MAXCWND
(
xprt
)
;
xprt
->
nocong
=
1
;
}
else
xprt
->
cwnd
=
RPC_INITCWND
;
...
...
@@ -1453,12 +1447,15 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
spin_lock_init
(
&
xprt
->
xprt_lock
);
init_waitqueue_head
(
&
xprt
->
cong_wait
);
INIT_LIST_HEAD
(
&
xprt
->
free
);
INIT_LIST_HEAD
(
&
xprt
->
recv
);
INIT_WORK
(
&
xprt
->
sock_connect
,
xprt_socket_connect
,
xprt
);
INIT_WORK
(
&
xprt
->
task_cleanup
,
xprt_socket_autoclose
,
xprt
);
init_timer
(
&
xprt
->
timer
);
xprt
->
timer
.
function
=
xprt_init_autodisconnect
;
xprt
->
timer
.
data
=
(
unsigned
long
)
xprt
;
xprt
->
last_used
=
jiffies
;
xprt
->
port
=
XPRT_MAX_RESVPORT
;
/* Set timeout parameters */
if
(
to
)
{
...
...
@@ -1473,15 +1470,16 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
INIT_RPC_WAITQ
(
&
xprt
->
backlog
,
"xprt_backlog"
);
/* initialize free list */
for
(
i
=
0
,
req
=
xprt
->
slot
;
i
<
RPC_MAXREQS
-
1
;
i
++
,
req
++
)
req
->
rq_next
=
req
+
1
;
req
->
rq_next
=
NULL
;
xprt
->
free
=
xprt
->
slot
;
for
(
req
=
&
xprt
->
slot
[
entries
-
1
];
req
>=
&
xprt
->
slot
[
0
];
req
--
)
list_add
(
&
req
->
rq_list
,
&
xprt
->
free
)
;
xprt
_init_xid
(
xprt
)
;
/* Check whether we want to use a reserved port */
xprt
->
resvport
=
capable
(
CAP_NET_BIND_SERVICE
)
?
1
:
0
;
dprintk
(
"RPC: created transport %p
\n
"
,
xprt
);
dprintk
(
"RPC: created transport %p with %u slots
\n
"
,
xprt
,
xprt
->
max_reqs
);
return
xprt
;
}
...
...
@@ -1489,31 +1487,28 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
/*
* Bind to a reserved port
*/
static
inline
int
xprt_bindresvport
(
struct
socket
*
sock
)
static
inline
int
xprt_bindresvport
(
struct
rpc_xprt
*
xprt
,
struct
socket
*
sock
)
{
struct
sockaddr_in
myaddr
;
struct
sockaddr_in
myaddr
=
{
.
sin_family
=
AF_INET
,
};
int
err
,
port
;
kernel_cap_t
saved_cap
=
current
->
cap_effective
;
/* Override capabilities.
* They were checked in xprt_create_proto i.e. at mount time
*/
cap_raise
(
current
->
cap_effective
,
CAP_NET_BIND_SERVICE
);
memset
(
&
myaddr
,
0
,
sizeof
(
myaddr
));
myaddr
.
sin_family
=
AF_INET
;
port
=
800
;
/* Were we already bound to a given port? Try to reuse it */
port
=
xprt
->
port
;
do
{
myaddr
.
sin_port
=
htons
(
port
);
err
=
sock
->
ops
->
bind
(
sock
,
(
struct
sockaddr
*
)
&
myaddr
,
sizeof
(
myaddr
));
}
while
(
err
==
-
EADDRINUSE
&&
--
port
>
0
);
current
->
cap_effective
=
saved_cap
;
if
(
err
==
0
)
{
xprt
->
port
=
port
;
return
0
;
}
if
(
--
port
==
0
)
port
=
XPRT_MAX_RESVPORT
;
}
while
(
err
==
-
EADDRINUSE
&&
port
!=
xprt
->
port
);
if
(
err
<
0
)
printk
(
"RPC: Can't bind to reserved port (%d).
\n
"
,
-
err
);
return
err
;
}
...
...
@@ -1563,11 +1558,11 @@ xprt_sock_setbufsize(struct rpc_xprt *xprt)
return
;
if
(
xprt
->
rcvsize
)
{
sk
->
sk_userlocks
|=
SOCK_RCVBUF_LOCK
;
sk
->
sk_rcvbuf
=
xprt
->
rcvsize
*
RPC_MAXCONG
*
2
;
sk
->
sk_rcvbuf
=
xprt
->
rcvsize
*
xprt
->
max_reqs
*
2
;
}
if
(
xprt
->
sndsize
)
{
sk
->
sk_userlocks
|=
SOCK_SNDBUF_LOCK
;
sk
->
sk_sndbuf
=
xprt
->
sndsize
*
RPC_MAXCONG
*
2
;
sk
->
sk_sndbuf
=
xprt
->
sndsize
*
xprt
->
max_reqs
*
2
;
sk
->
sk_write_space
(
sk
);
}
}
...
...
@@ -1576,8 +1571,7 @@ xprt_sock_setbufsize(struct rpc_xprt *xprt)
* Datastream sockets are created here, but xprt_connect will create
* and connect stream sockets.
*/
static
struct
socket
*
xprt_create_socket
(
int
proto
,
struct
rpc_timeout
*
to
,
int
resvport
)
static
struct
socket
*
xprt_create_socket
(
struct
rpc_xprt
*
xprt
,
int
proto
,
int
resvport
)
{
struct
socket
*
sock
;
int
type
,
err
;
...
...
@@ -1593,7 +1587,7 @@ xprt_create_socket(int proto, struct rpc_timeout *to, int resvport)
}
/* If the caller has the capability, bind to a reserved port */
if
(
resvport
&&
xprt_bindresvport
(
sock
)
<
0
)
{
if
(
resvport
&&
xprt_bindresvport
(
xprt
,
sock
)
<
0
)
{
printk
(
"RPC: can't bind to reserved port.
\n
"
);
goto
failed
;
}
...
...
@@ -1614,16 +1608,11 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
struct
rpc_xprt
*
xprt
;
xprt
=
xprt_setup
(
proto
,
sap
,
to
);
if
(
!
xprt
)
goto
out_bad
;
if
(
IS_ERR
(
xprt
)
)
dprintk
(
"RPC: xprt_create_proto failed
\n
"
)
;
else
dprintk
(
"RPC: xprt_create_proto created xprt %p
\n
"
,
xprt
);
return
xprt
;
out_bad:
dprintk
(
"RPC: xprt_create_proto failed
\n
"
);
if
(
xprt
)
kfree
(
xprt
);
return
NULL
;
}
/*
...
...
@@ -1662,6 +1651,7 @@ xprt_destroy(struct rpc_xprt *xprt)
dprintk
(
"RPC: destroying transport %p
\n
"
,
xprt
);
xprt_shutdown
(
xprt
);
xprt_close
(
xprt
);
kfree
(
xprt
->
slot
);
kfree
(
xprt
);
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment