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
bd0f725c
Commit
bd0f725c
authored
Mar 17, 2014
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'devel' into linux-next
parents
2ca310fc
fdb63dcd
Changes
17
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
310 additions
and
228 deletions
+310
-228
fs/nfs/callback_proc.c
fs/nfs/callback_proc.c
+12
-7
fs/nfs/dir.c
fs/nfs/dir.c
+49
-6
fs/nfs/inode.c
fs/nfs/inode.c
+27
-7
fs/nfs/internal.h
fs/nfs/internal.h
+8
-0
fs/nfs/nfs3proc.c
fs/nfs/nfs3proc.c
+0
-36
fs/nfs/nfs4_fs.h
fs/nfs/nfs4_fs.h
+11
-0
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+75
-79
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+1
-1
fs/nfs/pnfs.c
fs/nfs/pnfs.c
+16
-1
fs/nfs/proc.c
fs/nfs/proc.c
+0
-25
fs/nfs/unlink.c
fs/nfs/unlink.c
+30
-5
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+1
-1
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+1
-2
include/linux/sunrpc/bc_xprt.h
include/linux/sunrpc/bc_xprt.h
+2
-1
net/sunrpc/backchannel_rqst.c
net/sunrpc/backchannel_rqst.c
+64
-29
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+5
-8
net/sunrpc/xprtsock.c
net/sunrpc/xprtsock.c
+8
-20
No files found.
fs/nfs/callback_proc.c
View file @
bd0f725c
...
...
@@ -112,7 +112,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
* TODO: keep track of all layouts (and delegations) in a hash table
* hashed by filehandle.
*/
static
struct
pnfs_layout_hdr
*
get_layout_by_fh_locked
(
struct
nfs_client
*
clp
,
struct
nfs_fh
*
fh
)
static
struct
pnfs_layout_hdr
*
get_layout_by_fh_locked
(
struct
nfs_client
*
clp
,
struct
nfs_fh
*
fh
,
nfs4_stateid
*
stateid
)
{
struct
nfs_server
*
server
;
struct
inode
*
ino
;
...
...
@@ -120,17 +121,19 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
list_for_each_entry_rcu
(
server
,
&
clp
->
cl_superblocks
,
client_link
)
{
list_for_each_entry
(
lo
,
&
server
->
layouts
,
plh_layouts
)
{
if
(
!
nfs4_stateid_match_other
(
&
lo
->
plh_stateid
,
stateid
))
continue
;
if
(
nfs_compare_fh
(
fh
,
&
NFS_I
(
lo
->
plh_inode
)
->
fh
))
continue
;
ino
=
igrab
(
lo
->
plh_inode
);
if
(
!
ino
)
continue
;
break
;
spin_lock
(
&
ino
->
i_lock
);
/* Is this layout in the process of being freed? */
if
(
NFS_I
(
ino
)
->
layout
!=
lo
)
{
spin_unlock
(
&
ino
->
i_lock
);
iput
(
ino
);
continue
;
break
;
}
pnfs_get_layout_hdr
(
lo
);
spin_unlock
(
&
ino
->
i_lock
);
...
...
@@ -141,13 +144,14 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
return
NULL
;
}
static
struct
pnfs_layout_hdr
*
get_layout_by_fh
(
struct
nfs_client
*
clp
,
struct
nfs_fh
*
fh
)
static
struct
pnfs_layout_hdr
*
get_layout_by_fh
(
struct
nfs_client
*
clp
,
struct
nfs_fh
*
fh
,
nfs4_stateid
*
stateid
)
{
struct
pnfs_layout_hdr
*
lo
;
spin_lock
(
&
clp
->
cl_lock
);
rcu_read_lock
();
lo
=
get_layout_by_fh_locked
(
clp
,
fh
);
lo
=
get_layout_by_fh_locked
(
clp
,
fh
,
stateid
);
rcu_read_unlock
();
spin_unlock
(
&
clp
->
cl_lock
);
...
...
@@ -162,9 +166,9 @@ static u32 initiate_file_draining(struct nfs_client *clp,
u32
rv
=
NFS4ERR_NOMATCHING_LAYOUT
;
LIST_HEAD
(
free_me_list
);
lo
=
get_layout_by_fh
(
clp
,
&
args
->
cbl_fh
);
lo
=
get_layout_by_fh
(
clp
,
&
args
->
cbl_fh
,
&
args
->
cbl_stateid
);
if
(
!
lo
)
return
NFS4ERR_NOMATCHING_LAYOUT
;
goto
out
;
ino
=
lo
->
plh_inode
;
spin_lock
(
&
ino
->
i_lock
);
...
...
@@ -179,6 +183,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
pnfs_free_lseg_list
(
&
free_me_list
);
pnfs_put_layout_hdr
(
lo
);
iput
(
ino
);
out:
return
rv
;
}
...
...
fs/nfs/dir.c
View file @
bd0f725c
...
...
@@ -69,21 +69,28 @@ const struct address_space_operations nfs_dir_aops = {
static
struct
nfs_open_dir_context
*
alloc_nfs_open_dir_context
(
struct
inode
*
dir
,
struct
rpc_cred
*
cred
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
dir
);
struct
nfs_open_dir_context
*
ctx
;
ctx
=
kmalloc
(
sizeof
(
*
ctx
),
GFP_KERNEL
);
if
(
ctx
!=
NULL
)
{
ctx
->
duped
=
0
;
ctx
->
attr_gencount
=
NFS_I
(
dir
)
->
attr_gencount
;
ctx
->
attr_gencount
=
nfsi
->
attr_gencount
;
ctx
->
dir_cookie
=
0
;
ctx
->
dup_cookie
=
0
;
ctx
->
cred
=
get_rpccred
(
cred
);
spin_lock
(
&
dir
->
i_lock
);
list_add
(
&
ctx
->
list
,
&
nfsi
->
open_files
);
spin_unlock
(
&
dir
->
i_lock
);
return
ctx
;
}
return
ERR_PTR
(
-
ENOMEM
);
}
static
void
put_nfs_open_dir_context
(
struct
nfs_open_dir_context
*
ctx
)
static
void
put_nfs_open_dir_context
(
struct
inode
*
dir
,
struct
nfs_open_dir_context
*
ctx
)
{
spin_lock
(
&
dir
->
i_lock
);
list_del
(
&
ctx
->
list
);
spin_unlock
(
&
dir
->
i_lock
);
put_rpccred
(
ctx
->
cred
);
kfree
(
ctx
);
}
...
...
@@ -126,7 +133,7 @@ nfs_opendir(struct inode *inode, struct file *filp)
static
int
nfs_closedir
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
put_nfs_open_dir_context
(
filp
->
private_data
);
put_nfs_open_dir_context
(
filp
->
f_path
.
dentry
->
d_inode
,
filp
->
private_data
);
return
0
;
}
...
...
@@ -437,6 +444,22 @@ void nfs_advise_use_readdirplus(struct inode *dir)
set_bit
(
NFS_INO_ADVISE_RDPLUS
,
&
NFS_I
(
dir
)
->
flags
);
}
/*
* This function is mainly for use by nfs_getattr().
*
* If this is an 'ls -l', we want to force use of readdirplus.
* Do this by checking if there is an active file descriptor
* and calling nfs_advise_use_readdirplus, then forcing a
* cache flush.
*/
void
nfs_force_use_readdirplus
(
struct
inode
*
dir
)
{
if
(
!
list_empty
(
&
NFS_I
(
dir
)
->
open_files
))
{
nfs_advise_use_readdirplus
(
dir
);
nfs_zap_mapping
(
dir
,
dir
->
i_mapping
);
}
}
static
void
nfs_prime_dcache
(
struct
dentry
*
parent
,
struct
nfs_entry
*
entry
)
{
...
...
@@ -815,6 +838,17 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc)
goto
out
;
}
static
bool
nfs_dir_mapping_need_revalidate
(
struct
inode
*
dir
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
dir
);
if
(
nfs_attribute_cache_expired
(
dir
))
return
true
;
if
(
nfsi
->
cache_validity
&
NFS_INO_INVALID_DATA
)
return
true
;
return
false
;
}
/* The file offset position represents the dirent entry number. A
last cookie cache takes care of the common case of reading the
whole directory.
...
...
@@ -847,7 +881,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
desc
->
plus
=
nfs_use_readdirplus
(
inode
,
ctx
)
?
1
:
0
;
nfs_block_sillyrename
(
dentry
);
if
(
ctx
->
pos
==
0
||
nfs_
attribute_cache_expired
(
inode
))
if
(
ctx
->
pos
==
0
||
nfs_
dir_mapping_need_revalidate
(
inode
))
res
=
nfs_revalidate_mapping
(
inode
,
file
->
f_mapping
);
if
(
res
<
0
)
goto
out
;
...
...
@@ -1906,6 +1940,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct
inode
*
old_inode
=
old_dentry
->
d_inode
;
struct
inode
*
new_inode
=
new_dentry
->
d_inode
;
struct
dentry
*
dentry
=
NULL
,
*
rehash
=
NULL
;
struct
rpc_task
*
task
;
int
error
=
-
EBUSY
;
dfprintk
(
VFS
,
"NFS: rename(%pd2 -> %pd2, ct=%d)
\n
"
,
...
...
@@ -1953,8 +1988,16 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if
(
new_inode
!=
NULL
)
NFS_PROTO
(
new_inode
)
->
return_delegation
(
new_inode
);
error
=
NFS_PROTO
(
old_dir
)
->
rename
(
old_dir
,
&
old_dentry
->
d_name
,
new_dir
,
&
new_dentry
->
d_name
);
task
=
nfs_async_rename
(
old_dir
,
new_dir
,
old_dentry
,
new_dentry
,
NULL
);
if
(
IS_ERR
(
task
))
{
error
=
PTR_ERR
(
task
);
goto
out
;
}
error
=
rpc_wait_for_completion_task
(
task
);
if
(
error
==
0
)
error
=
task
->
tk_status
;
rpc_put_task
(
task
);
nfs_mark_for_revalidate
(
old_inode
);
out:
if
(
rehash
)
...
...
fs/nfs/inode.c
View file @
bd0f725c
...
...
@@ -588,6 +588,25 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
}
EXPORT_SYMBOL_GPL
(
nfs_setattr_update_inode
);
static
void
nfs_request_parent_use_readdirplus
(
struct
dentry
*
dentry
)
{
struct
dentry
*
parent
;
parent
=
dget_parent
(
dentry
);
nfs_force_use_readdirplus
(
parent
->
d_inode
);
dput
(
parent
);
}
static
bool
nfs_need_revalidate_inode
(
struct
inode
*
inode
)
{
if
(
NFS_I
(
inode
)
->
cache_validity
&
(
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_LABEL
))
return
true
;
if
(
nfs_attribute_cache_expired
(
inode
))
return
true
;
return
false
;
}
int
nfs_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
struct
kstat
*
stat
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
...
...
@@ -616,10 +635,13 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
((
mnt
->
mnt_flags
&
MNT_NODIRATIME
)
&&
S_ISDIR
(
inode
->
i_mode
)))
need_atime
=
0
;
if
(
need_atime
)
err
=
__nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
else
err
=
nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
if
(
need_atime
||
nfs_need_revalidate_inode
(
inode
))
{
struct
nfs_server
*
server
=
NFS_SERVER
(
inode
);
if
(
server
->
caps
&
NFS_CAP_READDIRPLUS
)
nfs_request_parent_use_readdirplus
(
dentry
);
err
=
__nfs_revalidate_inode
(
server
,
inode
);
}
if
(
!
err
)
{
generic_fillattr
(
inode
,
stat
);
stat
->
ino
=
nfs_compat_user_ino64
(
NFS_FILEID
(
inode
));
...
...
@@ -961,9 +983,7 @@ int nfs_attribute_cache_expired(struct inode *inode)
*/
int
nfs_revalidate_inode
(
struct
nfs_server
*
server
,
struct
inode
*
inode
)
{
if
(
!
(
NFS_I
(
inode
)
->
cache_validity
&
(
NFS_INO_INVALID_ATTR
|
NFS_INO_INVALID_LABEL
))
&&
!
nfs_attribute_cache_expired
(
inode
))
if
(
!
nfs_need_revalidate_inode
(
inode
))
return
NFS_STALE
(
inode
)
?
-
ESTALE
:
0
;
return
__nfs_revalidate_inode
(
server
,
inode
);
}
...
...
fs/nfs/internal.h
View file @
bd0f725c
...
...
@@ -301,6 +301,7 @@ extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
const
char
*
ip_addr
);
/* dir.c */
extern
void
nfs_force_use_readdirplus
(
struct
inode
*
dir
);
extern
unsigned
long
nfs_access_cache_count
(
struct
shrinker
*
shrink
,
struct
shrink_control
*
sc
);
extern
unsigned
long
nfs_access_cache_scan
(
struct
shrinker
*
shrink
,
...
...
@@ -474,6 +475,13 @@ extern int nfs_migrate_page(struct address_space *,
#define nfs_migrate_page NULL
#endif
/* unlink.c */
extern
struct
rpc_task
*
nfs_async_rename
(
struct
inode
*
old_dir
,
struct
inode
*
new_dir
,
struct
dentry
*
old_dentry
,
struct
dentry
*
new_dentry
,
void
(
*
complete
)(
struct
rpc_task
*
,
struct
nfs_renamedata
*
));
extern
int
nfs_sillyrename
(
struct
inode
*
dir
,
struct
dentry
*
dentry
);
/* direct.c */
void
nfs_init_cinfo_from_dreq
(
struct
nfs_commit_info
*
cinfo
,
struct
nfs_direct_req
*
dreq
);
...
...
fs/nfs/nfs3proc.c
View file @
bd0f725c
...
...
@@ -477,41 +477,6 @@ nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
return
1
;
}
static
int
nfs3_proc_rename
(
struct
inode
*
old_dir
,
struct
qstr
*
old_name
,
struct
inode
*
new_dir
,
struct
qstr
*
new_name
)
{
struct
nfs_renameargs
arg
=
{
.
old_dir
=
NFS_FH
(
old_dir
),
.
old_name
=
old_name
,
.
new_dir
=
NFS_FH
(
new_dir
),
.
new_name
=
new_name
,
};
struct
nfs_renameres
res
;
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_RENAME
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
int
status
=
-
ENOMEM
;
dprintk
(
"NFS call rename %s -> %s
\n
"
,
old_name
->
name
,
new_name
->
name
);
res
.
old_fattr
=
nfs_alloc_fattr
();
res
.
new_fattr
=
nfs_alloc_fattr
();
if
(
res
.
old_fattr
==
NULL
||
res
.
new_fattr
==
NULL
)
goto
out
;
status
=
rpc_call_sync
(
NFS_CLIENT
(
old_dir
),
&
msg
,
0
);
nfs_post_op_update_inode
(
old_dir
,
res
.
old_fattr
);
nfs_post_op_update_inode
(
new_dir
,
res
.
new_fattr
);
out:
nfs_free_fattr
(
res
.
old_fattr
);
nfs_free_fattr
(
res
.
new_fattr
);
dprintk
(
"NFS reply rename: %d
\n
"
,
status
);
return
status
;
}
static
int
nfs3_proc_link
(
struct
inode
*
inode
,
struct
inode
*
dir
,
struct
qstr
*
name
)
{
...
...
@@ -967,7 +932,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
.
unlink_setup
=
nfs3_proc_unlink_setup
,
.
unlink_rpc_prepare
=
nfs3_proc_unlink_rpc_prepare
,
.
unlink_done
=
nfs3_proc_unlink_done
,
.
rename
=
nfs3_proc_rename
,
.
rename_setup
=
nfs3_proc_rename_setup
,
.
rename_rpc_prepare
=
nfs3_proc_rename_rpc_prepare
,
.
rename_done
=
nfs3_proc_rename_done
,
...
...
fs/nfs/nfs4_fs.h
View file @
bd0f725c
...
...
@@ -427,6 +427,7 @@ extern void nfs4_close_sync(struct nfs4_state *, fmode_t);
extern
void
nfs4_state_set_mode_locked
(
struct
nfs4_state
*
,
fmode_t
);
extern
void
nfs_inode_find_state_and_recover
(
struct
inode
*
inode
,
const
nfs4_stateid
*
stateid
);
extern
int
nfs4_state_mark_reclaim_nograce
(
struct
nfs_client
*
,
struct
nfs4_state
*
);
extern
void
nfs4_schedule_lease_recovery
(
struct
nfs_client
*
);
extern
int
nfs4_wait_clnt_recover
(
struct
nfs_client
*
clp
);
extern
int
nfs4_client_recover_expired_lease
(
struct
nfs_client
*
clp
);
...
...
@@ -500,6 +501,16 @@ static inline bool nfs4_stateid_match(const nfs4_stateid *dst, const nfs4_statei
return
memcmp
(
dst
,
src
,
sizeof
(
*
dst
))
==
0
;
}
static
inline
bool
nfs4_stateid_match_other
(
const
nfs4_stateid
*
dst
,
const
nfs4_stateid
*
src
)
{
return
memcmp
(
dst
->
other
,
src
->
other
,
NFS4_STATEID_OTHER_SIZE
)
==
0
;
}
static
inline
bool
nfs4_stateid_is_newer
(
const
nfs4_stateid
*
s1
,
const
nfs4_stateid
*
s2
)
{
return
(
s32
)(
be32_to_cpu
(
s1
->
seqid
)
-
be32_to_cpu
(
s2
->
seqid
))
>
0
;
}
static
inline
bool
nfs4_valid_open_stateid
(
const
struct
nfs4_state
*
state
)
{
return
test_bit
(
NFS_STATE_RECOVERY_FAILED
,
&
state
->
flags
)
==
0
;
...
...
fs/nfs/nfs4proc.c
View file @
bd0f725c
...
...
@@ -1137,12 +1137,71 @@ static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
nfs4_state_set_mode_locked
(
state
,
state
->
state
|
fmode
);
}
static
void
nfs_set_open_stateid_locked
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
stateid
,
fmode_t
fmode
)
static
void
nfs_test_and_clear_all_open_stateid
(
struct
nfs4_state
*
state
)
{
struct
nfs_client
*
clp
=
state
->
owner
->
so_server
->
nfs_client
;
bool
need_recover
=
false
;
if
(
test_and_clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
)
&&
state
->
n_rdonly
)
need_recover
=
true
;
if
(
test_and_clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
)
&&
state
->
n_wronly
)
need_recover
=
true
;
if
(
test_and_clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
)
&&
state
->
n_rdwr
)
need_recover
=
true
;
if
(
need_recover
)
nfs4_state_mark_reclaim_nograce
(
clp
,
state
);
}
static
bool
nfs_need_update_open_stateid
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
stateid
)
{
if
(
test_and_set_bit
(
NFS_OPEN_STATE
,
&
state
->
flags
)
==
0
)
return
true
;
if
(
!
nfs4_stateid_match_other
(
stateid
,
&
state
->
open_stateid
))
{
nfs_test_and_clear_all_open_stateid
(
state
);
return
true
;
}
if
(
nfs4_stateid_is_newer
(
stateid
,
&
state
->
open_stateid
))
return
true
;
return
false
;
}
static
void
nfs_clear_open_stateid_locked
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
stateid
,
fmode_t
fmode
)
{
clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
switch
(
fmode
&
(
FMODE_READ
|
FMODE_WRITE
))
{
case
FMODE_WRITE
:
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
break
;
case
FMODE_READ
:
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
break
;
case
0
:
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_OPEN_STATE
,
&
state
->
flags
);
}
if
(
stateid
==
NULL
)
return
;
if
(
!
nfs_need_update_open_stateid
(
state
,
stateid
))
return
;
if
(
test_bit
(
NFS_DELEGATED_STATE
,
&
state
->
flags
)
==
0
)
nfs4_stateid_copy
(
&
state
->
stateid
,
stateid
);
nfs4_stateid_copy
(
&
state
->
open_stateid
,
stateid
);
set_bit
(
NFS_OPEN_STATE
,
&
state
->
flags
);
}
static
void
nfs_clear_open_stateid
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
stateid
,
fmode_t
fmode
)
{
write_seqlock
(
&
state
->
seqlock
);
nfs_clear_open_stateid_locked
(
state
,
stateid
,
fmode
);
write_sequnlock
(
&
state
->
seqlock
);
if
(
test_bit
(
NFS_STATE_RECLAIM_NOGRACE
,
&
state
->
flags
))
nfs4_schedule_state_manager
(
state
->
owner
->
so_server
->
nfs_client
);
}
static
void
nfs_set_open_stateid_locked
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
stateid
,
fmode_t
fmode
)
{
switch
(
fmode
)
{
case
FMODE_READ
:
set_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
...
...
@@ -1153,13 +1212,11 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *
case
FMODE_READ
|
FMODE_WRITE
:
set_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
}
}
static
void
nfs_set_open_stateid
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
stateid
,
fmode_t
fmode
)
{
write_seqlock
(
&
state
->
seqlock
);
nfs_set_open_stateid_locked
(
state
,
stateid
,
fmode
);
write_sequnlock
(
&
state
->
seqlock
);
if
(
!
nfs_need_update_open_stateid
(
state
,
stateid
))
return
;
if
(
test_bit
(
NFS_DELEGATED_STATE
,
&
state
->
flags
)
==
0
)
nfs4_stateid_copy
(
&
state
->
stateid
,
stateid
);
nfs4_stateid_copy
(
&
state
->
open_stateid
,
stateid
);
}
static
void
__update_open_stateid
(
struct
nfs4_state
*
state
,
nfs4_stateid
*
open_stateid
,
const
nfs4_stateid
*
deleg_stateid
,
fmode_t
fmode
)
...
...
@@ -1217,6 +1274,8 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat
__update_open_stateid
(
state
,
open_stateid
,
NULL
,
fmode
);
ret
=
1
;
}
if
(
test_bit
(
NFS_STATE_RECLAIM_NOGRACE
,
&
state
->
flags
))
nfs4_schedule_state_manager
(
state
->
owner
->
so_server
->
nfs_client
);
return
ret
;
}
...
...
@@ -1450,12 +1509,15 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
struct
nfs4_state
*
newstate
;
int
ret
;
/* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
/* memory barrier prior to reading state->n_* */
clear_bit
(
NFS_DELEGATED_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_OPEN_STATE
,
&
state
->
flags
);
smp_rmb
();
if
(
state
->
n_rdwr
!=
0
)
{
clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
ret
=
nfs4_open_recover_helper
(
opendata
,
FMODE_READ
|
FMODE_WRITE
,
&
newstate
);
if
(
ret
!=
0
)
return
ret
;
...
...
@@ -1463,7 +1525,6 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
return
-
ESTALE
;
}
if
(
state
->
n_wronly
!=
0
)
{
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
ret
=
nfs4_open_recover_helper
(
opendata
,
FMODE_WRITE
,
&
newstate
);
if
(
ret
!=
0
)
return
ret
;
...
...
@@ -1471,7 +1532,6 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
return
-
ESTALE
;
}
if
(
state
->
n_rdonly
!=
0
)
{
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
ret
=
nfs4_open_recover_helper
(
opendata
,
FMODE_READ
,
&
newstate
);
if
(
ret
!=
0
)
return
ret
;
...
...
@@ -2479,26 +2539,6 @@ static void nfs4_free_closedata(void *data)
kfree
(
calldata
);
}
static
void
nfs4_close_clear_stateid_flags
(
struct
nfs4_state
*
state
,
fmode_t
fmode
)
{
spin_lock
(
&
state
->
owner
->
so_lock
);
clear_bit
(
NFS_O_RDWR_STATE
,
&
state
->
flags
);
switch
(
fmode
&
(
FMODE_READ
|
FMODE_WRITE
))
{
case
FMODE_WRITE
:
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
break
;
case
FMODE_READ
:
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
break
;
case
0
:
clear_bit
(
NFS_O_RDONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_O_WRONLY_STATE
,
&
state
->
flags
);
clear_bit
(
NFS_OPEN_STATE
,
&
state
->
flags
);
}
spin_unlock
(
&
state
->
owner
->
so_lock
);
}
static
void
nfs4_close_done
(
struct
rpc_task
*
task
,
void
*
data
)
{
struct
nfs4_closedata
*
calldata
=
data
;
...
...
@@ -2517,9 +2557,9 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
if
(
calldata
->
roc
)
pnfs_roc_set_barrier
(
state
->
inode
,
calldata
->
roc_barrier
);
nfs_
set
_open_stateid
(
state
,
&
calldata
->
res
.
stateid
,
0
);
nfs_
clear
_open_stateid
(
state
,
&
calldata
->
res
.
stateid
,
0
);
renew_lease
(
server
,
calldata
->
timestamp
);
break
;
goto
out_release
;
case
-
NFS4ERR_ADMIN_REVOKED
:
case
-
NFS4ERR_STALE_STATEID
:
case
-
NFS4ERR_OLD_STATEID
:
...
...
@@ -2533,7 +2573,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
goto
out_release
;
}
}
nfs
4_close_clear_stateid_flags
(
state
,
calldata
->
arg
.
fmode
);
nfs
_clear_open_stateid
(
state
,
NULL
,
calldata
->
arg
.
fmode
);
out_release:
nfs_release_seqid
(
calldata
->
arg
.
seqid
);
nfs_refresh_inode
(
calldata
->
inode
,
calldata
->
res
.
fattr
);
...
...
@@ -3507,49 +3547,6 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
return
1
;
}
static
int
_nfs4_proc_rename
(
struct
inode
*
old_dir
,
struct
qstr
*
old_name
,
struct
inode
*
new_dir
,
struct
qstr
*
new_name
)
{
struct
nfs_server
*
server
=
NFS_SERVER
(
old_dir
);
struct
nfs_renameargs
arg
=
{
.
old_dir
=
NFS_FH
(
old_dir
),
.
new_dir
=
NFS_FH
(
new_dir
),
.
old_name
=
old_name
,
.
new_name
=
new_name
,
};
struct
nfs_renameres
res
=
{
.
server
=
server
,
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs4_procedures
[
NFSPROC4_CLNT_RENAME
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
int
status
=
-
ENOMEM
;
status
=
nfs4_call_sync
(
server
->
client
,
server
,
&
msg
,
&
arg
.
seq_args
,
&
res
.
seq_res
,
1
);
if
(
!
status
)
{
update_changeattr
(
old_dir
,
&
res
.
old_cinfo
);
update_changeattr
(
new_dir
,
&
res
.
new_cinfo
);
}
return
status
;
}
static
int
nfs4_proc_rename
(
struct
inode
*
old_dir
,
struct
qstr
*
old_name
,
struct
inode
*
new_dir
,
struct
qstr
*
new_name
)
{
struct
nfs4_exception
exception
=
{
};
int
err
;
do
{
err
=
_nfs4_proc_rename
(
old_dir
,
old_name
,
new_dir
,
new_name
);
trace_nfs4_rename
(
old_dir
,
old_name
,
new_dir
,
new_name
,
err
);
err
=
nfs4_handle_exception
(
NFS_SERVER
(
old_dir
),
err
,
&
exception
);
}
while
(
exception
.
retry
);
return
err
;
}
static
int
_nfs4_proc_link
(
struct
inode
*
inode
,
struct
inode
*
dir
,
struct
qstr
*
name
)
{
struct
nfs_server
*
server
=
NFS_SERVER
(
inode
);
...
...
@@ -8408,7 +8405,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.
unlink_setup
=
nfs4_proc_unlink_setup
,
.
unlink_rpc_prepare
=
nfs4_proc_unlink_rpc_prepare
,
.
unlink_done
=
nfs4_proc_unlink_done
,
.
rename
=
nfs4_proc_rename
,
.
rename_setup
=
nfs4_proc_rename_setup
,
.
rename_rpc_prepare
=
nfs4_proc_rename_rpc_prepare
,
.
rename_done
=
nfs4_proc_rename_done
,
...
...
fs/nfs/nfs4state.c
View file @
bd0f725c
...
...
@@ -1316,7 +1316,7 @@ static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_st
return
1
;
}
static
int
nfs4_state_mark_reclaim_nograce
(
struct
nfs_client
*
clp
,
struct
nfs4_state
*
state
)
int
nfs4_state_mark_reclaim_nograce
(
struct
nfs_client
*
clp
,
struct
nfs4_state
*
state
)
{
set_bit
(
NFS_STATE_RECLAIM_NOGRACE
,
&
state
->
flags
);
clear_bit
(
NFS_STATE_RECLAIM_REBOOT
,
&
state
->
flags
);
...
...
fs/nfs/pnfs.c
View file @
bd0f725c
...
...
@@ -662,7 +662,18 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
*/
static
bool
pnfs_seqid_is_newer
(
u32
s1
,
u32
s2
)
{
return
(
s32
)
s1
-
(
s32
)
s2
>
0
;
return
(
s32
)(
s1
-
s2
)
>
0
;
}
static
void
pnfs_verify_layout_stateid
(
struct
pnfs_layout_hdr
*
lo
,
const
nfs4_stateid
*
new
,
struct
list_head
*
free_me_list
)
{
if
(
nfs4_stateid_match_other
(
&
lo
->
plh_stateid
,
new
))
return
;
/* Layout is new! Kill existing layout segments */
pnfs_mark_matching_lsegs_invalid
(
lo
,
free_me_list
,
NULL
);
}
/* update lo->plh_stateid with new if is more recent */
...
...
@@ -1315,6 +1326,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
struct
nfs4_layoutget_res
*
res
=
&
lgp
->
res
;
struct
pnfs_layout_segment
*
lseg
;
struct
inode
*
ino
=
lo
->
plh_inode
;
LIST_HEAD
(
free_me
);
int
status
=
0
;
/* Inject layout blob into I/O device driver */
...
...
@@ -1341,6 +1353,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
goto
out_forget_reply
;
}
/* Check that the new stateid matches the old stateid */
pnfs_verify_layout_stateid
(
lo
,
&
res
->
stateid
,
&
free_me
);
/* Done processing layoutget. Set the layout stateid */
pnfs_set_layout_stateid
(
lo
,
&
res
->
stateid
,
false
);
...
...
@@ -1355,6 +1369,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
}
spin_unlock
(
&
ino
->
i_lock
);
pnfs_free_lseg_list
(
&
free_me
);
return
lseg
;
out:
return
ERR_PTR
(
status
);
...
...
fs/nfs/proc.c
View file @
bd0f725c
...
...
@@ -356,30 +356,6 @@ nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
return
1
;
}
static
int
nfs_proc_rename
(
struct
inode
*
old_dir
,
struct
qstr
*
old_name
,
struct
inode
*
new_dir
,
struct
qstr
*
new_name
)
{
struct
nfs_renameargs
arg
=
{
.
old_dir
=
NFS_FH
(
old_dir
),
.
old_name
=
old_name
,
.
new_dir
=
NFS_FH
(
new_dir
),
.
new_name
=
new_name
,
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs_procedures
[
NFSPROC_RENAME
],
.
rpc_argp
=
&
arg
,
};
int
status
;
dprintk
(
"NFS call rename %s -> %s
\n
"
,
old_name
->
name
,
new_name
->
name
);
status
=
rpc_call_sync
(
NFS_CLIENT
(
old_dir
),
&
msg
,
0
);
nfs_mark_for_revalidate
(
old_dir
);
nfs_mark_for_revalidate
(
new_dir
);
dprintk
(
"NFS reply rename: %d
\n
"
,
status
);
return
status
;
}
static
int
nfs_proc_link
(
struct
inode
*
inode
,
struct
inode
*
dir
,
struct
qstr
*
name
)
{
...
...
@@ -745,7 +721,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
.
unlink_setup
=
nfs_proc_unlink_setup
,
.
unlink_rpc_prepare
=
nfs_proc_unlink_rpc_prepare
,
.
unlink_done
=
nfs_proc_unlink_done
,
.
rename
=
nfs_proc_rename
,
.
rename_setup
=
nfs_proc_rename_setup
,
.
rename_rpc_prepare
=
nfs_proc_rename_rpc_prepare
,
.
rename_done
=
nfs_proc_rename_done
,
...
...
fs/nfs/unlink.c
View file @
bd0f725c
...
...
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/namei.h>
#include <linux/fsnotify.h>
#include "internal.h"
#include "nfs4_fs.h"
...
...
@@ -353,8 +354,8 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
return
;
}
if
(
task
->
tk_status
!=
0
)
nfs_cancel_async_unlink
(
old_dentry
);
if
(
data
->
complete
)
data
->
complete
(
task
,
data
);
}
/**
...
...
@@ -399,9 +400,10 @@ static const struct rpc_call_ops nfs_rename_ops = {
*
* It's expected that valid references to the dentries and inodes are held
*/
st
atic
st
ruct
rpc_task
*
struct
rpc_task
*
nfs_async_rename
(
struct
inode
*
old_dir
,
struct
inode
*
new_dir
,
struct
dentry
*
old_dentry
,
struct
dentry
*
new_dentry
)
struct
dentry
*
old_dentry
,
struct
dentry
*
new_dentry
,
void
(
*
complete
)(
struct
rpc_task
*
,
struct
nfs_renamedata
*
))
{
struct
nfs_renamedata
*
data
;
struct
rpc_message
msg
=
{
};
...
...
@@ -438,6 +440,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
data
->
new_dentry
=
dget
(
new_dentry
);
nfs_fattr_init
(
&
data
->
old_fattr
);
nfs_fattr_init
(
&
data
->
new_fattr
);
data
->
complete
=
complete
;
/* set up nfs_renameargs */
data
->
args
.
old_dir
=
NFS_FH
(
old_dir
);
...
...
@@ -456,6 +459,27 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
return
rpc_run_task
(
&
task_setup_data
);
}
/*
* Perform tasks needed when a sillyrename is done such as cancelling the
* queued async unlink if it failed.
*/
static
void
nfs_complete_sillyrename
(
struct
rpc_task
*
task
,
struct
nfs_renamedata
*
data
)
{
struct
dentry
*
dentry
=
data
->
old_dentry
;
if
(
task
->
tk_status
!=
0
)
{
nfs_cancel_async_unlink
(
dentry
);
return
;
}
/*
* vfs_unlink and the like do not issue this when a file is
* sillyrenamed, so do it here.
*/
fsnotify_nameremove
(
dentry
,
0
);
}
#define SILLYNAME_PREFIX ".nfs"
#define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1)
#define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1)
...
...
@@ -548,7 +572,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
}
/* run the rename task, undo unlink if it fails */
task
=
nfs_async_rename
(
dir
,
dir
,
dentry
,
sdentry
);
task
=
nfs_async_rename
(
dir
,
dir
,
dentry
,
sdentry
,
nfs_complete_sillyrename
);
if
(
IS_ERR
(
task
))
{
error
=
-
EBUSY
;
nfs_cancel_async_unlink
(
dentry
);
...
...
include/linux/nfs_fs.h
View file @
bd0f725c
...
...
@@ -92,6 +92,7 @@ struct nfs_open_context {
};
struct
nfs_open_dir_context
{
struct
list_head
list
;
struct
rpc_cred
*
cred
;
unsigned
long
attr_gencount
;
__u64
dir_cookie
;
...
...
@@ -510,7 +511,6 @@ extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
extern
void
nfs_wait_on_sillyrename
(
struct
dentry
*
dentry
);
extern
void
nfs_block_sillyrename
(
struct
dentry
*
dentry
);
extern
void
nfs_unblock_sillyrename
(
struct
dentry
*
dentry
);
extern
int
nfs_sillyrename
(
struct
inode
*
dir
,
struct
dentry
*
dentry
);
/*
* linux/fs/nfs/write.c
...
...
include/linux/nfs_xdr.h
View file @
bd0f725c
...
...
@@ -1402,6 +1402,7 @@ struct nfs_renamedata {
struct
inode
*
new_dir
;
struct
dentry
*
new_dentry
;
struct
nfs_fattr
new_fattr
;
void
(
*
complete
)(
struct
rpc_task
*
,
struct
nfs_renamedata
*
);
};
struct
nfs_access_entry
;
...
...
@@ -1444,8 +1445,6 @@ struct nfs_rpc_ops {
void
(
*
unlink_setup
)
(
struct
rpc_message
*
,
struct
inode
*
dir
);
void
(
*
unlink_rpc_prepare
)
(
struct
rpc_task
*
,
struct
nfs_unlinkdata
*
);
int
(
*
unlink_done
)
(
struct
rpc_task
*
,
struct
inode
*
);
int
(
*
rename
)
(
struct
inode
*
,
struct
qstr
*
,
struct
inode
*
,
struct
qstr
*
);
void
(
*
rename_setup
)
(
struct
rpc_message
*
msg
,
struct
inode
*
dir
);
void
(
*
rename_rpc_prepare
)(
struct
rpc_task
*
task
,
struct
nfs_renamedata
*
);
int
(
*
rename_done
)
(
struct
rpc_task
*
task
,
struct
inode
*
old_dir
,
struct
inode
*
new_dir
);
...
...
include/linux/sunrpc/bc_xprt.h
View file @
bd0f725c
...
...
@@ -32,7 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <linux/sunrpc/sched.h>
#ifdef CONFIG_SUNRPC_BACKCHANNEL
struct
rpc_rqst
*
xprt_alloc_bc_request
(
struct
rpc_xprt
*
xprt
);
struct
rpc_rqst
*
xprt_lookup_bc_request
(
struct
rpc_xprt
*
xprt
,
__be32
xid
);
void
xprt_complete_bc_request
(
struct
rpc_rqst
*
req
,
uint32_t
copied
);
void
xprt_free_bc_request
(
struct
rpc_rqst
*
req
);
int
xprt_setup_backchannel
(
struct
rpc_xprt
*
,
unsigned
int
min_reqs
);
void
xprt_destroy_backchannel
(
struct
rpc_xprt
*
,
unsigned
int
max_reqs
);
...
...
net/sunrpc/backchannel_rqst.c
View file @
bd0f725c
...
...
@@ -212,39 +212,23 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
}
EXPORT_SYMBOL_GPL
(
xprt_destroy_backchannel
);
/*
* One or more rpc_rqst structure have been preallocated during the
* backchannel setup. Buffer space for the send and private XDR buffers
* has been preallocated as well. Use xprt_alloc_bc_request to allocate
* to this request. Use xprt_free_bc_request to return it.
*
* We know that we're called in soft interrupt context, grab the spin_lock
* since there is no need to grab the bottom half spin_lock.
*
* Return an available rpc_rqst, otherwise NULL if non are available.
*/
struct
rpc_rqst
*
xprt_alloc_bc_request
(
struct
rpc_xprt
*
xprt
)
static
struct
rpc_rqst
*
xprt_alloc_bc_request
(
struct
rpc_xprt
*
xprt
,
__be32
xid
)
{
struct
rpc_rqst
*
req
;
struct
rpc_rqst
*
req
=
NULL
;
dprintk
(
"RPC: allocate a backchannel request
\n
"
);
spin_lock
(
&
xprt
->
bc_pa_lock
);
if
(
!
list_empty
(
&
xprt
->
bc_pa_list
))
{
if
(
list_empty
(
&
xprt
->
bc_pa_list
))
goto
not_found
;
req
=
list_first_entry
(
&
xprt
->
bc_pa_list
,
struct
rpc_rqst
,
rq_bc_pa_list
);
list_del
(
&
req
->
rq_bc_pa_list
);
}
else
{
req
=
NULL
;
}
spin_unlock
(
&
xprt
->
bc_pa_lock
);
if
(
req
!=
NULL
)
{
set_bit
(
RPC_BC_PA_IN_USE
,
&
req
->
rq_bc_pa_state
);
req
->
rq_reply_bytes_recvd
=
0
;
req
->
rq_bytes_sent
=
0
;
memcpy
(
&
req
->
rq_private_buf
,
&
req
->
rq_rcv_buf
,
sizeof
(
req
->
rq_private_buf
));
}
req
->
rq_xid
=
xid
;
req
->
rq_connect_cookie
=
xprt
->
connect_cookie
;
not_found:
dprintk
(
"RPC: backchannel req=%p
\n
"
,
req
);
return
req
;
}
...
...
@@ -259,6 +243,7 @@ void xprt_free_bc_request(struct rpc_rqst *req)
dprintk
(
"RPC: free backchannel req=%p
\n
"
,
req
);
req
->
rq_connect_cookie
=
xprt
->
connect_cookie
-
1
;
smp_mb__before_clear_bit
();
WARN_ON_ONCE
(
!
test_bit
(
RPC_BC_PA_IN_USE
,
&
req
->
rq_bc_pa_state
));
clear_bit
(
RPC_BC_PA_IN_USE
,
&
req
->
rq_bc_pa_state
);
...
...
@@ -281,7 +266,57 @@ void xprt_free_bc_request(struct rpc_rqst *req)
* may be reused by a new callback request.
*/
spin_lock_bh
(
&
xprt
->
bc_pa_lock
);
list_add
(
&
req
->
rq_bc_pa_list
,
&
xprt
->
bc_pa_list
);
list_add
_tail
(
&
req
->
rq_bc_pa_list
,
&
xprt
->
bc_pa_list
);
spin_unlock_bh
(
&
xprt
->
bc_pa_lock
);
}
/*
* One or more rpc_rqst structure have been preallocated during the
* backchannel setup. Buffer space for the send and private XDR buffers
* has been preallocated as well. Use xprt_alloc_bc_request to allocate
* to this request. Use xprt_free_bc_request to return it.
*
* We know that we're called in soft interrupt context, grab the spin_lock
* since there is no need to grab the bottom half spin_lock.
*
* Return an available rpc_rqst, otherwise NULL if non are available.
*/
struct
rpc_rqst
*
xprt_lookup_bc_request
(
struct
rpc_xprt
*
xprt
,
__be32
xid
)
{
struct
rpc_rqst
*
req
;
spin_lock
(
&
xprt
->
bc_pa_lock
);
list_for_each_entry
(
req
,
&
xprt
->
bc_pa_list
,
rq_bc_pa_list
)
{
if
(
req
->
rq_connect_cookie
!=
xprt
->
connect_cookie
)
continue
;
if
(
req
->
rq_xid
==
xid
)
goto
found
;
}
req
=
xprt_alloc_bc_request
(
xprt
,
xid
);
found:
spin_unlock
(
&
xprt
->
bc_pa_lock
);
return
req
;
}
/*
* Add callback request to callback list. The callback
* service sleeps on the sv_cb_waitq waiting for new
* requests. Wake it up after adding enqueing the
* request.
*/
void
xprt_complete_bc_request
(
struct
rpc_rqst
*
req
,
uint32_t
copied
)
{
struct
rpc_xprt
*
xprt
=
req
->
rq_xprt
;
struct
svc_serv
*
bc_serv
=
xprt
->
bc_serv
;
req
->
rq_private_buf
.
len
=
copied
;
set_bit
(
RPC_BC_PA_IN_USE
,
&
req
->
rq_bc_pa_state
);
dprintk
(
"RPC: add callback request to list
\n
"
);
spin_lock
(
&
bc_serv
->
sv_cb_lock
);
list_del
(
&
req
->
rq_bc_pa_list
);
list_add
(
&
req
->
rq_bc_list
,
&
bc_serv
->
sv_cb_list
);
wake_up
(
&
bc_serv
->
sv_cb_waitq
);
spin_unlock
(
&
bc_serv
->
sv_cb_lock
);
}
net/sunrpc/clnt.c
View file @
bd0f725c
...
...
@@ -1728,9 +1728,7 @@ call_bind_status(struct rpc_task *task)
case
-
EPROTONOSUPPORT
:
dprintk
(
"RPC: %5u remote rpcbind version unavailable, retrying
\n
"
,
task
->
tk_pid
);
task
->
tk_status
=
0
;
task
->
tk_action
=
call_bind
;
return
;
goto
retry_timeout
;
case
-
ECONNREFUSED
:
/* connection problems */
case
-
ECONNRESET
:
case
-
ECONNABORTED
:
...
...
@@ -1756,6 +1754,7 @@ call_bind_status(struct rpc_task *task)
return
;
retry_timeout:
task
->
tk_status
=
0
;
task
->
tk_action
=
call_timeout
;
}
...
...
@@ -1798,10 +1797,6 @@ call_connect_status(struct rpc_task *task)
trace_rpc_connect_status
(
task
,
status
);
task
->
tk_status
=
0
;
switch
(
status
)
{
/* if soft mounted, test if we've timed out */
case
-
ETIMEDOUT
:
task
->
tk_action
=
call_timeout
;
return
;
case
-
ECONNREFUSED
:
case
-
ECONNRESET
:
case
-
ECONNABORTED
:
...
...
@@ -1812,7 +1807,9 @@ call_connect_status(struct rpc_task *task)
if
(
RPC_IS_SOFTCONN
(
task
))
break
;
case
-
EAGAIN
:
task
->
tk_action
=
call_bind
;
/* Check for timeouts before looping back to call_bind */
case
-
ETIMEDOUT
:
task
->
tk_action
=
call_timeout
;
return
;
case
0
:
clnt
->
cl_stats
->
netreconn
++
;
...
...
net/sunrpc/xprtsock.c
View file @
bd0f725c
...
...
@@ -1306,41 +1306,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
* If we're unable to obtain the rpc_rqst we schedule the closing of the
* connection and return -1.
*/
static
in
line
in
t
xs_tcp_read_callback
(
struct
rpc_xprt
*
xprt
,
static
int
xs_tcp_read_callback
(
struct
rpc_xprt
*
xprt
,
struct
xdr_skb_reader
*
desc
)
{
struct
sock_xprt
*
transport
=
container_of
(
xprt
,
struct
sock_xprt
,
xprt
);
struct
rpc_rqst
*
req
;
req
=
xprt_alloc_bc_request
(
xprt
);
/* Look up and lock the request corresponding to the given XID */
spin_lock
(
&
xprt
->
transport_lock
);
req
=
xprt_lookup_bc_request
(
xprt
,
transport
->
tcp_xid
);
if
(
req
==
NULL
)
{
spin_unlock
(
&
xprt
->
transport_lock
);
printk
(
KERN_WARNING
"Callback slot table overflowed
\n
"
);
xprt_force_disconnect
(
xprt
);
return
-
1
;
}
req
->
rq_xid
=
transport
->
tcp_xid
;
dprintk
(
"RPC: read callback XID %08x
\n
"
,
ntohl
(
req
->
rq_xid
));
xs_tcp_read_common
(
xprt
,
desc
,
req
);
if
(
!
(
transport
->
tcp_flags
&
TCP_RCV_COPY_DATA
))
{
struct
svc_serv
*
bc_serv
=
xprt
->
bc_serv
;
/*
* Add callback request to callback list. The callback
* service sleeps on the sv_cb_waitq waiting for new
* requests. Wake it up after adding enqueing the
* request.
*/
dprintk
(
"RPC: add callback request to list
\n
"
);
spin_lock
(
&
bc_serv
->
sv_cb_lock
);
list_add
(
&
req
->
rq_bc_list
,
&
bc_serv
->
sv_cb_list
);
spin_unlock
(
&
bc_serv
->
sv_cb_lock
);
wake_up
(
&
bc_serv
->
sv_cb_waitq
);
}
req
->
rq_private_buf
.
len
=
transport
->
tcp_copied
;
if
(
!
(
transport
->
tcp_flags
&
TCP_RCV_COPY_DATA
))
xprt_complete_bc_request
(
req
,
transport
->
tcp_copied
);
spin_unlock
(
&
xprt
->
transport_lock
);
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