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
3f1990d3
Commit
3f1990d3
authored
Feb 07, 2004
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NFSv4: Add support for POSIX file locking.
parent
1f37cd43
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
878 additions
and
40 deletions
+878
-40
fs/nfs/file.c
fs/nfs/file.c
+9
-14
fs/nfs/nfs3proc.c
fs/nfs/nfs3proc.c
+8
-0
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+273
-17
fs/nfs/nfs4state.c
fs/nfs/nfs4state.c
+172
-2
fs/nfs/nfs4xdr.c
fs/nfs/nfs4xdr.c
+306
-3
fs/nfs/proc.c
fs/nfs/proc.c
+8
-0
include/linux/nfs4.h
include/linux/nfs4.h
+3
-0
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+36
-1
include/linux/nfs_page.h
include/linux/nfs_page.h
+1
-0
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+62
-3
No files found.
fs/nfs/file.c
View file @
3f1990d3
...
...
@@ -26,7 +26,6 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/lockd/bind.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
...
...
@@ -278,21 +277,17 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
if
(
!
inode
)
return
-
EINVAL
;
/* This will be in a forthcoming patch. */
if
(
NFS_PROTO
(
inode
)
->
version
==
4
)
{
printk
(
KERN_INFO
"NFS: file locking over NFSv4 is not yet supported
\n
"
);
return
-
EIO
;
}
/* No mandatory locks over NFS */
if
((
inode
->
i_mode
&
(
S_ISGID
|
S_IXGRP
))
==
S_ISGID
)
return
-
ENOLCK
;
/* Fake OK code if mounted without NLM support */
if
(
NFS_SERVER
(
inode
)
->
flags
&
NFS_MOUNT_NONLM
)
{
if
(
IS_GETLK
(
cmd
))
status
=
LOCK_USE_CLNT
;
goto
out_ok
;
if
(
NFS_PROTO
(
inode
)
->
version
!=
4
)
{
/* Fake OK code if mounted without NLM support */
if
(
NFS_SERVER
(
inode
)
->
flags
&
NFS_MOUNT_NONLM
)
{
if
(
IS_GETLK
(
cmd
))
status
=
LOCK_USE_CLNT
;
goto
out_ok
;
}
}
/*
...
...
@@ -302,7 +297,7 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
* Not sure whether that would be unique, though, or whether
* that would break in other places.
*/
if
(
!
fl
->
fl_owner
||
(
fl
->
fl_flags
&
FL_POSIX
)
!=
FL_POSIX
)
if
(
!
fl
->
fl_owner
||
!
(
fl
->
fl_flags
&
FL_POSIX
)
)
return
-
ENOLCK
;
/*
...
...
@@ -322,7 +317,7 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
return
status
;
lock_kernel
();
status
=
nlmclnt_proc
(
inode
,
cmd
,
fl
);
status
=
NFS_PROTO
(
inode
)
->
lock
(
filp
,
cmd
,
fl
);
unlock_kernel
();
if
(
status
<
0
)
return
status
;
...
...
fs/nfs/nfs3proc.c
View file @
3f1990d3
...
...
@@ -15,6 +15,7 @@
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
#include <linux/smp_lock.h>
#define NFSDBG_FACILITY NFSDBG_PROC
...
...
@@ -896,6 +897,12 @@ nfs3_request_compatible(struct nfs_page *req, struct file *filp, struct page *pa
return
1
;
}
static
int
nfs3_proc_lock
(
struct
file
*
filp
,
int
cmd
,
struct
file_lock
*
fl
)
{
return
nlmclnt_proc
(
filp
->
f_dentry
->
d_inode
,
cmd
,
fl
);
}
struct
nfs_rpc_ops
nfs_v3_clientops
=
{
.
version
=
3
,
/* protocol version */
.
dentry_ops
=
&
nfs_dentry_operations
,
...
...
@@ -931,4 +938,5 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.
file_release
=
nfs_release
,
.
request_init
=
nfs3_request_init
,
.
request_compatible
=
nfs3_request_compatible
,
.
lock
=
nfs3_proc_lock
,
};
fs/nfs/nfs4proc.c
View file @
3f1990d3
This diff is collapsed.
Click to expand it.
fs/nfs/nfs4state.c
View file @
3f1990d3
...
...
@@ -43,6 +43,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#define OPENOWNER_POOL_SIZE 8
...
...
@@ -168,7 +169,7 @@ nfs4_put_client(struct nfs4_client *clp)
nfs4_free_client
(
clp
);
}
static
inline
u32
u32
nfs4_alloc_lockowner_id
(
struct
nfs4_client
*
clp
)
{
return
clp
->
cl_lockowner_id
++
;
...
...
@@ -304,8 +305,12 @@ nfs4_alloc_open_state(void)
state
->
state
=
0
;
state
->
nreaders
=
0
;
state
->
nwriters
=
0
;
state
->
flags
=
0
;
memset
(
state
->
stateid
.
data
,
0
,
sizeof
(
state
->
stateid
.
data
));
atomic_set
(
&
state
->
count
,
1
);
INIT_LIST_HEAD
(
&
state
->
lock_states
);
init_MUTEX
(
&
state
->
lock_sema
);
rwlock_init
(
&
state
->
state_lock
);
return
state
;
}
...
...
@@ -453,7 +458,7 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
list_del_init
(
&
state
->
inode_states
);
spin_unlock
(
&
inode
->
i_lock
);
do
{
newstate
=
0
;
newstate
=
0
;
if
(
state
->
state
==
0
)
break
;
if
(
state
->
nreaders
)
...
...
@@ -478,6 +483,171 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
nfs4_put_open_state
(
state
);
}
/*
* Search the state->lock_states for an existing lock_owner
* that is compatible with current->files
*/
static
struct
nfs4_lock_state
*
__nfs4_find_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
fl_owner
)
{
struct
nfs4_lock_state
*
pos
;
list_for_each_entry
(
pos
,
&
state
->
lock_states
,
ls_locks
)
{
if
(
pos
->
ls_owner
!=
fl_owner
)
continue
;
atomic_inc
(
&
pos
->
ls_count
);
return
pos
;
}
return
NULL
;
}
struct
nfs4_lock_state
*
nfs4_find_lock_state
(
struct
nfs4_state
*
state
,
fl_owner_t
fl_owner
)
{
struct
nfs4_lock_state
*
lsp
;
read_lock
(
&
state
->
state_lock
);
lsp
=
__nfs4_find_lock_state
(
state
,
fl_owner
);
read_unlock
(
&
state
->
state_lock
);
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
*/
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
;
lsp
=
kmalloc
(
sizeof
(
*
lsp
),
GFP_KERNEL
);
if
(
lsp
==
NULL
)
return
NULL
;
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
);
spin_unlock
(
&
clp
->
cl_lock
);
return
lsp
;
}
/*
* Byte-range lock aware utility to initialize the stateid of read/write
* requests.
*/
void
nfs4_copy_stateid
(
nfs4_stateid
*
dst
,
struct
nfs4_state
*
state
,
fl_owner_t
fl_owner
)
{
if
(
test_bit
(
LK_STATE_IN_USE
,
&
state
->
flags
))
{
struct
nfs4_lock_state
*
lsp
;
lsp
=
nfs4_find_lock_state
(
state
,
fl_owner
);
if
(
lsp
)
{
memcpy
(
dst
,
&
lsp
->
ls_stateid
,
sizeof
(
*
dst
));
nfs4_put_lock_state
(
lsp
);
return
;
}
}
memcpy
(
dst
,
&
state
->
stateid
,
sizeof
(
*
dst
));
}
/*
* Called with state->lock_sema held.
*/
void
nfs4_increment_lock_seqid
(
int
status
,
struct
nfs4_lock_state
*
lsp
)
{
if
(
status
==
NFS_OK
||
seqid_mutating_err
(
-
status
))
lsp
->
ls_seqid
++
;
}
/*
* Check to see if the request lock (type FL_UNLK) effects the fl lock.
*
* fl and request must have the same posix owner
*
* return:
* 0 -> fl not effected by request
* 1 -> fl consumed by request
*/
static
int
nfs4_check_unlock
(
struct
file_lock
*
fl
,
struct
file_lock
*
request
)
{
if
(
fl
->
fl_start
>=
request
->
fl_start
&&
fl
->
fl_end
<=
request
->
fl_end
)
return
1
;
return
0
;
}
/*
* 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
)
{
struct
nfs4_state
*
state
=
lsp
->
ls_parent
;
if
(
!
list_empty
(
&
lsp
->
ls_locks
))
return
;
write_lock
(
&
state
->
state_lock
);
list_add
(
&
lsp
->
ls_locks
,
&
state
->
lock_states
);
set_bit
(
LK_STATE_IN_USE
,
&
state
->
flags
);
write_unlock
(
&
state
->
state_lock
);
}
/*
* to decide to 'reap' lock state:
* 1) search i_flock for file_locks with fl.lock_state = to ls.
* 2) determine if unlock will consume found lock.
* if so, reap
*
* else, don't reap.
*
*/
void
nfs4_notify_unlck
(
struct
inode
*
inode
,
struct
file_lock
*
request
,
struct
nfs4_lock_state
*
lsp
)
{
struct
nfs4_state
*
state
=
lsp
->
ls_parent
;
struct
file_lock
*
fl
;
for
(
fl
=
inode
->
i_flock
;
fl
!=
NULL
;
fl
=
fl
->
fl_next
)
{
if
(
!
(
fl
->
fl_flags
&
FL_POSIX
))
continue
;
if
(
fl
->
fl_owner
!=
lsp
->
ls_owner
)
continue
;
/* Exit if we find at least one lock which is not consumed */
if
(
nfs4_check_unlock
(
fl
,
request
)
==
0
)
return
;
}
write_lock
(
&
state
->
state_lock
);
list_del_init
(
&
lsp
->
ls_locks
);
if
(
list_empty
(
&
state
->
lock_states
))
clear_bit
(
LK_STATE_IN_USE
,
&
state
->
flags
);
write_unlock
(
&
state
->
state_lock
);
}
/*
* Release reference to lock_state, and free it if we see that
* it is no longer in use
*/
void
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
;
kfree
(
lsp
);
}
/*
* Called with sp->so_sema held.
*
...
...
fs/nfs/nfs4xdr.c
View file @
3f1990d3
...
...
@@ -66,6 +66,10 @@ static int nfs_stat_to_errno(int);
#define NFS4_MAXTAGLEN 0
#endif
/* lock,open owner id:
* we currently use size 1 (u32) out of (NFS4_OPAQUE_LIMIT >> 2)
*/
#define owner_id_maxsz 1 + 1
#define compound_encode_hdr_maxsz 3 + (NFS4_MAXTAGLEN >> 2)
#define compound_decode_hdr_maxsz 2 + (NFS4_MAXTAGLEN >> 2)
#define op_encode_hdr_maxsz 1
...
...
@@ -222,6 +226,36 @@ static int nfs_stat_to_errno(int);
decode_setclientid_confirm_maxsz + \
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz
#define NFS4_enc_lock_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 1 + 2 + 2 + \
1 + 4 + 1 + 2 + \
owner_id_maxsz
#define NFS4_dec_lock_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz + \
op_decode_hdr_maxsz + \
2 + 2 + 1 + 2 + \
owner_id_maxsz
#define NFS4_enc_lockt_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 2 + 2 + 2 + \
owner_id_maxsz
#define NFS4_dec_lockt_sz NFS4_dec_lock_sz
#define NFS4_enc_locku_sz compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 1 + 4 + 2 + 2
#define NFS4_dec_locku_sz compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz + \
op_decode_hdr_maxsz + 4
static
struct
{
...
...
@@ -596,6 +630,80 @@ encode_link(struct xdr_stream *xdr, struct nfs4_link *link)
return
0
;
}
/*
* opcode,type,reclaim,offset,length,new_lock_owner = 32
* open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
*/
static
int
encode_lock
(
struct
xdr_stream
*
xdr
,
struct
nfs_lockargs
*
arg
)
{
uint32_t
*
p
;
struct
nfs_lock_opargs
*
opargs
=
arg
->
u
.
lock
;
RESERVE_SPACE
(
32
);
WRITE32
(
OP_LOCK
);
WRITE32
(
arg
->
type
);
WRITE32
(
opargs
->
reclaim
);
WRITE64
(
arg
->
offset
);
WRITE64
(
arg
->
length
);
WRITE32
(
opargs
->
new_lock_owner
);
if
(
opargs
->
new_lock_owner
){
struct
nfs_open_to_lock
*
ol
=
opargs
->
u
.
open_lock
;
RESERVE_SPACE
(
40
);
WRITE32
(
ol
->
open_seqid
);
WRITEMEM
(
&
ol
->
open_stateid
,
sizeof
(
ol
->
open_stateid
));
WRITE32
(
ol
->
lock_seqid
);
WRITE64
(
ol
->
lock_owner
.
clientid
);
WRITE32
(
4
);
WRITE32
(
ol
->
lock_owner
.
id
);
}
else
{
struct
nfs_exist_lock
*
el
=
opargs
->
u
.
exist_lock
;
RESERVE_SPACE
(
20
);
WRITEMEM
(
&
el
->
stateid
,
sizeof
(
el
->
stateid
));
WRITE32
(
el
->
seqid
);
}
return
0
;
}
static
int
encode_lockt
(
struct
xdr_stream
*
xdr
,
struct
nfs_lockargs
*
arg
)
{
uint32_t
*
p
;
struct
nfs_lowner
*
opargs
=
arg
->
u
.
lockt
;
RESERVE_SPACE
(
40
);
WRITE32
(
OP_LOCKT
);
WRITE32
(
arg
->
type
);
WRITE64
(
arg
->
offset
);
WRITE64
(
arg
->
length
);
WRITE64
(
opargs
->
clientid
);
WRITE32
(
4
);
WRITE32
(
opargs
->
id
);
return
0
;
}
static
int
encode_locku
(
struct
xdr_stream
*
xdr
,
struct
nfs_lockargs
*
arg
)
{
uint32_t
*
p
;
struct
nfs_locku_opargs
*
opargs
=
arg
->
u
.
locku
;
RESERVE_SPACE
(
44
);
WRITE32
(
OP_LOCKU
);
WRITE32
(
arg
->
type
);
WRITE32
(
opargs
->
seqid
);
WRITEMEM
(
&
opargs
->
stateid
,
sizeof
(
opargs
->
stateid
));
WRITE64
(
arg
->
offset
);
WRITE64
(
arg
->
length
);
return
0
;
}
static
int
encode_lookup
(
struct
xdr_stream
*
xdr
,
struct
nfs4_lookup
*
lookup
)
{
...
...
@@ -1175,6 +1283,72 @@ nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct nfs_closea
return
status
;
}
/*
* Encode a LOCK request
*/
static
int
nfs4_xdr_enc_lock
(
struct
rpc_rqst
*
req
,
uint32_t
*
p
,
struct
nfs_lockargs
*
args
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
=
{
.
nops
=
2
,
};
int
status
;
xdr_init_encode
(
&
xdr
,
&
req
->
rq_snd_buf
,
p
);
encode_compound_hdr
(
&
xdr
,
&
hdr
);
status
=
encode_putfh
(
&
xdr
,
args
->
fh
);
if
(
status
)
goto
out
;
status
=
encode_lock
(
&
xdr
,
args
);
out:
return
status
;
}
/*
* Encode a LOCKT request
*/
static
int
nfs4_xdr_enc_lockt
(
struct
rpc_rqst
*
req
,
uint32_t
*
p
,
struct
nfs_lockargs
*
args
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
=
{
.
nops
=
2
,
};
int
status
;
xdr_init_encode
(
&
xdr
,
&
req
->
rq_snd_buf
,
p
);
encode_compound_hdr
(
&
xdr
,
&
hdr
);
status
=
encode_putfh
(
&
xdr
,
args
->
fh
);
if
(
status
)
goto
out
;
status
=
encode_lockt
(
&
xdr
,
args
);
out:
return
status
;
}
/*
* Encode a LOCKU request
*/
static
int
nfs4_xdr_enc_locku
(
struct
rpc_rqst
*
req
,
uint32_t
*
p
,
struct
nfs_lockargs
*
args
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
=
{
.
nops
=
2
,
};
int
status
;
xdr_init_encode
(
&
xdr
,
&
req
->
rq_snd_buf
,
p
);
encode_compound_hdr
(
&
xdr
,
&
hdr
);
status
=
encode_putfh
(
&
xdr
,
args
->
fh
);
if
(
status
)
goto
out
;
status
=
encode_locku
(
&
xdr
,
args
);
out:
return
status
;
}
/*
* Encode a READ request
*/
...
...
@@ -1997,6 +2171,66 @@ decode_link(struct xdr_stream *xdr, struct nfs4_link *link)
return
decode_change_info
(
xdr
,
link
->
ln_cinfo
);
}
/*
* We create the owner, so we know a proper owner.id length is 4.
*/
static
int
decode_lock_denied
(
struct
xdr_stream
*
xdr
,
struct
nfs_lock_denied
*
denied
)
{
uint32_t
*
p
;
uint32_t
namelen
;
READ_BUF
(
32
);
READ64
(
denied
->
offset
);
READ64
(
denied
->
length
);
READ32
(
denied
->
type
);
READ64
(
denied
->
owner
.
clientid
);
READ32
(
namelen
);
READ_BUF
(
namelen
);
if
(
namelen
==
4
)
READ32
(
denied
->
owner
.
id
);
return
-
NFS4ERR_DENIED
;
}
static
int
decode_lock
(
struct
xdr_stream
*
xdr
,
struct
nfs_lockres
*
res
)
{
uint32_t
*
p
;
int
status
;
status
=
decode_op_hdr
(
xdr
,
OP_LOCK
);
if
(
status
==
0
)
{
READ_BUF
(
sizeof
(
nfs4_stateid
));
COPYMEM
(
&
res
->
u
.
stateid
,
sizeof
(
res
->
u
.
stateid
));
}
else
if
(
status
==
-
NFS4ERR_DENIED
)
return
decode_lock_denied
(
xdr
,
&
res
->
u
.
denied
);
return
status
;
}
static
int
decode_lockt
(
struct
xdr_stream
*
xdr
,
struct
nfs_lockres
*
res
)
{
int
status
;
status
=
decode_op_hdr
(
xdr
,
OP_LOCKT
);
if
(
status
==
-
NFS4ERR_DENIED
)
return
decode_lock_denied
(
xdr
,
&
res
->
u
.
denied
);
return
status
;
}
static
int
decode_locku
(
struct
xdr_stream
*
xdr
,
struct
nfs_lockres
*
res
)
{
uint32_t
*
p
;
int
status
;
status
=
decode_op_hdr
(
xdr
,
OP_LOCKU
);
if
(
status
==
0
)
{
READ_BUF
(
sizeof
(
nfs4_stateid
));
COPYMEM
(
&
res
->
u
.
stateid
,
sizeof
(
res
->
u
.
stateid
));
}
return
status
;
}
static
int
decode_lookup
(
struct
xdr_stream
*
xdr
)
{
...
...
@@ -2037,10 +2271,11 @@ static int
decode_open_confirm
(
struct
xdr_stream
*
xdr
,
struct
nfs_open_confirmres
*
res
)
{
uint32_t
*
p
;
int
status
;
res
->
status
=
decode_op_hdr
(
xdr
,
OP_OPEN_CONFIRM
);
if
(
res
->
status
)
return
res
->
status
;
status
=
decode_op_hdr
(
xdr
,
OP_OPEN_CONFIRM
);
if
(
status
)
return
status
;
READ_BUF
(
sizeof
(
res
->
stateid
.
data
));
COPYMEM
(
res
->
stateid
.
data
,
sizeof
(
res
->
stateid
.
data
));
return
0
;
...
...
@@ -2619,6 +2854,71 @@ nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_setattrres
return
status
;
}
/*
* Decode LOCK response
*/
static
int
nfs4_xdr_dec_lock
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs_lockres
*
res
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
;
int
status
;
xdr_init_decode
(
&
xdr
,
&
rqstp
->
rq_rcv_buf
,
p
);
status
=
decode_compound_hdr
(
&
xdr
,
&
hdr
);
if
(
status
)
goto
out
;
status
=
decode_putfh
(
&
xdr
);
if
(
status
)
goto
out
;
status
=
decode_lock
(
&
xdr
,
res
);
out:
return
status
;
}
/*
* Decode LOCKT response
*/
static
int
nfs4_xdr_dec_lockt
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs_lockres
*
res
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
;
int
status
;
xdr_init_decode
(
&
xdr
,
&
rqstp
->
rq_rcv_buf
,
p
);
status
=
decode_compound_hdr
(
&
xdr
,
&
hdr
);
if
(
status
)
goto
out
;
status
=
decode_putfh
(
&
xdr
);
if
(
status
)
goto
out
;
status
=
decode_lockt
(
&
xdr
,
res
);
out:
return
status
;
}
/*
* Decode LOCKU response
*/
static
int
nfs4_xdr_dec_locku
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs_lockres
*
res
)
{
struct
xdr_stream
xdr
;
struct
compound_hdr
hdr
;
int
status
;
xdr_init_decode
(
&
xdr
,
&
rqstp
->
rq_rcv_buf
,
p
);
status
=
decode_compound_hdr
(
&
xdr
,
&
hdr
);
if
(
status
)
goto
out
;
status
=
decode_putfh
(
&
xdr
);
if
(
status
)
goto
out
;
status
=
decode_locku
(
&
xdr
,
res
);
out:
return
status
;
}
/*
* Decode Read response
...
...
@@ -2915,6 +3215,9 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC
(
RENEW
,
enc_renew
,
dec_renew
),
PROC
(
SETCLIENTID
,
enc_setclientid
,
dec_setclientid
),
PROC
(
SETCLIENTID_CONFIRM
,
enc_setclientid_confirm
,
dec_setclientid_confirm
),
PROC
(
LOCK
,
enc_lock
,
dec_lock
),
PROC
(
LOCKT
,
enc_lockt
,
dec_lockt
),
PROC
(
LOCKU
,
enc_locku
,
dec_locku
),
};
struct
rpc_version
nfs_version4
=
{
...
...
fs/nfs/proc.c
View file @
3f1990d3
...
...
@@ -42,6 +42,7 @@
#include <linux/nfs2.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
#include <linux/smp_lock.h>
#define NFSDBG_FACILITY NFSDBG_PROC
...
...
@@ -653,6 +654,12 @@ nfs_request_compatible(struct nfs_page *req, struct file *filp, struct page *pag
return
1
;
}
static
int
nfs_proc_lock
(
struct
file
*
filp
,
int
cmd
,
struct
file_lock
*
fl
)
{
return
nlmclnt_proc
(
filp
->
f_dentry
->
d_inode
,
cmd
,
fl
);
}
struct
nfs_rpc_ops
nfs_v2_clientops
=
{
.
version
=
2
,
/* protocol version */
...
...
@@ -689,4 +696,5 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.
file_release
=
nfs_release
,
.
request_init
=
nfs_request_init
,
.
request_compatible
=
nfs_request_compatible
,
.
lock
=
nfs_proc_lock
,
};
include/linux/nfs4.h
View file @
3f1990d3
...
...
@@ -297,6 +297,9 @@ enum {
NFSPROC4_CLNT_RENEW
,
NFSPROC4_CLNT_SETCLIENTID
,
NFSPROC4_CLNT_SETCLIENTID_CONFIRM
,
NFSPROC4_CLNT_LOCK
,
NFSPROC4_CLNT_LOCKT
,
NFSPROC4_CLNT_LOCKU
,
};
#endif
...
...
include/linux/nfs_fs.h
View file @
3f1990d3
...
...
@@ -542,19 +542,43 @@ struct nfs4_state_owner {
/*
* struct nfs4_state maintains the client-side state for a given
* (state_owner,inode) tuple.
* (state_owner,inode) tuple
(OPEN) or state_owner (LOCK)
.
*
* OPEN:
* In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server,
* we need to know how many files are open for reading or writing on a
* given inode. This information too is stored here.
*
* LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
*/
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 */
u32
ls_seqid
;
u32
ls_id
;
nfs4_stateid
ls_stateid
;
atomic_t
ls_count
;
};
/* bits for nfs4_state->flags */
enum
{
LK_STATE_IN_USE
,
};
struct
nfs4_state
{
struct
list_head
open_states
;
/* List of states for the same state_owner */
struct
list_head
inode_states
;
/* List of states for the same inode */
struct
list_head
lock_states
;
/* List of subservient lock stateids */
struct
nfs4_state_owner
*
owner
;
/* Pointer to the open owner */
struct
inode
*
inode
;
/* Pointer to the inode */
unsigned
long
flags
;
/* Do we hold any locks? */
struct
semaphore
lock_sema
;
/* Serializes file locking operations */
rwlock_t
state_lock
;
/* Protects the lock_states list */
nfs4_stateid
stateid
;
unsigned
int
nreaders
;
...
...
@@ -589,6 +613,8 @@ extern void init_nfsv4_state(struct nfs_server *);
extern
void
destroy_nfsv4_state
(
struct
nfs_server
*
);
extern
struct
nfs4_client
*
nfs4_get_client
(
struct
in_addr
*
);
extern
void
nfs4_put_client
(
struct
nfs4_client
*
clp
);
extern
u32
nfs4_alloc_lockowner_id
(
struct
nfs4_client
*
);
extern
struct
nfs4_state_owner
*
nfs4_get_state_owner
(
struct
nfs_server
*
,
struct
rpc_cred
*
);
extern
void
nfs4_put_state_owner
(
struct
nfs4_state_owner
*
);
extern
struct
nfs4_state
*
nfs4_get_open_state
(
struct
inode
*
,
struct
nfs4_state_owner
*
);
...
...
@@ -598,6 +624,15 @@ 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
int
nfs4_handle_error
(
struct
nfs_server
*
,
int
);
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
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
inode
*
,
struct
file_lock
*
,
struct
nfs4_lock_state
*
);
extern
void
nfs4_notify_unlck
(
struct
inode
*
,
struct
file_lock
*
,
struct
nfs4_lock_state
*
);
extern
void
nfs4_copy_stateid
(
nfs4_stateid
*
,
struct
nfs4_state
*
,
fl_owner_t
);
struct
nfs4_mount_data
;
#else
...
...
include/linux/nfs_page.h
View file @
3f1990d3
...
...
@@ -26,6 +26,7 @@ struct nfs_page {
struct
list_head
wb_list
,
/* Defines state of page: */
*
wb_list_head
;
/* read/write/commit */
struct
file
*
wb_file
;
fl_owner_t
wb_lockowner
;
struct
inode
*
wb_inode
;
struct
rpc_cred
*
wb_cred
;
struct
nfs4_state
*
wb_state
;
...
...
include/linux/nfs_xdr.h
View file @
3f1990d3
...
...
@@ -109,7 +109,6 @@ struct nfs_openargs {
};
struct
nfs_openres
{
__u32
status
;
nfs4_stateid
stateid
;
struct
nfs_fh
fh
;
struct
nfs4_change_info
*
cinfo
;
...
...
@@ -129,7 +128,6 @@ struct nfs_open_confirmargs {
};
struct
nfs_open_confirmres
{
__u32
status
;
nfs4_stateid
stateid
;
};
...
...
@@ -157,10 +155,68 @@ struct nfs_closeargs {
};
struct
nfs_closeres
{
__u32
status
;
nfs4_stateid
stateid
;
};
/*
* * Arguments to the lock,lockt, and locku call.
* */
struct
nfs_lowner
{
__u64
clientid
;
u32
id
;
};
struct
nfs_open_to_lock
{
__u32
open_seqid
;
nfs4_stateid
open_stateid
;
__u32
lock_seqid
;
struct
nfs_lowner
lock_owner
;
};
struct
nfs_exist_lock
{
nfs4_stateid
stateid
;
__u32
seqid
;
};
struct
nfs_lock_opargs
{
__u32
reclaim
;
__u32
new_lock_owner
;
union
{
struct
nfs_open_to_lock
*
open_lock
;
struct
nfs_exist_lock
*
exist_lock
;
}
u
;
};
struct
nfs_locku_opargs
{
__u32
seqid
;
nfs4_stateid
stateid
;
};
struct
nfs_lockargs
{
struct
nfs_fh
*
fh
;
__u32
type
;
__u64
offset
;
__u64
length
;
union
{
struct
nfs_lock_opargs
*
lock
;
/* LOCK */
struct
nfs_lowner
*
lockt
;
/* LOCKT */
struct
nfs_locku_opargs
*
locku
;
/* LOCKU */
}
u
;
};
struct
nfs_lock_denied
{
__u64
offset
;
__u64
length
;
__u32
type
;
struct
nfs_lowner
owner
;
};
struct
nfs_lockres
{
union
{
nfs4_stateid
stateid
;
/* LOCK success, LOCKU */
struct
nfs_lock_denied
denied
;
/* LOCK failed, LOCKT success */
}
u
;
struct
nfs_server
*
server
;
};
/*
* Arguments to the read call.
...
...
@@ -605,6 +661,7 @@ struct nfs_read_data {
struct
rpc_task
task
;
struct
inode
*
inode
;
struct
rpc_cred
*
cred
;
fl_owner_t
lockowner
;
struct
nfs_fattr
fattr
;
/* fattr storage */
struct
list_head
pages
;
/* Coalesced read requests */
struct
page
*
pagevec
[
NFS_READ_MAXIOV
];
...
...
@@ -620,6 +677,7 @@ struct nfs_write_data {
struct
rpc_task
task
;
struct
inode
*
inode
;
struct
rpc_cred
*
cred
;
fl_owner_t
lockowner
;
struct
nfs_fattr
fattr
;
struct
nfs_writeverf
verf
;
struct
list_head
pages
;
/* Coalesced requests we wish to flush */
...
...
@@ -686,6 +744,7 @@ struct nfs_rpc_ops {
int
(
*
file_release
)
(
struct
inode
*
,
struct
file
*
);
void
(
*
request_init
)(
struct
nfs_page
*
,
struct
file
*
);
int
(
*
request_compatible
)(
struct
nfs_page
*
,
struct
file
*
,
struct
page
*
);
int
(
*
lock
)(
struct
file
*
,
int
,
struct
file_lock
*
);
};
/*
...
...
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