Blame view
fs/nfs/delegation.c
18.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 |
/* * linux/fs/nfs/delegation.c * * Copyright (C) 2004 Trond Myklebust * * NFS file delegation management * */ |
1da177e4c Linux-2.6.12-rc2 |
9 |
#include <linux/completion.h> |
58d9714a4 NFSv4: Send RENEW... |
10 |
#include <linux/kthread.h> |
1da177e4c Linux-2.6.12-rc2 |
11 12 |
#include <linux/module.h> #include <linux/sched.h> |
5a0e3ad6a include cleanup: ... |
13 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
14 15 16 17 18 |
#include <linux/spinlock.h> #include <linux/nfs4.h> #include <linux/nfs_fs.h> #include <linux/nfs_xdr.h> |
4ce79717c [PATCH] NFS: Head... |
19 |
#include "nfs4_fs.h" |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include "delegation.h" |
24c8dbbb5 NFS: Generalise t... |
21 |
#include "internal.h" |
1da177e4c Linux-2.6.12-rc2 |
22 |
|
905f8d16e NFSv4: Don't call... |
23 24 |
static void nfs_free_delegation(struct nfs_delegation *delegation) { |
e00b8a240 NFS: Fix an NFS c... |
25 26 27 28 |
if (delegation->cred) { put_rpccred(delegation->cred); delegation->cred = NULL; } |
26f04dde6 nfs,rcu: convert ... |
29 |
kfree_rcu(delegation, rcu); |
8383e4602 NFSv4: Use RCU to... |
30 |
} |
d3978bb32 NFS: Move cl_dele... |
31 32 33 34 35 |
/** * nfs_mark_delegation_referenced - set delegation's REFERENCED flag * @delegation: delegation to process * */ |
b7391f44f NFSv4: Return unr... |
36 37 38 39 |
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) { set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags); } |
d3978bb32 NFS: Move cl_dele... |
40 41 42 43 44 45 46 |
/** * nfs_have_delegation - check if inode has a delegation * @inode: inode to check * @flags: delegation types to check for * * Returns one if inode has the indicated delegation, otherwise zero. */ |
bd7bf9d54 NFSv4: Convert de... |
47 |
int nfs_have_delegation(struct inode *inode, fmode_t flags) |
b7391f44f NFSv4: Return unr... |
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
{ struct nfs_delegation *delegation; int ret = 0; flags &= FMODE_READ|FMODE_WRITE; rcu_read_lock(); delegation = rcu_dereference(NFS_I(inode)->delegation); if (delegation != NULL && (delegation->type & flags) == flags) { nfs_mark_delegation_referenced(delegation); ret = 1; } rcu_read_unlock(); return ret; } |
888e694c1 NFSv4: Recover lo... |
62 63 64 65 |
static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state) { struct inode *inode = state->inode; struct file_lock *fl; |
d5122201a NFSv4: Move error... |
66 |
int status = 0; |
888e694c1 NFSv4: Recover lo... |
67 |
|
3f09df70e NFS: Ensure we al... |
68 69 |
if (inode->i_flock == NULL) goto out; |
b89f43213 fs/locks.c: prepa... |
70 71 |
/* Protect inode->i_flock using the file locks lock */ lock_flocks(); |
90dc7d279 nfs: fix sparse w... |
72 |
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
888e694c1 NFSv4: Recover lo... |
73 74 |
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) continue; |
cd3758e37 NFS: Replace file... |
75 |
if (nfs_file_open_context(fl->fl_file) != ctx) |
888e694c1 NFSv4: Recover lo... |
76 |
continue; |
b89f43213 fs/locks.c: prepa... |
77 |
unlock_flocks(); |
888e694c1 NFSv4: Recover lo... |
78 |
status = nfs4_lock_delegation_recall(state, fl); |
d5122201a NFSv4: Move error... |
79 |
if (status < 0) |
3f09df70e NFS: Ensure we al... |
80 |
goto out; |
b89f43213 fs/locks.c: prepa... |
81 |
lock_flocks(); |
888e694c1 NFSv4: Recover lo... |
82 |
} |
b89f43213 fs/locks.c: prepa... |
83 |
unlock_flocks(); |
3f09df70e NFS: Ensure we al... |
84 |
out: |
888e694c1 NFSv4: Recover lo... |
85 86 |
return status; } |
d18cc1fda NFSv4: Fix a pote... |
87 |
static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) |
1da177e4c Linux-2.6.12-rc2 |
88 89 90 91 |
{ struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *ctx; struct nfs4_state *state; |
888e694c1 NFSv4: Recover lo... |
92 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
93 94 95 96 97 98 99 100 101 |
again: spin_lock(&inode->i_lock); list_for_each_entry(ctx, &nfsi->open_files, list) { state = ctx->state; if (state == NULL) continue; if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) continue; |
901630278 NFSv4: Support re... |
102 103 |
if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0) continue; |
1da177e4c Linux-2.6.12-rc2 |
104 105 |
get_nfs_open_context(ctx); spin_unlock(&inode->i_lock); |
13437e12f NFSv4: Support re... |
106 |
err = nfs4_open_delegation_recall(ctx, state, stateid); |
888e694c1 NFSv4: Recover lo... |
107 108 |
if (err >= 0) err = nfs_delegation_claim_locks(ctx, state); |
1da177e4c Linux-2.6.12-rc2 |
109 |
put_nfs_open_context(ctx); |
888e694c1 NFSv4: Recover lo... |
110 |
if (err != 0) |
d18cc1fda NFSv4: Fix a pote... |
111 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
112 113 114 |
goto again; } spin_unlock(&inode->i_lock); |
d18cc1fda NFSv4: Fix a pote... |
115 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
116 |
} |
d3978bb32 NFS: Move cl_dele... |
117 118 119 120 121 122 |
/** * nfs_inode_reclaim_delegation - process a delegation reclaim request * @inode: inode to process * @cred: credential to use for request * @res: new delegation state from server * |
1da177e4c Linux-2.6.12-rc2 |
123 |
*/ |
d3978bb32 NFS: Move cl_dele... |
124 125 |
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) |
1da177e4c Linux-2.6.12-rc2 |
126 |
{ |
8f649c376 NFSv4: Fix the lo... |
127 128 |
struct nfs_delegation *delegation; struct rpc_cred *oldcred = NULL; |
1da177e4c Linux-2.6.12-rc2 |
129 |
|
8f649c376 NFSv4: Fix the lo... |
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
rcu_read_lock(); delegation = rcu_dereference(NFS_I(inode)->delegation); if (delegation != NULL) { spin_lock(&delegation->lock); if (delegation->inode != NULL) { memcpy(delegation->stateid.data, res->delegation.data, sizeof(delegation->stateid.data)); delegation->type = res->delegation_type; delegation->maxsize = res->maxsize; oldcred = delegation->cred; delegation->cred = get_rpccred(cred); clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); NFS_I(inode)->delegation_state = delegation->type; spin_unlock(&delegation->lock); put_rpccred(oldcred); rcu_read_unlock(); } else { /* We appear to have raced with a delegation return. */ spin_unlock(&delegation->lock); rcu_read_unlock(); nfs_inode_set_delegation(inode, cred, res); } } else { rcu_read_unlock(); } |
1da177e4c Linux-2.6.12-rc2 |
156 |
} |
57bfa8917 NFSv4: Deal more ... |
157 158 159 160 161 162 163 164 |
static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { int res = 0; res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); nfs_free_delegation(delegation); return res; } |
86e894899 NFSv4: Fix up the... |
165 166 167 168 169 170 171 172 173 174 |
static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation) { struct inode *inode = NULL; spin_lock(&delegation->lock); if (delegation->inode != NULL) inode = igrab(delegation->inode); spin_unlock(&delegation->lock); return inode; } |
dda4b2256 NFS: Introduce nf... |
175 176 |
static struct nfs_delegation * nfs_detach_delegation_locked(struct nfs_inode *nfsi, |
d3978bb32 NFS: Move cl_dele... |
177 |
struct nfs_server *server) |
57bfa8917 NFSv4: Deal more ... |
178 |
{ |
17d2c0a0c NFS: Fix RCU issu... |
179 180 |
struct nfs_delegation *delegation = rcu_dereference_protected(nfsi->delegation, |
d3978bb32 NFS: Move cl_dele... |
181 |
lockdep_is_held(&server->nfs_client->cl_lock)); |
57bfa8917 NFSv4: Deal more ... |
182 183 184 |
if (delegation == NULL) goto nomatch; |
dda4b2256 NFS: Introduce nf... |
185 |
|
343104308 NFSv4: Fix up ano... |
186 |
spin_lock(&delegation->lock); |
57bfa8917 NFSv4: Deal more ... |
187 |
list_del_rcu(&delegation->super_list); |
86e894899 NFSv4: Fix up the... |
188 |
delegation->inode = NULL; |
57bfa8917 NFSv4: Deal more ... |
189 190 |
nfsi->delegation_state = 0; rcu_assign_pointer(nfsi->delegation, NULL); |
343104308 NFSv4: Fix up ano... |
191 |
spin_unlock(&delegation->lock); |
57bfa8917 NFSv4: Deal more ... |
192 193 194 195 |
return delegation; nomatch: return NULL; } |
dda4b2256 NFS: Introduce nf... |
196 |
static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi, |
d3978bb32 NFS: Move cl_dele... |
197 |
struct nfs_server *server) |
dda4b2256 NFS: Introduce nf... |
198 |
{ |
d3978bb32 NFS: Move cl_dele... |
199 |
struct nfs_client *clp = server->nfs_client; |
dda4b2256 NFS: Introduce nf... |
200 201 202 |
struct nfs_delegation *delegation; spin_lock(&clp->cl_lock); |
d3978bb32 NFS: Move cl_dele... |
203 |
delegation = nfs_detach_delegation_locked(nfsi, server); |
dda4b2256 NFS: Introduce nf... |
204 205 206 |
spin_unlock(&clp->cl_lock); return delegation; } |
d3978bb32 NFS: Move cl_dele... |
207 208 209 210 211 212 213 |
/** * nfs_inode_set_delegation - set up a delegation on an inode * @inode: inode to which delegation applies * @cred: cred to use for subsequent delegation processing * @res: new delegation state from server * * Returns zero on success, or a negative errno value. |
1da177e4c Linux-2.6.12-rc2 |
214 215 216 |
*/ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) { |
d3978bb32 NFS: Move cl_dele... |
217 218 |
struct nfs_server *server = NFS_SERVER(inode); struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
219 |
struct nfs_inode *nfsi = NFS_I(inode); |
17d2c0a0c NFS: Fix RCU issu... |
220 |
struct nfs_delegation *delegation, *old_delegation; |
57bfa8917 NFSv4: Deal more ... |
221 |
struct nfs_delegation *freeme = NULL; |
1da177e4c Linux-2.6.12-rc2 |
222 |
int status = 0; |
8535b2be5 NFSv4: Don't use ... |
223 |
delegation = kmalloc(sizeof(*delegation), GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
224 225 226 227 228 229 |
if (delegation == NULL) return -ENOMEM; memcpy(delegation->stateid.data, res->delegation.data, sizeof(delegation->stateid.data)); delegation->type = res->delegation_type; delegation->maxsize = res->maxsize; |
a9a4a87a5 NFS: Use the inod... |
230 |
delegation->change_attr = inode->i_version; |
1da177e4c Linux-2.6.12-rc2 |
231 232 |
delegation->cred = get_rpccred(cred); delegation->inode = inode; |
b7391f44f NFSv4: Return unr... |
233 |
delegation->flags = 1<<NFS_DELEGATION_REFERENCED; |
343104308 NFSv4: Fix up ano... |
234 |
spin_lock_init(&delegation->lock); |
1da177e4c Linux-2.6.12-rc2 |
235 236 |
spin_lock(&clp->cl_lock); |
17d2c0a0c NFS: Fix RCU issu... |
237 |
old_delegation = rcu_dereference_protected(nfsi->delegation, |
d3978bb32 NFS: Move cl_dele... |
238 |
lockdep_is_held(&clp->cl_lock)); |
17d2c0a0c NFS: Fix RCU issu... |
239 240 241 242 |
if (old_delegation != NULL) { if (memcmp(&delegation->stateid, &old_delegation->stateid, sizeof(old_delegation->stateid)) == 0 && delegation->type == old_delegation->type) { |
57bfa8917 NFSv4: Deal more ... |
243 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
244 |
} |
57bfa8917 NFSv4: Deal more ... |
245 246 247 248 249 250 251 |
/* * Deal with broken servers that hand out two * delegations for the same file. */ dfprintk(FILE, "%s: server %s handed out " "a duplicate delegation! ", |
3110ff804 nfs: replace rema... |
252 |
__func__, clp->cl_hostname); |
17d2c0a0c NFS: Fix RCU issu... |
253 |
if (delegation->type <= old_delegation->type) { |
57bfa8917 NFSv4: Deal more ... |
254 255 256 257 |
freeme = delegation; delegation = NULL; goto out; } |
d3978bb32 NFS: Move cl_dele... |
258 |
freeme = nfs_detach_delegation_locked(nfsi, server); |
1da177e4c Linux-2.6.12-rc2 |
259 |
} |
d3978bb32 NFS: Move cl_dele... |
260 |
list_add_rcu(&delegation->super_list, &server->delegations); |
57bfa8917 NFSv4: Deal more ... |
261 262 263 |
nfsi->delegation_state = delegation->type; rcu_assign_pointer(nfsi->delegation, delegation); delegation = NULL; |
412c77cee NFSv4: Defer inod... |
264 265 266 267 268 |
/* Ensure we revalidate the attributes and page cache! */ spin_lock(&inode->i_lock); nfsi->cache_validity |= NFS_INO_REVAL_FORCED; spin_unlock(&inode->i_lock); |
57bfa8917 NFSv4: Deal more ... |
269 |
out: |
1da177e4c Linux-2.6.12-rc2 |
270 |
spin_unlock(&clp->cl_lock); |
603c83da1 NFSv4: Fix an rpc... |
271 272 |
if (delegation != NULL) nfs_free_delegation(delegation); |
57bfa8917 NFSv4: Deal more ... |
273 274 |
if (freeme != NULL) nfs_do_return_delegation(inode, freeme, 0); |
1da177e4c Linux-2.6.12-rc2 |
275 276 |
return status; } |
1da177e4c Linux-2.6.12-rc2 |
277 278 279 |
/* * Basic procedure for returning a delegation to the server */ |
d18cc1fda NFSv4: Fix a pote... |
280 |
static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) |
1da177e4c Linux-2.6.12-rc2 |
281 |
{ |
1da177e4c Linux-2.6.12-rc2 |
282 |
struct nfs_inode *nfsi = NFS_I(inode); |
d18cc1fda NFSv4: Fix a pote... |
283 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
284 |
|
3f09df70e NFS: Ensure we al... |
285 286 287 288 |
/* * Guard against new delegated open/lock/unlock calls and against * state recovery */ |
1da177e4c Linux-2.6.12-rc2 |
289 |
down_write(&nfsi->rwsem); |
d18cc1fda NFSv4: Fix a pote... |
290 |
err = nfs_delegation_claim_opens(inode, &delegation->stateid); |
1da177e4c Linux-2.6.12-rc2 |
291 |
up_write(&nfsi->rwsem); |
d18cc1fda NFSv4: Fix a pote... |
292 293 |
if (err) goto out; |
1da177e4c Linux-2.6.12-rc2 |
294 |
|
d18cc1fda NFSv4: Fix a pote... |
295 296 297 |
err = nfs_do_return_delegation(inode, delegation, issync); out: return err; |
901630278 NFSv4: Support re... |
298 |
} |
d3978bb32 NFS: Move cl_dele... |
299 300 301 302 303 |
/** * nfs_client_return_marked_delegations - return previously marked delegations * @clp: nfs_client to process * * Returns zero on success, or a negative errno value. |
515d86117 NFSv4: Clean up t... |
304 |
*/ |
d18cc1fda NFSv4: Fix a pote... |
305 |
int nfs_client_return_marked_delegations(struct nfs_client *clp) |
515d86117 NFSv4: Clean up t... |
306 307 |
{ struct nfs_delegation *delegation; |
d3978bb32 NFS: Move cl_dele... |
308 |
struct nfs_server *server; |
515d86117 NFSv4: Clean up t... |
309 |
struct inode *inode; |
d18cc1fda NFSv4: Fix a pote... |
310 |
int err = 0; |
515d86117 NFSv4: Clean up t... |
311 312 313 |
restart: rcu_read_lock(); |
d3978bb32 NFS: Move cl_dele... |
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { list_for_each_entry_rcu(delegation, &server->delegations, super_list) { if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) continue; inode = nfs_delegation_grab_inode(delegation); if (inode == NULL) continue; delegation = nfs_detach_delegation(NFS_I(inode), server); rcu_read_unlock(); if (delegation != NULL) { filemap_flush(inode->i_mapping); err = __nfs_inode_return_delegation(inode, delegation, 0); } iput(inode); if (!err) goto restart; set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); return err; |
d18cc1fda NFSv4: Fix a pote... |
337 |
} |
515d86117 NFSv4: Clean up t... |
338 339 |
} rcu_read_unlock(); |
d18cc1fda NFSv4: Fix a pote... |
340 |
return 0; |
515d86117 NFSv4: Clean up t... |
341 |
} |
d3978bb32 NFS: Move cl_dele... |
342 343 344 345 346 347 |
/** * nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens * @inode: inode to process * * Does not protect against delegation reclaims, therefore really only safe * to be called from nfs4_clear_inode(). |
e6f810759 NFS: Add an async... |
348 349 350 |
*/ void nfs_inode_return_delegation_noreclaim(struct inode *inode) { |
d3978bb32 NFS: Move cl_dele... |
351 |
struct nfs_server *server = NFS_SERVER(inode); |
e6f810759 NFS: Add an async... |
352 353 |
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; |
17d2c0a0c NFS: Fix RCU issu... |
354 |
if (rcu_access_pointer(nfsi->delegation) != NULL) { |
d3978bb32 NFS: Move cl_dele... |
355 |
delegation = nfs_detach_delegation(nfsi, server); |
e6f810759 NFS: Add an async... |
356 357 358 359 |
if (delegation != NULL) nfs_do_return_delegation(inode, delegation, 0); } } |
d3978bb32 NFS: Move cl_dele... |
360 361 362 363 364 365 |
/** * nfs_inode_return_delegation - synchronously return a delegation * @inode: inode to process * * Returns zero on success, or a negative errno value. */ |
901630278 NFSv4: Support re... |
366 367 |
int nfs_inode_return_delegation(struct inode *inode) { |
d3978bb32 NFS: Move cl_dele... |
368 |
struct nfs_server *server = NFS_SERVER(inode); |
901630278 NFSv4: Support re... |
369 370 371 |
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; int err = 0; |
17d2c0a0c NFS: Fix RCU issu... |
372 |
if (rcu_access_pointer(nfsi->delegation) != NULL) { |
d3978bb32 NFS: Move cl_dele... |
373 |
delegation = nfs_detach_delegation(nfsi, server); |
d18cc1fda NFSv4: Fix a pote... |
374 |
if (delegation != NULL) { |
1b924e5f8 NFS: Clean up the... |
375 |
nfs_wb_all(inode); |
d18cc1fda NFSv4: Fix a pote... |
376 377 |
err = __nfs_inode_return_delegation(inode, delegation, 1); } |
901630278 NFSv4: Support re... |
378 379 |
} return err; |
1da177e4c Linux-2.6.12-rc2 |
380 |
} |
ed1e6211a NFSv4: Don't use ... |
381 382 |
static void nfs_mark_return_delegation(struct nfs_server *server, struct nfs_delegation *delegation) |
6411bd4a4 NFSv4: Clean up t... |
383 384 |
{ set_bit(NFS_DELEGATION_RETURN, &delegation->flags); |
ed1e6211a NFSv4: Don't use ... |
385 |
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); |
6411bd4a4 NFSv4: Clean up t... |
386 |
} |
d3978bb32 NFS: Move cl_dele... |
387 388 389 390 |
/** * nfs_super_return_all_delegations - return delegations for one superblock * @sb: sb to process * |
1da177e4c Linux-2.6.12-rc2 |
391 |
*/ |
515d86117 NFSv4: Clean up t... |
392 |
void nfs_super_return_all_delegations(struct super_block *sb) |
1da177e4c Linux-2.6.12-rc2 |
393 |
{ |
d3978bb32 NFS: Move cl_dele... |
394 395 |
struct nfs_server *server = NFS_SB(sb); struct nfs_client *clp = server->nfs_client; |
1da177e4c Linux-2.6.12-rc2 |
396 |
struct nfs_delegation *delegation; |
1da177e4c Linux-2.6.12-rc2 |
397 398 399 |
if (clp == NULL) return; |
d3978bb32 NFS: Move cl_dele... |
400 |
|
8383e4602 NFSv4: Use RCU to... |
401 |
rcu_read_lock(); |
d3978bb32 NFS: Move cl_dele... |
402 |
list_for_each_entry_rcu(delegation, &server->delegations, super_list) { |
86e894899 NFSv4: Fix up the... |
403 |
spin_lock(&delegation->lock); |
d3978bb32 NFS: Move cl_dele... |
404 |
set_bit(NFS_DELEGATION_RETURN, &delegation->flags); |
86e894899 NFSv4: Fix up the... |
405 |
spin_unlock(&delegation->lock); |
1da177e4c Linux-2.6.12-rc2 |
406 |
} |
8383e4602 NFSv4: Use RCU to... |
407 |
rcu_read_unlock(); |
d3978bb32 NFS: Move cl_dele... |
408 |
|
d18cc1fda NFSv4: Fix a pote... |
409 410 |
if (nfs_client_return_marked_delegations(clp) != 0) nfs4_schedule_state_manager(clp); |
515d86117 NFSv4: Clean up t... |
411 |
} |
d3978bb32 NFS: Move cl_dele... |
412 413 |
static void nfs_mark_return_all_delegation_types(struct nfs_server *server, fmode_t flags) |
515d86117 NFSv4: Clean up t... |
414 415 |
{ struct nfs_delegation *delegation; |
d3978bb32 NFS: Move cl_dele... |
416 |
list_for_each_entry_rcu(delegation, &server->delegations, super_list) { |
c79571a50 nfs4: V2 return/e... |
417 418 419 |
if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE)) continue; if (delegation->type & flags) |
ed1e6211a NFSv4: Don't use ... |
420 |
nfs_mark_return_delegation(server, delegation); |
707fb4b32 NFSv4: Clean up N... |
421 |
} |
d3978bb32 NFS: Move cl_dele... |
422 423 424 425 426 427 428 429 430 431 |
} static void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags) { struct nfs_server *server; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) nfs_mark_return_all_delegation_types(server, flags); |
515d86117 NFSv4: Clean up t... |
432 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
433 |
} |
c79571a50 nfs4: V2 return/e... |
434 435 436 437 |
static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) { nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE); } |
b0d3ded1a NFSv4: Clean up n... |
438 |
static void nfs_delegation_run_state_manager(struct nfs_client *clp) |
58d9714a4 NFSv4: Send RENEW... |
439 |
{ |
b0d3ded1a NFSv4: Clean up n... |
440 441 |
if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) nfs4_schedule_state_manager(clp); |
58d9714a4 NFSv4: Send RENEW... |
442 |
} |
d3978bb32 NFS: Move cl_dele... |
443 444 445 446 447 448 |
/** * nfs_expire_all_delegation_types * @clp: client to process * @flags: delegation types to expire * */ |
31f096077 nfs41: V2 initial... |
449 |
void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags) |
58d9714a4 NFSv4: Send RENEW... |
450 |
{ |
c79571a50 nfs4: V2 return/e... |
451 |
nfs_client_mark_return_all_delegation_types(clp, flags); |
b0d3ded1a NFSv4: Clean up n... |
452 |
nfs_delegation_run_state_manager(clp); |
58d9714a4 NFSv4: Send RENEW... |
453 |
} |
d3978bb32 NFS: Move cl_dele... |
454 455 456 457 458 |
/** * nfs_expire_all_delegations * @clp: client to process * */ |
c79571a50 nfs4: V2 return/e... |
459 460 461 462 |
void nfs_expire_all_delegations(struct nfs_client *clp) { nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE); } |
d3978bb32 NFS: Move cl_dele... |
463 464 465 466 |
/** * nfs_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN * @clp: client to process * |
1da177e4c Linux-2.6.12-rc2 |
467 |
*/ |
adfa6f980 NFS: Rename struc... |
468 |
void nfs_handle_cb_pathdown(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
469 |
{ |
1da177e4c Linux-2.6.12-rc2 |
470 471 |
if (clp == NULL) return; |
707fb4b32 NFSv4: Clean up N... |
472 |
nfs_client_mark_return_all_delegations(clp); |
1da177e4c Linux-2.6.12-rc2 |
473 |
} |
d3978bb32 NFS: Move cl_dele... |
474 |
static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server) |
b7391f44f NFSv4: Return unr... |
475 476 |
{ struct nfs_delegation *delegation; |
d3978bb32 NFS: Move cl_dele... |
477 |
list_for_each_entry_rcu(delegation, &server->delegations, super_list) { |
b7391f44f NFSv4: Return unr... |
478 479 |
if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags)) continue; |
ed1e6211a NFSv4: Don't use ... |
480 |
nfs_mark_return_delegation(server, delegation); |
b7391f44f NFSv4: Return unr... |
481 |
} |
b7391f44f NFSv4: Return unr... |
482 |
} |
d3978bb32 NFS: Move cl_dele... |
483 484 485 486 487 |
/** * nfs_expire_unreferenced_delegations - Eliminate unused delegations * @clp: nfs_client to process * */ |
b7391f44f NFSv4: Return unr... |
488 489 |
void nfs_expire_unreferenced_delegations(struct nfs_client *clp) { |
d3978bb32 NFS: Move cl_dele... |
490 491 492 493 494 495 |
struct nfs_server *server; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) nfs_mark_return_unreferenced_delegations(server); rcu_read_unlock(); |
b7391f44f NFSv4: Return unr... |
496 497 |
nfs_delegation_run_state_manager(clp); } |
d3978bb32 NFS: Move cl_dele... |
498 499 500 501 502 503 |
/** * nfs_async_inode_return_delegation - asynchronously return a delegation * @inode: inode to process * @stateid: state ID information from CB_RECALL arguments * * Returns zero on success, or a negative errno value. |
1da177e4c Linux-2.6.12-rc2 |
504 |
*/ |
d3978bb32 NFS: Move cl_dele... |
505 506 |
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) |
1da177e4c Linux-2.6.12-rc2 |
507 |
{ |
ed1e6211a NFSv4: Don't use ... |
508 509 |
struct nfs_server *server = NFS_SERVER(inode); struct nfs_client *clp = server->nfs_client; |
6411bd4a4 NFSv4: Clean up t... |
510 |
struct nfs_delegation *delegation; |
1da177e4c Linux-2.6.12-rc2 |
511 |
|
6411bd4a4 NFSv4: Clean up t... |
512 513 |
rcu_read_lock(); delegation = rcu_dereference(NFS_I(inode)->delegation); |
2597641de nfs41: v2 fix cb_... |
514 |
|
e047a10c1 NFSv41: Fix nfs_a... |
515 |
if (!clp->cl_mvops->validate_stateid(delegation, stateid)) { |
6411bd4a4 NFSv4: Clean up t... |
516 517 518 |
rcu_read_unlock(); return -ENOENT; } |
ed1e6211a NFSv4: Don't use ... |
519 |
nfs_mark_return_delegation(server, delegation); |
6411bd4a4 NFSv4: Clean up t... |
520 |
rcu_read_unlock(); |
d3978bb32 NFS: Move cl_dele... |
521 |
|
6411bd4a4 NFSv4: Clean up t... |
522 523 |
nfs_delegation_run_state_manager(clp); return 0; |
1da177e4c Linux-2.6.12-rc2 |
524 |
} |
d3978bb32 NFS: Move cl_dele... |
525 526 527 |
static struct inode * nfs_delegation_find_inode_server(struct nfs_server *server, const struct nfs_fh *fhandle) |
1da177e4c Linux-2.6.12-rc2 |
528 529 530 |
{ struct nfs_delegation *delegation; struct inode *res = NULL; |
d3978bb32 NFS: Move cl_dele... |
531 532 |
list_for_each_entry_rcu(delegation, &server->delegations, super_list) { |
86e894899 NFSv4: Fix up the... |
533 534 535 |
spin_lock(&delegation->lock); if (delegation->inode != NULL && nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) { |
1da177e4c Linux-2.6.12-rc2 |
536 |
res = igrab(delegation->inode); |
1da177e4c Linux-2.6.12-rc2 |
537 |
} |
86e894899 NFSv4: Fix up the... |
538 539 540 |
spin_unlock(&delegation->lock); if (res != NULL) break; |
1da177e4c Linux-2.6.12-rc2 |
541 |
} |
d3978bb32 NFS: Move cl_dele... |
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
return res; } /** * nfs_delegation_find_inode - retrieve the inode associated with a delegation * @clp: client state handle * @fhandle: filehandle from a delegation recall * * Returns pointer to inode matching "fhandle," or NULL if a matching inode * cannot be found. */ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle) { struct nfs_server *server; struct inode *res = NULL; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { res = nfs_delegation_find_inode_server(server, fhandle); if (res != NULL) break; } |
8383e4602 NFSv4: Use RCU to... |
565 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
566 567 |
return res; } |
d3978bb32 NFS: Move cl_dele... |
568 569 570 571 572 573 574 575 576 577 578 579 |
static void nfs_delegation_mark_reclaim_server(struct nfs_server *server) { struct nfs_delegation *delegation; list_for_each_entry_rcu(delegation, &server->delegations, super_list) set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); } /** * nfs_delegation_mark_reclaim - mark all delegations as needing to be reclaimed * @clp: nfs_client to process * |
1da177e4c Linux-2.6.12-rc2 |
580 |
*/ |
adfa6f980 NFS: Rename struc... |
581 |
void nfs_delegation_mark_reclaim(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
582 |
{ |
d3978bb32 NFS: Move cl_dele... |
583 |
struct nfs_server *server; |
8383e4602 NFSv4: Use RCU to... |
584 |
rcu_read_lock(); |
d3978bb32 NFS: Move cl_dele... |
585 586 |
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) nfs_delegation_mark_reclaim_server(server); |
8383e4602 NFSv4: Use RCU to... |
587 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
588 |
} |
d3978bb32 NFS: Move cl_dele... |
589 590 591 592 |
/** * nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done * @clp: nfs_client to process * |
1da177e4c Linux-2.6.12-rc2 |
593 |
*/ |
adfa6f980 NFS: Rename struc... |
594 |
void nfs_delegation_reap_unclaimed(struct nfs_client *clp) |
1da177e4c Linux-2.6.12-rc2 |
595 |
{ |
8383e4602 NFSv4: Use RCU to... |
596 |
struct nfs_delegation *delegation; |
d3978bb32 NFS: Move cl_dele... |
597 |
struct nfs_server *server; |
86e894899 NFSv4: Fix up the... |
598 |
struct inode *inode; |
d3978bb32 NFS: Move cl_dele... |
599 |
|
8383e4602 NFSv4: Use RCU to... |
600 601 |
restart: rcu_read_lock(); |
d3978bb32 NFS: Move cl_dele... |
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { list_for_each_entry_rcu(delegation, &server->delegations, super_list) { if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) continue; inode = nfs_delegation_grab_inode(delegation); if (inode == NULL) continue; delegation = nfs_detach_delegation(NFS_I(inode), server); rcu_read_unlock(); if (delegation != NULL) nfs_free_delegation(delegation); iput(inode); goto restart; } |
1da177e4c Linux-2.6.12-rc2 |
620 |
} |
8383e4602 NFSv4: Use RCU to... |
621 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
622 |
} |
3e4f6290c NFSv4: Send the d... |
623 |
|
d3978bb32 NFS: Move cl_dele... |
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
/** * nfs_delegations_present - check for existence of delegations * @clp: client state handle * * Returns one if there are any nfs_delegation structures attached * to this nfs_client. */ int nfs_delegations_present(struct nfs_client *clp) { struct nfs_server *server; int ret = 0; rcu_read_lock(); list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) if (!list_empty(&server->delegations)) { ret = 1; break; } rcu_read_unlock(); return ret; } /** * nfs4_copy_delegation_stateid - Copy inode's state ID information * @dst: stateid data structure to fill in * @inode: inode to check * * Returns one and fills in "dst->data" * if inode had a delegation, * otherwise zero is returned. */ |
3e4f6290c NFSv4: Send the d... |
654 655 |
int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode) { |
3e4f6290c NFSv4: Send the d... |
656 657 |
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; |
8383e4602 NFSv4: Use RCU to... |
658 |
int ret = 0; |
3e4f6290c NFSv4: Send the d... |
659 |
|
8383e4602 NFSv4: Use RCU to... |
660 661 |
rcu_read_lock(); delegation = rcu_dereference(nfsi->delegation); |
3e4f6290c NFSv4: Send the d... |
662 663 |
if (delegation != NULL) { memcpy(dst->data, delegation->stateid.data, sizeof(dst->data)); |
8383e4602 NFSv4: Use RCU to... |
664 |
ret = 1; |
3e4f6290c NFSv4: Send the d... |
665 |
} |
8383e4602 NFSv4: Use RCU to... |
666 667 |
rcu_read_unlock(); return ret; |
3e4f6290c NFSv4: Send the d... |
668 |
} |