4 * Client-side XDR for NFSv4.
6 * Copyright (c) 2002 The Regents of the University of Michigan.
9 * Kendrick Smith <kmsmith@umich.edu>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Implementation of the NFSv4 state model. For the time being,
37 * this is minimal, but will be made much more complex in a
41 #include <linux/config.h>
42 #include <linux/slab.h>
43 #include <linux/nfs_fs.h>
45 /* This protects most of the client-side state. */
46 static spinlock_t state_spinlock
= SPIN_LOCK_UNLOCKED
;
48 nfs4_stateid zero_stateid
=
49 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
51 nfs4_stateid one_stateid
=
52 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
56 * nfs4_get_client(): returns an empty client structure
57 * nfs4_put_client(): drops reference to client structure
59 * Since these are allocated/deallocated very rarely, we don't
60 * bother putting them in a slab cache...
65 struct nfs4_client
*clp
;
67 if ((clp
= kmalloc(sizeof(*clp
), GFP_KERNEL
)))
68 memset(clp
, 0, sizeof(nfs4_verifier
));
73 nfs4_put_client(struct nfs4_client
*clp
)
80 nfs4_alloc_lockowner_id(struct nfs4_client
*clp
)
84 spin_lock(&state_spinlock
);
85 res
= clp
->cl_lockowner_id
++;
86 spin_unlock(&state_spinlock
);
91 * nfs4_get_shareowner(): this is called on the OPEN or CREATE path to
92 * obtain a new shareowner.
94 * There are three shareowners (open_owner4 in rfc3010) per inode,
95 * one for each possible combination of share lock access. Since
96 * Linux does not support the deny access type, there are
97 * three (not 9) referenced by the nfs_inode:
99 * O_WRONLY: inode->wo_owner
100 * O_RDONLY: inode->ro_owner
101 * O_RDWR: inode->rw_owner
103 * We create a new shareowner the first time a file is OPENed with
104 * one of the above shares. All other OPENs with a similar
105 * share use the single stateid associated with the inode.
108 struct nfs4_shareowner
*
109 nfs4_get_shareowner(struct inode
*dir
)
111 struct nfs4_client
*clp
;
112 struct nfs4_shareowner
*sp
;
114 sp
= kmalloc(sizeof(*sp
),GFP_KERNEL
);
117 clp
= (NFS_SB(dir
->i_sb
))->nfs4_state
;
119 init_MUTEX(&sp
->so_sema
);
120 sp
->so_seqid
= 0; /* arbitrary */
121 memset(sp
->so_stateid
, 0, sizeof(nfs4_stateid
));
122 sp
->so_id
= nfs4_alloc_lockowner_id(clp
);
127 * Called for each non-null inode shareowner in nfs_clear_inode,
128 * or if nfs4_do_open fails.
131 nfs4_put_shareowner(struct inode
*inode
, struct nfs4_shareowner
*sp
)
135 if (sp
->so_flags
& O_ACCMODE
)
136 nfs4_do_close(inode
, sp
);
141 * Called with sp->so_sema held.
143 * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
144 * failed with a seqid incrementing error -
145 * see comments nfs_fs.h:seqid_mutating_error()
148 nfs4_increment_seqid(u32 status
, struct nfs4_shareowner
*sp
)
150 if (status
== NFS_OK
|| seqid_mutating_err(status
))
155 * Called by nfs4_proc_open to set the appropriate stateid
158 nfs4_set_inode_share(struct inode
* inode
, struct nfs4_shareowner
*sp
, unsigned int open_flags
)
160 struct nfs_inode
*nfsi
= NFS_I(inode
);
162 switch (open_flags
& O_ACCMODE
) {
164 if (!nfsi
->ro_owner
) {
170 if (!nfsi
->wo_owner
) {
176 if (!nfsi
->rw_owner
) {
185 * Boolean test to determine if an OPEN call goes on the wire.
187 * Called by nfs4_proc_open.
190 nfs4_test_shareowner(struct inode
*inode
, unsigned int open_flags
)
192 struct nfs_inode
*nfsi
= NFS_I(inode
);
194 switch (open_flags
& O_ACCMODE
) {
210 struct nfs4_shareowner
*
211 nfs4_get_inode_share(struct inode
* inode
, unsigned int open_flags
)
213 struct nfs_inode
*nfsi
= NFS_I(inode
);
215 switch (open_flags
& O_ACCMODE
) {
217 return nfsi
->ro_owner
;
219 return nfsi
->wo_owner
;
221 return nfsi
->rw_owner
;
223 /* Duh gcc warning if we don't... */