2
* linux/fs/nfs/delegation.c
4
* Copyright (C) 2004 Trond Myklebust
6
* NFS file delegation management
9
#include <linux/completion.h>
10
#include <linux/kthread.h>
11
#include <linux/module.h>
12
#include <linux/sched.h>
13
#include <linux/slab.h>
14
#include <linux/spinlock.h>
16
#include <linux/nfs4.h>
17
#include <linux/nfs_fs.h>
18
#include <linux/nfs_xdr.h>
21
#include "delegation.h"
24
static void nfs_free_delegation(struct nfs_delegation *delegation)
26
if (delegation->cred) {
27
put_rpccred(delegation->cred);
28
delegation->cred = NULL;
30
kfree_rcu(delegation, rcu);
34
* nfs_mark_delegation_referenced - set delegation's REFERENCED flag
35
* @delegation: delegation to process
38
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
40
set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
44
* nfs_have_delegation - check if inode has a delegation
45
* @inode: inode to check
46
* @flags: delegation types to check for
48
* Returns one if inode has the indicated delegation, otherwise zero.
50
int nfs_have_delegation(struct inode *inode, fmode_t flags)
52
struct nfs_delegation *delegation;
55
flags &= FMODE_READ|FMODE_WRITE;
57
delegation = rcu_dereference(NFS_I(inode)->delegation);
58
if (delegation != NULL && (delegation->type & flags) == flags) {
59
nfs_mark_delegation_referenced(delegation);
66
static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
68
struct inode *inode = state->inode;
72
if (inode->i_flock == NULL)
75
/* Protect inode->i_flock using the file locks lock */
77
for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
78
if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
80
if (nfs_file_open_context(fl->fl_file) != ctx)
83
status = nfs4_lock_delegation_recall(state, fl);
93
static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
95
struct nfs_inode *nfsi = NFS_I(inode);
96
struct nfs_open_context *ctx;
97
struct nfs4_state *state;
101
spin_lock(&inode->i_lock);
102
list_for_each_entry(ctx, &nfsi->open_files, list) {
106
if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
108
if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
110
get_nfs_open_context(ctx);
111
spin_unlock(&inode->i_lock);
112
err = nfs4_open_delegation_recall(ctx, state, stateid);
114
err = nfs_delegation_claim_locks(ctx, state);
115
put_nfs_open_context(ctx);
120
spin_unlock(&inode->i_lock);
125
* nfs_inode_reclaim_delegation - process a delegation reclaim request
126
* @inode: inode to process
127
* @cred: credential to use for request
128
* @res: new delegation state from server
131
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
132
struct nfs_openres *res)
134
struct nfs_delegation *delegation;
135
struct rpc_cred *oldcred = NULL;
138
delegation = rcu_dereference(NFS_I(inode)->delegation);
139
if (delegation != NULL) {
140
spin_lock(&delegation->lock);
141
if (delegation->inode != NULL) {
142
memcpy(delegation->stateid.data, res->delegation.data,
143
sizeof(delegation->stateid.data));
144
delegation->type = res->delegation_type;
145
delegation->maxsize = res->maxsize;
146
oldcred = delegation->cred;
147
delegation->cred = get_rpccred(cred);
148
clear_bit(NFS_DELEGATION_NEED_RECLAIM,
150
NFS_I(inode)->delegation_state = delegation->type;
151
spin_unlock(&delegation->lock);
152
put_rpccred(oldcred);
155
/* We appear to have raced with a delegation return. */
156
spin_unlock(&delegation->lock);
158
nfs_inode_set_delegation(inode, cred, res);
165
static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
169
res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
170
nfs_free_delegation(delegation);
174
static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
176
struct inode *inode = NULL;
178
spin_lock(&delegation->lock);
179
if (delegation->inode != NULL)
180
inode = igrab(delegation->inode);
181
spin_unlock(&delegation->lock);
185
static struct nfs_delegation *
186
nfs_detach_delegation_locked(struct nfs_inode *nfsi,
187
struct nfs_server *server)
189
struct nfs_delegation *delegation =
190
rcu_dereference_protected(nfsi->delegation,
191
lockdep_is_held(&server->nfs_client->cl_lock));
193
if (delegation == NULL)
196
spin_lock(&delegation->lock);
197
list_del_rcu(&delegation->super_list);
198
delegation->inode = NULL;
199
nfsi->delegation_state = 0;
200
rcu_assign_pointer(nfsi->delegation, NULL);
201
spin_unlock(&delegation->lock);
207
static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi,
208
struct nfs_server *server)
210
struct nfs_client *clp = server->nfs_client;
211
struct nfs_delegation *delegation;
213
spin_lock(&clp->cl_lock);
214
delegation = nfs_detach_delegation_locked(nfsi, server);
215
spin_unlock(&clp->cl_lock);
220
* nfs_inode_set_delegation - set up a delegation on an inode
221
* @inode: inode to which delegation applies
222
* @cred: cred to use for subsequent delegation processing
223
* @res: new delegation state from server
225
* Returns zero on success, or a negative errno value.
227
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
229
struct nfs_server *server = NFS_SERVER(inode);
230
struct nfs_client *clp = server->nfs_client;
231
struct nfs_inode *nfsi = NFS_I(inode);
232
struct nfs_delegation *delegation, *old_delegation;
233
struct nfs_delegation *freeme = NULL;
236
delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
237
if (delegation == NULL)
239
memcpy(delegation->stateid.data, res->delegation.data,
240
sizeof(delegation->stateid.data));
241
delegation->type = res->delegation_type;
242
delegation->maxsize = res->maxsize;
243
delegation->change_attr = inode->i_version;
244
delegation->cred = get_rpccred(cred);
245
delegation->inode = inode;
246
delegation->flags = 1<<NFS_DELEGATION_REFERENCED;
247
spin_lock_init(&delegation->lock);
249
spin_lock(&clp->cl_lock);
250
old_delegation = rcu_dereference_protected(nfsi->delegation,
251
lockdep_is_held(&clp->cl_lock));
252
if (old_delegation != NULL) {
253
if (memcmp(&delegation->stateid, &old_delegation->stateid,
254
sizeof(old_delegation->stateid)) == 0 &&
255
delegation->type == old_delegation->type) {
259
* Deal with broken servers that hand out two
260
* delegations for the same file.
262
dfprintk(FILE, "%s: server %s handed out "
263
"a duplicate delegation!\n",
264
__func__, clp->cl_hostname);
265
if (delegation->type <= old_delegation->type) {
270
freeme = nfs_detach_delegation_locked(nfsi, server);
272
list_add_rcu(&delegation->super_list, &server->delegations);
273
nfsi->delegation_state = delegation->type;
274
rcu_assign_pointer(nfsi->delegation, delegation);
277
/* Ensure we revalidate the attributes and page cache! */
278
spin_lock(&inode->i_lock);
279
nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
280
spin_unlock(&inode->i_lock);
283
spin_unlock(&clp->cl_lock);
284
if (delegation != NULL)
285
nfs_free_delegation(delegation);
287
nfs_do_return_delegation(inode, freeme, 0);
292
* Basic procedure for returning a delegation to the server
294
static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
296
struct nfs_inode *nfsi = NFS_I(inode);
300
* Guard against new delegated open/lock/unlock calls and against
303
down_write(&nfsi->rwsem);
304
err = nfs_delegation_claim_opens(inode, &delegation->stateid);
305
up_write(&nfsi->rwsem);
309
err = nfs_do_return_delegation(inode, delegation, issync);
315
* nfs_client_return_marked_delegations - return previously marked delegations
316
* @clp: nfs_client to process
318
* Returns zero on success, or a negative errno value.
320
int nfs_client_return_marked_delegations(struct nfs_client *clp)
322
struct nfs_delegation *delegation;
323
struct nfs_server *server;
329
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
330
list_for_each_entry_rcu(delegation, &server->delegations,
332
if (!test_and_clear_bit(NFS_DELEGATION_RETURN,
335
inode = nfs_delegation_grab_inode(delegation);
338
delegation = nfs_detach_delegation(NFS_I(inode),
342
if (delegation != NULL) {
343
filemap_flush(inode->i_mapping);
344
err = __nfs_inode_return_delegation(inode,
350
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
359
* nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens
360
* @inode: inode to process
362
* Does not protect against delegation reclaims, therefore really only safe
363
* to be called from nfs4_clear_inode().
365
void nfs_inode_return_delegation_noreclaim(struct inode *inode)
367
struct nfs_server *server = NFS_SERVER(inode);
368
struct nfs_inode *nfsi = NFS_I(inode);
369
struct nfs_delegation *delegation;
371
if (rcu_access_pointer(nfsi->delegation) != NULL) {
372
delegation = nfs_detach_delegation(nfsi, server);
373
if (delegation != NULL)
374
nfs_do_return_delegation(inode, delegation, 0);
379
* nfs_inode_return_delegation - synchronously return a delegation
380
* @inode: inode to process
382
* Returns zero on success, or a negative errno value.
384
int nfs_inode_return_delegation(struct inode *inode)
386
struct nfs_server *server = NFS_SERVER(inode);
387
struct nfs_inode *nfsi = NFS_I(inode);
388
struct nfs_delegation *delegation;
391
if (rcu_access_pointer(nfsi->delegation) != NULL) {
392
delegation = nfs_detach_delegation(nfsi, server);
393
if (delegation != NULL) {
395
err = __nfs_inode_return_delegation(inode, delegation, 1);
401
static void nfs_mark_return_delegation(struct nfs_server *server,
402
struct nfs_delegation *delegation)
404
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
405
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
409
* nfs_super_return_all_delegations - return delegations for one superblock
413
void nfs_super_return_all_delegations(struct super_block *sb)
415
struct nfs_server *server = NFS_SB(sb);
416
struct nfs_client *clp = server->nfs_client;
417
struct nfs_delegation *delegation;
423
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
424
spin_lock(&delegation->lock);
425
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
426
spin_unlock(&delegation->lock);
430
if (nfs_client_return_marked_delegations(clp) != 0)
431
nfs4_schedule_state_manager(clp);
434
static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
437
struct nfs_delegation *delegation;
439
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
440
if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
442
if (delegation->type & flags)
443
nfs_mark_return_delegation(server, delegation);
447
static void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp,
450
struct nfs_server *server;
453
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
454
nfs_mark_return_all_delegation_types(server, flags);
458
static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
460
nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
463
static void nfs_delegation_run_state_manager(struct nfs_client *clp)
465
if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
466
nfs4_schedule_state_manager(clp);
470
* nfs_expire_all_delegation_types
471
* @clp: client to process
472
* @flags: delegation types to expire
475
void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
477
nfs_client_mark_return_all_delegation_types(clp, flags);
478
nfs_delegation_run_state_manager(clp);
482
* nfs_expire_all_delegations
483
* @clp: client to process
486
void nfs_expire_all_delegations(struct nfs_client *clp)
488
nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
492
* nfs_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
493
* @clp: client to process
496
void nfs_handle_cb_pathdown(struct nfs_client *clp)
500
nfs_client_mark_return_all_delegations(clp);
503
static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
505
struct nfs_delegation *delegation;
507
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
508
if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
510
nfs_mark_return_delegation(server, delegation);
515
* nfs_expire_unreferenced_delegations - Eliminate unused delegations
516
* @clp: nfs_client to process
519
void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
521
struct nfs_server *server;
524
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
525
nfs_mark_return_unreferenced_delegations(server);
528
nfs_delegation_run_state_manager(clp);
532
* nfs_async_inode_return_delegation - asynchronously return a delegation
533
* @inode: inode to process
534
* @stateid: state ID information from CB_RECALL arguments
536
* Returns zero on success, or a negative errno value.
538
int nfs_async_inode_return_delegation(struct inode *inode,
539
const nfs4_stateid *stateid)
541
struct nfs_server *server = NFS_SERVER(inode);
542
struct nfs_client *clp = server->nfs_client;
543
struct nfs_delegation *delegation;
546
delegation = rcu_dereference(NFS_I(inode)->delegation);
548
if (!clp->cl_mvops->validate_stateid(delegation, stateid)) {
552
nfs_mark_return_delegation(server, delegation);
555
nfs_delegation_run_state_manager(clp);
559
static struct inode *
560
nfs_delegation_find_inode_server(struct nfs_server *server,
561
const struct nfs_fh *fhandle)
563
struct nfs_delegation *delegation;
564
struct inode *res = NULL;
566
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
567
spin_lock(&delegation->lock);
568
if (delegation->inode != NULL &&
569
nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
570
res = igrab(delegation->inode);
572
spin_unlock(&delegation->lock);
580
* nfs_delegation_find_inode - retrieve the inode associated with a delegation
581
* @clp: client state handle
582
* @fhandle: filehandle from a delegation recall
584
* Returns pointer to inode matching "fhandle," or NULL if a matching inode
587
struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
588
const struct nfs_fh *fhandle)
590
struct nfs_server *server;
591
struct inode *res = NULL;
594
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
595
res = nfs_delegation_find_inode_server(server, fhandle);
603
static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
605
struct nfs_delegation *delegation;
607
list_for_each_entry_rcu(delegation, &server->delegations, super_list)
608
set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
612
* nfs_delegation_mark_reclaim - mark all delegations as needing to be reclaimed
613
* @clp: nfs_client to process
616
void nfs_delegation_mark_reclaim(struct nfs_client *clp)
618
struct nfs_server *server;
621
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
622
nfs_delegation_mark_reclaim_server(server);
627
* nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done
628
* @clp: nfs_client to process
631
void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
633
struct nfs_delegation *delegation;
634
struct nfs_server *server;
639
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
640
list_for_each_entry_rcu(delegation, &server->delegations,
642
if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
643
&delegation->flags) == 0)
645
inode = nfs_delegation_grab_inode(delegation);
648
delegation = nfs_detach_delegation(NFS_I(inode),
652
if (delegation != NULL)
653
nfs_free_delegation(delegation);
662
* nfs_delegations_present - check for existence of delegations
663
* @clp: client state handle
665
* Returns one if there are any nfs_delegation structures attached
666
* to this nfs_client.
668
int nfs_delegations_present(struct nfs_client *clp)
670
struct nfs_server *server;
674
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
675
if (!list_empty(&server->delegations)) {
684
* nfs4_copy_delegation_stateid - Copy inode's state ID information
685
* @dst: stateid data structure to fill in
686
* @inode: inode to check
688
* Returns one and fills in "dst->data" * if inode had a delegation,
689
* otherwise zero is returned.
691
int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
693
struct nfs_inode *nfsi = NFS_I(inode);
694
struct nfs_delegation *delegation;
698
delegation = rcu_dereference(nfsi->delegation);
699
if (delegation != NULL) {
700
memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));