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
ed373838
Commit
ed373838
authored
Aug 23, 2004
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NFSv4: On server reboot we need to recover byte-range locks.
Signed-off-by:
Trond Myklebust
<
trond.myklebust@fys.uio.no
>
parent
191f7912
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
115 additions
and
36 deletions
+115
-36
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+35
-18
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+74
-14
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+6
-4
No files found.
fs/nfs/nfs4proc.c
View file @
ed373838
...
...
@@ -2192,16 +2192,19 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock
lsp
=
nfs4_find_lock_state
(
state
,
request
->
fl_owner
);
if
(
!
lsp
)
goto
out
;
luargs
.
seqid
=
lsp
->
ls_seqid
;
memcpy
(
&
luargs
.
stateid
,
&
lsp
->
ls_stateid
,
sizeof
(
luargs
.
stateid
));
arg
.
u
.
locku
=
&
luargs
;
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
nfs4_increment_lock_seqid
(
status
,
lsp
);
/* We might have lost the locks! */
if
((
lsp
->
ls_flags
&
NFS_LOCK_INITIALIZED
)
!=
0
)
{
luargs
.
seqid
=
lsp
->
ls_seqid
;
memcpy
(
&
luargs
.
stateid
,
&
lsp
->
ls_stateid
,
sizeof
(
luargs
.
stateid
));
arg
.
u
.
locku
=
&
luargs
;
status
=
rpc_call_sync
(
server
->
client
,
&
msg
,
0
);
nfs4_increment_lock_seqid
(
status
,
lsp
);
}
if
(
status
==
0
)
{
memcpy
(
&
lsp
->
ls_stateid
,
&
res
.
u
.
stateid
,
sizeof
(
lsp
->
ls_stateid
));
nfs4_notify_unlck
(
inod
e
,
request
,
lsp
);
nfs4_notify_unlck
(
stat
e
,
request
,
lsp
);
}
nfs4_put_lock_state
(
lsp
);
out:
...
...
@@ -2225,11 +2228,10 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
return
err
;
}
static
int
_nfs4_
proc_setlk
(
struct
nfs4_state
*
state
,
int
cmd
,
struct
file_lock
*
request
)
static
int
_nfs4_
do_setlk
(
struct
nfs4_state
*
state
,
int
cmd
,
struct
file_lock
*
request
,
int
reclaim
)
{
struct
inode
*
inode
=
state
->
inode
;
struct
nfs_server
*
server
=
NFS_SERVER
(
inode
);
struct
nfs4_client
*
clp
=
server
->
nfs4_state
;
struct
nfs4_lock_state
*
lsp
;
struct
nfs_lockargs
arg
=
{
.
fh
=
NFS_FH
(
inode
),
...
...
@@ -2247,24 +2249,22 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
.
rpc_cred
=
state
->
owner
->
so_cred
,
};
struct
nfs_lock_opargs
largs
=
{
.
reclaim
=
reclaim
,
.
new_lock_owner
=
0
,
};
int
status
;
down_read
(
&
clp
->
cl_sem
);
down
(
&
state
->
lock_sema
);
lsp
=
nfs4_find_lock_state
(
state
,
request
->
fl_owner
)
;
if
(
lsp
==
NULL
)
{
lsp
=
nfs4_get_lock_state
(
state
,
request
->
fl_owner
);
if
(
lsp
==
NULL
)
return
-
ENOMEM
;
if
(
!
(
lsp
->
ls_flags
&
NFS_LOCK_INITIALIZED
)
)
{
struct
nfs4_state_owner
*
owner
=
state
->
owner
;
struct
nfs_open_to_lock
otl
=
{
.
lock_owner
=
{
.
clientid
=
server
->
nfs4_state
->
cl_clientid
,
},
};
status
=
-
ENOMEM
;
lsp
=
nfs4_alloc_lock_state
(
state
,
request
->
fl_owner
);
if
(
!
lsp
)
goto
out
;
otl
.
lock_seqid
=
lsp
->
ls_seqid
;
otl
.
lock_owner
.
id
=
lsp
->
ls_id
;
memcpy
(
&
otl
.
open_stateid
,
&
state
->
stateid
,
sizeof
(
otl
.
open_stateid
));
...
...
@@ -2293,11 +2293,28 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
/* save the returned stateid. */
if
(
status
==
0
)
{
memcpy
(
&
lsp
->
ls_stateid
,
&
res
.
u
.
stateid
,
sizeof
(
nfs4_stateid
));
nfs4_notify_setlk
(
inode
,
request
,
lsp
);
lsp
->
ls_flags
|=
NFS_LOCK_INITIALIZED
;
if
(
!
reclaim
)
nfs4_notify_setlk
(
state
,
request
,
lsp
);
}
else
if
(
status
==
-
NFS4ERR_DENIED
)
status
=
-
EAGAIN
;
nfs4_put_lock_state
(
lsp
);
out:
return
status
;
}
int
nfs4_lock_reclaim
(
struct
nfs4_state
*
state
,
struct
file_lock
*
request
)
{
return
_nfs4_do_setlk
(
state
,
F_SETLK64
,
request
,
1
);
}
static
int
_nfs4_proc_setlk
(
struct
nfs4_state
*
state
,
int
cmd
,
struct
file_lock
*
request
)
{
struct
nfs4_client
*
clp
=
state
->
owner
->
so_client
;
int
status
;
down_read
(
&
clp
->
cl_sem
);
down
(
&
state
->
lock_sema
);
status
=
_nfs4_do_setlk
(
state
,
cmd
,
request
,
0
);
up
(
&
state
->
lock_sema
);
if
(
status
==
0
)
{
/* Note: we always want to sleep here! */
...
...
fs/nfs/nfs4state.c
View file @
ed373838
...
...
@@ -40,6 +40,7 @@
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
#include <linux/workqueue.h>
...
...
@@ -516,8 +517,7 @@ nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
*
* The caller must be holding state->lock_sema
*/
struct
nfs4_lock_state
*
nfs4_alloc_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
fl_owner
)
static
struct
nfs4_lock_state
*
nfs4_alloc_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
fl_owner
)
{
struct
nfs4_lock_state
*
lsp
;
struct
nfs4_client
*
clp
=
state
->
owner
->
so_client
;
...
...
@@ -525,12 +525,12 @@ nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
lsp
=
kmalloc
(
sizeof
(
*
lsp
),
GFP_KERNEL
);
if
(
lsp
==
NULL
)
return
NULL
;
lsp
->
ls_flags
=
0
;
lsp
->
ls_seqid
=
0
;
/* arbitrary */
lsp
->
ls_id
=
-
1
;
memset
(
lsp
->
ls_stateid
.
data
,
0
,
sizeof
(
lsp
->
ls_stateid
.
data
));
atomic_set
(
&
lsp
->
ls_count
,
1
);
lsp
->
ls_owner
=
fl_owner
;
lsp
->
ls_parent
=
state
;
INIT_LIST_HEAD
(
&
lsp
->
ls_locks
);
spin_lock
(
&
clp
->
cl_lock
);
lsp
->
ls_id
=
nfs4_alloc_lockowner_id
(
clp
);
...
...
@@ -538,6 +538,22 @@ nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
return
lsp
;
}
/*
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
*
* The caller must be holding state->lock_sema and clp->cl_sem
*/
struct
nfs4_lock_state
*
nfs4_get_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
owner
)
{
struct
nfs4_lock_state
*
lsp
;
lsp
=
nfs4_find_lock_state
(
state
,
owner
);
if
(
lsp
==
NULL
)
lsp
=
nfs4_alloc_lock_state
(
state
,
owner
);
return
lsp
;
}
/*
* Byte-range lock aware utility to initialize the stateid of read/write
* requests.
...
...
@@ -588,13 +604,11 @@ nfs4_check_unlock(struct file_lock *fl, struct file_lock *request)
/*
* Post an initialized lock_state on the state->lock_states list.
*/
void
nfs4_notify_setlk
(
struct
inode
*
inode
,
struct
file_lock
*
request
,
struct
nfs4_lock_state
*
lsp
)
void
nfs4_notify_setlk
(
struct
nfs4_state
*
state
,
struct
file_lock
*
request
,
struct
nfs4_lock_state
*
lsp
)
{
struct
nfs4_state
*
state
=
lsp
->
ls_parent
;
if
(
!
list_empty
(
&
lsp
->
ls_locks
))
return
;
atomic_inc
(
&
lsp
->
ls_count
);
write_lock
(
&
state
->
state_lock
);
list_add
(
&
lsp
->
ls_locks
,
&
state
->
lock_states
);
set_bit
(
LK_STATE_IN_USE
,
&
state
->
flags
);
...
...
@@ -611,9 +625,9 @@ nfs4_notify_setlk(struct inode *inode, struct file_lock *request, struct nfs4_lo
*
*/
void
nfs4_notify_unlck
(
struct
inode
*
inod
e
,
struct
file_lock
*
request
,
struct
nfs4_lock_state
*
lsp
)
nfs4_notify_unlck
(
struct
nfs4_state
*
stat
e
,
struct
file_lock
*
request
,
struct
nfs4_lock_state
*
lsp
)
{
struct
nfs4_state
*
state
=
lsp
->
ls_parent
;
struct
inode
*
inode
=
state
->
inode
;
struct
file_lock
*
fl
;
for
(
fl
=
inode
->
i_flock
;
fl
!=
NULL
;
fl
=
fl
->
fl_next
)
{
...
...
@@ -631,6 +645,7 @@ nfs4_notify_unlck(struct inode *inode, struct file_lock *request, struct nfs4_lo
if
(
list_empty
(
&
state
->
lock_states
))
clear_bit
(
LK_STATE_IN_USE
,
&
state
->
flags
);
write_unlock
(
&
state
->
state_lock
);
nfs4_put_lock_state
(
lsp
);
}
/*
...
...
@@ -642,8 +657,7 @@ nfs4_put_lock_state(struct nfs4_lock_state *lsp)
{
if
(
!
atomic_dec_and_test
(
&
lsp
->
ls_count
))
return
;
if
(
!
list_empty
(
&
lsp
->
ls_locks
))
return
;
BUG_ON
(
!
list_empty
(
&
lsp
->
ls_locks
));
kfree
(
lsp
);
}
...
...
@@ -705,18 +719,62 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp)
schedule_work
(
&
clp
->
cl_recoverd
);
}
static
int
nfs4_reclaim_open_state
(
struct
nfs4_state_owner
*
sp
)
static
int
nfs4_reclaim_locks
(
struct
nfs4_state
*
state
)
{
struct
inode
*
inode
=
state
->
inode
;
struct
file_lock
*
fl
;
int
status
=
0
;
for
(
fl
=
inode
->
i_flock
;
fl
!=
0
;
fl
=
fl
->
fl_next
)
{
if
(
!
(
fl
->
fl_flags
&
FL_POSIX
))
continue
;
if
((
struct
nfs4_state
*
)
fl
->
fl_file
->
private_data
!=
state
)
continue
;
status
=
nfs4_lock_reclaim
(
state
,
fl
);
if
(
status
>=
0
)
continue
;
switch
(
status
)
{
default:
printk
(
KERN_ERR
"%s: unhandled error %d. Zeroing state
\n
"
,
__FUNCTION__
,
status
);
case
-
NFS4ERR_EXPIRED
:
case
-
NFS4ERR_NO_GRACE
:
case
-
NFS4ERR_RECLAIM_BAD
:
case
-
NFS4ERR_RECLAIM_CONFLICT
:
/* kill_proc(fl->fl_owner, SIGLOST, 1); */
break
;
case
-
NFS4ERR_STALE_CLIENTID
:
goto
out_err
;
}
}
return
0
;
out_err:
return
status
;
}
static
int
nfs4_reclaim_open_state
(
struct
nfs4_state_owner
*
sp
)
{
struct
nfs4_state
*
state
;
struct
nfs4_lock_state
*
lock
;
int
status
=
0
;
list_for_each_entry
(
state
,
&
sp
->
so_states
,
open_states
)
{
if
(
state
->
state
==
0
)
continue
;
status
=
nfs4_open_reclaim
(
sp
,
state
);
if
(
status
>=
0
)
list_for_each_entry
(
lock
,
&
state
->
lock_states
,
ls_locks
)
lock
->
ls_flags
&=
~
NFS_LOCK_INITIALIZED
;
if
(
status
>=
0
)
{
status
=
nfs4_reclaim_locks
(
state
);
if
(
status
<
0
)
goto
out_err
;
list_for_each_entry
(
lock
,
&
state
->
lock_states
,
ls_locks
)
{
if
(
!
(
lock
->
ls_flags
&
NFS_LOCK_INITIALIZED
))
printk
(
"%s: Lock reclaim failed!
\n
"
,
__FUNCTION__
);
}
continue
;
}
switch
(
status
)
{
default:
printk
(
KERN_ERR
"%s: unhandled error %d. Zeroing state
\n
"
,
...
...
@@ -757,6 +815,7 @@ static int reclaimer(void *ptr)
complete
(
&
args
->
complete
);
/* Ensure exclusive access to NFSv4 state */
lock_kernel
();
down_write
(
&
clp
->
cl_sem
);
/* Are there any NFS mounts out there? */
if
(
list_empty
(
&
clp
->
cl_superblocks
))
...
...
@@ -780,6 +839,7 @@ static int reclaimer(void *ptr)
out:
set_bit
(
NFS4CLNT_OK
,
&
clp
->
cl_state
);
up_write
(
&
clp
->
cl_sem
);
unlock_kernel
();
wake_up_all
(
&
clp
->
cl_waitq
);
rpc_wake_up
(
&
clp
->
cl_rpcwaitq
);
nfs4_put_client
(
clp
);
...
...
include/linux/nfs_fs.h
View file @
ed373838
...
...
@@ -591,7 +591,8 @@ struct nfs4_state_owner {
struct
nfs4_lock_state
{
struct
list_head
ls_locks
;
/* Other lock stateids */
fl_owner_t
ls_owner
;
/* POSIX lock owner */
struct
nfs4_state
*
ls_parent
;
/* Parent nfs4_state */
#define NFS_LOCK_INITIALIZED 1
int
ls_flags
;
u32
ls_seqid
;
u32
ls_id
;
nfs4_stateid
ls_stateid
;
...
...
@@ -644,6 +645,7 @@ extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
extern
struct
inode
*
nfs4_atomic_open
(
struct
inode
*
,
struct
dentry
*
,
struct
nameidata
*
);
extern
int
nfs4_open_revalidate
(
struct
inode
*
,
struct
dentry
*
,
int
);
extern
int
nfs4_handle_exception
(
struct
nfs_server
*
,
int
,
struct
nfs4_exception
*
);
extern
int
nfs4_lock_reclaim
(
struct
nfs4_state
*
state
,
struct
file_lock
*
request
);
/* nfs4renewd.c */
extern
void
nfs4_schedule_state_renewal
(
struct
nfs4_client
*
);
...
...
@@ -667,11 +669,11 @@ extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mod
extern
void
nfs4_increment_seqid
(
int
status
,
struct
nfs4_state_owner
*
sp
);
extern
void
nfs4_schedule_state_recovery
(
struct
nfs4_client
*
);
extern
struct
nfs4_lock_state
*
nfs4_find_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
);
extern
struct
nfs4_lock_state
*
nfs4_
alloc
_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
);
extern
struct
nfs4_lock_state
*
nfs4_
get
_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
);
extern
void
nfs4_put_lock_state
(
struct
nfs4_lock_state
*
state
);
extern
void
nfs4_increment_lock_seqid
(
int
status
,
struct
nfs4_lock_state
*
ls
);
extern
void
nfs4_notify_setlk
(
struct
inod
e
*
,
struct
file_lock
*
,
struct
nfs4_lock_state
*
);
extern
void
nfs4_notify_unlck
(
struct
inod
e
*
,
struct
file_lock
*
,
struct
nfs4_lock_state
*
);
extern
void
nfs4_notify_setlk
(
struct
nfs4_stat
e
*
,
struct
file_lock
*
,
struct
nfs4_lock_state
*
);
extern
void
nfs4_notify_unlck
(
struct
nfs4_stat
e
*
,
struct
file_lock
*
,
struct
nfs4_lock_state
*
);
extern
void
nfs4_copy_stateid
(
nfs4_stateid
*
,
struct
nfs4_state
*
,
fl_owner_t
);
...
...
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