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
Kirill Smelkov
linux
Commits
6925bac1
Commit
6925bac1
authored
Oct 15, 2008
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next'
parents
04ab5918
011935a0
Changes
26
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
955 additions
and
500 deletions
+955
-500
fs/nfs/client.c
fs/nfs/client.c
+2
-3
fs/nfs/dir.c
fs/nfs/dir.c
+15
-5
fs/nfs/file.c
fs/nfs/file.c
+7
-11
fs/nfs/inode.c
fs/nfs/inode.c
+109
-74
fs/nfs/internal.h
fs/nfs/internal.h
+23
-2
fs/nfs/mount_clnt.c
fs/nfs/mount_clnt.c
+2
-1
fs/nfs/namespace.c
fs/nfs/namespace.c
+5
-2
fs/nfs/nfs3acl.c
fs/nfs/nfs3acl.c
+2
-0
fs/nfs/nfs3proc.c
fs/nfs/nfs3proc.c
+18
-2
fs/nfs/nfs4namespace.c
fs/nfs/nfs4namespace.c
+49
-56
fs/nfs/proc.c
fs/nfs/proc.c
+8
-2
fs/nfs/super.c
fs/nfs/super.c
+76
-50
fs/nfs/unlink.c
fs/nfs/unlink.c
+3
-2
fs/nfs/write.c
fs/nfs/write.c
+2
-1
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+7
-12
include/linux/nfs_fs_sb.h
include/linux/nfs_fs_sb.h
+0
-1
include/linux/nfs_mount.h
include/linux/nfs_mount.h
+4
-0
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+6
-5
include/linux/sunrpc/xprtrdma.h
include/linux/sunrpc/xprtrdma.h
+1
-3
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+2
-2
net/sunrpc/rpcb_clnt.c
net/sunrpc/rpcb_clnt.c
+32
-8
net/sunrpc/xprt.c
net/sunrpc/xprt.c
+4
-8
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/rpc_rdma.c
+24
-5
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/transport.c
+31
-10
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/verbs.c
+507
-234
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtrdma/xprt_rdma.h
+16
-1
No files found.
fs/nfs/client.c
View file @
6925bac1
...
...
@@ -675,7 +675,7 @@ static int nfs_init_server(struct nfs_server *server,
server
->
nfs_client
=
clp
;
/* Initialise the client representation from the mount data */
server
->
flags
=
data
->
flags
&
NFS_MOUNT_FLAGMASK
;
server
->
flags
=
data
->
flags
;
if
(
data
->
rsize
)
server
->
rsize
=
nfs_block_size
(
data
->
rsize
,
NULL
);
...
...
@@ -850,7 +850,6 @@ static struct nfs_server *nfs_alloc_server(void)
INIT_LIST_HEAD
(
&
server
->
client_link
);
INIT_LIST_HEAD
(
&
server
->
master_link
);
init_waitqueue_head
(
&
server
->
active_wq
);
atomic_set
(
&
server
->
active
,
0
);
server
->
io_stats
=
nfs_alloc_iostats
();
...
...
@@ -1073,7 +1072,7 @@ static int nfs4_init_server(struct nfs_server *server,
goto
error
;
/* Initialise the client representation from the mount data */
server
->
flags
=
data
->
flags
&
NFS_MOUNT_FLAGMASK
;
server
->
flags
=
data
->
flags
;
server
->
caps
|=
NFS_CAP_ATOMIC_OPEN
;
if
(
data
->
rsize
)
...
...
fs/nfs/dir.c
View file @
6925bac1
...
...
@@ -156,6 +156,7 @@ typedef struct {
decode_dirent_t
decode
;
int
plus
;
unsigned
long
timestamp
;
unsigned
long
gencount
;
int
timestamp_valid
;
}
nfs_readdir_descriptor_t
;
...
...
@@ -177,7 +178,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
struct
file
*
file
=
desc
->
file
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
rpc_cred
*
cred
=
nfs_file_cred
(
file
);
unsigned
long
timestamp
;
unsigned
long
timestamp
,
gencount
;
int
error
;
dfprintk
(
DIRCACHE
,
"NFS: %s: reading cookie %Lu into page %lu
\n
"
,
...
...
@@ -186,6 +187,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
again:
timestamp
=
jiffies
;
gencount
=
nfs_inc_attr_generation_counter
();
error
=
NFS_PROTO
(
inode
)
->
readdir
(
file
->
f_path
.
dentry
,
cred
,
desc
->
entry
->
cookie
,
page
,
NFS_SERVER
(
inode
)
->
dtsize
,
desc
->
plus
);
if
(
error
<
0
)
{
...
...
@@ -199,6 +201,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
goto
error
;
}
desc
->
timestamp
=
timestamp
;
desc
->
gencount
=
gencount
;
desc
->
timestamp_valid
=
1
;
SetPageUptodate
(
page
);
/* Ensure consistent page alignment of the data.
...
...
@@ -224,9 +227,10 @@ int dir_decode(nfs_readdir_descriptor_t *desc)
if
(
IS_ERR
(
p
))
return
PTR_ERR
(
p
);
desc
->
ptr
=
p
;
if
(
desc
->
timestamp_valid
)
if
(
desc
->
timestamp_valid
)
{
desc
->
entry
->
fattr
->
time_start
=
desc
->
timestamp
;
else
desc
->
entry
->
fattr
->
gencount
=
desc
->
gencount
;
}
else
desc
->
entry
->
fattr
->
valid
&=
~
NFS_ATTR_FATTR
;
return
0
;
}
...
...
@@ -471,7 +475,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
struct
rpc_cred
*
cred
=
nfs_file_cred
(
file
);
struct
page
*
page
=
NULL
;
int
status
;
unsigned
long
timestamp
;
unsigned
long
timestamp
,
gencount
;
dfprintk
(
DIRCACHE
,
"NFS: uncached_readdir() searching for cookie %Lu
\n
"
,
(
unsigned
long
long
)
*
desc
->
dir_cookie
);
...
...
@@ -482,6 +486,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
goto
out
;
}
timestamp
=
jiffies
;
gencount
=
nfs_inc_attr_generation_counter
();
status
=
NFS_PROTO
(
inode
)
->
readdir
(
file
->
f_path
.
dentry
,
cred
,
*
desc
->
dir_cookie
,
page
,
NFS_SERVER
(
inode
)
->
dtsize
,
...
...
@@ -490,6 +495,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
desc
->
ptr
=
kmap
(
page
);
/* matching kunmap in nfs_do_filldir */
if
(
status
>=
0
)
{
desc
->
timestamp
=
timestamp
;
desc
->
gencount
=
gencount
;
desc
->
timestamp_valid
=
1
;
if
((
status
=
dir_decode
(
desc
))
==
0
)
desc
->
entry
->
prev_cookie
=
*
desc
->
dir_cookie
;
...
...
@@ -655,7 +661,7 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
*/
void
nfs_force_lookup_revalidate
(
struct
inode
*
dir
)
{
NFS_I
(
dir
)
->
cache_change_attribute
=
jiffies
;
NFS_I
(
dir
)
->
cache_change_attribute
++
;
}
/*
...
...
@@ -667,6 +673,8 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
{
if
(
IS_ROOT
(
dentry
))
return
1
;
if
(
NFS_SERVER
(
dir
)
->
flags
&
NFS_MOUNT_LOOKUP_CACHE_NONE
)
return
0
;
if
(
!
nfs_verify_change_attribute
(
dir
,
dentry
->
d_time
))
return
0
;
/* Revalidate nfsi->cache_change_attribute before we declare a match */
...
...
@@ -750,6 +758,8 @@ 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
(
nd
!=
NULL
&&
nfs_lookup_check_intent
(
nd
,
LOOKUP_CREATE
)
!=
0
)
return
0
;
if
(
NFS_SERVER
(
dir
)
->
flags
&
NFS_MOUNT_LOOKUP_CACHE_NONEG
)
return
1
;
return
!
nfs_check_verifier
(
dir
,
dentry
);
}
...
...
fs/nfs/file.c
View file @
6925bac1
...
...
@@ -188,13 +188,16 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
/* origin == SEEK_END => we must revalidate the cached file length */
if
(
origin
==
SEEK_END
)
{
struct
inode
*
inode
=
filp
->
f_mapping
->
host
;
int
retval
=
nfs_revalidate_file_size
(
inode
,
filp
);
if
(
retval
<
0
)
return
(
loff_t
)
retval
;
}
lock_kernel
();
/* BKL needed? */
spin_lock
(
&
inode
->
i_lock
);
loff
=
generic_file_llseek_unlocked
(
filp
,
offset
,
origin
);
spin_unlock
(
&
inode
->
i_lock
);
}
else
loff
=
generic_file_llseek_unlocked
(
filp
,
offset
,
origin
);
unlock_kernel
();
return
loff
;
}
...
...
@@ -699,13 +702,6 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
filp
->
f_path
.
dentry
->
d_name
.
name
,
fl
->
fl_type
,
fl
->
fl_flags
);
/*
* No BSD flocks over NFS allowed.
* Note: we could try to fake a POSIX lock request here by
* using ((u32) filp | 0x80000000) or some such as the pid.
* Not sure whether that would be unique, though, or whether
* that would break in other places.
*/
if
(
!
(
fl
->
fl_flags
&
FL_FLOCK
))
return
-
ENOLCK
;
...
...
fs/nfs/inode.c
View file @
6925bac1
This diff is collapsed.
Click to expand it.
fs/nfs/internal.h
View file @
6925bac1
...
...
@@ -153,6 +153,7 @@ extern void nfs4_clear_inode(struct inode *);
void
nfs_zap_acl_cache
(
struct
inode
*
inode
);
/* super.c */
void
nfs_parse_ip_address
(
char
*
,
size_t
,
struct
sockaddr
*
,
size_t
*
);
extern
struct
file_system_type
nfs_xdev_fs_type
;
#ifdef CONFIG_NFS_V4
extern
struct
file_system_type
nfs4_xdev_fs_type
;
...
...
@@ -163,8 +164,8 @@ extern struct rpc_stat nfs_rpcstat;
extern
int
__init
register_nfs_fs
(
void
);
extern
void
__exit
unregister_nfs_fs
(
void
);
extern
void
nfs_sb_active
(
struct
nfs_server
*
server
);
extern
void
nfs_sb_deactive
(
struct
nfs_server
*
server
);
extern
void
nfs_sb_active
(
struct
super_block
*
sb
);
extern
void
nfs_sb_deactive
(
struct
super_block
*
sb
);
/* namespace.c */
extern
char
*
nfs_path
(
const
char
*
base
,
...
...
@@ -276,3 +277,23 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
PAGE_SIZE
-
1
)
>>
PAGE_SHIFT
;
}
#define IPV6_SCOPE_DELIMITER '%'
/*
* Set the port number in an address. Be agnostic about the address
* family.
*/
static
inline
void
nfs_set_port
(
struct
sockaddr
*
sap
,
unsigned
short
port
)
{
struct
sockaddr_in
*
ap
=
(
struct
sockaddr_in
*
)
sap
;
struct
sockaddr_in6
*
ap6
=
(
struct
sockaddr_in6
*
)
sap
;
switch
(
sap
->
sa_family
)
{
case
AF_INET
:
ap
->
sin_port
=
htons
(
port
);
break
;
case
AF_INET6
:
ap6
->
sin6_port
=
htons
(
port
);
break
;
}
}
fs/nfs/mount_clnt.c
View file @
6925bac1
...
...
@@ -14,6 +14,7 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/sched.h>
#include <linux/nfs_fs.h>
#include "internal.h"
#ifdef RPC_DEBUG
# define NFSDBG_FACILITY NFSDBG_MOUNT
...
...
@@ -98,7 +99,7 @@ int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
out_mnt_err:
dprintk
(
"NFS: MNT server returned result %d
\n
"
,
result
.
status
);
status
=
-
EACCES
;
status
=
nfs_stat_to_errno
(
result
.
status
)
;
goto
out
;
}
...
...
fs/nfs/namespace.c
View file @
6925bac1
...
...
@@ -105,7 +105,10 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
dprintk
(
"--> nfs_follow_mountpoint()
\n
"
);
BUG_ON
(
IS_ROOT
(
dentry
));
err
=
-
ESTALE
;
if
(
IS_ROOT
(
dentry
))
goto
out_err
;
dprintk
(
"%s: enter
\n
"
,
__func__
);
dput
(
nd
->
path
.
dentry
);
nd
->
path
.
dentry
=
dget
(
dentry
);
...
...
@@ -189,7 +192,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
struct
nfs_clone_mount
*
mountdata
)
{
#ifdef CONFIG_NFS_V4
struct
vfsmount
*
mnt
=
NULL
;
struct
vfsmount
*
mnt
=
ERR_PTR
(
-
EINVAL
)
;
switch
(
server
->
nfs_client
->
rpc_ops
->
version
)
{
case
2
:
case
3
:
...
...
fs/nfs/nfs3acl.c
View file @
6925bac1
...
...
@@ -229,6 +229,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
dprintk
(
"NFS call getacl
\n
"
);
msg
.
rpc_proc
=
&
server
->
client_acl
->
cl_procinfo
[
ACLPROC3_GETACL
];
nfs_fattr_init
(
&
fattr
);
status
=
rpc_call_sync
(
server
->
client_acl
,
&
msg
,
0
);
dprintk
(
"NFS reply getacl: %d
\n
"
,
status
);
...
...
@@ -322,6 +323,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
dprintk
(
"NFS call setacl
\n
"
);
msg
.
rpc_proc
=
&
server
->
client_acl
->
cl_procinfo
[
ACLPROC3_SETACL
];
nfs_fattr_init
(
&
fattr
);
status
=
rpc_call_sync
(
server
->
client_acl
,
&
msg
,
0
);
nfs_access_zap_cache
(
inode
);
nfs_zap_acl_cache
(
inode
);
...
...
fs/nfs/nfs3proc.c
View file @
6925bac1
...
...
@@ -699,7 +699,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
}
static
int
nfs3_proc_fsinfo
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
do_proc_fsinfo
(
struct
rpc_clnt
*
client
,
struct
nfs_fh
*
fhandle
,
struct
nfs_fsinfo
*
info
)
{
struct
rpc_message
msg
=
{
...
...
@@ -711,11 +711,27 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
dprintk
(
"NFS call fsinfo
\n
"
);
nfs_fattr_init
(
info
->
fattr
);
status
=
rpc_call_sync
(
server
->
nfs_client
->
cl_rpc
client
,
&
msg
,
0
);
status
=
rpc_call_sync
(
client
,
&
msg
,
0
);
dprintk
(
"NFS reply fsinfo: %d
\n
"
,
status
);
return
status
;
}
/*
* Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via
* nfs_create_server
*/
static
int
nfs3_proc_fsinfo
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
struct
nfs_fsinfo
*
info
)
{
int
status
;
status
=
do_proc_fsinfo
(
server
->
client
,
fhandle
,
info
);
if
(
status
&&
server
->
nfs_client
->
cl_rpcclient
!=
server
->
client
)
status
=
do_proc_fsinfo
(
server
->
nfs_client
->
cl_rpcclient
,
fhandle
,
info
);
return
status
;
}
static
int
nfs3_proc_pathconf
(
struct
nfs_server
*
server
,
struct
nfs_fh
*
fhandle
,
struct
nfs_pathconf
*
info
)
...
...
fs/nfs/nfs4namespace.c
View file @
6925bac1
...
...
@@ -93,21 +93,52 @@ static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
return
0
;
}
/*
* Check if the string represents a "valid" IPv4 address
*/
static
inline
int
valid_ipaddr4
(
const
char
*
buf
)
static
struct
vfsmount
*
try_location
(
struct
nfs_clone_mount
*
mountdata
,
char
*
page
,
char
*
page2
,
const
struct
nfs4_fs_location
*
location
)
{
int
rc
,
count
,
in
[
4
];
rc
=
sscanf
(
buf
,
"%d.%d.%d.%d"
,
&
in
[
0
],
&
in
[
1
],
&
in
[
2
],
&
in
[
3
]);
if
(
rc
!=
4
)
return
-
EINVAL
;
for
(
count
=
0
;
count
<
4
;
count
++
)
{
if
(
in
[
count
]
>
255
)
return
-
EINVAL
;
struct
vfsmount
*
mnt
=
ERR_PTR
(
-
ENOENT
);
char
*
mnt_path
;
int
page2len
;
unsigned
int
s
;
mnt_path
=
nfs4_pathname_string
(
&
location
->
rootpath
,
page2
,
PAGE_SIZE
);
if
(
IS_ERR
(
mnt_path
))
return
mnt
;
mountdata
->
mnt_path
=
mnt_path
;
page2
+=
strlen
(
mnt_path
)
+
1
;
page2len
=
PAGE_SIZE
-
strlen
(
mnt_path
)
-
1
;
for
(
s
=
0
;
s
<
location
->
nservers
;
s
++
)
{
const
struct
nfs4_string
*
buf
=
&
location
->
servers
[
s
];
struct
sockaddr_storage
addr
;
if
(
buf
->
len
<=
0
||
buf
->
len
>=
PAGE_SIZE
)
continue
;
mountdata
->
addr
=
(
struct
sockaddr
*
)
&
addr
;
if
(
memchr
(
buf
->
data
,
IPV6_SCOPE_DELIMITER
,
buf
->
len
))
continue
;
nfs_parse_ip_address
(
buf
->
data
,
buf
->
len
,
mountdata
->
addr
,
&
mountdata
->
addrlen
);
if
(
mountdata
->
addr
->
sa_family
==
AF_UNSPEC
)
continue
;
nfs_set_port
(
mountdata
->
addr
,
NFS_PORT
);
strncpy
(
page2
,
buf
->
data
,
page2len
);
page2
[
page2len
]
=
'\0'
;
mountdata
->
hostname
=
page2
;
snprintf
(
page
,
PAGE_SIZE
,
"%s:%s"
,
mountdata
->
hostname
,
mountdata
->
mnt_path
);
mnt
=
vfs_kern_mount
(
&
nfs4_referral_fs_type
,
0
,
page
,
mountdata
);
if
(
!
IS_ERR
(
mnt
))
break
;
}
return
0
;
return
mnt
;
}
/**
...
...
@@ -128,7 +159,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
.
authflavor
=
NFS_SB
(
mnt_parent
->
mnt_sb
)
->
client
->
cl_auth
->
au_flavor
,
};
char
*
page
=
NULL
,
*
page2
=
NULL
;
unsigned
int
s
;
int
loc
,
error
;
if
(
locations
==
NULL
||
locations
->
nlocations
<=
0
)
...
...
@@ -152,54 +182,17 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
goto
out
;
}
loc
=
0
;
while
(
loc
<
locations
->
nlocations
&&
IS_ERR
(
mnt
))
{
for
(
loc
=
0
;
loc
<
locations
->
nlocations
;
loc
++
)
{
const
struct
nfs4_fs_location
*
location
=
&
locations
->
locations
[
loc
];
char
*
mnt_path
;
if
(
location
==
NULL
||
location
->
nservers
<=
0
||
location
->
rootpath
.
ncomponents
==
0
)
{
loc
++
;
continue
;
}
mnt_path
=
nfs4_pathname_string
(
&
location
->
rootpath
,
page2
,
PAGE_SIZE
);
if
(
IS_ERR
(
mnt_path
))
{
loc
++
;
location
->
rootpath
.
ncomponents
==
0
)
continue
;
}
mountdata
.
mnt_path
=
mnt_path
;
s
=
0
;
while
(
s
<
location
->
nservers
)
{
struct
sockaddr_in
addr
=
{
.
sin_family
=
AF_INET
,
.
sin_port
=
htons
(
NFS_PORT
),
};
if
(
location
->
servers
[
s
].
len
<=
0
||
valid_ipaddr4
(
location
->
servers
[
s
].
data
)
<
0
)
{
s
++
;
continue
;
}
mountdata
.
hostname
=
location
->
servers
[
s
].
data
;
addr
.
sin_addr
.
s_addr
=
in_aton
(
mountdata
.
hostname
),
mountdata
.
addr
=
(
struct
sockaddr
*
)
&
addr
;
mountdata
.
addrlen
=
sizeof
(
addr
);
snprintf
(
page
,
PAGE_SIZE
,
"%s:%s"
,
mountdata
.
hostname
,
mountdata
.
mnt_path
);
mnt
=
vfs_kern_mount
(
&
nfs4_referral_fs_type
,
0
,
page
,
&
mountdata
);
if
(
!
IS_ERR
(
mnt
))
{
mnt
=
try_location
(
&
mountdata
,
page
,
page2
,
location
);
if
(
!
IS_ERR
(
mnt
))
break
;
}
s
++
;
}
loc
++
;
}
out:
free_page
((
unsigned
long
)
page
);
...
...
fs/nfs/proc.c
View file @
6925bac1
...
...
@@ -65,6 +65,9 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
dprintk
(
"%s: call getattr
\n
"
,
__func__
);
nfs_fattr_init
(
fattr
);
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
/* Retry with default authentication if different */
if
(
status
&&
server
->
nfs_client
->
cl_rpcclient
!=
server
->
client
)
status
=
rpc_call_sync
(
server
->
nfs_client
->
cl_rpcclient
,
&
msg
,
0
);
dprintk
(
"%s: reply getattr: %d
\n
"
,
__func__
,
status
);
if
(
status
)
...
...
@@ -72,6 +75,9 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
dprintk
(
"%s: call statfs
\n
"
,
__func__
);
msg
.
rpc_proc
=
&
nfs_procedures
[
NFSPROC_STATFS
];
msg
.
rpc_resp
=
&
fsinfo
;
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
/* Retry with default authentication if different */
if
(
status
&&
server
->
nfs_client
->
cl_rpcclient
!=
server
->
client
)
status
=
rpc_call_sync
(
server
->
nfs_client
->
cl_rpcclient
,
&
msg
,
0
);
dprintk
(
"%s: reply statfs: %d
\n
"
,
__func__
,
status
);
if
(
status
)
...
...
fs/nfs/super.c
View file @
6925bac1
...
...
@@ -91,6 +91,7 @@ enum {
/* Mount options that take string arguments */
Opt_sec
,
Opt_proto
,
Opt_mountproto
,
Opt_mounthost
,
Opt_addr
,
Opt_mountaddr
,
Opt_clientaddr
,
Opt_lookupcache
,
/* Special mount options */
Opt_userspace
,
Opt_deprecated
,
Opt_sloppy
,
...
...
@@ -154,6 +155,8 @@ static const match_table_t nfs_mount_option_tokens = {
{
Opt_mounthost
,
"mounthost=%s"
},
{
Opt_mountaddr
,
"mountaddr=%s"
},
{
Opt_lookupcache
,
"lookupcache=%s"
},
{
Opt_err
,
NULL
}
};
...
...
@@ -200,6 +203,22 @@ static const match_table_t nfs_secflavor_tokens = {
{
Opt_sec_err
,
NULL
}
};
enum
{
Opt_lookupcache_all
,
Opt_lookupcache_positive
,
Opt_lookupcache_none
,
Opt_lookupcache_err
};
static
match_table_t
nfs_lookupcache_tokens
=
{
{
Opt_lookupcache_all
,
"all"
},
{
Opt_lookupcache_positive
,
"pos"
},
{
Opt_lookupcache_positive
,
"positive"
},
{
Opt_lookupcache_none
,
"none"
},
{
Opt_lookupcache_err
,
NULL
}
};
static
void
nfs_umount_begin
(
struct
super_block
*
);
static
int
nfs_statfs
(
struct
dentry
*
,
struct
kstatfs
*
);
...
...
@@ -209,7 +228,6 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru
static
int
nfs_xdev_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
raw_data
,
struct
vfsmount
*
mnt
);
static
void
nfs_kill_super
(
struct
super_block
*
);
static
void
nfs_put_super
(
struct
super_block
*
);
static
int
nfs_remount
(
struct
super_block
*
sb
,
int
*
flags
,
char
*
raw_data
);
static
struct
file_system_type
nfs_fs_type
=
{
...
...
@@ -232,7 +250,6 @@ static const struct super_operations nfs_sops = {
.
alloc_inode
=
nfs_alloc_inode
,
.
destroy_inode
=
nfs_destroy_inode
,
.
write_inode
=
nfs_write_inode
,
.
put_super
=
nfs_put_super
,
.
statfs
=
nfs_statfs
,
.
clear_inode
=
nfs_clear_inode
,
.
umount_begin
=
nfs_umount_begin
,
...
...
@@ -337,26 +354,20 @@ void __exit unregister_nfs_fs(void)
unregister_filesystem
(
&
nfs_fs_type
);
}
void
nfs_sb_active
(
struct
nfs_server
*
server
)
void
nfs_sb_active
(
struct
super_block
*
sb
)
{
atomic_inc
(
&
server
->
active
);
}
struct
nfs_server
*
server
=
NFS_SB
(
sb
);
void
nfs_sb_deactive
(
struct
nfs_server
*
server
)
{
if
(
atomic_dec_and_test
(
&
server
->
active
))
wake_up
(
&
server
->
active_wq
);
if
(
atomic_inc_return
(
&
server
->
active
)
==
1
)
atomic_inc
(
&
sb
->
s_active
);
}
static
void
nfs_put_super
(
struct
super_block
*
sb
)
void
nfs_sb_deactive
(
struct
super_block
*
sb
)
{
struct
nfs_server
*
server
=
NFS_SB
(
sb
);
/*
* Make sure there are no outstanding ops to this server.
* If so, wait for them to finish before allowing the
* unmount to continue.
*/
wait_event
(
server
->
active_wq
,
atomic_read
(
&
server
->
active
)
==
0
);
if
(
atomic_dec_and_test
(
&
server
->
active
))
deactivate_super
(
sb
);
}
/*
...
...
@@ -663,25 +674,6 @@ static void nfs_umount_begin(struct super_block *sb)
rpc_killall_tasks
(
rpc
);
}
/*
* Set the port number in an address. Be agnostic about the address family.
*/
static
void
nfs_set_port
(
struct
sockaddr
*
sap
,
unsigned
short
port
)
{
switch
(
sap
->
sa_family
)
{
case
AF_INET
:
{
struct
sockaddr_in
*
ap
=
(
struct
sockaddr_in
*
)
sap
;
ap
->
sin_port
=
htons
(
port
);
break
;
}
case
AF_INET6
:
{
struct
sockaddr_in6
*
ap
=
(
struct
sockaddr_in6
*
)
sap
;
ap
->
sin6_port
=
htons
(
port
);
break
;
}
}
}
/*
* Sanity-check a server address provided by the mount command.
*
...
...
@@ -724,20 +716,22 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
*
addr_len
=
0
;
}
#define IPV6_SCOPE_DELIMITER '%'
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static
void
nfs_parse_ipv6_scope_id
(
const
char
*
string
,
const
size_t
str_len
,
static
int
nfs_parse_ipv6_scope_id
(
const
char
*
string
,
const
size_t
str_len
,
const
char
*
delim
,
struct
sockaddr_in6
*
sin6
)
{
char
*
p
;
size_t
len
;
if
(
!
(
ipv6_addr_type
(
&
sin6
->
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
))
return
;
if
((
string
+
str_len
)
==
delim
)
return
1
;
if
(
*
delim
!=
IPV6_SCOPE_DELIMITER
)
return
;
return
0
;
if
(
!
(
ipv6_addr_type
(
&
sin6
->
sin6_addr
)
&
IPV6_ADDR_LINKLOCAL
))
return
0
;
len
=
(
string
+
str_len
)
-
delim
-
1
;
p
=
kstrndup
(
delim
+
1
,
len
,
GFP_KERNEL
);
...
...
@@ -750,14 +744,20 @@ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
scope_id
=
dev
->
ifindex
;
dev_put
(
dev
);
}
else
{
/* scope_id is set to zero on error */
strict_strtoul
(
p
,
10
,
&
scope_id
);
if
(
strict_strtoul
(
p
,
10
,
&
scope_id
)
==
0
)
{
kfree
(
p
);
return
0
;
}
}
kfree
(
p
);
sin6
->
sin6_scope_id
=
scope_id
;
dfprintk
(
MOUNT
,
"NFS: IPv6 scope ID = %lu
\n
"
,
scope_id
);
return
1
;
}
return
0
;
}
static
void
nfs_parse_ipv6_address
(
char
*
string
,
size_t
str_len
,
...
...
@@ -773,8 +773,10 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
sin6
->
sin6_family
=
AF_INET6
;
*
addr_len
=
sizeof
(
*
sin6
);
if
(
in6_pton
(
string
,
str_len
,
addr
,
IPV6_SCOPE_DELIMITER
,
&
delim
))
{
nfs_parse_ipv6_scope_id
(
string
,
str_len
,
delim
,
sin6
);
if
(
in6_pton
(
string
,
str_len
,
addr
,
IPV6_SCOPE_DELIMITER
,
&
delim
)
!=
0
)
{
if
(
nfs_parse_ipv6_scope_id
(
string
,
str_len
,
delim
,
sin6
)
!=
0
)
return
;
}
}
...
...
@@ -798,7 +800,7 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
* If there is a problem constructing the new sockaddr, set the address
* family to AF_UNSPEC.
*/
static
void
nfs_parse_ip_address
(
char
*
string
,
size_t
str_len
,
void
nfs_parse_ip_address
(
char
*
string
,
size_t
str_len
,
struct
sockaddr
*
sap
,
size_t
*
addr_len
)
{
unsigned
int
i
,
colons
;
...
...
@@ -1258,6 +1260,30 @@ static int nfs_parse_mount_options(char *raw,
&
mnt
->
mount_server
.
addrlen
);
kfree
(
string
);
break
;
case
Opt_lookupcache
:
string
=
match_strdup
(
args
);
if
(
string
==
NULL
)
goto
out_nomem
;
token
=
match_token
(
string
,
nfs_lookupcache_tokens
,
args
);
kfree
(
string
);
switch
(
token
)
{
case
Opt_lookupcache_all
:
mnt
->
flags
&=
~
(
NFS_MOUNT_LOOKUP_CACHE_NONEG
|
NFS_MOUNT_LOOKUP_CACHE_NONE
);
break
;
case
Opt_lookupcache_positive
:
mnt
->
flags
&=
~
NFS_MOUNT_LOOKUP_CACHE_NONE
;
mnt
->
flags
|=
NFS_MOUNT_LOOKUP_CACHE_NONEG
;
break
;
case
Opt_lookupcache_none
:
mnt
->
flags
|=
NFS_MOUNT_LOOKUP_CACHE_NONEG
|
NFS_MOUNT_LOOKUP_CACHE_NONE
;
break
;
default:
errors
++
;
dfprintk
(
MOUNT
,
"NFS: invalid "
"lookupcache argument
\n
"
);
};
break
;
/*
* Special options
...
...
@@ -1558,7 +1584,7 @@ static int nfs_validate_mount_data(void *options,
* Translate to nfs_parsed_mount_data, which nfs_fill_super
* can deal with.
*/
args
->
flags
=
data
->
flags
;
args
->
flags
=
data
->
flags
&
NFS_MOUNT_FLAGMASK
;
args
->
rsize
=
data
->
rsize
;
args
->
wsize
=
data
->
wsize
;
args
->
timeo
=
data
->
timeo
;
...
...
fs/nfs/unlink.c
View file @
6925bac1
...
...
@@ -99,7 +99,7 @@ static void nfs_async_unlink_release(void *calldata)
nfs_dec_sillycount
(
data
->
dir
);
nfs_free_unlinkdata
(
data
);
nfs_sb_deactive
(
NFS_SB
(
sb
)
);
nfs_sb_deactive
(
sb
);
}
static
const
struct
rpc_call_ops
nfs_unlink_ops
=
{
...
...
@@ -118,6 +118,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
.
rpc_message
=
&
msg
,
.
callback_ops
=
&
nfs_unlink_ops
,
.
callback_data
=
data
,
.
workqueue
=
nfsiod_workqueue
,
.
flags
=
RPC_TASK_ASYNC
,
};
struct
rpc_task
*
task
;
...
...
@@ -149,7 +150,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
nfs_dec_sillycount
(
dir
);
return
0
;
}
nfs_sb_active
(
NFS_SERVER
(
dir
)
);
nfs_sb_active
(
dir
->
i_sb
);
data
->
args
.
fh
=
NFS_FH
(
dir
);
nfs_fattr_init
(
&
data
->
res
.
dir_attr
);
...
...
fs/nfs/write.c
View file @
6925bac1
...
...
@@ -1427,8 +1427,9 @@ static int nfs_write_mapping(struct address_space *mapping, int how)
.
bdi
=
mapping
->
backing_dev_info
,
.
sync_mode
=
WB_SYNC_NONE
,
.
nr_to_write
=
LONG_MAX
,
.
range_start
=
0
,
.
range_end
=
LLONG_MAX
,
.
for_writepages
=
1
,
.
range_cyclic
=
1
,
};
int
ret
;
...
...
include/linux/nfs_fs.h
View file @
6925bac1
...
...
@@ -137,7 +137,7 @@ struct nfs_inode {
unsigned
long
attrtimeo_timestamp
;
__u64
change_attr
;
/* v4 only */
unsigned
long
last_updated
;
unsigned
long
attr_gencount
;
/* "Generation counter" for the attribute cache. This is
* bumped whenever we update the metadata on the
* server.
...
...
@@ -200,11 +200,10 @@ struct nfs_inode {
/*
* Bit offsets in flags field
*/
#define NFS_INO_REVALIDATING (0)
/* revalidating attrs */
#define NFS_INO_ADVISE_RDPLUS (1)
/* advise readdirplus */
#define NFS_INO_STALE (2)
/* possible stale inode */
#define NFS_INO_ACL_LRU_SET (3)
/* Inode is on the LRU list */
#define NFS_INO_MOUNTPOINT (4)
/* inode is remote mountpoint */
#define NFS_INO_ADVISE_RDPLUS (0)
/* advise readdirplus */
#define NFS_INO_STALE (1)
/* possible stale inode */
#define NFS_INO_ACL_LRU_SET (2)
/* Inode is on the LRU list */
#define NFS_INO_MOUNTPOINT (3)
/* inode is remote mountpoint */
static
inline
struct
nfs_inode
*
NFS_I
(
const
struct
inode
*
inode
)
{
...
...
@@ -345,15 +344,11 @@ extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ct
extern
void
put_nfs_open_context
(
struct
nfs_open_context
*
ctx
);
extern
struct
nfs_open_context
*
nfs_find_open_context
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
int
mode
);
extern
u64
nfs_compat_user_ino64
(
u64
fileid
);
extern
void
nfs_fattr_init
(
struct
nfs_fattr
*
fattr
);
/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
extern
__be32
root_nfs_parse_addr
(
char
*
name
);
/*__init*/
static
inline
void
nfs_fattr_init
(
struct
nfs_fattr
*
fattr
)
{
fattr
->
valid
=
0
;
fattr
->
time_start
=
jiffies
;
}
extern
unsigned
long
nfs_inc_attr_generation_counter
(
void
);
/*
* linux/fs/nfs/file.c
...
...
include/linux/nfs_fs_sb.h
View file @
6925bac1
...
...
@@ -119,7 +119,6 @@ struct nfs_server {
void
(
*
destroy
)(
struct
nfs_server
*
);
atomic_t
active
;
/* Keep trace of any activity to this server */
wait_queue_head_t
active_wq
;
/* Wait for any activity to stop */
/* mountd-related mount options */
struct
sockaddr_storage
mountd_address
;
...
...
include/linux/nfs_mount.h
View file @
6925bac1
...
...
@@ -65,4 +65,8 @@ struct nfs_mount_data {
#define NFS_MOUNT_UNSHARED 0x8000
/* 5 */
#define NFS_MOUNT_FLAGMASK 0xFFFF
/* The following are for internal use only */
#define NFS_MOUNT_LOOKUP_CACHE_NONEG 0x10000
#define NFS_MOUNT_LOOKUP_CACHE_NONE 0x20000
#endif
include/linux/nfs_xdr.h
View file @
6925bac1
...
...
@@ -36,6 +36,7 @@ struct nfs_fattr {
__u32
nlink
;
__u32
uid
;
__u32
gid
;
dev_t
rdev
;
__u64
size
;
union
{
struct
{
...
...
@@ -46,7 +47,6 @@ struct nfs_fattr {
__u64
used
;
}
nfs3
;
}
du
;
dev_t
rdev
;
struct
nfs_fsid
fsid
;
__u64
fileid
;
struct
timespec
atime
;
...
...
@@ -56,6 +56,7 @@ struct nfs_fattr {
__u64
change_attr
;
/* NFSv4 change attribute */
__u64
pre_change_attr
;
/* pre-op NFSv4 change attribute */
unsigned
long
time_start
;
unsigned
long
gencount
;
};
#define NFS_ATTR_WCC 0x0001
/* pre-op WCC data */
...
...
@@ -672,16 +673,16 @@ struct nfs4_rename_res {
struct
nfs_fattr
*
new_fattr
;
};
#define NFS4_SETCLIENTID_NAMELEN (
56
)
#define NFS4_SETCLIENTID_NAMELEN (
127
)
struct
nfs4_setclientid
{
const
nfs4_verifier
*
sc_verifier
;
unsigned
int
sc_name_len
;
char
sc_name
[
NFS4_SETCLIENTID_NAMELEN
];
char
sc_name
[
NFS4_SETCLIENTID_NAMELEN
+
1
];
u32
sc_prog
;
unsigned
int
sc_netid_len
;
char
sc_netid
[
RPCBIND_MAXNETIDLEN
];
char
sc_netid
[
RPCBIND_MAXNETIDLEN
+
1
];
unsigned
int
sc_uaddr_len
;
char
sc_uaddr
[
RPCBIND_MAXUADDRLEN
];
char
sc_uaddr
[
RPCBIND_MAXUADDRLEN
+
1
];
u32
sc_cb_ident
;
};
...
...
include/linux/sunrpc/xprtrdma.h
View file @
6925bac1
...
...
@@ -66,9 +66,6 @@
#define RPCRDMA_INLINE_PAD_THRESH (512)
/* payload threshold to pad (bytes) */
#define RDMA_RESOLVE_TIMEOUT (5*HZ)
/* TBD 5 seconds */
#define RDMA_CONNECT_RETRY_MAX (2)
/* retries if no listener backlog */
/* memory registration strategies */
#define RPCRDMA_PERSISTENT_REGISTRATION (1)
...
...
@@ -78,6 +75,7 @@ enum rpcrdma_memreg {
RPCRDMA_MEMWINDOWS
,
RPCRDMA_MEMWINDOWS_ASYNC
,
RPCRDMA_MTHCAFMR
,
RPCRDMA_FRMR
,
RPCRDMA_ALLPHYSICAL
,
RPCRDMA_LAST
};
...
...
net/sunrpc/clnt.c
View file @
6925bac1
...
...
@@ -213,10 +213,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
}
/* save the nodename */
clnt
->
cl_nodelen
=
strlen
(
utsname
()
->
nodename
);
clnt
->
cl_nodelen
=
strlen
(
init_
utsname
()
->
nodename
);
if
(
clnt
->
cl_nodelen
>
UNX_MAXNODENAME
)
clnt
->
cl_nodelen
=
UNX_MAXNODENAME
;
memcpy
(
clnt
->
cl_nodename
,
utsname
()
->
nodename
,
clnt
->
cl_nodelen
);
memcpy
(
clnt
->
cl_nodename
,
init_
utsname
()
->
nodename
,
clnt
->
cl_nodelen
);
rpc_register_client
(
clnt
);
return
clnt
;
...
...
net/sunrpc/rpcb_clnt.c
View file @
6925bac1
...
...
@@ -460,6 +460,28 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
return
rpc_run_task
(
&
task_setup_data
);
}
/*
* In the case where rpc clients have been cloned, we want to make
* sure that we use the program number/version etc of the actual
* owner of the xprt. To do so, we walk back up the tree of parents
* to find whoever created the transport and/or whoever has the
* autobind flag set.
*/
static
struct
rpc_clnt
*
rpcb_find_transport_owner
(
struct
rpc_clnt
*
clnt
)
{
struct
rpc_clnt
*
parent
=
clnt
->
cl_parent
;
while
(
parent
!=
clnt
)
{
if
(
parent
->
cl_xprt
!=
clnt
->
cl_xprt
)
break
;
if
(
clnt
->
cl_autobind
)
break
;
clnt
=
parent
;
parent
=
parent
->
cl_parent
;
}
return
clnt
;
}
/**
* rpcb_getport_async - obtain the port for a given RPC service on a given host
* @task: task that is waiting for portmapper request
...
...
@@ -469,10 +491,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
*/
void
rpcb_getport_async
(
struct
rpc_task
*
task
)
{
struct
rpc_clnt
*
clnt
=
task
->
tk_client
;
struct
rpc_clnt
*
clnt
;
struct
rpc_procinfo
*
proc
;
u32
bind_version
;
struct
rpc_xprt
*
xprt
=
task
->
tk_xprt
;
struct
rpc_xprt
*
xprt
;
struct
rpc_clnt
*
rpcb_clnt
;
static
struct
rpcbind_args
*
map
;
struct
rpc_task
*
child
;
...
...
@@ -481,13 +503,13 @@ void rpcb_getport_async(struct rpc_task *task)
size_t
salen
;
int
status
;
clnt
=
rpcb_find_transport_owner
(
task
->
tk_client
);
xprt
=
clnt
->
cl_xprt
;
dprintk
(
"RPC: %5u %s(%s, %u, %u, %d)
\n
"
,
task
->
tk_pid
,
__func__
,
clnt
->
cl_server
,
clnt
->
cl_prog
,
clnt
->
cl_vers
,
xprt
->
prot
);
/* Autobind on cloned rpc clients is discouraged */
BUG_ON
(
clnt
->
cl_parent
!=
clnt
);
/* Put self on the wait queue to ensure we get notified if
* some other task is already attempting to bind the port */
rpc_sleep_on
(
&
xprt
->
binding
,
task
,
NULL
);
...
...
@@ -549,7 +571,7 @@ void rpcb_getport_async(struct rpc_task *task)
status
=
-
ENOMEM
;
dprintk
(
"RPC: %5u %s: no memory available
\n
"
,
task
->
tk_pid
,
__func__
);
goto
bailout_
nofree
;
goto
bailout_
release_client
;
}
map
->
r_prog
=
clnt
->
cl_prog
;
map
->
r_vers
=
clnt
->
cl_vers
;
...
...
@@ -569,11 +591,13 @@ void rpcb_getport_async(struct rpc_task *task)
task
->
tk_pid
,
__func__
);
return
;
}
rpc_put_task
(
child
);
task
->
tk_xprt
->
stat
.
bind_count
++
;
xprt
->
stat
.
bind_count
++
;
rpc_put_task
(
child
);
return
;
bailout_release_client:
rpc_release_client
(
rpcb_clnt
);
bailout_nofree:
rpcb_wake_rpcbind_waiters
(
xprt
,
status
);
task
->
tk_status
=
status
;
...
...
net/sunrpc/xprt.c
View file @
6925bac1
...
...
@@ -108,13 +108,10 @@ int xprt_register_transport(struct xprt_class *transport)
goto
out
;
}
result
=
-
EINVAL
;
if
(
try_module_get
(
THIS_MODULE
))
{
list_add_tail
(
&
transport
->
list
,
&
xprt_list
);
printk
(
KERN_INFO
"RPC: Registered %s transport module.
\n
"
,
transport
->
name
);
result
=
0
;
}
out:
spin_unlock
(
&
xprt_list_lock
);
...
...
@@ -143,7 +140,6 @@ int xprt_unregister_transport(struct xprt_class *transport)
"RPC: Unregistered %s transport module.
\n
"
,
transport
->
name
);
list_del_init
(
&
transport
->
list
);
module_put
(
THIS_MODULE
);
goto
out
;
}
}
...
...
net/sunrpc/xprtrdma/rpc_rdma.c
View file @
6925bac1
...
...
@@ -118,6 +118,10 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
}
if
(
xdrbuf
->
tail
[
0
].
iov_len
)
{
/* the rpcrdma protocol allows us to omit any trailing
* xdr pad bytes, saving the server an RDMA operation. */
if
(
xdrbuf
->
tail
[
0
].
iov_len
<
4
&&
xprt_rdma_pad_optimize
)
return
n
;
if
(
n
==
nsegs
)
return
0
;
seg
[
n
].
mr_page
=
NULL
;
...
...
@@ -508,7 +512,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
if
(
hdrlen
==
0
)
return
-
1
;
dprintk
(
"RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd
\n
"
dprintk
(
"RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd"
" headerp 0x%p base 0x%p lkey 0x%x
\n
"
,
__func__
,
transfertypes
[
wtype
],
hdrlen
,
rpclen
,
padlen
,
headerp
,
base
,
req
->
rl_iov
.
lkey
);
...
...
@@ -594,7 +598,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __b
* Scatter inline received data back into provided iov's.
*/
static
void
rpcrdma_inline_fixup
(
struct
rpc_rqst
*
rqst
,
char
*
srcp
,
int
copy_len
)
rpcrdma_inline_fixup
(
struct
rpc_rqst
*
rqst
,
char
*
srcp
,
int
copy_len
,
int
pad
)
{
int
i
,
npages
,
curlen
,
olen
;
char
*
destp
;
...
...
@@ -660,6 +664,13 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len)
}
else
rqst
->
rq_rcv_buf
.
tail
[
0
].
iov_len
=
0
;
if
(
pad
)
{
/* implicit padding on terminal chunk */
unsigned
char
*
p
=
rqst
->
rq_rcv_buf
.
tail
[
0
].
iov_base
;
while
(
pad
--
)
p
[
rqst
->
rq_rcv_buf
.
tail
[
0
].
iov_len
++
]
=
0
;
}
if
(
copy_len
)
dprintk
(
"RPC: %s: %d bytes in"
" %d extra segments (%d lost)
\n
"
,
...
...
@@ -681,12 +692,14 @@ rpcrdma_conn_func(struct rpcrdma_ep *ep)
struct
rpc_xprt
*
xprt
=
ep
->
rep_xprt
;
spin_lock_bh
(
&
xprt
->
transport_lock
);
if
(
++
xprt
->
connect_cookie
==
0
)
/* maintain a reserved value */
++
xprt
->
connect_cookie
;
if
(
ep
->
rep_connected
>
0
)
{
if
(
!
xprt_test_and_set_connected
(
xprt
))
xprt_wake_pending_tasks
(
xprt
,
0
);
}
else
{
if
(
xprt_test_and_clear_connected
(
xprt
))
xprt_wake_pending_tasks
(
xprt
,
ep
->
rep_connected
);
xprt_wake_pending_tasks
(
xprt
,
-
ENOTCONN
);
}
spin_unlock_bh
(
&
xprt
->
transport_lock
);
}
...
...
@@ -792,14 +805,20 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
((
unsigned
char
*
)
iptr
-
(
unsigned
char
*
)
headerp
);
status
=
rep
->
rr_len
+
rdmalen
;
r_xprt
->
rx_stats
.
total_rdma_reply
+=
rdmalen
;
/* special case - last chunk may omit padding */
if
(
rdmalen
&=
3
)
{
rdmalen
=
4
-
rdmalen
;
status
+=
rdmalen
;
}
}
else
{
/* else ordinary inline */
rdmalen
=
0
;
iptr
=
(
__be32
*
)((
unsigned
char
*
)
headerp
+
28
);
rep
->
rr_len
-=
28
;
/*sizeof *headerp;*/
status
=
rep
->
rr_len
;
}
/* Fix up the rpc results for upper layer */
rpcrdma_inline_fixup
(
rqst
,
(
char
*
)
iptr
,
rep
->
rr_len
);
rpcrdma_inline_fixup
(
rqst
,
(
char
*
)
iptr
,
rep
->
rr_len
,
rdmalen
);
break
;
case
htonl
(
RDMA_NOMSG
):
...
...
net/sunrpc/xprtrdma/transport.c
View file @
6925bac1
...
...
@@ -70,11 +70,8 @@ static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE;
static
unsigned
int
xprt_rdma_max_inline_read
=
RPCRDMA_DEF_INLINE
;
static
unsigned
int
xprt_rdma_max_inline_write
=
RPCRDMA_DEF_INLINE
;
static
unsigned
int
xprt_rdma_inline_write_padding
;
#if !RPCRDMA_PERSISTENT_REGISTRATION
static
unsigned
int
xprt_rdma_memreg_strategy
=
RPCRDMA_REGISTER
;
/* FMR? */
#else
static
unsigned
int
xprt_rdma_memreg_strategy
=
RPCRDMA_ALLPHYSICAL
;
#endif
static
unsigned
int
xprt_rdma_memreg_strategy
=
RPCRDMA_FRMR
;
int
xprt_rdma_pad_optimize
=
0
;
#ifdef RPC_DEBUG
...
...
@@ -139,6 +136,14 @@ static ctl_table xr_tunables_table[] = {
.
extra1
=
&
min_memreg
,
.
extra2
=
&
max_memreg
,
},
{
.
ctl_name
=
CTL_UNNUMBERED
,
.
procname
=
"rdma_pad_optimize"
,
.
data
=
&
xprt_rdma_pad_optimize
,
.
maxlen
=
sizeof
(
unsigned
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
,
},
{
.
ctl_name
=
0
,
},
...
...
@@ -458,6 +463,8 @@ xprt_rdma_close(struct rpc_xprt *xprt)
struct
rpcrdma_xprt
*
r_xprt
=
rpcx_to_rdmax
(
xprt
);
dprintk
(
"RPC: %s: closing
\n
"
,
__func__
);
if
(
r_xprt
->
rx_ep
.
rep_connected
>
0
)
xprt
->
reestablish_timeout
=
0
;
xprt_disconnect_done
(
xprt
);
(
void
)
rpcrdma_ep_disconnect
(
&
r_xprt
->
rx_ep
,
&
r_xprt
->
rx_ia
);
}
...
...
@@ -485,6 +492,11 @@ xprt_rdma_connect(struct rpc_task *task)
/* Reconnect */
schedule_delayed_work
(
&
r_xprt
->
rdma_connect
,
xprt
->
reestablish_timeout
);
xprt
->
reestablish_timeout
<<=
1
;
if
(
xprt
->
reestablish_timeout
>
(
30
*
HZ
))
xprt
->
reestablish_timeout
=
(
30
*
HZ
);
else
if
(
xprt
->
reestablish_timeout
<
(
5
*
HZ
))
xprt
->
reestablish_timeout
=
(
5
*
HZ
);
}
else
{
schedule_delayed_work
(
&
r_xprt
->
rdma_connect
,
0
);
if
(
!
RPC_IS_ASYNC
(
task
))
...
...
@@ -591,6 +603,7 @@ xprt_rdma_allocate(struct rpc_task *task, size_t size)
}
dprintk
(
"RPC: %s: size %zd, request 0x%p
\n
"
,
__func__
,
size
,
req
);
out:
req
->
rl_connect_cookie
=
0
;
/* our reserved value */
return
req
->
rl_xdr_buf
;
outfail:
...
...
@@ -694,13 +707,21 @@ xprt_rdma_send_request(struct rpc_task *task)
req
->
rl_reply
->
rr_xprt
=
xprt
;
}
if
(
rpcrdma_ep_post
(
&
r_xprt
->
rx_ia
,
&
r_xprt
->
rx_ep
,
req
))
{
xprt_disconnect_done
(
xprt
);
return
-
ENOTCONN
;
/* implies disconnect */
}
/* Must suppress retransmit to maintain credits */
if
(
req
->
rl_connect_cookie
==
xprt
->
connect_cookie
)
goto
drop_connection
;
req
->
rl_connect_cookie
=
xprt
->
connect_cookie
;
if
(
rpcrdma_ep_post
(
&
r_xprt
->
rx_ia
,
&
r_xprt
->
rx_ep
,
req
))
goto
drop_connection
;
task
->
tk_bytes_sent
+=
rqst
->
rq_snd_buf
.
len
;
rqst
->
rq_bytes_sent
=
0
;
return
0
;
drop_connection:
xprt_disconnect_done
(
xprt
);
return
-
ENOTCONN
;
/* implies disconnect */
}
static
void
xprt_rdma_print_stats
(
struct
rpc_xprt
*
xprt
,
struct
seq_file
*
seq
)
...
...
@@ -770,7 +791,7 @@ static void __exit xprt_rdma_cleanup(void)
{
int
rc
;
dprintk
(
"RPCRDMA Module Removed, deregister RPC RDMA transport
\n
"
);
dprintk
(
KERN_INFO
"RPCRDMA Module Removed, deregister RPC RDMA transport
\n
"
);
#ifdef RPC_DEBUG
if
(
sunrpc_table_header
)
{
unregister_sysctl_table
(
sunrpc_table_header
);
...
...
net/sunrpc/xprtrdma/verbs.c
View file @
6925bac1
This diff is collapsed.
Click to expand it.
net/sunrpc/xprtrdma/xprt_rdma.h
View file @
6925bac1
...
...
@@ -51,6 +51,9 @@
#include <linux/sunrpc/rpc_rdma.h>
/* RPC/RDMA protocol */
#include <linux/sunrpc/xprtrdma.h>
/* xprt parameters */
#define RDMA_RESOLVE_TIMEOUT (5000)
/* 5 seconds */
#define RDMA_CONNECT_RETRY_MAX (2)
/* retries if no listener backlog */
/*
* Interface Adapter -- one per transport instance
*/
...
...
@@ -58,6 +61,8 @@ struct rpcrdma_ia {
struct
rdma_cm_id
*
ri_id
;
struct
ib_pd
*
ri_pd
;
struct
ib_mr
*
ri_bind_mem
;
u32
ri_dma_lkey
;
int
ri_have_dma_lkey
;
struct
completion
ri_done
;
int
ri_async_rc
;
enum
rpcrdma_memreg
ri_memreg_strategy
;
...
...
@@ -156,6 +161,10 @@ struct rpcrdma_mr_seg { /* chunk descriptors */
union
{
struct
ib_mw
*
mw
;
struct
ib_fmr
*
fmr
;
struct
{
struct
ib_fast_reg_page_list
*
fr_pgl
;
struct
ib_mr
*
fr_mr
;
}
frmr
;
}
r
;
struct
list_head
mw_list
;
}
*
rl_mw
;
...
...
@@ -175,6 +184,7 @@ struct rpcrdma_req {
size_t
rl_size
;
/* actual length of buffer */
unsigned
int
rl_niovs
;
/* 0, 2 or 4 */
unsigned
int
rl_nchunks
;
/* non-zero if chunks */
unsigned
int
rl_connect_cookie
;
/* retry detection */
struct
rpcrdma_buffer
*
rl_buffer
;
/* home base for this structure */
struct
rpcrdma_rep
*
rl_reply
;
/* holder for reply buffer */
struct
rpcrdma_mr_seg
rl_segments
[
RPCRDMA_MAX_SEGS
];
/* chunk segments */
...
...
@@ -198,7 +208,7 @@ struct rpcrdma_buffer {
atomic_t
rb_credits
;
/* most recent server credits */
unsigned
long
rb_cwndscale
;
/* cached framework rpc_cwndscale */
int
rb_max_requests
;
/* client max requests */
struct
list_head
rb_mws
;
/* optional memory windows/fmrs */
struct
list_head
rb_mws
;
/* optional memory windows/fmrs
/frmrs
*/
int
rb_send_index
;
struct
rpcrdma_req
**
rb_send_bufs
;
int
rb_recv_index
;
...
...
@@ -273,6 +283,11 @@ struct rpcrdma_xprt {
#define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, xprt)
#define rpcx_to_rdmad(x) (rpcx_to_rdmax(x)->rx_data)
/* Setting this to 0 ensures interoperability with early servers.
* Setting this to 1 enhances certain unaligned read/write performance.
* Default is 0, see sysctl entry and rpc_rdma.c rpcrdma_convert_iovs() */
extern
int
xprt_rdma_pad_optimize
;
/*
* Interface Adapter calls - xprtrdma/verbs.c
*/
...
...
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