Blame view
fs/nfs/nfs4state.c
47.4 KB
1da177e4c Linux-2.6.12-rc2 |
1 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 34 35 36 37 38 39 |
/* * fs/nfs/nfs4state.c * * Client-side XDR for NFSv4. * * Copyright (c) 2002 The Regents of the University of Michigan. * All rights reserved. * * Kendrick Smith <kmsmith@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. * * Implementation of the NFSv4 state model. For the time being, * this is minimal, but will be made much more complex in a * subsequent patch. */ |
6f43ddccb NFSv4: Improve th... |
40 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
41 |
#include <linux/slab.h> |
b89f43213 fs/locks.c: prepa... |
42 |
#include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
43 44 |
#include <linux/nfs_fs.h> #include <linux/nfs_idmap.h> |
5043e900f NFS: Convert inst... |
45 46 |
#include <linux/kthread.h> #include <linux/module.h> |
9f958ab88 NFSv4: Reduce the... |
47 |
#include <linux/random.h> |
8c7597f6c nfs: include rate... |
48 |
#include <linux/ratelimit.h> |
1da177e4c Linux-2.6.12-rc2 |
49 50 |
#include <linux/workqueue.h> #include <linux/bitops.h> |
0aaaf5c42 NFS: Cache state ... |
51 |
#include <linux/jiffies.h> |
1da177e4c Linux-2.6.12-rc2 |
52 |
|
4ce79717c [PATCH] NFS: Head... |
53 |
#include "nfs4_fs.h" |
1da177e4c Linux-2.6.12-rc2 |
54 55 |
#include "callback.h" #include "delegation.h" |
24c8dbbb5 NFS: Generalise t... |
56 |
#include "internal.h" |
974cec8ca NFS: client needs... |
57 |
#include "pnfs.h" |
1da177e4c Linux-2.6.12-rc2 |
58 59 |
#define OPENOWNER_POOL_SIZE 8 |
4ce79717c [PATCH] NFS: Head... |
60 |
const nfs4_stateid zero_stateid; |
1da177e4c Linux-2.6.12-rc2 |
61 62 |
static LIST_HEAD(nfs4_clientid_list); |
591d71cbd nfs41: establish ... |
63 |
int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
64 |
{ |
fd954ae12 NFSv4.1: Don't lo... |
65 66 67 68 |
struct nfs4_setclientid_res clid = { .clientid = clp->cl_clientid, .confirm = clp->cl_confirm, }; |
f738f5170 NFS: Start PF_INE... |
69 70 |
unsigned short port; int status; |
fd954ae12 NFSv4.1: Don't lo... |
71 72 |
if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) goto do_confirm; |
f738f5170 NFS: Start PF_INE... |
73 74 75 |
port = nfs_callback_tcpport; if (clp->cl_addr.ss_family == AF_INET6) port = nfs_callback_tcpport6; |
bb8b27e50 NFSv4: Clean up t... |
76 77 78 |
status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
79 80 81 82 |
clp->cl_clientid = clid.clientid; clp->cl_confirm = clid.confirm; set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); do_confirm: |
bb8b27e50 NFSv4: Clean up t... |
83 84 85 |
status = nfs4_proc_setclientid_confirm(clp, &clid, cred); if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
86 |
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
bb8b27e50 NFSv4: Clean up t... |
87 88 |
nfs4_schedule_state_renewal(clp); out: |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
return status; } |
a7b721037 nfs41: introduce ... |
91 |
struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp) |
a2b2bb882 NFSv4: Attempt to... |
92 93 |
{ struct rpc_cred *cred = NULL; |
a2b2bb882 NFSv4: Attempt to... |
94 95 |
if (clp->cl_machine_cred != NULL) cred = get_rpccred(clp->cl_machine_cred); |
a2b2bb882 NFSv4: Attempt to... |
96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
return cred; } static void nfs4_clear_machine_cred(struct nfs_client *clp) { struct rpc_cred *cred; spin_lock(&clp->cl_lock); cred = clp->cl_machine_cred; clp->cl_machine_cred = NULL; spin_unlock(&clp->cl_lock); if (cred != NULL) put_rpccred(cred); } |
24d292b89 NFS: Move cl_stat... |
110 111 |
static struct rpc_cred * nfs4_get_renew_cred_server_locked(struct nfs_server *server) |
b4454fe1a NFSv4: Remove req... |
112 |
{ |
24d292b89 NFS: Move cl_stat... |
113 |
struct rpc_cred *cred = NULL; |
b4454fe1a NFSv4: Remove req... |
114 |
struct nfs4_state_owner *sp; |
9f958ab88 NFSv4: Reduce the... |
115 |
struct rb_node *pos; |
b4454fe1a NFSv4: Remove req... |
116 |
|
24d292b89 NFS: Move cl_stat... |
117 118 119 120 |
for (pos = rb_first(&server->state_owners); pos != NULL; pos = rb_next(pos)) { sp = rb_entry(pos, struct nfs4_state_owner, so_server_node); |
b4454fe1a NFSv4: Remove req... |
121 122 123 124 125 126 127 |
if (list_empty(&sp->so_states)) continue; cred = get_rpccred(sp->so_cred); break; } return cred; } |
24d292b89 NFS: Move cl_stat... |
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
/** * nfs4_get_renew_cred_locked - Acquire credential for a renew operation * @clp: client state handle * * Returns an rpc_cred with reference count bumped, or NULL. * Caller must hold clp->cl_lock. */ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp) { struct rpc_cred *cred = NULL; struct nfs_server *server; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { cred = nfs4_get_renew_cred_server_locked(server); if (cred != NULL) break; } rcu_read_unlock(); return cred; } |
b4b82607f nfs41: get_clid_c... |
149 |
#if defined(CONFIG_NFS_V4_1) |
9430fb6b5 nfs41: nfs41_setu... |
150 151 152 153 |
static int nfs41_setup_state_renewal(struct nfs_client *clp) { int status; struct nfs_fsinfo fsinfo; |
d6fb79d43 NFSv4.1: new flag... |
154 155 156 157 |
if (!test_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state)) { nfs4_schedule_state_renewal(clp); return 0; } |
9430fb6b5 nfs41: nfs41_setu... |
158 159 160 161 162 163 164 165 166 167 168 169 170 |
status = nfs4_proc_get_lease_time(clp, &fsinfo); if (status == 0) { /* Update lease time and schedule renewal */ spin_lock(&clp->cl_lock); clp->cl_lease_time = fsinfo.lease_time * HZ; clp->cl_last_renewal = jiffies; spin_unlock(&clp->cl_lock); nfs4_schedule_state_renewal(clp); } return status; } |
42acd0218 NFS add session b... |
171 172 173 174 175 |
/* * Back channel returns NFS4ERR_DELAY for new requests when * NFS4_SESSION_DRAINING is set so there is no work to be done when draining * is ended. */ |
5601a00d6 nfs: run state ma... |
176 |
static void nfs4_end_drain_session(struct nfs_client *clp) |
9dfdf404c nfs41: Don't clea... |
177 |
{ |
5601a00d6 nfs: run state ma... |
178 |
struct nfs4_session *ses = clp->cl_session; |
689cf5c15 nfs: enforce FIFO... |
179 |
int max_slots; |
a2118c33a NFSv41: Don't sto... |
180 181 182 |
if (ses == NULL) return; if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { |
689cf5c15 nfs: enforce FIFO... |
183 184 185 186 187 188 189 190 191 192 193 194 195 |
spin_lock(&ses->fc_slot_table.slot_tbl_lock); max_slots = ses->fc_slot_table.max_slots; while (max_slots--) { struct rpc_task *task; task = rpc_wake_up_next(&ses->fc_slot_table. slot_tbl_waitq); if (!task) break; rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); } spin_unlock(&ses->fc_slot_table.slot_tbl_lock); } |
9dfdf404c nfs41: Don't clea... |
196 |
} |
42acd0218 NFS add session b... |
197 |
static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) |
9dfdf404c nfs41: Don't clea... |
198 |
{ |
9dfdf404c nfs41: Don't clea... |
199 |
spin_lock(&tbl->slot_tbl_lock); |
9dfdf404c nfs41: Don't clea... |
200 |
if (tbl->highest_used_slotid != -1) { |
42acd0218 NFS add session b... |
201 |
INIT_COMPLETION(tbl->complete); |
9dfdf404c nfs41: Don't clea... |
202 |
spin_unlock(&tbl->slot_tbl_lock); |
42acd0218 NFS add session b... |
203 |
return wait_for_completion_interruptible(&tbl->complete); |
9dfdf404c nfs41: Don't clea... |
204 205 206 207 |
} spin_unlock(&tbl->slot_tbl_lock); return 0; } |
42acd0218 NFS add session b... |
208 209 210 211 212 213 214 215 216 217 218 219 220 |
static int nfs4_begin_drain_session(struct nfs_client *clp) { struct nfs4_session *ses = clp->cl_session; int ret = 0; set_bit(NFS4_SESSION_DRAINING, &ses->session_state); /* back channel */ ret = nfs4_wait_on_slot_tbl(&ses->bc_slot_table); if (ret) return ret; /* fore channel */ return nfs4_wait_on_slot_tbl(&ses->fc_slot_table); } |
4d643d1df nfs41: add create... |
221 222 223 |
int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) { int status; |
fd954ae12 NFSv4.1: Don't lo... |
224 225 |
if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) goto do_confirm; |
380454126 NFSv4: Fix a regr... |
226 |
nfs4_begin_drain_session(clp); |
4d643d1df nfs41: add create... |
227 |
status = nfs4_proc_exchange_id(clp, cred); |
9430fb6b5 nfs41: nfs41_setu... |
228 229 |
if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
230 231 |
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); do_confirm: |
9430fb6b5 nfs41: nfs41_setu... |
232 233 234 |
status = nfs4_proc_create_session(clp); if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
235 |
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
9430fb6b5 nfs41: nfs41_setu... |
236 237 238 |
nfs41_setup_state_renewal(clp); nfs_mark_client_ready(clp, NFS_CS_READY); out: |
4d643d1df nfs41: add create... |
239 240 |
return status; } |
b4b82607f nfs41: get_clid_c... |
241 242 243 244 245 246 247 248 249 250 251 |
struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp) { struct rpc_cred *cred; spin_lock(&clp->cl_lock); cred = nfs4_get_machine_cred_locked(clp); spin_unlock(&clp->cl_lock); return cred; } #endif /* CONFIG_NFS_V4_1 */ |
24d292b89 NFS: Move cl_stat... |
252 253 |
static struct rpc_cred * nfs4_get_setclientid_cred_server(struct nfs_server *server) |
286d7d6a0 NFSv4: Remove req... |
254 |
{ |
24d292b89 NFS: Move cl_stat... |
255 256 |
struct nfs_client *clp = server->nfs_client; struct rpc_cred *cred = NULL; |
286d7d6a0 NFSv4: Remove req... |
257 |
struct nfs4_state_owner *sp; |
9f958ab88 NFSv4: Reduce the... |
258 |
struct rb_node *pos; |
24d292b89 NFS: Move cl_stat... |
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
spin_lock(&clp->cl_lock); pos = rb_first(&server->state_owners); if (pos != NULL) { sp = rb_entry(pos, struct nfs4_state_owner, so_server_node); cred = get_rpccred(sp->so_cred); } spin_unlock(&clp->cl_lock); return cred; } /** * nfs4_get_setclientid_cred - Acquire credential for a setclientid operation * @clp: client state handle * * Returns an rpc_cred with reference count bumped, or NULL. */ struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) { struct nfs_server *server; |
a2b2bb882 NFSv4: Attempt to... |
279 |
struct rpc_cred *cred; |
286d7d6a0 NFSv4: Remove req... |
280 |
|
6dc9d57af NFSv4: Callers to... |
281 282 |
spin_lock(&clp->cl_lock); cred = nfs4_get_machine_cred_locked(clp); |
24d292b89 NFS: Move cl_stat... |
283 |
spin_unlock(&clp->cl_lock); |
a2b2bb882 NFSv4: Attempt to... |
284 285 |
if (cred != NULL) goto out; |
24d292b89 NFS: Move cl_stat... |
286 287 288 289 290 291 |
rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { cred = nfs4_get_setclientid_cred_server(server); if (cred != NULL) break; |
286d7d6a0 NFSv4: Remove req... |
292 |
} |
24d292b89 NFS: Move cl_stat... |
293 |
rcu_read_unlock(); |
a2b2bb882 NFSv4: Attempt to... |
294 295 |
out: return cred; |
286d7d6a0 NFSv4: Remove req... |
296 |
} |
24d292b89 NFS: Move cl_stat... |
297 298 299 |
static void nfs_alloc_unique_id_locked(struct rb_root *root, struct nfs_unique_id *new, __u64 minval, int maxbits) |
9f958ab88 NFSv4: Reduce the... |
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
{ struct rb_node **p, *parent; struct nfs_unique_id *pos; __u64 mask = ~0ULL; if (maxbits < 64) mask = (1ULL << maxbits) - 1ULL; /* Ensure distribution is more or less flat */ get_random_bytes(&new->id, sizeof(new->id)); new->id &= mask; if (new->id < minval) new->id += minval; retry: p = &root->rb_node; parent = NULL; while (*p != NULL) { parent = *p; pos = rb_entry(parent, struct nfs_unique_id, rb_node); if (new->id < pos->id) p = &(*p)->rb_left; else if (new->id > pos->id) p = &(*p)->rb_right; else goto id_exists; } rb_link_node(&new->rb_node, parent, p); rb_insert_color(&new->rb_node, root); return; id_exists: for (;;) { new->id++; if (new->id < minval || (new->id & mask) != new->id) { new->id = minval; break; } parent = rb_next(parent); if (parent == NULL) break; pos = rb_entry(parent, struct nfs_unique_id, rb_node); if (new->id < pos->id) break; } goto retry; } static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id) { rb_erase(&id->rb_node, root); } |
1da177e4c Linux-2.6.12-rc2 |
352 |
static struct nfs4_state_owner * |
24d292b89 NFS: Move cl_stat... |
353 |
nfs4_find_state_owner_locked(struct nfs_server *server, struct rpc_cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
354 |
{ |
24d292b89 NFS: Move cl_stat... |
355 |
struct rb_node **p = &server->state_owners.rb_node, |
9f958ab88 NFSv4: Reduce the... |
356 |
*parent = NULL; |
414adf14c NFS: Clean up nfs... |
357 |
struct nfs4_state_owner *sp; |
1da177e4c Linux-2.6.12-rc2 |
358 |
|
9f958ab88 NFSv4: Reduce the... |
359 360 |
while (*p != NULL) { parent = *p; |
24d292b89 NFS: Move cl_stat... |
361 |
sp = rb_entry(parent, struct nfs4_state_owner, so_server_node); |
9f958ab88 NFSv4: Reduce the... |
362 363 364 365 366 367 |
if (cred < sp->so_cred) p = &parent->rb_left; else if (cred > sp->so_cred) p = &parent->rb_right; else { |
0aaaf5c42 NFS: Cache state ... |
368 369 |
if (!list_empty(&sp->so_lru)) list_del_init(&sp->so_lru); |
9f958ab88 NFSv4: Reduce the... |
370 |
atomic_inc(&sp->so_count); |
414adf14c NFS: Clean up nfs... |
371 |
return sp; |
9f958ab88 NFSv4: Reduce the... |
372 |
} |
1da177e4c Linux-2.6.12-rc2 |
373 |
} |
414adf14c NFS: Clean up nfs... |
374 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
375 |
} |
9f958ab88 NFSv4: Reduce the... |
376 |
static struct nfs4_state_owner * |
24d292b89 NFS: Move cl_stat... |
377 |
nfs4_insert_state_owner_locked(struct nfs4_state_owner *new) |
9f958ab88 NFSv4: Reduce the... |
378 |
{ |
24d292b89 NFS: Move cl_stat... |
379 380 |
struct nfs_server *server = new->so_server; struct rb_node **p = &server->state_owners.rb_node, |
9f958ab88 NFSv4: Reduce the... |
381 382 383 384 385 |
*parent = NULL; struct nfs4_state_owner *sp; while (*p != NULL) { parent = *p; |
24d292b89 NFS: Move cl_stat... |
386 |
sp = rb_entry(parent, struct nfs4_state_owner, so_server_node); |
9f958ab88 NFSv4: Reduce the... |
387 388 389 390 391 392 |
if (new->so_cred < sp->so_cred) p = &parent->rb_left; else if (new->so_cred > sp->so_cred) p = &parent->rb_right; else { |
0aaaf5c42 NFS: Cache state ... |
393 394 |
if (!list_empty(&sp->so_lru)) list_del_init(&sp->so_lru); |
9f958ab88 NFSv4: Reduce the... |
395 396 397 398 |
atomic_inc(&sp->so_count); return sp; } } |
24d292b89 NFS: Move cl_stat... |
399 400 401 402 |
nfs_alloc_unique_id_locked(&server->openowner_id, &new->so_owner_id, 1, 64); rb_link_node(&new->so_server_node, parent, p); rb_insert_color(&new->so_server_node, &server->state_owners); |
9f958ab88 NFSv4: Reduce the... |
403 404 405 406 |
return new; } static void |
24d292b89 NFS: Move cl_stat... |
407 |
nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp) |
9f958ab88 NFSv4: Reduce the... |
408 |
{ |
24d292b89 NFS: Move cl_stat... |
409 410 411 412 413 |
struct nfs_server *server = sp->so_server; if (!RB_EMPTY_NODE(&sp->so_server_node)) rb_erase(&sp->so_server_node, &server->state_owners); nfs_free_unique_id(&server->openowner_id, &sp->so_owner_id); |
9f958ab88 NFSv4: Reduce the... |
414 |
} |
1da177e4c Linux-2.6.12-rc2 |
415 416 417 418 419 420 421 422 423 |
/* * nfs4_alloc_state_owner(): this is called on the OPEN or CREATE path to * create a new state_owner. * */ static struct nfs4_state_owner * nfs4_alloc_state_owner(void) { struct nfs4_state_owner *sp; |
8535b2be5 NFSv4: Don't use ... |
424 |
sp = kzalloc(sizeof(*sp),GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
425 426 |
if (!sp) return NULL; |
ec0734282 NFSv4: Fix up loc... |
427 |
spin_lock_init(&sp->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
428 |
INIT_LIST_HEAD(&sp->so_states); |
cee54fc94 NFSv4: Add functi... |
429 430 431 432 |
rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); sp->so_seqid.sequence = &sp->so_sequence; spin_lock_init(&sp->so_sequence.lock); INIT_LIST_HEAD(&sp->so_sequence.list); |
1da177e4c Linux-2.6.12-rc2 |
433 |
atomic_set(&sp->so_count, 1); |
0aaaf5c42 NFS: Cache state ... |
434 |
INIT_LIST_HEAD(&sp->so_lru); |
1da177e4c Linux-2.6.12-rc2 |
435 436 |
return sp; } |
1d2e88e73 nfs: make nfs4_dr... |
437 |
static void |
1da177e4c Linux-2.6.12-rc2 |
438 439 |
nfs4_drop_state_owner(struct nfs4_state_owner *sp) { |
24d292b89 NFS: Move cl_stat... |
440 441 442 |
if (!RB_EMPTY_NODE(&sp->so_server_node)) { struct nfs_server *server = sp->so_server; struct nfs_client *clp = server->nfs_client; |
9f958ab88 NFSv4: Reduce the... |
443 444 |
spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
445 446 |
rb_erase(&sp->so_server_node, &server->state_owners); RB_CLEAR_NODE(&sp->so_server_node); |
9f958ab88 NFSv4: Reduce the... |
447 448 |
spin_unlock(&clp->cl_lock); } |
1da177e4c Linux-2.6.12-rc2 |
449 |
} |
0aaaf5c42 NFS: Cache state ... |
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
static void nfs4_free_state_owner(struct nfs4_state_owner *sp) { rpc_destroy_wait_queue(&sp->so_sequence.wait); put_rpccred(sp->so_cred); kfree(sp); } static void nfs4_gc_state_owners(struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; struct nfs4_state_owner *sp, *tmp; unsigned long time_min, time_max; LIST_HEAD(doomed); spin_lock(&clp->cl_lock); time_max = jiffies; time_min = (long)time_max - (long)clp->cl_lease_time; list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) { /* NB: LRU is sorted so that oldest is at the head */ if (time_in_range(sp->so_expires, time_min, time_max)) break; list_move(&sp->so_lru, &doomed); nfs4_remove_state_owner_locked(sp); } spin_unlock(&clp->cl_lock); list_for_each_entry_safe(sp, tmp, &doomed, so_lru) { list_del(&sp->so_lru); nfs4_free_state_owner(sp); } } |
24d292b89 NFS: Move cl_stat... |
481 482 483 484 485 486 487 488 489 |
/** * nfs4_get_state_owner - Look up a state owner given a credential * @server: nfs_server to search * @cred: RPC credential to match * * Returns a pointer to an instantiated nfs4_state_owner struct, or NULL. */ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
490 |
{ |
7539bbab8 NFS: Rename nfs_s... |
491 |
struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
492 |
struct nfs4_state_owner *sp, *new; |
1da177e4c Linux-2.6.12-rc2 |
493 |
spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
494 |
sp = nfs4_find_state_owner_locked(server, cred); |
1da177e4c Linux-2.6.12-rc2 |
495 |
spin_unlock(&clp->cl_lock); |
1da177e4c Linux-2.6.12-rc2 |
496 |
if (sp != NULL) |
0aaaf5c42 NFS: Cache state ... |
497 |
goto out; |
9f958ab88 NFSv4: Reduce the... |
498 499 |
new = nfs4_alloc_state_owner(); if (new == NULL) |
0aaaf5c42 NFS: Cache state ... |
500 |
goto out; |
6f2e64d3e NFSv4: Make the N... |
501 |
new->so_server = server; |
9f958ab88 NFSv4: Reduce the... |
502 503 |
new->so_cred = cred; spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
504 |
sp = nfs4_insert_state_owner_locked(new); |
9f958ab88 NFSv4: Reduce the... |
505 506 507 |
spin_unlock(&clp->cl_lock); if (sp == new) get_rpccred(cred); |
f6a1cc893 SUNRPC: Add a (em... |
508 509 |
else { rpc_destroy_wait_queue(&new->so_sequence.wait); |
9f958ab88 NFSv4: Reduce the... |
510 |
kfree(new); |
f6a1cc893 SUNRPC: Add a (em... |
511 |
} |
0aaaf5c42 NFS: Cache state ... |
512 513 |
out: nfs4_gc_state_owners(server); |
9f958ab88 NFSv4: Reduce the... |
514 |
return sp; |
1da177e4c Linux-2.6.12-rc2 |
515 |
} |
24d292b89 NFS: Move cl_stat... |
516 517 518 |
/** * nfs4_put_state_owner - Release a nfs4_state_owner * @sp: state owner data to release |
24d292b89 NFS: Move cl_stat... |
519 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
520 521 |
void nfs4_put_state_owner(struct nfs4_state_owner *sp) { |
0aaaf5c42 NFS: Cache state ... |
522 523 |
struct nfs_server *server = sp->so_server; struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
524 525 526 |
if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) return; |
0aaaf5c42 NFS: Cache state ... |
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 |
if (!RB_EMPTY_NODE(&sp->so_server_node)) { sp->so_expires = jiffies; list_add_tail(&sp->so_lru, &server->state_owners_lru); spin_unlock(&clp->cl_lock); } else { nfs4_remove_state_owner_locked(sp); spin_unlock(&clp->cl_lock); nfs4_free_state_owner(sp); } } /** * nfs4_purge_state_owners - Release all cached state owners * @server: nfs_server with cached state owners to release * * Called at umount time. Remaining state owners will be on * the LRU with ref count of zero. */ void nfs4_purge_state_owners(struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; struct nfs4_state_owner *sp, *tmp; LIST_HEAD(doomed); spin_lock(&clp->cl_lock); list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) { list_move(&sp->so_lru, &doomed); nfs4_remove_state_owner_locked(sp); } |
1da177e4c Linux-2.6.12-rc2 |
557 |
spin_unlock(&clp->cl_lock); |
0aaaf5c42 NFS: Cache state ... |
558 559 560 561 562 |
list_for_each_entry_safe(sp, tmp, &doomed, so_lru) { list_del(&sp->so_lru); nfs4_free_state_owner(sp); } |
1da177e4c Linux-2.6.12-rc2 |
563 564 565 566 567 568 |
} static struct nfs4_state * nfs4_alloc_open_state(void) { struct nfs4_state *state; |
8535b2be5 NFSv4: Don't use ... |
569 |
state = kzalloc(sizeof(*state), GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
570 571 |
if (!state) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
572 573 |
atomic_set(&state->count, 1); INIT_LIST_HEAD(&state->lock_states); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
574 |
spin_lock_init(&state->state_lock); |
8bda4e4c9 NFSv4: Fix up sta... |
575 |
seqlock_init(&state->seqlock); |
1da177e4c Linux-2.6.12-rc2 |
576 577 |
return state; } |
4cecb76ff NFSv4: Fix a race... |
578 |
void |
dc0b027df NFSv4: Convert th... |
579 |
nfs4_state_set_mode_locked(struct nfs4_state *state, fmode_t fmode) |
4cecb76ff NFSv4: Fix a race... |
580 |
{ |
dc0b027df NFSv4: Convert th... |
581 |
if (state->state == fmode) |
4cecb76ff NFSv4: Fix a race... |
582 583 |
return; /* NB! List reordering - see the reclaim code for why. */ |
dc0b027df NFSv4: Convert th... |
584 585 |
if ((fmode & FMODE_WRITE) != (state->state & FMODE_WRITE)) { if (fmode & FMODE_WRITE) |
4cecb76ff NFSv4: Fix a race... |
586 587 588 589 |
list_move(&state->open_states, &state->owner->so_states); else list_move_tail(&state->open_states, &state->owner->so_states); } |
dc0b027df NFSv4: Convert th... |
590 |
state->state = fmode; |
4cecb76ff NFSv4: Fix a race... |
591 |
} |
1da177e4c Linux-2.6.12-rc2 |
592 |
static struct nfs4_state * |
1da177e4c Linux-2.6.12-rc2 |
593 594 595 596 597 598 |
__nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs4_state *state; list_for_each_entry(state, &nfsi->open_states, inode_states) { |
1c816efa2 NFSv4: Fix a bug ... |
599 |
if (state->owner != owner) |
1da177e4c Linux-2.6.12-rc2 |
600 |
continue; |
1c816efa2 NFSv4: Fix a bug ... |
601 |
if (atomic_inc_not_zero(&state->count)) |
1da177e4c Linux-2.6.12-rc2 |
602 |
return state; |
1da177e4c Linux-2.6.12-rc2 |
603 604 605 |
} return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
static void nfs4_free_open_state(struct nfs4_state *state) { kfree(state); } struct nfs4_state * nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner) { struct nfs4_state *state, *new; struct nfs_inode *nfsi = NFS_I(inode); spin_lock(&inode->i_lock); state = __nfs4_find_state_byowner(inode, owner); spin_unlock(&inode->i_lock); if (state) goto out; new = nfs4_alloc_open_state(); |
ec0734282 NFSv4: Fix up loc... |
624 |
spin_lock(&owner->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
625 626 627 628 |
spin_lock(&inode->i_lock); state = __nfs4_find_state_byowner(inode, owner); if (state == NULL && new != NULL) { state = new; |
1da177e4c Linux-2.6.12-rc2 |
629 630 631 |
state->owner = owner; atomic_inc(&owner->so_count); list_add(&state->inode_states, &nfsi->open_states); |
0444d76ae fs: don't use igr... |
632 633 |
ihold(inode); state->inode = inode; |
1da177e4c Linux-2.6.12-rc2 |
634 |
spin_unlock(&inode->i_lock); |
ec0734282 NFSv4: Fix up loc... |
635 636 637 638 |
/* Note: The reclaim code dictates that we add stateless * and read-only stateids to the end of the list */ list_add_tail(&state->open_states, &owner->so_states); spin_unlock(&owner->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
639 640 |
} else { spin_unlock(&inode->i_lock); |
ec0734282 NFSv4: Fix up loc... |
641 |
spin_unlock(&owner->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
642 643 644 645 646 647 |
if (new) nfs4_free_open_state(new); } out: return state; } |
1da177e4c Linux-2.6.12-rc2 |
648 649 650 651 |
void nfs4_put_open_state(struct nfs4_state *state) { struct inode *inode = state->inode; struct nfs4_state_owner *owner = state->owner; |
ec0734282 NFSv4: Fix up loc... |
652 |
if (!atomic_dec_and_lock(&state->count, &owner->so_lock)) |
1da177e4c Linux-2.6.12-rc2 |
653 |
return; |
ec0734282 NFSv4: Fix up loc... |
654 |
spin_lock(&inode->i_lock); |
ba683031f NFSv4: Fix a lock... |
655 |
list_del(&state->inode_states); |
1da177e4c Linux-2.6.12-rc2 |
656 |
list_del(&state->open_states); |
ec0734282 NFSv4: Fix up loc... |
657 658 |
spin_unlock(&inode->i_lock); spin_unlock(&owner->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
659 |
iput(inode); |
1da177e4c Linux-2.6.12-rc2 |
660 661 662 663 664 |
nfs4_free_open_state(state); nfs4_put_state_owner(owner); } /* |
83c9d41e4 NFSv4: Remove nfs... |
665 |
* Close the current file. |
1da177e4c Linux-2.6.12-rc2 |
666 |
*/ |
643168c2d nfs4_closedata do... |
667 |
static void __nfs4_close(struct nfs4_state *state, |
8535b2be5 NFSv4: Don't use ... |
668 |
fmode_t fmode, gfp_t gfp_mask, int wait) |
1da177e4c Linux-2.6.12-rc2 |
669 |
{ |
1da177e4c Linux-2.6.12-rc2 |
670 |
struct nfs4_state_owner *owner = state->owner; |
003707c72 NFSv4: Always use... |
671 |
int call_close = 0; |
dc0b027df NFSv4: Convert th... |
672 |
fmode_t newstate; |
1da177e4c Linux-2.6.12-rc2 |
673 674 |
atomic_inc(&owner->so_count); |
1da177e4c Linux-2.6.12-rc2 |
675 |
/* Protect against nfs4_find_state() */ |
ec0734282 NFSv4: Fix up loc... |
676 |
spin_lock(&owner->so_lock); |
dc0b027df NFSv4: Convert th... |
677 |
switch (fmode & (FMODE_READ | FMODE_WRITE)) { |
e76169238 NFSv4: Make nfs4_... |
678 679 680 681 682 683 684 685 686 |
case FMODE_READ: state->n_rdonly--; break; case FMODE_WRITE: state->n_wronly--; break; case FMODE_READ|FMODE_WRITE: state->n_rdwr--; } |
003707c72 NFSv4: Always use... |
687 |
newstate = FMODE_READ|FMODE_WRITE; |
e76169238 NFSv4: Make nfs4_... |
688 |
if (state->n_rdwr == 0) { |
003707c72 NFSv4: Always use... |
689 |
if (state->n_rdonly == 0) { |
e76169238 NFSv4: Make nfs4_... |
690 |
newstate &= ~FMODE_READ; |
003707c72 NFSv4: Always use... |
691 692 693 694 |
call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags); call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); } if (state->n_wronly == 0) { |
e76169238 NFSv4: Make nfs4_... |
695 |
newstate &= ~FMODE_WRITE; |
003707c72 NFSv4: Always use... |
696 697 698 699 700 |
call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags); call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); } if (newstate == 0) clear_bit(NFS_DELEGATED_STATE, &state->flags); |
e76169238 NFSv4: Make nfs4_... |
701 |
} |
003707c72 NFSv4: Always use... |
702 |
nfs4_state_set_mode_locked(state, newstate); |
ec0734282 NFSv4: Fix up loc... |
703 |
spin_unlock(&owner->so_lock); |
4cecb76ff NFSv4: Fix a race... |
704 |
|
003707c72 NFSv4: Always use... |
705 |
if (!call_close) { |
b39e625b6 NFSv4: Clean up n... |
706 707 |
nfs4_put_open_state(state); nfs4_put_state_owner(owner); |
f7e8917a6 pnfs: layout roc ... |
708 709 |
} else { bool roc = pnfs_roc(state->inode); |
643168c2d nfs4_closedata do... |
710 |
nfs4_do_close(state, gfp_mask, wait, roc); |
f7e8917a6 pnfs: layout roc ... |
711 |
} |
a49c3c773 NFSv4: Ensure tha... |
712 |
} |
643168c2d nfs4_closedata do... |
713 |
void nfs4_close_state(struct nfs4_state *state, fmode_t fmode) |
a49c3c773 NFSv4: Ensure tha... |
714 |
{ |
643168c2d nfs4_closedata do... |
715 |
__nfs4_close(state, fmode, GFP_NOFS, 0); |
a49c3c773 NFSv4: Ensure tha... |
716 |
} |
643168c2d nfs4_closedata do... |
717 |
void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode) |
a49c3c773 NFSv4: Ensure tha... |
718 |
{ |
643168c2d nfs4_closedata do... |
719 |
__nfs4_close(state, fmode, GFP_KERNEL, 1); |
1da177e4c Linux-2.6.12-rc2 |
720 721 722 723 724 725 726 |
} /* * Search the state->lock_states for an existing lock_owner * that is compatible with current->files */ static struct nfs4_lock_state * |
77041ed9b NFSv4: Ensure the... |
727 |
__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
728 729 730 |
{ struct nfs4_lock_state *pos; list_for_each_entry(pos, &state->lock_states, ls_locks) { |
77041ed9b NFSv4: Ensure the... |
731 |
if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type) |
1da177e4c Linux-2.6.12-rc2 |
732 |
continue; |
77041ed9b NFSv4: Ensure the... |
733 734 735 736 737 738 739 740 741 |
switch (pos->ls_owner.lo_type) { case NFS4_POSIX_LOCK_TYPE: if (pos->ls_owner.lo_u.posix_owner != fl_owner) continue; break; case NFS4_FLOCK_LOCK_TYPE: if (pos->ls_owner.lo_u.flock_owner != fl_pid) continue; } |
1da177e4c Linux-2.6.12-rc2 |
742 743 744 745 746 |
atomic_inc(&pos->ls_count); return pos; } return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
747 748 749 750 |
/* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. * |
1da177e4c Linux-2.6.12-rc2 |
751 |
*/ |
77041ed9b NFSv4: Ensure the... |
752 |
static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
753 754 |
{ struct nfs4_lock_state *lsp; |
24d292b89 NFS: Move cl_stat... |
755 756 |
struct nfs_server *server = state->owner->so_server; struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
757 |
|
8535b2be5 NFSv4: Don't use ... |
758 |
lsp = kzalloc(sizeof(*lsp), GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
759 760 |
if (lsp == NULL) return NULL; |
d0dc3701c NFSv4: Give the l... |
761 762 763 764 |
rpc_init_wait_queue(&lsp->ls_sequence.wait, "lock_seqid_waitqueue"); spin_lock_init(&lsp->ls_sequence.lock); INIT_LIST_HEAD(&lsp->ls_sequence.list); lsp->ls_seqid.sequence = &lsp->ls_sequence; |
1da177e4c Linux-2.6.12-rc2 |
765 |
atomic_set(&lsp->ls_count, 1); |
b64aec8d1 NFSv4: Fix an Oop... |
766 |
lsp->ls_state = state; |
77041ed9b NFSv4: Ensure the... |
767 768 769 770 771 772 773 774 775 776 777 778 |
lsp->ls_owner.lo_type = type; switch (lsp->ls_owner.lo_type) { case NFS4_FLOCK_LOCK_TYPE: lsp->ls_owner.lo_u.flock_owner = fl_pid; break; case NFS4_POSIX_LOCK_TYPE: lsp->ls_owner.lo_u.posix_owner = fl_owner; break; default: kfree(lsp); return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
779 |
spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
780 |
nfs_alloc_unique_id_locked(&server->lockowner_id, &lsp->ls_id, 1, 64); |
1da177e4c Linux-2.6.12-rc2 |
781 |
spin_unlock(&clp->cl_lock); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
782 |
INIT_LIST_HEAD(&lsp->ls_locks); |
1da177e4c Linux-2.6.12-rc2 |
783 784 |
return lsp; } |
9f958ab88 NFSv4: Reduce the... |
785 786 |
static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) { |
24d292b89 NFS: Move cl_stat... |
787 788 |
struct nfs_server *server = lsp->ls_state->owner->so_server; struct nfs_client *clp = server->nfs_client; |
9f958ab88 NFSv4: Reduce the... |
789 790 |
spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
791 |
nfs_free_unique_id(&server->lockowner_id, &lsp->ls_id); |
9f958ab88 NFSv4: Reduce the... |
792 |
spin_unlock(&clp->cl_lock); |
f6a1cc893 SUNRPC: Add a (em... |
793 |
rpc_destroy_wait_queue(&lsp->ls_sequence.wait); |
9f958ab88 NFSv4: Reduce the... |
794 795 |
kfree(lsp); } |
1da177e4c Linux-2.6.12-rc2 |
796 797 798 799 |
/* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. * |
1da177e4c Linux-2.6.12-rc2 |
800 |
*/ |
77041ed9b NFSv4: Ensure the... |
801 |
static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
802 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
803 |
struct nfs4_lock_state *lsp, *new = NULL; |
1da177e4c Linux-2.6.12-rc2 |
804 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
805 806 |
for(;;) { spin_lock(&state->state_lock); |
77041ed9b NFSv4: Ensure the... |
807 |
lsp = __nfs4_find_lock_state(state, owner, pid, type); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
808 809 810 |
if (lsp != NULL) break; if (new != NULL) { |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
811 812 813 814 815 816 817 |
list_add(&new->ls_locks, &state->lock_states); set_bit(LK_STATE_IN_USE, &state->flags); lsp = new; new = NULL; break; } spin_unlock(&state->state_lock); |
77041ed9b NFSv4: Ensure the... |
818 |
new = nfs4_alloc_lock_state(state, owner, pid, type); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
819 820 821 822 |
if (new == NULL) return NULL; } spin_unlock(&state->state_lock); |
9f958ab88 NFSv4: Reduce the... |
823 824 |
if (new != NULL) nfs4_free_lock_state(new); |
1da177e4c Linux-2.6.12-rc2 |
825 826 827 828 |
return lsp; } /* |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
829 830 |
* Release reference to lock_state, and free it if we see that * it is no longer in use |
1da177e4c Linux-2.6.12-rc2 |
831 |
*/ |
faf5f49c2 NFSv4: Make NFS c... |
832 |
void nfs4_put_lock_state(struct nfs4_lock_state *lsp) |
1da177e4c Linux-2.6.12-rc2 |
833 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
834 |
struct nfs4_state *state; |
1da177e4c Linux-2.6.12-rc2 |
835 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
836 837 838 839 840 841 842 843 844 |
if (lsp == NULL) return; state = lsp->ls_state; if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock)) return; list_del(&lsp->ls_locks); if (list_empty(&state->lock_states)) clear_bit(LK_STATE_IN_USE, &state->flags); spin_unlock(&state->state_lock); |
d3c7b7ccc NFSv4: Add suppor... |
845 846 |
if (lsp->ls_flags & NFS_LOCK_INITIALIZED) nfs4_release_lockowner(lsp); |
9f958ab88 NFSv4: Reduce the... |
847 |
nfs4_free_lock_state(lsp); |
1da177e4c Linux-2.6.12-rc2 |
848 |
} |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
849 |
static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src) |
1da177e4c Linux-2.6.12-rc2 |
850 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
851 |
struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner; |
1da177e4c Linux-2.6.12-rc2 |
852 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
853 854 855 |
dst->fl_u.nfs4_fl.owner = lsp; atomic_inc(&lsp->ls_count); } |
1da177e4c Linux-2.6.12-rc2 |
856 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
857 |
static void nfs4_fl_release_lock(struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
858 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
859 |
nfs4_put_lock_state(fl->fl_u.nfs4_fl.owner); |
1da177e4c Linux-2.6.12-rc2 |
860 |
} |
6aed62853 const: make file_... |
861 |
static const struct file_lock_operations nfs4_fl_lock_ops = { |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
862 863 864 865 866 |
.fl_copy_lock = nfs4_fl_copy_lock, .fl_release_private = nfs4_fl_release_lock, }; int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
867 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
868 869 870 871 |
struct nfs4_lock_state *lsp; if (fl->fl_ops != NULL) return 0; |
77041ed9b NFSv4: Ensure the... |
872 873 874 875 876 877 |
if (fl->fl_flags & FL_POSIX) lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE); else if (fl->fl_flags & FL_FLOCK) lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE); else return -EINVAL; |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
878 879 880 881 882 |
if (lsp == NULL) return -ENOMEM; fl->fl_u.nfs4_fl.owner = lsp; fl->fl_ops = &nfs4_fl_lock_ops; return 0; |
1da177e4c Linux-2.6.12-rc2 |
883 |
} |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
884 885 886 |
/* * Byte-range lock aware utility to initialize the stateid of read/write * requests. |
1da177e4c Linux-2.6.12-rc2 |
887 |
*/ |
77041ed9b NFSv4: Ensure the... |
888 |
void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid) |
1da177e4c Linux-2.6.12-rc2 |
889 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
890 |
struct nfs4_lock_state *lsp; |
8bda4e4c9 NFSv4: Fix up sta... |
891 |
int seq; |
1da177e4c Linux-2.6.12-rc2 |
892 |
|
8bda4e4c9 NFSv4: Fix up sta... |
893 894 895 896 |
do { seq = read_seqbegin(&state->seqlock); memcpy(dst, &state->stateid, sizeof(*dst)); } while (read_seqretry(&state->seqlock, seq)); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
897 898 |
if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) return; |
1da177e4c Linux-2.6.12-rc2 |
899 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
900 |
spin_lock(&state->state_lock); |
77041ed9b NFSv4: Ensure the... |
901 |
lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
902 903 904 |
if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); spin_unlock(&state->state_lock); |
1da177e4c Linux-2.6.12-rc2 |
905 906 |
nfs4_put_lock_state(lsp); } |
8535b2be5 NFSv4: Don't use ... |
907 |
struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) |
cee54fc94 NFSv4: Add functi... |
908 |
{ |
cee54fc94 NFSv4: Add functi... |
909 |
struct nfs_seqid *new; |
8535b2be5 NFSv4: Don't use ... |
910 |
new = kmalloc(sizeof(*new), gfp_mask); |
cee54fc94 NFSv4: Add functi... |
911 912 |
if (new != NULL) { new->sequence = counter; |
2f74c0a05 NFSv4: Clean up t... |
913 |
INIT_LIST_HEAD(&new->list); |
cee54fc94 NFSv4: Add functi... |
914 915 916 |
} return new; } |
72211dbe7 NFSv4: Release th... |
917 |
void nfs_release_seqid(struct nfs_seqid *seqid) |
1da177e4c Linux-2.6.12-rc2 |
918 |
{ |
2f74c0a05 NFSv4: Clean up t... |
919 920 |
if (!list_empty(&seqid->list)) { struct rpc_sequence *sequence = seqid->sequence->sequence; |
cee54fc94 NFSv4: Add functi... |
921 |
|
2f74c0a05 NFSv4: Clean up t... |
922 |
spin_lock(&sequence->lock); |
72211dbe7 NFSv4: Release th... |
923 |
list_del_init(&seqid->list); |
2f74c0a05 NFSv4: Clean up t... |
924 925 926 |
spin_unlock(&sequence->lock); rpc_wake_up(&sequence->wait); } |
72211dbe7 NFSv4: Release th... |
927 928 929 930 931 |
} void nfs_free_seqid(struct nfs_seqid *seqid) { nfs_release_seqid(seqid); |
cee54fc94 NFSv4: Add functi... |
932 |
kfree(seqid); |
1da177e4c Linux-2.6.12-rc2 |
933 934 935 |
} /* |
cee54fc94 NFSv4: Add functi... |
936 937 938 939 |
* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or * failed with a seqid incrementing error - * see comments nfs_fs.h:seqid_mutating_error() */ |
88d909399 NFSv4: nfs_increm... |
940 |
static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
cee54fc94 NFSv4: Add functi... |
941 |
{ |
2f74c0a05 NFSv4: Clean up t... |
942 |
BUG_ON(list_first_entry(&seqid->sequence->sequence->list, struct nfs_seqid, list) != seqid); |
cee54fc94 NFSv4: Add functi... |
943 944 945 946 |
switch (status) { case 0: break; case -NFS4ERR_BAD_SEQID: |
6f43ddccb NFSv4: Improve th... |
947 948 949 |
if (seqid->sequence->flags & NFS_SEQID_CONFIRMED) return; printk(KERN_WARNING "NFS: v4 server returned a bad" |
497799e7c NFS: missing spac... |
950 951 952 |
" sequence-id error on an" " unconfirmed sequence %p! ", |
6f43ddccb NFSv4: Improve th... |
953 |
seqid->sequence); |
cee54fc94 NFSv4: Add functi... |
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BADXDR: case -NFS4ERR_RESOURCE: case -NFS4ERR_NOFILEHANDLE: /* Non-seqid mutating errors */ return; }; /* * Note: no locking needed as we are guaranteed to be first * on the sequence list */ seqid->sequence->counter++; } void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) { |
34dc1ad75 nfs41: increment_... |
972 973 974 975 976 |
struct nfs4_state_owner *sp = container_of(seqid->sequence, struct nfs4_state_owner, so_seqid); struct nfs_server *server = sp->so_server; if (status == -NFS4ERR_BAD_SEQID) |
1da177e4c Linux-2.6.12-rc2 |
977 |
nfs4_drop_state_owner(sp); |
34dc1ad75 nfs41: increment_... |
978 979 |
if (!nfs4_has_session(server->nfs_client)) nfs_increment_seqid(status, seqid); |
cee54fc94 NFSv4: Add functi... |
980 981 982 |
} /* |
cee54fc94 NFSv4: Add functi... |
983 984 985 986 987 988 |
* Increment the seqid if the LOCK/LOCKU succeeded, or * failed with a seqid incrementing error - * see comments nfs_fs.h:seqid_mutating_error() */ void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) { |
88d909399 NFSv4: nfs_increm... |
989 |
nfs_increment_seqid(status, seqid); |
cee54fc94 NFSv4: Add functi... |
990 991 992 993 994 995 996 997 |
} int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) { struct rpc_sequence *sequence = seqid->sequence->sequence; int status = 0; spin_lock(&sequence->lock); |
2f74c0a05 NFSv4: Clean up t... |
998 999 1000 1001 |
if (list_empty(&seqid->list)) list_add_tail(&seqid->list, &sequence->list); if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid) goto unlock; |
5d00837b9 SUNRPC: Run rpc t... |
1002 |
rpc_sleep_on(&sequence->wait, task, NULL); |
2f74c0a05 NFSv4: Clean up t... |
1003 1004 |
status = -EAGAIN; unlock: |
cee54fc94 NFSv4: Add functi... |
1005 1006 |
spin_unlock(&sequence->lock); return status; |
1da177e4c Linux-2.6.12-rc2 |
1007 |
} |
e005e8041 NFSv4: Rename the... |
1008 |
static int nfs4_run_state_manager(void *); |
1da177e4c Linux-2.6.12-rc2 |
1009 |
|
e005e8041 NFSv4: Rename the... |
1010 |
static void nfs4_clear_state_manager_bit(struct nfs_client *clp) |
433fbe4c8 NFSv4: State reco... |
1011 1012 |
{ smp_mb__before_clear_bit(); |
e005e8041 NFSv4: Rename the... |
1013 |
clear_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); |
433fbe4c8 NFSv4: State reco... |
1014 |
smp_mb__after_clear_bit(); |
e005e8041 NFSv4: Rename the... |
1015 |
wake_up_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING); |
433fbe4c8 NFSv4: State reco... |
1016 1017 |
rpc_wake_up(&clp->cl_rpcwaitq); } |
1da177e4c Linux-2.6.12-rc2 |
1018 |
/* |
e005e8041 NFSv4: Rename the... |
1019 |
* Schedule the nfs_client asynchronous state management routine |
1da177e4c Linux-2.6.12-rc2 |
1020 |
*/ |
b0d3ded1a NFSv4: Clean up n... |
1021 |
void nfs4_schedule_state_manager(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
1022 |
{ |
5043e900f NFS: Convert inst... |
1023 |
struct task_struct *task; |
1da177e4c Linux-2.6.12-rc2 |
1024 |
|
e005e8041 NFSv4: Rename the... |
1025 1026 |
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) return; |
5043e900f NFS: Convert inst... |
1027 1028 |
__module_get(THIS_MODULE); atomic_inc(&clp->cl_count); |
e005e8041 NFSv4: Rename the... |
1029 |
task = kthread_run(nfs4_run_state_manager, clp, "%s-manager", |
5d8515cae NFS: eliminate NI... |
1030 1031 |
rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); |
5043e900f NFS: Convert inst... |
1032 1033 |
if (!IS_ERR(task)) return; |
e005e8041 NFSv4: Rename the... |
1034 |
nfs4_clear_state_manager_bit(clp); |
24c8dbbb5 NFS: Generalise t... |
1035 |
nfs_put_client(clp); |
5043e900f NFS: Convert inst... |
1036 |
module_put(THIS_MODULE); |
1da177e4c Linux-2.6.12-rc2 |
1037 1038 1039 |
} /* |
0400a6b0c NFSv4/4.1: Fix nf... |
1040 |
* Schedule a lease recovery attempt |
1da177e4c Linux-2.6.12-rc2 |
1041 |
*/ |
0400a6b0c NFSv4/4.1: Fix nf... |
1042 |
void nfs4_schedule_lease_recovery(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
1043 1044 1045 |
{ if (!clp) return; |
e598d843c NFSv4: Remove red... |
1046 1047 |
if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
e005e8041 NFSv4: Rename the... |
1048 |
nfs4_schedule_state_manager(clp); |
1da177e4c Linux-2.6.12-rc2 |
1049 |
} |
042b60beb NFSv4: renewd nee... |
1050 1051 1052 1053 1054 |
void nfs4_schedule_path_down_recovery(struct nfs_client *clp) { nfs_handle_cb_pathdown(clp); nfs4_schedule_state_manager(clp); } |
f9feab1e1 NFSv4: nfs4_state... |
1055 |
static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) |
b79a4a1b4 NFSv4: Fix state ... |
1056 1057 1058 1059 1060 1061 1062 1063 |
{ set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); /* Don't recover state that expired before the reboot */ if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags)) { clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); return 0; } |
7eff03aec NFSv4: Add a reco... |
1064 |
set_bit(NFS_OWNER_RECLAIM_REBOOT, &state->owner->so_flags); |
b79a4a1b4 NFSv4: Fix state ... |
1065 1066 1067 |
set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); return 1; } |
f9feab1e1 NFSv4: nfs4_state... |
1068 |
static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) |
b79a4a1b4 NFSv4: Fix state ... |
1069 1070 1071 |
{ set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); |
7eff03aec NFSv4: Add a reco... |
1072 |
set_bit(NFS_OWNER_RECLAIM_NOGRACE, &state->owner->so_flags); |
b79a4a1b4 NFSv4: Fix state ... |
1073 1074 1075 |
set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); return 1; } |
0400a6b0c NFSv4/4.1: Fix nf... |
1076 1077 1078 1079 1080 1081 1082 |
void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) { struct nfs_client *clp = server->nfs_client; nfs4_state_mark_reclaim_nograce(clp, state); nfs4_schedule_state_manager(clp); } |
028600143 NFSv4: Clean up f... |
1083 |
static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
1084 1085 |
{ struct inode *inode = state->inode; |
19e03c570 NFSv4: Ensure tha... |
1086 |
struct nfs_inode *nfsi = NFS_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
1087 1088 |
struct file_lock *fl; int status = 0; |
3f09df70e NFS: Ensure we al... |
1089 1090 1091 1092 |
if (inode->i_flock == NULL) return 0; /* Guard against delegation returns and new lock/unlock calls */ |
19e03c570 NFSv4: Ensure tha... |
1093 |
down_write(&nfsi->rwsem); |
3f09df70e NFS: Ensure we al... |
1094 |
/* Protect inode->i_flock using the BKL */ |
b89f43213 fs/locks.c: prepa... |
1095 |
lock_flocks(); |
90dc7d279 nfs: fix sparse w... |
1096 |
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
43b2a33aa NFSv4: Fix recove... |
1097 |
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
1da177e4c Linux-2.6.12-rc2 |
1098 |
continue; |
cd3758e37 NFS: Replace file... |
1099 |
if (nfs_file_open_context(fl->fl_file)->state != state) |
1da177e4c Linux-2.6.12-rc2 |
1100 |
continue; |
b89f43213 fs/locks.c: prepa... |
1101 |
unlock_flocks(); |
1da177e4c Linux-2.6.12-rc2 |
1102 |
status = ops->recover_lock(state, fl); |
1da177e4c Linux-2.6.12-rc2 |
1103 |
switch (status) { |
965b5d679 NFSv4: Handle mor... |
1104 1105 1106 1107 1108 1109 1110 1111 1112 |
case 0: break; case -ESTALE: case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_EXPIRED: case -NFS4ERR_NO_GRACE: case -NFS4ERR_STALE_CLIENTID: |
9c4c761a6 NFSv4.1: Handle N... |
1113 1114 1115 1116 |
case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
965b5d679 NFSv4: Handle mor... |
1117 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1118 1119 1120 |
default: printk(KERN_ERR "%s: unhandled error %d. Zeroing state ", |
3110ff804 nfs: replace rema... |
1121 |
__func__, status); |
965b5d679 NFSv4: Handle mor... |
1122 1123 |
case -ENOMEM: case -NFS4ERR_DENIED: |
1da177e4c Linux-2.6.12-rc2 |
1124 1125 |
case -NFS4ERR_RECLAIM_BAD: case -NFS4ERR_RECLAIM_CONFLICT: |
43b2a33aa NFSv4: Fix recove... |
1126 |
/* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
965b5d679 NFSv4: Handle mor... |
1127 |
status = 0; |
1da177e4c Linux-2.6.12-rc2 |
1128 |
} |
b89f43213 fs/locks.c: prepa... |
1129 |
lock_flocks(); |
1da177e4c Linux-2.6.12-rc2 |
1130 |
} |
b89f43213 fs/locks.c: prepa... |
1131 |
unlock_flocks(); |
965b5d679 NFSv4: Handle mor... |
1132 |
out: |
19e03c570 NFSv4: Ensure tha... |
1133 |
up_write(&nfsi->rwsem); |
1da177e4c Linux-2.6.12-rc2 |
1134 1135 |
return status; } |
028600143 NFSv4: Clean up f... |
1136 |
static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs4_state_recovery_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 |
{ struct nfs4_state *state; struct nfs4_lock_state *lock; int status = 0; /* Note: we rely on the sp->so_states list being ordered * so that we always reclaim open(O_RDWR) and/or open(O_WRITE) * states first. * This is needed to ensure that the server won't give us any * read delegations that we have to return if, say, we are * recovering after a network partition or a reboot from a * server that doesn't support a grace period. */ |
fe1d81952 NFSv4: Ensure tha... |
1150 1151 |
restart: spin_lock(&sp->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
1152 |
list_for_each_entry(state, &sp->so_states, open_states) { |
b79a4a1b4 NFSv4: Fix state ... |
1153 1154 |
if (!test_and_clear_bit(ops->state_flag_bit, &state->flags)) continue; |
1da177e4c Linux-2.6.12-rc2 |
1155 1156 |
if (state->state == 0) continue; |
fe1d81952 NFSv4: Ensure tha... |
1157 1158 |
atomic_inc(&state->count); spin_unlock(&sp->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
1159 |
status = ops->recover_open(sp, state); |
1da177e4c Linux-2.6.12-rc2 |
1160 |
if (status >= 0) { |
028600143 NFSv4: Clean up f... |
1161 1162 |
status = nfs4_reclaim_locks(state, ops); if (status >= 0) { |
4b44b40e0 NFSv4: Ensure cor... |
1163 |
spin_lock(&state->state_lock); |
028600143 NFSv4: Clean up f... |
1164 1165 1166 1167 |
list_for_each_entry(lock, &state->lock_states, ls_locks) { if (!(lock->ls_flags & NFS_LOCK_INITIALIZED)) printk("%s: Lock reclaim failed! ", |
3110ff804 nfs: replace rema... |
1168 |
__func__); |
028600143 NFSv4: Clean up f... |
1169 |
} |
4b44b40e0 NFSv4: Ensure cor... |
1170 |
spin_unlock(&state->state_lock); |
fe1d81952 NFSv4: Ensure tha... |
1171 1172 |
nfs4_put_open_state(state); goto restart; |
1da177e4c Linux-2.6.12-rc2 |
1173 |
} |
1da177e4c Linux-2.6.12-rc2 |
1174 1175 1176 1177 1178 |
} switch (status) { default: printk(KERN_ERR "%s: unhandled error %d. Zeroing state ", |
3110ff804 nfs: replace rema... |
1179 |
__func__, status); |
1da177e4c Linux-2.6.12-rc2 |
1180 |
case -ENOENT: |
965b5d679 NFSv4: Handle mor... |
1181 |
case -ENOMEM: |
b79a4a1b4 NFSv4: Fix state ... |
1182 |
case -ESTALE: |
1da177e4c Linux-2.6.12-rc2 |
1183 1184 1185 1186 1187 1188 1189 1190 1191 |
/* * Open state on this file cannot be recovered * All we can do is revert to using the zero stateid. */ memset(state->stateid.data, 0, sizeof(state->stateid.data)); /* Mark the file as being 'closed' */ state->state = 0; break; |
168667c43 NFSv4: The state ... |
1192 1193 1194 1195 1196 1197 1198 1199 |
case -EKEYEXPIRED: /* * User RPCSEC_GSS context has expired. * We cannot recover this stateid now, so * skip it and allow recovery thread to * proceed. */ break; |
965b5d679 NFSv4: Handle mor... |
1200 1201 1202 |
case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_BAD_STATEID: |
b79a4a1b4 NFSv4: Fix state ... |
1203 1204 |
case -NFS4ERR_RECLAIM_BAD: case -NFS4ERR_RECLAIM_CONFLICT: |
1f0e890db NFSv4: Clean up s... |
1205 |
nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
b79a4a1b4 NFSv4: Fix state ... |
1206 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1207 1208 |
case -NFS4ERR_EXPIRED: case -NFS4ERR_NO_GRACE: |
1f0e890db NFSv4: Clean up s... |
1209 |
nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
1da177e4c Linux-2.6.12-rc2 |
1210 |
case -NFS4ERR_STALE_CLIENTID: |
9c4c761a6 NFSv4.1: Handle N... |
1211 1212 1213 1214 |
case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
1da177e4c Linux-2.6.12-rc2 |
1215 1216 |
goto out_err; } |
fe1d81952 NFSv4: Ensure tha... |
1217 1218 |
nfs4_put_open_state(state); goto restart; |
1da177e4c Linux-2.6.12-rc2 |
1219 |
} |
fe1d81952 NFSv4: Ensure tha... |
1220 |
spin_unlock(&sp->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
1221 1222 |
return 0; out_err: |
fe1d81952 NFSv4: Ensure tha... |
1223 |
nfs4_put_open_state(state); |
1da177e4c Linux-2.6.12-rc2 |
1224 1225 |
return status; } |
b79a4a1b4 NFSv4: Fix state ... |
1226 1227 1228 1229 1230 1231 1232 1233 |
static void nfs4_clear_open_state(struct nfs4_state *state) { struct nfs4_lock_state *lock; clear_bit(NFS_DELEGATED_STATE, &state->flags); clear_bit(NFS_O_RDONLY_STATE, &state->flags); clear_bit(NFS_O_WRONLY_STATE, &state->flags); clear_bit(NFS_O_RDWR_STATE, &state->flags); |
4b44b40e0 NFSv4: Ensure cor... |
1234 |
spin_lock(&state->state_lock); |
b79a4a1b4 NFSv4: Fix state ... |
1235 |
list_for_each_entry(lock, &state->lock_states, ls_locks) { |
b79a4a1b4 NFSv4: Fix state ... |
1236 1237 1238 |
lock->ls_seqid.flags = 0; lock->ls_flags &= ~NFS_LOCK_INITIALIZED; } |
4b44b40e0 NFSv4: Ensure cor... |
1239 |
spin_unlock(&state->state_lock); |
b79a4a1b4 NFSv4: Fix state ... |
1240 |
} |
24d292b89 NFS: Move cl_stat... |
1241 1242 |
static void nfs4_reset_seqids(struct nfs_server *server, int (*mark_reclaim)(struct nfs_client *clp, struct nfs4_state *state)) |
cee54fc94 NFSv4: Add functi... |
1243 |
{ |
24d292b89 NFS: Move cl_stat... |
1244 |
struct nfs_client *clp = server->nfs_client; |
cee54fc94 NFSv4: Add functi... |
1245 |
struct nfs4_state_owner *sp; |
9f958ab88 NFSv4: Reduce the... |
1246 |
struct rb_node *pos; |
cee54fc94 NFSv4: Add functi... |
1247 |
struct nfs4_state *state; |
cee54fc94 NFSv4: Add functi... |
1248 |
|
24d292b89 NFS: Move cl_stat... |
1249 1250 1251 1252 1253 |
spin_lock(&clp->cl_lock); for (pos = rb_first(&server->state_owners); pos != NULL; pos = rb_next(pos)) { sp = rb_entry(pos, struct nfs4_state_owner, so_server_node); |
cee54fc94 NFSv4: Add functi... |
1254 |
sp->so_seqid.flags = 0; |
ec0734282 NFSv4: Fix up loc... |
1255 |
spin_lock(&sp->so_lock); |
cee54fc94 NFSv4: Add functi... |
1256 |
list_for_each_entry(state, &sp->so_states, open_states) { |
b79a4a1b4 NFSv4: Fix state ... |
1257 1258 |
if (mark_reclaim(clp, state)) nfs4_clear_open_state(state); |
cee54fc94 NFSv4: Add functi... |
1259 |
} |
ec0734282 NFSv4: Fix up loc... |
1260 |
spin_unlock(&sp->so_lock); |
cee54fc94 NFSv4: Add functi... |
1261 |
} |
24d292b89 NFS: Move cl_stat... |
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 |
spin_unlock(&clp->cl_lock); } static void nfs4_state_mark_reclaim_helper(struct nfs_client *clp, int (*mark_reclaim)(struct nfs_client *clp, struct nfs4_state *state)) { struct nfs_server *server; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) nfs4_reset_seqids(server, mark_reclaim); rcu_read_unlock(); |
cee54fc94 NFSv4: Add functi... |
1274 |
} |
b79a4a1b4 NFSv4: Fix state ... |
1275 1276 1277 1278 1279 1280 |
static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp) { /* Mark all delegations for reclaim */ nfs_delegation_mark_reclaim(clp); nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot); } |
fce5c838e nfs41: RECLAIM_CO... |
1281 1282 1283 1284 1285 1286 1287 |
static void nfs4_reclaim_complete(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) { /* Notify the server we're done reclaiming our state */ if (ops->reclaim_complete) (void)ops->reclaim_complete(clp); } |
24d292b89 NFS: Move cl_stat... |
1288 |
static void nfs4_clear_reclaim_server(struct nfs_server *server) |
b79a4a1b4 NFSv4: Fix state ... |
1289 |
{ |
24d292b89 NFS: Move cl_stat... |
1290 |
struct nfs_client *clp = server->nfs_client; |
b79a4a1b4 NFSv4: Fix state ... |
1291 1292 1293 |
struct nfs4_state_owner *sp; struct rb_node *pos; struct nfs4_state *state; |
24d292b89 NFS: Move cl_stat... |
1294 1295 1296 1297 1298 |
spin_lock(&clp->cl_lock); for (pos = rb_first(&server->state_owners); pos != NULL; pos = rb_next(pos)) { sp = rb_entry(pos, struct nfs4_state_owner, so_server_node); |
b79a4a1b4 NFSv4: Fix state ... |
1299 1300 |
spin_lock(&sp->so_lock); list_for_each_entry(state, &sp->so_states, open_states) { |
24d292b89 NFS: Move cl_stat... |
1301 1302 |
if (!test_and_clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags)) |
b79a4a1b4 NFSv4: Fix state ... |
1303 1304 1305 1306 1307 |
continue; nfs4_state_mark_reclaim_nograce(clp, state); } spin_unlock(&sp->so_lock); } |
24d292b89 NFS: Move cl_stat... |
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 |
spin_unlock(&clp->cl_lock); } static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp) { struct nfs_server *server; if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) return 0; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) nfs4_clear_reclaim_server(server); rcu_read_unlock(); |
b79a4a1b4 NFSv4: Fix state ... |
1322 1323 |
nfs_delegation_reap_unclaimed(clp); |
6eaa61496 NFSv4: Don't call... |
1324 1325 1326 1327 1328 1329 1330 1331 |
return 1; } static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) { if (!nfs4_state_clear_reclaim_reboot(clp)) return; nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); |
b79a4a1b4 NFSv4: Fix state ... |
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 |
} static void nfs_delegation_clear_all(struct nfs_client *clp) { nfs_delegation_mark_reclaim(clp); nfs_delegation_reap_unclaimed(clp); } static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) { nfs_delegation_clear_all(clp); nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); } |
168667c43 NFSv4: The state ... |
1345 1346 1347 1348 1349 1350 1351 1352 |
static void nfs4_warn_keyexpired(const char *s) { printk_ratelimited(KERN_WARNING "Error: state manager" " encountered RPCSEC_GSS session" " expired against NFSv4 server %s. ", s); } |
4f7cdf18e NFSv4: The state ... |
1353 |
static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) |
e598d843c NFSv4: Remove red... |
1354 1355 |
{ switch (error) { |
4f38e4aad NFSv4: Don't erro... |
1356 1357 |
case 0: break; |
e598d843c NFSv4: Remove red... |
1358 |
case -NFS4ERR_CB_PATH_DOWN: |
707fb4b32 NFSv4: Clean up N... |
1359 |
nfs_handle_cb_pathdown(clp); |
4f38e4aad NFSv4: Don't erro... |
1360 |
break; |
c8b7ae3d3 NFSv4: Ensure the... |
1361 1362 |
case -NFS4ERR_NO_GRACE: nfs4_state_end_reclaim_reboot(clp); |
4f38e4aad NFSv4: Don't erro... |
1363 |
break; |
e598d843c NFSv4: Remove red... |
1364 1365 1366 |
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_LEASE_MOVED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
6eaa61496 NFSv4: Don't call... |
1367 |
nfs4_state_clear_reclaim_reboot(clp); |
e598d843c NFSv4: Remove red... |
1368 1369 1370 1371 1372 |
nfs4_state_start_reclaim_reboot(clp); break; case -NFS4ERR_EXPIRED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs4_state_start_reclaim_nograce(clp); |
8ba9bf8e5 nfs41: fix switch... |
1373 |
break; |
c3fad1b1a nfs41: add sessio... |
1374 1375 1376 1377 1378 1379 1380 |
case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_DEADSESSION: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: case -NFS4ERR_SEQ_FALSE_RETRY: case -NFS4ERR_SEQ_MISORDERED: |
6df08189f nfs41: rename cl_... |
1381 |
set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
0b9e2d41f nfs41: only state... |
1382 |
/* Zero session reset errors */ |
4f38e4aad NFSv4: Don't erro... |
1383 |
break; |
168667c43 NFSv4: The state ... |
1384 1385 1386 |
case -EKEYEXPIRED: /* Nothing we can do */ nfs4_warn_keyexpired(clp->cl_hostname); |
4f38e4aad NFSv4: Don't erro... |
1387 1388 1389 |
break; default: return error; |
e598d843c NFSv4: Remove red... |
1390 |
} |
4f38e4aad NFSv4: Don't erro... |
1391 |
return 0; |
e598d843c NFSv4: Remove red... |
1392 |
} |
028600143 NFSv4: Clean up f... |
1393 |
static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
1394 |
{ |
24d292b89 NFS: Move cl_stat... |
1395 1396 |
struct nfs4_state_owner *sp; struct nfs_server *server; |
9f958ab88 NFSv4: Reduce the... |
1397 |
struct rb_node *pos; |
1da177e4c Linux-2.6.12-rc2 |
1398 |
int status = 0; |
7eff03aec NFSv4: Add a reco... |
1399 |
restart: |
24d292b89 NFS: Move cl_stat... |
1400 1401 |
rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
0aaaf5c42 NFS: Cache state ... |
1402 |
nfs4_purge_state_owners(server); |
24d292b89 NFS: Move cl_stat... |
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 |
spin_lock(&clp->cl_lock); for (pos = rb_first(&server->state_owners); pos != NULL; pos = rb_next(pos)) { sp = rb_entry(pos, struct nfs4_state_owner, so_server_node); if (!test_and_clear_bit(ops->owner_flag_bit, &sp->so_flags)) continue; atomic_inc(&sp->so_count); spin_unlock(&clp->cl_lock); rcu_read_unlock(); status = nfs4_reclaim_open_state(sp, ops); if (status < 0) { set_bit(ops->owner_flag_bit, &sp->so_flags); nfs4_put_state_owner(sp); return nfs4_recovery_handle_error(clp, status); } |
7eff03aec NFSv4: Add a reco... |
1422 |
nfs4_put_state_owner(sp); |
24d292b89 NFS: Move cl_stat... |
1423 |
goto restart; |
7eff03aec NFSv4: Add a reco... |
1424 |
} |
24d292b89 NFS: Move cl_stat... |
1425 |
spin_unlock(&clp->cl_lock); |
028600143 NFSv4: Clean up f... |
1426 |
} |
24d292b89 NFS: Move cl_stat... |
1427 |
rcu_read_unlock(); |
028600143 NFSv4: Clean up f... |
1428 1429 1430 1431 1432 1433 |
return status; } static int nfs4_check_lease(struct nfs_client *clp) { struct rpc_cred *cred; |
c48f4f354 NFSv41: Convert t... |
1434 1435 |
const struct nfs4_state_maintenance_ops *ops = clp->cl_mvops->state_renewal_ops; |
4f38e4aad NFSv4: Don't erro... |
1436 |
int status; |
1da177e4c Linux-2.6.12-rc2 |
1437 |
|
0f605b560 NFSv4: Don't tell... |
1438 1439 1440 |
/* Is the client already known to have an expired lease? */ if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) return 0; |
a7b721037 nfs41: introduce ... |
1441 1442 1443 |
spin_lock(&clp->cl_lock); cred = ops->get_state_renewal_cred_locked(clp); spin_unlock(&clp->cl_lock); |
0f605b560 NFSv4: Don't tell... |
1444 1445 |
if (cred == NULL) { cred = nfs4_get_setclientid_cred(clp); |
4f38e4aad NFSv4: Don't erro... |
1446 |
status = -ENOKEY; |
0f605b560 NFSv4: Don't tell... |
1447 1448 |
if (cred == NULL) goto out; |
286d7d6a0 NFSv4: Remove req... |
1449 |
} |
8e69514f2 nfs41: support mi... |
1450 |
status = ops->renew_lease(clp, cred); |
0f605b560 NFSv4: Don't tell... |
1451 1452 |
put_rpccred(cred); out: |
4f7cdf18e NFSv4: The state ... |
1453 |
return nfs4_recovery_handle_error(clp, status); |
028600143 NFSv4: Clean up f... |
1454 1455 1456 1457 1458 |
} static int nfs4_reclaim_lease(struct nfs_client *clp) { struct rpc_cred *cred; |
c48f4f354 NFSv41: Convert t... |
1459 1460 |
const struct nfs4_state_recovery_ops *ops = clp->cl_mvops->reboot_recovery_ops; |
028600143 NFSv4: Clean up f... |
1461 |
int status = -ENOENT; |
90a16617e nfs41: add a get_... |
1462 |
cred = ops->get_clid_cred(clp); |
286d7d6a0 NFSv4: Remove req... |
1463 |
if (cred != NULL) { |
591d71cbd nfs41: establish ... |
1464 |
status = ops->establish_clid(clp, cred); |
286d7d6a0 NFSv4: Remove req... |
1465 |
put_rpccred(cred); |
a2b2bb882 NFSv4: Attempt to... |
1466 1467 1468 |
/* Handle case where the user hasn't set up machine creds */ if (status == -EACCES && cred == clp->cl_machine_cred) { nfs4_clear_machine_cred(clp); |
028600143 NFSv4: Clean up f... |
1469 |
status = -EAGAIN; |
a2b2bb882 NFSv4: Attempt to... |
1470 |
} |
c2e713dd8 nfs41: translate ... |
1471 1472 |
if (status == -NFS4ERR_MINOR_VERS_MISMATCH) status = -EPROTONOSUPPORT; |
286d7d6a0 NFSv4: Remove req... |
1473 |
} |
028600143 NFSv4: Clean up f... |
1474 1475 |
return status; } |
76db6d950 nfs41: add sessio... |
1476 |
#ifdef CONFIG_NFS_V4_1 |
0400a6b0c NFSv4/4.1: Fix nf... |
1477 1478 |
void nfs4_schedule_session_recovery(struct nfs4_session *session) { |
444f72fe7 NFSv4.1: Fix the ... |
1479 1480 1481 1482 |
struct nfs_client *clp = session->clp; set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); nfs4_schedule_lease_recovery(clp); |
0400a6b0c NFSv4/4.1: Fix nf... |
1483 |
} |
cbdabc7f8 NFSv4.1: filelayo... |
1484 |
EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); |
0400a6b0c NFSv4/4.1: Fix nf... |
1485 |
|
b9efa1b27 nfs41: implement ... |
1486 1487 1488 |
void nfs41_handle_recall_slot(struct nfs_client *clp) { set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); |
0400a6b0c NFSv4/4.1: Fix nf... |
1489 |
nfs4_schedule_state_manager(clp); |
b9efa1b27 nfs41: implement ... |
1490 |
} |
0f79fd6f5 NFSv4.1: Various ... |
1491 1492 1493 1494 1495 |
static void nfs4_reset_all_state(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { clp->cl_boot_time = CURRENT_TIME; nfs4_state_start_reclaim_nograce(clp); |
0400a6b0c NFSv4/4.1: Fix nf... |
1496 |
nfs4_schedule_state_manager(clp); |
0f79fd6f5 NFSv4.1: Various ... |
1497 1498 1499 1500 1501 1502 1503 |
} } static void nfs41_handle_server_reboot(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { nfs4_state_start_reclaim_reboot(clp); |
0400a6b0c NFSv4/4.1: Fix nf... |
1504 |
nfs4_schedule_state_manager(clp); |
0f79fd6f5 NFSv4.1: Various ... |
1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 |
} } static void nfs41_handle_state_revoked(struct nfs_client *clp) { /* Temporary */ nfs4_reset_all_state(clp); } static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp) { /* This will need to handle layouts too */ nfs_expire_all_delegations(clp); } static void nfs41_handle_cb_path_down(struct nfs_client *clp) { nfs_expire_all_delegations(clp); if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) |
0400a6b0c NFSv4/4.1: Fix nf... |
1524 |
nfs4_schedule_state_manager(clp); |
0f79fd6f5 NFSv4.1: Various ... |
1525 |
} |
0629e370d nfs41: check SEQU... |
1526 1527 1528 1529 |
void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) { if (!flags) return; |
111d489f0 NFSv4.1: Ensure t... |
1530 |
if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) |
0f79fd6f5 NFSv4.1: Various ... |
1531 |
nfs41_handle_server_reboot(clp); |
111d489f0 NFSv4.1: Ensure t... |
1532 |
if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | |
0629e370d nfs41: check SEQU... |
1533 1534 |
SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | SEQ4_STATUS_ADMIN_STATE_REVOKED | |
0f79fd6f5 NFSv4.1: Various ... |
1535 1536 |
SEQ4_STATUS_LEASE_MOVED)) nfs41_handle_state_revoked(clp); |
111d489f0 NFSv4.1: Ensure t... |
1537 |
if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) |
0f79fd6f5 NFSv4.1: Various ... |
1538 |
nfs41_handle_recallable_state_revoked(clp); |
111d489f0 NFSv4.1: Ensure t... |
1539 |
if (flags & (SEQ4_STATUS_CB_PATH_DOWN | |
0629e370d nfs41: check SEQU... |
1540 1541 |
SEQ4_STATUS_BACKCHANNEL_FAULT | SEQ4_STATUS_CB_PATH_DOWN_SESSION)) |
0f79fd6f5 NFSv4.1: Various ... |
1542 |
nfs41_handle_cb_path_down(clp); |
0629e370d nfs41: check SEQU... |
1543 |
} |
c3fad1b1a nfs41: add sessio... |
1544 1545 1546 |
static int nfs4_reset_session(struct nfs_client *clp) { int status; |
380454126 NFSv4: Fix a regr... |
1547 |
nfs4_begin_drain_session(clp); |
c3fad1b1a nfs41: add sessio... |
1548 1549 1550 |
status = nfs4_proc_destroy_session(clp->cl_session); if (status && status != -NFS4ERR_BADSESSION && status != -NFS4ERR_DEADSESSION) { |
f455848a1 nfs41: Mark state... |
1551 |
status = nfs4_recovery_handle_error(clp, status); |
c3fad1b1a nfs41: add sessio... |
1552 1553 1554 1555 |
goto out; } memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); |
f26468fb9 NFSv41: Fix nfs4_... |
1556 |
status = nfs4_proc_create_session(clp); |
41f54a554 nfs41: clear NFS4... |
1557 |
if (status) { |
f455848a1 nfs41: Mark state... |
1558 |
status = nfs4_recovery_handle_error(clp, status); |
41f54a554 nfs41: clear NFS4... |
1559 1560 |
goto out; } |
444f72fe7 NFSv4.1: Fix the ... |
1561 |
clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
41f54a554 nfs41: clear NFS4... |
1562 1563 |
/* create_session negotiated new slot table */ clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); |
9dfdf404c nfs41: Don't clea... |
1564 |
|
41f54a554 nfs41: clear NFS4... |
1565 1566 |
/* Let the state manager reestablish state */ if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
5601a00d6 nfs: run state ma... |
1567 |
nfs41_setup_state_renewal(clp); |
41f54a554 nfs41: clear NFS4... |
1568 |
out: |
c3fad1b1a nfs41: add sessio... |
1569 1570 |
return status; } |
76db6d950 nfs41: add sessio... |
1571 |
|
b9efa1b27 nfs41: implement ... |
1572 1573 1574 1575 1576 1577 1578 1579 1580 |
static int nfs4_recall_slot(struct nfs_client *clp) { struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table; struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs; struct nfs4_slot *new, *old; int i; nfs4_begin_drain_session(clp); new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), |
8535b2be5 NFSv4: Don't use ... |
1581 |
GFP_NOFS); |
b9efa1b27 nfs41: implement ... |
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 |
if (!new) return -ENOMEM; spin_lock(&fc_tbl->slot_tbl_lock); for (i = 0; i < fc_tbl->target_max_slots; i++) new[i].seq_nr = fc_tbl->slots[i].seq_nr; old = fc_tbl->slots; fc_tbl->slots = new; fc_tbl->max_slots = fc_tbl->target_max_slots; fc_tbl->target_max_slots = 0; fc_attrs->max_reqs = fc_tbl->max_slots; spin_unlock(&fc_tbl->slot_tbl_lock); kfree(old); nfs4_end_drain_session(clp); return 0; } |
76db6d950 nfs41: add sessio... |
1599 |
#else /* CONFIG_NFS_V4_1 */ |
c3fad1b1a nfs41: add sessio... |
1600 |
static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
5601a00d6 nfs: run state ma... |
1601 |
static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } |
b9efa1b27 nfs41: implement ... |
1602 |
static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } |
76db6d950 nfs41: add sessio... |
1603 |
#endif /* CONFIG_NFS_V4_1 */ |
78722e9c9 nfs41: only retry... |
1604 1605 1606 1607 1608 |
/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors * on EXCHANGE_ID for v4.1 */ static void nfs4_set_lease_expired(struct nfs_client *clp, int status) { |
fd954ae12 NFSv4.1: Don't lo... |
1609 1610 1611 1612 1613 1614 |
switch (status) { case -NFS4ERR_CLID_INUSE: case -NFS4ERR_STALE_CLIENTID: clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); break; case -NFS4ERR_DELAY: |
1bd714f2a NFSv4: Ensure tha... |
1615 |
case -ETIMEDOUT: |
fd954ae12 NFSv4.1: Don't lo... |
1616 1617 1618 |
case -EAGAIN: ssleep(1); break; |
78722e9c9 nfs41: only retry... |
1619 |
|
fd954ae12 NFSv4.1: Don't lo... |
1620 1621 1622 1623 1624 1625 |
case -EKEYEXPIRED: nfs4_warn_keyexpired(clp->cl_hostname); case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery * in nfs4_exchange_id */ default: return; |
78722e9c9 nfs41: only retry... |
1626 1627 1628 |
} set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); } |
e005e8041 NFSv4: Rename the... |
1629 |
static void nfs4_state_manager(struct nfs_client *clp) |
028600143 NFSv4: Clean up f... |
1630 |
{ |
028600143 NFSv4: Clean up f... |
1631 |
int status = 0; |
028600143 NFSv4: Clean up f... |
1632 |
/* Ensure exclusive access to NFSv4 state */ |
47c2199b6 NFSv4.1: Ensure s... |
1633 |
do { |
b79a4a1b4 NFSv4: Fix state ... |
1634 1635 1636 1637 |
if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { /* We're going to have to re-establish a clientid */ status = nfs4_reclaim_lease(clp); if (status) { |
78722e9c9 nfs41: only retry... |
1638 |
nfs4_set_lease_expired(clp, status); |
b6d408ba8 NFSv4: Fix up err... |
1639 1640 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
b79a4a1b4 NFSv4: Fix state ... |
1641 |
continue; |
76db6d950 nfs41: add sessio... |
1642 1643 1644 |
if (clp->cl_cons_state == NFS_CS_SESSION_INITING) nfs_mark_client_ready(clp, status); |
b79a4a1b4 NFSv4: Fix state ... |
1645 1646 |
goto out_error; } |
e598d843c NFSv4: Remove red... |
1647 |
clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
78fe0f41d NFS: use scope fr... |
1648 1649 1650 1651 1652 1653 1654 |
if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state)) nfs4_state_start_reclaim_nograce(clp); else set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); |
974cec8ca NFS: client needs... |
1655 |
pnfs_destroy_all_layouts(clp); |
e598d843c NFSv4: Remove red... |
1656 1657 1658 1659 |
} if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { status = nfs4_check_lease(clp); |
4f38e4aad NFSv4: Don't erro... |
1660 1661 |
if (status < 0) goto out_error; |
b6d408ba8 NFSv4: Fix up err... |
1662 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
e598d843c NFSv4: Remove red... |
1663 |
continue; |
b79a4a1b4 NFSv4: Fix state ... |
1664 |
} |
b6d408ba8 NFSv4: Fix up err... |
1665 |
|
c3fad1b1a nfs41: add sessio... |
1666 |
/* Initialize or reset the session */ |
6df08189f nfs41: rename cl_... |
1667 |
if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) |
7111dc739 NFSv4: Fix an inf... |
1668 |
&& nfs4_has_session(clp)) { |
4d643d1df nfs41: add create... |
1669 |
status = nfs4_reset_session(clp); |
b6d408ba8 NFSv4: Fix up err... |
1670 1671 1672 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) continue; if (status < 0) |
76db6d950 nfs41: add sessio... |
1673 |
goto out_error; |
76db6d950 nfs41: add sessio... |
1674 |
} |
b6d408ba8 NFSv4: Fix up err... |
1675 |
|
b79a4a1b4 NFSv4: Fix state ... |
1676 |
/* First recover reboot state... */ |
e345e88a7 NFSv4: Fix up the... |
1677 |
if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
591d71cbd nfs41: establish ... |
1678 |
status = nfs4_do_reclaim(clp, |
c48f4f354 NFSv41: Convert t... |
1679 |
clp->cl_mvops->reboot_recovery_ops); |
b6d408ba8 NFSv4: Fix up err... |
1680 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
6df08189f nfs41: rename cl_... |
1681 |
test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) |
c3fad1b1a nfs41: add sessio... |
1682 |
continue; |
b79a4a1b4 NFSv4: Fix state ... |
1683 |
nfs4_state_end_reclaim_reboot(clp); |
b6d408ba8 NFSv4: Fix up err... |
1684 1685 1686 1687 |
if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) continue; if (status < 0) goto out_error; |
028600143 NFSv4: Clean up f... |
1688 |
} |
b79a4a1b4 NFSv4: Fix state ... |
1689 1690 |
/* Now recover expired state... */ if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
591d71cbd nfs41: establish ... |
1691 |
status = nfs4_do_reclaim(clp, |
c48f4f354 NFSv41: Convert t... |
1692 |
clp->cl_mvops->nograce_recovery_ops); |
b6d408ba8 NFSv4: Fix up err... |
1693 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
6df08189f nfs41: rename cl_... |
1694 |
test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || |
b6d408ba8 NFSv4: Fix up err... |
1695 1696 1697 |
test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) continue; if (status < 0) |
b79a4a1b4 NFSv4: Fix state ... |
1698 |
goto out_error; |
1da177e4c Linux-2.6.12-rc2 |
1699 |
} |
707fb4b32 NFSv4: Clean up N... |
1700 |
|
5601a00d6 nfs: run state ma... |
1701 |
nfs4_end_drain_session(clp); |
707fb4b32 NFSv4: Clean up N... |
1702 1703 1704 1705 |
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { nfs_client_return_marked_delegations(clp); continue; } |
b9efa1b27 nfs41: implement ... |
1706 1707 1708 1709 1710 1711 1712 1713 |
/* Recall session slots */ if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state) && nfs4_has_session(clp)) { status = nfs4_recall_slot(clp); if (status < 0) goto out_error; continue; } |
e005e8041 NFSv4: Rename the... |
1714 1715 |
nfs4_clear_state_manager_bit(clp); |
f3c76491e NFSv4: Don't exit... |
1716 1717 1718 1719 1720 |
/* Did we race with an attempt to give us more work? */ if (clp->cl_state == 0) break; if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) break; |
47c2199b6 NFSv4.1: Ensure s... |
1721 |
} while (atomic_read(&clp->cl_count) > 1); |
e005e8041 NFSv4: Rename the... |
1722 |
return; |
1da177e4c Linux-2.6.12-rc2 |
1723 |
out_error: |
e005e8041 NFSv4: Rename the... |
1724 |
printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" |
5d8515cae NFS: eliminate NI... |
1725 1726 |
" with error %d ", clp->cl_hostname, -status); |
5601a00d6 nfs: run state ma... |
1727 |
nfs4_end_drain_session(clp); |
e005e8041 NFSv4: Rename the... |
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 |
nfs4_clear_state_manager_bit(clp); } static int nfs4_run_state_manager(void *ptr) { struct nfs_client *clp = ptr; allow_signal(SIGKILL); nfs4_state_manager(clp); nfs_put_client(clp); module_put_and_exit(0); return 0; |
1da177e4c Linux-2.6.12-rc2 |
1740 1741 1742 1743 1744 1745 1746 |
} /* * Local variables: * c-basic-offset: 8 * End: */ |