Blame view
fs/nfsd/nfs4state.c
121 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
* Copyright (c) 2001 The Regents of the University of Michigan. * All rights reserved. * * Kendrick Smith <kmsmith@umich.edu> * Andy Adamson <kandros@umich.edu> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ |
aceaf78da [PATCH] r/o bind ... |
34 |
#include <linux/file.h> |
b89f43213 fs/locks.c: prepa... |
35 |
#include <linux/fs.h> |
5a0e3ad6a include cleanup: ... |
36 |
#include <linux/slab.h> |
0964a3d3f [PATCH] knfsd: nf... |
37 |
#include <linux/namei.h> |
c2f1a551d knfsd: nfsd4: var... |
38 |
#include <linux/swap.h> |
174568045 NFSD: Added TEST_... |
39 |
#include <linux/pagemap.h> |
68e76ad0b nfsd: pass client... |
40 |
#include <linux/sunrpc/svcauth_gss.h> |
363168b4e nfsd: make nfs4_c... |
41 |
#include <linux/sunrpc/clnt.h> |
9a74af213 nfsd: Move privat... |
42 |
#include "xdr4.h" |
0a3adadee nfsd: make fs/nfs... |
43 |
#include "vfs.h" |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 |
#define NFSDDBG_FACILITY NFSDDBG_PROC /* Globals */ |
cf07d2ea4 nfsd4: simplify r... |
48 |
time_t nfsd4_lease = 90; /* default lease time */ |
efc4bb4fd nfsd4: allow sett... |
49 |
time_t nfsd4_grace = 90; |
fd39ca9a8 [PATCH] knfsd: nf... |
50 |
static time_t boot_time; |
f32f3c2d3 nfsd4: initialize... |
51 52 53 54 55 56 57 58 59 |
#define all_ones {{~0,~0},~0} static const stateid_t one_stateid = { .si_generation = ~0, .si_opaque = all_ones, }; static const stateid_t zero_stateid = { /* all fields zero */ }; |
ec6b5d7b5 nfsd41: create_se... |
60 |
static u64 current_sessionid = 1; |
fd39ca9a8 [PATCH] knfsd: nf... |
61 |
|
f32f3c2d3 nfsd4: initialize... |
62 63 |
#define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t))) #define ONE_STATEID(stateid) (!memcmp((stateid), &one_stateid, sizeof(stateid_t))) |
1da177e4c Linux-2.6.12-rc2 |
64 |
|
1da177e4c Linux-2.6.12-rc2 |
65 |
/* forward declarations */ |
fe0750e5c nfsd4: split stat... |
66 |
static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); |
1da177e4c Linux-2.6.12-rc2 |
67 |
|
8b671b807 nfsd4: remove use... |
68 69 70 |
/* Locking: */ /* Currently used for almost all code touching nfsv4 state: */ |
353ab6e97 [PATCH] sem2mutex... |
71 |
static DEFINE_MUTEX(client_mutex); |
1da177e4c Linux-2.6.12-rc2 |
72 |
|
8b671b807 nfsd4: remove use... |
73 74 75 76 77 78 |
/* * Currently used for the del_recall_lru and file hash table. In an * effort to decrease the scope of the client_mutex, this spinlock may * eventually cover more: */ static DEFINE_SPINLOCK(recall_lock); |
fe0750e5c nfsd4: split stat... |
79 80 |
static struct kmem_cache *openowner_slab = NULL; static struct kmem_cache *lockowner_slab = NULL; |
e18b890bb [PATCH] slab: rem... |
81 82 83 |
static struct kmem_cache *file_slab = NULL; static struct kmem_cache *stateid_slab = NULL; static struct kmem_cache *deleg_slab = NULL; |
e60d4398a [PATCH] nfsd4: sl... |
84 |
|
1da177e4c Linux-2.6.12-rc2 |
85 86 87 |
void nfs4_lock_state(void) { |
353ab6e97 [PATCH] sem2mutex... |
88 |
mutex_lock(&client_mutex); |
1da177e4c Linux-2.6.12-rc2 |
89 90 91 92 93 |
} void nfs4_unlock_state(void) { |
353ab6e97 [PATCH] sem2mutex... |
94 |
mutex_unlock(&client_mutex); |
1da177e4c Linux-2.6.12-rc2 |
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
} static inline u32 opaque_hashval(const void *ptr, int nbytes) { unsigned char *cptr = (unsigned char *) ptr; u32 x = 0; while (nbytes--) { x *= 37; x += *cptr++; } return x; } |
1da177e4c Linux-2.6.12-rc2 |
109 |
static struct list_head del_recall_lru; |
32513b40e nfsd4: preallocat... |
110 111 112 113 |
static void nfsd4_free_file(struct nfs4_file *f) { kmem_cache_free(file_slab, f); } |
13cd21845 [PATCH] nfsd4: re... |
114 115 116 |
static inline void put_nfs4_file(struct nfs4_file *fi) { |
8b671b807 nfsd4: remove use... |
117 118 119 120 |
if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) { list_del(&fi->fi_hash); spin_unlock(&recall_lock); iput(fi->fi_inode); |
32513b40e nfsd4: preallocat... |
121 |
nfsd4_free_file(fi); |
8b671b807 nfsd4: remove use... |
122 |
} |
13cd21845 [PATCH] nfsd4: re... |
123 124 125 126 127 |
} static inline void get_nfs4_file(struct nfs4_file *fi) { |
8b671b807 nfsd4: remove use... |
128 |
atomic_inc(&fi->fi_ref); |
13cd21845 [PATCH] nfsd4: re... |
129 |
} |
ef0f3390e [PATCH] knfsd: nf... |
130 |
static int num_delegations; |
c2f1a551d knfsd: nfsd4: var... |
131 |
unsigned int max_delegations; |
ef0f3390e [PATCH] knfsd: nf... |
132 133 134 135 |
/* * Open owner state (share locks) */ |
16bfdaafa nfsd4: share open... |
136 137 138 139 |
/* hash tables for lock and open owners */ #define OWNER_HASH_BITS 8 #define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS) #define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1) |
ef0f3390e [PATCH] knfsd: nf... |
140 |
|
16bfdaafa nfsd4: share open... |
141 |
static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) |
ddc04c416 nfsd4: replace so... |
142 143 144 145 146 |
{ unsigned int ret; ret = opaque_hashval(ownername->data, ownername->len); ret += clientid; |
16bfdaafa nfsd4: share open... |
147 |
return ret & OWNER_HASH_MASK; |
ddc04c416 nfsd4: replace so... |
148 |
} |
ef0f3390e [PATCH] knfsd: nf... |
149 |
|
16bfdaafa nfsd4: share open... |
150 |
static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; |
ef0f3390e [PATCH] knfsd: nf... |
151 152 153 154 |
/* hash table for nfs4_file */ #define FILE_HASH_BITS 8 #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) |
35079582e nfsd: kill unused... |
155 |
|
ddc04c416 nfsd4: replace so... |
156 157 158 159 160 |
static unsigned int file_hashval(struct inode *ino) { /* XXX: why are we hashing on inode pointer, anyway? */ return hash_ptr(ino, FILE_HASH_BITS); } |
ef0f3390e [PATCH] knfsd: nf... |
161 |
static struct list_head file_hashtbl[FILE_HASH_SIZE]; |
ef0f3390e [PATCH] knfsd: nf... |
162 |
|
998db52c0 nfsd4: fix file o... |
163 |
static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag) |
f9d7562fd nfsd4: share file... |
164 165 166 167 |
{ BUG_ON(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR])); atomic_inc(&fp->fi_access[oflag]); } |
998db52c0 nfsd4: fix file o... |
168 169 170 171 172 173 174 175 176 177 |
static void nfs4_file_get_access(struct nfs4_file *fp, int oflag) { if (oflag == O_RDWR) { __nfs4_file_get_access(fp, O_RDONLY); __nfs4_file_get_access(fp, O_WRONLY); } else __nfs4_file_get_access(fp, oflag); } static void nfs4_file_put_fd(struct nfs4_file *fp, int oflag) |
f9d7562fd nfsd4: share file... |
178 179 180 181 182 183 |
{ if (fp->fi_fds[oflag]) { fput(fp->fi_fds[oflag]); fp->fi_fds[oflag] = NULL; } } |
998db52c0 nfsd4: fix file o... |
184 |
static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag) |
f9d7562fd nfsd4: share file... |
185 186 |
{ if (atomic_dec_and_test(&fp->fi_access[oflag])) { |
f9d7562fd nfsd4: share file... |
187 |
nfs4_file_put_fd(fp, oflag); |
3d02fa29d nfsd4: fix open d... |
188 189 190 191 192 193 194 195 |
/* * It's also safe to get rid of the RDWR open *if* * we no longer have need of the other kind of access * or if we already have the other kind of open: */ if (fp->fi_fds[1-oflag] || atomic_read(&fp->fi_access[1 - oflag]) == 0) nfs4_file_put_fd(fp, O_RDWR); |
f9d7562fd nfsd4: share file... |
196 197 |
} } |
998db52c0 nfsd4: fix file o... |
198 199 200 201 202 203 204 205 |
static void nfs4_file_put_access(struct nfs4_file *fp, int oflag) { if (oflag == O_RDWR) { __nfs4_file_put_access(fp, O_RDONLY); __nfs4_file_put_access(fp, O_WRONLY); } else __nfs4_file_put_access(fp, oflag); } |
6136d2b40 nfsd4: use idr fo... |
206 |
static inline int get_new_stid(struct nfs4_stid *stid) |
36d44c603 nfsd4: share comm... |
207 |
{ |
6136d2b40 nfsd4: use idr fo... |
208 |
static int min_stateid = 0; |
38c2f4b12 nfsd4: look up st... |
209 |
struct idr *stateids = &stid->sc_client->cl_stateids; |
6136d2b40 nfsd4: use idr fo... |
210 211 |
int new_stid; int error; |
38c2f4b12 nfsd4: look up st... |
212 |
error = idr_get_new_above(stateids, stid, min_stateid, &new_stid); |
6136d2b40 nfsd4: use idr fo... |
213 |
/* |
996e09385 nfsd4: do idr pre... |
214 215 216 217 |
* Note: the necessary preallocation was done in * nfs4_alloc_stateid(). The idr code caps the number of * preallocations that can exist at a time, but the state lock * prevents anyone from using ours before we get here: |
6136d2b40 nfsd4: use idr fo... |
218 219 220 221 222 223 224 225 226 227 228 |
*/ BUG_ON(error); /* * It shouldn't be a problem to reuse an opaque stateid value. * I don't think it is for 4.1. But with 4.0 I worry that, for * example, a stray write retransmission could be accepted by * the server when it should have been rejected. Therefore, * adopt a trick from the sctp code to attempt to maximize the * amount of time until an id is reused, by ensuring they always * "increase" (mod INT_MAX): */ |
36d44c603 nfsd4: share comm... |
229 |
|
6136d2b40 nfsd4: use idr fo... |
230 231 232 233 |
min_stateid = new_stid+1; if (min_stateid == INT_MAX) min_stateid = 0; return new_stid; |
36d44c603 nfsd4: share comm... |
234 |
} |
996e09385 nfsd4: do idr pre... |
235 |
static void init_stid(struct nfs4_stid *stid, struct nfs4_client *cl, unsigned char type) |
2a74aba79 nfsd4: move clien... |
236 237 |
{ stateid_t *s = &stid->sc_stateid; |
6136d2b40 nfsd4: use idr fo... |
238 |
int new_id; |
2a74aba79 nfsd4: move clien... |
239 240 241 242 |
stid->sc_type = type; stid->sc_client = cl; s->si_opaque.so_clid = cl->cl_clientid; |
6136d2b40 nfsd4: use idr fo... |
243 |
new_id = get_new_stid(stid); |
6136d2b40 nfsd4: use idr fo... |
244 |
s->si_opaque.so_id = (u32)new_id; |
2a74aba79 nfsd4: move clien... |
245 246 |
/* Will be incremented before return to client: */ s->si_generation = 0; |
996e09385 nfsd4: do idr pre... |
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
} static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab) { struct idr *stateids = &cl->cl_stateids; if (!idr_pre_get(stateids, GFP_KERNEL)) return NULL; /* * Note: if we fail here (or any time between now and the time * we actually get the new idr), we won't need to undo the idr * preallocation, since the idr code caps the number of * preallocated entries. */ return kmem_cache_alloc(slab, GFP_KERNEL); |
2a74aba79 nfsd4: move clien... |
262 |
} |
4cdc951b8 nfsd4: preallocat... |
263 264 265 266 |
static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp) { return openlockstateid(nfs4_alloc_stid(clp, stateid_slab)); } |
1da177e4c Linux-2.6.12-rc2 |
267 |
static struct nfs4_delegation * |
dcef0413d nfsd4: move some ... |
268 |
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type) |
1da177e4c Linux-2.6.12-rc2 |
269 270 271 |
{ struct nfs4_delegation *dp; struct nfs4_file *fp = stp->st_file; |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 |
dprintk("NFSD alloc_init_deleg "); |
c3e480808 nfsd4: don't pret... |
275 276 277 278 279 280 281 |
/* * Major work on the lease subsystem (for example, to support * calbacks on stat) will be required before we can support * write delegations properly. */ if (type != NFS4_OPEN_DELEGATE_READ) return NULL; |
47f9940c5 knfsd: nfsd4: don... |
282 283 |
if (fp->fi_had_conflict) return NULL; |
c2f1a551d knfsd: nfsd4: var... |
284 |
if (num_delegations > max_delegations) |
ef0f3390e [PATCH] knfsd: nf... |
285 |
return NULL; |
996e09385 nfsd4: do idr pre... |
286 |
dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); |
5b2d21c19 [PATCH] nfsd4: sl... |
287 |
if (dp == NULL) |
1da177e4c Linux-2.6.12-rc2 |
288 |
return dp; |
996e09385 nfsd4: do idr pre... |
289 |
init_stid(&dp->dl_stid, clp, NFS4_DELEG_STID); |
2a74aba79 nfsd4: move clien... |
290 291 |
/* * delegation seqid's are never incremented. The 4.1 special |
6136d2b40 nfsd4: use idr fo... |
292 293 |
* meaning of seqid 0 isn't meaningful, really, but let's avoid * 0 anyway just for consistency and use 1: |
2a74aba79 nfsd4: move clien... |
294 295 |
*/ dp->dl_stid.sc_stateid.si_generation = 1; |
ef0f3390e [PATCH] knfsd: nf... |
296 |
num_delegations++; |
ea1da636e [PATCH] knfsd: nf... |
297 298 |
INIT_LIST_HEAD(&dp->dl_perfile); INIT_LIST_HEAD(&dp->dl_perclnt); |
1da177e4c Linux-2.6.12-rc2 |
299 |
INIT_LIST_HEAD(&dp->dl_recall_lru); |
13cd21845 [PATCH] nfsd4: re... |
300 |
get_nfs4_file(fp); |
1da177e4c Linux-2.6.12-rc2 |
301 |
dp->dl_file = fp; |
1da177e4c Linux-2.6.12-rc2 |
302 |
dp->dl_type = type; |
6c02eaa1d nfsd4: use helper... |
303 |
fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); |
1da177e4c Linux-2.6.12-rc2 |
304 305 |
dp->dl_time = 0; atomic_set(&dp->dl_count, 1); |
b5a1a81e5 nfsd4: don't slee... |
306 |
INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc); |
1da177e4c Linux-2.6.12-rc2 |
307 308 309 310 311 312 313 314 315 |
return dp; } void nfs4_put_delegation(struct nfs4_delegation *dp) { if (atomic_dec_and_test(&dp->dl_count)) { dprintk("NFSD: freeing dp %p ",dp); |
13cd21845 [PATCH] nfsd4: re... |
316 |
put_nfs4_file(dp->dl_file); |
5b2d21c19 [PATCH] nfsd4: sl... |
317 |
kmem_cache_free(deleg_slab, dp); |
ef0f3390e [PATCH] knfsd: nf... |
318 |
num_delegations--; |
1da177e4c Linux-2.6.12-rc2 |
319 320 |
} } |
acfdf5c38 nfsd4: acquire on... |
321 |
static void nfs4_put_deleg_lease(struct nfs4_file *fp) |
1da177e4c Linux-2.6.12-rc2 |
322 |
{ |
acfdf5c38 nfsd4: acquire on... |
323 324 325 |
if (atomic_dec_and_test(&fp->fi_delegees)) { vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); fp->fi_lease = NULL; |
4ee63624f nfsd4: fix struct... |
326 |
fput(fp->fi_deleg_file); |
acfdf5c38 nfsd4: acquire on... |
327 328 |
fp->fi_deleg_file = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
329 |
} |
6136d2b40 nfsd4: use idr fo... |
330 331 |
static void unhash_stid(struct nfs4_stid *s) { |
38c2f4b12 nfsd4: look up st... |
332 333 334 |
struct idr *stateids = &s->sc_client->cl_stateids; idr_remove(stateids, s->sc_stateid.si_opaque.so_id); |
6136d2b40 nfsd4: use idr fo... |
335 |
} |
1da177e4c Linux-2.6.12-rc2 |
336 337 338 339 |
/* Called under the state lock. */ static void unhash_delegation(struct nfs4_delegation *dp) { |
6136d2b40 nfsd4: use idr fo... |
340 |
unhash_stid(&dp->dl_stid); |
ea1da636e [PATCH] knfsd: nf... |
341 |
list_del_init(&dp->dl_perclnt); |
1da177e4c Linux-2.6.12-rc2 |
342 |
spin_lock(&recall_lock); |
5d926e8c2 nfsd4: modify fi_... |
343 |
list_del_init(&dp->dl_perfile); |
1da177e4c Linux-2.6.12-rc2 |
344 345 |
list_del_init(&dp->dl_recall_lru); spin_unlock(&recall_lock); |
acfdf5c38 nfsd4: acquire on... |
346 |
nfs4_put_deleg_lease(dp->dl_file); |
1da177e4c Linux-2.6.12-rc2 |
347 348 349 350 351 352 |
nfs4_put_delegation(dp); } /* * SETCLIENTID state */ |
36acb66bd nfsd4: extend the... |
353 |
/* client_lock protects the client lru list and session hash table */ |
9089f1b47 nfsd4: rename ses... |
354 |
static DEFINE_SPINLOCK(client_lock); |
1da177e4c Linux-2.6.12-rc2 |
355 356 357 358 |
/* Hash tables for nfs4_clientid state */ #define CLIENT_HASH_BITS 4 #define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS) #define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1) |
ddc04c416 nfsd4: replace so... |
359 360 361 362 363 364 365 366 367 |
static unsigned int clientid_hashval(u32 id) { return id & CLIENT_HASH_MASK; } static unsigned int clientstr_hashval(const char *name) { return opaque_hashval(name, 8) & CLIENT_HASH_MASK; } |
1da177e4c Linux-2.6.12-rc2 |
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
/* * reclaim_str_hashtbl[] holds known client info from previous reset/reboot * used in reboot/reset lease grace period processing * * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed * setclientid_confirmed info. * * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed * setclientid info. * * client_lru holds client queue ordered by nfs4_client.cl_time * for lease renewal. * * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time * for last close replay. */ static struct list_head reclaim_str_hashtbl[CLIENT_HASH_SIZE]; static int reclaim_str_hashtbl_size = 0; static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE]; static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE]; static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE]; static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE]; static struct list_head client_lru; static struct list_head close_lru; |
f9d7562fd nfsd4: share file... |
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
/* * We store the NONE, READ, WRITE, and BOTH bits separately in the * st_{access,deny}_bmap field of the stateid, in order to track not * only what share bits are currently in force, but also what * combinations of share bits previous opens have used. This allows us * to enforce the recommendation of rfc 3530 14.2.19 that the server * return an error if the client attempt to downgrade to a combination * of share bits not explicable by closing some of its previous opens. * * XXX: This enforcement is actually incomplete, since we don't keep * track of access/deny bit combinations; so, e.g., we allow: * * OPEN allow read, deny write * OPEN allow both, deny none * DOWNGRADE allow read, deny none * * which we should reject. */ static void set_access(unsigned int *access, unsigned long bmap) { int i; *access = 0; for (i = 1; i < 4; i++) { if (test_bit(i, &bmap)) *access |= i; } } static void set_deny(unsigned int *deny, unsigned long bmap) { int i; *deny = 0; for (i = 0; i < 4; i++) { if (test_bit(i, &bmap)) *deny |= i ; } } static int |
dcef0413d nfsd4: move some ... |
433 |
test_share(struct nfs4_ol_stateid *stp, struct nfsd4_open *open) { |
f9d7562fd nfsd4: share file... |
434 435 436 437 438 439 440 441 442 443 444 |
unsigned int access, deny; set_access(&access, stp->st_access_bmap); set_deny(&deny, stp->st_deny_bmap); if ((access & open->op_share_deny) || (deny & open->op_share_access)) return 0; return 1; } static int nfs4_access_to_omode(u32 access) { |
8f34a430a nfsd4: mask out n... |
445 |
switch (access & NFS4_SHARE_ACCESS_BOTH) { |
f9d7562fd nfsd4: share file... |
446 447 448 449 450 451 452 453 454 |
case NFS4_SHARE_ACCESS_READ: return O_RDONLY; case NFS4_SHARE_ACCESS_WRITE: return O_WRONLY; case NFS4_SHARE_ACCESS_BOTH: return O_RDWR; } BUG(); } |
dcef0413d nfsd4: move some ... |
455 |
static void unhash_generic_stateid(struct nfs4_ol_stateid *stp) |
529d7b2a7 nfsd4: minor nfs4... |
456 |
{ |
529d7b2a7 nfsd4: minor nfs4... |
457 458 459 |
list_del(&stp->st_perfile); list_del(&stp->st_perstateowner); } |
dcef0413d nfsd4: move some ... |
460 |
static void close_generic_stateid(struct nfs4_ol_stateid *stp) |
529d7b2a7 nfsd4: minor nfs4... |
461 |
{ |
499f3edc2 nfsd4: remember t... |
462 |
int i; |
0997b1736 nfsd4: fix struct... |
463 |
|
23fcf2ec9 nfsd4: fix oops o... |
464 |
if (stp->st_access_bmap) { |
499f3edc2 nfsd4: remember t... |
465 466 467 468 |
for (i = 1; i < 4; i++) { if (test_bit(i, &stp->st_access_bmap)) nfs4_file_put_access(stp->st_file, nfs4_access_to_omode(i)); |
4665e2bac nfsd4: split out ... |
469 |
__clear_bit(i, &stp->st_access_bmap); |
499f3edc2 nfsd4: remember t... |
470 |
} |
23fcf2ec9 nfsd4: fix oops o... |
471 |
} |
a96e5b908 nfsd4: Fix filp leak |
472 |
put_nfs4_file(stp->st_file); |
4665e2bac nfsd4: split out ... |
473 474 |
stp->st_file = NULL; } |
dcef0413d nfsd4: move some ... |
475 |
static void free_generic_stateid(struct nfs4_ol_stateid *stp) |
4665e2bac nfsd4: split out ... |
476 |
{ |
529d7b2a7 nfsd4: minor nfs4... |
477 478 |
kmem_cache_free(stateid_slab, stp); } |
dcef0413d nfsd4: move some ... |
479 |
static void release_lock_stateid(struct nfs4_ol_stateid *stp) |
529d7b2a7 nfsd4: minor nfs4... |
480 481 482 483 |
{ struct file *file; unhash_generic_stateid(stp); |
6136d2b40 nfsd4: use idr fo... |
484 |
unhash_stid(&stp->st_stid); |
529d7b2a7 nfsd4: minor nfs4... |
485 486 |
file = find_any_file(stp->st_file); if (file) |
fe0750e5c nfsd4: split stat... |
487 |
locks_remove_posix(file, (fl_owner_t)lockowner(stp->st_stateowner)); |
38c387b52 nfsd4: match clos... |
488 |
close_generic_stateid(stp); |
529d7b2a7 nfsd4: minor nfs4... |
489 490 |
free_generic_stateid(stp); } |
fe0750e5c nfsd4: split stat... |
491 |
static void unhash_lockowner(struct nfs4_lockowner *lo) |
529d7b2a7 nfsd4: minor nfs4... |
492 |
{ |
dcef0413d nfsd4: move some ... |
493 |
struct nfs4_ol_stateid *stp; |
529d7b2a7 nfsd4: minor nfs4... |
494 |
|
fe0750e5c nfsd4: split stat... |
495 496 |
list_del(&lo->lo_owner.so_strhash); list_del(&lo->lo_perstateid); |
009673b43 nfsd4: add a sepa... |
497 |
list_del(&lo->lo_owner_ino_hash); |
fe0750e5c nfsd4: split stat... |
498 499 |
while (!list_empty(&lo->lo_owner.so_stateids)) { stp = list_first_entry(&lo->lo_owner.so_stateids, |
dcef0413d nfsd4: move some ... |
500 |
struct nfs4_ol_stateid, st_perstateowner); |
529d7b2a7 nfsd4: minor nfs4... |
501 502 503 |
release_lock_stateid(stp); } } |
fe0750e5c nfsd4: split stat... |
504 |
static void release_lockowner(struct nfs4_lockowner *lo) |
529d7b2a7 nfsd4: minor nfs4... |
505 |
{ |
fe0750e5c nfsd4: split stat... |
506 507 |
unhash_lockowner(lo); nfs4_free_lockowner(lo); |
529d7b2a7 nfsd4: minor nfs4... |
508 509 510 |
} static void |
dcef0413d nfsd4: move some ... |
511 |
release_stateid_lockowners(struct nfs4_ol_stateid *open_stp) |
529d7b2a7 nfsd4: minor nfs4... |
512 |
{ |
fe0750e5c nfsd4: split stat... |
513 |
struct nfs4_lockowner *lo; |
529d7b2a7 nfsd4: minor nfs4... |
514 515 |
while (!list_empty(&open_stp->st_lockowners)) { |
fe0750e5c nfsd4: split stat... |
516 517 518 |
lo = list_entry(open_stp->st_lockowners.next, struct nfs4_lockowner, lo_perstateid); release_lockowner(lo); |
529d7b2a7 nfsd4: minor nfs4... |
519 520 |
} } |
38c387b52 nfsd4: match clos... |
521 |
static void unhash_open_stateid(struct nfs4_ol_stateid *stp) |
2283963f2 nfsd4: split lock... |
522 523 524 |
{ unhash_generic_stateid(stp); release_stateid_lockowners(stp); |
38c387b52 nfsd4: match clos... |
525 526 527 528 529 530 |
close_generic_stateid(stp); } static void release_open_stateid(struct nfs4_ol_stateid *stp) { unhash_open_stateid(stp); |
6136d2b40 nfsd4: use idr fo... |
531 |
unhash_stid(&stp->st_stid); |
2283963f2 nfsd4: split lock... |
532 533 |
free_generic_stateid(stp); } |
fe0750e5c nfsd4: split stat... |
534 |
static void unhash_openowner(struct nfs4_openowner *oo) |
f1d110caf nfsd4: remove a f... |
535 |
{ |
dcef0413d nfsd4: move some ... |
536 |
struct nfs4_ol_stateid *stp; |
f1d110caf nfsd4: remove a f... |
537 |
|
fe0750e5c nfsd4: split stat... |
538 539 540 541 |
list_del(&oo->oo_owner.so_strhash); list_del(&oo->oo_perclient); while (!list_empty(&oo->oo_owner.so_stateids)) { stp = list_first_entry(&oo->oo_owner.so_stateids, |
dcef0413d nfsd4: move some ... |
542 |
struct nfs4_ol_stateid, st_perstateowner); |
f044ff830 nfsd4: split open... |
543 |
release_open_stateid(stp); |
f1d110caf nfsd4: remove a f... |
544 545 |
} } |
f7a4d8720 nfsd4: hash close... |
546 547 548 549 550 |
static void release_last_closed_stateid(struct nfs4_openowner *oo) { struct nfs4_ol_stateid *s = oo->oo_last_closed_stid; if (s) { |
6136d2b40 nfsd4: use idr fo... |
551 |
unhash_stid(&s->st_stid); |
f7a4d8720 nfsd4: hash close... |
552 553 554 555 |
free_generic_stateid(s); oo->oo_last_closed_stid = NULL; } } |
fe0750e5c nfsd4: split stat... |
556 |
static void release_openowner(struct nfs4_openowner *oo) |
f1d110caf nfsd4: remove a f... |
557 |
{ |
fe0750e5c nfsd4: split stat... |
558 559 |
unhash_openowner(oo); list_del(&oo->oo_close_lru); |
f7a4d8720 nfsd4: hash close... |
560 |
release_last_closed_stateid(oo); |
fe0750e5c nfsd4: split stat... |
561 |
nfs4_free_openowner(oo); |
f1d110caf nfsd4: remove a f... |
562 |
} |
5282fd724 nfsd41: sessionid... |
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
#define SESSION_HASH_SIZE 512 static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE]; static inline int hash_sessionid(struct nfs4_sessionid *sessionid) { struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)sessionid; return sid->sequence % SESSION_HASH_SIZE; } static inline void dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid) { u32 *ptr = (u32 *)(&sessionid->data[0]); dprintk("%s: %u:%u:%u:%u ", fn, ptr[0], ptr[1], ptr[2], ptr[3]); } |
ec6b5d7b5 nfsd41: create_se... |
581 582 583 584 585 586 587 588 589 590 591 592 593 |
static void gen_sessionid(struct nfsd4_session *ses) { struct nfs4_client *clp = ses->se_client; struct nfsd4_sessionid *sid; sid = (struct nfsd4_sessionid *)ses->se_sessionid.data; sid->clientid = clp->cl_clientid; sid->sequence = current_sessionid++; sid->reserved = 0; } /* |
a649637c7 nfsd41: bound for... |
594 595 596 597 598 599 600 601 602 603 604 605 |
* The protocol defines ca_maxresponssize_cached to include the size of * the rpc header, but all we need to cache is the data starting after * the end of the initial SEQUENCE operation--the rest we regenerate * each time. Therefore we can advertise a ca_maxresponssize_cached * value that is the number of bytes in our cache plus a few additional * bytes. In order to stay on the safe side, and not promise more than * we can cache, those additional bytes must be the minimum possible: 24 * bytes of rpc header (xid through accept state, with AUTH_NULL * verifier), 12 for the compound header (with zero-length tag), and 44 * for the SEQUENCE op response: */ #define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44) |
557ce2646 nfsd41: replace p... |
606 607 608 609 610 611 612 613 |
static void free_session_slots(struct nfsd4_session *ses) { int i; for (i = 0; i < ses->se_fchannel.maxreqs; i++) kfree(ses->se_slots[i]); } |
a649637c7 nfsd41: bound for... |
614 |
/* |
efe0cb6d5 nfsd4.1: common s... |
615 616 617 618 619 620 621 |
* We don't actually need to cache the rpc and session headers, so we * can allocate a little less for each slot: */ static inline int slot_bytes(struct nfsd4_channel_attrs *ca) { return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ; } |
5b6feee96 nfsd4: clean up s... |
622 |
static int nfsd4_sanitize_slot_size(u32 size) |
ec6b5d7b5 nfsd41: create_se... |
623 |
{ |
5b6feee96 nfsd4: clean up s... |
624 625 |
size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */ size = min_t(u32, size, NFSD_SLOT_CACHE_SIZE); |
ec6b5d7b5 nfsd41: create_se... |
626 |
|
5b6feee96 nfsd4: clean up s... |
627 628 |
return size; } |
ec6b5d7b5 nfsd41: create_se... |
629 |
|
5b6feee96 nfsd4: clean up s... |
630 631 |
/* * XXX: If we run out of reserved DRC memory we could (up to a point) |
a649637c7 nfsd41: bound for... |
632 |
* re-negotiate active sessions and reduce their slot usage to make |
42b2aa86c treewide: Fix typ... |
633 |
* room for new connections. For now we just fail the create session. |
ec6b5d7b5 nfsd41: create_se... |
634 |
*/ |
5b6feee96 nfsd4: clean up s... |
635 |
static int nfsd4_get_drc_mem(int slotsize, u32 num) |
ec6b5d7b5 nfsd41: create_se... |
636 |
{ |
5b6feee96 nfsd4: clean up s... |
637 |
int avail; |
ec6b5d7b5 nfsd41: create_se... |
638 |
|
5b6feee96 nfsd4: clean up s... |
639 |
num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION); |
5d77ddfbc nfsd41: sanity ch... |
640 |
|
5b6feee96 nfsd4: clean up s... |
641 642 643 644 645 646 |
spin_lock(&nfsd_drc_lock); avail = min_t(int, NFSD_MAX_MEM_PER_SESSION, nfsd_drc_max_mem - nfsd_drc_mem_used); num = min_t(int, num, avail / slotsize); nfsd_drc_mem_used += num * slotsize; spin_unlock(&nfsd_drc_lock); |
ec6b5d7b5 nfsd41: create_se... |
647 |
|
5b6feee96 nfsd4: clean up s... |
648 649 |
return num; } |
ec6b5d7b5 nfsd41: create_se... |
650 |
|
5b6feee96 nfsd4: clean up s... |
651 652 |
static void nfsd4_put_drc_mem(int slotsize, int num) { |
4bd9b0f4a nfsd41: use globa... |
653 |
spin_lock(&nfsd_drc_lock); |
5b6feee96 nfsd4: clean up s... |
654 |
nfsd_drc_mem_used -= slotsize * num; |
4bd9b0f4a nfsd41: use globa... |
655 |
spin_unlock(&nfsd_drc_lock); |
5b6feee96 nfsd4: clean up s... |
656 |
} |
ec6b5d7b5 nfsd41: create_se... |
657 |
|
5b6feee96 nfsd4: clean up s... |
658 659 660 661 |
static struct nfsd4_session *alloc_session(int slotsize, int numslots) { struct nfsd4_session *new; int mem, i; |
a649637c7 nfsd41: bound for... |
662 |
|
5b6feee96 nfsd4: clean up s... |
663 664 665 |
BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *) + sizeof(struct nfsd4_session) > PAGE_SIZE); mem = numslots * sizeof(struct nfsd4_slot *); |
ec6b5d7b5 nfsd41: create_se... |
666 |
|
5b6feee96 nfsd4: clean up s... |
667 668 669 |
new = kzalloc(sizeof(*new) + mem, GFP_KERNEL); if (!new) return NULL; |
557ce2646 nfsd41: replace p... |
670 |
/* allocate each struct nfsd4_slot and data cache in one piece */ |
5b6feee96 nfsd4: clean up s... |
671 672 673 674 |
for (i = 0; i < numslots; i++) { mem = sizeof(struct nfsd4_slot) + slotsize; new->se_slots[i] = kzalloc(mem, GFP_KERNEL); if (!new->se_slots[i]) |
557ce2646 nfsd41: replace p... |
675 |
goto out_free; |
557ce2646 nfsd41: replace p... |
676 |
} |
5b6feee96 nfsd4: clean up s... |
677 678 679 680 681 682 |
return new; out_free: while (i--) kfree(new->se_slots[i]); kfree(new); return NULL; |
ec6b5d7b5 nfsd41: create_se... |
683 |
} |
5b6feee96 nfsd4: clean up s... |
684 |
static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize) |
ec6b5d7b5 nfsd41: create_se... |
685 |
{ |
5b6feee96 nfsd4: clean up s... |
686 |
u32 maxrpc = nfsd_serv->sv_max_mesg; |
ec6b5d7b5 nfsd41: create_se... |
687 |
|
5b6feee96 nfsd4: clean up s... |
688 |
new->maxreqs = numslots; |
d2b217439 nfs41: make sure ... |
689 690 |
new->maxresp_cached = min_t(u32, req->maxresp_cached, slotsize + NFSD_MIN_HDR_SEQ_SZ); |
5b6feee96 nfsd4: clean up s... |
691 692 693 694 |
new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc); new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc); new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); } |
ec6b5d7b5 nfsd41: create_se... |
695 |
|
19cf5c026 nfsd4: use callba... |
696 697 698 699 700 |
static void free_conn(struct nfsd4_conn *c) { svc_xprt_put(c->cn_xprt); kfree(c); } |
ec6b5d7b5 nfsd41: create_se... |
701 |
|
19cf5c026 nfsd4: use callba... |
702 703 704 705 |
static void nfsd4_conn_lost(struct svc_xpt_user *u) { struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user); struct nfs4_client *clp = c->cn_session->se_client; |
ec6b5d7b5 nfsd41: create_se... |
706 |
|
19cf5c026 nfsd4: use callba... |
707 708 709 710 711 712 |
spin_lock(&clp->cl_lock); if (!list_empty(&c->cn_persession)) { list_del(&c->cn_persession); free_conn(c); } spin_unlock(&clp->cl_lock); |
eea498066 nfsd4: re-probe c... |
713 |
nfsd4_probe_callback(clp); |
19cf5c026 nfsd4: use callba... |
714 |
} |
ec6b5d7b5 nfsd41: create_se... |
715 |
|
d29c374cd nfsd4: track back... |
716 |
static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags) |
c7662518c nfsd4: keep per-s... |
717 |
{ |
c7662518c nfsd4: keep per-s... |
718 |
struct nfsd4_conn *conn; |
ec6b5d7b5 nfsd41: create_se... |
719 |
|
c7662518c nfsd4: keep per-s... |
720 721 |
conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL); if (!conn) |
db90681d6 nfsd4: refactor c... |
722 |
return NULL; |
c7662518c nfsd4: keep per-s... |
723 724 |
svc_xprt_get(rqstp->rq_xprt); conn->cn_xprt = rqstp->rq_xprt; |
d29c374cd nfsd4: track back... |
725 |
conn->cn_flags = flags; |
db90681d6 nfsd4: refactor c... |
726 727 728 |
INIT_LIST_HEAD(&conn->cn_xpt_user.list); return conn; } |
a649637c7 nfsd41: bound for... |
729 |
|
328ead287 nfsd4: add new co... |
730 731 732 733 |
static void __nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses) { conn->cn_session = ses; list_add(&conn->cn_persession, &ses->se_conns); |
ec6b5d7b5 nfsd41: create_se... |
734 |
} |
db90681d6 nfsd4: refactor c... |
735 |
static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses) |
557ce2646 nfsd41: replace p... |
736 |
{ |
db90681d6 nfsd4: refactor c... |
737 |
struct nfs4_client *clp = ses->se_client; |
557ce2646 nfsd41: replace p... |
738 |
|
c7662518c nfsd4: keep per-s... |
739 |
spin_lock(&clp->cl_lock); |
328ead287 nfsd4: add new co... |
740 |
__nfsd4_hash_conn(conn, ses); |
c7662518c nfsd4: keep per-s... |
741 |
spin_unlock(&clp->cl_lock); |
557ce2646 nfsd41: replace p... |
742 |
} |
21b75b019 nfsd4: fix 4.1 co... |
743 |
static int nfsd4_register_conn(struct nfsd4_conn *conn) |
efe0cb6d5 nfsd4.1: common s... |
744 |
{ |
19cf5c026 nfsd4: use callba... |
745 |
conn->cn_xpt_user.callback = nfsd4_conn_lost; |
21b75b019 nfsd4: fix 4.1 co... |
746 |
return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); |
efe0cb6d5 nfsd4.1: common s... |
747 |
} |
1d1bc8f20 nfsd4: support BI... |
748 |
static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) |
ec6b5d7b5 nfsd41: create_se... |
749 |
{ |
db90681d6 nfsd4: refactor c... |
750 |
struct nfsd4_conn *conn; |
21b75b019 nfsd4: fix 4.1 co... |
751 |
int ret; |
ec6b5d7b5 nfsd41: create_se... |
752 |
|
1d1bc8f20 nfsd4: support BI... |
753 |
conn = alloc_conn(rqstp, dir); |
db90681d6 nfsd4: refactor c... |
754 755 756 |
if (!conn) return nfserr_jukebox; nfsd4_hash_conn(conn, ses); |
21b75b019 nfsd4: fix 4.1 co... |
757 758 759 760 |
ret = nfsd4_register_conn(conn); if (ret) /* oops; xprt is already down: */ nfsd4_conn_lost(&conn->cn_xpt_user); |
c7662518c nfsd4: keep per-s... |
761 762 |
return nfs_ok; } |
ec6b5d7b5 nfsd41: create_se... |
763 |
|
1d1bc8f20 nfsd4: support BI... |
764 765 766 767 768 769 770 771 772 773 774 |
static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) { u32 dir = NFS4_CDFC4_FORE; if (ses->se_flags & SESSION4_BACK_CHAN) dir |= NFS4_CDFC4_BACK; return nfsd4_new_conn(rqstp, ses, dir); } /* must be called under client_lock */ |
19cf5c026 nfsd4: use callba... |
775 |
static void nfsd4_del_conns(struct nfsd4_session *s) |
c7662518c nfsd4: keep per-s... |
776 |
{ |
19cf5c026 nfsd4: use callba... |
777 778 |
struct nfs4_client *clp = s->se_client; struct nfsd4_conn *c; |
ec6b5d7b5 nfsd41: create_se... |
779 |
|
19cf5c026 nfsd4: use callba... |
780 781 782 783 784 |
spin_lock(&clp->cl_lock); while (!list_empty(&s->se_conns)) { c = list_first_entry(&s->se_conns, struct nfsd4_conn, cn_persession); list_del_init(&c->cn_persession); spin_unlock(&clp->cl_lock); |
557ce2646 nfsd41: replace p... |
785 |
|
19cf5c026 nfsd4: use callba... |
786 787 |
unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user); free_conn(c); |
ec6b5d7b5 nfsd41: create_se... |
788 |
|
19cf5c026 nfsd4: use callba... |
789 790 791 |
spin_lock(&clp->cl_lock); } spin_unlock(&clp->cl_lock); |
c7662518c nfsd4: keep per-s... |
792 |
} |
ec6b5d7b5 nfsd41: create_se... |
793 |
|
c7662518c nfsd4: keep per-s... |
794 795 796 797 798 799 |
void free_session(struct kref *kref) { struct nfsd4_session *ses; int mem; ses = container_of(kref, struct nfsd4_session, se_ref); |
19cf5c026 nfsd4: use callba... |
800 |
nfsd4_del_conns(ses); |
c7662518c nfsd4: keep per-s... |
801 802 803 804 805 806 807 |
spin_lock(&nfsd_drc_lock); mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel); nfsd_drc_mem_used -= mem; spin_unlock(&nfsd_drc_lock); free_session_slots(ses); kfree(ses); } |
ac7c46f29 nfsd4: make backc... |
808 |
static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) |
5b6feee96 nfsd4: clean up s... |
809 810 811 812 |
{ struct nfsd4_session *new; struct nfsd4_channel_attrs *fchan = &cses->fore_channel; int numslots, slotsize; |
c7662518c nfsd4: keep per-s... |
813 |
int status; |
5b6feee96 nfsd4: clean up s... |
814 815 816 817 818 819 820 821 822 823 824 |
int idx; /* * Note decreasing slot size below client's request may * make it difficult for client to function correctly, whereas * decreasing the number of slots will (just?) affect * performance. When short on memory we therefore prefer to * decrease number of slots instead of their size. */ slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached); numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs); |
ced6dfe9f NFS4.1: server ge... |
825 826 |
if (numslots < 1) return NULL; |
5b6feee96 nfsd4: clean up s... |
827 828 829 830 |
new = alloc_session(slotsize, numslots); if (!new) { nfsd4_put_drc_mem(slotsize, fchan->maxreqs); |
ac7c46f29 nfsd4: make backc... |
831 |
return NULL; |
557ce2646 nfsd41: replace p... |
832 |
} |
5b6feee96 nfsd4: clean up s... |
833 |
init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); |
557ce2646 nfsd41: replace p... |
834 |
|
ec6b5d7b5 nfsd41: create_se... |
835 836 |
new->se_client = clp; gen_sessionid(new); |
ec6b5d7b5 nfsd41: create_se... |
837 |
|
c7662518c nfsd4: keep per-s... |
838 |
INIT_LIST_HEAD(&new->se_conns); |
ac7c46f29 nfsd4: make backc... |
839 |
new->se_cb_seq_nr = 1; |
ec6b5d7b5 nfsd41: create_se... |
840 |
new->se_flags = cses->flags; |
8b5ce5cd4 nfsd4: callback p... |
841 |
new->se_cb_prog = cses->callback_prog; |
ec6b5d7b5 nfsd41: create_se... |
842 |
kref_init(&new->se_ref); |
5b6feee96 nfsd4: clean up s... |
843 |
idx = hash_sessionid(&new->se_sessionid); |
9089f1b47 nfsd4: rename ses... |
844 |
spin_lock(&client_lock); |
ec6b5d7b5 nfsd41: create_se... |
845 |
list_add(&new->se_hash, &sessionid_hashtbl[idx]); |
4c6493785 nfsd4: modify ses... |
846 |
spin_lock(&clp->cl_lock); |
ec6b5d7b5 nfsd41: create_se... |
847 |
list_add(&new->se_perclnt, &clp->cl_sessions); |
4c6493785 nfsd4: modify ses... |
848 |
spin_unlock(&clp->cl_lock); |
9089f1b47 nfsd4: rename ses... |
849 |
spin_unlock(&client_lock); |
ec6b5d7b5 nfsd41: create_se... |
850 |
|
1d1bc8f20 nfsd4: support BI... |
851 |
status = nfsd4_new_conn_from_crses(rqstp, new); |
ac7c46f29 nfsd4: make backc... |
852 |
/* whoops: benny points out, status is ignored! (err, or bogus) */ |
c7662518c nfsd4: keep per-s... |
853 854 |
if (status) { free_session(&new->se_ref); |
ac7c46f29 nfsd4: make backc... |
855 |
return NULL; |
c7662518c nfsd4: keep per-s... |
856 |
} |
dcbeaa68d nfsd4: allow back... |
857 |
if (cses->flags & SESSION4_BACK_CHAN) { |
edd767866 nfsd4: move callb... |
858 |
struct sockaddr *sa = svc_addr(rqstp); |
dcbeaa68d nfsd4: allow back... |
859 860 861 862 863 864 865 |
/* * This is a little silly; with sessions there's no real * use for the callback address. Use the peer address * as a reasonable default for now, but consider fixing * the rpc client not to require an address in the * future: */ |
edd767866 nfsd4: move callb... |
866 867 |
rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); |
edd767866 nfsd4: move callb... |
868 |
} |
dcbeaa68d nfsd4: allow back... |
869 |
nfsd4_probe_callback(clp); |
ac7c46f29 nfsd4: make backc... |
870 |
return new; |
ec6b5d7b5 nfsd41: create_se... |
871 |
} |
9089f1b47 nfsd4: rename ses... |
872 |
/* caller must hold client_lock */ |
5282fd724 nfsd41: sessionid... |
873 874 875 876 877 878 879 880 |
static struct nfsd4_session * find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid) { struct nfsd4_session *elem; int idx; dump_sessionid(__func__, sessionid); idx = hash_sessionid(sessionid); |
5282fd724 nfsd41: sessionid... |
881 882 |
/* Search in the appropriate list */ list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) { |
5282fd724 nfsd41: sessionid... |
883 884 885 886 887 888 889 890 891 892 |
if (!memcmp(elem->se_sessionid.data, sessionid->data, NFS4_MAX_SESSIONID_LEN)) { return elem; } } dprintk("%s: session not found ", __func__); return NULL; } |
9089f1b47 nfsd4: rename ses... |
893 |
/* caller must hold client_lock */ |
7116ed6b9 nfsd41: sessions ... |
894 |
static void |
5282fd724 nfsd41: sessionid... |
895 |
unhash_session(struct nfsd4_session *ses) |
7116ed6b9 nfsd41: sessions ... |
896 897 |
{ list_del(&ses->se_hash); |
4c6493785 nfsd4: modify ses... |
898 |
spin_lock(&ses->se_client->cl_lock); |
7116ed6b9 nfsd41: sessions ... |
899 |
list_del(&ses->se_perclnt); |
4c6493785 nfsd4: modify ses... |
900 |
spin_unlock(&ses->se_client->cl_lock); |
5282fd724 nfsd41: sessionid... |
901 |
} |
36acb66bd nfsd4: extend the... |
902 |
/* must be called under the client_lock */ |
1da177e4c Linux-2.6.12-rc2 |
903 |
static inline void |
36acb66bd nfsd4: extend the... |
904 |
renew_client_locked(struct nfs4_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
905 |
{ |
07cd4909a nfsd4: mark_clien... |
906 907 908 909 910 911 912 913 |
if (is_client_expired(clp)) { dprintk("%s: client (clientid %08x/%08x) already expired ", __func__, clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); return; } |
1da177e4c Linux-2.6.12-rc2 |
914 915 916 917 918 919 920 |
dprintk("renewing client (clientid %08x/%08x) ", clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); list_move_tail(&clp->cl_lru, &client_lru); clp->cl_time = get_seconds(); } |
36acb66bd nfsd4: extend the... |
921 922 923 924 925 926 927 |
static inline void renew_client(struct nfs4_client *clp) { spin_lock(&client_lock); renew_client_locked(clp); spin_unlock(&client_lock); } |
1da177e4c Linux-2.6.12-rc2 |
928 929 930 931 932 933 |
/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ static int STALE_CLIENTID(clientid_t *clid) { if (clid->cl_boot == boot_time) return 0; |
60adfc50d nfsd41: clientid ... |
934 935 936 |
dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx ", clid->cl_boot, clid->cl_id, boot_time); |
1da177e4c Linux-2.6.12-rc2 |
937 938 939 940 941 942 943 944 |
return 1; } /* * XXX Should we use a slab cache ? * This type of memory management is somewhat inefficient, but we use it * anyway since SETCLIENTID is not a common operation. */ |
35bba9a37 nfsd4: miscellane... |
945 |
static struct nfs4_client *alloc_client(struct xdr_netobj name) |
1da177e4c Linux-2.6.12-rc2 |
946 947 |
{ struct nfs4_client *clp; |
35bba9a37 nfsd4: miscellane... |
948 949 950 |
clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL); if (clp == NULL) return NULL; |
67114fe61 nfsd4: Use kmemdu... |
951 |
clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL); |
35bba9a37 nfsd4: miscellane... |
952 953 954 |
if (clp->cl_name.data == NULL) { kfree(clp); return NULL; |
1da177e4c Linux-2.6.12-rc2 |
955 |
} |
35bba9a37 nfsd4: miscellane... |
956 |
clp->cl_name.len = name.len; |
1da177e4c Linux-2.6.12-rc2 |
957 958 959 960 961 962 |
return clp; } static inline void free_client(struct nfs4_client *clp) { |
792c95dd5 nfsd4: delay sess... |
963 964 965 966 967 968 969 |
while (!list_empty(&clp->cl_sessions)) { struct nfsd4_session *ses; ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, se_perclnt); list_del(&ses->se_perclnt); nfsd4_put_session(ses); } |
1da177e4c Linux-2.6.12-rc2 |
970 971 |
if (clp->cl_cred.cr_group_info) put_group_info(clp->cl_cred.cr_group_info); |
68e76ad0b nfsd: pass client... |
972 |
kfree(clp->cl_principal); |
1da177e4c Linux-2.6.12-rc2 |
973 974 975 |
kfree(clp->cl_name.data); kfree(clp); } |
d76829889 nfsd4: keep a ref... |
976 977 978 979 980 981 982 983 984 985 986 987 988 |
void release_session_client(struct nfsd4_session *session) { struct nfs4_client *clp = session->se_client; if (!atomic_dec_and_lock(&clp->cl_refcount, &client_lock)) return; if (is_client_expired(clp)) { free_client(clp); session->se_client = NULL; } else renew_client_locked(clp); spin_unlock(&client_lock); |
d76829889 nfsd4: keep a ref... |
989 |
} |
84d38ac9a nfsd4: refactor e... |
990 991 992 993 |
/* must be called under the client_lock */ static inline void unhash_client_locked(struct nfs4_client *clp) { |
792c95dd5 nfsd4: delay sess... |
994 |
struct nfsd4_session *ses; |
07cd4909a nfsd4: mark_clien... |
995 |
mark_client_expired(clp); |
84d38ac9a nfsd4: refactor e... |
996 |
list_del(&clp->cl_lru); |
4c6493785 nfsd4: modify ses... |
997 |
spin_lock(&clp->cl_lock); |
792c95dd5 nfsd4: delay sess... |
998 999 |
list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) list_del_init(&ses->se_hash); |
4c6493785 nfsd4: modify ses... |
1000 |
spin_unlock(&clp->cl_lock); |
84d38ac9a nfsd4: refactor e... |
1001 |
} |
1da177e4c Linux-2.6.12-rc2 |
1002 1003 1004 |
static void expire_client(struct nfs4_client *clp) { |
fe0750e5c nfsd4: split stat... |
1005 |
struct nfs4_openowner *oo; |
1da177e4c Linux-2.6.12-rc2 |
1006 |
struct nfs4_delegation *dp; |
1da177e4c Linux-2.6.12-rc2 |
1007 |
struct list_head reaplist; |
1da177e4c Linux-2.6.12-rc2 |
1008 1009 |
INIT_LIST_HEAD(&reaplist); spin_lock(&recall_lock); |
ea1da636e [PATCH] knfsd: nf... |
1010 1011 |
while (!list_empty(&clp->cl_delegations)) { dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt); |
ea1da636e [PATCH] knfsd: nf... |
1012 |
list_del_init(&dp->dl_perclnt); |
1da177e4c Linux-2.6.12-rc2 |
1013 1014 1015 1016 1017 |
list_move(&dp->dl_recall_lru, &reaplist); } spin_unlock(&recall_lock); while (!list_empty(&reaplist)) { dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); |
1da177e4c Linux-2.6.12-rc2 |
1018 1019 |
unhash_delegation(dp); } |
ea1da636e [PATCH] knfsd: nf... |
1020 |
while (!list_empty(&clp->cl_openowners)) { |
fe0750e5c nfsd4: split stat... |
1021 1022 |
oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); release_openowner(oo); |
1da177e4c Linux-2.6.12-rc2 |
1023 |
} |
6ff8da088 nfsd4: Move callb... |
1024 |
nfsd4_shutdown_callback(clp); |
84d38ac9a nfsd4: refactor e... |
1025 1026 |
if (clp->cl_cb_conn.cb_xprt) svc_xprt_put(clp->cl_cb_conn.cb_xprt); |
36acb66bd nfsd4: extend the... |
1027 1028 |
list_del(&clp->cl_idhash); list_del(&clp->cl_strhash); |
be1fdf6c4 nfsd4: fold relea... |
1029 |
spin_lock(&client_lock); |
84d38ac9a nfsd4: refactor e... |
1030 |
unhash_client_locked(clp); |
46583e259 nfsd4: introduce ... |
1031 1032 |
if (atomic_read(&clp->cl_refcount) == 0) free_client(clp); |
be1fdf6c4 nfsd4: fold relea... |
1033 |
spin_unlock(&client_lock); |
1da177e4c Linux-2.6.12-rc2 |
1034 |
} |
35bba9a37 nfsd4: miscellane... |
1035 1036 1037 1038 |
static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) { memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data)); |
1da177e4c Linux-2.6.12-rc2 |
1039 |
} |
35bba9a37 nfsd4: miscellane... |
1040 1041 |
static void copy_clid(struct nfs4_client *target, struct nfs4_client *source) { |
1da177e4c Linux-2.6.12-rc2 |
1042 1043 1044 |
target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; target->cl_clientid.cl_id = source->cl_clientid.cl_id; } |
35bba9a37 nfsd4: miscellane... |
1045 1046 |
static void copy_cred(struct svc_cred *target, struct svc_cred *source) { |
1da177e4c Linux-2.6.12-rc2 |
1047 1048 1049 1050 1051 |
target->cr_uid = source->cr_uid; target->cr_gid = source->cr_gid; target->cr_group_info = source->cr_group_info; get_group_info(target->cr_group_info); } |
35bba9a37 nfsd4: miscellane... |
1052 |
static int same_name(const char *n1, const char *n2) |
599e0a229 knfsd: cleanup of... |
1053 |
{ |
a55370a3c [PATCH] knfsd: nf... |
1054 |
return 0 == memcmp(n1, n2, HEXDIR_LEN); |
1da177e4c Linux-2.6.12-rc2 |
1055 1056 1057 |
} static int |
599e0a229 knfsd: cleanup of... |
1058 1059 1060 |
same_verf(nfs4_verifier *v1, nfs4_verifier *v2) { return 0 == memcmp(v1->data, v2->data, sizeof(v1->data)); |
1da177e4c Linux-2.6.12-rc2 |
1061 1062 1063 |
} static int |
599e0a229 knfsd: cleanup of... |
1064 1065 1066 |
same_clid(clientid_t *cl1, clientid_t *cl2) { return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id); |
1da177e4c Linux-2.6.12-rc2 |
1067 1068 1069 1070 |
} /* XXX what about NGROUP */ static int |
599e0a229 knfsd: cleanup of... |
1071 1072 1073 |
same_creds(struct svc_cred *cr1, struct svc_cred *cr2) { return cr1->cr_uid == cr2->cr_uid; |
1da177e4c Linux-2.6.12-rc2 |
1074 |
} |
5ec7b46c2 nfsd4: make curre... |
1075 1076 1077 |
static void gen_clid(struct nfs4_client *clp) { static u32 current_clientid = 1; |
1da177e4c Linux-2.6.12-rc2 |
1078 1079 1080 |
clp->cl_clientid.cl_boot = boot_time; clp->cl_clientid.cl_id = current_clientid++; } |
deda2faa8 nfsd: uniquify cl... |
1081 1082 1083 1084 |
static void gen_confirm(struct nfs4_client *clp) { static u32 i; u32 *p; |
1da177e4c Linux-2.6.12-rc2 |
1085 |
|
1da177e4c Linux-2.6.12-rc2 |
1086 |
p = (u32 *)clp->cl_confirm.data; |
deda2faa8 nfsd: uniquify cl... |
1087 1088 |
*p++ = get_seconds(); *p++ = i++; |
1da177e4c Linux-2.6.12-rc2 |
1089 |
} |
38c2f4b12 nfsd4: look up st... |
1090 |
static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) |
4581d1409 nfsd4: rearrange ... |
1091 |
{ |
38c2f4b12 nfsd4: look up st... |
1092 |
return idr_find(&cl->cl_stateids, t->si_opaque.so_id); |
4d71ab875 nfsd4: split up f... |
1093 |
} |
38c2f4b12 nfsd4: look up st... |
1094 |
static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) |
f459e4535 nfsd4: hash deleg... |
1095 1096 |
{ struct nfs4_stid *s; |
4d71ab875 nfsd4: split up f... |
1097 |
|
38c2f4b12 nfsd4: look up st... |
1098 |
s = find_stateid(cl, t); |
4d71ab875 nfsd4: split up f... |
1099 1100 |
if (!s) return NULL; |
f459e4535 nfsd4: hash deleg... |
1101 |
if (typemask & s->sc_type) |
4581d1409 nfsd4: rearrange ... |
1102 |
return s; |
4581d1409 nfsd4: rearrange ... |
1103 1104 |
return NULL; } |
b09333c46 nfsd41: Refactor ... |
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 |
static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, struct svc_rqst *rqstp, nfs4_verifier *verf) { struct nfs4_client *clp; struct sockaddr *sa = svc_addr(rqstp); char *princ; clp = alloc_client(name); if (clp == NULL) return NULL; |
792c95dd5 nfsd4: delay sess... |
1115 |
INIT_LIST_HEAD(&clp->cl_sessions); |
b09333c46 nfsd41: Refactor ... |
1116 1117 1118 1119 1120 1121 1122 1123 |
princ = svc_gss_principal(rqstp); if (princ) { clp->cl_principal = kstrdup(princ, GFP_KERNEL); if (clp->cl_principal == NULL) { free_client(clp); return NULL; } } |
38c2f4b12 nfsd4: look up st... |
1124 |
idr_init(&clp->cl_stateids); |
b09333c46 nfsd41: Refactor ... |
1125 |
memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); |
46583e259 nfsd4: introduce ... |
1126 |
atomic_set(&clp->cl_refcount, 0); |
77a3569d6 nfsd4: keep finer... |
1127 |
clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
b09333c46 nfsd41: Refactor ... |
1128 1129 1130 1131 |
INIT_LIST_HEAD(&clp->cl_idhash); INIT_LIST_HEAD(&clp->cl_strhash); INIT_LIST_HEAD(&clp->cl_openowners); INIT_LIST_HEAD(&clp->cl_delegations); |
b09333c46 nfsd41: Refactor ... |
1132 |
INIT_LIST_HEAD(&clp->cl_lru); |
5ce8ba25d nfsd4: allow rest... |
1133 |
INIT_LIST_HEAD(&clp->cl_callbacks); |
6ff8da088 nfsd4: Move callb... |
1134 |
spin_lock_init(&clp->cl_lock); |
cee277d92 nfsd4: use generi... |
1135 |
INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc); |
07cd4909a nfsd4: mark_clien... |
1136 |
clp->cl_time = get_seconds(); |
b09333c46 nfsd41: Refactor ... |
1137 1138 1139 1140 1141 1142 1143 |
clear_bit(0, &clp->cl_cb_slot_busy); rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); copy_verf(clp, verf); rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa); clp->cl_flavor = rqstp->rq_flavor; copy_cred(&clp->cl_cred, &rqstp->rq_cred); gen_confirm(clp); |
edd767866 nfsd4: move callb... |
1144 |
clp->cl_cb_session = NULL; |
b09333c46 nfsd41: Refactor ... |
1145 1146 |
return clp; } |
fd39ca9a8 [PATCH] knfsd: nf... |
1147 |
static void |
1da177e4c Linux-2.6.12-rc2 |
1148 1149 1150 1151 1152 1153 1154 |
add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) { unsigned int idhashval; list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]); idhashval = clientid_hashval(clp->cl_clientid.cl_id); list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]); |
36acb66bd nfsd4: extend the... |
1155 |
renew_client(clp); |
1da177e4c Linux-2.6.12-rc2 |
1156 |
} |
fd39ca9a8 [PATCH] knfsd: nf... |
1157 |
static void |
1da177e4c Linux-2.6.12-rc2 |
1158 1159 1160 1161 1162 1163 1164 |
move_to_confirmed(struct nfs4_client *clp) { unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id); unsigned int strhashval; dprintk("NFSD: move_to_confirm nfs4_client %p ", clp); |
f116629d0 [PATCH] fs: use l... |
1165 |
list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); |
a55370a3c [PATCH] knfsd: nf... |
1166 |
strhashval = clientstr_hashval(clp->cl_recdir); |
328efbab0 nfsd4: use list_m... |
1167 |
list_move(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); |
1da177e4c Linux-2.6.12-rc2 |
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 |
renew_client(clp); } static struct nfs4_client * find_confirmed_client(clientid_t *clid) { struct nfs4_client *clp; unsigned int idhashval = clientid_hashval(clid->cl_id); list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { |
a50d2ad17 nfsd4: centralize... |
1178 1179 |
if (same_clid(&clp->cl_clientid, clid)) { renew_client(clp); |
1da177e4c Linux-2.6.12-rc2 |
1180 |
return clp; |
a50d2ad17 nfsd4: centralize... |
1181 |
} |
1da177e4c Linux-2.6.12-rc2 |
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 |
} return NULL; } static struct nfs4_client * find_unconfirmed_client(clientid_t *clid) { struct nfs4_client *clp; unsigned int idhashval = clientid_hashval(clid->cl_id); list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { |
599e0a229 knfsd: cleanup of... |
1193 |
if (same_clid(&clp->cl_clientid, clid)) |
1da177e4c Linux-2.6.12-rc2 |
1194 1195 1196 1197 |
return clp; } return NULL; } |
6e5f15c93 nfsd4: replace un... |
1198 |
static bool clp_used_exchangeid(struct nfs4_client *clp) |
a1bcecd29 nfsd41: match cli... |
1199 |
{ |
6e5f15c93 nfsd4: replace un... |
1200 |
return clp->cl_exchange_flags != 0; |
e203d506b nfsd4: fix mixed ... |
1201 |
} |
a1bcecd29 nfsd41: match cli... |
1202 |
|
28ce6054f [PATCH] knfsd: nf... |
1203 |
static struct nfs4_client * |
e203d506b nfsd4: fix mixed ... |
1204 |
find_confirmed_client_by_str(const char *dname, unsigned int hashval) |
28ce6054f [PATCH] knfsd: nf... |
1205 1206 1207 1208 |
{ struct nfs4_client *clp; list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { |
e203d506b nfsd4: fix mixed ... |
1209 |
if (same_name(clp->cl_recdir, dname)) |
28ce6054f [PATCH] knfsd: nf... |
1210 1211 1212 1213 1214 1215 |
return clp; } return NULL; } static struct nfs4_client * |
e203d506b nfsd4: fix mixed ... |
1216 |
find_unconfirmed_client_by_str(const char *dname, unsigned int hashval) |
28ce6054f [PATCH] knfsd: nf... |
1217 1218 1219 1220 |
{ struct nfs4_client *clp; list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { |
e203d506b nfsd4: fix mixed ... |
1221 |
if (same_name(clp->cl_recdir, dname)) |
28ce6054f [PATCH] knfsd: nf... |
1222 1223 1224 1225 |
return clp; } return NULL; } |
fd39ca9a8 [PATCH] knfsd: nf... |
1226 |
static void |
6f3d772fb nfs4: set source ... |
1227 |
gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp) |
1da177e4c Linux-2.6.12-rc2 |
1228 |
{ |
07263f1ef nfsd4: minor vari... |
1229 |
struct nfs4_cb_conn *conn = &clp->cl_cb_conn; |
6f3d772fb nfs4: set source ... |
1230 1231 |
struct sockaddr *sa = svc_addr(rqstp); u32 scopeid = rpc_get_scope_id(sa); |
7077ecbab nfsd: add support... |
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
unsigned short expected_family; /* Currently, we only support tcp and tcp6 for the callback channel */ if (se->se_callback_netid_len == 3 && !memcmp(se->se_callback_netid_val, "tcp", 3)) expected_family = AF_INET; else if (se->se_callback_netid_len == 4 && !memcmp(se->se_callback_netid_val, "tcp6", 4)) expected_family = AF_INET6; else |
1da177e4c Linux-2.6.12-rc2 |
1242 |
goto out_err; |
07263f1ef nfsd4: minor vari... |
1243 |
conn->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val, |
aa9a4ec77 nfsd: convert nfs... |
1244 |
se->se_callback_addr_len, |
07263f1ef nfsd4: minor vari... |
1245 1246 |
(struct sockaddr *)&conn->cb_addr, sizeof(conn->cb_addr)); |
aa9a4ec77 nfsd: convert nfs... |
1247 |
|
07263f1ef nfsd4: minor vari... |
1248 |
if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family) |
1da177e4c Linux-2.6.12-rc2 |
1249 |
goto out_err; |
aa9a4ec77 nfsd: convert nfs... |
1250 |
|
07263f1ef nfsd4: minor vari... |
1251 1252 |
if (conn->cb_addr.ss_family == AF_INET6) ((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid; |
fbf4665f4 nfsd: populate si... |
1253 |
|
07263f1ef nfsd4: minor vari... |
1254 1255 |
conn->cb_prog = se->se_callback_prog; conn->cb_ident = se->se_callback_ident; |
849a1cf13 SUNRPC: Replace s... |
1256 |
memcpy(&conn->cb_saddr, &rqstp->rq_daddr, rqstp->rq_daddrlen); |
1da177e4c Linux-2.6.12-rc2 |
1257 1258 |
return; out_err: |
07263f1ef nfsd4: minor vari... |
1259 1260 |
conn->cb_addr.ss_family = AF_UNSPEC; conn->cb_addrlen = 0; |
849823c52 [PATCH] nfsd4: pr... |
1261 |
dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " |
1da177e4c Linux-2.6.12-rc2 |
1262 1263 1264 |
"will not receive delegations ", clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); |
1da177e4c Linux-2.6.12-rc2 |
1265 1266 |
return; } |
074fe8975 nfsd41: DRC save,... |
1267 |
/* |
557ce2646 nfsd41: replace p... |
1268 |
* Cache a reply. nfsd4_check_drc_limit() has bounded the cache size. |
074fe8975 nfsd41: DRC save,... |
1269 |
*/ |
074fe8975 nfsd41: DRC save,... |
1270 1271 |
void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) |
074fe8975 nfsd41: DRC save,... |
1272 |
{ |
557ce2646 nfsd41: replace p... |
1273 1274 |
struct nfsd4_slot *slot = resp->cstate.slot; unsigned int base; |
074fe8975 nfsd41: DRC save,... |
1275 |
|
557ce2646 nfsd41: replace p... |
1276 1277 |
dprintk("--> %s slot %p ", __func__, slot); |
074fe8975 nfsd41: DRC save,... |
1278 |
|
557ce2646 nfsd41: replace p... |
1279 1280 |
slot->sl_opcnt = resp->opcnt; slot->sl_status = resp->cstate.status; |
074fe8975 nfsd41: DRC save,... |
1281 |
|
bf864a31d nfsd41: non-page ... |
1282 |
if (nfsd4_not_cached(resp)) { |
557ce2646 nfsd41: replace p... |
1283 |
slot->sl_datalen = 0; |
bf864a31d nfsd41: non-page ... |
1284 |
return; |
074fe8975 nfsd41: DRC save,... |
1285 |
} |
557ce2646 nfsd41: replace p... |
1286 1287 1288 1289 1290 1291 1292 1293 |
slot->sl_datalen = (char *)resp->p - (char *)resp->cstate.datap; base = (char *)resp->cstate.datap - (char *)resp->xbuf->head[0].iov_base; if (read_bytes_from_xdr_buf(resp->xbuf, base, slot->sl_data, slot->sl_datalen)) WARN("%s: sessions DRC could not cache compound ", __func__); return; |
074fe8975 nfsd41: DRC save,... |
1294 1295 1296 |
} /* |
abfabf8ca nfsd41: encode re... |
1297 1298 1299 1300 |
* Encode the replay sequence operation from the slot values. * If cachethis is FALSE encode the uncached rep error on the next * operation which sets resp->p and increments resp->opcnt for * nfs4svc_encode_compoundres. |
074fe8975 nfsd41: DRC save,... |
1301 |
* |
074fe8975 nfsd41: DRC save,... |
1302 |
*/ |
abfabf8ca nfsd41: encode re... |
1303 1304 1305 |
static __be32 nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args, struct nfsd4_compoundres *resp) |
074fe8975 nfsd41: DRC save,... |
1306 |
{ |
abfabf8ca nfsd41: encode re... |
1307 1308 |
struct nfsd4_op *op; struct nfsd4_slot *slot = resp->cstate.slot; |
bf864a31d nfsd41: non-page ... |
1309 |
|
abfabf8ca nfsd41: encode re... |
1310 1311 |
dprintk("--> %s resp->opcnt %d cachethis %u ", __func__, |
557ce2646 nfsd41: replace p... |
1312 |
resp->opcnt, resp->cstate.slot->sl_cachethis); |
bf864a31d nfsd41: non-page ... |
1313 |
|
abfabf8ca nfsd41: encode re... |
1314 1315 1316 |
/* Encode the replayed sequence operation */ op = &args->ops[resp->opcnt - 1]; nfsd4_encode_operation(resp, op); |
bf864a31d nfsd41: non-page ... |
1317 |
|
abfabf8ca nfsd41: encode re... |
1318 |
/* Return nfserr_retry_uncached_rep in next operation. */ |
557ce2646 nfsd41: replace p... |
1319 |
if (args->opcnt > 1 && slot->sl_cachethis == 0) { |
abfabf8ca nfsd41: encode re... |
1320 1321 1322 |
op = &args->ops[resp->opcnt++]; op->status = nfserr_retry_uncached_rep; nfsd4_encode_operation(resp, op); |
074fe8975 nfsd41: DRC save,... |
1323 |
} |
abfabf8ca nfsd41: encode re... |
1324 |
return op->status; |
074fe8975 nfsd41: DRC save,... |
1325 1326 1327 |
} /* |
557ce2646 nfsd41: replace p... |
1328 1329 |
* The sequence operation is not cached because we can use the slot and * session values. |
074fe8975 nfsd41: DRC save,... |
1330 1331 |
*/ __be32 |
bf864a31d nfsd41: non-page ... |
1332 1333 |
nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, struct nfsd4_sequence *seq) |
074fe8975 nfsd41: DRC save,... |
1334 |
{ |
557ce2646 nfsd41: replace p... |
1335 |
struct nfsd4_slot *slot = resp->cstate.slot; |
074fe8975 nfsd41: DRC save,... |
1336 |
__be32 status; |
557ce2646 nfsd41: replace p... |
1337 1338 |
dprintk("--> %s slot %p ", __func__, slot); |
074fe8975 nfsd41: DRC save,... |
1339 |
|
abfabf8ca nfsd41: encode re... |
1340 1341 1342 1343 |
/* Either returns 0 or nfserr_retry_uncached */ status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp); if (status == nfserr_retry_uncached_rep) return status; |
074fe8975 nfsd41: DRC save,... |
1344 |
|
557ce2646 nfsd41: replace p... |
1345 1346 |
/* The sequence operation has been encoded, cstate->datap set. */ memcpy(resp->cstate.datap, slot->sl_data, slot->sl_datalen); |
074fe8975 nfsd41: DRC save,... |
1347 |
|
557ce2646 nfsd41: replace p... |
1348 1349 1350 |
resp->opcnt = slot->sl_opcnt; resp->p = resp->cstate.datap + XDR_QUADLEN(slot->sl_datalen); status = slot->sl_status; |
074fe8975 nfsd41: DRC save,... |
1351 1352 1353 |
return status; } |
0733d2133 nfsd41: exchange_... |
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 |
/* * Set the exchange_id flags returned by the server. */ static void nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid) { /* pNFS is not supported */ new->cl_exchange_flags |= EXCHGID4_FLAG_USE_NON_PNFS; /* Referrals are supported, Migration is not. */ new->cl_exchange_flags |= EXCHGID4_FLAG_SUPP_MOVED_REFER; /* set the wire flags to return to client. */ clid->flags = new->cl_exchange_flags; } |
b37ad28bc [PATCH] nfsd: nfs... |
1369 |
__be32 |
069b6ad4b nfsd41: proc stubs |
1370 1371 1372 1373 |
nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_exchange_id *exid) { |
0733d2133 nfsd41: exchange_... |
1374 1375 1376 1377 |
struct nfs4_client *unconf, *conf, *new; int status; unsigned int strhashval; char dname[HEXDIR_LEN]; |
363168b4e nfsd: make nfs4_c... |
1378 |
char addr_str[INET6_ADDRSTRLEN]; |
0733d2133 nfsd41: exchange_... |
1379 |
nfs4_verifier verf = exid->verifier; |
363168b4e nfsd: make nfs4_c... |
1380 |
struct sockaddr *sa = svc_addr(rqstp); |
0733d2133 nfsd41: exchange_... |
1381 |
|
363168b4e nfsd: make nfs4_c... |
1382 |
rpc_ntop(sa, addr_str, sizeof(addr_str)); |
0733d2133 nfsd41: exchange_... |
1383 |
dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p " |
363168b4e nfsd: make nfs4_c... |
1384 1385 |
"ip_addr=%s flags %x, spa_how %d ", |
0733d2133 nfsd41: exchange_... |
1386 |
__func__, rqstp, exid, exid->clname.len, exid->clname.data, |
363168b4e nfsd: make nfs4_c... |
1387 |
addr_str, exid->flags, exid->spa_how); |
0733d2133 nfsd41: exchange_... |
1388 |
|
a084daf51 nfsd4: move name-... |
1389 |
if (exid->flags & ~EXCHGID4_FLAG_MASK_A) |
0733d2133 nfsd41: exchange_... |
1390 1391 1392 1393 1394 1395 1396 |
return nfserr_inval; /* Currently only support SP4_NONE */ switch (exid->spa_how) { case SP4_NONE: break; case SP4_SSV: |
044bc1d43 nfsd4: return ser... |
1397 |
return nfserr_serverfault; |
0733d2133 nfsd41: exchange_... |
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 |
default: BUG(); /* checked by xdr code */ case SP4_MACH_CRED: return nfserr_serverfault; /* no excuse :-/ */ } status = nfs4_make_rec_clidname(dname, &exid->clname); if (status) goto error; strhashval = clientstr_hashval(dname); nfs4_lock_state(); status = nfs_ok; |
e203d506b nfsd4: fix mixed ... |
1413 |
conf = find_confirmed_client_by_str(dname, strhashval); |
0733d2133 nfsd41: exchange_... |
1414 |
if (conf) { |
e203d506b nfsd4: fix mixed ... |
1415 1416 1417 1418 |
if (!clp_used_exchangeid(conf)) { status = nfserr_clid_inuse; /* XXX: ? */ goto out; } |
0733d2133 nfsd41: exchange_... |
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 |
if (!same_verf(&verf, &conf->cl_verifier)) { /* 18.35.4 case 8 */ if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { status = nfserr_not_same; goto out; } /* Client reboot: destroy old state */ expire_client(conf); goto out_new; } if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { /* 18.35.4 case 9 */ if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { status = nfserr_perm; goto out; } expire_client(conf); goto out_new; } |
0733d2133 nfsd41: exchange_... |
1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 |
/* * Set bit when the owner id and verifier map to an already * confirmed client id (18.35.3). */ exid->flags |= EXCHGID4_FLAG_CONFIRMED_R; /* * Falling into 18.35.4 case 2, possible router replay. * Leave confirmed record intact and return same result. */ copy_verf(conf, &verf); new = conf; goto out_copy; |
6ddbbbfe5 nfsd41: Remove ip... |
1451 1452 1453 1454 1455 1456 |
} /* 18.35.4 case 7 */ if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { status = nfserr_noent; goto out; |
0733d2133 nfsd41: exchange_... |
1457 |
} |
e203d506b nfsd4: fix mixed ... |
1458 |
unconf = find_unconfirmed_client_by_str(dname, strhashval); |
0733d2133 nfsd41: exchange_... |
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 |
if (unconf) { /* * Possible retry or client restart. Per 18.35.4 case 4, * a new unconfirmed record should be generated regardless * of whether any properties have changed. */ expire_client(unconf); } out_new: /* Normal case */ |
b09333c46 nfsd41: Refactor ... |
1470 |
new = create_client(exid->clname, dname, rqstp, &verf); |
0733d2133 nfsd41: exchange_... |
1471 |
if (new == NULL) { |
4731030d5 nfsd4: translate ... |
1472 |
status = nfserr_jukebox; |
0733d2133 nfsd41: exchange_... |
1473 1474 |
goto out; } |
0733d2133 nfsd41: exchange_... |
1475 |
gen_clid(new); |
0733d2133 nfsd41: exchange_... |
1476 1477 1478 1479 |
add_to_unconfirmed(new, strhashval); out_copy: exid->clientid.cl_boot = new->cl_clientid.cl_boot; exid->clientid.cl_id = new->cl_clientid.cl_id; |
38eb76a54 nfsd41: Add a cre... |
1480 |
exid->seqid = 1; |
0733d2133 nfsd41: exchange_... |
1481 1482 1483 1484 |
nfsd4_set_ex_flags(new, exid); dprintk("nfsd4_exchange_id seqid %d flags %x ", |
49557cc74 nfsd41: Use separ... |
1485 |
new->cl_cs_slot.sl_seqid, new->cl_exchange_flags); |
0733d2133 nfsd41: exchange_... |
1486 1487 1488 1489 1490 1491 1492 1493 |
status = nfs_ok; out: nfs4_unlock_state(); error: dprintk("nfsd4_exchange_id returns %d ", ntohl(status)); return status; |
069b6ad4b nfsd41: proc stubs |
1494 |
} |
b85d4c01b nfsd41: sequence ... |
1495 |
static int |
88e588d56 nfsd41: change ch... |
1496 |
check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse) |
b85d4c01b nfsd41: sequence ... |
1497 |
{ |
88e588d56 nfsd41: change ch... |
1498 1499 1500 |
dprintk("%s enter. seqid %d slot_seqid %d ", __func__, seqid, slot_seqid); |
b85d4c01b nfsd41: sequence ... |
1501 1502 |
/* The slot is in use, and no response has been sent. */ |
88e588d56 nfsd41: change ch... |
1503 1504 |
if (slot_inuse) { if (seqid == slot_seqid) |
b85d4c01b nfsd41: sequence ... |
1505 1506 1507 1508 1509 |
return nfserr_jukebox; else return nfserr_seq_misordered; } /* Normal */ |
88e588d56 nfsd41: change ch... |
1510 |
if (likely(seqid == slot_seqid + 1)) |
b85d4c01b nfsd41: sequence ... |
1511 1512 |
return nfs_ok; /* Replay */ |
88e588d56 nfsd41: change ch... |
1513 |
if (seqid == slot_seqid) |
b85d4c01b nfsd41: sequence ... |
1514 1515 |
return nfserr_replay_cache; /* Wraparound */ |
88e588d56 nfsd41: change ch... |
1516 |
if (seqid == 1 && (slot_seqid + 1) == 0) |
b85d4c01b nfsd41: sequence ... |
1517 1518 1519 1520 |
return nfs_ok; /* Misordered replay or misordered new request */ return nfserr_seq_misordered; } |
49557cc74 nfsd41: Use separ... |
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 |
/* * Cache the create session result into the create session single DRC * slot cache by saving the xdr structure. sl_seqid has been set. * Do this for solo or embedded create session operations. */ static void nfsd4_cache_create_session(struct nfsd4_create_session *cr_ses, struct nfsd4_clid_slot *slot, int nfserr) { slot->sl_status = nfserr; memcpy(&slot->sl_cr_ses, cr_ses, sizeof(*cr_ses)); } static __be32 nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses, struct nfsd4_clid_slot *slot) { memcpy(cr_ses, &slot->sl_cr_ses, sizeof(*cr_ses)); return slot->sl_status; } |
1b74c25bc nfsd41: error out... |
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 |
#define NFSD_MIN_REQ_HDR_SEQ_SZ ((\ 2 * 2 + /* credential,verifier: AUTH_NULL, length 0 */ \ 1 + /* MIN tag is length with zero, only length */ \ 3 + /* version, opcount, opcode */ \ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ /* seqid, slotID, slotID, cache */ \ 4 ) * sizeof(__be32)) #define NFSD_MIN_RESP_HDR_SEQ_SZ ((\ 2 + /* verifier: AUTH_NULL, length 0 */\ 1 + /* status */ \ 1 + /* MIN tag is length with zero, only length */ \ 3 + /* opcount, opcode, opstatus*/ \ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ /* seqid, slotID, slotID, slotID, status */ \ 5 ) * sizeof(__be32)) static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs fchannel) { return fchannel.maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ || fchannel.maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ; } |
069b6ad4b nfsd41: proc stubs |
1563 1564 1565 1566 1567 |
__be32 nfsd4_create_session(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_create_session *cr_ses) { |
363168b4e nfsd: make nfs4_c... |
1568 |
struct sockaddr *sa = svc_addr(rqstp); |
ec6b5d7b5 nfsd41: create_se... |
1569 |
struct nfs4_client *conf, *unconf; |
ac7c46f29 nfsd4: make backc... |
1570 |
struct nfsd4_session *new; |
49557cc74 nfsd41: Use separ... |
1571 |
struct nfsd4_clid_slot *cs_slot = NULL; |
86c3e16cc nfsd4: confirm on... |
1572 |
bool confirm_me = false; |
ec6b5d7b5 nfsd41: create_se... |
1573 |
int status = 0; |
a62573dc3 nfsd41: add flag ... |
1574 1575 |
if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) return nfserr_inval; |
ec6b5d7b5 nfsd41: create_se... |
1576 1577 1578 1579 1580 |
nfs4_lock_state(); unconf = find_unconfirmed_client(&cr_ses->clientid); conf = find_confirmed_client(&cr_ses->clientid); if (conf) { |
49557cc74 nfsd41: Use separ... |
1581 1582 |
cs_slot = &conf->cl_cs_slot; status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); |
38eb76a54 nfsd41: Add a cre... |
1583 |
if (status == nfserr_replay_cache) { |
ec6b5d7b5 nfsd41: create_se... |
1584 1585 |
dprintk("Got a create_session replay! seqid= %d ", |
49557cc74 nfsd41: Use separ... |
1586 |
cs_slot->sl_seqid); |
38eb76a54 nfsd41: Add a cre... |
1587 |
/* Return the cached reply status */ |
49557cc74 nfsd41: Use separ... |
1588 |
status = nfsd4_replay_create_session(cr_ses, cs_slot); |
38eb76a54 nfsd41: Add a cre... |
1589 |
goto out; |
49557cc74 nfsd41: Use separ... |
1590 |
} else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { |
ec6b5d7b5 nfsd41: create_se... |
1591 1592 1593 1594 1595 |
status = nfserr_seq_misordered; dprintk("Sequence misordered! "); dprintk("Expected seqid= %d but got seqid= %d ", |
49557cc74 nfsd41: Use separ... |
1596 |
cs_slot->sl_seqid, cr_ses->seqid); |
ec6b5d7b5 nfsd41: create_se... |
1597 1598 |
goto out; } |
ec6b5d7b5 nfsd41: create_se... |
1599 1600 |
} else if (unconf) { if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || |
363168b4e nfsd: make nfs4_c... |
1601 |
!rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { |
ec6b5d7b5 nfsd41: create_se... |
1602 1603 1604 |
status = nfserr_clid_inuse; goto out; } |
49557cc74 nfsd41: Use separ... |
1605 1606 |
cs_slot = &unconf->cl_cs_slot; status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); |
38eb76a54 nfsd41: Add a cre... |
1607 1608 |
if (status) { /* an unconfirmed replay returns misordered */ |
ec6b5d7b5 nfsd41: create_se... |
1609 |
status = nfserr_seq_misordered; |
cd5b81445 nfsd4: don't cach... |
1610 |
goto out; |
ec6b5d7b5 nfsd41: create_se... |
1611 |
} |
86c3e16cc nfsd4: confirm on... |
1612 |
confirm_me = true; |
ec6b5d7b5 nfsd41: create_se... |
1613 1614 1615 1616 1617 |
conf = unconf; } else { status = nfserr_stale_clientid; goto out; } |
408b79bcc nfsd4: consistent... |
1618 |
/* |
8323c3b2a nfsd4: move minor... |
1619 1620 1621 1622 1623 |
* XXX: we should probably set this at creation time, and check * for consistent minorversion use throughout: */ conf->cl_minorversion = 1; /* |
408b79bcc nfsd4: consistent... |
1624 1625 1626 1627 |
* We do not support RDMA or persistent sessions */ cr_ses->flags &= ~SESSION4_PERSIST; cr_ses->flags &= ~SESSION4_RDMA; |
1b74c25bc nfsd41: error out... |
1628 1629 1630 |
status = nfserr_toosmall; if (check_forechannel_attrs(cr_ses->fore_channel)) goto out; |
ac7c46f29 nfsd4: make backc... |
1631 1632 1633 |
status = nfserr_jukebox; new = alloc_init_session(rqstp, conf, cr_ses); if (!new) |
ec6b5d7b5 nfsd41: create_se... |
1634 |
goto out; |
ac7c46f29 nfsd4: make backc... |
1635 1636 |
status = nfs_ok; memcpy(cr_ses->sessionid.data, new->se_sessionid.data, |
ec6b5d7b5 nfsd41: create_se... |
1637 |
NFS4_MAX_SESSIONID_LEN); |
120506576 NFS4.1: Fix bug s... |
1638 1639 |
memcpy(&cr_ses->fore_channel, &new->se_fchannel, sizeof(struct nfsd4_channel_attrs)); |
86c3e16cc nfsd4: confirm on... |
1640 |
cs_slot->sl_seqid++; |
49557cc74 nfsd41: Use separ... |
1641 |
cr_ses->seqid = cs_slot->sl_seqid; |
ec6b5d7b5 nfsd41: create_se... |
1642 |
|
49557cc74 nfsd41: Use separ... |
1643 1644 |
/* cache solo and embedded create sessions under the state lock */ nfsd4_cache_create_session(cr_ses, cs_slot, status); |
86c3e16cc nfsd4: confirm on... |
1645 1646 |
if (confirm_me) move_to_confirmed(conf); |
ec6b5d7b5 nfsd41: create_se... |
1647 1648 1649 1650 1651 |
out: nfs4_unlock_state(); dprintk("%s returns %d ", __func__, ntohl(status)); return status; |
069b6ad4b nfsd41: proc stubs |
1652 |
} |
577163559 nfsd4: complete e... |
1653 1654 1655 1656 1657 1658 1659 |
static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) { struct nfsd4_compoundres *resp = rqstp->rq_resp; struct nfsd4_compoundargs *argp = rqstp->rq_argp; return argp->opcnt == resp->opcnt; } |
1d1bc8f20 nfsd4: support BI... |
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 |
static __be32 nfsd4_map_bcts_dir(u32 *dir) { switch (*dir) { case NFS4_CDFC4_FORE: case NFS4_CDFC4_BACK: return nfs_ok; case NFS4_CDFC4_FORE_OR_BOTH: case NFS4_CDFC4_BACK_OR_BOTH: *dir = NFS4_CDFC4_BOTH; return nfs_ok; }; return nfserr_inval; } __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_bind_conn_to_session *bcts) { __be32 status; if (!nfsd4_last_compound_op(rqstp)) return nfserr_not_only_op; spin_lock(&client_lock); cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid); /* Sorta weird: we only need the refcnt'ing because new_conn acquires * client_lock iself: */ if (cstate->session) { nfsd4_get_session(cstate->session); atomic_inc(&cstate->session->se_client->cl_refcount); } spin_unlock(&client_lock); if (!cstate->session) return nfserr_badsession; status = nfsd4_map_bcts_dir(&bcts->dir); |
1db2b9dde NFSD: Check statu... |
1695 1696 1697 |
if (!status) nfsd4_new_conn(rqstp, cstate->session, bcts->dir); return status; |
1d1bc8f20 nfsd4: support BI... |
1698 |
} |
5d4cec2f2 nfsd4: fix bare d... |
1699 1700 1701 1702 1703 1704 |
static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) { if (!session) return 0; return !memcmp(sid, &session->se_sessionid, sizeof(*sid)); } |
069b6ad4b nfsd41: proc stubs |
1705 1706 1707 1708 1709 |
__be32 nfsd4_destroy_session(struct svc_rqst *r, struct nfsd4_compound_state *cstate, struct nfsd4_destroy_session *sessionid) { |
e10e0cfc2 nfsd41: destroy_s... |
1710 1711 1712 1713 1714 1715 1716 1717 1718 |
struct nfsd4_session *ses; u32 status = nfserr_badsession; /* Notes: * - The confirmed nfs4_client->cl_sessionid holds destroyed sessinid * - Should we return nfserr_back_chan_busy if waiting for * callbacks on to-be-destroyed session? * - Do we need to clear any callback info from previous session? */ |
5d4cec2f2 nfsd4: fix bare d... |
1719 |
if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) { |
577163559 nfsd4: complete e... |
1720 1721 1722 |
if (!nfsd4_last_compound_op(r)) return nfserr_not_only_op; } |
e10e0cfc2 nfsd41: destroy_s... |
1723 |
dump_sessionid(__func__, &sessionid->sessionid); |
9089f1b47 nfsd4: rename ses... |
1724 |
spin_lock(&client_lock); |
e10e0cfc2 nfsd41: destroy_s... |
1725 1726 |
ses = find_in_sessionid_hashtbl(&sessionid->sessionid); if (!ses) { |
9089f1b47 nfsd4: rename ses... |
1727 |
spin_unlock(&client_lock); |
e10e0cfc2 nfsd41: destroy_s... |
1728 1729 1730 1731 |
goto out; } unhash_session(ses); |
9089f1b47 nfsd4: rename ses... |
1732 |
spin_unlock(&client_lock); |
e10e0cfc2 nfsd41: destroy_s... |
1733 |
|
ab707e156 nfsd4: nfsd4_dest... |
1734 |
nfs4_lock_state(); |
84f5f7ccc nfsd4: make sure ... |
1735 |
nfsd4_probe_callback_sync(ses->se_client); |
ab707e156 nfsd4: nfsd4_dest... |
1736 |
nfs4_unlock_state(); |
19cf5c026 nfsd4: use callba... |
1737 1738 |
nfsd4_del_conns(ses); |
e10e0cfc2 nfsd41: destroy_s... |
1739 1740 1741 1742 1743 1744 |
nfsd4_put_session(ses); status = nfs_ok; out: dprintk("%s returns %d ", __func__, ntohl(status)); return status; |
069b6ad4b nfsd41: proc stubs |
1745 |
} |
a663bdd8c nfsd4: fix connec... |
1746 |
static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s) |
328ead287 nfsd4: add new co... |
1747 1748 1749 1750 |
{ struct nfsd4_conn *c; list_for_each_entry(c, &s->se_conns, cn_persession) { |
a663bdd8c nfsd4: fix connec... |
1751 |
if (c->cn_xprt == xpt) { |
328ead287 nfsd4: add new co... |
1752 1753 1754 1755 1756 |
return c; } } return NULL; } |
a663bdd8c nfsd4: fix connec... |
1757 |
static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) |
328ead287 nfsd4: add new co... |
1758 1759 |
{ struct nfs4_client *clp = ses->se_client; |
a663bdd8c nfsd4: fix connec... |
1760 |
struct nfsd4_conn *c; |
21b75b019 nfsd4: fix 4.1 co... |
1761 |
int ret; |
328ead287 nfsd4: add new co... |
1762 1763 |
spin_lock(&clp->cl_lock); |
a663bdd8c nfsd4: fix connec... |
1764 |
c = __nfsd4_find_conn(new->cn_xprt, ses); |
328ead287 nfsd4: add new co... |
1765 1766 1767 1768 1769 1770 1771 |
if (c) { spin_unlock(&clp->cl_lock); free_conn(new); return; } __nfsd4_hash_conn(new, ses); spin_unlock(&clp->cl_lock); |
21b75b019 nfsd4: fix 4.1 co... |
1772 1773 1774 1775 |
ret = nfsd4_register_conn(new); if (ret) /* oops; xprt is already down: */ nfsd4_conn_lost(&new->cn_xpt_user); |
328ead287 nfsd4: add new co... |
1776 1777 |
return; } |
868b89c3d nfsd41: compare r... |
1778 1779 1780 1781 1782 1783 |
static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session) { struct nfsd4_compoundargs *args = rqstp->rq_argp; return args->opcnt > session->se_fchannel.maxops; } |
ae82a8d06 nfsd41: check the... |
1784 1785 1786 1787 1788 1789 1790 |
static bool nfsd4_request_too_big(struct svc_rqst *rqstp, struct nfsd4_session *session) { struct xdr_buf *xb = &rqstp->rq_arg; return xb->len > session->se_fchannel.maxreq_sz; } |
069b6ad4b nfsd41: proc stubs |
1791 |
__be32 |
b85d4c01b nfsd41: sequence ... |
1792 |
nfsd4_sequence(struct svc_rqst *rqstp, |
069b6ad4b nfsd41: proc stubs |
1793 1794 1795 |
struct nfsd4_compound_state *cstate, struct nfsd4_sequence *seq) { |
f9bb94c4c nfsd41: enforce N... |
1796 |
struct nfsd4_compoundres *resp = rqstp->rq_resp; |
b85d4c01b nfsd41: sequence ... |
1797 1798 |
struct nfsd4_session *session; struct nfsd4_slot *slot; |
a663bdd8c nfsd4: fix connec... |
1799 |
struct nfsd4_conn *conn; |
b85d4c01b nfsd41: sequence ... |
1800 |
int status; |
f9bb94c4c nfsd41: enforce N... |
1801 1802 |
if (resp->opcnt != 1) return nfserr_sequence_pos; |
a663bdd8c nfsd4: fix connec... |
1803 1804 1805 1806 1807 1808 1809 |
/* * Will be either used or freed by nfsd4_sequence_check_conn * below. */ conn = alloc_conn(rqstp, NFS4_CDFC4_FORE); if (!conn) return nfserr_jukebox; |
9089f1b47 nfsd4: rename ses... |
1810 |
spin_lock(&client_lock); |
b85d4c01b nfsd41: sequence ... |
1811 1812 1813 1814 |
status = nfserr_badsession; session = find_in_sessionid_hashtbl(&seq->sessionid); if (!session) goto out; |
868b89c3d nfsd41: compare r... |
1815 1816 1817 |
status = nfserr_too_many_ops; if (nfsd4_session_too_many_ops(rqstp, session)) goto out; |
ae82a8d06 nfsd41: check the... |
1818 1819 1820 |
status = nfserr_req_too_big; if (nfsd4_request_too_big(rqstp, session)) goto out; |
b85d4c01b nfsd41: sequence ... |
1821 |
status = nfserr_badslot; |
6c18ba9f5 nfsd41: move chan... |
1822 |
if (seq->slotid >= session->se_fchannel.maxreqs) |
b85d4c01b nfsd41: sequence ... |
1823 |
goto out; |
557ce2646 nfsd41: replace p... |
1824 |
slot = session->se_slots[seq->slotid]; |
b85d4c01b nfsd41: sequence ... |
1825 1826 |
dprintk("%s: slotid %d ", __func__, seq->slotid); |
a8dfdaeb7 nfsd41: use sessi... |
1827 1828 1829 1830 |
/* We do not negotiate the number of slots yet, so set the * maxslots to the session maxreqs which is used to encode * sr_highest_slotid and the sr_target_slot id to maxslots */ seq->maxslots = session->se_fchannel.maxreqs; |
88e588d56 nfsd41: change ch... |
1831 |
status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_inuse); |
b85d4c01b nfsd41: sequence ... |
1832 1833 1834 |
if (status == nfserr_replay_cache) { cstate->slot = slot; cstate->session = session; |
da3846a28 nfsd41: nfsd DRC ... |
1835 |
/* Return the cached reply status and set cstate->status |
557ce2646 nfsd41: replace p... |
1836 |
* for nfsd4_proc_compound processing */ |
bf864a31d nfsd41: non-page ... |
1837 |
status = nfsd4_replay_cache_entry(resp, seq); |
da3846a28 nfsd41: nfsd DRC ... |
1838 |
cstate->status = nfserr_replay_cache; |
aaf84eb95 nfsd41: renew_cli... |
1839 |
goto out; |
b85d4c01b nfsd41: sequence ... |
1840 1841 1842 |
} if (status) goto out; |
a663bdd8c nfsd4: fix connec... |
1843 1844 |
nfsd4_sequence_check_conn(conn, session); conn = NULL; |
328ead287 nfsd4: add new co... |
1845 |
|
b85d4c01b nfsd41: sequence ... |
1846 1847 1848 |
/* Success! bump slot seqid */ slot->sl_inuse = true; slot->sl_seqid = seq->seqid; |
557ce2646 nfsd41: replace p... |
1849 |
slot->sl_cachethis = seq->cachethis; |
b85d4c01b nfsd41: sequence ... |
1850 1851 1852 |
cstate->slot = slot; cstate->session = session; |
b85d4c01b nfsd41: sequence ... |
1853 |
out: |
26c0c75e6 nfsd4: fix unlike... |
1854 |
/* Hold a session reference until done processing the compound. */ |
aaf84eb95 nfsd41: renew_cli... |
1855 |
if (cstate->session) { |
0d7bb7190 nfsd4: set sequen... |
1856 |
struct nfs4_client *clp = session->se_client; |
36acb66bd nfsd4: extend the... |
1857 |
nfsd4_get_session(cstate->session); |
0d7bb7190 nfsd4: set sequen... |
1858 |
atomic_inc(&clp->cl_refcount); |
5423732a7 nfsd41: use SEQ4_... |
1859 1860 |
switch (clp->cl_cb_state) { case NFSD4_CB_DOWN: |
fc0c3dd13 nfsd4: seq->statu... |
1861 |
seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN; |
5423732a7 nfsd41: use SEQ4_... |
1862 1863 |
break; case NFSD4_CB_FAULT: |
fc0c3dd13 nfsd4: seq->statu... |
1864 |
seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT; |
5423732a7 nfsd41: use SEQ4_... |
1865 |
break; |
fc0c3dd13 nfsd4: seq->statu... |
1866 1867 |
default: seq->status_flags = 0; |
5423732a7 nfsd41: use SEQ4_... |
1868 |
} |
aaf84eb95 nfsd41: renew_cli... |
1869 |
} |
a663bdd8c nfsd4: fix connec... |
1870 |
kfree(conn); |
36acb66bd nfsd4: extend the... |
1871 |
spin_unlock(&client_lock); |
b85d4c01b nfsd41: sequence ... |
1872 1873 1874 |
dprintk("%s: return %d ", __func__, ntohl(status)); return status; |
069b6ad4b nfsd41: proc stubs |
1875 |
} |
345c28429 nfs41: implement ... |
1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 |
static inline bool has_resources(struct nfs4_client *clp) { return !list_empty(&clp->cl_openowners) || !list_empty(&clp->cl_delegations) || !list_empty(&clp->cl_sessions); } __be32 nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_destroy_clientid *dc) { struct nfs4_client *conf, *unconf, *clp; int status = 0; nfs4_lock_state(); unconf = find_unconfirmed_client(&dc->clientid); conf = find_confirmed_client(&dc->clientid); if (conf) { clp = conf; if (!is_client_expired(conf) && has_resources(conf)) { status = nfserr_clientid_busy; goto out; } /* rfc5661 18.50.3 */ if (cstate->session && conf == cstate->session->se_client) { status = nfserr_clientid_busy; goto out; } } else if (unconf) clp = unconf; else { status = nfserr_stale_clientid; goto out; } expire_client(clp); out: nfs4_unlock_state(); dprintk("%s return %d ", __func__, ntohl(status)); return status; } |
069b6ad4b nfsd41: proc stubs |
1920 |
__be32 |
4dc6ec00f nfsd4: implement ... |
1921 1922 |
nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc) { |
bcecf1ccc nfsd41: error out... |
1923 |
int status = 0; |
4dc6ec00f nfsd4: implement ... |
1924 1925 1926 1927 1928 1929 1930 1931 1932 |
if (rc->rca_one_fs) { if (!cstate->current_fh.fh_dentry) return nfserr_nofilehandle; /* * We don't take advantage of the rca_one_fs case. * That's OK, it's optional, we can safely ignore it. */ return nfs_ok; } |
bcecf1ccc nfsd41: error out... |
1933 |
|
4dc6ec00f nfsd4: implement ... |
1934 |
nfs4_lock_state(); |
bcecf1ccc nfsd41: error out... |
1935 1936 1937 1938 1939 1940 |
status = nfserr_complete_already; if (cstate->session->se_client->cl_firststate) goto out; status = nfserr_stale_clientid; if (is_client_expired(cstate->session->se_client)) |
4dc6ec00f nfsd4: implement ... |
1941 1942 1943 1944 1945 1946 1947 |
/* * The following error isn't really legal. * But we only get here if the client just explicitly * destroyed the client. Surely it no longer cares what * error it gets back on an operation for the dead * client. */ |
bcecf1ccc nfsd41: error out... |
1948 1949 1950 |
goto out; status = nfs_ok; |
4dc6ec00f nfsd4: implement ... |
1951 |
nfsd4_create_clid_dir(cstate->session->se_client); |
bcecf1ccc nfsd41: error out... |
1952 |
out: |
4dc6ec00f nfsd4: implement ... |
1953 |
nfs4_unlock_state(); |
bcecf1ccc nfsd41: error out... |
1954 |
return status; |
4dc6ec00f nfsd4: implement ... |
1955 1956 1957 |
} __be32 |
b591480bb [PATCH] knfsd: nf... |
1958 1959 |
nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_setclientid *setclid) |
1da177e4c Linux-2.6.12-rc2 |
1960 |
{ |
a084daf51 nfsd4: move name-... |
1961 |
struct xdr_netobj clname = setclid->se_name; |
1da177e4c Linux-2.6.12-rc2 |
1962 1963 |
nfs4_verifier clverifier = setclid->se_verf; unsigned int strhashval; |
28ce6054f [PATCH] knfsd: nf... |
1964 |
struct nfs4_client *conf, *unconf, *new; |
b37ad28bc [PATCH] nfsd: nfs... |
1965 |
__be32 status; |
a55370a3c [PATCH] knfsd: nf... |
1966 |
char dname[HEXDIR_LEN]; |
1da177e4c Linux-2.6.12-rc2 |
1967 |
|
a55370a3c [PATCH] knfsd: nf... |
1968 1969 |
status = nfs4_make_rec_clidname(dname, &clname); if (status) |
73aea4ecd [PATCH] nfsd4: fi... |
1970 |
return status; |
a55370a3c [PATCH] knfsd: nf... |
1971 |
|
1da177e4c Linux-2.6.12-rc2 |
1972 1973 1974 1975 |
/* * XXX The Duplicate Request Cache (DRC) has been checked (??) * We get here on a DRC miss. */ |
a55370a3c [PATCH] knfsd: nf... |
1976 |
strhashval = clientstr_hashval(dname); |
1da177e4c Linux-2.6.12-rc2 |
1977 |
|
1da177e4c Linux-2.6.12-rc2 |
1978 |
nfs4_lock_state(); |
e203d506b nfsd4: fix mixed ... |
1979 |
conf = find_confirmed_client_by_str(dname, strhashval); |
28ce6054f [PATCH] knfsd: nf... |
1980 |
if (conf) { |
a186e7674 nfsd4: kill some ... |
1981 |
/* RFC 3530 14.2.33 CASE 0: */ |
1da177e4c Linux-2.6.12-rc2 |
1982 |
status = nfserr_clid_inuse; |
e203d506b nfsd4: fix mixed ... |
1983 1984 |
if (clp_used_exchangeid(conf)) goto out; |
026722c25 nfsd4: don't chec... |
1985 |
if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { |
363168b4e nfsd: make nfs4_c... |
1986 1987 1988 1989 1990 1991 |
char addr_str[INET6_ADDRSTRLEN]; rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str, sizeof(addr_str)); dprintk("NFSD: setclientid: string in use by client " "at %s ", addr_str); |
1da177e4c Linux-2.6.12-rc2 |
1992 1993 |
goto out; } |
1da177e4c Linux-2.6.12-rc2 |
1994 |
} |
a186e7674 nfsd4: kill some ... |
1995 1996 1997 1998 1999 |
/* * section 14.2.33 of RFC 3530 (under the heading "IMPLEMENTATION") * has a description of SETCLIENTID request processing consisting * of 5 bullet points, labeled as CASE0 - CASE4 below. */ |
e203d506b nfsd4: fix mixed ... |
2000 |
unconf = find_unconfirmed_client_by_str(dname, strhashval); |
3e7724639 nfsd4: stop using... |
2001 |
status = nfserr_jukebox; |
1da177e4c Linux-2.6.12-rc2 |
2002 |
if (!conf) { |
a186e7674 nfsd4: kill some ... |
2003 2004 2005 |
/* * RFC 3530 14.2.33 CASE 4: * placed first, because it is the normal case |
1da177e4c Linux-2.6.12-rc2 |
2006 2007 2008 |
*/ if (unconf) expire_client(unconf); |
b09333c46 nfsd41: Refactor ... |
2009 |
new = create_client(clname, dname, rqstp, &clverifier); |
a55370a3c [PATCH] knfsd: nf... |
2010 |
if (new == NULL) |
1da177e4c Linux-2.6.12-rc2 |
2011 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
2012 |
gen_clid(new); |
599e0a229 knfsd: cleanup of... |
2013 |
} else if (same_verf(&conf->cl_verifier, &clverifier)) { |
1da177e4c Linux-2.6.12-rc2 |
2014 |
/* |
a186e7674 nfsd4: kill some ... |
2015 2016 |
* RFC 3530 14.2.33 CASE 1: * probable callback update |
1da177e4c Linux-2.6.12-rc2 |
2017 |
*/ |
31f4a6c12 [PATCH] knfsd: nf... |
2018 2019 2020 2021 2022 2023 2024 |
if (unconf) { /* Note this is removing unconfirmed {*x***}, * which is stronger than RFC recommended {vxc**}. * This has the advantage that there is at most * one {*x***} in either list at any time. */ expire_client(unconf); |
1da177e4c Linux-2.6.12-rc2 |
2025 |
} |
b09333c46 nfsd41: Refactor ... |
2026 |
new = create_client(clname, dname, rqstp, &clverifier); |
a55370a3c [PATCH] knfsd: nf... |
2027 |
if (new == NULL) |
1da177e4c Linux-2.6.12-rc2 |
2028 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
2029 |
copy_clid(new, conf); |
1da177e4c Linux-2.6.12-rc2 |
2030 2031 |
} else if (!unconf) { /* |
a186e7674 nfsd4: kill some ... |
2032 2033 2034 |
* RFC 3530 14.2.33 CASE 2: * probable client reboot; state will be removed if * confirmed. |
1da177e4c Linux-2.6.12-rc2 |
2035 |
*/ |
b09333c46 nfsd41: Refactor ... |
2036 |
new = create_client(clname, dname, rqstp, &clverifier); |
a55370a3c [PATCH] knfsd: nf... |
2037 |
if (new == NULL) |
1da177e4c Linux-2.6.12-rc2 |
2038 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
2039 |
gen_clid(new); |
49ba87811 nfsd: eliminate f... |
2040 |
} else { |
a186e7674 nfsd4: kill some ... |
2041 2042 2043 2044 |
/* * RFC 3530 14.2.33 CASE 3: * probable client reboot; state will be removed if * confirmed. |
1da177e4c Linux-2.6.12-rc2 |
2045 2046 |
*/ expire_client(unconf); |
b09333c46 nfsd41: Refactor ... |
2047 |
new = create_client(clname, dname, rqstp, &clverifier); |
a55370a3c [PATCH] knfsd: nf... |
2048 |
if (new == NULL) |
1da177e4c Linux-2.6.12-rc2 |
2049 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
2050 |
gen_clid(new); |
1da177e4c Linux-2.6.12-rc2 |
2051 |
} |
8323c3b2a nfsd4: move minor... |
2052 2053 2054 2055 2056 |
/* * XXX: we should probably set this at creation time, and check * for consistent minorversion use throughout: */ new->cl_minorversion = 0; |
6f3d772fb nfs4: set source ... |
2057 |
gen_callback(new, setclid, rqstp); |
c175b83c4 knfsd: remove cod... |
2058 |
add_to_unconfirmed(new, strhashval); |
1da177e4c Linux-2.6.12-rc2 |
2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 |
setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; setclid->se_clientid.cl_id = new->cl_clientid.cl_id; memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data)); status = nfs_ok; out: nfs4_unlock_state(); return status; } /* |
a186e7674 nfsd4: kill some ... |
2070 2071 2072 |
* Section 14.2.34 of RFC 3530 (under the heading "IMPLEMENTATION") has * a description of SETCLIENTID_CONFIRM request processing consisting of 4 * bullets, labeled as CASE1 - CASE4 below. |
1da177e4c Linux-2.6.12-rc2 |
2073 |
*/ |
b37ad28bc [PATCH] nfsd: nfs... |
2074 |
__be32 |
b591480bb [PATCH] knfsd: nf... |
2075 2076 2077 |
nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_setclientid_confirm *setclientid_confirm) |
1da177e4c Linux-2.6.12-rc2 |
2078 |
{ |
363168b4e nfsd: make nfs4_c... |
2079 |
struct sockaddr *sa = svc_addr(rqstp); |
21ab45a48 [PATCH] knfsd: nf... |
2080 |
struct nfs4_client *conf, *unconf; |
1da177e4c Linux-2.6.12-rc2 |
2081 2082 |
nfs4_verifier confirm = setclientid_confirm->sc_confirm; clientid_t * clid = &setclientid_confirm->sc_clientid; |
b37ad28bc [PATCH] nfsd: nfs... |
2083 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
2084 2085 2086 2087 2088 2089 2090 2091 2092 |
if (STALE_CLIENTID(clid)) return nfserr_stale_clientid; /* * XXX The Duplicate Request Cache (DRC) has been checked (??) * We get here on a DRC miss. */ nfs4_lock_state(); |
21ab45a48 [PATCH] knfsd: nf... |
2093 2094 2095 2096 2097 |
conf = find_confirmed_client(clid); unconf = find_unconfirmed_client(clid); status = nfserr_clid_inuse; |
363168b4e nfsd: make nfs4_c... |
2098 |
if (conf && !rpc_cmp_addr((struct sockaddr *) &conf->cl_addr, sa)) |
21ab45a48 [PATCH] knfsd: nf... |
2099 |
goto out; |
363168b4e nfsd: make nfs4_c... |
2100 |
if (unconf && !rpc_cmp_addr((struct sockaddr *) &unconf->cl_addr, sa)) |
21ab45a48 [PATCH] knfsd: nf... |
2101 |
goto out; |
a186e7674 nfsd4: kill some ... |
2102 2103 2104 2105 2106 |
/* * section 14.2.34 of RFC 3530 has a description of * SETCLIENTID_CONFIRM request processing consisting * of 4 bullet points, labeled as CASE1 - CASE4 below. */ |
366e0c1d9 nfsd4: kill unnee... |
2107 |
if (conf && unconf && same_verf(&confirm, &unconf->cl_confirm)) { |
a186e7674 nfsd4: kill some ... |
2108 2109 2110 2111 |
/* * RFC 3530 14.2.34 CASE 1: * callback update */ |
599e0a229 knfsd: cleanup of... |
2112 |
if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) |
1da177e4c Linux-2.6.12-rc2 |
2113 2114 |
status = nfserr_clid_inuse; else { |
5a3c9d713 nfsd4: separate c... |
2115 2116 |
nfsd4_change_callback(conf, &unconf->cl_cb_conn); nfsd4_probe_callback(conf); |
1a69c179a [PATCH] knfsd: nf... |
2117 |
expire_client(unconf); |
1da177e4c Linux-2.6.12-rc2 |
2118 |
status = nfs_ok; |
1a69c179a [PATCH] knfsd: nf... |
2119 |
|
1da177e4c Linux-2.6.12-rc2 |
2120 |
} |
f3aba4e5a nfsd4: remove unn... |
2121 |
} else if (conf && !unconf) { |
a186e7674 nfsd4: kill some ... |
2122 2123 2124 2125 |
/* * RFC 3530 14.2.34 CASE 2: * probable retransmitted request; play it safe and * do nothing. |
7c79f7377 [PATCH] knfsd: nf... |
2126 |
*/ |
599e0a229 knfsd: cleanup of... |
2127 |
if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) |
1da177e4c Linux-2.6.12-rc2 |
2128 |
status = nfserr_clid_inuse; |
21ab45a48 [PATCH] knfsd: nf... |
2129 |
else |
1da177e4c Linux-2.6.12-rc2 |
2130 |
status = nfs_ok; |
7c79f7377 [PATCH] knfsd: nf... |
2131 |
} else if (!conf && unconf |
599e0a229 knfsd: cleanup of... |
2132 |
&& same_verf(&unconf->cl_confirm, &confirm)) { |
a186e7674 nfsd4: kill some ... |
2133 2134 2135 |
/* * RFC 3530 14.2.34 CASE 3: * Normal case; new or rebooted client: |
7c79f7377 [PATCH] knfsd: nf... |
2136 |
*/ |
599e0a229 knfsd: cleanup of... |
2137 |
if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { |
1da177e4c Linux-2.6.12-rc2 |
2138 2139 |
status = nfserr_clid_inuse; } else { |
1a69c179a [PATCH] knfsd: nf... |
2140 2141 2142 |
unsigned int hash = clientstr_hashval(unconf->cl_recdir); conf = find_confirmed_client_by_str(unconf->cl_recdir, |
e203d506b nfsd4: fix mixed ... |
2143 |
hash); |
1a69c179a [PATCH] knfsd: nf... |
2144 |
if (conf) { |
c7b9a4592 [PATCH] knfsd: nf... |
2145 |
nfsd4_remove_clid_dir(conf); |
1a69c179a [PATCH] knfsd: nf... |
2146 2147 |
expire_client(conf); } |
1da177e4c Linux-2.6.12-rc2 |
2148 |
move_to_confirmed(unconf); |
21ab45a48 [PATCH] knfsd: nf... |
2149 |
conf = unconf; |
5a3c9d713 nfsd4: separate c... |
2150 |
nfsd4_probe_callback(conf); |
1a69c179a [PATCH] knfsd: nf... |
2151 |
status = nfs_ok; |
1da177e4c Linux-2.6.12-rc2 |
2152 |
} |
599e0a229 knfsd: cleanup of... |
2153 2154 |
} else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, |
7c79f7377 [PATCH] knfsd: nf... |
2155 |
&confirm)))) { |
a186e7674 nfsd4: kill some ... |
2156 2157 2158 |
/* * RFC 3530 14.2.34 CASE 4: * Client probably hasn't noticed that we rebooted yet. |
7c79f7377 [PATCH] knfsd: nf... |
2159 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
2160 |
status = nfserr_stale_clientid; |
7c79f7377 [PATCH] knfsd: nf... |
2161 |
} else { |
08e8987c3 [PATCH] knfsd: nf... |
2162 2163 2164 |
/* check that we have hit one of the cases...*/ status = nfserr_clid_inuse; } |
1da177e4c Linux-2.6.12-rc2 |
2165 |
out: |
1da177e4c Linux-2.6.12-rc2 |
2166 2167 2168 |
nfs4_unlock_state(); return status; } |
32513b40e nfsd4: preallocat... |
2169 2170 2171 2172 |
static struct nfs4_file *nfsd4_alloc_file(void) { return kmem_cache_alloc(file_slab, GFP_KERNEL); } |
1da177e4c Linux-2.6.12-rc2 |
2173 |
/* OPEN Share state helper functions */ |
32513b40e nfsd4: preallocat... |
2174 |
static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino) |
1da177e4c Linux-2.6.12-rc2 |
2175 |
{ |
1da177e4c Linux-2.6.12-rc2 |
2176 |
unsigned int hashval = file_hashval(ino); |
32513b40e nfsd4: preallocat... |
2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 |
atomic_set(&fp->fi_ref, 1); INIT_LIST_HEAD(&fp->fi_hash); INIT_LIST_HEAD(&fp->fi_stateids); INIT_LIST_HEAD(&fp->fi_delegations); fp->fi_inode = igrab(ino); fp->fi_had_conflict = false; fp->fi_lease = NULL; memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); memset(fp->fi_access, 0, sizeof(fp->fi_access)); spin_lock(&recall_lock); list_add(&fp->fi_hash, &file_hashtbl[hashval]); spin_unlock(&recall_lock); |
1da177e4c Linux-2.6.12-rc2 |
2189 2190 2191 |
} static void |
e18b890bb [PATCH] slab: rem... |
2192 |
nfsd4_free_slab(struct kmem_cache **slab) |
1da177e4c Linux-2.6.12-rc2 |
2193 |
{ |
e60d4398a [PATCH] nfsd4: sl... |
2194 2195 |
if (*slab == NULL) return; |
1a1d92c10 [PATCH] Really ig... |
2196 |
kmem_cache_destroy(*slab); |
e60d4398a [PATCH] nfsd4: sl... |
2197 |
*slab = NULL; |
1da177e4c Linux-2.6.12-rc2 |
2198 |
} |
e8ff2a845 knfsd: move nfsv4... |
2199 |
void |
1da177e4c Linux-2.6.12-rc2 |
2200 2201 |
nfsd4_free_slabs(void) { |
fe0750e5c nfsd4: split stat... |
2202 2203 |
nfsd4_free_slab(&openowner_slab); nfsd4_free_slab(&lockowner_slab); |
e60d4398a [PATCH] nfsd4: sl... |
2204 |
nfsd4_free_slab(&file_slab); |
5ac049ac6 [PATCH] nfsd4: sl... |
2205 |
nfsd4_free_slab(&stateid_slab); |
5b2d21c19 [PATCH] nfsd4: sl... |
2206 |
nfsd4_free_slab(&deleg_slab); |
e60d4398a [PATCH] nfsd4: sl... |
2207 |
} |
1da177e4c Linux-2.6.12-rc2 |
2208 |
|
720833960 NFSD: Call nfsd4_... |
2209 |
int |
e60d4398a [PATCH] nfsd4: sl... |
2210 2211 |
nfsd4_init_slabs(void) { |
fe0750e5c nfsd4: split stat... |
2212 2213 2214 2215 2216 2217 2218 |
openowner_slab = kmem_cache_create("nfsd4_openowners", sizeof(struct nfs4_openowner), 0, 0, NULL); if (openowner_slab == NULL) goto out_nomem; lockowner_slab = kmem_cache_create("nfsd4_lockowners", sizeof(struct nfs4_openowner), 0, 0, NULL); if (lockowner_slab == NULL) |
e60d4398a [PATCH] nfsd4: sl... |
2219 2220 |
goto out_nomem; file_slab = kmem_cache_create("nfsd4_files", |
20c2df83d mm: Remove slab d... |
2221 |
sizeof(struct nfs4_file), 0, 0, NULL); |
e60d4398a [PATCH] nfsd4: sl... |
2222 2223 |
if (file_slab == NULL) goto out_nomem; |
5ac049ac6 [PATCH] nfsd4: sl... |
2224 |
stateid_slab = kmem_cache_create("nfsd4_stateids", |
dcef0413d nfsd4: move some ... |
2225 |
sizeof(struct nfs4_ol_stateid), 0, 0, NULL); |
5ac049ac6 [PATCH] nfsd4: sl... |
2226 2227 |
if (stateid_slab == NULL) goto out_nomem; |
5b2d21c19 [PATCH] nfsd4: sl... |
2228 |
deleg_slab = kmem_cache_create("nfsd4_delegations", |
20c2df83d mm: Remove slab d... |
2229 |
sizeof(struct nfs4_delegation), 0, 0, NULL); |
5b2d21c19 [PATCH] nfsd4: sl... |
2230 2231 |
if (deleg_slab == NULL) goto out_nomem; |
e60d4398a [PATCH] nfsd4: sl... |
2232 2233 2234 2235 2236 2237 |
return 0; out_nomem: nfsd4_free_slabs(); dprintk("nfsd4: out of memory while initializing nfsv4 "); return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
2238 |
} |
fe0750e5c nfsd4: split stat... |
2239 2240 2241 2242 2243 2244 2245 |
void nfs4_free_openowner(struct nfs4_openowner *oo) { kfree(oo->oo_owner.so_owner.data); kmem_cache_free(openowner_slab, oo); } void nfs4_free_lockowner(struct nfs4_lockowner *lo) |
1da177e4c Linux-2.6.12-rc2 |
2246 |
{ |
fe0750e5c nfsd4: split stat... |
2247 2248 |
kfree(lo->lo_owner.so_owner.data); kmem_cache_free(lockowner_slab, lo); |
1da177e4c Linux-2.6.12-rc2 |
2249 |
} |
ff194bd95 nfsd4: cleanup lo... |
2250 |
static void init_nfs4_replay(struct nfs4_replay *rp) |
1da177e4c Linux-2.6.12-rc2 |
2251 |
{ |
ff194bd95 nfsd4: cleanup lo... |
2252 2253 2254 |
rp->rp_status = nfserr_serverfault; rp->rp_buflen = 0; rp->rp_buf = rp->rp_ibuf; |
1da177e4c Linux-2.6.12-rc2 |
2255 |
} |
fe0750e5c nfsd4: split stat... |
2256 |
static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj *owner, struct nfs4_client *clp) |
ff194bd95 nfsd4: cleanup lo... |
2257 |
{ |
1da177e4c Linux-2.6.12-rc2 |
2258 |
struct nfs4_stateowner *sop; |
1da177e4c Linux-2.6.12-rc2 |
2259 |
|
fe0750e5c nfsd4: split stat... |
2260 |
sop = kmem_cache_alloc(slab, GFP_KERNEL); |
ff194bd95 nfsd4: cleanup lo... |
2261 2262 2263 2264 2265 |
if (!sop) return NULL; sop->so_owner.data = kmemdup(owner->data, owner->len, GFP_KERNEL); if (!sop->so_owner.data) { |
fe0750e5c nfsd4: split stat... |
2266 |
kmem_cache_free(slab, sop); |
1da177e4c Linux-2.6.12-rc2 |
2267 |
return NULL; |
ff194bd95 nfsd4: cleanup lo... |
2268 2269 |
} sop->so_owner.len = owner->len; |
ea1da636e [PATCH] knfsd: nf... |
2270 |
INIT_LIST_HEAD(&sop->so_stateids); |
ff194bd95 nfsd4: cleanup lo... |
2271 2272 2273 2274 |
sop->so_client = clp; init_nfs4_replay(&sop->so_replay); return sop; } |
fe0750e5c nfsd4: split stat... |
2275 |
static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) |
ff194bd95 nfsd4: cleanup lo... |
2276 |
{ |
16bfdaafa nfsd4: share open... |
2277 |
list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); |
fe0750e5c nfsd4: split stat... |
2278 |
list_add(&oo->oo_perclient, &clp->cl_openowners); |
ff194bd95 nfsd4: cleanup lo... |
2279 |
} |
fe0750e5c nfsd4: split stat... |
2280 |
static struct nfs4_openowner * |
ff194bd95 nfsd4: cleanup lo... |
2281 |
alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) { |
fe0750e5c nfsd4: split stat... |
2282 |
struct nfs4_openowner *oo; |
ff194bd95 nfsd4: cleanup lo... |
2283 |
|
fe0750e5c nfsd4: split stat... |
2284 2285 |
oo = alloc_stateowner(openowner_slab, &open->op_owner, clp); if (!oo) |
ff194bd95 nfsd4: cleanup lo... |
2286 |
return NULL; |
fe0750e5c nfsd4: split stat... |
2287 2288 |
oo->oo_owner.so_is_open_owner = 1; oo->oo_owner.so_seqid = open->op_seqid; |
d29b20cd5 nfsd4: clean up o... |
2289 |
oo->oo_flags = NFS4_OO_NEW; |
fe0750e5c nfsd4: split stat... |
2290 |
oo->oo_time = 0; |
38c387b52 nfsd4: match clos... |
2291 |
oo->oo_last_closed_stid = NULL; |
fe0750e5c nfsd4: split stat... |
2292 2293 2294 |
INIT_LIST_HEAD(&oo->oo_close_lru); hash_openowner(oo, clp, strhashval); return oo; |
1da177e4c Linux-2.6.12-rc2 |
2295 |
} |
996e09385 nfsd4: do idr pre... |
2296 |
static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) { |
fe0750e5c nfsd4: split stat... |
2297 |
struct nfs4_openowner *oo = open->op_openowner; |
d3b313a46 nfsd4: construct ... |
2298 |
struct nfs4_client *clp = oo->oo_owner.so_client; |
1da177e4c Linux-2.6.12-rc2 |
2299 |
|
996e09385 nfsd4: do idr pre... |
2300 |
init_stid(&stp->st_stid, clp, NFS4_OPEN_STID); |
ea1da636e [PATCH] knfsd: nf... |
2301 |
INIT_LIST_HEAD(&stp->st_lockowners); |
fe0750e5c nfsd4: split stat... |
2302 |
list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); |
8beefa249 [PATCH] nfsd4: re... |
2303 |
list_add(&stp->st_perfile, &fp->fi_stateids); |
fe0750e5c nfsd4: split stat... |
2304 |
stp->st_stateowner = &oo->oo_owner; |
13cd21845 [PATCH] nfsd4: re... |
2305 |
get_nfs4_file(fp); |
1da177e4c Linux-2.6.12-rc2 |
2306 |
stp->st_file = fp; |
1da177e4c Linux-2.6.12-rc2 |
2307 2308 |
stp->st_access_bmap = 0; stp->st_deny_bmap = 0; |
b6d2f1ca3 nfsd4: more robus... |
2309 |
__set_bit(open->op_share_access, &stp->st_access_bmap); |
1da177e4c Linux-2.6.12-rc2 |
2310 |
__set_bit(open->op_share_deny, &stp->st_deny_bmap); |
4c4cd222e [PATCH] nfsd4: ch... |
2311 |
stp->st_openstp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
2312 2313 2314 |
} static void |
fe0750e5c nfsd4: split stat... |
2315 |
move_to_close_lru(struct nfs4_openowner *oo) |
1da177e4c Linux-2.6.12-rc2 |
2316 |
{ |
fe0750e5c nfsd4: split stat... |
2317 2318 |
dprintk("NFSD: move_to_close_lru nfs4_openowner %p ", oo); |
1da177e4c Linux-2.6.12-rc2 |
2319 |
|
fe0750e5c nfsd4: split stat... |
2320 2321 |
list_move_tail(&oo->oo_close_lru, &close_lru); oo->oo_time = get_seconds(); |
1da177e4c Linux-2.6.12-rc2 |
2322 |
} |
1da177e4c Linux-2.6.12-rc2 |
2323 |
static int |
599e0a229 knfsd: cleanup of... |
2324 2325 2326 2327 2328 2329 |
same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { return (sop->so_owner.len == owner->len) && 0 == memcmp(sop->so_owner.data, owner->data, owner->len) && (sop->so_client->cl_clientid.cl_id == clid->cl_id); |
1da177e4c Linux-2.6.12-rc2 |
2330 |
} |
fe0750e5c nfsd4: split stat... |
2331 |
static struct nfs4_openowner * |
1da177e4c Linux-2.6.12-rc2 |
2332 2333 |
find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) { |
a50d2ad17 nfsd4: centralize... |
2334 2335 |
struct nfs4_stateowner *so; struct nfs4_openowner *oo; |
1da177e4c Linux-2.6.12-rc2 |
2336 |
|
16bfdaafa nfsd4: share open... |
2337 2338 2339 |
list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { if (!so->so_is_open_owner) continue; |
a50d2ad17 nfsd4: centralize... |
2340 2341 2342 2343 2344 |
if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { oo = openowner(so); renew_client(oo->oo_owner.so_client); return oo; } |
1da177e4c Linux-2.6.12-rc2 |
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 |
} return NULL; } /* search file_hashtbl[] for file */ static struct nfs4_file * find_file(struct inode *ino) { unsigned int hashval = file_hashval(ino); struct nfs4_file *fp; |
8b671b807 nfsd4: remove use... |
2355 |
spin_lock(&recall_lock); |
1da177e4c Linux-2.6.12-rc2 |
2356 |
list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { |
13cd21845 [PATCH] nfsd4: re... |
2357 2358 |
if (fp->fi_inode == ino) { get_nfs4_file(fp); |
8b671b807 nfsd4: remove use... |
2359 |
spin_unlock(&recall_lock); |
1da177e4c Linux-2.6.12-rc2 |
2360 |
return fp; |
13cd21845 [PATCH] nfsd4: re... |
2361 |
} |
1da177e4c Linux-2.6.12-rc2 |
2362 |
} |
8b671b807 nfsd4: remove use... |
2363 |
spin_unlock(&recall_lock); |
1da177e4c Linux-2.6.12-rc2 |
2364 2365 |
return NULL; } |
4f83aa302 nfsd: document op... |
2366 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2367 2368 2369 |
* Called to check deny when READ with all zero stateid or * WRITE with all zero or all one stateid */ |
b37ad28bc [PATCH] nfsd: nfs... |
2370 |
static __be32 |
1da177e4c Linux-2.6.12-rc2 |
2371 2372 2373 2374 |
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) { struct inode *ino = current_fh->fh_dentry->d_inode; struct nfs4_file *fp; |
dcef0413d nfsd4: move some ... |
2375 |
struct nfs4_ol_stateid *stp; |
b37ad28bc [PATCH] nfsd: nfs... |
2376 |
__be32 ret; |
1da177e4c Linux-2.6.12-rc2 |
2377 2378 2379 2380 2381 |
dprintk("NFSD: nfs4_share_conflict "); fp = find_file(ino); |
13cd21845 [PATCH] nfsd4: re... |
2382 2383 |
if (!fp) return nfs_ok; |
b700949b7 [PATCH] nfsd4: re... |
2384 |
ret = nfserr_locked; |
1da177e4c Linux-2.6.12-rc2 |
2385 |
/* Search for conflicting share reservations */ |
13cd21845 [PATCH] nfsd4: re... |
2386 2387 2388 2389 |
list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { if (test_bit(deny_type, &stp->st_deny_bmap) || test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap)) goto out; |
1da177e4c Linux-2.6.12-rc2 |
2390 |
} |
13cd21845 [PATCH] nfsd4: re... |
2391 2392 2393 2394 |
ret = nfs_ok; out: put_nfs4_file(fp); return ret; |
1da177e4c Linux-2.6.12-rc2 |
2395 |
} |
6b57d9c86 nfsd4: split up n... |
2396 |
static void nfsd_break_one_deleg(struct nfs4_delegation *dp) |
1da177e4c Linux-2.6.12-rc2 |
2397 |
{ |
1da177e4c Linux-2.6.12-rc2 |
2398 2399 2400 2401 2402 2403 |
/* We're assuming the state code never drops its reference * without first removing the lease. Since we're in this lease * callback (and since the lease code is serialized by the kernel * lock) we know the server hasn't removed the lease yet, we know * it's safe to take a reference: */ atomic_inc(&dp->dl_count); |
1da177e4c Linux-2.6.12-rc2 |
2404 |
list_add_tail(&dp->dl_recall_lru, &del_recall_lru); |
1da177e4c Linux-2.6.12-rc2 |
2405 |
|
460781b54 BKL: remove refer... |
2406 |
/* only place dl_time is set. protected by lock_flocks*/ |
1da177e4c Linux-2.6.12-rc2 |
2407 |
dp->dl_time = get_seconds(); |
6b57d9c86 nfsd4: split up n... |
2408 2409 |
nfsd4_cb_recall(dp); } |
acfdf5c38 nfsd4: acquire on... |
2410 |
/* Called from break_lease() with lock_flocks() held. */ |
6b57d9c86 nfsd4: split up n... |
2411 2412 |
static void nfsd_break_deleg_cb(struct file_lock *fl) { |
acfdf5c38 nfsd4: acquire on... |
2413 2414 |
struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner; struct nfs4_delegation *dp; |
6b57d9c86 nfsd4: split up n... |
2415 |
|
acfdf5c38 nfsd4: acquire on... |
2416 2417 2418 |
BUG_ON(!fp); /* We assume break_lease is only called once per lease: */ BUG_ON(fp->fi_had_conflict); |
0272e1fd9 knfsd: let nfsd m... |
2419 2420 |
/* * We don't want the locks code to timeout the lease for us; |
acfdf5c38 nfsd4: acquire on... |
2421 |
* we'll remove it ourself if a delegation isn't returned |
6b57d9c86 nfsd4: split up n... |
2422 |
* in time: |
0272e1fd9 knfsd: let nfsd m... |
2423 2424 |
*/ fl->fl_break_time = 0; |
1da177e4c Linux-2.6.12-rc2 |
2425 |
|
5d926e8c2 nfsd4: modify fi_... |
2426 |
spin_lock(&recall_lock); |
acfdf5c38 nfsd4: acquire on... |
2427 2428 2429 |
fp->fi_had_conflict = true; list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) nfsd_break_one_deleg(dp); |
5d926e8c2 nfsd4: modify fi_... |
2430 |
spin_unlock(&recall_lock); |
1da177e4c Linux-2.6.12-rc2 |
2431 |
} |
1da177e4c Linux-2.6.12-rc2 |
2432 2433 2434 2435 2436 2437 2438 2439 |
static int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) { if (arg & F_UNLCK) return lease_modify(onlist, arg); else return -EAGAIN; } |
7b021967c const: make lock_... |
2440 |
static const struct lock_manager_operations nfsd_lease_mng_ops = { |
8fb47a4fb locks: rename loc... |
2441 2442 |
.lm_break = nfsd_break_deleg_cb, .lm_change = nfsd_change_deleg_cb, |
1da177e4c Linux-2.6.12-rc2 |
2443 |
}; |
7a8711c9a nfsd4: share comm... |
2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 |
static __be32 nfsd4_check_seqid(struct nfsd4_compound_state *cstate, struct nfs4_stateowner *so, u32 seqid) { if (nfsd4_has_session(cstate)) return nfs_ok; if (seqid == so->so_seqid - 1) return nfserr_replay_me; if (seqid == so->so_seqid) return nfs_ok; return nfserr_bad_seqid; } |
1da177e4c Linux-2.6.12-rc2 |
2454 |
|
b37ad28bc [PATCH] nfsd: nfs... |
2455 |
__be32 |
6668958fa nfsd41: stateid h... |
2456 2457 |
nfsd4_process_open1(struct nfsd4_compound_state *cstate, struct nfsd4_open *open) |
1da177e4c Linux-2.6.12-rc2 |
2458 |
{ |
1da177e4c Linux-2.6.12-rc2 |
2459 2460 2461 |
clientid_t *clientid = &open->op_clientid; struct nfs4_client *clp = NULL; unsigned int strhashval; |
fe0750e5c nfsd4: split stat... |
2462 |
struct nfs4_openowner *oo = NULL; |
4cdc951b8 nfsd4: preallocat... |
2463 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
2464 |
|
1da177e4c Linux-2.6.12-rc2 |
2465 2466 |
if (STALE_CLIENTID(&open->op_clientid)) return nfserr_stale_clientid; |
32513b40e nfsd4: preallocat... |
2467 2468 2469 2470 2471 2472 2473 |
/* * In case we need it later, after we've already created the * file and don't want to risk a further failure: */ open->op_file = nfsd4_alloc_file(); if (open->op_file == NULL) return nfserr_jukebox; |
1da177e4c Linux-2.6.12-rc2 |
2474 |
|
16bfdaafa nfsd4: share open... |
2475 |
strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); |
fe0750e5c nfsd4: split stat... |
2476 2477 2478 |
oo = find_openstateowner_str(strhashval, open); open->op_openowner = oo; if (!oo) { |
1da177e4c Linux-2.6.12-rc2 |
2479 2480 |
clp = find_confirmed_client(clientid); if (clp == NULL) |
0f442aa29 [PATCH] nfsd4: si... |
2481 |
return nfserr_expired; |
bcf130f9d nfsd4: simplify p... |
2482 |
goto new_owner; |
1da177e4c Linux-2.6.12-rc2 |
2483 |
} |
dad1c067e nfsd4: replace oo... |
2484 |
if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { |
0f442aa29 [PATCH] nfsd4: si... |
2485 |
/* Replace unconfirmed owners without checking for replay. */ |
fe0750e5c nfsd4: split stat... |
2486 2487 2488 |
clp = oo->oo_owner.so_client; release_openowner(oo); open->op_openowner = NULL; |
bcf130f9d nfsd4: simplify p... |
2489 |
goto new_owner; |
0f442aa29 [PATCH] nfsd4: si... |
2490 |
} |
4cdc951b8 nfsd4: preallocat... |
2491 2492 2493 2494 2495 |
status = nfsd4_check_seqid(cstate, &oo->oo_owner, open->op_seqid); if (status) return status; clp = oo->oo_owner.so_client; goto alloc_stateid; |
bcf130f9d nfsd4: simplify p... |
2496 2497 2498 2499 2500 |
new_owner: oo = alloc_init_open_stateowner(strhashval, clp, open); if (oo == NULL) return nfserr_jukebox; open->op_openowner = oo; |
4cdc951b8 nfsd4: preallocat... |
2501 2502 2503 2504 |
alloc_stateid: open->op_stp = nfs4_alloc_stateid(clp); if (!open->op_stp) return nfserr_jukebox; |
0f442aa29 [PATCH] nfsd4: si... |
2505 |
return nfs_ok; |
1da177e4c Linux-2.6.12-rc2 |
2506 |
} |
b37ad28bc [PATCH] nfsd: nfs... |
2507 |
static inline __be32 |
4a6e43e6d [PATCH] nfsd4: nf... |
2508 2509 2510 2511 2512 2513 2514 |
nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) { if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ)) return nfserr_openmode; else return nfs_ok; } |
f459e4535 nfsd4: hash deleg... |
2515 |
static int share_access_to_flags(u32 share_access) |
52f4fb430 [PATCH] nfsd4: fi... |
2516 |
{ |
f459e4535 nfsd4: hash deleg... |
2517 |
share_access &= ~NFS4_SHARE_WANT_MASK; |
52f4fb430 [PATCH] nfsd4: fi... |
2518 |
|
f459e4535 nfsd4: hash deleg... |
2519 |
return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; |
52f4fb430 [PATCH] nfsd4: fi... |
2520 |
} |
38c2f4b12 nfsd4: look up st... |
2521 |
static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, stateid_t *s) |
24a0111e4 nfsd4: fix use of... |
2522 |
{ |
f459e4535 nfsd4: hash deleg... |
2523 |
struct nfs4_stid *ret; |
24a0111e4 nfsd4: fix use of... |
2524 |
|
38c2f4b12 nfsd4: look up st... |
2525 |
ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID); |
f459e4535 nfsd4: hash deleg... |
2526 2527 2528 |
if (!ret) return NULL; return delegstateid(ret); |
24a0111e4 nfsd4: fix use of... |
2529 |
} |
8b289b2c2 nfsd4: implement ... |
2530 2531 2532 2533 2534 |
static bool nfsd4_is_deleg_cur(struct nfsd4_open *open) { return open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR || open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH; } |
b37ad28bc [PATCH] nfsd: nfs... |
2535 |
static __be32 |
38c2f4b12 nfsd4: look up st... |
2536 |
nfs4_check_deleg(struct nfs4_client *cl, struct nfs4_file *fp, struct nfsd4_open *open, |
567d98292 [PATCH] nfsd4: do... |
2537 2538 2539 |
struct nfs4_delegation **dp) { int flags; |
b37ad28bc [PATCH] nfsd: nfs... |
2540 |
__be32 status = nfserr_bad_stateid; |
567d98292 [PATCH] nfsd4: do... |
2541 |
|
38c2f4b12 nfsd4: look up st... |
2542 |
*dp = find_deleg_stateid(cl, &open->op_delegate_stateid); |
567d98292 [PATCH] nfsd4: do... |
2543 |
if (*dp == NULL) |
c44c5eeb2 [PATCH] nfsd4: ad... |
2544 |
goto out; |
24a0111e4 nfsd4: fix use of... |
2545 |
flags = share_access_to_flags(open->op_share_access); |
567d98292 [PATCH] nfsd4: do... |
2546 2547 2548 |
status = nfs4_check_delegmode(*dp, flags); if (status) *dp = NULL; |
c44c5eeb2 [PATCH] nfsd4: ad... |
2549 |
out: |
8b289b2c2 nfsd4: implement ... |
2550 |
if (!nfsd4_is_deleg_cur(open)) |
c44c5eeb2 [PATCH] nfsd4: ad... |
2551 2552 2553 |
return nfs_ok; if (status) return status; |
dad1c067e nfsd4: replace oo... |
2554 |
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; |
c44c5eeb2 [PATCH] nfsd4: ad... |
2555 |
return nfs_ok; |
567d98292 [PATCH] nfsd4: do... |
2556 |
} |
b37ad28bc [PATCH] nfsd: nfs... |
2557 |
static __be32 |
dcef0413d nfsd4: move some ... |
2558 |
nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_stateid **stpp) |
1da177e4c Linux-2.6.12-rc2 |
2559 |
{ |
dcef0413d nfsd4: move some ... |
2560 |
struct nfs4_ol_stateid *local; |
fe0750e5c nfsd4: split stat... |
2561 |
struct nfs4_openowner *oo = open->op_openowner; |
1da177e4c Linux-2.6.12-rc2 |
2562 |
|
8beefa249 [PATCH] nfsd4: re... |
2563 |
list_for_each_entry(local, &fp->fi_stateids, st_perfile) { |
1da177e4c Linux-2.6.12-rc2 |
2564 2565 2566 2567 |
/* ignore lock owners */ if (local->st_stateowner->so_is_open_owner == 0) continue; /* remember if we have seen this open owner */ |
fe0750e5c nfsd4: split stat... |
2568 |
if (local->st_stateowner == &oo->oo_owner) |
1da177e4c Linux-2.6.12-rc2 |
2569 2570 2571 |
*stpp = local; /* check for conflicting share reservations */ if (!test_share(local, open)) |
77eaae8d4 nfsd4: simplify c... |
2572 |
return nfserr_share_denied; |
1da177e4c Linux-2.6.12-rc2 |
2573 |
} |
77eaae8d4 nfsd4: simplify c... |
2574 |
return nfs_ok; |
1da177e4c Linux-2.6.12-rc2 |
2575 |
} |
996e09385 nfsd4: do idr pre... |
2576 2577 2578 |
static void nfs4_free_stateid(struct nfs4_ol_stateid *s) { kmem_cache_free(stateid_slab, s); |
5ac049ac6 [PATCH] nfsd4: sl... |
2579 |
} |
21fb4016b nfsd4: miscellane... |
2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 |
static inline int nfs4_access_to_access(u32 nfs4_access) { int flags = 0; if (nfs4_access & NFS4_SHARE_ACCESS_READ) flags |= NFSD_MAY_READ; if (nfs4_access & NFS4_SHARE_ACCESS_WRITE) flags |= NFSD_MAY_WRITE; return flags; } |
0c12eaffd nfsd: don't break... |
2590 2591 |
static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfsd4_open *open) |
f9d7562fd nfsd4: share file... |
2592 2593 |
{ __be32 status; |
0c12eaffd nfsd: don't break... |
2594 2595 |
int oflag = nfs4_access_to_omode(open->op_share_access); int access = nfs4_access_to_access(open->op_share_access); |
f9d7562fd nfsd4: share file... |
2596 2597 2598 |
if (!fp->fi_fds[oflag]) { status = nfsd_open(rqstp, cur_fh, S_IFREG, access, &fp->fi_fds[oflag]); |
f9d7562fd nfsd4: share file... |
2599 2600 2601 2602 2603 2604 2605 |
if (status) return status; } nfs4_file_get_access(fp, oflag); return nfs_ok; } |
b37ad28bc [PATCH] nfsd: nfs... |
2606 |
static inline __be32 |
1da177e4c Linux-2.6.12-rc2 |
2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 |
nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, struct nfsd4_open *open) { struct iattr iattr = { .ia_valid = ATTR_SIZE, .ia_size = 0, }; if (!open->op_truncate) return 0; if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) |
9246585a1 [PATCH] nfsd4_tru... |
2617 |
return nfserr_inval; |
1da177e4c Linux-2.6.12-rc2 |
2618 2619 |
return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); } |
b37ad28bc [PATCH] nfsd: nfs... |
2620 |
static __be32 |
dcef0413d nfsd4: move some ... |
2621 |
nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_ol_stateid *stp, struct nfsd4_open *open) |
1da177e4c Linux-2.6.12-rc2 |
2622 |
{ |
b6d2f1ca3 nfsd4: more robus... |
2623 |
u32 op_share_access = open->op_share_access; |
7d9478429 nfsd4: fix downgr... |
2624 |
bool new_access; |
b37ad28bc [PATCH] nfsd: nfs... |
2625 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
2626 |
|
7d9478429 nfsd4: fix downgr... |
2627 |
new_access = !test_bit(op_share_access, &stp->st_access_bmap); |
f9d7562fd nfsd4: share file... |
2628 |
if (new_access) { |
0c12eaffd nfsd: don't break... |
2629 |
status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open); |
f9d7562fd nfsd4: share file... |
2630 2631 |
if (status) return status; |
6c26d08f0 [PATCH] nfsd4: fi... |
2632 |
} |
1da177e4c Linux-2.6.12-rc2 |
2633 2634 |
status = nfsd4_truncate(rqstp, cur_fh, open); if (status) { |
f9d7562fd nfsd4: share file... |
2635 |
if (new_access) { |
f197c2719 nfsd4: fix file l... |
2636 |
int oflag = nfs4_access_to_omode(op_share_access); |
f9d7562fd nfsd4: share file... |
2637 2638 |
nfs4_file_put_access(fp, oflag); } |
1da177e4c Linux-2.6.12-rc2 |
2639 2640 2641 |
return status; } /* remember the open */ |
24a0111e4 nfsd4: fix use of... |
2642 |
__set_bit(op_share_access, &stp->st_access_bmap); |
b55e0ba19 nfsd: remove unne... |
2643 |
__set_bit(open->op_share_deny, &stp->st_deny_bmap); |
1da177e4c Linux-2.6.12-rc2 |
2644 2645 2646 |
return nfs_ok; } |
1da177e4c Linux-2.6.12-rc2 |
2647 |
static void |
375151773 [PATCH] nfsd4: st... |
2648 |
nfs4_set_claim_prev(struct nfsd4_open *open) |
1da177e4c Linux-2.6.12-rc2 |
2649 |
{ |
dad1c067e nfsd4: replace oo... |
2650 |
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; |
fe0750e5c nfsd4: split stat... |
2651 |
open->op_openowner->oo_owner.so_client->cl_firststate = 1; |
1da177e4c Linux-2.6.12-rc2 |
2652 |
} |
14a24e99f nfsd4: give out d... |
2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 |
/* Should we give out recallable state?: */ static bool nfsd4_cb_channel_good(struct nfs4_client *clp) { if (clp->cl_cb_state == NFSD4_CB_UP) return true; /* * In the sessions case, since we don't have to establish a * separate connection for callbacks, we assume it's OK * until we hear otherwise: */ return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN; } |
22d38c4c1 nfsd4: add helper... |
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 |
static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int flag) { struct file_lock *fl; fl = locks_alloc_lock(); if (!fl) return NULL; locks_init_lock(fl); fl->fl_lmops = &nfsd_lease_mng_ops; fl->fl_flags = FL_LEASE; fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; fl->fl_end = OFFSET_MAX; |
acfdf5c38 nfsd4: acquire on... |
2677 |
fl->fl_owner = (fl_owner_t)(dp->dl_file); |
22d38c4c1 nfsd4: add helper... |
2678 |
fl->fl_pid = current->tgid; |
22d38c4c1 nfsd4: add helper... |
2679 2680 |
return fl; } |
edab9782b nfsd4: split leas... |
2681 2682 |
static int nfs4_setlease(struct nfs4_delegation *dp, int flag) { |
acfdf5c38 nfsd4: acquire on... |
2683 |
struct nfs4_file *fp = dp->dl_file; |
edab9782b nfsd4: split leas... |
2684 2685 2686 2687 2688 2689 |
struct file_lock *fl; int status; fl = nfs4_alloc_init_lease(dp, flag); if (!fl) return -ENOMEM; |
acfdf5c38 nfsd4: acquire on... |
2690 |
fl->fl_file = find_readable_file(fp); |
2a74aba79 nfsd4: move clien... |
2691 |
list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); |
acfdf5c38 nfsd4: acquire on... |
2692 |
status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); |
edab9782b nfsd4: split leas... |
2693 |
if (status) { |
acfdf5c38 nfsd4: acquire on... |
2694 |
list_del_init(&dp->dl_perclnt); |
edab9782b nfsd4: split leas... |
2695 2696 2697 |
locks_free_lock(fl); return -ENOMEM; } |
acfdf5c38 nfsd4: acquire on... |
2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 |
fp->fi_lease = fl; fp->fi_deleg_file = fl->fl_file; get_file(fp->fi_deleg_file); atomic_set(&fp->fi_delegees, 1); list_add(&dp->dl_perfile, &fp->fi_delegations); return 0; } static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) { struct nfs4_file *fp = dp->dl_file; if (!fp->fi_lease) return nfs4_setlease(dp, flag); spin_lock(&recall_lock); if (fp->fi_had_conflict) { spin_unlock(&recall_lock); return -EAGAIN; } atomic_inc(&fp->fi_delegees); list_add(&dp->dl_perfile, &fp->fi_delegations); spin_unlock(&recall_lock); |
2a74aba79 nfsd4: move clien... |
2720 |
list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); |
edab9782b nfsd4: split leas... |
2721 2722 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
2723 2724 2725 2726 |
/* * Attempt to hand out a delegation. */ static void |
dcef0413d nfsd4: move some ... |
2727 |
nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_stateid *stp) |
1da177e4c Linux-2.6.12-rc2 |
2728 2729 |
{ struct nfs4_delegation *dp; |
fe0750e5c nfsd4: split stat... |
2730 |
struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); |
14a24e99f nfsd4: give out d... |
2731 |
int cb_up; |
1da177e4c Linux-2.6.12-rc2 |
2732 |
int status, flag = 0; |
fe0750e5c nfsd4: split stat... |
2733 |
cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); |
1da177e4c Linux-2.6.12-rc2 |
2734 |
flag = NFS4_OPEN_DELEGATE_NONE; |
7b190fecf [PATCH] knfsd: nf... |
2735 2736 2737 |
open->op_recall = 0; switch (open->op_claim_type) { case NFS4_OPEN_CLAIM_PREVIOUS: |
2bf23875f nfsd4: rearrange ... |
2738 |
if (!cb_up) |
7b190fecf [PATCH] knfsd: nf... |
2739 2740 2741 2742 2743 2744 2745 2746 |
open->op_recall = 1; flag = open->op_delegate_type; if (flag == NFS4_OPEN_DELEGATE_NONE) goto out; break; case NFS4_OPEN_CLAIM_NULL: /* Let's not give out any delegations till everyone's * had the chance to reclaim theirs.... */ |
af558e33b nfsd: common grac... |
2747 |
if (locks_in_grace()) |
7b190fecf [PATCH] knfsd: nf... |
2748 |
goto out; |
dad1c067e nfsd4: replace oo... |
2749 |
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) |
7b190fecf [PATCH] knfsd: nf... |
2750 2751 2752 2753 2754 2755 2756 2757 2758 |
goto out; if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) flag = NFS4_OPEN_DELEGATE_WRITE; else flag = NFS4_OPEN_DELEGATE_READ; break; default: goto out; } |
1da177e4c Linux-2.6.12-rc2 |
2759 |
|
fe0750e5c nfsd4: split stat... |
2760 |
dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh, flag); |
dd239cc05 nfsd4: fix leak o... |
2761 2762 |
if (dp == NULL) goto out_no_deleg; |
acfdf5c38 nfsd4: acquire on... |
2763 |
status = nfs4_set_delegation(dp, flag); |
edab9782b nfsd4: split leas... |
2764 |
if (status) |
dd239cc05 nfsd4: fix leak o... |
2765 |
goto out_free; |
1da177e4c Linux-2.6.12-rc2 |
2766 |
|
d5477a8db nfsd4: add common... |
2767 |
memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid)); |
1da177e4c Linux-2.6.12-rc2 |
2768 |
|
8c10cbdb4 nfsd: use STATEID... |
2769 2770 |
dprintk("NFSD: delegation stateid=" STATEID_FMT " ", |
d5477a8db nfsd4: add common... |
2771 |
STATEID_VAL(&dp->dl_stid.sc_stateid)); |
1da177e4c Linux-2.6.12-rc2 |
2772 |
out: |
7b190fecf [PATCH] knfsd: nf... |
2773 2774 2775 |
if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && flag == NFS4_OPEN_DELEGATE_NONE && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) |
2fdada03b knfsd: demote som... |
2776 2777 |
dprintk("NFSD: WARNING: refusing delegation reclaim "); |
1da177e4c Linux-2.6.12-rc2 |
2778 |
open->op_delegate_type = flag; |
dd239cc05 nfsd4: fix leak o... |
2779 2780 |
return; out_free: |
acfdf5c38 nfsd4: acquire on... |
2781 |
nfs4_put_delegation(dp); |
dd239cc05 nfsd4: fix leak o... |
2782 2783 2784 |
out_no_deleg: flag = NFS4_OPEN_DELEGATE_NONE; goto out; |
1da177e4c Linux-2.6.12-rc2 |
2785 2786 2787 2788 2789 |
} /* * called with nfs4_lock_state() held. */ |
b37ad28bc [PATCH] nfsd: nfs... |
2790 |
__be32 |
1da177e4c Linux-2.6.12-rc2 |
2791 2792 |
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { |
6668958fa nfsd41: stateid h... |
2793 |
struct nfsd4_compoundres *resp = rqstp->rq_resp; |
38c2f4b12 nfsd4: look up st... |
2794 |
struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; |
1da177e4c Linux-2.6.12-rc2 |
2795 2796 |
struct nfs4_file *fp = NULL; struct inode *ino = current_fh->fh_dentry->d_inode; |
dcef0413d nfsd4: move some ... |
2797 |
struct nfs4_ol_stateid *stp = NULL; |
567d98292 [PATCH] nfsd4: do... |
2798 |
struct nfs4_delegation *dp = NULL; |
b37ad28bc [PATCH] nfsd: nfs... |
2799 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
2800 |
|
1da177e4c Linux-2.6.12-rc2 |
2801 2802 2803 2804 2805 2806 2807 2808 2809 |
/* * Lookup file; if found, lookup stateid and check open request, * and check for delegations in the process of being recalled. * If not found, create the nfs4_file struct */ fp = find_file(ino); if (fp) { if ((status = nfs4_check_open(fp, open, &stp))) goto out; |
38c2f4b12 nfsd4: look up st... |
2810 |
status = nfs4_check_deleg(cl, fp, open, &dp); |
c44c5eeb2 [PATCH] nfsd4: ad... |
2811 2812 |
if (status) goto out; |
1da177e4c Linux-2.6.12-rc2 |
2813 |
} else { |
c44c5eeb2 [PATCH] nfsd4: ad... |
2814 |
status = nfserr_bad_stateid; |
8b289b2c2 nfsd4: implement ... |
2815 |
if (nfsd4_is_deleg_cur(open)) |
c44c5eeb2 [PATCH] nfsd4: ad... |
2816 |
goto out; |
3e7724639 nfsd4: stop using... |
2817 |
status = nfserr_jukebox; |
32513b40e nfsd4: preallocat... |
2818 2819 2820 |
fp = open->op_file; open->op_file = NULL; nfsd4_init_file(fp, ino); |
1da177e4c Linux-2.6.12-rc2 |
2821 2822 2823 2824 2825 2826 2827 2828 |
} /* * OPEN the file, or upgrade an existing OPEN. * If truncate fails, the OPEN fails. */ if (stp) { /* Stateid was found, this is an OPEN upgrade */ |
f9d7562fd nfsd4: share file... |
2829 |
status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); |
1da177e4c Linux-2.6.12-rc2 |
2830 2831 2832 |
if (status) goto out; } else { |
4cdc951b8 nfsd4: preallocat... |
2833 |
status = nfs4_get_vfs_file(rqstp, fp, current_fh, open); |
567d98292 [PATCH] nfsd4: do... |
2834 |
if (status) |
1da177e4c Linux-2.6.12-rc2 |
2835 |
goto out; |
4cdc951b8 nfsd4: preallocat... |
2836 2837 |
stp = open->op_stp; open->op_stp = NULL; |
996e09385 nfsd4: do idr pre... |
2838 |
init_open_stateid(stp, fp, open); |
1da177e4c Linux-2.6.12-rc2 |
2839 2840 |
status = nfsd4_truncate(rqstp, current_fh, open); if (status) { |
2283963f2 nfsd4: split lock... |
2841 |
release_open_stateid(stp); |
1da177e4c Linux-2.6.12-rc2 |
2842 2843 2844 |
goto out; } } |
dcef0413d nfsd4: move some ... |
2845 2846 |
update_stateid(&stp->st_stid.sc_stateid); memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
1da177e4c Linux-2.6.12-rc2 |
2847 |
|
4dc6ec00f nfsd4: implement ... |
2848 |
if (nfsd4_has_session(&resp->cstate)) |
dad1c067e nfsd4: replace oo... |
2849 |
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; |
6668958fa nfsd41: stateid h... |
2850 |
|
1da177e4c Linux-2.6.12-rc2 |
2851 2852 2853 2854 2855 2856 2857 |
/* * Attempt to hand out a delegation. No error return, because the * OPEN succeeds even if we fail. */ nfs4_open_delegation(current_fh, open, stp); status = nfs_ok; |
8c10cbdb4 nfsd: use STATEID... |
2858 2859 |
dprintk("%s: stateid=" STATEID_FMT " ", __func__, |
dcef0413d nfsd4: move some ... |
2860 |
STATEID_VAL(&stp->st_stid.sc_stateid)); |
1da177e4c Linux-2.6.12-rc2 |
2861 |
out: |
13cd21845 [PATCH] nfsd4: re... |
2862 2863 |
if (fp) put_nfs4_file(fp); |
375151773 [PATCH] nfsd4: st... |
2864 2865 |
if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) nfs4_set_claim_prev(open); |
1da177e4c Linux-2.6.12-rc2 |
2866 2867 2868 2869 |
/* * To finish the open response, we just need to set the rflags. */ open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX; |
dad1c067e nfsd4: replace oo... |
2870 |
if (!(open->op_openowner->oo_flags & NFS4_OO_CONFIRMED) && |
6668958fa nfsd41: stateid h... |
2871 |
!nfsd4_has_session(&resp->cstate)) |
1da177e4c Linux-2.6.12-rc2 |
2872 2873 2874 2875 |
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM; return status; } |
d29b20cd5 nfsd4: clean up o... |
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 |
void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status) { if (open->op_openowner) { struct nfs4_openowner *oo = open->op_openowner; if (!list_empty(&oo->oo_owner.so_stateids)) list_del_init(&oo->oo_close_lru); if (oo->oo_flags & NFS4_OO_NEW) { if (status) { release_openowner(oo); open->op_openowner = NULL; } else oo->oo_flags &= ~NFS4_OO_NEW; } } |
32513b40e nfsd4: preallocat... |
2891 2892 |
if (open->op_file) nfsd4_free_file(open->op_file); |
4cdc951b8 nfsd4: preallocat... |
2893 2894 |
if (open->op_stp) nfs4_free_stateid(open->op_stp); |
d29b20cd5 nfsd4: clean up o... |
2895 |
} |
b37ad28bc [PATCH] nfsd: nfs... |
2896 |
__be32 |
b591480bb [PATCH] knfsd: nf... |
2897 2898 |
nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, clientid_t *clid) |
1da177e4c Linux-2.6.12-rc2 |
2899 2900 |
{ struct nfs4_client *clp; |
b37ad28bc [PATCH] nfsd: nfs... |
2901 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 |
nfs4_lock_state(); dprintk("process_renew(%08x/%08x): starting ", clid->cl_boot, clid->cl_id); status = nfserr_stale_clientid; if (STALE_CLIENTID(clid)) goto out; clp = find_confirmed_client(clid); status = nfserr_expired; if (clp == NULL) { /* We assume the client took too long to RENEW. */ dprintk("nfsd4_renew: clientid not found! "); goto out; } |
1da177e4c Linux-2.6.12-rc2 |
2918 |
status = nfserr_cb_path_down; |
ea1da636e [PATCH] knfsd: nf... |
2919 |
if (!list_empty(&clp->cl_delegations) |
77a3569d6 nfsd4: keep finer... |
2920 |
&& clp->cl_cb_state != NFSD4_CB_UP) |
1da177e4c Linux-2.6.12-rc2 |
2921 2922 2923 2924 2925 2926 |
goto out; status = nfs_ok; out: nfs4_unlock_state(); return status; } |
c47d832bc nfsd: make local ... |
2927 |
static struct lock_manager nfsd4_manager = { |
af558e33b nfsd: common grac... |
2928 |
}; |
a76b4319c [PATCH] knfsd: nf... |
2929 |
static void |
af558e33b nfsd: common grac... |
2930 |
nfsd4_end_grace(void) |
a76b4319c [PATCH] knfsd: nf... |
2931 2932 2933 |
{ dprintk("NFSD: end of grace period "); |
c7b9a4592 [PATCH] knfsd: nf... |
2934 |
nfsd4_recdir_purge_old(); |
af558e33b nfsd: common grac... |
2935 |
locks_end_grace(&nfsd4_manager); |
e46b498c8 nfsd4: simplify l... |
2936 2937 2938 2939 2940 2941 |
/* * Now that every NFSv4 client has had the chance to recover and * to see the (possibly new, possibly shorter) lease time, we * can safely set the next grace time to the current lease time: */ nfsd4_grace = nfsd4_lease; |
a76b4319c [PATCH] knfsd: nf... |
2942 |
} |
fd39ca9a8 [PATCH] knfsd: nf... |
2943 |
static time_t |
1da177e4c Linux-2.6.12-rc2 |
2944 2945 2946 |
nfs4_laundromat(void) { struct nfs4_client *clp; |
fe0750e5c nfsd4: split stat... |
2947 |
struct nfs4_openowner *oo; |
1da177e4c Linux-2.6.12-rc2 |
2948 2949 |
struct nfs4_delegation *dp; struct list_head *pos, *next, reaplist; |
cf07d2ea4 nfsd4: simplify r... |
2950 2951 2952 |
time_t cutoff = get_seconds() - nfsd4_lease; time_t t, clientid_val = nfsd4_lease; time_t u, test_val = nfsd4_lease; |
1da177e4c Linux-2.6.12-rc2 |
2953 2954 2955 2956 2957 |
nfs4_lock_state(); dprintk("NFSD: laundromat service - starting "); |
af558e33b nfsd: common grac... |
2958 2959 |
if (locks_in_grace()) nfsd4_end_grace(); |
36acb66bd nfsd4: extend the... |
2960 2961 |
INIT_LIST_HEAD(&reaplist); spin_lock(&client_lock); |
1da177e4c Linux-2.6.12-rc2 |
2962 2963 2964 2965 2966 2967 2968 2969 |
list_for_each_safe(pos, next, &client_lru) { clp = list_entry(pos, struct nfs4_client, cl_lru); if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { t = clp->cl_time - cutoff; if (clientid_val > t) clientid_val = t; break; } |
d76829889 nfsd4: keep a ref... |
2970 2971 2972 2973 2974 2975 2976 2977 |
if (atomic_read(&clp->cl_refcount)) { dprintk("NFSD: client in use (clientid %08x) ", clp->cl_clientid.cl_id); continue; } unhash_client_locked(clp); list_add(&clp->cl_lru, &reaplist); |
36acb66bd nfsd4: extend the... |
2978 2979 2980 2981 |
} spin_unlock(&client_lock); list_for_each_safe(pos, next, &reaplist) { clp = list_entry(pos, struct nfs4_client, cl_lru); |
1da177e4c Linux-2.6.12-rc2 |
2982 2983 2984 |
dprintk("NFSD: purging unused client (clientid %08x) ", clp->cl_clientid.cl_id); |
c7b9a4592 [PATCH] knfsd: nf... |
2985 |
nfsd4_remove_clid_dir(clp); |
1da177e4c Linux-2.6.12-rc2 |
2986 2987 |
expire_client(clp); } |
1da177e4c Linux-2.6.12-rc2 |
2988 2989 2990 2991 2992 2993 2994 2995 2996 |
spin_lock(&recall_lock); list_for_each_safe(pos, next, &del_recall_lru) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) { u = dp->dl_time - cutoff; if (test_val > u) test_val = u; break; } |
1da177e4c Linux-2.6.12-rc2 |
2997 2998 2999 3000 3001 |
list_move(&dp->dl_recall_lru, &reaplist); } spin_unlock(&recall_lock); list_for_each_safe(pos, next, &reaplist) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); |
1da177e4c Linux-2.6.12-rc2 |
3002 3003 |
unhash_delegation(dp); } |
cf07d2ea4 nfsd4: simplify r... |
3004 |
test_val = nfsd4_lease; |
1da177e4c Linux-2.6.12-rc2 |
3005 |
list_for_each_safe(pos, next, &close_lru) { |
fe0750e5c nfsd4: split stat... |
3006 3007 3008 |
oo = container_of(pos, struct nfs4_openowner, oo_close_lru); if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) { u = oo->oo_time - cutoff; |
1da177e4c Linux-2.6.12-rc2 |
3009 3010 3011 3012 |
if (test_val > u) test_val = u; break; } |
fe0750e5c nfsd4: split stat... |
3013 |
release_openowner(oo); |
1da177e4c Linux-2.6.12-rc2 |
3014 3015 3016 3017 3018 3019 |
} if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT; nfs4_unlock_state(); return clientid_val; } |
a254b246e nfsd: fix sparse ... |
3020 3021 3022 3023 3024 |
static struct workqueue_struct *laundry_wq; static void laundromat_main(struct work_struct *); static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main); static void |
c4028958b WorkStruct: make ... |
3025 |
laundromat_main(struct work_struct *not_used) |
1da177e4c Linux-2.6.12-rc2 |
3026 3027 3028 3029 3030 3031 |
{ time_t t; t = nfs4_laundromat(); dprintk("NFSD: laundromat_main - sleeping for %ld seconds ", t); |
58da282b7 [PATCH] knfsd: nf... |
3032 |
queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); |
1da177e4c Linux-2.6.12-rc2 |
3033 |
} |
f7a4d8720 nfsd4: hash close... |
3034 |
static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp) |
1da177e4c Linux-2.6.12-rc2 |
3035 |
{ |
f7a4d8720 nfsd4: hash close... |
3036 3037 3038 |
if (fhp->fh_dentry->d_inode != stp->st_file->fi_inode) return nfserr_bad_stateid; return nfs_ok; |
1da177e4c Linux-2.6.12-rc2 |
3039 3040 3041 3042 3043 |
} static int STALE_STATEID(stateid_t *stateid) { |
d3b313a46 nfsd4: construct ... |
3044 |
if (stateid->si_opaque.so_clid.cl_boot == boot_time) |
e4e83ea47 Revert "nfsd4: di... |
3045 3046 3047 |
return 0; dprintk("NFSD: stale stateid " STATEID_FMT "! ", |
8c10cbdb4 nfsd: use STATEID... |
3048 |
STATEID_VAL(stateid)); |
e4e83ea47 Revert "nfsd4: di... |
3049 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 |
} static inline int access_permit_read(unsigned long access_bmap) { return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) || test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) || test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap); } static inline int access_permit_write(unsigned long access_bmap) { return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) || test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap); } static |
dcef0413d nfsd4: move some ... |
3068 |
__be32 nfs4_check_openmode(struct nfs4_ol_stateid *stp, int flags) |
1da177e4c Linux-2.6.12-rc2 |
3069 |
{ |
b37ad28bc [PATCH] nfsd: nfs... |
3070 |
__be32 status = nfserr_openmode; |
1da177e4c Linux-2.6.12-rc2 |
3071 |
|
029219141 nfsd4: fix openmo... |
3072 3073 3074 |
/* For lock stateid's, we test the parent open, not the lock: */ if (stp->st_openstp) stp = stp->st_openstp; |
1da177e4c Linux-2.6.12-rc2 |
3075 3076 3077 3078 3079 3080 3081 3082 |
if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap))) goto out; if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap))) goto out; status = nfs_ok; out: return status; } |
b37ad28bc [PATCH] nfsd: nfs... |
3083 |
static inline __be32 |
1da177e4c Linux-2.6.12-rc2 |
3084 3085 |
check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) { |
203a8c8e6 nfsd4: separate d... |
3086 |
if (ONE_STATEID(stateid) && (flags & RD_STATE)) |
1da177e4c Linux-2.6.12-rc2 |
3087 |
return nfs_ok; |
af558e33b nfsd: common grac... |
3088 |
else if (locks_in_grace()) { |
25985edce Fix common misspe... |
3089 |
/* Answer in remaining cases depends on existence of |
1da177e4c Linux-2.6.12-rc2 |
3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 |
* conflicting state; so we must wait out the grace period. */ return nfserr_grace; } else if (flags & WR_STATE) return nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE); else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */ return nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_READ); } /* * Allow READ/WRITE during grace period on recovered state only for files * that are not able to provide mandatory locking. */ static inline int |
18f82731b nfsd4: rename io_... |
3105 |
grace_disallows_io(struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
3106 |
{ |
203a8c8e6 nfsd4: separate d... |
3107 |
return locks_in_grace() && mandatory_lock(inode); |
1da177e4c Linux-2.6.12-rc2 |
3108 |
} |
81b829655 nfsd4: simplify s... |
3109 3110 3111 3112 3113 |
/* Returns true iff a is later than b: */ static bool stateid_generation_after(stateid_t *a, stateid_t *b) { return (s32)a->si_generation - (s32)b->si_generation > 0; } |
28dde241c nfsd4: remove HAS... |
3114 |
static int check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session) |
0836f5872 nfsd4: simplify s... |
3115 |
{ |
6668958fa nfsd41: stateid h... |
3116 3117 3118 3119 |
/* * When sessions are used the stateid generation number is ignored * when it is zero. */ |
28dde241c nfsd4: remove HAS... |
3120 |
if (has_session && in->si_generation == 0) |
81b829655 nfsd4: simplify s... |
3121 3122 3123 3124 |
return nfs_ok; if (in->si_generation == ref->si_generation) return nfs_ok; |
6668958fa nfsd41: stateid h... |
3125 |
|
0836f5872 nfsd4: simplify s... |
3126 |
/* If the client sends us a stateid from the future, it's buggy: */ |
81b829655 nfsd4: simplify s... |
3127 |
if (stateid_generation_after(in, ref)) |
0836f5872 nfsd4: simplify s... |
3128 3129 |
return nfserr_bad_stateid; /* |
81b829655 nfsd4: simplify s... |
3130 3131 3132 3133 3134 3135 3136 3137 |
* However, we could see a stateid from the past, even from a * non-buggy client. For example, if the client sends a lock * while some IO is outstanding, the lock may bump si_generation * while the IO is still in flight. The client could avoid that * situation by waiting for responses on all the IO requests, * but better performance may result in retrying IO that * receives an old_stateid error if requests are rarely * reordered in flight: |
0836f5872 nfsd4: simplify s... |
3138 |
*/ |
81b829655 nfsd4: simplify s... |
3139 |
return nfserr_old_stateid; |
0836f5872 nfsd4: simplify s... |
3140 |
} |
38c2f4b12 nfsd4: look up st... |
3141 |
__be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) |
174568045 NFSD: Added TEST_... |
3142 |
{ |
97b7e3b6d nfsd4: fix test_s... |
3143 3144 3145 |
struct nfs4_stid *s; struct nfs4_ol_stateid *ols; __be32 status; |
174568045 NFSD: Added TEST_... |
3146 3147 |
if (STALE_STATEID(stateid)) |
97b7e3b6d nfsd4: fix test_s... |
3148 |
return nfserr_stale_stateid; |
174568045 NFSD: Added TEST_... |
3149 |
|
38c2f4b12 nfsd4: look up st... |
3150 |
s = find_stateid(cl, stateid); |
97b7e3b6d nfsd4: fix test_s... |
3151 3152 |
if (!s) return nfserr_stale_stateid; |
36279ac10 nfsd4: assume tes... |
3153 |
status = check_stateid_generation(stateid, &s->sc_stateid, 1); |
174568045 NFSD: Added TEST_... |
3154 |
if (status) |
97b7e3b6d nfsd4: fix test_s... |
3155 3156 3157 3158 3159 |
return status; if (!(s->sc_type & (NFS4_OPEN_STID | NFS4_LOCK_STID))) return nfs_ok; ols = openlockstateid(s); if (ols->st_stateowner->so_is_open_owner |
dad1c067e nfsd4: replace oo... |
3160 |
&& !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED)) |
97b7e3b6d nfsd4: fix test_s... |
3161 3162 |
return nfserr_bad_stateid; return nfs_ok; |
174568045 NFSD: Added TEST_... |
3163 |
} |
38c2f4b12 nfsd4: look up st... |
3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 |
static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) { struct nfs4_client *cl; if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) return nfserr_bad_stateid; if (STALE_STATEID(stateid)) return nfserr_stale_stateid; cl = find_confirmed_client(&stateid->si_opaque.so_clid); if (!cl) return nfserr_expired; *s = find_stateid_by_type(cl, stateid, typemask); if (!*s) return nfserr_bad_stateid; return nfs_ok; } |
1da177e4c Linux-2.6.12-rc2 |
3181 3182 3183 |
/* * Checks for stateid operations */ |
b37ad28bc [PATCH] nfsd: nfs... |
3184 |
__be32 |
dd453dfd7 nfsd: pass nfsd4_... |
3185 3186 |
nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, stateid_t *stateid, int flags, struct file **filpp) |
1da177e4c Linux-2.6.12-rc2 |
3187 |
{ |
69064a276 nfsd4: use deleg ... |
3188 |
struct nfs4_stid *s; |
dcef0413d nfsd4: move some ... |
3189 |
struct nfs4_ol_stateid *stp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
3190 |
struct nfs4_delegation *dp = NULL; |
dd453dfd7 nfsd: pass nfsd4_... |
3191 |
struct svc_fh *current_fh = &cstate->current_fh; |
1da177e4c Linux-2.6.12-rc2 |
3192 |
struct inode *ino = current_fh->fh_dentry->d_inode; |
b37ad28bc [PATCH] nfsd: nfs... |
3193 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
3194 |
|
1da177e4c Linux-2.6.12-rc2 |
3195 3196 |
if (filpp) *filpp = NULL; |
18f82731b nfsd4: rename io_... |
3197 |
if (grace_disallows_io(ino)) |
1da177e4c Linux-2.6.12-rc2 |
3198 3199 3200 3201 |
return nfserr_grace; if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) return check_special_stateids(current_fh, stateid, flags); |
38c2f4b12 nfsd4: look up st... |
3202 3203 3204 |
status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); if (status) return status; |
69064a276 nfsd4: use deleg ... |
3205 3206 3207 |
status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); if (status) goto out; |
f7a4d8720 nfsd4: hash close... |
3208 3209 |
switch (s->sc_type) { case NFS4_DELEG_STID: |
69064a276 nfsd4: use deleg ... |
3210 |
dp = delegstateid(s); |
dc9bf700e nfsd4: remove red... |
3211 3212 3213 |
status = nfs4_check_delegmode(dp, flags); if (status) goto out; |
43b0178ed nfsd: fix NULL de... |
3214 |
if (filpp) { |
acfdf5c38 nfsd4: acquire on... |
3215 |
*filpp = dp->dl_file->fi_deleg_file; |
43b0178ed nfsd: fix NULL de... |
3216 3217 |
BUG_ON(!*filpp); } |
f7a4d8720 nfsd4: hash close... |
3218 3219 3220 |
break; case NFS4_OPEN_STID: case NFS4_LOCK_STID: |
69064a276 nfsd4: use deleg ... |
3221 |
stp = openlockstateid(s); |
f7a4d8720 nfsd4: hash close... |
3222 3223 |
status = nfs4_check_fh(current_fh, stp); if (status) |
1da177e4c Linux-2.6.12-rc2 |
3224 |
goto out; |
fe0750e5c nfsd4: split stat... |
3225 |
if (stp->st_stateowner->so_is_open_owner |
dad1c067e nfsd4: replace oo... |
3226 |
&& !(openowner(stp->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED)) |
1da177e4c Linux-2.6.12-rc2 |
3227 |
goto out; |
a4455be08 nfsd4: trivial pr... |
3228 3229 |
status = nfs4_check_openmode(stp, flags); if (status) |
1da177e4c Linux-2.6.12-rc2 |
3230 |
goto out; |
f9d7562fd nfsd4: share file... |
3231 3232 3233 3234 3235 |
if (filpp) { if (flags & RD_STATE) *filpp = find_readable_file(stp->st_file); else *filpp = find_writeable_file(stp->st_file); |
f9d7562fd nfsd4: share file... |
3236 |
} |
f7a4d8720 nfsd4: hash close... |
3237 3238 3239 |
break; default: return nfserr_bad_stateid; |
1da177e4c Linux-2.6.12-rc2 |
3240 3241 3242 3243 3244 |
} status = nfs_ok; out: return status; } |
e1ca12dfb NFSD: added FREE_... |
3245 |
static __be32 |
dcef0413d nfsd4: move some ... |
3246 |
nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp) |
e1ca12dfb NFSD: added FREE_... |
3247 |
{ |
fe0750e5c nfsd4: split stat... |
3248 |
if (check_for_locks(stp->st_file, lockowner(stp->st_stateowner))) |
e1ca12dfb NFSD: added FREE_... |
3249 3250 3251 3252 3253 3254 |
return nfserr_locks_held; release_lock_stateid(stp); return nfs_ok; } /* |
174568045 NFSD: Added TEST_... |
3255 3256 3257 3258 3259 3260 |
* Test if the stateid is valid */ __be32 nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_test_stateid *test_stateid) { |
36279ac10 nfsd4: assume tes... |
3261 |
/* real work is done during encoding */ |
174568045 NFSD: Added TEST_... |
3262 3263 |
return nfs_ok; } |
e1ca12dfb NFSD: added FREE_... |
3264 3265 3266 3267 3268 |
__be32 nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_free_stateid *free_stateid) { stateid_t *stateid = &free_stateid->fr_stateid; |
2da1cec71 nfsd4: simplify f... |
3269 |
struct nfs4_stid *s; |
38c2f4b12 nfsd4: look up st... |
3270 |
struct nfs4_client *cl = cstate->session->se_client; |
2da1cec71 nfsd4: simplify f... |
3271 |
__be32 ret = nfserr_bad_stateid; |
e1ca12dfb NFSD: added FREE_... |
3272 3273 |
nfs4_lock_state(); |
38c2f4b12 nfsd4: look up st... |
3274 |
s = find_stateid(cl, stateid); |
2da1cec71 nfsd4: simplify f... |
3275 |
if (!s) |
81b829655 nfsd4: simplify s... |
3276 |
goto out; |
2da1cec71 nfsd4: simplify f... |
3277 3278 |
switch (s->sc_type) { case NFS4_DELEG_STID: |
e1ca12dfb NFSD: added FREE_... |
3279 3280 |
ret = nfserr_locks_held; goto out; |
2da1cec71 nfsd4: simplify f... |
3281 3282 3283 3284 3285 3286 3287 3288 3289 |
case NFS4_OPEN_STID: case NFS4_LOCK_STID: ret = check_stateid_generation(stateid, &s->sc_stateid, 1); if (ret) goto out; if (s->sc_type == NFS4_LOCK_STID) ret = nfsd4_free_lock_stateid(openlockstateid(s)); else ret = nfserr_locks_held; |
f7a4d8720 nfsd4: hash close... |
3290 3291 3292 |
break; default: ret = nfserr_bad_stateid; |
e1ca12dfb NFSD: added FREE_... |
3293 |
} |
e1ca12dfb NFSD: added FREE_... |
3294 3295 3296 3297 |
out: nfs4_unlock_state(); return ret; } |
4c4cd222e [PATCH] nfsd4: ch... |
3298 3299 3300 3301 3302 3303 |
static inline int setlkflg (int type) { return (type == NFS4_READW_LT || type == NFS4_READ_LT) ? RD_STATE : WR_STATE; } |
1da177e4c Linux-2.6.12-rc2 |
3304 |
|
dcef0413d nfsd4: move some ... |
3305 |
static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_t *stateid, u32 seqid, struct nfs4_ol_stateid *stp) |
c0a5d93ef nfsd4: split prep... |
3306 3307 3308 3309 |
{ struct svc_fh *current_fh = &cstate->current_fh; struct nfs4_stateowner *sop = stp->st_stateowner; __be32 status; |
c0a5d93ef nfsd4: split prep... |
3310 3311 3312 |
status = nfsd4_check_seqid(cstate, sop, seqid); if (status) return status; |
f7a4d8720 nfsd4: hash close... |
3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 |
if (stp->st_stid.sc_type == NFS4_CLOSED_STID) /* * "Closed" stateid's exist *only* to return * nfserr_replay_me from the previous step. */ return nfserr_bad_stateid; status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); if (status) return status; return nfs4_check_fh(current_fh, stp); |
c0a5d93ef nfsd4: split prep... |
3323 |
} |
1da177e4c Linux-2.6.12-rc2 |
3324 3325 3326 |
/* * Checks for sequence id mutating operations. */ |
b37ad28bc [PATCH] nfsd: nfs... |
3327 |
static __be32 |
dd453dfd7 nfsd: pass nfsd4_... |
3328 |
nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, |
2288d0e39 nfsd4: pass aroun... |
3329 |
stateid_t *stateid, char typemask, |
dcef0413d nfsd4: move some ... |
3330 |
struct nfs4_ol_stateid **stpp) |
1da177e4c Linux-2.6.12-rc2 |
3331 |
{ |
0836f5872 nfsd4: simplify s... |
3332 |
__be32 status; |
38c2f4b12 nfsd4: look up st... |
3333 |
struct nfs4_stid *s; |
1da177e4c Linux-2.6.12-rc2 |
3334 |
|
8c10cbdb4 nfsd: use STATEID... |
3335 3336 3337 |
dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT " ", __func__, seqid, STATEID_VAL(stateid)); |
3a4f98bbf [PATCH] nfsd4: cl... |
3338 |
|
1da177e4c Linux-2.6.12-rc2 |
3339 |
*stpp = NULL; |
38c2f4b12 nfsd4: look up st... |
3340 |
status = nfsd4_lookup_stateid(stateid, typemask, &s); |
c0a5d93ef nfsd4: split prep... |
3341 3342 |
if (status) return status; |
38c2f4b12 nfsd4: look up st... |
3343 |
*stpp = openlockstateid(s); |
c0a5d93ef nfsd4: split prep... |
3344 |
cstate->replay_owner = (*stpp)->st_stateowner; |
1da177e4c Linux-2.6.12-rc2 |
3345 |
|
c0a5d93ef nfsd4: split prep... |
3346 3347 |
return nfs4_seqid_op_checks(cstate, stateid, seqid, *stpp); } |
39325bd03 nfsd4: fix bad se... |
3348 |
|
dcef0413d nfsd4: move some ... |
3349 |
static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, stateid_t *stateid, struct nfs4_ol_stateid **stpp) |
c0a5d93ef nfsd4: split prep... |
3350 3351 3352 |
{ __be32 status; struct nfs4_openowner *oo; |
1da177e4c Linux-2.6.12-rc2 |
3353 |
|
c0a5d93ef nfsd4: split prep... |
3354 |
status = nfs4_preprocess_seqid_op(cstate, seqid, stateid, |
2288d0e39 nfsd4: pass aroun... |
3355 |
NFS4_OPEN_STID, stpp); |
7a8711c9a nfsd4: share comm... |
3356 3357 |
if (status) return status; |
c0a5d93ef nfsd4: split prep... |
3358 |
oo = openowner((*stpp)->st_stateowner); |
dad1c067e nfsd4: replace oo... |
3359 |
if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) |
3a4f98bbf [PATCH] nfsd4: cl... |
3360 |
return nfserr_bad_stateid; |
3a4f98bbf [PATCH] nfsd4: cl... |
3361 |
return nfs_ok; |
1da177e4c Linux-2.6.12-rc2 |
3362 |
} |
b37ad28bc [PATCH] nfsd: nfs... |
3363 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
3364 |
nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
a4f1706a9 [PATCH] knfsd: nf... |
3365 |
struct nfsd4_open_confirm *oc) |
1da177e4c Linux-2.6.12-rc2 |
3366 |
{ |
b37ad28bc [PATCH] nfsd: nfs... |
3367 |
__be32 status; |
fe0750e5c nfsd4: split stat... |
3368 |
struct nfs4_openowner *oo; |
dcef0413d nfsd4: move some ... |
3369 |
struct nfs4_ol_stateid *stp; |
1da177e4c Linux-2.6.12-rc2 |
3370 3371 3372 |
dprintk("NFSD: nfsd4_open_confirm on file %.*s ", |
ca3643171 [PATCH] knfsd: nf... |
3373 3374 |
(int)cstate->current_fh.fh_dentry->d_name.len, cstate->current_fh.fh_dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
3375 |
|
ca3643171 [PATCH] knfsd: nf... |
3376 |
status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0); |
a8cddc5df [PATCH] knfsd: nf... |
3377 3378 |
if (status) return status; |
1da177e4c Linux-2.6.12-rc2 |
3379 3380 |
nfs4_lock_state(); |
9072d5c66 nfsd4: cleanup se... |
3381 |
status = nfs4_preprocess_seqid_op(cstate, |
ca3643171 [PATCH] knfsd: nf... |
3382 |
oc->oc_seqid, &oc->oc_req_stateid, |
2288d0e39 nfsd4: pass aroun... |
3383 |
NFS4_OPEN_STID, &stp); |
9072d5c66 nfsd4: cleanup se... |
3384 |
if (status) |
68b66e827 nfsd4: move doubl... |
3385 |
goto out; |
fe0750e5c nfsd4: split stat... |
3386 |
oo = openowner(stp->st_stateowner); |
68b66e827 nfsd4: move doubl... |
3387 |
status = nfserr_bad_stateid; |
dad1c067e nfsd4: replace oo... |
3388 |
if (oo->oo_flags & NFS4_OO_CONFIRMED) |
68b66e827 nfsd4: move doubl... |
3389 |
goto out; |
dad1c067e nfsd4: replace oo... |
3390 |
oo->oo_flags |= NFS4_OO_CONFIRMED; |
dcef0413d nfsd4: move some ... |
3391 3392 |
update_stateid(&stp->st_stid.sc_stateid); memcpy(&oc->oc_resp_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
8c10cbdb4 nfsd: use STATEID... |
3393 3394 |
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT " ", |
dcef0413d nfsd4: move some ... |
3395 |
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); |
c7b9a4592 [PATCH] knfsd: nf... |
3396 |
|
fe0750e5c nfsd4: split stat... |
3397 |
nfsd4_create_clid_dir(oo->oo_owner.so_client); |
68b66e827 nfsd4: move doubl... |
3398 |
status = nfs_ok; |
1da177e4c Linux-2.6.12-rc2 |
3399 |
out: |
5ec094c10 nfsd4: extend sta... |
3400 3401 |
if (!cstate->replay_owner) nfs4_unlock_state(); |
1da177e4c Linux-2.6.12-rc2 |
3402 3403 |
return status; } |
6409a5a65 nfsd4: clean up d... |
3404 |
static inline void nfs4_stateid_downgrade_bit(struct nfs4_ol_stateid *stp, u32 access) |
1da177e4c Linux-2.6.12-rc2 |
3405 |
{ |
6409a5a65 nfsd4: clean up d... |
3406 3407 3408 3409 3410 |
if (!test_bit(access, &stp->st_access_bmap)) return; nfs4_file_put_access(stp->st_file, nfs4_access_to_omode(access)); __clear_bit(access, &stp->st_access_bmap); } |
f197c2719 nfsd4: fix file l... |
3411 |
|
6409a5a65 nfsd4: clean up d... |
3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 |
static inline void nfs4_stateid_downgrade(struct nfs4_ol_stateid *stp, u32 to_access) { switch (to_access) { case NFS4_SHARE_ACCESS_READ: nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_WRITE); nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_BOTH); break; case NFS4_SHARE_ACCESS_WRITE: nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_READ); nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_BOTH); break; case NFS4_SHARE_ACCESS_BOTH: break; default: BUG(); |
1da177e4c Linux-2.6.12-rc2 |
3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 |
} } static void reset_union_bmap_deny(unsigned long deny, unsigned long *bmap) { int i; for (i = 0; i < 4; i++) { if ((i & deny) != i) __clear_bit(i, bmap); } } |
b37ad28bc [PATCH] nfsd: nfs... |
3439 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
3440 3441 |
nfsd4_open_downgrade(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
a4f1706a9 [PATCH] knfsd: nf... |
3442 |
struct nfsd4_open_downgrade *od) |
1da177e4c Linux-2.6.12-rc2 |
3443 |
{ |
b37ad28bc [PATCH] nfsd: nfs... |
3444 |
__be32 status; |
dcef0413d nfsd4: move some ... |
3445 |
struct nfs4_ol_stateid *stp; |
1da177e4c Linux-2.6.12-rc2 |
3446 3447 3448 |
dprintk("NFSD: nfsd4_open_downgrade on file %.*s ", |
ca3643171 [PATCH] knfsd: nf... |
3449 3450 |
(int)cstate->current_fh.fh_dentry->d_name.len, cstate->current_fh.fh_dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
3451 |
|
c30e92df3 nfsd4: ignore WAN... |
3452 3453 |
/* We don't yet support WANT bits: */ od->od_share_access &= NFS4_SHARE_ACCESS_MASK; |
1da177e4c Linux-2.6.12-rc2 |
3454 3455 |
nfs4_lock_state(); |
c0a5d93ef nfsd4: split prep... |
3456 3457 |
status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid, &od->od_stateid, &stp); |
9072d5c66 nfsd4: cleanup se... |
3458 |
if (status) |
1da177e4c Linux-2.6.12-rc2 |
3459 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 |
status = nfserr_inval; if (!test_bit(od->od_share_access, &stp->st_access_bmap)) { dprintk("NFSD:access not a subset current bitmap: 0x%lx, input access=%08x ", stp->st_access_bmap, od->od_share_access); goto out; } if (!test_bit(od->od_share_deny, &stp->st_deny_bmap)) { dprintk("NFSD:deny not a subset current bitmap: 0x%lx, input deny=%08x ", stp->st_deny_bmap, od->od_share_deny); goto out; } |
6409a5a65 nfsd4: clean up d... |
3473 |
nfs4_stateid_downgrade(stp, od->od_share_access); |
1da177e4c Linux-2.6.12-rc2 |
3474 |
|
1da177e4c Linux-2.6.12-rc2 |
3475 |
reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap); |
dcef0413d nfsd4: move some ... |
3476 3477 |
update_stateid(&stp->st_stid.sc_stateid); memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
1da177e4c Linux-2.6.12-rc2 |
3478 3479 |
status = nfs_ok; out: |
5ec094c10 nfsd4: extend sta... |
3480 3481 |
if (!cstate->replay_owner) nfs4_unlock_state(); |
1da177e4c Linux-2.6.12-rc2 |
3482 3483 |
return status; } |
38c387b52 nfsd4: match clos... |
3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 |
void nfsd4_purge_closed_stateid(struct nfs4_stateowner *so) { struct nfs4_openowner *oo; struct nfs4_ol_stateid *s; if (!so->so_is_open_owner) return; oo = openowner(so); s = oo->oo_last_closed_stid; if (!s) return; if (!(oo->oo_flags & NFS4_OO_PURGE_CLOSE)) { /* Release the last_closed_stid on the next seqid bump: */ oo->oo_flags |= NFS4_OO_PURGE_CLOSE; return; } oo->oo_flags &= ~NFS4_OO_PURGE_CLOSE; |
f7a4d8720 nfsd4: hash close... |
3501 3502 3503 3504 3505 3506 3507 |
release_last_closed_stateid(oo); } static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) { unhash_open_stateid(s); s->st_stid.sc_type = NFS4_CLOSED_STID; |
38c387b52 nfsd4: match clos... |
3508 |
} |
1da177e4c Linux-2.6.12-rc2 |
3509 3510 3511 |
/* * nfs4_unlock_state() called after encode */ |
b37ad28bc [PATCH] nfsd: nfs... |
3512 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
3513 |
nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
a4f1706a9 [PATCH] knfsd: nf... |
3514 |
struct nfsd4_close *close) |
1da177e4c Linux-2.6.12-rc2 |
3515 |
{ |
b37ad28bc [PATCH] nfsd: nfs... |
3516 |
__be32 status; |
fe0750e5c nfsd4: split stat... |
3517 |
struct nfs4_openowner *oo; |
dcef0413d nfsd4: move some ... |
3518 |
struct nfs4_ol_stateid *stp; |
1da177e4c Linux-2.6.12-rc2 |
3519 3520 3521 |
dprintk("NFSD: nfsd4_close on file %.*s ", |
ca3643171 [PATCH] knfsd: nf... |
3522 3523 |
(int)cstate->current_fh.fh_dentry->d_name.len, cstate->current_fh.fh_dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
3524 3525 |
nfs4_lock_state(); |
f7a4d8720 nfsd4: hash close... |
3526 3527 3528 3529 |
status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid, &close->cl_stateid, NFS4_OPEN_STID|NFS4_CLOSED_STID, &stp); |
9072d5c66 nfsd4: cleanup se... |
3530 |
if (status) |
1da177e4c Linux-2.6.12-rc2 |
3531 |
goto out; |
fe0750e5c nfsd4: split stat... |
3532 |
oo = openowner(stp->st_stateowner); |
1da177e4c Linux-2.6.12-rc2 |
3533 |
status = nfs_ok; |
dcef0413d nfsd4: move some ... |
3534 3535 |
update_stateid(&stp->st_stid.sc_stateid); memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
1da177e4c Linux-2.6.12-rc2 |
3536 |
|
f7a4d8720 nfsd4: hash close... |
3537 |
nfsd4_close_open_stateid(stp); |
38c387b52 nfsd4: match clos... |
3538 |
oo->oo_last_closed_stid = stp; |
04ef59548 [PATCH] nfsd4: re... |
3539 3540 3541 3542 3543 |
/* place unused nfs4_stateowners on so_close_lru list to be * released by the laundromat service after the lease period * to enable us to handle CLOSE replay */ |
fe0750e5c nfsd4: split stat... |
3544 3545 |
if (list_empty(&oo->oo_owner.so_stateids)) move_to_close_lru(oo); |
1da177e4c Linux-2.6.12-rc2 |
3546 |
out: |
5ec094c10 nfsd4: extend sta... |
3547 3548 |
if (!cstate->replay_owner) nfs4_unlock_state(); |
1da177e4c Linux-2.6.12-rc2 |
3549 3550 |
return status; } |
b37ad28bc [PATCH] nfsd: nfs... |
3551 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
3552 3553 |
nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_delegreturn *dr) |
1da177e4c Linux-2.6.12-rc2 |
3554 |
{ |
203a8c8e6 nfsd4: separate d... |
3555 3556 |
struct nfs4_delegation *dp; stateid_t *stateid = &dr->dr_stateid; |
38c2f4b12 nfsd4: look up st... |
3557 |
struct nfs4_stid *s; |
203a8c8e6 nfsd4: separate d... |
3558 |
struct inode *inode; |
b37ad28bc [PATCH] nfsd: nfs... |
3559 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
3560 |
|
ca3643171 [PATCH] knfsd: nf... |
3561 |
if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) |
203a8c8e6 nfsd4: separate d... |
3562 3563 |
return status; inode = cstate->current_fh.fh_dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
3564 3565 |
nfs4_lock_state(); |
38c2f4b12 nfsd4: look up st... |
3566 3567 |
status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s); if (status) |
203a8c8e6 nfsd4: separate d... |
3568 |
goto out; |
38c2f4b12 nfsd4: look up st... |
3569 |
dp = delegstateid(s); |
d5477a8db nfsd4: add common... |
3570 |
status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate)); |
203a8c8e6 nfsd4: separate d... |
3571 3572 |
if (status) goto out; |
203a8c8e6 nfsd4: separate d... |
3573 3574 |
unhash_delegation(dp); |
1da177e4c Linux-2.6.12-rc2 |
3575 |
out: |
203a8c8e6 nfsd4: separate d... |
3576 |
nfs4_unlock_state(); |
1da177e4c Linux-2.6.12-rc2 |
3577 3578 |
return status; } |
1da177e4c Linux-2.6.12-rc2 |
3579 |
#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start)) |
1da177e4c Linux-2.6.12-rc2 |
3580 |
|
009673b43 nfsd4: add a sepa... |
3581 3582 3583 |
#define LOCKOWNER_INO_HASH_BITS 8 #define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS) #define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1) |
1da177e4c Linux-2.6.12-rc2 |
3584 |
|
87df4de80 nfsd: last_byte_o... |
3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 |
static inline u64 end_offset(u64 start, u64 len) { u64 end; end = start + len; return end >= start ? end: NFS4_MAX_UINT64; } /* last octet in a range */ static inline u64 last_byte_offset(u64 start, u64 len) { u64 end; BUG_ON(!len); end = start + len; return end > start ? end - 1: NFS4_MAX_UINT64; } |
009673b43 nfsd4: add a sepa... |
3604 |
static unsigned int lockowner_ino_hashval(struct inode *inode, u32 cl_id, struct xdr_netobj *ownername) |
1da177e4c Linux-2.6.12-rc2 |
3605 3606 3607 |
{ return (file_hashval(inode) + cl_id + opaque_hashval(ownername->data, ownername->len)) |
009673b43 nfsd4: add a sepa... |
3608 |
& LOCKOWNER_INO_HASH_MASK; |
1da177e4c Linux-2.6.12-rc2 |
3609 |
} |
009673b43 nfsd4: add a sepa... |
3610 |
static struct list_head lockowner_ino_hashtbl[LOCKOWNER_INO_HASH_SIZE]; |
1da177e4c Linux-2.6.12-rc2 |
3611 |
|
1da177e4c Linux-2.6.12-rc2 |
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 |
/* * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that * we can't properly handle lock requests that go beyond the (2^63 - 1)-th * byte, because of sign extension problems. Since NFSv4 calls for 64-bit * locking, this prevents us from being completely protocol-compliant. The * real solution to this problem is to start using unsigned file offsets in * the VFS, but this is a very deep change! */ static inline void nfs4_transform_lock_offset(struct file_lock *lock) { if (lock->fl_start < 0) lock->fl_start = OFFSET_MAX; if (lock->fl_end < 0) lock->fl_end = OFFSET_MAX; } |
d5b9026a6 [PATCH] knfsd: lo... |
3628 3629 |
/* Hack!: For now, we're defining this just so we can use a pointer to it * as a unique cookie to identify our (NFSv4's) posix locks. */ |
7b021967c const: make lock_... |
3630 |
static const struct lock_manager_operations nfsd_posix_mng_ops = { |
d5b9026a6 [PATCH] knfsd: lo... |
3631 |
}; |
1da177e4c Linux-2.6.12-rc2 |
3632 3633 3634 3635 |
static inline void nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) { |
fe0750e5c nfsd4: split stat... |
3636 |
struct nfs4_lockowner *lo; |
1da177e4c Linux-2.6.12-rc2 |
3637 |
|
d5b9026a6 [PATCH] knfsd: lo... |
3638 |
if (fl->fl_lmops == &nfsd_posix_mng_ops) { |
fe0750e5c nfsd4: split stat... |
3639 3640 3641 |
lo = (struct nfs4_lockowner *) fl->fl_owner; deny->ld_owner.data = kmemdup(lo->lo_owner.so_owner.data, lo->lo_owner.so_owner.len, GFP_KERNEL); |
7c13f344c nfsd4: drop most ... |
3642 3643 3644 |
if (!deny->ld_owner.data) /* We just don't care that much */ goto nevermind; |
fe0750e5c nfsd4: split stat... |
3645 3646 |
deny->ld_owner.len = lo->lo_owner.so_owner.len; deny->ld_clientid = lo->lo_owner.so_client->cl_clientid; |
d5b9026a6 [PATCH] knfsd: lo... |
3647 |
} else { |
7c13f344c nfsd4: drop most ... |
3648 3649 3650 |
nevermind: deny->ld_owner.len = 0; deny->ld_owner.data = NULL; |
d5b9026a6 [PATCH] knfsd: lo... |
3651 3652 |
deny->ld_clientid.cl_boot = 0; deny->ld_clientid.cl_id = 0; |
1da177e4c Linux-2.6.12-rc2 |
3653 3654 |
} deny->ld_start = fl->fl_start; |
87df4de80 nfsd: last_byte_o... |
3655 3656 |
deny->ld_length = NFS4_MAX_UINT64; if (fl->fl_end != NFS4_MAX_UINT64) |
1da177e4c Linux-2.6.12-rc2 |
3657 3658 3659 3660 3661 |
deny->ld_length = fl->fl_end - fl->fl_start + 1; deny->ld_type = NFS4_READ_LT; if (fl->fl_type != F_RDLCK) deny->ld_type = NFS4_WRITE_LT; } |
b93d87c19 nfsd4: fix lockow... |
3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 |
static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) { struct nfs4_ol_stateid *lst; if (!same_owner_str(&lo->lo_owner, owner, clid)) return false; lst = list_first_entry(&lo->lo_owner.so_stateids, struct nfs4_ol_stateid, st_perstateowner); return lst->st_file->fi_inode == inode; } |
fe0750e5c nfsd4: split stat... |
3672 3673 |
static struct nfs4_lockowner * find_lockowner_str(struct inode *inode, clientid_t *clid, |
1da177e4c Linux-2.6.12-rc2 |
3674 3675 |
struct xdr_netobj *owner) { |
009673b43 nfsd4: add a sepa... |
3676 |
unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner); |
b93d87c19 nfsd4: fix lockow... |
3677 |
struct nfs4_lockowner *lo; |
1da177e4c Linux-2.6.12-rc2 |
3678 |
|
009673b43 nfsd4: add a sepa... |
3679 |
list_for_each_entry(lo, &lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) { |
b93d87c19 nfsd4: fix lockow... |
3680 3681 |
if (same_lockowner_ino(lo, inode, clid, owner)) return lo; |
1da177e4c Linux-2.6.12-rc2 |
3682 3683 3684 |
} return NULL; } |
dcef0413d nfsd4: move some ... |
3685 |
static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp) |
ff194bd95 nfsd4: cleanup lo... |
3686 |
{ |
009673b43 nfsd4: add a sepa... |
3687 3688 3689 |
struct inode *inode = open_stp->st_file->fi_inode; unsigned int inohash = lockowner_ino_hashval(inode, clp->cl_clientid.cl_id, &lo->lo_owner.so_owner); |
16bfdaafa nfsd4: share open... |
3690 |
list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); |
009673b43 nfsd4: add a sepa... |
3691 |
list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]); |
fe0750e5c nfsd4: split stat... |
3692 |
list_add(&lo->lo_perstateid, &open_stp->st_lockowners); |
ff194bd95 nfsd4: cleanup lo... |
3693 |
} |
1da177e4c Linux-2.6.12-rc2 |
3694 3695 3696 |
/* * Alloc a lock owner structure. * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has |
25985edce Fix common misspe... |
3697 |
* occurred. |
1da177e4c Linux-2.6.12-rc2 |
3698 |
* |
16bfdaafa nfsd4: share open... |
3699 |
* strhashval = ownerstr_hashval |
1da177e4c Linux-2.6.12-rc2 |
3700 |
*/ |
fe0750e5c nfsd4: split stat... |
3701 |
static struct nfs4_lockowner * |
dcef0413d nfsd4: move some ... |
3702 |
alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp, struct nfsd4_lock *lock) { |
fe0750e5c nfsd4: split stat... |
3703 |
struct nfs4_lockowner *lo; |
1da177e4c Linux-2.6.12-rc2 |
3704 |
|
fe0750e5c nfsd4: split stat... |
3705 3706 |
lo = alloc_stateowner(lockowner_slab, &lock->lk_new_owner, clp); if (!lo) |
1da177e4c Linux-2.6.12-rc2 |
3707 |
return NULL; |
fe0750e5c nfsd4: split stat... |
3708 3709 |
INIT_LIST_HEAD(&lo->lo_owner.so_stateids); lo->lo_owner.so_is_open_owner = 0; |
b59e3c0e1 [PATCH] nfsd4: fi... |
3710 3711 |
/* It is the openowner seqid that will be incremented in encode in the * case of new lockowners; so increment the lock seqid manually: */ |
fe0750e5c nfsd4: split stat... |
3712 3713 3714 |
lo->lo_owner.so_seqid = lock->lk_new_lock_seqid + 1; hash_lockowner(lo, strhashval, clp, open_stp); return lo; |
1da177e4c Linux-2.6.12-rc2 |
3715 |
} |
dcef0413d nfsd4: move some ... |
3716 3717 |
static struct nfs4_ol_stateid * alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp) |
1da177e4c Linux-2.6.12-rc2 |
3718 |
{ |
dcef0413d nfsd4: move some ... |
3719 |
struct nfs4_ol_stateid *stp; |
d3b313a46 nfsd4: construct ... |
3720 |
struct nfs4_client *clp = lo->lo_owner.so_client; |
1da177e4c Linux-2.6.12-rc2 |
3721 |
|
996e09385 nfsd4: do idr pre... |
3722 |
stp = nfs4_alloc_stateid(clp); |
5ac049ac6 [PATCH] nfsd4: sl... |
3723 |
if (stp == NULL) |
6136d2b40 nfsd4: use idr fo... |
3724 |
return NULL; |
996e09385 nfsd4: do idr pre... |
3725 |
init_stid(&stp->st_stid, clp, NFS4_LOCK_STID); |
8beefa249 [PATCH] nfsd4: re... |
3726 |
list_add(&stp->st_perfile, &fp->fi_stateids); |
fe0750e5c nfsd4: split stat... |
3727 3728 |
list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); stp->st_stateowner = &lo->lo_owner; |
13cd21845 [PATCH] nfsd4: re... |
3729 |
get_nfs4_file(fp); |
1da177e4c Linux-2.6.12-rc2 |
3730 |
stp->st_file = fp; |
0997b1736 nfsd4: fix struct... |
3731 |
stp->st_access_bmap = 0; |
1da177e4c Linux-2.6.12-rc2 |
3732 |
stp->st_deny_bmap = open_stp->st_deny_bmap; |
4c4cd222e [PATCH] nfsd4: ch... |
3733 |
stp->st_openstp = open_stp; |
1da177e4c Linux-2.6.12-rc2 |
3734 3735 |
return stp; } |
fd39ca9a8 [PATCH] knfsd: nf... |
3736 |
static int |
1da177e4c Linux-2.6.12-rc2 |
3737 3738 |
check_lock_length(u64 offset, u64 length) { |
87df4de80 nfsd: last_byte_o... |
3739 |
return ((length == 0) || ((length != NFS4_MAX_UINT64) && |
1da177e4c Linux-2.6.12-rc2 |
3740 3741 |
LOFF_OVERFLOW(offset, length))); } |
dcef0413d nfsd4: move some ... |
3742 |
static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access) |
0997b1736 nfsd4: fix struct... |
3743 3744 3745 3746 3747 3748 3749 3750 3751 |
{ struct nfs4_file *fp = lock_stp->st_file; int oflag = nfs4_access_to_omode(access); if (test_bit(access, &lock_stp->st_access_bmap)) return; nfs4_file_get_access(fp, oflag); __set_bit(access, &lock_stp->st_access_bmap); } |
64a284d07 nfsd4: maintain o... |
3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 |
__be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct nfs4_ol_stateid *ost, struct nfsd4_lock *lock, struct nfs4_ol_stateid **lst, bool *new) { struct nfs4_file *fi = ost->st_file; struct nfs4_openowner *oo = openowner(ost->st_stateowner); struct nfs4_client *cl = oo->oo_owner.so_client; struct nfs4_lockowner *lo; unsigned int strhashval; lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner); if (lo) { if (!cstate->minorversion) return nfserr_bad_seqid; /* XXX: a lockowner always has exactly one stateid: */ *lst = list_first_entry(&lo->lo_owner.so_stateids, struct nfs4_ol_stateid, st_perstateowner); return nfs_ok; } |
16bfdaafa nfsd4: share open... |
3769 |
strhashval = ownerstr_hashval(cl->cl_clientid.cl_id, |
64a284d07 nfsd4: maintain o... |
3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 |
&lock->v.new.owner); lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); if (lo == NULL) return nfserr_jukebox; *lst = alloc_init_lock_stateid(lo, fi, ost); if (*lst == NULL) { release_lockowner(lo); return nfserr_jukebox; } *new = true; return nfs_ok; } |
1da177e4c Linux-2.6.12-rc2 |
3782 3783 3784 |
/* * LOCK operation */ |
b37ad28bc [PATCH] nfsd: nfs... |
3785 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
3786 |
nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
a4f1706a9 [PATCH] knfsd: nf... |
3787 |
struct nfsd4_lock *lock) |
1da177e4c Linux-2.6.12-rc2 |
3788 |
{ |
fe0750e5c nfsd4: split stat... |
3789 3790 |
struct nfs4_openowner *open_sop = NULL; struct nfs4_lockowner *lock_sop = NULL; |
dcef0413d nfsd4: move some ... |
3791 |
struct nfs4_ol_stateid *lock_stp; |
7d9478429 nfsd4: fix downgr... |
3792 3793 |
struct nfs4_file *fp; struct file *filp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
3794 |
struct file_lock file_lock; |
8dc7c3115 locks,lockd: fix ... |
3795 |
struct file_lock conflock; |
b37ad28bc [PATCH] nfsd: nfs... |
3796 |
__be32 status = 0; |
64a284d07 nfsd4: maintain o... |
3797 |
bool new_state = false; |
b34f27aa5 nfsd4: get lock c... |
3798 |
int lkflg; |
b8dd7b9ab [PATCH] nfsd: NFS... |
3799 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
3800 3801 3802 3803 3804 |
dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld ", (long long) lock->lk_offset, (long long) lock->lk_length); |
1da177e4c Linux-2.6.12-rc2 |
3805 3806 |
if (check_lock_length(lock->lk_offset, lock->lk_length)) return nfserr_inval; |
ca3643171 [PATCH] knfsd: nf... |
3807 |
if ((status = fh_verify(rqstp, &cstate->current_fh, |
8837abcab nfsd: rename MAY_... |
3808 |
S_IFREG, NFSD_MAY_LOCK))) { |
a6f6ef2f1 [PATCH] nfsd4: mi... |
3809 3810 3811 3812 |
dprintk("NFSD: nfsd4_lock: permission denied! "); return status; } |
1da177e4c Linux-2.6.12-rc2 |
3813 3814 3815 |
nfs4_lock_state(); if (lock->lk_is_new) { |
893f87701 [PATCH] nfsd4: co... |
3816 3817 3818 3819 3820 |
/* * Client indicates that this is a new lockowner. * Use open owner and open stateid to create lock owner and * lock stateid. */ |
dcef0413d nfsd4: move some ... |
3821 |
struct nfs4_ol_stateid *open_stp = NULL; |
684e56385 nfsd4: cleanup lo... |
3822 3823 3824 3825 3826 3827 |
if (nfsd4_has_session(cstate)) /* See rfc 5661 18.10.3: given clientid is ignored: */ memcpy(&lock->v.new.clientid, &cstate->session->se_client->cl_clientid, sizeof(clientid_t)); |
1da177e4c Linux-2.6.12-rc2 |
3828 |
status = nfserr_stale_clientid; |
684e56385 nfsd4: cleanup lo... |
3829 |
if (STALE_CLIENTID(&lock->lk_new_clientid)) |
1da177e4c Linux-2.6.12-rc2 |
3830 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
3831 |
|
1da177e4c Linux-2.6.12-rc2 |
3832 |
/* validate and update open stateid and open seqid */ |
c0a5d93ef nfsd4: split prep... |
3833 |
status = nfs4_preprocess_confirmed_seqid_op(cstate, |
1da177e4c Linux-2.6.12-rc2 |
3834 3835 |
lock->lk_new_open_seqid, &lock->lk_new_open_stateid, |
c0a5d93ef nfsd4: split prep... |
3836 |
&open_stp); |
375151773 [PATCH] nfsd4: st... |
3837 |
if (status) |
1da177e4c Linux-2.6.12-rc2 |
3838 |
goto out; |
fe0750e5c nfsd4: split stat... |
3839 |
open_sop = openowner(open_stp->st_stateowner); |
b34f27aa5 nfsd4: get lock c... |
3840 |
status = nfserr_bad_stateid; |
684e56385 nfsd4: cleanup lo... |
3841 |
if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, |
b34f27aa5 nfsd4: get lock c... |
3842 3843 |
&lock->v.new.clientid)) goto out; |
64a284d07 nfsd4: maintain o... |
3844 3845 3846 |
status = lookup_or_create_lock_state(cstate, open_stp, lock, &lock_stp, &new_state); if (status) |
1da177e4c Linux-2.6.12-rc2 |
3847 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
3848 3849 |
} else { /* lock (lock owner + lock stateid) already exists */ |
dd453dfd7 nfsd: pass nfsd4_... |
3850 |
status = nfs4_preprocess_seqid_op(cstate, |
fe0750e5c nfsd4: split stat... |
3851 3852 |
lock->lk_old_lock_seqid, &lock->lk_old_lock_stateid, |
2288d0e39 nfsd4: pass aroun... |
3853 |
NFS4_LOCK_STID, &lock_stp); |
1da177e4c Linux-2.6.12-rc2 |
3854 3855 3856 |
if (status) goto out; } |
64a284d07 nfsd4: maintain o... |
3857 3858 |
lock_sop = lockowner(lock_stp->st_stateowner); fp = lock_stp->st_file; |
1da177e4c Linux-2.6.12-rc2 |
3859 |
|
b34f27aa5 nfsd4: get lock c... |
3860 3861 3862 3863 |
lkflg = setlkflg(lock->lk_type); status = nfs4_check_openmode(lock_stp, lkflg); if (status) goto out; |
0dd395dc7 [PATCH] nfsd4: ER... |
3864 |
status = nfserr_grace; |
af558e33b nfsd: common grac... |
3865 |
if (locks_in_grace() && !lock->lk_reclaim) |
0dd395dc7 [PATCH] nfsd4: ER... |
3866 3867 |
goto out; status = nfserr_no_grace; |
af558e33b nfsd: common grac... |
3868 |
if (!locks_in_grace() && lock->lk_reclaim) |
0dd395dc7 [PATCH] nfsd4: ER... |
3869 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
3870 3871 3872 3873 |
locks_init_lock(&file_lock); switch (lock->lk_type) { case NFS4_READ_LT: case NFS4_READW_LT: |
0997b1736 nfsd4: fix struct... |
3874 3875 3876 |
filp = find_readable_file(lock_stp->st_file); if (filp) get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); |
1da177e4c Linux-2.6.12-rc2 |
3877 |
file_lock.fl_type = F_RDLCK; |
529d7b2a7 nfsd4: minor nfs4... |
3878 |
break; |
1da177e4c Linux-2.6.12-rc2 |
3879 3880 |
case NFS4_WRITE_LT: case NFS4_WRITEW_LT: |
0997b1736 nfsd4: fix struct... |
3881 3882 3883 |
filp = find_writeable_file(lock_stp->st_file); if (filp) get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); |
1da177e4c Linux-2.6.12-rc2 |
3884 |
file_lock.fl_type = F_WRLCK; |
529d7b2a7 nfsd4: minor nfs4... |
3885 |
break; |
1da177e4c Linux-2.6.12-rc2 |
3886 3887 3888 3889 |
default: status = nfserr_inval; goto out; } |
f9d7562fd nfsd4: share file... |
3890 3891 3892 3893 |
if (!filp) { status = nfserr_openmode; goto out; } |
b59e3c0e1 [PATCH] nfsd4: fi... |
3894 |
file_lock.fl_owner = (fl_owner_t)lock_sop; |
1da177e4c Linux-2.6.12-rc2 |
3895 3896 3897 |
file_lock.fl_pid = current->tgid; file_lock.fl_file = filp; file_lock.fl_flags = FL_POSIX; |
d5b9026a6 [PATCH] knfsd: lo... |
3898 |
file_lock.fl_lmops = &nfsd_posix_mng_ops; |
1da177e4c Linux-2.6.12-rc2 |
3899 3900 |
file_lock.fl_start = lock->lk_offset; |
87df4de80 nfsd: last_byte_o... |
3901 |
file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); |
1da177e4c Linux-2.6.12-rc2 |
3902 3903 3904 3905 3906 3907 |
nfs4_transform_lock_offset(&file_lock); /* * Try to lock the file in the VFS. * Note: locks.c uses the BKL to protect the inode's lock list. */ |
529d7b2a7 nfsd4: minor nfs4... |
3908 |
err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); |
b8dd7b9ab [PATCH] nfsd: NFS... |
3909 |
switch (-err) { |
1da177e4c Linux-2.6.12-rc2 |
3910 |
case 0: /* success! */ |
dcef0413d nfsd4: move some ... |
3911 3912 |
update_stateid(&lock_stp->st_stid.sc_stateid); memcpy(&lock->lk_resp_stateid, &lock_stp->st_stid.sc_stateid, |
1da177e4c Linux-2.6.12-rc2 |
3913 |
sizeof(stateid_t)); |
b8dd7b9ab [PATCH] nfsd: NFS... |
3914 |
status = 0; |
eb76b3fda [PATCH] NFSD4: re... |
3915 3916 3917 3918 3919 3920 3921 |
break; case (EAGAIN): /* conflock holds conflicting lock */ status = nfserr_denied; dprintk("NFSD: nfsd4_lock: conflicting lock found! "); nfs4_set_lock_denied(&conflock, &lock->lk_denied); break; |
1da177e4c Linux-2.6.12-rc2 |
3922 3923 |
case (EDEADLK): status = nfserr_deadlock; |
eb76b3fda [PATCH] NFSD4: re... |
3924 |
break; |
3e7724639 nfsd4: stop using... |
3925 |
default: |
fd85b8170 nfsd4: Convert NF... |
3926 3927 |
dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d ",err); |
3e7724639 nfsd4: stop using... |
3928 |
status = nfserrno(err); |
eb76b3fda [PATCH] NFSD4: re... |
3929 |
break; |
1da177e4c Linux-2.6.12-rc2 |
3930 |
} |
1da177e4c Linux-2.6.12-rc2 |
3931 |
out: |
64a284d07 nfsd4: maintain o... |
3932 |
if (status && new_state) |
f044ff830 nfsd4: split open... |
3933 |
release_lockowner(lock_sop); |
5ec094c10 nfsd4: extend sta... |
3934 3935 |
if (!cstate->replay_owner) nfs4_unlock_state(); |
1da177e4c Linux-2.6.12-rc2 |
3936 3937 3938 3939 |
return status; } /* |
55ef1274d nfsd: Ensure nfsv... |
3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 |
* The NFSv4 spec allows a client to do a LOCKT without holding an OPEN, * so we do a temporary open here just to get an open file to pass to * vfs_test_lock. (Arguably perhaps test_lock should be done with an * inode operation.) */ static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) { struct file *file; int err; err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); if (err) return err; err = vfs_test_lock(file, lock); nfsd_close(file); return err; } /* |
1da177e4c Linux-2.6.12-rc2 |
3959 3960 |
* LOCKT operation */ |
b37ad28bc [PATCH] nfsd: nfs... |
3961 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
3962 3963 |
nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_lockt *lockt) |
1da177e4c Linux-2.6.12-rc2 |
3964 3965 |
{ struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
3966 |
struct file_lock file_lock; |
fe0750e5c nfsd4: split stat... |
3967 |
struct nfs4_lockowner *lo; |
fd85b8170 nfsd4: Convert NF... |
3968 |
int error; |
b37ad28bc [PATCH] nfsd: nfs... |
3969 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
3970 |
|
af558e33b nfsd: common grac... |
3971 |
if (locks_in_grace()) |
1da177e4c Linux-2.6.12-rc2 |
3972 3973 3974 3975 |
return nfserr_grace; if (check_lock_length(lockt->lt_offset, lockt->lt_length)) return nfserr_inval; |
1da177e4c Linux-2.6.12-rc2 |
3976 3977 3978 |
nfs4_lock_state(); status = nfserr_stale_clientid; |
60adfc50d nfsd41: clientid ... |
3979 |
if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid)) |
1da177e4c Linux-2.6.12-rc2 |
3980 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
3981 |
|
75c096f75 nfsd4: it's OK to... |
3982 |
if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) |
1da177e4c Linux-2.6.12-rc2 |
3983 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
3984 |
|
ca3643171 [PATCH] knfsd: nf... |
3985 |
inode = cstate->current_fh.fh_dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 |
locks_init_lock(&file_lock); switch (lockt->lt_type) { case NFS4_READ_LT: case NFS4_READW_LT: file_lock.fl_type = F_RDLCK; break; case NFS4_WRITE_LT: case NFS4_WRITEW_LT: file_lock.fl_type = F_WRLCK; break; default: |
2fdada03b knfsd: demote som... |
3997 3998 |
dprintk("NFSD: nfs4_lockt: bad lock type! "); |
1da177e4c Linux-2.6.12-rc2 |
3999 4000 4001 |
status = nfserr_inval; goto out; } |
fe0750e5c nfsd4: split stat... |
4002 4003 4004 |
lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); if (lo) file_lock.fl_owner = (fl_owner_t)lo; |
1da177e4c Linux-2.6.12-rc2 |
4005 4006 4007 4008 |
file_lock.fl_pid = current->tgid; file_lock.fl_flags = FL_POSIX; file_lock.fl_start = lockt->lt_offset; |
87df4de80 nfsd: last_byte_o... |
4009 |
file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); |
1da177e4c Linux-2.6.12-rc2 |
4010 4011 |
nfs4_transform_lock_offset(&file_lock); |
1da177e4c Linux-2.6.12-rc2 |
4012 |
status = nfs_ok; |
55ef1274d nfsd: Ensure nfsv... |
4013 |
error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); |
fd85b8170 nfsd4: Convert NF... |
4014 4015 4016 4017 |
if (error) { status = nfserrno(error); goto out; } |
9d6a8c5c2 locks: give posix... |
4018 |
if (file_lock.fl_type != F_UNLCK) { |
1da177e4c Linux-2.6.12-rc2 |
4019 |
status = nfserr_denied; |
9d6a8c5c2 locks: give posix... |
4020 |
nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); |
1da177e4c Linux-2.6.12-rc2 |
4021 4022 4023 4024 4025 |
} out: nfs4_unlock_state(); return status; } |
b37ad28bc [PATCH] nfsd: nfs... |
4026 |
__be32 |
ca3643171 [PATCH] knfsd: nf... |
4027 |
nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
a4f1706a9 [PATCH] knfsd: nf... |
4028 |
struct nfsd4_locku *locku) |
1da177e4c Linux-2.6.12-rc2 |
4029 |
{ |
dcef0413d nfsd4: move some ... |
4030 |
struct nfs4_ol_stateid *stp; |
1da177e4c Linux-2.6.12-rc2 |
4031 4032 |
struct file *filp = NULL; struct file_lock file_lock; |
b37ad28bc [PATCH] nfsd: nfs... |
4033 |
__be32 status; |
b8dd7b9ab [PATCH] nfsd: NFS... |
4034 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 |
dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld ", (long long) locku->lu_offset, (long long) locku->lu_length); if (check_lock_length(locku->lu_offset, locku->lu_length)) return nfserr_inval; nfs4_lock_state(); |
9072d5c66 nfsd4: cleanup se... |
4046 |
status = nfs4_preprocess_seqid_op(cstate, locku->lu_seqid, |
2288d0e39 nfsd4: pass aroun... |
4047 |
&locku->lu_stateid, NFS4_LOCK_STID, &stp); |
9072d5c66 nfsd4: cleanup se... |
4048 |
if (status) |
1da177e4c Linux-2.6.12-rc2 |
4049 |
goto out; |
f9d7562fd nfsd4: share file... |
4050 4051 4052 4053 4054 |
filp = find_any_file(stp->st_file); if (!filp) { status = nfserr_lock_range; goto out; } |
1da177e4c Linux-2.6.12-rc2 |
4055 4056 4057 |
BUG_ON(!filp); locks_init_lock(&file_lock); file_lock.fl_type = F_UNLCK; |
fe0750e5c nfsd4: split stat... |
4058 |
file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); |
1da177e4c Linux-2.6.12-rc2 |
4059 4060 4061 |
file_lock.fl_pid = current->tgid; file_lock.fl_file = filp; file_lock.fl_flags = FL_POSIX; |
d5b9026a6 [PATCH] knfsd: lo... |
4062 |
file_lock.fl_lmops = &nfsd_posix_mng_ops; |
1da177e4c Linux-2.6.12-rc2 |
4063 |
file_lock.fl_start = locku->lu_offset; |
87df4de80 nfsd: last_byte_o... |
4064 |
file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); |
1da177e4c Linux-2.6.12-rc2 |
4065 4066 4067 4068 4069 |
nfs4_transform_lock_offset(&file_lock); /* * Try to unlock the file in the VFS. */ |
fd85b8170 nfsd4: Convert NF... |
4070 |
err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); |
b8dd7b9ab [PATCH] nfsd: NFS... |
4071 |
if (err) { |
fd85b8170 nfsd4: Convert NF... |
4072 4073 |
dprintk("NFSD: nfs4_locku: vfs_lock_file failed! "); |
1da177e4c Linux-2.6.12-rc2 |
4074 4075 4076 4077 4078 |
goto out_nfserr; } /* * OK, unlock succeeded; the only thing left to do is update the stateid. */ |
dcef0413d nfsd4: move some ... |
4079 4080 |
update_stateid(&stp->st_stid.sc_stateid); memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
1da177e4c Linux-2.6.12-rc2 |
4081 4082 |
out: |
71c3bcd71 nfsd4: fix state ... |
4083 4084 |
if (!cstate->replay_owner) nfs4_unlock_state(); |
1da177e4c Linux-2.6.12-rc2 |
4085 4086 4087 |
return status; out_nfserr: |
b8dd7b9ab [PATCH] nfsd: NFS... |
4088 |
status = nfserrno(err); |
1da177e4c Linux-2.6.12-rc2 |
4089 4090 4091 4092 4093 4094 4095 4096 4097 |
goto out; } /* * returns * 1: locks held by lockowner * 0: no locks held by lockowner */ static int |
fe0750e5c nfsd4: split stat... |
4098 |
check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner) |
1da177e4c Linux-2.6.12-rc2 |
4099 4100 |
{ struct file_lock **flpp; |
f9d7562fd nfsd4: share file... |
4101 |
struct inode *inode = filp->fi_inode; |
1da177e4c Linux-2.6.12-rc2 |
4102 |
int status = 0; |
b89f43213 fs/locks.c: prepa... |
4103 |
lock_flocks(); |
1da177e4c Linux-2.6.12-rc2 |
4104 |
for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { |
796dadfd0 [PATCH] nfsd4: fi... |
4105 |
if ((*flpp)->fl_owner == (fl_owner_t)lowner) { |
1da177e4c Linux-2.6.12-rc2 |
4106 4107 |
status = 1; goto out; |
796dadfd0 [PATCH] nfsd4: fi... |
4108 |
} |
1da177e4c Linux-2.6.12-rc2 |
4109 4110 |
} out: |
b89f43213 fs/locks.c: prepa... |
4111 |
unlock_flocks(); |
1da177e4c Linux-2.6.12-rc2 |
4112 4113 |
return status; } |
b37ad28bc [PATCH] nfsd: nfs... |
4114 |
__be32 |
b591480bb [PATCH] knfsd: nf... |
4115 4116 4117 |
nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_release_lockowner *rlockowner) |
1da177e4c Linux-2.6.12-rc2 |
4118 4119 |
{ clientid_t *clid = &rlockowner->rl_clientid; |
3e9e3dbe0 [PATCH] knfsd: nf... |
4120 |
struct nfs4_stateowner *sop; |
fe0750e5c nfsd4: split stat... |
4121 |
struct nfs4_lockowner *lo; |
dcef0413d nfsd4: move some ... |
4122 |
struct nfs4_ol_stateid *stp; |
1da177e4c Linux-2.6.12-rc2 |
4123 |
struct xdr_netobj *owner = &rlockowner->rl_owner; |
3e9e3dbe0 [PATCH] knfsd: nf... |
4124 |
struct list_head matches; |
16bfdaafa nfsd4: share open... |
4125 |
unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); |
b37ad28bc [PATCH] nfsd: nfs... |
4126 |
__be32 status; |
1da177e4c Linux-2.6.12-rc2 |
4127 4128 4129 4130 4131 4132 4133 4134 |
dprintk("nfsd4_release_lockowner clientid: (%08x/%08x): ", clid->cl_boot, clid->cl_id); /* XXX check for lease expiration */ status = nfserr_stale_clientid; |
849823c52 [PATCH] nfsd4: pr... |
4135 |
if (STALE_CLIENTID(clid)) |
1da177e4c Linux-2.6.12-rc2 |
4136 |
return status; |
1da177e4c Linux-2.6.12-rc2 |
4137 4138 |
nfs4_lock_state(); |
3e9e3dbe0 [PATCH] knfsd: nf... |
4139 |
status = nfserr_locks_held; |
3e9e3dbe0 [PATCH] knfsd: nf... |
4140 |
INIT_LIST_HEAD(&matches); |
06f1f864d nfsd4: hash locko... |
4141 |
|
16bfdaafa nfsd4: share open... |
4142 4143 4144 |
list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) { if (sop->so_is_open_owner) continue; |
06f1f864d nfsd4: hash locko... |
4145 4146 4147 4148 4149 4150 4151 4152 |
if (!same_owner_str(sop, owner, clid)) continue; list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { lo = lockowner(sop); if (check_for_locks(stp->st_file, lo)) goto out; list_add(&lo->lo_list, &matches); |
1da177e4c Linux-2.6.12-rc2 |
4153 |
} |
3e9e3dbe0 [PATCH] knfsd: nf... |
4154 4155 4156 4157 4158 |
} /* Clients probably won't expect us to return with some (but not all) * of the lockowner state released; so don't release any until all * have been checked. */ status = nfs_ok; |
0fa822e45 [PATCH] nfsd4: fi... |
4159 |
while (!list_empty(&matches)) { |
fe0750e5c nfsd4: split stat... |
4160 4161 |
lo = list_entry(matches.next, struct nfs4_lockowner, lo_list); |
0fa822e45 [PATCH] nfsd4: fi... |
4162 4163 |
/* unhash_stateowner deletes so_perclient only * for openowners. */ |
fe0750e5c nfsd4: split stat... |
4164 4165 |
list_del(&lo->lo_list); release_lockowner(lo); |
1da177e4c Linux-2.6.12-rc2 |
4166 4167 4168 4169 4170 4171 4172 |
} out: nfs4_unlock_state(); return status; } static inline struct nfs4_client_reclaim * |
a55370a3c [PATCH] knfsd: nf... |
4173 |
alloc_reclaim(void) |
1da177e4c Linux-2.6.12-rc2 |
4174 |
{ |
a55370a3c [PATCH] knfsd: nf... |
4175 |
return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
4176 |
} |
c7b9a4592 [PATCH] knfsd: nf... |
4177 |
int |
a1bcecd29 nfsd41: match cli... |
4178 |
nfs4_has_reclaimed_state(const char *name, bool use_exchange_id) |
c7b9a4592 [PATCH] knfsd: nf... |
4179 4180 4181 |
{ unsigned int strhashval = clientstr_hashval(name); struct nfs4_client *clp; |
e203d506b nfsd4: fix mixed ... |
4182 |
clp = find_confirmed_client_by_str(name, strhashval); |
c7b9a4592 [PATCH] knfsd: nf... |
4183 4184 |
return clp ? 1 : 0; } |
1da177e4c Linux-2.6.12-rc2 |
4185 4186 4187 |
/* * failure => all reset bets are off, nfserr_no_grace... */ |
190e4fbf9 [PATCH] knfsd: nf... |
4188 4189 |
int nfs4_client_to_reclaim(const char *name) |
1da177e4c Linux-2.6.12-rc2 |
4190 4191 4192 |
{ unsigned int strhashval; struct nfs4_client_reclaim *crp = NULL; |
a55370a3c [PATCH] knfsd: nf... |
4193 4194 4195 |
dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s ", HEXDIR_LEN, name); crp = alloc_reclaim(); |
1da177e4c Linux-2.6.12-rc2 |
4196 4197 |
if (!crp) return 0; |
a55370a3c [PATCH] knfsd: nf... |
4198 |
strhashval = clientstr_hashval(name); |
1da177e4c Linux-2.6.12-rc2 |
4199 4200 |
INIT_LIST_HEAD(&crp->cr_strhash); list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]); |
a55370a3c [PATCH] knfsd: nf... |
4201 |
memcpy(crp->cr_recdir, name, HEXDIR_LEN); |
1da177e4c Linux-2.6.12-rc2 |
4202 4203 4204 4205 4206 4207 4208 4209 4210 |
reclaim_str_hashtbl_size++; return 1; } static void nfs4_release_reclaim(void) { struct nfs4_client_reclaim *crp = NULL; int i; |
1da177e4c Linux-2.6.12-rc2 |
4211 4212 4213 4214 4215 |
for (i = 0; i < CLIENT_HASH_SIZE; i++) { while (!list_empty(&reclaim_str_hashtbl[i])) { crp = list_entry(reclaim_str_hashtbl[i].next, struct nfs4_client_reclaim, cr_strhash); list_del(&crp->cr_strhash); |
1da177e4c Linux-2.6.12-rc2 |
4216 4217 4218 4219 4220 4221 4222 4223 4224 |
kfree(crp); reclaim_str_hashtbl_size--; } } BUG_ON(reclaim_str_hashtbl_size); } /* * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ |
fd39ca9a8 [PATCH] knfsd: nf... |
4225 |
static struct nfs4_client_reclaim * |
1da177e4c Linux-2.6.12-rc2 |
4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 |
nfs4_find_reclaim_client(clientid_t *clid) { unsigned int strhashval; struct nfs4_client *clp; struct nfs4_client_reclaim *crp = NULL; /* find clientid in conf_id_hashtbl */ clp = find_confirmed_client(clid); if (clp == NULL) return NULL; |
a55370a3c [PATCH] knfsd: nf... |
4237 4238 4239 4240 |
dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s ", clp->cl_name.len, clp->cl_name.data, clp->cl_recdir); |
1da177e4c Linux-2.6.12-rc2 |
4241 4242 |
/* find clp->cl_name in reclaim_str_hashtbl */ |
a55370a3c [PATCH] knfsd: nf... |
4243 |
strhashval = clientstr_hashval(clp->cl_recdir); |
1da177e4c Linux-2.6.12-rc2 |
4244 |
list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { |
a55370a3c [PATCH] knfsd: nf... |
4245 |
if (same_name(crp->cr_recdir, clp->cl_recdir)) { |
1da177e4c Linux-2.6.12-rc2 |
4246 4247 4248 4249 4250 4251 4252 4253 4254 |
return crp; } } return NULL; } /* * Called from OPEN. Look for clientid in reclaim list. */ |
b37ad28bc [PATCH] nfsd: nfs... |
4255 |
__be32 |
1da177e4c Linux-2.6.12-rc2 |
4256 4257 |
nfs4_check_open_reclaim(clientid_t *clid) { |
dfc835657 [PATCH] knfsd: nf... |
4258 |
return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; |
1da177e4c Linux-2.6.12-rc2 |
4259 |
} |
65178db42 NFSD: Added fault... |
4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 |
#ifdef CONFIG_NFSD_FAULT_INJECTION void nfsd_forget_clients(u64 num) { struct nfs4_client *clp, *next; int count = 0; nfs4_lock_state(); list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { nfsd4_remove_clid_dir(clp); expire_client(clp); if (++count == num) break; } nfs4_unlock_state(); printk(KERN_INFO "NFSD: Forgot %d clients", count); } static void release_lockowner_sop(struct nfs4_stateowner *sop) { release_lockowner(lockowner(sop)); } static void release_openowner_sop(struct nfs4_stateowner *sop) { release_openowner(openowner(sop)); } |
353de31b8 nfsd4: fix CONFIG... |
4288 |
static int nfsd_release_n_owners(u64 num, bool is_open_owner, |
65178db42 NFSD: Added fault... |
4289 4290 4291 4292 |
void (*release_sop)(struct nfs4_stateowner *)) { int i, count = 0; struct nfs4_stateowner *sop, *next; |
16bfdaafa nfsd4: share open... |
4293 4294 4295 4296 |
for (i = 0; i < OWNER_HASH_SIZE; i++) { list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) { if (sop->so_is_open_owner != is_open_owner) continue; |
65178db42 NFSD: Added fault... |
4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 |
release_sop(sop); if (++count == num) return count; } } return count; } void nfsd_forget_locks(u64 num) { int count; nfs4_lock_state(); |
16bfdaafa nfsd4: share open... |
4310 |
count = nfsd_release_n_owners(num, false, release_lockowner_sop); |
65178db42 NFSD: Added fault... |
4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 |
nfs4_unlock_state(); printk(KERN_INFO "NFSD: Forgot %d locks", count); } void nfsd_forget_openowners(u64 num) { int count; nfs4_lock_state(); |
16bfdaafa nfsd4: share open... |
4321 |
count = nfsd_release_n_owners(num, true, release_openowner_sop); |
65178db42 NFSD: Added fault... |
4322 4323 4324 4325 4326 4327 4328 4329 |
nfs4_unlock_state(); printk(KERN_INFO "NFSD: Forgot %d open owners", count); } int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegation *)) { int i, count = 0; |
2d3475c0a NFSD: forget_dele... |
4330 4331 |
struct nfs4_file *fp, *fnext; struct nfs4_delegation *dp, *dnext; |
65178db42 NFSD: Added fault... |
4332 4333 |
for (i = 0; i < FILE_HASH_SIZE; i++) { |
2d3475c0a NFSD: forget_dele... |
4334 4335 |
list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) { list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) { |
65178db42 NFSD: Added fault... |
4336 4337 4338 4339 4340 4341 |
deleg_func(dp); if (++count == num) return count; } } } |
2d3475c0a NFSD: forget_dele... |
4342 |
|
65178db42 NFSD: Added fault... |
4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 |
return count; } void nfsd_forget_delegations(u64 num) { unsigned int count; nfs4_lock_state(); count = nfsd_process_n_delegations(num, unhash_delegation); nfs4_unlock_state(); printk(KERN_INFO "NFSD: Forgot %d delegations", count); } void nfsd_recall_delegations(u64 num) { unsigned int count; nfs4_lock_state(); spin_lock(&recall_lock); count = nfsd_process_n_delegations(num, nfsd_break_one_deleg); spin_unlock(&recall_lock); nfs4_unlock_state(); printk(KERN_INFO "NFSD: Recalled %d delegations", count); } #endif /* CONFIG_NFSD_FAULT_INJECTION */ |
ac4d8ff2a [PATCH] knfsd: nf... |
4371 |
/* initialization to perform at module load time: */ |
1da177e4c Linux-2.6.12-rc2 |
4372 |
|
720833960 NFSD: Call nfsd4_... |
4373 |
void |
ac4d8ff2a [PATCH] knfsd: nf... |
4374 |
nfs4_state_init(void) |
1da177e4c Linux-2.6.12-rc2 |
4375 |
{ |
720833960 NFSD: Call nfsd4_... |
4376 |
int i; |
1da177e4c Linux-2.6.12-rc2 |
4377 |
|
1da177e4c Linux-2.6.12-rc2 |
4378 4379 4380 4381 4382 |
for (i = 0; i < CLIENT_HASH_SIZE; i++) { INIT_LIST_HEAD(&conf_id_hashtbl[i]); INIT_LIST_HEAD(&conf_str_hashtbl[i]); INIT_LIST_HEAD(&unconf_str_hashtbl[i]); INIT_LIST_HEAD(&unconf_id_hashtbl[i]); |
02cb2858d nfsd: nfs4_stat_i... |
4383 |
INIT_LIST_HEAD(&reclaim_str_hashtbl[i]); |
1da177e4c Linux-2.6.12-rc2 |
4384 |
} |
5282fd724 nfsd41: sessionid... |
4385 4386 |
for (i = 0; i < SESSION_HASH_SIZE; i++) INIT_LIST_HEAD(&sessionid_hashtbl[i]); |
1da177e4c Linux-2.6.12-rc2 |
4387 4388 4389 |
for (i = 0; i < FILE_HASH_SIZE; i++) { INIT_LIST_HEAD(&file_hashtbl[i]); } |
16bfdaafa nfsd4: share open... |
4390 4391 |
for (i = 0; i < OWNER_HASH_SIZE; i++) { INIT_LIST_HEAD(&ownerstr_hashtbl[i]); |
1da177e4c Linux-2.6.12-rc2 |
4392 |
} |
009673b43 nfsd4: add a sepa... |
4393 4394 |
for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++) INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]); |
1da177e4c Linux-2.6.12-rc2 |
4395 4396 4397 |
INIT_LIST_HEAD(&close_lru); INIT_LIST_HEAD(&client_lru); INIT_LIST_HEAD(&del_recall_lru); |
ac4d8ff2a [PATCH] knfsd: nf... |
4398 |
reclaim_str_hashtbl_size = 0; |
ac4d8ff2a [PATCH] knfsd: nf... |
4399 |
} |
190e4fbf9 [PATCH] knfsd: nf... |
4400 4401 4402 4403 |
static void nfsd4_load_reboot_recovery_data(void) { int status; |
0964a3d3f [PATCH] knfsd: nf... |
4404 |
nfs4_lock_state(); |
48483bf23 nfsd4: simplify r... |
4405 |
nfsd4_init_recdir(); |
190e4fbf9 [PATCH] knfsd: nf... |
4406 |
status = nfsd4_recdir_load(); |
0964a3d3f [PATCH] knfsd: nf... |
4407 |
nfs4_unlock_state(); |
190e4fbf9 [PATCH] knfsd: nf... |
4408 4409 4410 4411 |
if (status) printk("NFSD: Failure reading reboot recovery data "); } |
c2f1a551d knfsd: nfsd4: var... |
4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 |
/* * Since the lifetime of a delegation isn't limited to that of an open, a * client may quite reasonably hang on to a delegation as long as it has * the inode cached. This becomes an obvious problem the first time a * client's inode cache approaches the size of the server's total memory. * * For now we avoid this problem by imposing a hard limit on the number * of delegations, which varies according to the server's memory size. */ static void set_max_delegations(void) { /* * Allow at most 4 delegations per megabyte of RAM. Quick * estimates suggest that in the worst case (where every delegation * is for a different inode), a delegation could take about 1.5K, * giving a worst case usage of about 6% of memory. */ max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT); } |
ac4d8ff2a [PATCH] knfsd: nf... |
4432 |
/* initialization to perform when the nfsd service is started: */ |
29ab23cc5 nfsd4: allow nfs4... |
4433 |
static int |
ac4d8ff2a [PATCH] knfsd: nf... |
4434 4435 |
__nfs4_state_start(void) { |
b5a1a81e5 nfsd4: don't slee... |
4436 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
4437 |
boot_time = get_seconds(); |
af558e33b nfsd: common grac... |
4438 |
locks_start_grace(&nfsd4_manager); |
9a8db97e7 knfsd: lockd: nfs... |
4439 4440 |
printk(KERN_INFO "NFSD: starting %ld-second grace period ", |
e46b498c8 nfsd4: simplify l... |
4441 |
nfsd4_grace); |
b5a1a81e5 nfsd4: don't slee... |
4442 4443 4444 |
ret = set_callback_cred(); if (ret) return -ENOMEM; |
58da282b7 [PATCH] knfsd: nf... |
4445 |
laundry_wq = create_singlethread_workqueue("nfsd4"); |
29ab23cc5 nfsd4: allow nfs4... |
4446 4447 |
if (laundry_wq == NULL) return -ENOMEM; |
b5a1a81e5 nfsd4: don't slee... |
4448 4449 4450 |
ret = nfsd4_create_callback_queue(); if (ret) goto out_free_laundry; |
e46b498c8 nfsd4: simplify l... |
4451 |
queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ); |
c2f1a551d knfsd: nfsd4: var... |
4452 |
set_max_delegations(); |
b5a1a81e5 nfsd4: don't slee... |
4453 4454 4455 4456 |
return 0; out_free_laundry: destroy_workqueue(laundry_wq); return ret; |
1da177e4c Linux-2.6.12-rc2 |
4457 |
} |
29ab23cc5 nfsd4: allow nfs4... |
4458 |
int |
76a3550ec [PATCH] knfsd: nf... |
4459 |
nfs4_state_start(void) |
1da177e4c Linux-2.6.12-rc2 |
4460 |
{ |
190e4fbf9 [PATCH] knfsd: nf... |
4461 |
nfsd4_load_reboot_recovery_data(); |
4ad9a344b nfsd4: fix v4 sta... |
4462 |
return __nfs4_state_start(); |
1da177e4c Linux-2.6.12-rc2 |
4463 |
} |
1da177e4c Linux-2.6.12-rc2 |
4464 4465 4466 4467 4468 4469 |
static void __nfs4_state_shutdown(void) { int i; struct nfs4_client *clp = NULL; struct nfs4_delegation *dp = NULL; |
1da177e4c Linux-2.6.12-rc2 |
4470 |
struct list_head *pos, *next, reaplist; |
1da177e4c Linux-2.6.12-rc2 |
4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 |
for (i = 0; i < CLIENT_HASH_SIZE; i++) { while (!list_empty(&conf_id_hashtbl[i])) { clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); expire_client(clp); } while (!list_empty(&unconf_str_hashtbl[i])) { clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); expire_client(clp); } } INIT_LIST_HEAD(&reaplist); spin_lock(&recall_lock); list_for_each_safe(pos, next, &del_recall_lru) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); list_move(&dp->dl_recall_lru, &reaplist); } spin_unlock(&recall_lock); list_for_each_safe(pos, next, &reaplist) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); |
1da177e4c Linux-2.6.12-rc2 |
4490 4491 |
unhash_delegation(dp); } |
190e4fbf9 [PATCH] knfsd: nf... |
4492 |
nfsd4_shutdown_recdir(); |
1da177e4c Linux-2.6.12-rc2 |
4493 4494 4495 4496 4497 |
} void nfs4_state_shutdown(void) { |
afe2c511f workqueue: conver... |
4498 |
cancel_delayed_work_sync(&laundromat_work); |
5e8d5c294 [PATCH] knfsd: nf... |
4499 |
destroy_workqueue(laundry_wq); |
2c5e76158 nfsd: clean up gr... |
4500 |
locks_end_grace(&nfsd4_manager); |
1da177e4c Linux-2.6.12-rc2 |
4501 4502 4503 |
nfs4_lock_state(); nfs4_release_reclaim(); __nfs4_state_shutdown(); |
1da177e4c Linux-2.6.12-rc2 |
4504 |
nfs4_unlock_state(); |
c3935e304 nfsd4: shut down ... |
4505 |
nfsd4_destroy_callback_queue(); |
1da177e4c Linux-2.6.12-rc2 |
4506 |
} |