Fix prototype of SMP version of synchronize_irq.
[linux-2.6/linux-mips.git] / fs / nfs / nfs4state.c
blob8243f6d7398d48944393676402b76e0aa8b1a5d7
1 /*
2 * fs/nfs/nfs4state.c
4 * Client-side XDR for NFSv4.
6 * Copyright (c) 2002 The Regents of the University of Michigan.
7 * All rights reserved.
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
13 * are met:
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
38 * subsequent patch.
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...
62 struct nfs4_client *
63 nfs4_get_client(void)
65 struct nfs4_client *clp;
67 if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)))
68 memset(clp, 0, sizeof(nfs4_verifier));
69 return clp;
72 void
73 nfs4_put_client(struct nfs4_client *clp)
75 BUG_ON(!clp);
76 kfree(clp);
79 static inline u32
80 nfs4_alloc_lockowner_id(struct nfs4_client *clp)
82 u32 res;
84 spin_lock(&state_spinlock);
85 res = clp->cl_lockowner_id ++;
86 spin_unlock(&state_spinlock);
87 return res;
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);
115 if (!sp)
116 return NULL;
117 clp = (NFS_SB(dir->i_sb))->nfs4_state;
118 BUG_ON(!clp);
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);
123 return sp;
127 * Called for each non-null inode shareowner in nfs_clear_inode,
128 * or if nfs4_do_open fails.
130 void
131 nfs4_put_shareowner(struct inode *inode, struct nfs4_shareowner *sp)
133 if (!sp)
134 return;
135 if (sp->so_flags & O_ACCMODE)
136 nfs4_do_close(inode, sp);
137 kfree(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()
147 void
148 nfs4_increment_seqid(u32 status, struct nfs4_shareowner *sp)
150 if (status == NFS_OK || seqid_mutating_err(status))
151 sp->so_seqid++;
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) {
163 case O_RDONLY:
164 if (!nfsi->ro_owner) {
165 nfsi->ro_owner = sp;
166 return 0;
168 break;
169 case O_WRONLY:
170 if (!nfsi->wo_owner) {
171 nfsi->wo_owner = sp;
172 return 0;
174 break;
175 case O_RDWR:
176 if (!nfsi->rw_owner) {
177 nfsi->rw_owner = sp;
178 return 0;
181 return -EBUSY;
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) {
195 case O_RDONLY:
196 if(nfsi->ro_owner)
197 return 0;
198 break;
199 case O_WRONLY:
200 if(nfsi->wo_owner)
201 return 0;
202 break;
203 case O_RDWR:
204 if(nfsi->rw_owner)
205 return 0;
207 return 1;
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) {
216 case O_RDONLY:
217 return nfsi->ro_owner;
218 case O_WRONLY:
219 return nfsi->wo_owner;
220 case O_RDWR:
221 return nfsi->rw_owner;
223 /* Duh gcc warning if we don't... */
224 return NULL;
228 * Local variables:
229 * c-basic-offset: 8
230 * End: