1/*
2 * linux/fs/nfs/delegation.c
3 *
4 * Copyright (C) 2004 Trond Myklebust
5 *
6 * NFS file delegation management
7 *
8 */
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/smp_lock.h>
15#include <linux/spinlock.h>
16
17#include <linux/nfs4.h>
18#include <linux/nfs_fs.h>
19#include <linux/nfs_xdr.h>
20
21#include "nfs4_fs.h"
22#include "delegation.h"
23#include "internal.h"
24
25static void nfs_do_free_delegation(struct nfs_delegation *delegation)
26{
27	kfree(delegation);
28}
29
30static void nfs_free_delegation_callback(struct rcu_head *head)
31{
32	struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
33
34	nfs_do_free_delegation(delegation);
35}
36
37static void nfs_free_delegation(struct nfs_delegation *delegation)
38{
39	if (delegation->cred) {
40		put_rpccred(delegation->cred);
41		delegation->cred = NULL;
42	}
43	call_rcu(&delegation->rcu, nfs_free_delegation_callback);
44}
45
46void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
47{
48	set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
49}
50
51int nfs_have_delegation(struct inode *inode, fmode_t flags)
52{
53	struct nfs_delegation *delegation;
54	int ret = 0;
55
56	flags &= FMODE_READ|FMODE_WRITE;
57	rcu_read_lock();
58	delegation = rcu_dereference(NFS_I(inode)->delegation);
59	if (delegation != NULL && (delegation->type & flags) == flags) {
60		nfs_mark_delegation_referenced(delegation);
61		ret = 1;
62	}
63	rcu_read_unlock();
64	return ret;
65}
66
67static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
68{
69	struct inode *inode = state->inode;
70	struct file_lock *fl;
71	int status = 0;
72
73	if (inode->i_flock == NULL)
74		goto out;
75
76	/* Protect inode->i_flock using the BKL */
77	lock_kernel();
78	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
79		if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
80			continue;
81		if (nfs_file_open_context(fl->fl_file) != ctx)
82			continue;
83		unlock_kernel();
84		status = nfs4_lock_delegation_recall(state, fl);
85		if (status < 0)
86			goto out;
87		lock_kernel();
88	}
89	unlock_kernel();
90out:
91	return status;
92}
93
94static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
95{
96	struct nfs_inode *nfsi = NFS_I(inode);
97	struct nfs_open_context *ctx;
98	struct nfs4_state *state;
99	int err;
100
101again:
102	spin_lock(&inode->i_lock);
103	list_for_each_entry(ctx, &nfsi->open_files, list) {
104		state = ctx->state;
105		if (state == NULL)
106			continue;
107		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
108			continue;
109		if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
110			continue;
111		get_nfs_open_context(ctx);
112		spin_unlock(&inode->i_lock);
113		err = nfs4_open_delegation_recall(ctx, state, stateid);
114		if (err >= 0)
115			err = nfs_delegation_claim_locks(ctx, state);
116		put_nfs_open_context(ctx);
117		if (err != 0)
118			return err;
119		goto again;
120	}
121	spin_unlock(&inode->i_lock);
122	return 0;
123}
124
125/*
126 * Set up a delegation on an inode
127 */
128void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
129{
130	struct nfs_delegation *delegation;
131	struct rpc_cred *oldcred = NULL;
132
133	rcu_read_lock();
134	delegation = rcu_dereference(NFS_I(inode)->delegation);
135	if (delegation != NULL) {
136		spin_lock(&delegation->lock);
137		if (delegation->inode != NULL) {
138			memcpy(delegation->stateid.data, res->delegation.data,
139			       sizeof(delegation->stateid.data));
140			delegation->type = res->delegation_type;
141			delegation->maxsize = res->maxsize;
142			oldcred = delegation->cred;
143			delegation->cred = get_rpccred(cred);
144			clear_bit(NFS_DELEGATION_NEED_RECLAIM,
145				  &delegation->flags);
146			NFS_I(inode)->delegation_state = delegation->type;
147			spin_unlock(&delegation->lock);
148			put_rpccred(oldcred);
149			rcu_read_unlock();
150		} else {
151			/* We appear to have raced with a delegation return. */
152			spin_unlock(&delegation->lock);
153			rcu_read_unlock();
154			nfs_inode_set_delegation(inode, cred, res);
155		}
156	} else {
157		rcu_read_unlock();
158	}
159}
160
161static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
162{
163	int res = 0;
164
165	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
166	nfs_free_delegation(delegation);
167	return res;
168}
169
170static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
171{
172	struct inode *inode = NULL;
173
174	spin_lock(&delegation->lock);
175	if (delegation->inode != NULL)
176		inode = igrab(delegation->inode);
177	spin_unlock(&delegation->lock);
178	return inode;
179}
180
181static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi,
182							   const nfs4_stateid *stateid,
183							   struct nfs_client *clp)
184{
185	struct nfs_delegation *delegation =
186		rcu_dereference_protected(nfsi->delegation,
187					  lockdep_is_held(&clp->cl_lock));
188
189	if (delegation == NULL)
190		goto nomatch;
191	spin_lock(&delegation->lock);
192	if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
193				sizeof(delegation->stateid.data)) != 0)
194		goto nomatch_unlock;
195	list_del_rcu(&delegation->super_list);
196	delegation->inode = NULL;
197	nfsi->delegation_state = 0;
198	rcu_assign_pointer(nfsi->delegation, NULL);
199	spin_unlock(&delegation->lock);
200	return delegation;
201nomatch_unlock:
202	spin_unlock(&delegation->lock);
203nomatch:
204	return NULL;
205}
206
207/*
208 * Set up a delegation on an inode
209 */
210int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
211{
212	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
213	struct nfs_inode *nfsi = NFS_I(inode);
214	struct nfs_delegation *delegation, *old_delegation;
215	struct nfs_delegation *freeme = NULL;
216	int status = 0;
217
218	delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
219	if (delegation == NULL)
220		return -ENOMEM;
221	memcpy(delegation->stateid.data, res->delegation.data,
222			sizeof(delegation->stateid.data));
223	delegation->type = res->delegation_type;
224	delegation->maxsize = res->maxsize;
225	delegation->change_attr = nfsi->change_attr;
226	delegation->cred = get_rpccred(cred);
227	delegation->inode = inode;
228	delegation->flags = 1<<NFS_DELEGATION_REFERENCED;
229	spin_lock_init(&delegation->lock);
230
231	spin_lock(&clp->cl_lock);
232	old_delegation = rcu_dereference_protected(nfsi->delegation,
233						   lockdep_is_held(&clp->cl_lock));
234	if (old_delegation != NULL) {
235		if (memcmp(&delegation->stateid, &old_delegation->stateid,
236					sizeof(old_delegation->stateid)) == 0 &&
237				delegation->type == old_delegation->type) {
238			goto out;
239		}
240		/*
241		 * Deal with broken servers that hand out two
242		 * delegations for the same file.
243		 */
244		dfprintk(FILE, "%s: server %s handed out "
245				"a duplicate delegation!\n",
246				__func__, clp->cl_hostname);
247		if (delegation->type <= old_delegation->type) {
248			freeme = delegation;
249			delegation = NULL;
250			goto out;
251		}
252		freeme = nfs_detach_delegation_locked(nfsi, NULL, clp);
253	}
254	list_add_rcu(&delegation->super_list, &clp->cl_delegations);
255	nfsi->delegation_state = delegation->type;
256	rcu_assign_pointer(nfsi->delegation, delegation);
257	delegation = NULL;
258
259	/* Ensure we revalidate the attributes and page cache! */
260	spin_lock(&inode->i_lock);
261	nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
262	spin_unlock(&inode->i_lock);
263
264out:
265	spin_unlock(&clp->cl_lock);
266	if (delegation != NULL)
267		nfs_free_delegation(delegation);
268	if (freeme != NULL)
269		nfs_do_return_delegation(inode, freeme, 0);
270	return status;
271}
272
273/*
274 * Basic procedure for returning a delegation to the server
275 */
276static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
277{
278	struct nfs_inode *nfsi = NFS_I(inode);
279	int err;
280
281	/*
282	 * Guard against new delegated open/lock/unlock calls and against
283	 * state recovery
284	 */
285	down_write(&nfsi->rwsem);
286	err = nfs_delegation_claim_opens(inode, &delegation->stateid);
287	up_write(&nfsi->rwsem);
288	if (err)
289		goto out;
290
291	err = nfs_do_return_delegation(inode, delegation, issync);
292out:
293	return err;
294}
295
296/*
297 * Return all delegations that have been marked for return
298 */
299int nfs_client_return_marked_delegations(struct nfs_client *clp)
300{
301	struct nfs_delegation *delegation;
302	struct inode *inode;
303	int err = 0;
304
305restart:
306	rcu_read_lock();
307	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
308		if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
309			continue;
310		inode = nfs_delegation_grab_inode(delegation);
311		if (inode == NULL)
312			continue;
313		spin_lock(&clp->cl_lock);
314		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp);
315		spin_unlock(&clp->cl_lock);
316		rcu_read_unlock();
317		if (delegation != NULL) {
318			filemap_flush(inode->i_mapping);
319			err = __nfs_inode_return_delegation(inode, delegation, 0);
320		}
321		iput(inode);
322		if (!err)
323			goto restart;
324		set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
325		return err;
326	}
327	rcu_read_unlock();
328	return 0;
329}
330
331/*
332 * This function returns the delegation without reclaiming opens
333 * or protecting against delegation reclaims.
334 * It is therefore really only safe to be called from
335 * nfs4_clear_inode()
336 */
337void nfs_inode_return_delegation_noreclaim(struct inode *inode)
338{
339	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
340	struct nfs_inode *nfsi = NFS_I(inode);
341	struct nfs_delegation *delegation;
342
343	if (rcu_access_pointer(nfsi->delegation) != NULL) {
344		spin_lock(&clp->cl_lock);
345		delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
346		spin_unlock(&clp->cl_lock);
347		if (delegation != NULL)
348			nfs_do_return_delegation(inode, delegation, 0);
349	}
350}
351
352int nfs_inode_return_delegation(struct inode *inode)
353{
354	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
355	struct nfs_inode *nfsi = NFS_I(inode);
356	struct nfs_delegation *delegation;
357	int err = 0;
358
359	if (rcu_access_pointer(nfsi->delegation) != NULL) {
360		spin_lock(&clp->cl_lock);
361		delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
362		spin_unlock(&clp->cl_lock);
363		if (delegation != NULL) {
364			nfs_wb_all(inode);
365			err = __nfs_inode_return_delegation(inode, delegation, 1);
366		}
367	}
368	return err;
369}
370
371static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation)
372{
373	set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
374	set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
375}
376
377/*
378 * Return all delegations associated to a super block
379 */
380void nfs_super_return_all_delegations(struct super_block *sb)
381{
382	struct nfs_client *clp = NFS_SB(sb)->nfs_client;
383	struct nfs_delegation *delegation;
384
385	if (clp == NULL)
386		return;
387	rcu_read_lock();
388	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
389		spin_lock(&delegation->lock);
390		if (delegation->inode != NULL && delegation->inode->i_sb == sb)
391			set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
392		spin_unlock(&delegation->lock);
393	}
394	rcu_read_unlock();
395	if (nfs_client_return_marked_delegations(clp) != 0)
396		nfs4_schedule_state_manager(clp);
397}
398
399static
400void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags)
401{
402	struct nfs_delegation *delegation;
403
404	rcu_read_lock();
405	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
406		if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
407			continue;
408		if (delegation->type & flags)
409			nfs_mark_return_delegation(clp, delegation);
410	}
411	rcu_read_unlock();
412}
413
414static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
415{
416	nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
417}
418
419static void nfs_delegation_run_state_manager(struct nfs_client *clp)
420{
421	if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
422		nfs4_schedule_state_manager(clp);
423}
424
425void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
426{
427	nfs_client_mark_return_all_delegation_types(clp, flags);
428	nfs_delegation_run_state_manager(clp);
429}
430
431void nfs_expire_all_delegations(struct nfs_client *clp)
432{
433	nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
434}
435
436/*
437 * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
438 */
439void nfs_handle_cb_pathdown(struct nfs_client *clp)
440{
441	if (clp == NULL)
442		return;
443	nfs_client_mark_return_all_delegations(clp);
444}
445
446static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *clp)
447{
448	struct nfs_delegation *delegation;
449
450	rcu_read_lock();
451	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
452		if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
453			continue;
454		nfs_mark_return_delegation(clp, delegation);
455	}
456	rcu_read_unlock();
457}
458
459void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
460{
461	nfs_client_mark_return_unreferenced_delegations(clp);
462	nfs_delegation_run_state_manager(clp);
463}
464
465/*
466 * Asynchronous delegation recall!
467 */
468int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
469{
470	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
471	struct nfs_delegation *delegation;
472
473	rcu_read_lock();
474	delegation = rcu_dereference(NFS_I(inode)->delegation);
475
476	if (!clp->cl_mvops->validate_stateid(delegation, stateid)) {
477		rcu_read_unlock();
478		return -ENOENT;
479	}
480
481	nfs_mark_return_delegation(clp, delegation);
482	rcu_read_unlock();
483	nfs_delegation_run_state_manager(clp);
484	return 0;
485}
486
487/*
488 * Retrieve the inode associated with a delegation
489 */
490struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
491{
492	struct nfs_delegation *delegation;
493	struct inode *res = NULL;
494	rcu_read_lock();
495	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
496		spin_lock(&delegation->lock);
497		if (delegation->inode != NULL &&
498		    nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
499			res = igrab(delegation->inode);
500		}
501		spin_unlock(&delegation->lock);
502		if (res != NULL)
503			break;
504	}
505	rcu_read_unlock();
506	return res;
507}
508
509/*
510 * Mark all delegations as needing to be reclaimed
511 */
512void nfs_delegation_mark_reclaim(struct nfs_client *clp)
513{
514	struct nfs_delegation *delegation;
515	rcu_read_lock();
516	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
517		set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
518	rcu_read_unlock();
519}
520
521/*
522 * Reap all unclaimed delegations after reboot recovery is done
523 */
524void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
525{
526	struct nfs_delegation *delegation;
527	struct inode *inode;
528restart:
529	rcu_read_lock();
530	list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
531		if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0)
532			continue;
533		inode = nfs_delegation_grab_inode(delegation);
534		if (inode == NULL)
535			continue;
536		spin_lock(&clp->cl_lock);
537		delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp);
538		spin_unlock(&clp->cl_lock);
539		rcu_read_unlock();
540		if (delegation != NULL)
541			nfs_free_delegation(delegation);
542		iput(inode);
543		goto restart;
544	}
545	rcu_read_unlock();
546}
547
548int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
549{
550	struct nfs_inode *nfsi = NFS_I(inode);
551	struct nfs_delegation *delegation;
552	int ret = 0;
553
554	rcu_read_lock();
555	delegation = rcu_dereference(nfsi->delegation);
556	if (delegation != NULL) {
557		memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
558		ret = 1;
559	}
560	rcu_read_unlock();
561	return ret;
562}
563