Blame view
fs/nfs/nfs4state.c
70.5 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 |
#include <linux/nfs_fs.h> |
5043e900f NFS: Convert inst... |
44 45 |
#include <linux/kthread.h> #include <linux/module.h> |
9f958ab88 NFSv4: Reduce the... |
46 |
#include <linux/random.h> |
8c7597f6c nfs: include rate... |
47 |
#include <linux/ratelimit.h> |
1da177e4c Linux-2.6.12-rc2 |
48 49 |
#include <linux/workqueue.h> #include <linux/bitops.h> |
0aaaf5c42 NFS: Cache state ... |
50 |
#include <linux/jiffies.h> |
1da177e4c Linux-2.6.12-rc2 |
51 |
|
05f4c350e NFS: Discover NFS... |
52 |
#include <linux/sunrpc/clnt.h> |
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" |
40c64c26a NFS: Move nfs_idm... |
57 |
#include "nfs4idmap.h" |
76e697ba7 NFSv4.1: Move slo... |
58 |
#include "nfs4session.h" |
974cec8ca NFS: client needs... |
59 |
#include "pnfs.h" |
bbe0a3aa4 NFS: make nfs_cal... |
60 |
#include "netns.h" |
511ba52e4 NFS4: Trace state... |
61 |
#include "nfs4trace.h" |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
e3c0fb7ef NFS: Add NFSDBG_S... |
63 |
#define NFSDBG_FACILITY NFSDBG_STATE |
1da177e4c Linux-2.6.12-rc2 |
64 |
#define OPENOWNER_POOL_SIZE 8 |
93b717fd8 NFSv4: Label stat... |
65 |
const nfs4_stateid zero_stateid = { |
e0714ec4f nfs: fix anonymou... |
66 |
{ .data = { 0 } }, |
93b717fd8 NFSv4: Label stat... |
67 68 |
.type = NFS4_SPECIAL_STATEID_TYPE, }; |
fcd8843c4 NFSv4: Replace cl... |
69 70 |
const nfs4_stateid invalid_stateid = { { |
445f288d7 NFSv4: Ensure gcc... |
71 72 |
/* Funky initialiser keeps older gcc versions happy */ .data = { 0xff, 0xff, 0xff, 0xff, 0 }, |
fcd8843c4 NFSv4: Replace cl... |
73 74 75 |
}, .type = NFS4_INVALID_STATEID_TYPE, }; |
2409a976a pnfs: Add LAYOUTG... |
76 77 78 79 80 81 82 |
const nfs4_stateid current_stateid = { { /* Funky initialiser keeps older gcc versions happy */ .data = { 0x0, 0x0, 0x0, 0x1, 0 }, }, .type = NFS4_SPECIAL_STATEID_TYPE, }; |
05f4c350e NFS: Discover NFS... |
83 |
static DEFINE_MUTEX(nfs_clid_init_mutex); |
1da177e4c Linux-2.6.12-rc2 |
84 |
|
5b596830d nfs4.0: Refetch l... |
85 86 87 88 |
static int nfs4_setup_state_renewal(struct nfs_client *clp) { int status; struct nfs_fsinfo fsinfo; |
5b596830d nfs4.0: Refetch l... |
89 90 91 92 93 |
if (!test_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state)) { nfs4_schedule_state_renewal(clp); return 0; } |
5b596830d nfs4.0: Refetch l... |
94 95 |
status = nfs4_proc_get_lease_time(clp, &fsinfo); if (status == 0) { |
7dc2993a9 NFSv4.0: nfs4_do_... |
96 |
nfs4_set_lease_period(clp, fsinfo.lease_time * HZ); |
5b596830d nfs4.0: Refetch l... |
97 98 99 100 101 |
nfs4_schedule_state_renewal(clp); } return status; } |
a52458b48 NFS/NFSD/SUNRPC: ... |
102 |
int nfs4_init_clientid(struct nfs_client *clp, const struct cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
103 |
{ |
fd954ae12 NFSv4.1: Don't lo... |
104 105 106 107 |
struct nfs4_setclientid_res clid = { .clientid = clp->cl_clientid, .confirm = clp->cl_confirm, }; |
f738f5170 NFS: Start PF_INE... |
108 109 |
unsigned short port; int status; |
bbe0a3aa4 NFS: make nfs_cal... |
110 |
struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); |
f738f5170 NFS: Start PF_INE... |
111 |
|
fd954ae12 NFSv4.1: Don't lo... |
112 113 |
if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) goto do_confirm; |
bbe0a3aa4 NFS: make nfs_cal... |
114 |
port = nn->nfs_callback_tcpport; |
f738f5170 NFS: Start PF_INE... |
115 |
if (clp->cl_addr.ss_family == AF_INET6) |
29dcc16a8 NFS: make nfs_cal... |
116 |
port = nn->nfs_callback_tcpport6; |
f738f5170 NFS: Start PF_INE... |
117 |
|
bb8b27e50 NFSv4: Clean up t... |
118 119 120 |
status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
121 122 123 124 |
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... |
125 126 127 |
status = nfs4_proc_setclientid_confirm(clp, &clid, cred); if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
128 |
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
5b596830d nfs4.0: Refetch l... |
129 |
nfs4_setup_state_renewal(clp); |
bb8b27e50 NFSv4: Clean up t... |
130 |
out: |
1da177e4c Linux-2.6.12-rc2 |
131 132 |
return status; } |
05f4c350e NFS: Discover NFS... |
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
/** * nfs40_discover_server_trunking - Detect server IP address trunking (mv0) * * @clp: nfs_client under test * @result: OUT: found nfs_client, or clp * @cred: credential to use for trunking test * * Returns zero, a negative errno, or a negative NFS4ERR status. * If zero is returned, an nfs_client pointer is planted in * "result". * * Note: The returned client may not yet be marked ready. */ int nfs40_discover_server_trunking(struct nfs_client *clp, struct nfs_client **result, |
a52458b48 NFS/NFSD/SUNRPC: ... |
148 |
const struct cred *cred) |
05f4c350e NFS: Discover NFS... |
149 150 151 152 153 |
{ struct nfs4_setclientid_res clid = { .clientid = clp->cl_clientid, .confirm = clp->cl_confirm, }; |
9f62387d6 NFSv4: Fix up a m... |
154 |
struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); |
05f4c350e NFS: Discover NFS... |
155 156 |
unsigned short port; int status; |
9f62387d6 NFSv4: Fix up a m... |
157 |
port = nn->nfs_callback_tcpport; |
05f4c350e NFS: Discover NFS... |
158 |
if (clp->cl_addr.ss_family == AF_INET6) |
9f62387d6 NFSv4: Fix up a m... |
159 |
port = nn->nfs_callback_tcpport6; |
05f4c350e NFS: Discover NFS... |
160 161 162 163 164 165 166 167 |
status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); if (status != 0) goto out; clp->cl_clientid = clid.clientid; clp->cl_confirm = clid.confirm; status = nfs40_walk_client_list(clp, result, cred); |
202c312db NFSv4: Fix NFSv4 ... |
168 |
if (status == 0) { |
05f4c350e NFS: Discover NFS... |
169 170 171 |
/* Sustain the lease, even if it's empty. If the clientid4 * goes stale it's of no use for trunking discovery. */ nfs4_schedule_state_renewal(*result); |
f02f3755d NFS4: Fix v4.0 cl... |
172 173 174 175 |
/* If the client state need to recover, do it. */ if (clp->cl_state) nfs4_schedule_state_manager(clp); |
05f4c350e NFS: Discover NFS... |
176 |
} |
05f4c350e NFS: Discover NFS... |
177 178 179 |
out: return status; } |
a52458b48 NFS/NFSD/SUNRPC: ... |
180 |
const struct cred *nfs4_get_machine_cred(struct nfs_client *clp) |
a2b2bb882 NFSv4: Attempt to... |
181 |
{ |
a52458b48 NFS/NFSD/SUNRPC: ... |
182 |
return get_cred(rpc_machine_cred()); |
a2b2bb882 NFSv4: Attempt to... |
183 |
} |
d688f7b8f NFS: Use root's c... |
184 185 |
static void nfs4_root_machine_cred(struct nfs_client *clp) { |
d688f7b8f NFS: Use root's c... |
186 |
|
5e16923b4 NFS/SUNRPC: don't... |
187 188 189 |
/* Force root creds instead of machine */ clp->cl_principal = NULL; clp->cl_rpcclient->cl_principal = NULL; |
d688f7b8f NFS: Use root's c... |
190 |
} |
a52458b48 NFS/NFSD/SUNRPC: ... |
191 |
static const struct cred * |
24d292b89 NFS: Move cl_stat... |
192 |
nfs4_get_renew_cred_server_locked(struct nfs_server *server) |
b4454fe1a NFSv4: Remove req... |
193 |
{ |
a52458b48 NFS/NFSD/SUNRPC: ... |
194 |
const struct cred *cred = NULL; |
b4454fe1a NFSv4: Remove req... |
195 |
struct nfs4_state_owner *sp; |
9f958ab88 NFSv4: Reduce the... |
196 |
struct rb_node *pos; |
b4454fe1a NFSv4: Remove req... |
197 |
|
24d292b89 NFS: Move cl_stat... |
198 199 200 201 |
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... |
202 203 |
if (list_empty(&sp->so_states)) continue; |
a52458b48 NFS/NFSD/SUNRPC: ... |
204 |
cred = get_cred(sp->so_cred); |
b4454fe1a NFSv4: Remove req... |
205 206 207 208 |
break; } return cred; } |
24d292b89 NFS: Move cl_stat... |
209 |
/** |
f15e1e8bc NFSv4: don't requ... |
210 |
* nfs4_get_renew_cred - Acquire credential for a renew operation |
24d292b89 NFS: Move cl_stat... |
211 212 213 214 215 |
* @clp: client state handle * * Returns an rpc_cred with reference count bumped, or NULL. * Caller must hold clp->cl_lock. */ |
a52458b48 NFS/NFSD/SUNRPC: ... |
216 |
const struct cred *nfs4_get_renew_cred(struct nfs_client *clp) |
24d292b89 NFS: Move cl_stat... |
217 |
{ |
a52458b48 NFS/NFSD/SUNRPC: ... |
218 |
const struct cred *cred = NULL; |
24d292b89 NFS: Move cl_stat... |
219 |
struct nfs_server *server; |
e49a29bd0 Try using machine... |
220 |
/* Use machine credentials if available */ |
f15e1e8bc NFSv4: don't requ... |
221 |
cred = nfs4_get_machine_cred(clp); |
e49a29bd0 Try using machine... |
222 223 |
if (cred != NULL) goto out; |
f15e1e8bc NFSv4: don't requ... |
224 |
spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
225 226 227 228 229 230 231 |
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(); |
f15e1e8bc NFSv4: don't requ... |
232 |
spin_unlock(&clp->cl_lock); |
e49a29bd0 Try using machine... |
233 234 |
out: |
24d292b89 NFS: Move cl_stat... |
235 236 |
return cred; } |
62f288a02 NFSv4.1 end back ... |
237 |
static void nfs4_end_drain_slot_table(struct nfs4_slot_table *tbl) |
9dfdf404c nfs41: Don't clea... |
238 |
{ |
774d5f14e NFSv4.1 Fix a pNF... |
239 |
if (test_and_clear_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state)) { |
961a828df SUNRPC: Fix poten... |
240 |
spin_lock(&tbl->slot_tbl_lock); |
b75ad4cda NFSv4.1: Ensure s... |
241 |
nfs41_wake_slot_table(tbl); |
961a828df SUNRPC: Fix poten... |
242 |
spin_unlock(&tbl->slot_tbl_lock); |
689cf5c15 nfs: enforce FIFO... |
243 |
} |
9dfdf404c nfs41: Don't clea... |
244 |
} |
62f288a02 NFSv4.1 end back ... |
245 246 247 |
static void nfs4_end_drain_session(struct nfs_client *clp) { struct nfs4_session *ses = clp->cl_session; |
2cf8bca8b NFS: Update sessi... |
248 249 250 251 |
if (clp->cl_slot_tbl) { nfs4_end_drain_slot_table(clp->cl_slot_tbl); return; } |
62f288a02 NFSv4.1 end back ... |
252 253 254 255 256 |
if (ses != NULL) { nfs4_end_drain_slot_table(&ses->bc_slot_table); nfs4_end_drain_slot_table(&ses->fc_slot_table); } } |
774d5f14e NFSv4.1 Fix a pNF... |
257 |
static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl) |
9dfdf404c nfs41: Don't clea... |
258 |
{ |
774d5f14e NFSv4.1 Fix a pNF... |
259 |
set_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state); |
9dfdf404c nfs41: Don't clea... |
260 |
spin_lock(&tbl->slot_tbl_lock); |
b6bf6e7d6 NFSv4.1 set highe... |
261 |
if (tbl->highest_used_slotid != NFS4_NO_SLOT) { |
16735d022 tree-wide: use re... |
262 |
reinit_completion(&tbl->complete); |
9dfdf404c nfs41: Don't clea... |
263 |
spin_unlock(&tbl->slot_tbl_lock); |
42acd0218 NFS add session b... |
264 |
return wait_for_completion_interruptible(&tbl->complete); |
9dfdf404c nfs41: Don't clea... |
265 266 267 268 |
} spin_unlock(&tbl->slot_tbl_lock); return 0; } |
42acd0218 NFS add session b... |
269 270 271 |
static int nfs4_begin_drain_session(struct nfs_client *clp) { struct nfs4_session *ses = clp->cl_session; |
8aafd2fde NFSv4: Don't busy... |
272 |
int ret; |
42acd0218 NFS add session b... |
273 |
|
2cf8bca8b NFS: Update sessi... |
274 275 |
if (clp->cl_slot_tbl) return nfs4_drain_slot_tbl(clp->cl_slot_tbl); |
42acd0218 NFS add session b... |
276 |
/* back channel */ |
774d5f14e NFSv4.1 Fix a pNF... |
277 |
ret = nfs4_drain_slot_tbl(&ses->bc_slot_table); |
42acd0218 NFS add session b... |
278 279 280 |
if (ret) return ret; /* fore channel */ |
774d5f14e NFSv4.1 Fix a pNF... |
281 |
return nfs4_drain_slot_tbl(&ses->fc_slot_table); |
42acd0218 NFS add session b... |
282 |
} |
c9fdeb280 NFS: Add basic mi... |
283 |
#if defined(CONFIG_NFS_V4_1) |
bda197f5d NFSv4.1: Ensure w... |
284 285 286 287 288 |
static void nfs41_finish_session_reset(struct nfs_client *clp) { clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); /* create_session negotiated new slot table */ |
bda197f5d NFSv4.1: Ensure w... |
289 |
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); |
ea51efaa9 nfs4: Rename nfs4... |
290 |
nfs4_setup_state_renewal(clp); |
bda197f5d NFSv4.1: Ensure w... |
291 |
} |
a52458b48 NFS/NFSD/SUNRPC: ... |
292 |
int nfs41_init_clientid(struct nfs_client *clp, const struct cred *cred) |
4d643d1df nfs41: add create... |
293 294 |
{ int status; |
fd954ae12 NFSv4.1: Don't lo... |
295 296 |
if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) goto do_confirm; |
4d643d1df nfs41: add create... |
297 |
status = nfs4_proc_exchange_id(clp, cred); |
9430fb6b5 nfs41: nfs41_setu... |
298 299 |
if (status != 0) goto out; |
fd954ae12 NFSv4.1: Don't lo... |
300 301 |
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); do_confirm: |
848f5bda5 NFSv4.1: Ensure w... |
302 |
status = nfs4_proc_create_session(clp, cred); |
9430fb6b5 nfs41: nfs41_setu... |
303 304 |
if (status != 0) goto out; |
bda197f5d NFSv4.1: Ensure w... |
305 |
nfs41_finish_session_reset(clp); |
9430fb6b5 nfs41: nfs41_setu... |
306 307 |
nfs_mark_client_ready(clp, NFS_CS_READY); out: |
4d643d1df nfs41: add create... |
308 309 |
return status; } |
05f4c350e NFS: Discover NFS... |
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
/** * nfs41_discover_server_trunking - Detect server IP address trunking (mv1) * * @clp: nfs_client under test * @result: OUT: found nfs_client, or clp * @cred: credential to use for trunking test * * Returns NFS4_OK, a negative errno, or a negative NFS4ERR status. * If NFS4_OK is returned, an nfs_client pointer is planted in * "result". * * Note: The returned client may not yet be marked ready. */ int nfs41_discover_server_trunking(struct nfs_client *clp, struct nfs_client **result, |
a52458b48 NFS/NFSD/SUNRPC: ... |
325 |
const struct cred *cred) |
05f4c350e NFS: Discover NFS... |
326 327 328 329 330 331 |
{ int status; status = nfs4_proc_exchange_id(clp, cred); if (status != NFS4_OK) return status; |
48d66b974 NFSv4: Fix a race... |
332 333 334 335 336 |
status = nfs41_walk_client_list(clp, result, cred); if (status < 0) return status; if (clp != *result) return 0; |
8dcbec6d2 NFSv4.1: Handle E... |
337 338 339 340 341 342 343 344 345 346 347 |
/* * Purge state if the client id was established in a prior * instance and the client id could not have arrived on the * server via Transparent State Migration. */ if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) { if (!test_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags)) set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); else set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); } |
48d66b974 NFSv4: Fix a race... |
348 349 350 351 352 |
nfs4_schedule_state_manager(clp); status = nfs_wait_client_init_complete(clp); if (status < 0) nfs_put_client(clp); return status; |
05f4c350e NFS: Discover NFS... |
353 |
} |
b4b82607f nfs41: get_clid_c... |
354 |
#endif /* CONFIG_NFS_V4_1 */ |
24d292b89 NFS: Move cl_stat... |
355 |
/** |
73d8bde5e NFS: Never use us... |
356 |
* nfs4_get_clid_cred - Acquire credential for a setclientid operation |
24d292b89 NFS: Move cl_stat... |
357 358 |
* @clp: client state handle * |
a52458b48 NFS/NFSD/SUNRPC: ... |
359 |
* Returns a cred with reference count bumped, or NULL. |
24d292b89 NFS: Move cl_stat... |
360 |
*/ |
a52458b48 NFS/NFSD/SUNRPC: ... |
361 |
const struct cred *nfs4_get_clid_cred(struct nfs_client *clp) |
24d292b89 NFS: Move cl_stat... |
362 |
{ |
a52458b48 NFS/NFSD/SUNRPC: ... |
363 |
const struct cred *cred; |
286d7d6a0 NFSv4: Remove req... |
364 |
|
f15e1e8bc NFSv4: don't requ... |
365 |
cred = nfs4_get_machine_cred(clp); |
a2b2bb882 NFSv4: Attempt to... |
366 |
return cred; |
286d7d6a0 NFSv4: Remove req... |
367 |
} |
1da177e4c Linux-2.6.12-rc2 |
368 |
static struct nfs4_state_owner * |
a52458b48 NFS/NFSD/SUNRPC: ... |
369 |
nfs4_find_state_owner_locked(struct nfs_server *server, const struct cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
370 |
{ |
24d292b89 NFS: Move cl_stat... |
371 |
struct rb_node **p = &server->state_owners.rb_node, |
9f958ab88 NFSv4: Reduce the... |
372 |
*parent = NULL; |
414adf14c NFS: Clean up nfs... |
373 |
struct nfs4_state_owner *sp; |
a52458b48 NFS/NFSD/SUNRPC: ... |
374 |
int cmp; |
1da177e4c Linux-2.6.12-rc2 |
375 |
|
9f958ab88 NFSv4: Reduce the... |
376 377 |
while (*p != NULL) { parent = *p; |
24d292b89 NFS: Move cl_stat... |
378 |
sp = rb_entry(parent, struct nfs4_state_owner, so_server_node); |
a52458b48 NFS/NFSD/SUNRPC: ... |
379 |
cmp = cred_fscmp(cred, sp->so_cred); |
9f958ab88 NFSv4: Reduce the... |
380 |
|
a52458b48 NFS/NFSD/SUNRPC: ... |
381 |
if (cmp < 0) |
9f958ab88 NFSv4: Reduce the... |
382 |
p = &parent->rb_left; |
a52458b48 NFS/NFSD/SUNRPC: ... |
383 |
else if (cmp > 0) |
9f958ab88 NFSv4: Reduce the... |
384 385 |
p = &parent->rb_right; else { |
0aaaf5c42 NFS: Cache state ... |
386 387 |
if (!list_empty(&sp->so_lru)) list_del_init(&sp->so_lru); |
9f958ab88 NFSv4: Reduce the... |
388 |
atomic_inc(&sp->so_count); |
414adf14c NFS: Clean up nfs... |
389 |
return sp; |
9f958ab88 NFSv4: Reduce the... |
390 |
} |
1da177e4c Linux-2.6.12-rc2 |
391 |
} |
414adf14c NFS: Clean up nfs... |
392 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
393 |
} |
9f958ab88 NFSv4: Reduce the... |
394 |
static struct nfs4_state_owner * |
24d292b89 NFS: Move cl_stat... |
395 |
nfs4_insert_state_owner_locked(struct nfs4_state_owner *new) |
9f958ab88 NFSv4: Reduce the... |
396 |
{ |
24d292b89 NFS: Move cl_stat... |
397 398 |
struct nfs_server *server = new->so_server; struct rb_node **p = &server->state_owners.rb_node, |
9f958ab88 NFSv4: Reduce the... |
399 400 |
*parent = NULL; struct nfs4_state_owner *sp; |
a52458b48 NFS/NFSD/SUNRPC: ... |
401 |
int cmp; |
9f958ab88 NFSv4: Reduce the... |
402 403 404 |
while (*p != NULL) { parent = *p; |
24d292b89 NFS: Move cl_stat... |
405 |
sp = rb_entry(parent, struct nfs4_state_owner, so_server_node); |
a52458b48 NFS/NFSD/SUNRPC: ... |
406 |
cmp = cred_fscmp(new->so_cred, sp->so_cred); |
9f958ab88 NFSv4: Reduce the... |
407 |
|
a52458b48 NFS/NFSD/SUNRPC: ... |
408 |
if (cmp < 0) |
9f958ab88 NFSv4: Reduce the... |
409 |
p = &parent->rb_left; |
a52458b48 NFS/NFSD/SUNRPC: ... |
410 |
else if (cmp > 0) |
9f958ab88 NFSv4: Reduce the... |
411 412 |
p = &parent->rb_right; else { |
0aaaf5c42 NFS: Cache state ... |
413 414 |
if (!list_empty(&sp->so_lru)) list_del_init(&sp->so_lru); |
9f958ab88 NFSv4: Reduce the... |
415 416 417 418 |
atomic_inc(&sp->so_count); return sp; } } |
24d292b89 NFS: Move cl_stat... |
419 420 |
rb_link_node(&new->so_server_node, parent, p); rb_insert_color(&new->so_server_node, &server->state_owners); |
9f958ab88 NFSv4: Reduce the... |
421 422 423 424 |
return new; } static void |
24d292b89 NFS: Move cl_stat... |
425 |
nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp) |
9f958ab88 NFSv4: Reduce the... |
426 |
{ |
24d292b89 NFS: Move cl_stat... |
427 428 429 430 |
struct nfs_server *server = sp->so_server; if (!RB_EMPTY_NODE(&sp->so_server_node)) rb_erase(&sp->so_server_node, &server->state_owners); |
9f958ab88 NFSv4: Reduce the... |
431 |
} |
7ba127ab9 NFSv4: Move conte... |
432 433 434 |
static void nfs4_init_seqid_counter(struct nfs_seqid_counter *sc) { |
95b72eb0b NFSv4: Ensure we ... |
435 |
sc->create_time = ktime_get(); |
7ba127ab9 NFSv4: Move conte... |
436 437 438 439 440 441 442 443 444 445 446 447 |
sc->flags = 0; sc->counter = 0; spin_lock_init(&sc->lock); INIT_LIST_HEAD(&sc->list); rpc_init_wait_queue(&sc->wait, "Seqid_waitqueue"); } static void nfs4_destroy_seqid_counter(struct nfs_seqid_counter *sc) { rpc_destroy_wait_queue(&sc->wait); } |
1da177e4c Linux-2.6.12-rc2 |
448 449 450 451 452 453 |
/* * nfs4_alloc_state_owner(): this is called on the OPEN or CREATE path to * create a new state_owner. * */ static struct nfs4_state_owner * |
d1e284d50 NFSv4: Clean up n... |
454 |
nfs4_alloc_state_owner(struct nfs_server *server, |
a52458b48 NFS/NFSD/SUNRPC: ... |
455 |
const struct cred *cred, |
d1e284d50 NFSv4: Clean up n... |
456 |
gfp_t gfp_flags) |
1da177e4c Linux-2.6.12-rc2 |
457 458 |
{ struct nfs4_state_owner *sp; |
d1e284d50 NFSv4: Clean up n... |
459 |
sp = kzalloc(sizeof(*sp), gfp_flags); |
1da177e4c Linux-2.6.12-rc2 |
460 461 |
if (!sp) return NULL; |
aae5730e2 nfs: Use ida_simp... |
462 463 464 465 466 467 |
sp->so_seqid.owner_id = ida_simple_get(&server->openowner_id, 0, 0, gfp_flags); if (sp->so_seqid.owner_id < 0) { kfree(sp); return NULL; } |
d1e284d50 NFSv4: Clean up n... |
468 |
sp->so_server = server; |
a52458b48 NFS/NFSD/SUNRPC: ... |
469 |
sp->so_cred = get_cred(cred); |
ec0734282 NFSv4: Fix up loc... |
470 |
spin_lock_init(&sp->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
471 |
INIT_LIST_HEAD(&sp->so_states); |
7ba127ab9 NFSv4: Move conte... |
472 |
nfs4_init_seqid_counter(&sp->so_seqid); |
1da177e4c Linux-2.6.12-rc2 |
473 |
atomic_set(&sp->so_count, 1); |
0aaaf5c42 NFS: Cache state ... |
474 |
INIT_LIST_HEAD(&sp->so_lru); |
76246c921 NFSv4: Use sequen... |
475 |
seqcount_spinlock_init(&sp->so_reclaim_seqcount, &sp->so_lock); |
65b62a29f NFSv4: Ensure del... |
476 |
mutex_init(&sp->so_delegreturn_mutex); |
1da177e4c Linux-2.6.12-rc2 |
477 478 |
return sp; } |
1d2e88e73 nfs: make nfs4_dr... |
479 |
static void |
86cfb0418 NFS: Don't discon... |
480 |
nfs4_reset_state_owner(struct nfs4_state_owner *sp) |
1da177e4c Linux-2.6.12-rc2 |
481 |
{ |
86cfb0418 NFS: Don't discon... |
482 483 484 485 486 487 488 489 490 491 |
/* This state_owner is no longer usable, but must * remain in place so that state recovery can find it * and the opens associated with it. * It may also be used for new 'open' request to * return a delegation to the server. * So update the 'create_time' so that it looks like * a new state_owner. This will cause the server to * request an OPEN_CONFIRM to start a new sequence. */ sp->so_seqid.create_time = ktime_get(); |
1da177e4c Linux-2.6.12-rc2 |
492 |
} |
0aaaf5c42 NFS: Cache state ... |
493 494 |
static void nfs4_free_state_owner(struct nfs4_state_owner *sp) { |
7ba127ab9 NFSv4: Move conte... |
495 |
nfs4_destroy_seqid_counter(&sp->so_seqid); |
a52458b48 NFS/NFSD/SUNRPC: ... |
496 |
put_cred(sp->so_cred); |
aae5730e2 nfs: Use ida_simp... |
497 |
ida_simple_remove(&sp->so_server->openowner_id, sp->so_seqid.owner_id); |
0aaaf5c42 NFS: Cache state ... |
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
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... |
525 526 527 528 |
/** * nfs4_get_state_owner - Look up a state owner given a credential * @server: nfs_server to search * @cred: RPC credential to match |
302fad7bd NFS: Fix up docum... |
529 |
* @gfp_flags: allocation mode |
24d292b89 NFS: Move cl_stat... |
530 531 532 533 |
* * Returns a pointer to an instantiated nfs4_state_owner struct, or NULL. */ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, |
a52458b48 NFS/NFSD/SUNRPC: ... |
534 |
const struct cred *cred, |
d1e284d50 NFSv4: Clean up n... |
535 |
gfp_t gfp_flags) |
1da177e4c Linux-2.6.12-rc2 |
536 |
{ |
7539bbab8 NFS: Rename nfs_s... |
537 |
struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
538 |
struct nfs4_state_owner *sp, *new; |
1da177e4c Linux-2.6.12-rc2 |
539 |
spin_lock(&clp->cl_lock); |
24d292b89 NFS: Move cl_stat... |
540 |
sp = nfs4_find_state_owner_locked(server, cred); |
1da177e4c Linux-2.6.12-rc2 |
541 |
spin_unlock(&clp->cl_lock); |
1da177e4c Linux-2.6.12-rc2 |
542 |
if (sp != NULL) |
0aaaf5c42 NFS: Cache state ... |
543 |
goto out; |
d1e284d50 NFSv4: Clean up n... |
544 |
new = nfs4_alloc_state_owner(server, cred, gfp_flags); |
9f958ab88 NFSv4: Reduce the... |
545 |
if (new == NULL) |
0aaaf5c42 NFS: Cache state ... |
546 |
goto out; |
aae5730e2 nfs: Use ida_simp... |
547 548 549 |
spin_lock(&clp->cl_lock); sp = nfs4_insert_state_owner_locked(new); spin_unlock(&clp->cl_lock); |
d1e284d50 NFSv4: Clean up n... |
550 551 |
if (sp != new) nfs4_free_state_owner(new); |
0aaaf5c42 NFS: Cache state ... |
552 553 |
out: nfs4_gc_state_owners(server); |
9f958ab88 NFSv4: Reduce the... |
554 |
return sp; |
1da177e4c Linux-2.6.12-rc2 |
555 |
} |
24d292b89 NFS: Move cl_stat... |
556 557 558 |
/** * nfs4_put_state_owner - Release a nfs4_state_owner * @sp: state owner data to release |
7bf97bc27 NFSv4: Keep dropp... |
559 560 561 562 563 564 565 566 |
* * Note that we keep released state owners on an LRU * list. * This caches valid state owners so that they can be * reused, to avoid the OPEN_CONFIRM on minor version 0. * It also pins the uniquifier of dropped state owners for * a while, to ensure that those state owner names are * never reused. |
24d292b89 NFS: Move cl_stat... |
567 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
568 569 |
void nfs4_put_state_owner(struct nfs4_state_owner *sp) { |
0aaaf5c42 NFS: Cache state ... |
570 571 |
struct nfs_server *server = sp->so_server; struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
572 573 574 |
if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) return; |
0aaaf5c42 NFS: Cache state ... |
575 |
|
7bf97bc27 NFSv4: Keep dropp... |
576 577 578 |
sp->so_expires = jiffies; list_add_tail(&sp->so_lru, &server->state_owners_lru); spin_unlock(&clp->cl_lock); |
0aaaf5c42 NFS: Cache state ... |
579 580 581 582 583 |
} /** * nfs4_purge_state_owners - Release all cached state owners * @server: nfs_server with cached state owners to release |
c77e22834 NFSv4: Fix a pote... |
584 |
* @head: resulting list of state owners |
0aaaf5c42 NFS: Cache state ... |
585 586 587 |
* * Called at umount time. Remaining state owners will be on * the LRU with ref count of zero. |
c77e22834 NFSv4: Fix a pote... |
588 589 590 |
* Note that the state owners are not freed, but are added * to the list @head, which can later be used as an argument * to nfs4_free_state_owners. |
0aaaf5c42 NFS: Cache state ... |
591 |
*/ |
c77e22834 NFSv4: Fix a pote... |
592 |
void nfs4_purge_state_owners(struct nfs_server *server, struct list_head *head) |
0aaaf5c42 NFS: Cache state ... |
593 594 595 |
{ struct nfs_client *clp = server->nfs_client; struct nfs4_state_owner *sp, *tmp; |
0aaaf5c42 NFS: Cache state ... |
596 597 598 |
spin_lock(&clp->cl_lock); list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) { |
c77e22834 NFSv4: Fix a pote... |
599 |
list_move(&sp->so_lru, head); |
0aaaf5c42 NFS: Cache state ... |
600 601 |
nfs4_remove_state_owner_locked(sp); } |
1da177e4c Linux-2.6.12-rc2 |
602 |
spin_unlock(&clp->cl_lock); |
c77e22834 NFSv4: Fix a pote... |
603 |
} |
0aaaf5c42 NFS: Cache state ... |
604 |
|
c77e22834 NFSv4: Fix a pote... |
605 606 607 608 609 610 611 612 613 614 615 616 |
/** * nfs4_purge_state_owners - Release all cached state owners * @head: resulting list of state owners * * Frees a list of state owners that was generated by * nfs4_purge_state_owners */ void nfs4_free_state_owners(struct list_head *head) { struct nfs4_state_owner *sp, *tmp; list_for_each_entry_safe(sp, tmp, head, so_lru) { |
0aaaf5c42 NFS: Cache state ... |
617 618 619 |
list_del(&sp->so_lru); nfs4_free_state_owner(sp); } |
1da177e4c Linux-2.6.12-rc2 |
620 621 622 623 624 625 |
} static struct nfs4_state * nfs4_alloc_open_state(void) { struct nfs4_state *state; |
8535b2be5 NFSv4: Don't use ... |
626 |
state = kzalloc(sizeof(*state), GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
627 628 |
if (!state) return NULL; |
ace9fad43 NFSv4: Convert st... |
629 |
refcount_set(&state->count, 1); |
1da177e4c Linux-2.6.12-rc2 |
630 |
INIT_LIST_HEAD(&state->lock_states); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
631 |
spin_lock_init(&state->state_lock); |
8bda4e4c9 NFSv4: Fix up sta... |
632 |
seqlock_init(&state->seqlock); |
c9399f21c NFSv4: Fix OPEN /... |
633 |
init_waitqueue_head(&state->waitq); |
1da177e4c Linux-2.6.12-rc2 |
634 635 |
return state; } |
4cecb76ff NFSv4: Fix a race... |
636 |
void |
dc0b027df NFSv4: Convert th... |
637 |
nfs4_state_set_mode_locked(struct nfs4_state *state, fmode_t fmode) |
4cecb76ff NFSv4: Fix a race... |
638 |
{ |
dc0b027df NFSv4: Convert th... |
639 |
if (state->state == fmode) |
4cecb76ff NFSv4: Fix a race... |
640 641 |
return; /* NB! List reordering - see the reclaim code for why. */ |
dc0b027df NFSv4: Convert th... |
642 643 |
if ((fmode & FMODE_WRITE) != (state->state & FMODE_WRITE)) { if (fmode & FMODE_WRITE) |
4cecb76ff NFSv4: Fix a race... |
644 645 646 647 |
list_move(&state->open_states, &state->owner->so_states); else list_move_tail(&state->open_states, &state->owner->so_states); } |
dc0b027df NFSv4: Convert th... |
648 |
state->state = fmode; |
4cecb76ff NFSv4: Fix a race... |
649 |
} |
1da177e4c Linux-2.6.12-rc2 |
650 |
static struct nfs4_state * |
1da177e4c Linux-2.6.12-rc2 |
651 652 653 654 |
__nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs4_state *state; |
9ae075fdd NFSv4: Convert op... |
655 |
list_for_each_entry_rcu(state, &nfsi->open_states, inode_states) { |
1c816efa2 NFSv4: Fix a bug ... |
656 |
if (state->owner != owner) |
1da177e4c Linux-2.6.12-rc2 |
657 |
continue; |
5d422301f NFSv4: Fail I/O i... |
658 659 |
if (!nfs4_valid_open_stateid(state)) continue; |
ace9fad43 NFSv4: Convert st... |
660 |
if (refcount_inc_not_zero(&state->count)) |
1da177e4c Linux-2.6.12-rc2 |
661 |
return state; |
1da177e4c Linux-2.6.12-rc2 |
662 663 664 |
} return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
665 666 667 |
static void nfs4_free_open_state(struct nfs4_state *state) { |
9ae075fdd NFSv4: Convert op... |
668 |
kfree_rcu(state, rcu_head); |
1da177e4c Linux-2.6.12-rc2 |
669 670 671 672 673 674 675 |
} 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); |
9ae075fdd NFSv4: Convert op... |
676 |
rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
677 |
state = __nfs4_find_state_byowner(inode, owner); |
9ae075fdd NFSv4: Convert op... |
678 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
679 680 681 |
if (state) goto out; new = nfs4_alloc_open_state(); |
ec0734282 NFSv4: Fix up loc... |
682 |
spin_lock(&owner->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
683 684 685 686 |
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 |
687 688 |
state->owner = owner; atomic_inc(&owner->so_count); |
0444d76ae fs: don't use igr... |
689 690 |
ihold(inode); state->inode = inode; |
29fe83997 nfs: fix NULL def... |
691 |
list_add_rcu(&state->inode_states, &nfsi->open_states); |
1da177e4c Linux-2.6.12-rc2 |
692 |
spin_unlock(&inode->i_lock); |
ec0734282 NFSv4: Fix up loc... |
693 694 695 696 |
/* 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 |
697 698 |
} else { spin_unlock(&inode->i_lock); |
ec0734282 NFSv4: Fix up loc... |
699 |
spin_unlock(&owner->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
700 701 702 703 704 705 |
if (new) nfs4_free_open_state(new); } out: return state; } |
1da177e4c Linux-2.6.12-rc2 |
706 707 708 709 |
void nfs4_put_open_state(struct nfs4_state *state) { struct inode *inode = state->inode; struct nfs4_state_owner *owner = state->owner; |
ace9fad43 NFSv4: Convert st... |
710 |
if (!refcount_dec_and_lock(&state->count, &owner->so_lock)) |
1da177e4c Linux-2.6.12-rc2 |
711 |
return; |
ec0734282 NFSv4: Fix up loc... |
712 |
spin_lock(&inode->i_lock); |
9ae075fdd NFSv4: Convert op... |
713 |
list_del_rcu(&state->inode_states); |
1da177e4c Linux-2.6.12-rc2 |
714 |
list_del(&state->open_states); |
ec0734282 NFSv4: Fix up loc... |
715 716 |
spin_unlock(&inode->i_lock); spin_unlock(&owner->so_lock); |
b7b7dac68 NFSv4: Try to ret... |
717 |
nfs4_inode_return_delegation_on_close(inode); |
1da177e4c Linux-2.6.12-rc2 |
718 |
iput(inode); |
1da177e4c Linux-2.6.12-rc2 |
719 720 721 722 723 |
nfs4_free_open_state(state); nfs4_put_state_owner(owner); } /* |
83c9d41e4 NFSv4: Remove nfs... |
724 |
* Close the current file. |
1da177e4c Linux-2.6.12-rc2 |
725 |
*/ |
643168c2d nfs4_closedata do... |
726 |
static void __nfs4_close(struct nfs4_state *state, |
8535b2be5 NFSv4: Don't use ... |
727 |
fmode_t fmode, gfp_t gfp_mask, int wait) |
1da177e4c Linux-2.6.12-rc2 |
728 |
{ |
1da177e4c Linux-2.6.12-rc2 |
729 |
struct nfs4_state_owner *owner = state->owner; |
003707c72 NFSv4: Always use... |
730 |
int call_close = 0; |
dc0b027df NFSv4: Convert th... |
731 |
fmode_t newstate; |
1da177e4c Linux-2.6.12-rc2 |
732 733 |
atomic_inc(&owner->so_count); |
1da177e4c Linux-2.6.12-rc2 |
734 |
/* Protect against nfs4_find_state() */ |
ec0734282 NFSv4: Fix up loc... |
735 |
spin_lock(&owner->so_lock); |
dc0b027df NFSv4: Convert th... |
736 |
switch (fmode & (FMODE_READ | FMODE_WRITE)) { |
e76169238 NFSv4: Make nfs4_... |
737 738 739 740 741 742 743 744 745 |
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... |
746 |
newstate = FMODE_READ|FMODE_WRITE; |
e76169238 NFSv4: Make nfs4_... |
747 |
if (state->n_rdwr == 0) { |
003707c72 NFSv4: Always use... |
748 |
if (state->n_rdonly == 0) { |
e76169238 NFSv4: Make nfs4_... |
749 |
newstate &= ~FMODE_READ; |
003707c72 NFSv4: Always use... |
750 751 752 753 |
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_... |
754 |
newstate &= ~FMODE_WRITE; |
003707c72 NFSv4: Always use... |
755 756 757 758 759 |
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_... |
760 |
} |
003707c72 NFSv4: Always use... |
761 |
nfs4_state_set_mode_locked(state, newstate); |
ec0734282 NFSv4: Fix up loc... |
762 |
spin_unlock(&owner->so_lock); |
4cecb76ff NFSv4: Fix a race... |
763 |
|
003707c72 NFSv4: Always use... |
764 |
if (!call_close) { |
b39e625b6 NFSv4: Clean up n... |
765 766 |
nfs4_put_open_state(state); nfs4_put_state_owner(owner); |
1f7977c13 NFSv4.1: Simplify... |
767 768 |
} else nfs4_do_close(state, gfp_mask, wait); |
a49c3c773 NFSv4: Ensure tha... |
769 |
} |
643168c2d nfs4_closedata do... |
770 |
void nfs4_close_state(struct nfs4_state *state, fmode_t fmode) |
a49c3c773 NFSv4: Ensure tha... |
771 |
{ |
643168c2d nfs4_closedata do... |
772 |
__nfs4_close(state, fmode, GFP_NOFS, 0); |
a49c3c773 NFSv4: Ensure tha... |
773 |
} |
643168c2d nfs4_closedata do... |
774 |
void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode) |
a49c3c773 NFSv4: Ensure tha... |
775 |
{ |
643168c2d nfs4_closedata do... |
776 |
__nfs4_close(state, fmode, GFP_KERNEL, 1); |
1da177e4c Linux-2.6.12-rc2 |
777 778 779 780 |
} /* * Search the state->lock_states for an existing lock_owner |
3f8f25489 NFSv4: ensure __n... |
781 782 783 784 785 786 787 788 789 790 |
* that is compatible with either of the given owners. * If the second is non-zero, then the first refers to a Posix-lock * owner (current->files) and the second refers to a flock/OFD * owner (struct file*). In that case, prefer a match for the first * owner. * If both sorts of locks are held on the one file we cannot know * which stateid was intended to be used, so a "correct" choice cannot * be made. Failing that, a "consistent" choice is preferable. The * consistent choice we make is to prefer the first owner, that of a * Posix lock. |
1da177e4c Linux-2.6.12-rc2 |
791 792 |
*/ static struct nfs4_lock_state * |
8d4244316 NFSv4: enhance nf... |
793 794 |
__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, fl_owner_t fl_owner2) |
1da177e4c Linux-2.6.12-rc2 |
795 |
{ |
3f8f25489 NFSv4: ensure __n... |
796 |
struct nfs4_lock_state *pos, *ret = NULL; |
1da177e4c Linux-2.6.12-rc2 |
797 |
list_for_each_entry(pos, &state->lock_states, ls_locks) { |
3f8f25489 NFSv4: ensure __n... |
798 799 800 801 802 803 |
if (pos->ls_owner == fl_owner) { ret = pos; break; } if (pos->ls_owner == fl_owner2) ret = pos; |
1da177e4c Linux-2.6.12-rc2 |
804 |
} |
3f8f25489 NFSv4: ensure __n... |
805 |
if (ret) |
194bc1f48 fs, nfs: convert ... |
806 |
refcount_inc(&ret->ls_count); |
3f8f25489 NFSv4: ensure __n... |
807 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
808 |
} |
1da177e4c Linux-2.6.12-rc2 |
809 810 811 812 |
/* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. * |
1da177e4c Linux-2.6.12-rc2 |
813 |
*/ |
8003d3c4a nfs4: treat lock ... |
814 |
static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) |
1da177e4c Linux-2.6.12-rc2 |
815 816 |
{ struct nfs4_lock_state *lsp; |
24d292b89 NFS: Move cl_stat... |
817 |
struct nfs_server *server = state->owner->so_server; |
1da177e4c Linux-2.6.12-rc2 |
818 |
|
8535b2be5 NFSv4: Don't use ... |
819 |
lsp = kzalloc(sizeof(*lsp), GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
820 821 |
if (lsp == NULL) return NULL; |
7ba127ab9 NFSv4: Move conte... |
822 |
nfs4_init_seqid_counter(&lsp->ls_seqid); |
194bc1f48 fs, nfs: convert ... |
823 |
refcount_set(&lsp->ls_count, 1); |
b64aec8d1 NFSv4: Fix an Oop... |
824 |
lsp->ls_state = state; |
8003d3c4a nfs4: treat lock ... |
825 |
lsp->ls_owner = fl_owner; |
48c22eb21 NFS: Move struct ... |
826 827 |
lsp->ls_seqid.owner_id = ida_simple_get(&server->lockowner_id, 0, 0, GFP_NOFS); if (lsp->ls_seqid.owner_id < 0) |
d2d7ce28a NFSv4: Replace lo... |
828 |
goto out_free; |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
829 |
INIT_LIST_HEAD(&lsp->ls_locks); |
1da177e4c Linux-2.6.12-rc2 |
830 |
return lsp; |
d2d7ce28a NFSv4: Replace lo... |
831 832 833 |
out_free: kfree(lsp); return NULL; |
1da177e4c Linux-2.6.12-rc2 |
834 |
} |
5ae67c4fe NFSv4: It is not ... |
835 |
void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) |
9f958ab88 NFSv4: Reduce the... |
836 |
{ |
48c22eb21 NFS: Move struct ... |
837 |
ida_simple_remove(&server->lockowner_id, lsp->ls_seqid.owner_id); |
7ba127ab9 NFSv4: Move conte... |
838 |
nfs4_destroy_seqid_counter(&lsp->ls_seqid); |
9f958ab88 NFSv4: Reduce the... |
839 840 |
kfree(lsp); } |
1da177e4c Linux-2.6.12-rc2 |
841 842 843 844 |
/* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. * |
1da177e4c Linux-2.6.12-rc2 |
845 |
*/ |
8003d3c4a nfs4: treat lock ... |
846 |
static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) |
1da177e4c Linux-2.6.12-rc2 |
847 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
848 |
struct nfs4_lock_state *lsp, *new = NULL; |
1da177e4c Linux-2.6.12-rc2 |
849 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
850 851 |
for(;;) { spin_lock(&state->state_lock); |
68e33bd6b NFSv4: Fix warnin... |
852 |
lsp = __nfs4_find_lock_state(state, owner, NULL); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
853 854 855 |
if (lsp != NULL) break; if (new != NULL) { |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
856 857 858 859 860 861 862 |
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); |
8003d3c4a nfs4: treat lock ... |
863 |
new = nfs4_alloc_lock_state(state, owner); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
864 865 866 867 |
if (new == NULL) return NULL; } spin_unlock(&state->state_lock); |
9f958ab88 NFSv4: Reduce the... |
868 |
if (new != NULL) |
5ae67c4fe NFSv4: It is not ... |
869 |
nfs4_free_lock_state(state->owner->so_server, new); |
1da177e4c Linux-2.6.12-rc2 |
870 871 872 873 |
return lsp; } /* |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
874 875 |
* Release reference to lock_state, and free it if we see that * it is no longer in use |
1da177e4c Linux-2.6.12-rc2 |
876 |
*/ |
faf5f49c2 NFSv4: Make NFS c... |
877 |
void nfs4_put_lock_state(struct nfs4_lock_state *lsp) |
1da177e4c Linux-2.6.12-rc2 |
878 |
{ |
c8b2d0bfd NFSv4.1: Ensure t... |
879 |
struct nfs_server *server; |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
880 |
struct nfs4_state *state; |
1da177e4c Linux-2.6.12-rc2 |
881 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
882 883 884 |
if (lsp == NULL) return; state = lsp->ls_state; |
194bc1f48 fs, nfs: convert ... |
885 |
if (!refcount_dec_and_lock(&lsp->ls_count, &state->state_lock)) |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
886 887 888 889 890 |
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); |
0c0e0d3c0 nfs: revert "nfs4... |
891 892 893 894 895 896 |
server = state->owner->so_server; if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { struct nfs_client *clp = server->nfs_client; clp->cl_mvops->free_lock_state(server, lsp); } else |
c8b2d0bfd NFSv4.1: Ensure t... |
897 |
nfs4_free_lock_state(server, lsp); |
1da177e4c Linux-2.6.12-rc2 |
898 |
} |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
899 |
static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src) |
1da177e4c Linux-2.6.12-rc2 |
900 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
901 |
struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner; |
1da177e4c Linux-2.6.12-rc2 |
902 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
903 |
dst->fl_u.nfs4_fl.owner = lsp; |
194bc1f48 fs, nfs: convert ... |
904 |
refcount_inc(&lsp->ls_count); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
905 |
} |
1da177e4c Linux-2.6.12-rc2 |
906 |
|
8d0a8a9d0 [PATCH] NFSv4: Cl... |
907 |
static void nfs4_fl_release_lock(struct file_lock *fl) |
1da177e4c Linux-2.6.12-rc2 |
908 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
909 |
nfs4_put_lock_state(fl->fl_u.nfs4_fl.owner); |
1da177e4c Linux-2.6.12-rc2 |
910 |
} |
6aed62853 const: make file_... |
911 |
static const struct file_lock_operations nfs4_fl_lock_ops = { |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
912 913 914 915 916 |
.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 |
917 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
918 919 920 921 |
struct nfs4_lock_state *lsp; if (fl->fl_ops != NULL) return 0; |
8003d3c4a nfs4: treat lock ... |
922 |
lsp = nfs4_get_lock_state(state, fl->fl_owner); |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
923 924 925 926 927 |
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 |
928 |
} |
5521abfdc NFSv4: Resend the... |
929 930 |
static int nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state, |
173934754 NFSv4: change nfs... |
931 |
const struct nfs_lock_context *l_ctx) |
1da177e4c Linux-2.6.12-rc2 |
932 |
{ |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
933 |
struct nfs4_lock_state *lsp; |
8d4244316 NFSv4: enhance nf... |
934 |
fl_owner_t fl_owner, fl_flock_owner; |
5521abfdc NFSv4: Resend the... |
935 |
int ret = -ENOENT; |
1da177e4c Linux-2.6.12-rc2 |
936 |
|
173934754 NFSv4: change nfs... |
937 |
if (l_ctx == NULL) |
2a369153c NFS: Clean up hel... |
938 |
goto out; |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
939 |
if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) |
4fc8796d2 NFSv4: Clean up n... |
940 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
941 |
|
d51fdb87a NFS: discard nfs_... |
942 |
fl_owner = l_ctx->lockowner; |
8d4244316 NFSv4: enhance nf... |
943 |
fl_flock_owner = l_ctx->open_context->flock_owner; |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
944 |
spin_lock(&state->state_lock); |
8d4244316 NFSv4: enhance nf... |
945 |
lsp = __nfs4_find_lock_state(state, fl_owner, fl_flock_owner); |
ef1820f9b NFSv4: Don't try ... |
946 947 948 |
if (lsp && test_bit(NFS_LOCK_LOST, &lsp->ls_flags)) ret = -EIO; else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { |
f597c5379 NFSv4: Add helper... |
949 |
nfs4_stateid_copy(dst, &lsp->ls_stateid); |
5521abfdc NFSv4: Resend the... |
950 |
ret = 0; |
4fc8796d2 NFSv4: Clean up n... |
951 |
} |
8d0a8a9d0 [PATCH] NFSv4: Cl... |
952 |
spin_unlock(&state->state_lock); |
1da177e4c Linux-2.6.12-rc2 |
953 |
nfs4_put_lock_state(lsp); |
4fc8796d2 NFSv4: Clean up n... |
954 955 956 |
out: return ret; } |
c82bac6f4 NFSv4: Don't try ... |
957 |
bool nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) |
4fc8796d2 NFSv4: Clean up n... |
958 |
{ |
c82bac6f4 NFSv4: Don't try ... |
959 |
bool ret; |
92b40e938 NFSv4: Use the op... |
960 |
const nfs4_stateid *src; |
4fc8796d2 NFSv4: Clean up n... |
961 962 963 |
int seq; do { |
c82bac6f4 NFSv4: Don't try ... |
964 |
ret = false; |
92b40e938 NFSv4: Use the op... |
965 |
src = &zero_stateid; |
4fc8796d2 NFSv4: Clean up n... |
966 |
seq = read_seqbegin(&state->seqlock); |
c82bac6f4 NFSv4: Don't try ... |
967 |
if (test_bit(NFS_OPEN_STATE, &state->flags)) { |
92b40e938 NFSv4: Use the op... |
968 |
src = &state->open_stateid; |
c82bac6f4 NFSv4: Don't try ... |
969 970 |
ret = true; } |
92b40e938 NFSv4: Use the op... |
971 |
nfs4_stateid_copy(dst, src); |
4fc8796d2 NFSv4: Clean up n... |
972 |
} while (read_seqretry(&state->seqlock, seq)); |
c82bac6f4 NFSv4: Don't try ... |
973 |
return ret; |
4fc8796d2 NFSv4: Clean up n... |
974 975 976 977 978 979 |
} /* * Byte-range lock aware utility to initialize the stateid of read/write * requests. */ |
abf4e13cc NFSv4: Use the ri... |
980 |
int nfs4_select_rw_stateid(struct nfs4_state *state, |
173934754 NFSv4: change nfs... |
981 |
fmode_t fmode, const struct nfs_lock_context *l_ctx, |
a52458b48 NFS/NFSD/SUNRPC: ... |
982 |
nfs4_stateid *dst, const struct cred **cred) |
4fc8796d2 NFSv4: Clean up n... |
983 |
{ |
abf4e13cc NFSv4: Use the ri... |
984 |
int ret; |
7ebeb7fe7 NFSv4: If recover... |
985 986 |
if (!nfs4_valid_open_stateid(state)) return -EIO; |
abf4e13cc NFSv4: Use the ri... |
987 988 |
if (cred != NULL) *cred = NULL; |
173934754 NFSv4: change nfs... |
989 |
ret = nfs4_copy_lock_stateid(dst, state, l_ctx); |
ef1820f9b NFSv4: Don't try ... |
990 991 992 |
if (ret == -EIO) /* A lost lock - don't even consider delegations */ goto out; |
146d70caa NFS fix error ret... |
993 |
/* returns true if delegation stateid found and copied */ |
abf4e13cc NFSv4: Use the ri... |
994 |
if (nfs4_copy_delegation_stateid(state->inode, fmode, dst, cred)) { |
146d70caa NFS fix error ret... |
995 |
ret = 0; |
5521abfdc NFSv4: Resend the... |
996 |
goto out; |
146d70caa NFS fix error ret... |
997 |
} |
5521abfdc NFSv4: Resend the... |
998 |
if (ret != -ENOENT) |
ef1820f9b NFSv4: Don't try ... |
999 1000 1001 1002 |
/* nfs4_copy_delegation_stateid() didn't over-write * dst, so it still has the lock stateid which we now * choose to use. */ |
5521abfdc NFSv4: Resend the... |
1003 |
goto out; |
d9aba2b40 NFSv4: Don't use ... |
1004 |
ret = nfs4_copy_open_stateid(dst, state) ? 0 : -EAGAIN; |
5521abfdc NFSv4: Resend the... |
1005 |
out: |
3b66486c4 NFSv4.1: Select t... |
1006 1007 |
if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) dst->seqid = 0; |
5521abfdc NFSv4: Resend the... |
1008 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1009 |
} |
8535b2be5 NFSv4: Don't use ... |
1010 |
struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) |
cee54fc94 NFSv4: Add functi... |
1011 |
{ |
cee54fc94 NFSv4: Add functi... |
1012 |
struct nfs_seqid *new; |
8535b2be5 NFSv4: Don't use ... |
1013 |
new = kmalloc(sizeof(*new), gfp_mask); |
badc76dd0 NFSv4: Convert nf... |
1014 1015 1016 1017 1018 |
if (new == NULL) return ERR_PTR(-ENOMEM); new->sequence = counter; INIT_LIST_HEAD(&new->list); new->task = NULL; |
cee54fc94 NFSv4: Add functi... |
1019 1020 |
return new; } |
72211dbe7 NFSv4: Release th... |
1021 |
void nfs_release_seqid(struct nfs_seqid *seqid) |
1da177e4c Linux-2.6.12-rc2 |
1022 |
{ |
4601df20f NFSv4: Avoid thun... |
1023 |
struct nfs_seqid_counter *sequence; |
cee54fc94 NFSv4: Add functi... |
1024 |
|
a67964197 NFSv4: Check for ... |
1025 |
if (seqid == NULL || list_empty(&seqid->list)) |
4601df20f NFSv4: Avoid thun... |
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 |
return; sequence = seqid->sequence; spin_lock(&sequence->lock); list_del_init(&seqid->list); if (!list_empty(&sequence->list)) { struct nfs_seqid *next; next = list_first_entry(&sequence->list, struct nfs_seqid, list); rpc_wake_up_queued_task(&sequence->wait, next->task); |
2f74c0a05 NFSv4: Clean up t... |
1036 |
} |
4601df20f NFSv4: Avoid thun... |
1037 |
spin_unlock(&sequence->lock); |
72211dbe7 NFSv4: Release th... |
1038 1039 1040 1041 1042 |
} void nfs_free_seqid(struct nfs_seqid *seqid) { nfs_release_seqid(seqid); |
cee54fc94 NFSv4: Add functi... |
1043 |
kfree(seqid); |
1da177e4c Linux-2.6.12-rc2 |
1044 1045 1046 |
} /* |
cee54fc94 NFSv4: Add functi... |
1047 1048 |
* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or * failed with a seqid incrementing error - |
16a6ddc70 point to the righ... |
1049 |
* see comments nfs4.h:seqid_mutating_error() |
cee54fc94 NFSv4: Add functi... |
1050 |
*/ |
88d909399 NFSv4: nfs_increm... |
1051 |
static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
cee54fc94 NFSv4: Add functi... |
1052 1053 1054 1055 1056 |
{ switch (status) { case 0: break; case -NFS4ERR_BAD_SEQID: |
6f43ddccb NFSv4: Improve th... |
1057 1058 |
if (seqid->sequence->flags & NFS_SEQID_CONFIRMED) return; |
9a3ba4323 NFSv4: Rate limit... |
1059 |
pr_warn_ratelimited("NFS: v4 server returned a bad" |
497799e7c NFS: missing spac... |
1060 1061 1062 |
" sequence-id error on an" " unconfirmed sequence %p! ", |
6f43ddccb NFSv4: Improve th... |
1063 |
seqid->sequence); |
cee54fc94 NFSv4: Add functi... |
1064 1065 1066 1067 1068 1069 |
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BADXDR: case -NFS4ERR_RESOURCE: case -NFS4ERR_NOFILEHANDLE: |
406dab845 nfs: Fix "Don't i... |
1070 |
case -NFS4ERR_MOVED: |
cee54fc94 NFSv4: Add functi... |
1071 1072 |
/* Non-seqid mutating errors */ return; |
8b98a5324 NFS4: Remove unne... |
1073 |
} |
cee54fc94 NFSv4: Add functi... |
1074 1075 1076 1077 1078 1079 1080 1081 1082 |
/* * 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) { |
a67964197 NFSv4: Check for ... |
1083 1084 1085 1086 |
struct nfs4_state_owner *sp; if (seqid == NULL) return; |
34dc1ad75 nfs41: increment_... |
1087 |
|
a67964197 NFSv4: Check for ... |
1088 |
sp = container_of(seqid->sequence, struct nfs4_state_owner, so_seqid); |
34dc1ad75 nfs41: increment_... |
1089 |
if (status == -NFS4ERR_BAD_SEQID) |
86cfb0418 NFS: Don't discon... |
1090 |
nfs4_reset_state_owner(sp); |
a67964197 NFSv4: Check for ... |
1091 |
if (!nfs4_has_session(sp->so_server->nfs_client)) |
34dc1ad75 nfs41: increment_... |
1092 |
nfs_increment_seqid(status, seqid); |
cee54fc94 NFSv4: Add functi... |
1093 1094 1095 |
} /* |
cee54fc94 NFSv4: Add functi... |
1096 1097 |
* Increment the seqid if the LOCK/LOCKU succeeded, or * failed with a seqid incrementing error - |
16a6ddc70 point to the righ... |
1098 |
* see comments nfs4.h:seqid_mutating_error() |
cee54fc94 NFSv4: Add functi... |
1099 1100 1101 |
*/ void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) { |
a67964197 NFSv4: Check for ... |
1102 1103 |
if (seqid != NULL) nfs_increment_seqid(status, seqid); |
cee54fc94 NFSv4: Add functi... |
1104 1105 1106 1107 |
} int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) { |
a67964197 NFSv4: Check for ... |
1108 |
struct nfs_seqid_counter *sequence; |
cee54fc94 NFSv4: Add functi... |
1109 |
int status = 0; |
a67964197 NFSv4: Check for ... |
1110 1111 1112 |
if (seqid == NULL) goto out; sequence = seqid->sequence; |
cee54fc94 NFSv4: Add functi... |
1113 |
spin_lock(&sequence->lock); |
4601df20f NFSv4: Avoid thun... |
1114 |
seqid->task = task; |
2f74c0a05 NFSv4: Clean up t... |
1115 1116 1117 1118 |
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... |
1119 |
rpc_sleep_on(&sequence->wait, task, NULL); |
2f74c0a05 NFSv4: Clean up t... |
1120 1121 |
status = -EAGAIN; unlock: |
cee54fc94 NFSv4: Add functi... |
1122 |
spin_unlock(&sequence->lock); |
a67964197 NFSv4: Check for ... |
1123 |
out: |
cee54fc94 NFSv4: Add functi... |
1124 |
return status; |
1da177e4c Linux-2.6.12-rc2 |
1125 |
} |
e005e8041 NFSv4: Rename the... |
1126 |
static int nfs4_run_state_manager(void *); |
1da177e4c Linux-2.6.12-rc2 |
1127 |
|
e005e8041 NFSv4: Rename the... |
1128 |
static void nfs4_clear_state_manager_bit(struct nfs_client *clp) |
433fbe4c8 NFSv4: State reco... |
1129 |
{ |
4e857c58e arch: Mass conver... |
1130 |
smp_mb__before_atomic(); |
e005e8041 NFSv4: Rename the... |
1131 |
clear_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); |
4e857c58e arch: Mass conver... |
1132 |
smp_mb__after_atomic(); |
e005e8041 NFSv4: Rename the... |
1133 |
wake_up_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING); |
433fbe4c8 NFSv4: State reco... |
1134 1135 |
rpc_wake_up(&clp->cl_rpcwaitq); } |
1da177e4c Linux-2.6.12-rc2 |
1136 |
/* |
e005e8041 NFSv4: Rename the... |
1137 |
* Schedule the nfs_client asynchronous state management routine |
1da177e4c Linux-2.6.12-rc2 |
1138 |
*/ |
b0d3ded1a NFSv4: Clean up n... |
1139 |
void nfs4_schedule_state_manager(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
1140 |
{ |
5043e900f NFS: Convert inst... |
1141 |
struct task_struct *task; |
2446ab607 SUNRPC: Use RCU t... |
1142 |
char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; |
1da177e4c Linux-2.6.12-rc2 |
1143 |
|
aeabb3c96 NFSv4: Fix a NFSv... |
1144 |
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
e005e8041 NFSv4: Rename the... |
1145 1146 |
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) return; |
5043e900f NFS: Convert inst... |
1147 |
__module_get(THIS_MODULE); |
212bf41d8 fs, nfs: convert ... |
1148 |
refcount_inc(&clp->cl_count); |
2446ab607 SUNRPC: Use RCU t... |
1149 1150 1151 1152 1153 1154 1155 1156 |
/* The rcu_read_lock() is not strictly necessary, as the state * manager is the only thread that ever changes the rpc_xprt * after it's initialized. At this point, we're single threaded. */ rcu_read_lock(); snprintf(buf, sizeof(buf), "%s-manager", rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); rcu_read_unlock(); |
f170168b9 drivers: avoid pa... |
1157 |
task = kthread_run(nfs4_run_state_manager, clp, "%s", buf); |
2446ab607 SUNRPC: Use RCU t... |
1158 1159 1160 1161 1162 1163 1164 1165 |
if (IS_ERR(task)) { printk(KERN_ERR "%s: kthread_run: %ld ", __func__, PTR_ERR(task)); nfs4_clear_state_manager_bit(clp); nfs_put_client(clp); module_put(THIS_MODULE); } |
1da177e4c Linux-2.6.12-rc2 |
1166 1167 1168 |
} /* |
0400a6b0c NFSv4/4.1: Fix nf... |
1169 |
* Schedule a lease recovery attempt |
1da177e4c Linux-2.6.12-rc2 |
1170 |
*/ |
0400a6b0c NFSv4/4.1: Fix nf... |
1171 |
void nfs4_schedule_lease_recovery(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
1172 1173 1174 |
{ if (!clp) return; |
e598d843c NFSv4: Remove red... |
1175 1176 |
if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
cc0a98436 NFSv4: Add debugg... |
1177 1178 1179 |
dprintk("%s: scheduling lease recovery for server %s ", __func__, clp->cl_hostname); |
e005e8041 NFSv4: Rename the... |
1180 |
nfs4_schedule_state_manager(clp); |
1da177e4c Linux-2.6.12-rc2 |
1181 |
} |
9cb819683 NFSv4.1 handle DS... |
1182 |
EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); |
1da177e4c Linux-2.6.12-rc2 |
1183 |
|
c9fdeb280 NFS: Add basic mi... |
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 |
/** * nfs4_schedule_migration_recovery - trigger migration recovery * * @server: FSID that is migrating * * Returns zero if recovery has started, otherwise a negative NFS4ERR * value is returned. */ int nfs4_schedule_migration_recovery(const struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; if (server->fh_expire_type != NFS4_FH_PERSISTENT) { pr_err("NFS: volatile file handles not supported (server %s) ", clp->cl_hostname); return -NFS4ERR_IO; } if (test_bit(NFS_MIG_FAILED, &server->mig_status)) return -NFS4ERR_IO; dprintk("%s: scheduling migration recovery for (%llx:%llx) on %s ", __func__, (unsigned long long)server->fsid.major, (unsigned long long)server->fsid.minor, clp->cl_hostname); set_bit(NFS_MIG_IN_TRANSITION, &((struct nfs_server *)server)->mig_status); set_bit(NFS4CLNT_MOVED, &clp->cl_state); nfs4_schedule_state_manager(clp); return 0; } EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery); |
b7f7a66e4 NFS: Support NFS4... |
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 |
/** * nfs4_schedule_lease_moved_recovery - start lease-moved recovery * * @clp: server to check for moved leases * */ void nfs4_schedule_lease_moved_recovery(struct nfs_client *clp) { dprintk("%s: scheduling lease-moved recovery for client ID %llx on %s ", __func__, clp->cl_clientid, clp->cl_hostname); set_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state); nfs4_schedule_state_manager(clp); } EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery); |
330212796 NFSv4: Move nfs4_... |
1237 1238 1239 1240 1241 |
int nfs4_wait_clnt_recover(struct nfs_client *clp) { int res; might_sleep(); |
212bf41d8 fs, nfs: convert ... |
1242 |
refcount_inc(&clp->cl_count); |
743162013 sched: Remove pro... |
1243 1244 |
res = wait_on_bit_action(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, nfs_wait_bit_killable, TASK_KILLABLE); |
330212796 NFSv4: Move nfs4_... |
1245 |
if (res) |
0625c2dd6 NFS: Fix possible... |
1246 |
goto out; |
330212796 NFSv4: Move nfs4_... |
1247 |
if (clp->cl_cons_state < 0) |
0625c2dd6 NFS: Fix possible... |
1248 1249 1250 1251 |
res = clp->cl_cons_state; out: nfs_put_client(clp); return res; |
330212796 NFSv4: Move nfs4_... |
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 |
} int nfs4_client_recover_expired_lease(struct nfs_client *clp) { unsigned int loop; int ret; for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { ret = nfs4_wait_clnt_recover(clp); if (ret != 0) break; if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) break; nfs4_schedule_state_manager(clp); ret = -EIO; } return ret; } |
ad1e39682 NFSv4.0: Re-estab... |
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 |
/* * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN * @clp: client to process * * Set the NFS4CLNT_LEASE_EXPIRED state in order to force a * resend of the SETCLIENTID and hence re-establish the * callback channel. Then return all existing delegations. */ static void nfs40_handle_cb_pathdown(struct nfs_client *clp) { set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs_expire_all_delegations(clp); |
cc0a98436 NFSv4: Add debugg... |
1283 1284 1285 |
dprintk("%s: handling CB_PATHDOWN recovery for server %s ", __func__, clp->cl_hostname); |
ad1e39682 NFSv4.0: Re-estab... |
1286 |
} |
042b60beb NFSv4: renewd nee... |
1287 1288 |
void nfs4_schedule_path_down_recovery(struct nfs_client *clp) { |
ad1e39682 NFSv4.0: Re-estab... |
1289 |
nfs40_handle_cb_pathdown(clp); |
042b60beb NFSv4: renewd nee... |
1290 1291 |
nfs4_schedule_state_manager(clp); } |
f9feab1e1 NFSv4: nfs4_state... |
1292 |
static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) |
b79a4a1b4 NFSv4: Fix state ... |
1293 |
{ |
7ebeb7fe7 NFSv4: If recover... |
1294 1295 |
if (!nfs4_valid_open_stateid(state)) return 0; |
b79a4a1b4 NFSv4: Fix state ... |
1296 1297 1298 1299 1300 1301 |
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... |
1302 |
set_bit(NFS_OWNER_RECLAIM_REBOOT, &state->owner->so_flags); |
b79a4a1b4 NFSv4: Fix state ... |
1303 1304 1305 |
set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); return 1; } |
4f14c194a NFSv4: Clear the ... |
1306 |
int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) |
b79a4a1b4 NFSv4: Fix state ... |
1307 |
{ |
7ebeb7fe7 NFSv4: If recover... |
1308 1309 |
if (!nfs4_valid_open_stateid(state)) return 0; |
b79a4a1b4 NFSv4: Fix state ... |
1310 1311 |
set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); |
7eff03aec NFSv4: Add a reco... |
1312 |
set_bit(NFS_OWNER_RECLAIM_NOGRACE, &state->owner->so_flags); |
b79a4a1b4 NFSv4: Fix state ... |
1313 1314 1315 |
set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); return 1; } |
5d422301f NFSv4: Fail I/O i... |
1316 |
int nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) |
0400a6b0c NFSv4/4.1: Fix nf... |
1317 1318 |
{ struct nfs_client *clp = server->nfs_client; |
7ebeb7fe7 NFSv4: If recover... |
1319 |
if (!nfs4_state_mark_reclaim_nograce(clp, state)) |
5d422301f NFSv4: Fail I/O i... |
1320 |
return -EBADF; |
994b15b98 NFSv4.1 fix infin... |
1321 1322 |
nfs_inode_find_delegation_state_and_recover(state->inode, &state->stateid); |
cc0a98436 NFSv4: Add debugg... |
1323 1324 1325 |
dprintk("%s: scheduling stateid recovery for server %s ", __func__, clp->cl_hostname); |
0400a6b0c NFSv4/4.1: Fix nf... |
1326 |
nfs4_schedule_state_manager(clp); |
5d422301f NFSv4: Fail I/O i... |
1327 |
return 0; |
0400a6b0c NFSv4/4.1: Fix nf... |
1328 |
} |
9cb819683 NFSv4.1 handle DS... |
1329 |
EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery); |
0400a6b0c NFSv4/4.1: Fix nf... |
1330 |
|
6c2d8f8d3 NFSv4: nfs_inode_... |
1331 1332 1333 1334 1335 1336 1337 1338 1339 |
static struct nfs4_lock_state * nfs_state_find_lock_state_by_stateid(struct nfs4_state *state, const nfs4_stateid *stateid) { struct nfs4_lock_state *pos; list_for_each_entry(pos, &state->lock_states, ls_locks) { if (!test_bit(NFS_LOCK_INITIALIZED, &pos->ls_flags)) continue; |
42c304c34 NFS: nfs_inode_fi... |
1340 |
if (nfs4_stateid_match_or_older(&pos->ls_stateid, stateid)) |
6c2d8f8d3 NFSv4: nfs_inode_... |
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 |
return pos; } return NULL; } static bool nfs_state_lock_state_matches_stateid(struct nfs4_state *state, const nfs4_stateid *stateid) { bool found = false; if (test_bit(LK_STATE_IN_USE, &state->flags)) { spin_lock(&state->state_lock); if (nfs_state_find_lock_state_by_stateid(state, stateid)) found = true; spin_unlock(&state->state_lock); } return found; } |
a1d0b5eeb NFS: Properly han... |
1359 1360 1361 1362 1363 1364 1365 1366 |
void nfs_inode_find_state_and_recover(struct inode *inode, const nfs4_stateid *stateid) { struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *ctx; struct nfs4_state *state; bool found = false; |
0de43976f NFS: Convert look... |
1367 1368 |
rcu_read_lock(); list_for_each_entry_rcu(ctx, &nfsi->open_files, list) { |
a1d0b5eeb NFS: Properly han... |
1369 1370 1371 |
state = ctx->state; if (state == NULL) continue; |
42c304c34 NFS: nfs_inode_fi... |
1372 |
if (nfs4_stateid_match_or_older(&state->stateid, stateid) && |
7ebeb7fe7 NFSv4: If recover... |
1373 |
nfs4_state_mark_reclaim_nograce(clp, state)) { |
6c2d8f8d3 NFSv4: nfs_inode_... |
1374 |
found = true; |
a1d0b5eeb NFS: Properly han... |
1375 |
continue; |
6c2d8f8d3 NFSv4: nfs_inode_... |
1376 |
} |
42c304c34 NFS: nfs_inode_fi... |
1377 1378 |
if (test_bit(NFS_OPEN_STATE, &state->flags) && nfs4_stateid_match_or_older(&state->open_stateid, stateid) && |
46280d9d3 NFSv4: Check the ... |
1379 1380 1381 1382 |
nfs4_state_mark_reclaim_nograce(clp, state)) { found = true; continue; } |
7ebeb7fe7 NFSv4: If recover... |
1383 1384 |
if (nfs_state_lock_state_matches_stateid(state, stateid) && nfs4_state_mark_reclaim_nograce(clp, state)) |
6c2d8f8d3 NFSv4: nfs_inode_... |
1385 |
found = true; |
a1d0b5eeb NFS: Properly han... |
1386 |
} |
0de43976f NFS: Convert look... |
1387 |
rcu_read_unlock(); |
6c2d8f8d3 NFSv4: nfs_inode_... |
1388 1389 |
nfs_inode_find_delegation_state_and_recover(inode, stateid); |
a1d0b5eeb NFS: Properly han... |
1390 1391 1392 |
if (found) nfs4_schedule_state_manager(clp); } |
86dbd08b3 NFSv4: Print an e... |
1393 |
static void nfs4_state_mark_open_context_bad(struct nfs4_state *state, int err) |
c58c84418 NFS: Don't accept... |
1394 1395 1396 1397 |
{ struct inode *inode = state->inode; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *ctx; |
0de43976f NFS: Convert look... |
1398 1399 |
rcu_read_lock(); list_for_each_entry_rcu(ctx, &nfsi->open_files, list) { |
c58c84418 NFS: Don't accept... |
1400 1401 1402 |
if (ctx->state != state) continue; set_bit(NFS_CONTEXT_BAD, &ctx->flags); |
86dbd08b3 NFSv4: Print an e... |
1403 1404 1405 |
pr_warn("NFSv4: state recovery failed for open file %pd2, " "error = %d ", ctx->dentry, err); |
c58c84418 NFS: Don't accept... |
1406 |
} |
0de43976f NFS: Convert look... |
1407 |
rcu_read_unlock(); |
c58c84418 NFS: Don't accept... |
1408 |
} |
5d422301f NFSv4: Fail I/O i... |
1409 1410 1411 |
static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error) { set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags); |
86dbd08b3 NFSv4: Print an e... |
1412 |
nfs4_state_mark_open_context_bad(state, error); |
5d422301f NFSv4: Fail I/O i... |
1413 |
} |
a1d0b5eeb NFS: Properly han... |
1414 |
|
028600143 NFSv4: Clean up f... |
1415 |
static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
1416 1417 |
{ struct inode *inode = state->inode; |
19e03c570 NFSv4: Ensure tha... |
1418 |
struct nfs_inode *nfsi = NFS_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
1419 |
struct file_lock *fl; |
dce2630c7 NFSv4: always set... |
1420 |
struct nfs4_lock_state *lsp; |
1da177e4c Linux-2.6.12-rc2 |
1421 |
int status = 0; |
5263e31e4 locks: move flock... |
1422 |
struct file_lock_context *flctx = inode->i_flctx; |
bd61e0a9c locks: convert po... |
1423 |
struct list_head *list; |
1da177e4c Linux-2.6.12-rc2 |
1424 |
|
bd61e0a9c locks: convert po... |
1425 |
if (flctx == NULL) |
3f09df70e NFS: Ensure we al... |
1426 |
return 0; |
bd61e0a9c locks: convert po... |
1427 |
list = &flctx->flc_posix; |
3f09df70e NFS: Ensure we al... |
1428 |
/* Guard against delegation returns and new lock/unlock calls */ |
19e03c570 NFSv4: Ensure tha... |
1429 |
down_write(&nfsi->rwsem); |
6109c8503 locks: add a dedi... |
1430 |
spin_lock(&flctx->flc_lock); |
bd61e0a9c locks: convert po... |
1431 1432 |
restart: list_for_each_entry(fl, list, fl_list) { |
5263e31e4 locks: move flock... |
1433 1434 |
if (nfs_file_open_context(fl->fl_file)->state != state) continue; |
6109c8503 locks: add a dedi... |
1435 |
spin_unlock(&flctx->flc_lock); |
5263e31e4 locks: move flock... |
1436 1437 1438 1439 |
status = ops->recover_lock(state, fl); switch (status) { case 0: break; |
67e7b52d4 NFSv4: Ensure sta... |
1440 |
case -ETIMEDOUT: |
5263e31e4 locks: move flock... |
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 |
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: case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: goto out; default: pr_err("NFS: %s: unhandled error %d ", __func__, status); |
df561f668 treewide: Use fal... |
1457 |
fallthrough; |
5263e31e4 locks: move flock... |
1458 1459 1460 1461 |
case -ENOMEM: case -NFS4ERR_DENIED: case -NFS4ERR_RECLAIM_BAD: case -NFS4ERR_RECLAIM_CONFLICT: |
dce2630c7 NFSv4: always set... |
1462 1463 1464 |
lsp = fl->fl_u.nfs4_fl.owner; if (lsp) set_bit(NFS_LOCK_LOST, &lsp->ls_flags); |
5263e31e4 locks: move flock... |
1465 1466 |
status = 0; } |
6109c8503 locks: add a dedi... |
1467 |
spin_lock(&flctx->flc_lock); |
5263e31e4 locks: move flock... |
1468 |
} |
bd61e0a9c locks: convert po... |
1469 1470 1471 1472 |
if (list == &flctx->flc_posix) { list = &flctx->flc_flock; goto restart; } |
6109c8503 locks: add a dedi... |
1473 |
spin_unlock(&flctx->flc_lock); |
965b5d679 NFSv4: Handle mor... |
1474 |
out: |
19e03c570 NFSv4: Ensure tha... |
1475 |
up_write(&nfsi->rwsem); |
1da177e4c Linux-2.6.12-rc2 |
1476 1477 |
return status; } |
80f423688 NFSv4: Split out ... |
1478 1479 1480 1481 |
#ifdef CONFIG_NFS_V4_2 static void nfs42_complete_copies(struct nfs4_state_owner *sp, struct nfs4_state *state) { struct nfs4_copy_state *copy; |
0e65a32c8 NFS: handle sourc... |
1482 1483 |
if (!test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags) && !test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags)) |
80f423688 NFSv4: Split out ... |
1484 1485 1486 1487 |
return; spin_lock(&sp->so_server->nfs_client->cl_lock); list_for_each_entry(copy, &sp->so_server->ss_copies, copies) { |
0e65a32c8 NFS: handle sourc... |
1488 1489 1490 1491 |
if ((test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags) && !nfs4_stateid_match_other(&state->stateid, ©->parent_dst_state->stateid))) continue; |
80f423688 NFSv4: Split out ... |
1492 |
copy->flags = 1; |
0e65a32c8 NFS: handle sourc... |
1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 |
if (test_and_clear_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags)) { clear_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags); complete(©->completion); } } list_for_each_entry(copy, &sp->so_server->ss_copies, src_copies) { if ((test_bit(NFS_CLNT_SRC_SSC_COPY_STATE, &state->flags) && !nfs4_stateid_match_other(&state->stateid, ©->parent_src_state->stateid))) continue; copy->flags = 1; if (test_and_clear_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags)) complete(©->completion); |
80f423688 NFSv4: Split out ... |
1508 1509 1510 1511 1512 1513 1514 1515 1516 |
} spin_unlock(&sp->so_server->nfs_client->cl_lock); } #else /* !CONFIG_NFS_V4_2 */ static inline void nfs42_complete_copies(struct nfs4_state_owner *sp, struct nfs4_state *state) { } #endif /* CONFIG_NFS_V4_2 */ |
cb7a8384d NFS: Split out th... |
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 |
static int __nfs4_reclaim_open_state(struct nfs4_state_owner *sp, struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) { struct nfs4_lock_state *lock; int status; status = ops->recover_open(sp, state); if (status < 0) return status; status = nfs4_reclaim_locks(state, ops); if (status < 0) return status; if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) { spin_lock(&state->state_lock); list_for_each_entry(lock, &state->lock_states, ls_locks) { |
21f86d2d6 NFS4: Trace lock ... |
1534 |
trace_nfs4_state_lock_reclaim(state, lock); |
cb7a8384d NFS: Split out th... |
1535 1536 1537 1538 1539 1540 |
if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags)) pr_warn_ratelimited("NFS: %s: Lock reclaim failed! ", __func__); } spin_unlock(&state->state_lock); } |
80f423688 NFSv4: Split out ... |
1541 |
nfs42_complete_copies(sp, state); |
cb7a8384d NFS: Split out th... |
1542 1543 1544 |
clear_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); return status; } |
028600143 NFSv4: Clean up f... |
1545 |
static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs4_state_recovery_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
1546 1547 |
{ struct nfs4_state *state; |
c34fae003 NFSv4: When recov... |
1548 |
unsigned int loop = 0; |
1da177e4c Linux-2.6.12-rc2 |
1549 |
int status = 0; |
0b9018b9c NFS: skip recover... |
1550 1551 1552 |
#ifdef CONFIG_NFS_V4_2 bool found_ssc_copy_state = false; #endif /* CONFIG_NFS_V4_2 */ |
1da177e4c Linux-2.6.12-rc2 |
1553 1554 1555 1556 1557 1558 1559 1560 1561 |
/* 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... |
1562 |
spin_lock(&sp->so_lock); |
abbec2da1 NFS: Use raw_writ... |
1563 |
raw_write_seqcount_begin(&sp->so_reclaim_seqcount); |
c137afabe NFSv4: Allow the ... |
1564 |
restart: |
1da177e4c Linux-2.6.12-rc2 |
1565 |
list_for_each_entry(state, &sp->so_states, open_states) { |
b79a4a1b4 NFSv4: Fix state ... |
1566 1567 |
if (!test_and_clear_bit(ops->state_flag_bit, &state->flags)) continue; |
5d422301f NFSv4: Fail I/O i... |
1568 1569 |
if (!nfs4_valid_open_stateid(state)) continue; |
1da177e4c Linux-2.6.12-rc2 |
1570 1571 |
if (state->state == 0) continue; |
0b9018b9c NFS: skip recover... |
1572 1573 1574 1575 1576 1577 1578 |
#ifdef CONFIG_NFS_V4_2 if (test_bit(NFS_SRV_SSC_COPY_STATE, &state->flags)) { nfs4_state_mark_recovery_failed(state, -EIO); found_ssc_copy_state = true; continue; } #endif /* CONFIG_NFS_V4_2 */ |
ace9fad43 NFSv4: Convert st... |
1579 |
refcount_inc(&state->count); |
fe1d81952 NFSv4: Ensure tha... |
1580 |
spin_unlock(&sp->so_lock); |
cb7a8384d NFS: Split out th... |
1581 |
status = __nfs4_reclaim_open_state(sp, state, ops); |
cb7a8384d NFS: Split out th... |
1582 |
|
1da177e4c Linux-2.6.12-rc2 |
1583 |
switch (status) { |
35a61606a NFS: Reduce inden... |
1584 |
default: |
c34fae003 NFSv4: When recov... |
1585 1586 |
if (status >= 0) { loop = 0; |
b79a4a1b4 NFSv4: Fix state ... |
1587 |
break; |
c34fae003 NFSv4: When recov... |
1588 |
} |
35a61606a NFS: Reduce inden... |
1589 1590 |
printk(KERN_ERR "NFS: %s: unhandled error %d ", __func__, status); |
df561f668 treewide: Use fal... |
1591 |
fallthrough; |
35a61606a NFS: Reduce inden... |
1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 |
case -ENOENT: case -ENOMEM: case -EACCES: case -EROFS: case -EIO: case -ESTALE: /* Open state on this file cannot be recovered */ nfs4_state_mark_recovery_failed(state, status); break; case -EAGAIN: ssleep(1); |
c34fae003 NFSv4: When recov... |
1603 1604 1605 1606 |
if (loop++ < 10) { set_bit(ops->state_flag_bit, &state->flags); break; } |
df561f668 treewide: Use fal... |
1607 |
fallthrough; |
35a61606a NFS: Reduce inden... |
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 |
case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_OLD_STATEID: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_RECLAIM_BAD: case -NFS4ERR_RECLAIM_CONFLICT: nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); break; case -NFS4ERR_EXPIRED: case -NFS4ERR_NO_GRACE: nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
df561f668 treewide: Use fal... |
1619 |
fallthrough; |
35a61606a NFS: Reduce inden... |
1620 1621 1622 1623 1624 |
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
67e7b52d4 NFSv4: Ensure sta... |
1625 |
case -ETIMEDOUT: |
35a61606a NFS: Reduce inden... |
1626 |
goto out_err; |
1da177e4c Linux-2.6.12-rc2 |
1627 |
} |
fe1d81952 NFSv4: Ensure tha... |
1628 |
nfs4_put_open_state(state); |
c137afabe NFSv4: Allow the ... |
1629 |
spin_lock(&sp->so_lock); |
fe1d81952 NFSv4: Ensure tha... |
1630 |
goto restart; |
1da177e4c Linux-2.6.12-rc2 |
1631 |
} |
abbec2da1 NFS: Use raw_writ... |
1632 |
raw_write_seqcount_end(&sp->so_reclaim_seqcount); |
fe1d81952 NFSv4: Ensure tha... |
1633 |
spin_unlock(&sp->so_lock); |
0b9018b9c NFS: skip recover... |
1634 1635 1636 1637 |
#ifdef CONFIG_NFS_V4_2 if (found_ssc_copy_state) return -EIO; #endif /* CONFIG_NFS_V4_2 */ |
1da177e4c Linux-2.6.12-rc2 |
1638 1639 |
return 0; out_err: |
fe1d81952 NFSv4: Ensure tha... |
1640 |
nfs4_put_open_state(state); |
c137afabe NFSv4: Allow the ... |
1641 |
spin_lock(&sp->so_lock); |
abbec2da1 NFS: Use raw_writ... |
1642 |
raw_write_seqcount_end(&sp->so_reclaim_seqcount); |
c137afabe NFSv4: Allow the ... |
1643 |
spin_unlock(&sp->so_lock); |
1da177e4c Linux-2.6.12-rc2 |
1644 1645 |
return status; } |
b79a4a1b4 NFSv4: Fix state ... |
1646 1647 1648 1649 1650 1651 1652 1653 |
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... |
1654 |
spin_lock(&state->state_lock); |
b79a4a1b4 NFSv4: Fix state ... |
1655 |
list_for_each_entry(lock, &state->lock_states, ls_locks) { |
b79a4a1b4 NFSv4: Fix state ... |
1656 |
lock->ls_seqid.flags = 0; |
795a88c96 NFSv4: Convert th... |
1657 |
clear_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags); |
b79a4a1b4 NFSv4: Fix state ... |
1658 |
} |
4b44b40e0 NFSv4: Ensure cor... |
1659 |
spin_unlock(&state->state_lock); |
b79a4a1b4 NFSv4: Fix state ... |
1660 |
} |
24d292b89 NFS: Move cl_stat... |
1661 1662 |
static void nfs4_reset_seqids(struct nfs_server *server, int (*mark_reclaim)(struct nfs_client *clp, struct nfs4_state *state)) |
cee54fc94 NFSv4: Add functi... |
1663 |
{ |
24d292b89 NFS: Move cl_stat... |
1664 |
struct nfs_client *clp = server->nfs_client; |
cee54fc94 NFSv4: Add functi... |
1665 |
struct nfs4_state_owner *sp; |
9f958ab88 NFSv4: Reduce the... |
1666 |
struct rb_node *pos; |
cee54fc94 NFSv4: Add functi... |
1667 |
struct nfs4_state *state; |
cee54fc94 NFSv4: Add functi... |
1668 |
|
24d292b89 NFS: Move cl_stat... |
1669 1670 1671 1672 1673 |
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... |
1674 |
sp->so_seqid.flags = 0; |
ec0734282 NFSv4: Fix up loc... |
1675 |
spin_lock(&sp->so_lock); |
cee54fc94 NFSv4: Add functi... |
1676 |
list_for_each_entry(state, &sp->so_states, open_states) { |
b79a4a1b4 NFSv4: Fix state ... |
1677 1678 |
if (mark_reclaim(clp, state)) nfs4_clear_open_state(state); |
cee54fc94 NFSv4: Add functi... |
1679 |
} |
ec0734282 NFSv4: Fix up loc... |
1680 |
spin_unlock(&sp->so_lock); |
cee54fc94 NFSv4: Add functi... |
1681 |
} |
24d292b89 NFS: Move cl_stat... |
1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 |
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... |
1694 |
} |
b79a4a1b4 NFSv4: Fix state ... |
1695 1696 1697 1698 1699 1700 |
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); } |
0048fdd06 NFSv4.1: RECLAIM_... |
1701 |
static int nfs4_reclaim_complete(struct nfs_client *clp, |
965e9c23d NFSv4.1: Ensure t... |
1702 |
const struct nfs4_state_recovery_ops *ops, |
a52458b48 NFS/NFSD/SUNRPC: ... |
1703 |
const struct cred *cred) |
fce5c838e nfs41: RECLAIM_CO... |
1704 1705 1706 |
{ /* Notify the server we're done reclaiming our state */ if (ops->reclaim_complete) |
0048fdd06 NFSv4.1: RECLAIM_... |
1707 1708 |
return ops->reclaim_complete(clp, cred); return 0; |
fce5c838e nfs41: RECLAIM_CO... |
1709 |
} |
24d292b89 NFS: Move cl_stat... |
1710 |
static void nfs4_clear_reclaim_server(struct nfs_server *server) |
b79a4a1b4 NFSv4: Fix state ... |
1711 |
{ |
24d292b89 NFS: Move cl_stat... |
1712 |
struct nfs_client *clp = server->nfs_client; |
b79a4a1b4 NFSv4: Fix state ... |
1713 1714 1715 |
struct nfs4_state_owner *sp; struct rb_node *pos; struct nfs4_state *state; |
24d292b89 NFS: Move cl_stat... |
1716 1717 1718 1719 1720 |
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 ... |
1721 1722 |
spin_lock(&sp->so_lock); list_for_each_entry(state, &sp->so_states, open_states) { |
24d292b89 NFS: Move cl_stat... |
1723 1724 |
if (!test_and_clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags)) |
b79a4a1b4 NFSv4: Fix state ... |
1725 1726 1727 1728 1729 |
continue; nfs4_state_mark_reclaim_nograce(clp, state); } spin_unlock(&sp->so_lock); } |
24d292b89 NFS: Move cl_stat... |
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 |
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 ... |
1744 1745 |
nfs_delegation_reap_unclaimed(clp); |
6eaa61496 NFSv4: Don't call... |
1746 1747 1748 1749 1750 |
return 1; } static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) { |
965e9c23d NFSv4.1: Ensure t... |
1751 |
const struct nfs4_state_recovery_ops *ops; |
a52458b48 NFS/NFSD/SUNRPC: ... |
1752 |
const struct cred *cred; |
0048fdd06 NFSv4.1: RECLAIM_... |
1753 |
int err; |
965e9c23d NFSv4.1: Ensure t... |
1754 |
|
6eaa61496 NFSv4: Don't call... |
1755 1756 |
if (!nfs4_state_clear_reclaim_reboot(clp)) return; |
965e9c23d NFSv4.1: Ensure t... |
1757 |
ops = clp->cl_mvops->reboot_recovery_ops; |
73d8bde5e NFS: Never use us... |
1758 |
cred = nfs4_get_clid_cred(clp); |
0048fdd06 NFSv4.1: RECLAIM_... |
1759 |
err = nfs4_reclaim_complete(clp, ops, cred); |
a52458b48 NFS/NFSD/SUNRPC: ... |
1760 |
put_cred(cred); |
0048fdd06 NFSv4.1: RECLAIM_... |
1761 1762 |
if (err == -NFS4ERR_CONN_NOT_BOUND_TO_SESSION) set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); |
b79a4a1b4 NFSv4: Fix state ... |
1763 |
} |
b79a4a1b4 NFSv4: Fix state ... |
1764 1765 |
static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) { |
45870d690 NFSv4.1: Test del... |
1766 |
nfs_mark_test_expired_all_delegations(clp); |
b79a4a1b4 NFSv4: Fix state ... |
1767 1768 |
nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); } |
4f7cdf18e NFSv4: The state ... |
1769 |
static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) |
e598d843c NFSv4: Remove red... |
1770 1771 |
{ switch (error) { |
000d3f956 NFS: Reduce inden... |
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 |
case 0: break; case -NFS4ERR_CB_PATH_DOWN: nfs40_handle_cb_pathdown(clp); break; case -NFS4ERR_NO_GRACE: nfs4_state_end_reclaim_reboot(clp); break; case -NFS4ERR_STALE_CLIENTID: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs4_state_start_reclaim_reboot(clp); break; case -NFS4ERR_EXPIRED: set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs4_state_start_reclaim_nograce(clp); break; case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_DEADSESSION: case -NFS4ERR_SEQ_FALSE_RETRY: case -NFS4ERR_SEQ_MISORDERED: set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); /* Zero session reset errors */ break; case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); break; default: dprintk("%s: failed to handle error %d for server %s ", __func__, error, clp->cl_hostname); return error; |
e598d843c NFSv4: Remove red... |
1805 |
} |
cc0a98436 NFSv4: Add debugg... |
1806 1807 1808 |
dprintk("%s: handled error %d for server %s ", __func__, error, clp->cl_hostname); |
4f38e4aad NFSv4: Don't erro... |
1809 |
return 0; |
e598d843c NFSv4: Remove red... |
1810 |
} |
028600143 NFSv4: Clean up f... |
1811 |
static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
1812 |
{ |
24d292b89 NFS: Move cl_stat... |
1813 1814 |
struct nfs4_state_owner *sp; struct nfs_server *server; |
9f958ab88 NFSv4: Reduce the... |
1815 |
struct rb_node *pos; |
c77e22834 NFSv4: Fix a pote... |
1816 |
LIST_HEAD(freeme); |
1da177e4c Linux-2.6.12-rc2 |
1817 |
int status = 0; |
7eff03aec NFSv4: Add a reco... |
1818 |
restart: |
24d292b89 NFS: Move cl_stat... |
1819 1820 |
rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
c77e22834 NFSv4: Fix a pote... |
1821 |
nfs4_purge_state_owners(server, &freeme); |
24d292b89 NFS: Move cl_stat... |
1822 1823 1824 1825 1826 1827 1828 1829 1830 |
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; |
4a0954ef3 NFSv4: Don't try ... |
1831 1832 |
if (!atomic_inc_not_zero(&sp->so_count)) continue; |
24d292b89 NFS: Move cl_stat... |
1833 1834 1835 1836 1837 1838 1839 |
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); |
df817ba35 NFSv4: fix open/l... |
1840 1841 |
status = nfs4_recovery_handle_error(clp, status); return (status != 0) ? status : -EAGAIN; |
24d292b89 NFS: Move cl_stat... |
1842 |
} |
7eff03aec NFSv4: Add a reco... |
1843 |
nfs4_put_state_owner(sp); |
24d292b89 NFS: Move cl_stat... |
1844 |
goto restart; |
7eff03aec NFSv4: Add a reco... |
1845 |
} |
24d292b89 NFS: Move cl_stat... |
1846 |
spin_unlock(&clp->cl_lock); |
028600143 NFSv4: Clean up f... |
1847 |
} |
24d292b89 NFS: Move cl_stat... |
1848 |
rcu_read_unlock(); |
c77e22834 NFSv4: Fix a pote... |
1849 |
nfs4_free_state_owners(&freeme); |
df817ba35 NFSv4: fix open/l... |
1850 |
return 0; |
028600143 NFSv4: Clean up f... |
1851 1852 1853 1854 |
} static int nfs4_check_lease(struct nfs_client *clp) { |
a52458b48 NFS/NFSD/SUNRPC: ... |
1855 |
const struct cred *cred; |
c48f4f354 NFSv41: Convert t... |
1856 1857 |
const struct nfs4_state_maintenance_ops *ops = clp->cl_mvops->state_renewal_ops; |
4f38e4aad NFSv4: Don't erro... |
1858 |
int status; |
1da177e4c Linux-2.6.12-rc2 |
1859 |
|
0f605b560 NFSv4: Don't tell... |
1860 1861 1862 |
/* Is the client already known to have an expired lease? */ if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) return 0; |
f15e1e8bc NFSv4: don't requ... |
1863 |
cred = ops->get_state_renewal_cred(clp); |
0f605b560 NFSv4: Don't tell... |
1864 |
if (cred == NULL) { |
73d8bde5e NFS: Never use us... |
1865 |
cred = nfs4_get_clid_cred(clp); |
4f38e4aad NFSv4: Don't erro... |
1866 |
status = -ENOKEY; |
0f605b560 NFSv4: Don't tell... |
1867 1868 |
if (cred == NULL) goto out; |
286d7d6a0 NFSv4: Remove req... |
1869 |
} |
8e69514f2 nfs41: support mi... |
1870 |
status = ops->renew_lease(clp, cred); |
a52458b48 NFS/NFSD/SUNRPC: ... |
1871 |
put_cred(cred); |
bc7a05ca5 NFSv4: Handle tim... |
1872 1873 1874 1875 |
if (status == -ETIMEDOUT) { set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); return 0; } |
0f605b560 NFSv4: Don't tell... |
1876 |
out: |
4f7cdf18e NFSv4: The state ... |
1877 |
return nfs4_recovery_handle_error(clp, status); |
028600143 NFSv4: Clean up f... |
1878 |
} |
47b803c8d NFSv4.0 reclaim r... |
1879 1880 |
/* Set NFS4CLNT_LEASE_EXPIRED and reclaim reboot state for all v4.0 errors * and for recoverable errors on EXCHANGE_ID for v4.1 |
2a6ee6aa2 NFSv4: Clean up t... |
1881 1882 1883 1884 |
*/ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) { switch (status) { |
89a217360 NFSv4.1: Handle N... |
1885 1886 1887 1888 1889 |
case -NFS4ERR_SEQ_MISORDERED: if (test_and_set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) return -ESERVERFAULT; /* Lease confirmation error: retry after purging the lease */ ssleep(1); |
47b803c8d NFSv4.0 reclaim r... |
1890 1891 |
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); break; |
2a6ee6aa2 NFSv4: Clean up t... |
1892 1893 |
case -NFS4ERR_STALE_CLIENTID: clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
47b803c8d NFSv4.0 reclaim r... |
1894 |
nfs4_state_start_reclaim_reboot(clp); |
2a6ee6aa2 NFSv4: Clean up t... |
1895 |
break; |
de7348312 NFS: Treat NFS4ER... |
1896 1897 1898 1899 1900 1901 1902 |
case -NFS4ERR_CLID_INUSE: pr_err("NFS: Server %s reports our clientid is in use ", clp->cl_hostname); nfs_mark_client_ready(clp, -EPERM); clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); return -EPERM; |
2a6ee6aa2 NFSv4: Clean up t... |
1903 |
case -EACCES: |
2a6ee6aa2 NFSv4: Clean up t... |
1904 |
case -NFS4ERR_DELAY: |
2a6ee6aa2 NFSv4: Clean up t... |
1905 1906 1907 1908 1909 1910 1911 |
case -EAGAIN: ssleep(1); break; case -NFS4ERR_MINOR_VERS_MISMATCH: if (clp->cl_cons_state == NFS_CS_SESSION_INITING) nfs_mark_client_ready(clp, -EPROTONOSUPPORT); |
cc0a98436 NFSv4: Add debugg... |
1912 1913 1914 |
dprintk("%s: exit with error %d for server %s ", __func__, -EPROTONOSUPPORT, clp->cl_hostname); |
2a6ee6aa2 NFSv4: Clean up t... |
1915 |
return -EPROTONOSUPPORT; |
2a6ee6aa2 NFSv4: Clean up t... |
1916 1917 1918 |
case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery * in nfs4_exchange_id */ default: |
cc0a98436 NFSv4: Add debugg... |
1919 1920 1921 |
dprintk("%s: exit with error %d for server %s ", __func__, status, clp->cl_hostname); |
2a6ee6aa2 NFSv4: Clean up t... |
1922 1923 1924 |
return status; } set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
cc0a98436 NFSv4: Add debugg... |
1925 1926 1927 |
dprintk("%s: handled error %d for server %s ", __func__, status, clp->cl_hostname); |
2a6ee6aa2 NFSv4: Clean up t... |
1928 1929 |
return 0; } |
b42353ff8 NFSv4.1: Clean up... |
1930 |
static int nfs4_establish_lease(struct nfs_client *clp) |
028600143 NFSv4: Clean up f... |
1931 |
{ |
a52458b48 NFS/NFSD/SUNRPC: ... |
1932 |
const struct cred *cred; |
c48f4f354 NFSv41: Convert t... |
1933 1934 |
const struct nfs4_state_recovery_ops *ops = clp->cl_mvops->reboot_recovery_ops; |
2a6ee6aa2 NFSv4: Clean up t... |
1935 |
int status; |
028600143 NFSv4: Clean up f... |
1936 |
|
8aafd2fde NFSv4: Don't busy... |
1937 1938 1939 |
status = nfs4_begin_drain_session(clp); if (status != 0) return status; |
73d8bde5e NFS: Never use us... |
1940 |
cred = nfs4_get_clid_cred(clp); |
2a6ee6aa2 NFSv4: Clean up t... |
1941 1942 1943 |
if (cred == NULL) return -ENOENT; status = ops->establish_clid(clp, cred); |
a52458b48 NFS/NFSD/SUNRPC: ... |
1944 |
put_cred(cred); |
2a6ee6aa2 NFSv4: Clean up t... |
1945 |
if (status != 0) |
b42353ff8 NFSv4.1: Clean up... |
1946 1947 1948 1949 |
return status; pnfs_destroy_all_layouts(clp); return 0; } |
6bbb4ae8f NFS: Clean up nfs... |
1950 1951 1952 1953 |
/* * Returns zero or a negative errno. NFS4ERR values are converted * to local errno values. */ |
b42353ff8 NFSv4.1: Clean up... |
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 |
static int nfs4_reclaim_lease(struct nfs_client *clp) { int status; status = nfs4_establish_lease(clp); if (status < 0) return nfs4_handle_reclaim_lease_error(clp, status); if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state)) nfs4_state_start_reclaim_nograce(clp); if (!test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); return 0; } static int nfs4_purge_lease(struct nfs_client *clp) { int status; status = nfs4_establish_lease(clp); if (status < 0) |
2a6ee6aa2 NFSv4: Clean up t... |
1976 |
return nfs4_handle_reclaim_lease_error(clp, status); |
b42353ff8 NFSv4.1: Clean up... |
1977 1978 1979 |
clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); nfs4_state_start_reclaim_nograce(clp); |
2a6ee6aa2 NFSv4: Clean up t... |
1980 |
return 0; |
028600143 NFSv4: Clean up f... |
1981 |
} |
c9fdeb280 NFS: Add basic mi... |
1982 1983 1984 1985 1986 1987 1988 |
/* * Try remote migration of one FSID from a source server to a * destination server. The source server provides a list of * potential destinations. * * Returns zero or a negative NFS4ERR status code. */ |
a52458b48 NFS/NFSD/SUNRPC: ... |
1989 |
static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred) |
c9fdeb280 NFS: Add basic mi... |
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 |
{ struct nfs_client *clp = server->nfs_client; struct nfs4_fs_locations *locations = NULL; struct inode *inode; struct page *page; int status, result; dprintk("--> %s: FSID %llx:%llx on \"%s\" ", __func__, (unsigned long long)server->fsid.major, (unsigned long long)server->fsid.minor, clp->cl_hostname); result = 0; page = alloc_page(GFP_KERNEL); locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); if (page == NULL || locations == NULL) { dprintk("<-- %s: no memory ", __func__); goto out; } |
2b0143b5c VFS: normal files... |
2011 |
inode = d_inode(server->super->s_root); |
c9fdeb280 NFS: Add basic mi... |
2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 |
result = nfs4_proc_get_locations(inode, locations, page, cred); if (result) { dprintk("<-- %s: failed to retrieve fs_locations: %d ", __func__, result); goto out; } result = -NFS4ERR_NXIO; if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { dprintk("<-- %s: No fs_locations data, migration skipped ", __func__); goto out; } |
8aafd2fde NFSv4: Don't busy... |
2027 |
status = nfs4_begin_drain_session(clp); |
1e672e364 NFSv4: Fix a memo... |
2028 2029 2030 2031 |
if (status != 0) { result = status; goto out; } |
c9fdeb280 NFS: Add basic mi... |
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 |
status = nfs4_replace_transport(server, locations); if (status != 0) { dprintk("<-- %s: failed to replace transport: %d ", __func__, status); goto out; } result = 0; dprintk("<-- %s: migration succeeded ", __func__); out: if (page != NULL) __free_page(page); kfree(locations); if (result) { pr_err("NFS: migration recovery failed (server %s) ", clp->cl_hostname); set_bit(NFS_MIG_FAILED, &server->mig_status); } return result; } /* * Returns zero or a negative NFS4ERR status code. */ static int nfs4_handle_migration(struct nfs_client *clp) { const struct nfs4_state_maintenance_ops *ops = clp->cl_mvops->state_renewal_ops; struct nfs_server *server; |
a52458b48 NFS/NFSD/SUNRPC: ... |
2066 |
const struct cred *cred; |
c9fdeb280 NFS: Add basic mi... |
2067 2068 2069 2070 |
dprintk("%s: migration reported on \"%s\" ", __func__, clp->cl_hostname); |
f15e1e8bc NFSv4: don't requ... |
2071 |
cred = ops->get_state_renewal_cred(clp); |
c9fdeb280 NFS: Add basic mi... |
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 |
if (cred == NULL) return -NFS4ERR_NOENT; clp->cl_mig_gen++; restart: rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { int status; if (server->mig_gen == clp->cl_mig_gen) continue; server->mig_gen = clp->cl_mig_gen; if (!test_and_clear_bit(NFS_MIG_IN_TRANSITION, &server->mig_status)) continue; rcu_read_unlock(); status = nfs4_try_migration(server, cred); if (status < 0) { |
a52458b48 NFS/NFSD/SUNRPC: ... |
2092 |
put_cred(cred); |
c9fdeb280 NFS: Add basic mi... |
2093 2094 2095 2096 2097 |
return status; } goto restart; } rcu_read_unlock(); |
a52458b48 NFS/NFSD/SUNRPC: ... |
2098 |
put_cred(cred); |
c9fdeb280 NFS: Add basic mi... |
2099 2100 |
return 0; } |
b7f7a66e4 NFS: Support NFS4... |
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 |
/* * Test each nfs_server on the clp's cl_superblocks list to see * if it's moved to another server. Stop when the server no longer * returns NFS4ERR_LEASE_MOVED. */ static int nfs4_handle_lease_moved(struct nfs_client *clp) { const struct nfs4_state_maintenance_ops *ops = clp->cl_mvops->state_renewal_ops; struct nfs_server *server; |
a52458b48 NFS/NFSD/SUNRPC: ... |
2111 |
const struct cred *cred; |
b7f7a66e4 NFS: Support NFS4... |
2112 2113 2114 2115 |
dprintk("%s: lease moved reported on \"%s\" ", __func__, clp->cl_hostname); |
f15e1e8bc NFSv4: don't requ... |
2116 |
cred = ops->get_state_renewal_cred(clp); |
b7f7a66e4 NFS: Support NFS4... |
2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 |
if (cred == NULL) return -NFS4ERR_NOENT; clp->cl_mig_gen++; restart: rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { struct inode *inode; int status; if (server->mig_gen == clp->cl_mig_gen) continue; server->mig_gen = clp->cl_mig_gen; rcu_read_unlock(); |
2b0143b5c VFS: normal files... |
2132 |
inode = d_inode(server->super->s_root); |
b7f7a66e4 NFS: Support NFS4... |
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 |
status = nfs4_proc_fsid_present(inode, cred); if (status != -NFS4ERR_MOVED) goto restart; /* wasn't this one */ if (nfs4_try_migration(server, cred) == -NFS4ERR_LEASE_MOVED) goto restart; /* there are more */ goto out; } rcu_read_unlock(); out: |
a52458b48 NFS/NFSD/SUNRPC: ... |
2143 |
put_cred(cred); |
b7f7a66e4 NFS: Support NFS4... |
2144 2145 |
return 0; } |
05f4c350e NFS: Discover NFS... |
2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 |
/** * nfs4_discover_server_trunking - Detect server IP address trunking * * @clp: nfs_client under test * @result: OUT: found nfs_client, or clp * * Returns zero or a negative errno. If zero is returned, * an nfs_client pointer is planted in "result". * * Note: since we are invoked in process context, and * not from inside the state manager, we cannot use * nfs4_handle_reclaim_lease_error(). */ int nfs4_discover_server_trunking(struct nfs_client *clp, struct nfs_client **result) { const struct nfs4_state_recovery_ops *ops = clp->cl_mvops->reboot_recovery_ops; |
05f4c350e NFS: Discover NFS... |
2164 |
struct rpc_clnt *clnt; |
a52458b48 NFS/NFSD/SUNRPC: ... |
2165 |
const struct cred *cred; |
4edaa3088 NFS: Use "krb5i" ... |
2166 |
int i, status; |
05f4c350e NFS: Discover NFS... |
2167 2168 2169 |
dprintk("NFS: %s: testing '%s' ", __func__, clp->cl_hostname); |
05f4c350e NFS: Discover NFS... |
2170 |
clnt = clp->cl_rpcclient; |
05f4c350e NFS: Discover NFS... |
2171 2172 2173 |
i = 0; mutex_lock(&nfs_clid_init_mutex); |
05f4c350e NFS: Discover NFS... |
2174 |
again: |
ea33e6c3e NFSv4: Fix issues... |
2175 |
status = -ENOENT; |
73d8bde5e NFS: Never use us... |
2176 |
cred = nfs4_get_clid_cred(clp); |
05f4c350e NFS: Discover NFS... |
2177 2178 2179 2180 |
if (cred == NULL) goto out_unlock; status = ops->detect_trunking(clp, result, cred); |
a52458b48 NFS/NFSD/SUNRPC: ... |
2181 |
put_cred(cred); |
05f4c350e NFS: Discover NFS... |
2182 2183 |
switch (status) { case 0: |
898fc11bb NFS: Trunking det... |
2184 2185 |
case -EINTR: case -ERESTARTSYS: |
05f4c350e NFS: Discover NFS... |
2186 |
break; |
05f4c350e NFS: Discover NFS... |
2187 |
case -ETIMEDOUT: |
150e7260f NFSv4: Ensure we ... |
2188 2189 |
if (clnt->cl_softrtry) break; |
df561f668 treewide: Use fal... |
2190 |
fallthrough; |
150e7260f NFSv4: Ensure we ... |
2191 |
case -NFS4ERR_DELAY: |
05f4c350e NFS: Discover NFS... |
2192 2193 |
case -EAGAIN: ssleep(1); |
df561f668 treewide: Use fal... |
2194 |
fallthrough; |
202c312db NFSv4: Fix NFSv4 ... |
2195 |
case -NFS4ERR_STALE_CLIENTID: |
05f4c350e NFS: Discover NFS... |
2196 2197 2198 2199 |
dprintk("NFS: %s after status %d, retrying ", __func__, status); goto again; |
4edaa3088 NFS: Use "krb5i" ... |
2200 |
case -EACCES: |
d688f7b8f NFS: Use root's c... |
2201 2202 2203 2204 |
if (i++ == 0) { nfs4_root_machine_cred(clp); goto again; } |
6d769f1e1 nfs: don't retry ... |
2205 |
if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX) |
4edaa3088 NFS: Use "krb5i" ... |
2206 |
break; |
df561f668 treewide: Use fal... |
2207 |
fallthrough; |
05f4c350e NFS: Discover NFS... |
2208 2209 |
case -NFS4ERR_CLID_INUSE: case -NFS4ERR_WRONGSEC: |
6d769f1e1 nfs: don't retry ... |
2210 2211 2212 2213 2214 |
/* No point in retrying if we already used RPC_AUTH_UNIX */ if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX) { status = -EPERM; break; } |
79d852bf5 NFS: Retry SETCLI... |
2215 |
clnt = rpc_clone_client_set_auth(clnt, RPC_AUTH_UNIX); |
05f4c350e NFS: Discover NFS... |
2216 2217 2218 2219 |
if (IS_ERR(clnt)) { status = PTR_ERR(clnt); break; } |
b193d59a4 NFSv4: Fix a memo... |
2220 2221 2222 2223 2224 2225 2226 |
/* Note: this is safe because we haven't yet marked the * client as ready, so we are the only user of * clp->cl_rpcclient */ clnt = xchg(&clp->cl_rpcclient, clnt); rpc_shutdown_client(clnt); clnt = clp->cl_rpcclient; |
05f4c350e NFS: Discover NFS... |
2227 2228 2229 2230 2231 2232 2233 |
goto again; case -NFS4ERR_MINOR_VERS_MISMATCH: status = -EPROTONOSUPPORT; break; case -EKEYEXPIRED: |
05f4c350e NFS: Discover NFS... |
2234 2235 2236 |
case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery * in nfs4_exchange_id */ status = -EKEYEXPIRED; |
ea33e6c3e NFSv4: Fix issues... |
2237 2238 2239 2240 2241 2242 |
break; default: pr_warn("NFS: %s unhandled error %d. Exiting with error EIO ", __func__, status); status = -EIO; |
05f4c350e NFS: Discover NFS... |
2243 2244 2245 2246 |
} out_unlock: mutex_unlock(&nfs_clid_init_mutex); |
05f4c350e NFS: Discover NFS... |
2247 2248 2249 2250 |
dprintk("NFS: %s: status = %d ", __func__, status); return status; } |
76db6d950 nfs41: add sessio... |
2251 |
#ifdef CONFIG_NFS_V4_1 |
9f594791d NFSv4.1: Handle o... |
2252 |
void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) |
0400a6b0c NFSv4/4.1: Fix nf... |
2253 |
{ |
444f72fe7 NFSv4.1: Fix the ... |
2254 |
struct nfs_client *clp = session->clp; |
9f594791d NFSv4.1: Handle o... |
2255 2256 2257 2258 2259 2260 2261 |
switch (err) { default: set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); break; case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); } |
d94cbf6c7 NFSv4.1: Don't sc... |
2262 |
nfs4_schedule_state_manager(clp); |
0400a6b0c NFSv4/4.1: Fix nf... |
2263 |
} |
cbdabc7f8 NFSv4.1: filelayo... |
2264 |
EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); |
0400a6b0c NFSv4/4.1: Fix nf... |
2265 |
|
3f10a6af4 NFS: Remove nfs41... |
2266 |
void nfs41_notify_server(struct nfs_client *clp) |
ac0748359 NFSv4.1: CB_RECAL... |
2267 2268 2269 2270 2271 |
{ /* Use CHECK_LEASE to ping the server with a SEQUENCE */ set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); nfs4_schedule_state_manager(clp); } |
0f79fd6f5 NFSv4.1: Various ... |
2272 2273 2274 |
static void nfs4_reset_all_state(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |
2c820d9a9 NFS: Force server... |
2275 |
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); |
be0bfed00 NFSv4: When purgi... |
2276 |
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
0f79fd6f5 NFSv4.1: Various ... |
2277 |
nfs4_state_start_reclaim_nograce(clp); |
cc0a98436 NFSv4: Add debugg... |
2278 2279 2280 |
dprintk("%s: scheduling reset of all state for server %s! ", __func__, clp->cl_hostname); |
0400a6b0c NFSv4/4.1: Fix nf... |
2281 |
nfs4_schedule_state_manager(clp); |
0f79fd6f5 NFSv4.1: Various ... |
2282 2283 2284 2285 2286 2287 2288 |
} } 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); |
cc0a98436 NFSv4: Add debugg... |
2289 2290 2291 |
dprintk("%s: server %s rebooted! ", __func__, clp->cl_hostname); |
0400a6b0c NFSv4/4.1: Fix nf... |
2292 |
nfs4_schedule_state_manager(clp); |
0f79fd6f5 NFSv4.1: Various ... |
2293 2294 |
} } |
8b895ce65 NFSv4.1: Handle S... |
2295 |
static void nfs41_handle_all_state_revoked(struct nfs_client *clp) |
0f79fd6f5 NFSv4.1: Various ... |
2296 |
{ |
0f79fd6f5 NFSv4.1: Various ... |
2297 |
nfs4_reset_all_state(clp); |
cc0a98436 NFSv4: Add debugg... |
2298 2299 |
dprintk("%s: state revoked on server %s ", __func__, clp->cl_hostname); |
0f79fd6f5 NFSv4.1: Various ... |
2300 |
} |
8b895ce65 NFSv4.1: Handle S... |
2301 2302 |
static void nfs41_handle_some_state_revoked(struct nfs_client *clp) { |
45870d690 NFSv4.1: Test del... |
2303 |
nfs4_state_start_reclaim_nograce(clp); |
8b895ce65 NFSv4.1: Handle S... |
2304 2305 2306 2307 2308 |
nfs4_schedule_state_manager(clp); dprintk("%s: state revoked on server %s ", __func__, clp->cl_hostname); } |
0f79fd6f5 NFSv4.1: Various ... |
2309 2310 |
static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp) { |
4099287fe NFSv4.1: Handle S... |
2311 2312 |
/* FIXME: For now, we destroy all layouts. */ pnfs_destroy_all_layouts(clp); |
8ca017c8c NFSv4: don't mark... |
2313 |
nfs_test_expired_all_delegations(clp); |
cc0a98436 NFSv4: Add debugg... |
2314 2315 2316 |
dprintk("%s: Recallable state revoked on server %s! ", __func__, clp->cl_hostname); |
0f79fd6f5 NFSv4.1: Various ... |
2317 |
} |
a9e64442f nfs41: Use BIND_C... |
2318 |
static void nfs41_handle_backchannel_fault(struct nfs_client *clp) |
0f79fd6f5 NFSv4.1: Various ... |
2319 |
{ |
b13529059 NFSv4.1: Handle S... |
2320 2321 |
set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); nfs4_schedule_state_manager(clp); |
cc0a98436 NFSv4: Add debugg... |
2322 2323 2324 |
dprintk("%s: server %s declared a backchannel fault ", __func__, clp->cl_hostname); |
0f79fd6f5 NFSv4.1: Various ... |
2325 |
} |
a9e64442f nfs41: Use BIND_C... |
2326 2327 2328 2329 2330 2331 |
static void nfs41_handle_cb_path_down(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state) == 0) nfs4_schedule_state_manager(clp); } |
0a014a44a NFSv4.1: Don't de... |
2332 2333 |
void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags, bool recovery) |
0629e370d nfs41: check SEQU... |
2334 2335 2336 |
{ if (!flags) return; |
2c820d9a9 NFS: Force server... |
2337 2338 2339 2340 |
dprintk("%s: \"%s\" (client ID %llx) flags=0x%08x ", __func__, clp->cl_hostname, clp->cl_clientid, flags); |
0a014a44a NFSv4.1: Don't de... |
2341 2342 2343 2344 2345 2346 2347 2348 |
/* * If we're called from the state manager thread, then assume we're * already handling the RECLAIM_NEEDED and/or STATE_REVOKED. * Those flags are expected to remain set until we're done * recovering (see RFC5661, section 18.46.3). */ if (recovery) goto out_recovery; |
2c820d9a9 NFS: Force server... |
2349 |
|
111d489f0 NFSv4.1: Ensure t... |
2350 |
if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) |
0f79fd6f5 NFSv4.1: Various ... |
2351 |
nfs41_handle_server_reboot(clp); |
8b895ce65 NFSv4.1: Handle S... |
2352 2353 2354 |
if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED)) nfs41_handle_all_state_revoked(clp); if (flags & (SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | |
d1c2331e7 NFS: Handle SEQ4_... |
2355 |
SEQ4_STATUS_ADMIN_STATE_REVOKED)) |
8b895ce65 NFSv4.1: Handle S... |
2356 |
nfs41_handle_some_state_revoked(clp); |
d1c2331e7 NFS: Handle SEQ4_... |
2357 2358 |
if (flags & SEQ4_STATUS_LEASE_MOVED) nfs4_schedule_lease_moved_recovery(clp); |
111d489f0 NFSv4.1: Ensure t... |
2359 |
if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) |
0f79fd6f5 NFSv4.1: Various ... |
2360 |
nfs41_handle_recallable_state_revoked(clp); |
0a014a44a NFSv4.1: Don't de... |
2361 |
out_recovery: |
a9e64442f nfs41: Use BIND_C... |
2362 2363 2364 2365 |
if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT) nfs41_handle_backchannel_fault(clp); else if (flags & (SEQ4_STATUS_CB_PATH_DOWN | SEQ4_STATUS_CB_PATH_DOWN_SESSION)) |
0f79fd6f5 NFSv4.1: Various ... |
2366 |
nfs41_handle_cb_path_down(clp); |
0629e370d nfs41: check SEQU... |
2367 |
} |
c3fad1b1a nfs41: add sessio... |
2368 2369 |
static int nfs4_reset_session(struct nfs_client *clp) { |
a52458b48 NFS/NFSD/SUNRPC: ... |
2370 |
const struct cred *cred; |
c3fad1b1a nfs41: add sessio... |
2371 |
int status; |
1a47e7a66 NFSv4.1: Cleanup ... |
2372 2373 |
if (!nfs4_has_session(clp)) return 0; |
8aafd2fde NFSv4: Don't busy... |
2374 2375 2376 |
status = nfs4_begin_drain_session(clp); if (status != 0) return status; |
73d8bde5e NFS: Never use us... |
2377 |
cred = nfs4_get_clid_cred(clp); |
848f5bda5 NFSv4.1: Ensure w... |
2378 |
status = nfs4_proc_destroy_session(clp->cl_session, cred); |
c489ee290 NFSv4.1: Handle N... |
2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 |
switch (status) { case 0: case -NFS4ERR_BADSESSION: case -NFS4ERR_DEADSESSION: break; case -NFS4ERR_BACK_CHAN_BUSY: case -NFS4ERR_DELAY: set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); status = 0; ssleep(1); goto out; default: |
f455848a1 nfs41: Mark state... |
2391 |
status = nfs4_recovery_handle_error(clp, status); |
c3fad1b1a nfs41: add sessio... |
2392 2393 2394 2395 |
goto out; } memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); |
848f5bda5 NFSv4.1: Ensure w... |
2396 |
status = nfs4_proc_create_session(clp, cred); |
41f54a554 nfs41: clear NFS4... |
2397 |
if (status) { |
cc0a98436 NFSv4: Add debugg... |
2398 2399 2400 |
dprintk("%s: session reset failed with status %d for server %s! ", __func__, status, clp->cl_hostname); |
f2c1b5100 NFSv4.1: nfs4_res... |
2401 |
status = nfs4_handle_reclaim_lease_error(clp, status); |
41f54a554 nfs41: clear NFS4... |
2402 2403 |
goto out; } |
bda197f5d NFSv4.1: Ensure w... |
2404 |
nfs41_finish_session_reset(clp); |
cc0a98436 NFSv4: Add debugg... |
2405 2406 2407 |
dprintk("%s: session reset was successful for server %s! ", __func__, clp->cl_hostname); |
41f54a554 nfs41: clear NFS4... |
2408 |
out: |
a52458b48 NFS/NFSD/SUNRPC: ... |
2409 |
put_cred(cred); |
c3fad1b1a nfs41: add sessio... |
2410 2411 |
return status; } |
76db6d950 nfs41: add sessio... |
2412 |
|
a9e64442f nfs41: Use BIND_C... |
2413 2414 |
static int nfs4_bind_conn_to_session(struct nfs_client *clp) { |
a52458b48 NFS/NFSD/SUNRPC: ... |
2415 |
const struct cred *cred; |
2cf047c99 NFSv4.1: Ensure w... |
2416 |
int ret; |
1a47e7a66 NFSv4.1: Cleanup ... |
2417 2418 |
if (!nfs4_has_session(clp)) return 0; |
8aafd2fde NFSv4: Don't busy... |
2419 2420 2421 |
ret = nfs4_begin_drain_session(clp); if (ret != 0) return ret; |
73d8bde5e NFS: Never use us... |
2422 |
cred = nfs4_get_clid_cred(clp); |
2cf047c99 NFSv4.1: Ensure w... |
2423 |
ret = nfs4_proc_bind_conn_to_session(clp, cred); |
a52458b48 NFS/NFSD/SUNRPC: ... |
2424 |
put_cred(cred); |
43ac544cb NFSv4.1: nfs4_bin... |
2425 |
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); |
bf674c822 NFSv4.1: Handle e... |
2426 2427 |
switch (ret) { case 0: |
cc0a98436 NFSv4: Add debugg... |
2428 2429 2430 |
dprintk("%s: bind_conn_to_session was successful for server %s! ", __func__, clp->cl_hostname); |
bf674c822 NFSv4.1: Handle e... |
2431 2432 2433 2434 2435 2436 2437 2438 2439 |
break; case -NFS4ERR_DELAY: ssleep(1); set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); break; default: return nfs4_recovery_handle_error(clp, ret); } return 0; |
a9e64442f nfs41: Use BIND_C... |
2440 |
} |
b5fdf8418 NFSv4: Add suppor... |
2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 |
static void nfs4_layoutreturn_any_run(struct nfs_client *clp) { int iomode = 0; if (test_and_clear_bit(NFS4CLNT_RECALL_ANY_LAYOUT_READ, &clp->cl_state)) iomode += IOMODE_READ; if (test_and_clear_bit(NFS4CLNT_RECALL_ANY_LAYOUT_RW, &clp->cl_state)) iomode += IOMODE_RW; /* Note: IOMODE_READ + IOMODE_RW == IOMODE_ANY */ if (iomode) { pnfs_layout_return_unused_byclid(clp, iomode); set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); } } |
76db6d950 nfs41: add sessio... |
2456 |
#else /* CONFIG_NFS_V4_1 */ |
c3fad1b1a nfs41: add sessio... |
2457 |
static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
a9e64442f nfs41: Use BIND_C... |
2458 2459 2460 2461 2462 |
static int nfs4_bind_conn_to_session(struct nfs_client *clp) { return 0; } |
b5fdf8418 NFSv4: Add suppor... |
2463 2464 2465 2466 |
static void nfs4_layoutreturn_any_run(struct nfs_client *clp) { } |
76db6d950 nfs41: add sessio... |
2467 |
#endif /* CONFIG_NFS_V4_1 */ |
e005e8041 NFSv4: Rename the... |
2468 |
static void nfs4_state_manager(struct nfs_client *clp) |
028600143 NFSv4: Clean up f... |
2469 |
{ |
028600143 NFSv4: Clean up f... |
2470 |
int status = 0; |
8ed27d4fb NFS: add more con... |
2471 |
const char *section = "", *section_sep = ""; |
028600143 NFSv4: Clean up f... |
2472 |
|
028600143 NFSv4: Clean up f... |
2473 |
/* Ensure exclusive access to NFSv4 state */ |
47c2199b6 NFSv4.1: Ensure s... |
2474 |
do { |
511ba52e4 NFS4: Trace state... |
2475 |
trace_nfs4_state_mgr(clp); |
aeabb3c96 NFSv4: Fix a NFSv... |
2476 |
clear_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
2c820d9a9 NFS: Force server... |
2477 |
if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { |
8ed27d4fb NFS: add more con... |
2478 |
section = "purge state"; |
b42353ff8 NFSv4.1: Clean up... |
2479 |
status = nfs4_purge_lease(clp); |
2a6ee6aa2 NFSv4: Clean up t... |
2480 2481 |
if (status < 0) goto out_error; |
b42353ff8 NFSv4.1: Clean up... |
2482 |
continue; |
2c820d9a9 NFS: Force server... |
2483 |
} |
b42353ff8 NFSv4.1: Clean up... |
2484 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { |
8ed27d4fb NFS: add more con... |
2485 |
section = "lease expired"; |
b79a4a1b4 NFSv4: Fix state ... |
2486 2487 |
/* We're going to have to re-establish a clientid */ status = nfs4_reclaim_lease(clp); |
2a6ee6aa2 NFSv4: Clean up t... |
2488 |
if (status < 0) |
b79a4a1b4 NFSv4: Fix state ... |
2489 |
goto out_error; |
b42353ff8 NFSv4.1: Clean up... |
2490 |
continue; |
e598d843c NFSv4: Remove red... |
2491 |
} |
c3fad1b1a nfs41: add sessio... |
2492 |
/* Initialize or reset the session */ |
1a47e7a66 NFSv4.1: Cleanup ... |
2493 |
if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { |
8ed27d4fb NFS: add more con... |
2494 |
section = "reset session"; |
4d643d1df nfs41: add create... |
2495 |
status = nfs4_reset_session(clp); |
b6d408ba8 NFSv4: Fix up err... |
2496 2497 2498 |
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) continue; if (status < 0) |
76db6d950 nfs41: add sessio... |
2499 |
goto out_error; |
76db6d950 nfs41: add sessio... |
2500 |
} |
b6d408ba8 NFSv4: Fix up err... |
2501 |
|
a9e64442f nfs41: Use BIND_C... |
2502 2503 |
/* Send BIND_CONN_TO_SESSION */ if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, |
1a47e7a66 NFSv4.1: Cleanup ... |
2504 |
&clp->cl_state)) { |
8ed27d4fb NFS: add more con... |
2505 |
section = "bind conn to session"; |
a9e64442f nfs41: Use BIND_C... |
2506 2507 2508 |
status = nfs4_bind_conn_to_session(clp); if (status < 0) goto out_error; |
bf674c822 NFSv4.1: Handle e... |
2509 |
continue; |
a9e64442f nfs41: Use BIND_C... |
2510 |
} |
5df904aeb NFSv4.1: Handle s... |
2511 2512 2513 2514 2515 |
if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { section = "check lease"; status = nfs4_check_lease(clp); if (status < 0) goto out_error; |
8faaa6d5d Fixing lease renewal |
2516 |
continue; |
c9fdeb280 NFS: Add basic mi... |
2517 2518 2519 2520 2521 2522 2523 |
} if (test_and_clear_bit(NFS4CLNT_MOVED, &clp->cl_state)) { section = "migration"; status = nfs4_handle_migration(clp); if (status < 0) goto out_error; |
5df904aeb NFSv4.1: Handle s... |
2524 |
} |
b7f7a66e4 NFS: Support NFS4... |
2525 2526 2527 2528 2529 2530 |
if (test_and_clear_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state)) { section = "lease moved"; status = nfs4_handle_lease_moved(clp); if (status < 0) goto out_error; } |
b79a4a1b4 NFSv4: Fix state ... |
2531 |
/* First recover reboot state... */ |
e345e88a7 NFSv4: Fix up the... |
2532 |
if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
8ed27d4fb NFS: add more con... |
2533 |
section = "reclaim reboot"; |
591d71cbd nfs41: establish ... |
2534 |
status = nfs4_do_reclaim(clp, |
c48f4f354 NFSv41: Convert t... |
2535 |
clp->cl_mvops->reboot_recovery_ops); |
df817ba35 NFSv4: fix open/l... |
2536 |
if (status == -EAGAIN) |
b6d408ba8 NFSv4: Fix up err... |
2537 2538 2539 |
continue; if (status < 0) goto out_error; |
df817ba35 NFSv4: fix open/l... |
2540 |
nfs4_state_end_reclaim_reboot(clp); |
028600143 NFSv4: Clean up f... |
2541 |
} |
45870d690 NFSv4.1: Test del... |
2542 2543 2544 2545 2546 2547 |
/* Detect expired delegations... */ if (test_and_clear_bit(NFS4CLNT_DELEGATION_EXPIRED, &clp->cl_state)) { section = "detect expired delegations"; nfs_reap_expired_delegations(clp); continue; } |
b79a4a1b4 NFSv4: Fix state ... |
2548 |
/* Now recover expired state... */ |
67e7b52d4 NFSv4: Ensure sta... |
2549 |
if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
8ed27d4fb NFS: add more con... |
2550 |
section = "reclaim nograce"; |
591d71cbd nfs41: establish ... |
2551 |
status = nfs4_do_reclaim(clp, |
c48f4f354 NFSv41: Convert t... |
2552 |
clp->cl_mvops->nograce_recovery_ops); |
df817ba35 NFSv4: fix open/l... |
2553 |
if (status == -EAGAIN) |
b6d408ba8 NFSv4: Fix up err... |
2554 2555 |
continue; if (status < 0) |
b79a4a1b4 NFSv4: Fix state ... |
2556 |
goto out_error; |
67e7b52d4 NFSv4: Ensure sta... |
2557 |
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); |
1da177e4c Linux-2.6.12-rc2 |
2558 |
} |
707fb4b32 NFSv4: Clean up N... |
2559 |
|
5601a00d6 nfs: run state ma... |
2560 |
nfs4_end_drain_session(clp); |
aeabb3c96 NFSv4: Fix a NFSv... |
2561 |
nfs4_clear_state_manager_bit(clp); |
b5fdf8418 NFSv4: Add suppor... |
2562 |
if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) { |
aeabb3c96 NFSv4: Fix a NFSv... |
2563 2564 2565 2566 |
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { nfs_client_return_marked_delegations(clp); set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); } |
b5fdf8418 NFSv4: Add suppor... |
2567 2568 |
nfs4_layoutreturn_any_run(clp); clear_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state); |
707fb4b32 NFSv4: Clean up N... |
2569 |
} |
e005e8041 NFSv4: Rename the... |
2570 |
|
f3c76491e NFSv4: Don't exit... |
2571 |
/* Did we race with an attempt to give us more work? */ |
aeabb3c96 NFSv4: Fix a NFSv... |
2572 |
if (!test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state)) |
21a446cf1 NFSv4: Don't exit... |
2573 |
return; |
f3c76491e NFSv4: Don't exit... |
2574 |
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) |
21a446cf1 NFSv4: Don't exit... |
2575 |
return; |
a1aa09be2 NFSv4: Ensure tha... |
2576 |
} while (refcount_read(&clp->cl_count) > 1 && !signalled()); |
21a446cf1 NFSv4: Don't exit... |
2577 |
goto out_drain; |
1da177e4c Linux-2.6.12-rc2 |
2578 |
out_error: |
8ed27d4fb NFS: add more con... |
2579 2580 |
if (strlen(section)) section_sep = ": "; |
511ba52e4 NFS4: Trace state... |
2581 |
trace_nfs4_state_mgr_failed(clp, section, status); |
8ed27d4fb NFS: add more con... |
2582 2583 2584 2585 |
pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" " with error %d ", section_sep, section, clp->cl_hostname, -status); |
ffe5a8300 NFS: Slow down st... |
2586 |
ssleep(1); |
21a446cf1 NFSv4: Don't exit... |
2587 |
out_drain: |
5601a00d6 nfs: run state ma... |
2588 |
nfs4_end_drain_session(clp); |
e005e8041 NFSv4: Rename the... |
2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 |
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 |
2601 2602 2603 2604 2605 2606 2607 |
} /* * Local variables: * c-basic-offset: 8 * End: */ |