nfs4state.c 188 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
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
/*
*  Copyright (c) 2001 The Regents of the University of Michigan.
*  All rights reserved.
*
*  Kendrick Smith <kmsmith@umich.edu>
*  Andy Adamson <kandros@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.
*
*/

35
#include <linux/file.h>
36
#include <linux/fs.h>
37
#include <linux/slab.h>
38
#include <linux/namei.h>
39
#include <linux/swap.h>
40
#include <linux/pagemap.h>
41
#include <linux/ratelimit.h>
42
#include <linux/sunrpc/svcauth_gss.h>
43
#include <linux/sunrpc/addr.h>
44
#include <linux/jhash.h>
45
#include "xdr4.h"
46
#include "xdr4cb.h"
47
#include "vfs.h"
48
#include "current_stateid.h"
Linus Torvalds's avatar
Linus Torvalds committed
49

50
#include "netns.h"
51
#include "pnfs.h"
52

Linus Torvalds's avatar
Linus Torvalds committed
53 54
#define NFSDDBG_FACILITY                NFSDDBG_PROC

55 56 57 58 59 60 61 62
#define all_ones {{~0,~0},~0}
static const stateid_t one_stateid = {
	.si_generation = ~0,
	.si_opaque = all_ones,
};
static const stateid_t zero_stateid = {
	/* all fields zero */
};
63 64 65
static const stateid_t currentstateid = {
	.si_generation = 1,
};
66 67 68
static const stateid_t close_stateid = {
	.si_generation = 0xffffffffU,
};
69

70
static u64 current_sessionid = 1;
71

72 73
#define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t)))
#define ONE_STATEID(stateid)  (!memcmp((stateid), &one_stateid, sizeof(stateid_t)))
74
#define CURRENT_STATEID(stateid) (!memcmp((stateid), &currentstateid, sizeof(stateid_t)))
75
#define CLOSE_STATEID(stateid)  (!memcmp((stateid), &close_stateid, sizeof(stateid_t)))
Linus Torvalds's avatar
Linus Torvalds committed
76 77

/* forward declarations */
78
static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner);
79
static void nfs4_free_ol_stateid(struct nfs4_stid *stid);
Linus Torvalds's avatar
Linus Torvalds committed
80

81 82 83 84 85 86 87
/* Locking: */

/*
 * Currently used for the del_recall_lru and file hash table.  In an
 * effort to decrease the scope of the client_mutex, this spinlock may
 * eventually cover more:
 */
88
static DEFINE_SPINLOCK(state_lock);
89

90 91 92 93 94
enum nfsd4_st_mutex_lock_subclass {
	OPEN_STATEID_MUTEX = 0,
	LOCK_STATEID_MUTEX = 1,
};

95 96 97 98 99 100
/*
 * A waitqueue for all in-progress 4.0 CLOSE operations that are waiting for
 * the refcount on the open stateid to drop.
 */
static DECLARE_WAIT_QUEUE_HEAD(close_wq);

101
static struct kmem_cache *client_slab;
102 103 104 105 106
static struct kmem_cache *openowner_slab;
static struct kmem_cache *lockowner_slab;
static struct kmem_cache *file_slab;
static struct kmem_cache *stateid_slab;
static struct kmem_cache *deleg_slab;
107
static struct kmem_cache *odstate_slab;
108

109
static void free_session(struct nfsd4_session *);
110

111
static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
112
static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops;
113

114
static bool is_session_dead(struct nfsd4_session *ses)
115
{
116
	return ses->se_flags & NFS4_SESSION_DEAD;
117 118
}

119
static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me)
120
{
121
	if (atomic_read(&ses->se_ref) > ref_held_by_me)
122 123 124
		return nfserr_jukebox;
	ses->se_flags |= NFS4_SESSION_DEAD;
	return nfs_ok;
125 126
}

127 128 129 130 131 132 133
static bool is_client_expired(struct nfs4_client *clp)
{
	return clp->cl_time == 0;
}

static __be32 get_client_locked(struct nfs4_client *clp)
{
134 135 136 137
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	lockdep_assert_held(&nn->client_lock);

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
	if (is_client_expired(clp))
		return nfserr_expired;
	atomic_inc(&clp->cl_refcount);
	return nfs_ok;
}

/* must be called under the client_lock */
static inline void
renew_client_locked(struct nfs4_client *clp)
{
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	if (is_client_expired(clp)) {
		WARN_ON(1);
		printk("%s: client (clientid %08x/%08x) already expired\n",
			__func__,
			clp->cl_clientid.cl_boot,
			clp->cl_clientid.cl_id);
		return;
	}

	dprintk("renewing client (clientid %08x/%08x)\n",
			clp->cl_clientid.cl_boot,
			clp->cl_clientid.cl_id);
	list_move_tail(&clp->cl_lru, &nn->client_lru);
	clp->cl_time = get_seconds();
}

166
static void put_client_renew_locked(struct nfs4_client *clp)
167
{
168 169 170 171
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	lockdep_assert_held(&nn->client_lock);

172 173 174 175 176 177
	if (!atomic_dec_and_test(&clp->cl_refcount))
		return;
	if (!is_client_expired(clp))
		renew_client_locked(clp);
}

178 179 180 181
static void put_client_renew(struct nfs4_client *clp)
{
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

182 183 184 185
	if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
		return;
	if (!is_client_expired(clp))
		renew_client_locked(clp);
186 187 188
	spin_unlock(&nn->client_lock);
}

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
static __be32 nfsd4_get_session_locked(struct nfsd4_session *ses)
{
	__be32 status;

	if (is_session_dead(ses))
		return nfserr_badsession;
	status = get_client_locked(ses->se_client);
	if (status)
		return status;
	atomic_inc(&ses->se_ref);
	return nfs_ok;
}

static void nfsd4_put_session_locked(struct nfsd4_session *ses)
{
	struct nfs4_client *clp = ses->se_client;
205 206 207
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	lockdep_assert_held(&nn->client_lock);
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

	if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses))
		free_session(ses);
	put_client_renew_locked(clp);
}

static void nfsd4_put_session(struct nfsd4_session *ses)
{
	struct nfs4_client *clp = ses->se_client;
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	spin_lock(&nn->client_lock);
	nfsd4_put_session_locked(ses);
	spin_unlock(&nn->client_lock);
}

224 225 226 227 228 229
static struct nfsd4_blocked_lock *
find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
			struct nfsd_net *nn)
{
	struct nfsd4_blocked_lock *cur, *found = NULL;

230
	spin_lock(&nn->blocked_locks_lock);
231 232 233
	list_for_each_entry(cur, &lo->lo_blocked, nbl_list) {
		if (fh_match(fh, &cur->nbl_fh)) {
			list_del_init(&cur->nbl_list);
234
			list_del_init(&cur->nbl_lru);
235 236 237 238
			found = cur;
			break;
		}
	}
239
	spin_unlock(&nn->blocked_locks_lock);
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
	if (found)
		posix_unblock_lock(&found->nbl_lock);
	return found;
}

static struct nfsd4_blocked_lock *
find_or_allocate_block(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
			struct nfsd_net *nn)
{
	struct nfsd4_blocked_lock *nbl;

	nbl = find_blocked_lock(lo, fh, nn);
	if (!nbl) {
		nbl= kmalloc(sizeof(*nbl), GFP_KERNEL);
		if (nbl) {
255 256
			INIT_LIST_HEAD(&nbl->nbl_list);
			INIT_LIST_HEAD(&nbl->nbl_lru);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
			fh_copy_shallow(&nbl->nbl_fh, fh);
			locks_init_lock(&nbl->nbl_lock);
			nfsd4_init_cb(&nbl->nbl_cb, lo->lo_owner.so_client,
					&nfsd4_cb_notify_lock_ops,
					NFSPROC4_CLNT_CB_NOTIFY_LOCK);
		}
	}
	return nbl;
}

static void
free_blocked_lock(struct nfsd4_blocked_lock *nbl)
{
	locks_release_private(&nbl->nbl_lock);
	kfree(nbl);
}

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
static void
remove_blocked_locks(struct nfs4_lockowner *lo)
{
	struct nfs4_client *clp = lo->lo_owner.so_client;
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
	struct nfsd4_blocked_lock *nbl;
	LIST_HEAD(reaplist);

	/* Dequeue all blocked locks */
	spin_lock(&nn->blocked_locks_lock);
	while (!list_empty(&lo->lo_blocked)) {
		nbl = list_first_entry(&lo->lo_blocked,
					struct nfsd4_blocked_lock,
					nbl_list);
		list_del_init(&nbl->nbl_list);
		list_move(&nbl->nbl_lru, &reaplist);
	}
	spin_unlock(&nn->blocked_locks_lock);

	/* Now free them */
	while (!list_empty(&reaplist)) {
		nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock,
					nbl_lru);
		list_del_init(&nbl->nbl_lru);
		posix_unblock_lock(&nbl->nbl_lock);
		free_blocked_lock(nbl);
	}
}

303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
static int
nfsd4_cb_notify_lock_done(struct nfsd4_callback *cb, struct rpc_task *task)
{
	/*
	 * Since this is just an optimization, we don't try very hard if it
	 * turns out not to succeed. We'll requeue it on NFS4ERR_DELAY, and
	 * just quit trying on anything else.
	 */
	switch (task->tk_status) {
	case -NFS4ERR_DELAY:
		rpc_delay(task, 1 * HZ);
		return 0;
	default:
		return 1;
	}
}

static void
nfsd4_cb_notify_lock_release(struct nfsd4_callback *cb)
{
	struct nfsd4_blocked_lock	*nbl = container_of(cb,
						struct nfsd4_blocked_lock, nbl_cb);

	free_blocked_lock(nbl);
}

static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = {
	.done		= nfsd4_cb_notify_lock_done,
	.release	= nfsd4_cb_notify_lock_release,
};

334 335 336 337 338 339 340
static inline struct nfs4_stateowner *
nfs4_get_stateowner(struct nfs4_stateowner *sop)
{
	atomic_inc(&sop->so_count);
	return sop;
}

341
static int
342
same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner)
343 344
{
	return (sop->so_owner.len == owner->len) &&
345
		0 == memcmp(sop->so_owner.data, owner->data, owner->len);
346 347 348 349
}

static struct nfs4_openowner *
find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open,
350
			struct nfs4_client *clp)
351 352 353
{
	struct nfs4_stateowner *so;

354
	lockdep_assert_held(&clp->cl_lock);
355

356 357
	list_for_each_entry(so, &clp->cl_ownerstr_hashtbl[hashval],
			    so_strhash) {
358 359
		if (!so->so_is_open_owner)
			continue;
360 361
		if (same_owner_str(so, &open->op_owner))
			return openowner(nfs4_get_stateowner(so));
362 363 364 365 366 367
	}
	return NULL;
}

static struct nfs4_openowner *
find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open,
368
			struct nfs4_client *clp)
369 370 371
{
	struct nfs4_openowner *oo;

372 373 374
	spin_lock(&clp->cl_lock);
	oo = find_openstateowner_str_locked(hashval, open, clp);
	spin_unlock(&clp->cl_lock);
375 376 377
	return oo;
}

Linus Torvalds's avatar
Linus Torvalds committed
378 379 380 381 382 383 384 385 386 387 388 389 390
static inline u32
opaque_hashval(const void *ptr, int nbytes)
{
	unsigned char *cptr = (unsigned char *) ptr;

	u32 x = 0;
	while (nbytes--) {
		x *= 37;
		x += *cptr++;
	}
	return x;
}

391
static void nfsd4_free_file_rcu(struct rcu_head *rcu)
392
{
393 394 395
	struct nfs4_file *fp = container_of(rcu, struct nfs4_file, fi_rcu);

	kmem_cache_free(file_slab, fp);
396 397
}

398
void
399 400
put_nfs4_file(struct nfs4_file *fi)
{
401 402
	might_lock(&state_lock);

403
	if (refcount_dec_and_lock(&fi->fi_ref, &state_lock)) {
404
		hlist_del_rcu(&fi->fi_hash);
405
		spin_unlock(&state_lock);
406
		WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate));
407 408
		WARN_ON_ONCE(!list_empty(&fi->fi_delegations));
		call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu);
409
	}
410 411
}

412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
static struct file *
__nfs4_get_fd(struct nfs4_file *f, int oflag)
{
	if (f->fi_fds[oflag])
		return get_file(f->fi_fds[oflag]);
	return NULL;
}

static struct file *
find_writeable_file_locked(struct nfs4_file *f)
{
	struct file *ret;

	lockdep_assert_held(&f->fi_lock);

	ret = __nfs4_get_fd(f, O_WRONLY);
	if (!ret)
		ret = __nfs4_get_fd(f, O_RDWR);
	return ret;
}

static struct file *
find_writeable_file(struct nfs4_file *f)
{
	struct file *ret;

	spin_lock(&f->fi_lock);
	ret = find_writeable_file_locked(f);
	spin_unlock(&f->fi_lock);

	return ret;
}

static struct file *find_readable_file_locked(struct nfs4_file *f)
{
	struct file *ret;

	lockdep_assert_held(&f->fi_lock);

	ret = __nfs4_get_fd(f, O_RDONLY);
	if (!ret)
		ret = __nfs4_get_fd(f, O_RDWR);
	return ret;
}

static struct file *
find_readable_file(struct nfs4_file *f)
{
	struct file *ret;

	spin_lock(&f->fi_lock);
	ret = find_readable_file_locked(f);
	spin_unlock(&f->fi_lock);

	return ret;
}

469
struct file *
470 471 472 473
find_any_file(struct nfs4_file *f)
{
	struct file *ret;

474 475
	if (!f)
		return NULL;
476 477 478 479 480 481 482 483 484 485 486
	spin_lock(&f->fi_lock);
	ret = __nfs4_get_fd(f, O_RDWR);
	if (!ret) {
		ret = __nfs4_get_fd(f, O_WRONLY);
		if (!ret)
			ret = __nfs4_get_fd(f, O_RDONLY);
	}
	spin_unlock(&f->fi_lock);
	return ret;
}

487
static atomic_long_t num_delegations;
488
unsigned long max_delegations;
489 490 491 492 493

/*
 * Open owner state (share locks)
 */

494 495 496 497
/* hash tables for lock and open owners */
#define OWNER_HASH_BITS              8
#define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
#define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
498

499
static unsigned int ownerstr_hashval(struct xdr_netobj *ownername)
500 501 502 503
{
	unsigned int ret;

	ret = opaque_hashval(ownername->data, ownername->len);
504
	return ret & OWNER_HASH_MASK;
505
}
506 507 508 509

/* hash table for nfs4_file */
#define FILE_HASH_BITS                   8
#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
510

511
static unsigned int nfsd_fh_hashval(struct knfsd_fh *fh)
512
{
513 514 515 516 517 518 519 520
	return jhash2(fh->fh_base.fh_pad, XDR_QUADLEN(fh->fh_size), 0);
}

static unsigned int file_hashval(struct knfsd_fh *fh)
{
	return nfsd_fh_hashval(fh) & (FILE_HASH_SIZE - 1);
}

521
static struct hlist_head file_hashtbl[FILE_HASH_SIZE];
522

523 524
static void
__nfs4_file_get_access(struct nfs4_file *fp, u32 access)
525
{
526 527
	lockdep_assert_held(&fp->fi_lock);

528 529 530 531
	if (access & NFS4_SHARE_ACCESS_WRITE)
		atomic_inc(&fp->fi_access[O_WRONLY]);
	if (access & NFS4_SHARE_ACCESS_READ)
		atomic_inc(&fp->fi_access[O_RDONLY]);
532 533
}

534 535
static __be32
nfs4_file_get_access(struct nfs4_file *fp, u32 access)
536
{
537 538
	lockdep_assert_held(&fp->fi_lock);

539 540 541 542
	/* Does this access mode make sense? */
	if (access & ~NFS4_SHARE_ACCESS_BOTH)
		return nfserr_inval;

543 544 545 546
	/* Does it conflict with a deny mode already set? */
	if ((access & fp->fi_share_deny) != 0)
		return nfserr_share_denied;

547 548
	__nfs4_file_get_access(fp, access);
	return nfs_ok;
549 550
}

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
static __be32 nfs4_file_check_deny(struct nfs4_file *fp, u32 deny)
{
	/* Common case is that there is no deny mode. */
	if (deny) {
		/* Does this deny mode make sense? */
		if (deny & ~NFS4_SHARE_DENY_BOTH)
			return nfserr_inval;

		if ((deny & NFS4_SHARE_DENY_READ) &&
		    atomic_read(&fp->fi_access[O_RDONLY]))
			return nfserr_share_denied;

		if ((deny & NFS4_SHARE_DENY_WRITE) &&
		    atomic_read(&fp->fi_access[O_WRONLY]))
			return nfserr_share_denied;
	}
	return nfs_ok;
}

570
static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
571
{
572 573 574 575 576 577
	might_lock(&fp->fi_lock);

	if (atomic_dec_and_lock(&fp->fi_access[oflag], &fp->fi_lock)) {
		struct file *f1 = NULL;
		struct file *f2 = NULL;

Jeff Layton's avatar
Jeff Layton committed
578
		swap(f1, fp->fi_fds[oflag]);
579
		if (atomic_read(&fp->fi_access[1 - oflag]) == 0)
Jeff Layton's avatar
Jeff Layton committed
580
			swap(f2, fp->fi_fds[O_RDWR]);
581 582 583 584 585
		spin_unlock(&fp->fi_lock);
		if (f1)
			fput(f1);
		if (f2)
			fput(f2);
586 587 588
	}
}

589
static void nfs4_file_put_access(struct nfs4_file *fp, u32 access)
590
{
591 592 593
	WARN_ON_ONCE(access & ~NFS4_SHARE_ACCESS_BOTH);

	if (access & NFS4_SHARE_ACCESS_WRITE)
594
		__nfs4_file_put_access(fp, O_WRONLY);
595 596
	if (access & NFS4_SHARE_ACCESS_READ)
		__nfs4_file_put_access(fp, O_RDONLY);
597 598
}

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
/*
 * Allocate a new open/delegation state counter. This is needed for
 * pNFS for proper return on close semantics.
 *
 * Note that we only allocate it for pNFS-enabled exports, otherwise
 * all pointers to struct nfs4_clnt_odstate are always NULL.
 */
static struct nfs4_clnt_odstate *
alloc_clnt_odstate(struct nfs4_client *clp)
{
	struct nfs4_clnt_odstate *co;

	co = kmem_cache_zalloc(odstate_slab, GFP_KERNEL);
	if (co) {
		co->co_client = clp;
614
		refcount_set(&co->co_odcount, 1);
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
	}
	return co;
}

static void
hash_clnt_odstate_locked(struct nfs4_clnt_odstate *co)
{
	struct nfs4_file *fp = co->co_file;

	lockdep_assert_held(&fp->fi_lock);
	list_add(&co->co_perfile, &fp->fi_clnt_odstate);
}

static inline void
get_clnt_odstate(struct nfs4_clnt_odstate *co)
{
	if (co)
632
		refcount_inc(&co->co_odcount);
633 634 635 636 637 638 639 640 641 642 643
}

static void
put_clnt_odstate(struct nfs4_clnt_odstate *co)
{
	struct nfs4_file *fp;

	if (!co)
		return;

	fp = co->co_file;
644
	if (refcount_dec_and_lock(&co->co_odcount, &fp->fi_lock)) {
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
		list_del(&co->co_perfile);
		spin_unlock(&fp->fi_lock);

		nfsd4_return_all_file_layouts(co->co_client, fp);
		kmem_cache_free(odstate_slab, co);
	}
}

static struct nfs4_clnt_odstate *
find_or_hash_clnt_odstate(struct nfs4_file *fp, struct nfs4_clnt_odstate *new)
{
	struct nfs4_clnt_odstate *co;
	struct nfs4_client *cl;

	if (!new)
		return NULL;

	cl = new->co_client;

	spin_lock(&fp->fi_lock);
	list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
		if (co->co_client == cl) {
			get_clnt_odstate(co);
			goto out;
		}
	}
	co = new;
	co->co_file = fp;
	hash_clnt_odstate_locked(new);
out:
	spin_unlock(&fp->fi_lock);
	return co;
}

679 680
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
				  void (*sc_free)(struct nfs4_stid *))
681
{
682
	struct nfs4_stid *stid;
683
	int new_id;
684

685
	stid = kmem_cache_zalloc(slab, GFP_KERNEL);
686 687 688
	if (!stid)
		return NULL;

689 690 691 692 693
	idr_preload(GFP_KERNEL);
	spin_lock(&cl->cl_lock);
	new_id = idr_alloc_cyclic(&cl->cl_stateids, stid, 0, 0, GFP_NOWAIT);
	spin_unlock(&cl->cl_lock);
	idr_preload_end();
Tejun Heo's avatar
Tejun Heo committed
694
	if (new_id < 0)
695
		goto out_free;
696 697

	stid->sc_free = sc_free;
698
	stid->sc_client = cl;
699 700
	stid->sc_stateid.si_opaque.so_id = new_id;
	stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
701
	/* Will be incremented before return to client: */
702
	refcount_set(&stid->sc_count, 1);
703
	spin_lock_init(&stid->sc_lock);
704 705

	/*
706 707 708 709 710 711 712
	 * It shouldn't be a problem to reuse an opaque stateid value.
	 * I don't think it is for 4.1.  But with 4.0 I worry that, for
	 * example, a stray write retransmission could be accepted by
	 * the server when it should have been rejected.  Therefore,
	 * adopt a trick from the sctp code to attempt to maximize the
	 * amount of time until an id is reused, by ensuring they always
	 * "increase" (mod INT_MAX):
713
	 */
714 715
	return stid;
out_free:
716
	kmem_cache_free(slab, stid);
717
	return NULL;
718 719
}

720
static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp)
721
{
722 723
	struct nfs4_stid *stid;

724
	stid = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_ol_stateid);
725 726 727
	if (!stid)
		return NULL;

728
	return openlockstateid(stid);
729 730 731 732 733 734
}

static void nfs4_free_deleg(struct nfs4_stid *stid)
{
	kmem_cache_free(deleg_slab, stid);
	atomic_long_dec(&num_delegations);
735 736
}

737 738 739 740 741 742 743 744 745 746 747 748 749 750
/*
 * When we recall a delegation, we should be careful not to hand it
 * out again straight away.
 * To ensure this we keep a pair of bloom filters ('new' and 'old')
 * in which the filehandles of recalled delegations are "stored".
 * If a filehandle appear in either filter, a delegation is blocked.
 * When a delegation is recalled, the filehandle is stored in the "new"
 * filter.
 * Every 30 seconds we swap the filters and clear the "new" one,
 * unless both are empty of course.
 *
 * Each filter is 256 bits.  We hash the filehandle to 32bit and use the
 * low 3 bytes as hash-table indices.
 *
751
 * 'blocked_delegations_lock', which is always taken in block_delegations(),
752 753 754
 * is used to manage concurrent access.  Testing does not need the lock
 * except when swapping the two filters.
 */
755
static DEFINE_SPINLOCK(blocked_delegations_lock);
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
static struct bloom_pair {
	int	entries, old_entries;
	time_t	swap_time;
	int	new; /* index into 'set' */
	DECLARE_BITMAP(set[2], 256);
} blocked_delegations;

static int delegation_blocked(struct knfsd_fh *fh)
{
	u32 hash;
	struct bloom_pair *bd = &blocked_delegations;

	if (bd->entries == 0)
		return 0;
	if (seconds_since_boot() - bd->swap_time > 30) {
771
		spin_lock(&blocked_delegations_lock);
772 773 774 775 776 777 778 779
		if (seconds_since_boot() - bd->swap_time > 30) {
			bd->entries -= bd->old_entries;
			bd->old_entries = bd->entries;
			memset(bd->set[bd->new], 0,
			       sizeof(bd->set[0]));
			bd->new = 1-bd->new;
			bd->swap_time = seconds_since_boot();
		}
780
		spin_unlock(&blocked_delegations_lock);
781
	}
782
	hash = jhash(&fh->fh_base, fh->fh_size, 0);
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
	if (test_bit(hash&255, bd->set[0]) &&
	    test_bit((hash>>8)&255, bd->set[0]) &&
	    test_bit((hash>>16)&255, bd->set[0]))
		return 1;

	if (test_bit(hash&255, bd->set[1]) &&
	    test_bit((hash>>8)&255, bd->set[1]) &&
	    test_bit((hash>>16)&255, bd->set[1]))
		return 1;

	return 0;
}

static void block_delegations(struct knfsd_fh *fh)
{
	u32 hash;
	struct bloom_pair *bd = &blocked_delegations;

801
	hash = jhash(&fh->fh_base, fh->fh_size, 0);
802

803
	spin_lock(&blocked_delegations_lock);
804 805 806 807 808 809
	__set_bit(hash&255, bd->set[bd->new]);
	__set_bit((hash>>8)&255, bd->set[bd->new]);
	__set_bit((hash>>16)&255, bd->set[bd->new]);
	if (bd->entries == 0)
		bd->swap_time = seconds_since_boot();
	bd->entries += 1;
810
	spin_unlock(&blocked_delegations_lock);
811 812
}

Linus Torvalds's avatar
Linus Torvalds committed
813
static struct nfs4_delegation *
814 815
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp,
		 struct svc_fh *current_fh,
816
		 struct nfs4_clnt_odstate *odstate)
Linus Torvalds's avatar
Linus Torvalds committed
817 818
{
	struct nfs4_delegation *dp;
819
	long n;
Linus Torvalds's avatar
Linus Torvalds committed
820 821

	dprintk("NFSD alloc_init_deleg\n");
822 823 824
	n = atomic_long_inc_return(&num_delegations);
	if (n < 0 || n > max_delegations)
		goto out_dec;
825
	if (delegation_blocked(&current_fh->fh_handle))
826
		goto out_dec;
827
	dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab, nfs4_free_deleg));
828
	if (dp == NULL)
829
		goto out_dec;
830

831 832
	/*
	 * delegation seqid's are never incremented.  The 4.1 special
833 834
	 * meaning of seqid 0 isn't meaningful, really, but let's avoid
	 * 0 anyway just for consistency and use 1:
835 836
	 */
	dp->dl_stid.sc_stateid.si_generation = 1;
837 838
	INIT_LIST_HEAD(&dp->dl_perfile);
	INIT_LIST_HEAD(&dp->dl_perclnt);
Linus Torvalds's avatar
Linus Torvalds committed
839
	INIT_LIST_HEAD(&dp->dl_recall_lru);
840 841
	dp->dl_clnt_odstate = odstate;
	get_clnt_odstate(odstate);
842
	dp->dl_type = NFS4_OPEN_DELEGATE_READ;
843 844
	dp->dl_retries = 1;
	nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client,
845
		      &nfsd4_cb_recall_ops, NFSPROC4_CLNT_CB_RECALL);
846 847
	get_nfs4_file(fp);
	dp->dl_stid.sc_file = fp;
Linus Torvalds's avatar
Linus Torvalds committed
848
	return dp;
849 850 851
out_dec:
	atomic_long_dec(&num_delegations);
	return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
852 853 854
}

void
855
nfs4_put_stid(struct nfs4_stid *s)
Linus Torvalds's avatar
Linus Torvalds committed
856
{
857
	struct nfs4_file *fp = s->sc_file;
858 859
	struct nfs4_client *clp = s->sc_client;

860 861
	might_lock(&clp->cl_lock);

862
	if (!refcount_dec_and_lock(&s->sc_count, &clp->cl_lock)) {
863
		wake_up_all(&close_wq);
864
		return;
865
	}
866
	idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id);
867
	spin_unlock(&clp->cl_lock);
868
	s->sc_free(s);
869 870
	if (fp)
		put_nfs4_file(fp);
Linus Torvalds's avatar
Linus Torvalds committed
871 872
}

873 874 875 876 877 878 879 880 881 882 883 884
void
nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid)
{
	stateid_t *src = &stid->sc_stateid;

	spin_lock(&stid->sc_lock);
	if (unlikely(++src->si_generation == 0))
		src->si_generation = 1;
	memcpy(dst, src, sizeof(*dst));
	spin_unlock(&stid->sc_lock);
}

885
static void put_deleg_file(struct nfs4_file *fp)
Linus Torvalds's avatar
Linus Torvalds committed
886
{
887
	struct file *filp = NULL;
888

889
	spin_lock(&fp->fi_lock);
890
	if (--fp->fi_delegees == 0)
891 892 893
		swap(filp, fp->fi_deleg_file);
	spin_unlock(&fp->fi_lock);

894
	if (filp)
895
		fput(filp);
896 897 898 899 900 901 902 903 904 905 906
}

static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
{
	struct nfs4_file *fp = dp->dl_stid.sc_file;
	struct file *filp = fp->fi_deleg_file;

	WARN_ON_ONCE(!fp->fi_delegees);

	vfs_setlease(filp, F_UNLCK, NULL, (void **)&dp);
	put_deleg_file(fp);
Linus Torvalds's avatar
Linus Torvalds committed
907 908
}

909 910 911
static void destroy_unhashed_deleg(struct nfs4_delegation *dp)
{
	put_clnt_odstate(dp->dl_clnt_odstate);
912
	nfs4_unlock_deleg_lease(dp);
913 914 915
	nfs4_put_stid(&dp->dl_stid);
}

916
void nfs4_unhash_stid(struct nfs4_stid *s)
917
{
918
	s->sc_type = 0;
919 920
}

921
/**
922
 * nfs4_delegation_exists - Discover if this delegation already exists
923 924 925 926
 * @clp:     a pointer to the nfs4_client we're granting a delegation to
 * @fp:      a pointer to the nfs4_file we're granting a delegation on
 *
 * Return:
927
 *      On success: true iff an existing delegation is found
928 929
 */

930 931
static bool
nfs4_delegation_exists(struct nfs4_client *clp, struct nfs4_file *fp)
932 933 934 935 936 937 938 939 940 941
{
	struct nfs4_delegation *searchdp = NULL;
	struct nfs4_client *searchclp = NULL;

	lockdep_assert_held(&state_lock);
	lockdep_assert_held(&fp->fi_lock);

	list_for_each_entry(searchdp, &fp->fi_delegations, dl_perfile) {
		searchclp = searchdp->dl_stid.sc_client;
		if (clp == searchclp) {
942
			return true;
943 944
		}
	}
945
	return false;
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
}

/**
 * hash_delegation_locked - Add a delegation to the appropriate lists
 * @dp:     a pointer to the nfs4_delegation we are adding.
 * @fp:     a pointer to the nfs4_file we're granting a delegation on
 *
 * Return:
 *      On success: NULL if the delegation was successfully hashed.
 *
 *      On error: -EAGAIN if one was previously granted to this
 *                 nfs4_client for this nfs4_file. Delegation is not hashed.
 *
 */

static int
962 963
hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)
{
964 965
	struct nfs4_client *clp = dp->dl_stid.sc_client;

966
	lockdep_assert_held(&state_lock);
967
	lockdep_assert_held(&fp->fi_lock);
968

969 970
	if (nfs4_delegation_exists(clp, fp))
		return -EAGAIN;
971
	refcount_inc(&dp->dl_stid.sc_count);
972
	dp->dl_stid.sc_type = NFS4_DELEG_STID;
973
	list_add(&dp->dl_perfile, &fp->fi_delegations);
974 975
	list_add(&dp->dl_perclnt, &clp->cl_delegations);
	return 0;
976 977
}

978
static bool
979
unhash_delegation_locked(struct nfs4_delegation *dp)
Linus Torvalds's avatar
Linus Torvalds committed
980
{
981
	struct nfs4_file *fp = dp->dl_stid.sc_file;
982

983 984
	lockdep_assert_held(&state_lock);

985 986 987
	if (list_empty(&dp->dl_perfile))
		return false;

988
	dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID;
989 990
	/* Ensure that deleg break won't try to requeue it */
	++dp->dl_time;
991
	spin_lock(&fp->fi_lock);
992
	list_del_init(&dp->dl_perclnt);
Linus Torvalds's avatar
Linus Torvalds committed
993
	list_del_init(&dp->dl_recall_lru);
994 995
	list_del_init(&dp->dl_perfile);
	spin_unlock(&fp->fi_lock);
996
	return true;
997 998 999 1000
}

static void destroy_delegation(struct nfs4_delegation *dp)
{
1001 1002
	bool unhashed;

1003
	spin_lock(&state_lock);
1004
	unhashed = unhash_delegation_locked(dp);
1005
	spin_unlock(&state_lock);
1006 1007
	if (unhashed)
		destroy_unhashed_deleg(dp);
1008 1009 1010 1011 1012 1013
}

static void revoke_delegation(struct nfs4_delegation *dp)
{
	struct nfs4_client *clp = dp->dl_stid.sc_client;

1014 1015
	WARN_ON(!list_empty(&dp->dl_recall_lru));

1016
	if (clp->cl_minorversion) {
1017
		dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID;
1018
		refcount_inc(&dp->dl_stid.sc_count);
1019 1020 1021
		spin_lock(&clp->cl_lock);
		list_add(&dp->dl_recall_lru, &clp->cl_revoked);
		spin_unlock(&clp->cl_lock);
1022
	}
1023
	destroy_unhashed_deleg(dp);
1024 1025
}

Linus Torvalds's avatar
Linus Torvalds committed
1026 1027 1028 1029
/* 
 * SETCLIENTID state 
 */

1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
static unsigned int clientid_hashval(u32 id)
{
	return id & CLIENT_HASH_MASK;
}

static unsigned int clientstr_hashval(const char *name)
{
	return opaque_hashval(name, 8) & CLIENT_HASH_MASK;
}

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
/*
 * We store the NONE, READ, WRITE, and BOTH bits separately in the
 * st_{access,deny}_bmap field of the stateid, in order to track not
 * only what share bits are currently in force, but also what
 * combinations of share bits previous opens have used.  This allows us
 * to enforce the recommendation of rfc 3530 14.2.19 that the server
 * return an error if the client attempt to downgrade to a combination
 * of share bits not explicable by closing some of its previous opens.
 *
 * XXX: This enforcement is actually incomplete, since we don't keep
 * track of access/deny bit combinations; so, e.g., we allow:
 *
 *	OPEN allow read, deny write
 *	OPEN allow both, deny none
 *	DOWNGRADE allow read, deny none
 *
 * which we should reject.
 */
1058 1059
static unsigned int
bmap_to_share_mode(unsigned long bmap) {
1060
	int i;
1061
	unsigned int access = 0;
1062 1063 1064

	for (i = 1; i < 4; i++) {
		if (test_bit(i, &bmap))
1065
			access |= i;
1066
	}
1067
	return access;
1068 1069
}

1070 1071 1072 1073
/* set share access for a given stateid */
static inline void
set_access(u32 access, struct nfs4_ol_stateid *stp)
{
1074 1075 1076 1077
	unsigned char mask = 1 << access;

	WARN_ON_ONCE(access > NFS4_SHARE_ACCESS_BOTH);
	stp->st_access_bmap |= mask;
1078 1079 1080 1081 1082 1083
}

/* clear share access for a given stateid */
static inline void
clear_access(u32 access, struct nfs4_ol_stateid *stp)
{
1084 1085 1086 1087
	unsigned char mask = 1 << access;

	WARN_ON_ONCE(access > NFS4_SHARE_ACCESS_BOTH);
	stp->st_access_bmap &= ~mask;
1088 1089 1090 1091 1092 1093
}

/* test whether a given stateid has access */
static inline bool
test_access(u32 access, struct nfs4_ol_stateid *stp)
{
1094 1095 1096
	unsigned char mask = 1 << access;

	return (bool)(stp->st_access_bmap & mask);
1097 1098
}

1099 1100
/* set share deny for a given stateid */
static inline void
1101
set_deny(u32 deny, struct nfs4_ol_stateid *stp)
1102
{
1103 1104 1105 1106
	unsigned char mask = 1 << deny;

	WARN_ON_ONCE(deny > NFS4_SHARE_DENY_BOTH);
	stp->st_deny_bmap |= mask;
1107 1108 1109 1110
}

/* clear share deny for a given stateid */
static inline void
1111
clear_deny(u32 deny, struct nfs4_ol_stateid *stp)
1112
{
1113 1114 1115 1116
	unsigned char mask = 1 << deny;

	WARN_ON_ONCE(deny > NFS4_SHARE_DENY_BOTH);
	stp->st_deny_bmap &= ~mask;
1117 1118 1119 1120
}

/* test whether a given stateid is denying specific access */
static inline bool
1121
test_deny(u32 deny, struct nfs4_ol_stateid *stp)
1122
{
1123 1124 1125
	unsigned char mask = 1 << deny;

	return (bool)(stp->st_deny_bmap & mask);
1126 1127 1128 1129
}

static int nfs4_access_to_omode(u32 access)
{
1130
	switch (access & NFS4_SHARE_ACCESS_BOTH) {
1131 1132 1133 1134 1135 1136 1137
	case NFS4_SHARE_ACCESS_READ:
		return O_RDONLY;
	case NFS4_SHARE_ACCESS_WRITE:
		return O_WRONLY;
	case NFS4_SHARE_ACCESS_BOTH:
		return O_RDWR;
	}
1138 1139
	WARN_ON_ONCE(1);
	return O_RDONLY;
1140 1141
}

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
/*
 * A stateid that had a deny mode associated with it is being released
 * or downgraded. Recalculate the deny mode on the file.
 */
static void
recalculate_deny_mode(struct nfs4_file *fp)
{
	struct nfs4_ol_stateid *stp;

	spin_lock(&fp->fi_lock);
	fp->fi_share_deny = 0;
	list_for_each_entry(stp, &fp->fi_stateids, st_perfile)
		fp->fi_share_deny |= bmap_to_share_mode(stp->st_deny_bmap);
	spin_unlock(&fp->fi_lock);
}

static void
reset_union_bmap_deny(u32 deny, struct nfs4_ol_stateid *stp)
{
	int i;
	bool change = false;

	for (i = 1; i < 4; i++) {
		if ((i & deny) != i) {
			change = true;
			clear_deny(i, stp);
		}
	}

	/* Recalculate per-file deny mode if there was a change */
	if (change)
1173
		recalculate_deny_mode(stp->st_stid.sc_file);
1174 1175
}

1176 1177 1178 1179 1180
/* release all access and file references for a given stateid */
static void
release_all_access(struct nfs4_ol_stateid *stp)
{
	int i;
1181
	struct nfs4_file *fp = stp->st_stid.sc_file;
1182 1183 1184

	if (fp && stp->st_deny_bmap != 0)
		recalculate_deny_mode(fp);
1185 1186 1187

	for (i = 1; i < 4; i++) {
		if (test_access(i, stp))
1188
			nfs4_file_put_access(stp->st_stid.sc_file, i);
1189 1190 1191 1192
		clear_access(i, stp);
	}
}

1193 1194 1195 1196 1197 1198
static inline void nfs4_free_stateowner(struct nfs4_stateowner *sop)
{
	kfree(sop->so_owner.data);
	sop->so_ops->so_free(sop);
}

1199 1200
static void nfs4_put_stateowner(struct nfs4_stateowner *sop)
{
1201 1202 1203 1204 1205
	struct nfs4_client *clp = sop->so_client;

	might_lock(&clp->cl_lock);

	if (!atomic_dec_and_lock(&sop->so_count, &clp->cl_lock))
1206
		return;
1207
	sop->so_ops->so_unhash(sop);
1208
	spin_unlock(&clp->cl_lock);
1209
	nfs4_free_stateowner(sop);
1210 1211
}

1212 1213 1214 1215 1216 1217
static bool
nfs4_ol_stateid_unhashed(const struct nfs4_ol_stateid *stp)
{
	return list_empty(&stp->st_perfile);
}

1218
static bool unhash_ol_stateid(struct nfs4_ol_stateid *stp)
1219
{
1220
	struct nfs4_file *fp = stp->st_stid.sc_file;
1221

1222 1223
	lockdep_assert_held(&stp->st_stateowner->so_client->cl_lock);

1224 1225 1226
	if (list_empty(&stp->st_perfile))
		return false;

1227
	spin_lock(&fp->fi_lock);
1228
	list_del_init(&stp->st_perfile);
1229
	spin_unlock(&fp->fi_lock);
1230
	list_del(&stp->st_perstateowner);
1231
	return true;
1232 1233
}

1234
static void nfs4_free_ol_stateid(struct nfs4_stid *stid)
1235
{
1236
	struct nfs4_ol_stateid *stp = openlockstateid(stid);
1237

1238
	put_clnt_odstate(stp->st_clnt_odstate);
1239
	release_all_access(stp);
1240 1241
	if (stp->st_stateowner)
		nfs4_put_stateowner(stp->st_stateowner);
1242
	kmem_cache_free(stateid_slab, stid);
1243 1244
}

1245
static void nfs4_free_lock_stateid(struct nfs4_stid *stid)
1246
{
1247 1248
	struct nfs4_ol_stateid *stp = openlockstateid(stid);
	struct nfs4_lockowner *lo = lockowner(stp->st_stateowner);
1249 1250
	struct file *file;

1251 1252 1253 1254 1255 1256
	file = find_any_file(stp->st_stid.sc_file);
	if (file)
		filp_close(file, (fl_owner_t)lo);
	nfs4_free_ol_stateid(stid);
}

1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
/*
 * Put the persistent reference to an already unhashed generic stateid, while
 * holding the cl_lock. If it's the last reference, then put it onto the
 * reaplist for later destruction.
 */
static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp,
				       struct list_head *reaplist)
{
	struct nfs4_stid *s = &stp->st_stid;
	struct nfs4_client *clp = s->sc_client;

	lockdep_assert_held(&clp->cl_lock);

	WARN_ON_ONCE(!list_empty(&stp->st_locks));

1272
	if (!refcount_dec_and_test(&s->sc_count)) {
1273 1274 1275 1276 1277 1278 1279 1280
		wake_up_all(&close_wq);
		return;
	}

	idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id);
	list_add(&stp->st_locks, reaplist);
}

1281
static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp)
1282
{
1283
	lockdep_assert_held(&stp->st_stid.sc_client->cl_lock);
1284

1285 1286
	if (!unhash_ol_stateid(stp))
		return false;
1287
	list_del_init(&stp->st_locks);
1288
	nfs4_unhash_stid(&stp->st_stid);
1289
	return true;
1290 1291 1292 1293
}

static void release_lock_stateid(struct nfs4_ol_stateid *stp)
{
1294
	struct nfs4_client *clp = stp->st_stid.sc_client;
1295
	bool unhashed;
1296

1297
	spin_lock(&clp->cl_lock);
1298
	unhashed = unhash_lock_stateid(stp);
1299
	spin_unlock(&clp->cl_lock);
1300 1301
	if (unhashed)
		nfs4_put_stid(&stp->st_stid);
1302 1303
}

1304
static void unhash_lockowner_locked(struct nfs4_lockowner *lo)
1305
{
1306
	struct nfs4_client *clp = lo->lo_owner.so_client;
1307

1308
	lockdep_assert_held(&clp->cl_lock);
1309

1310 1311 1312
	list_del_init(&lo->lo_owner.so_strhash);
}

1313 1314 1315 1316 1317 1318 1319 1320
/*
 * Free a list of generic stateids that were collected earlier after being
 * fully unhashed.
 */
static void
free_ol_stateid_reaplist(struct list_head *reaplist)
{
	struct nfs4_ol_stateid *stp;
1321
	struct nfs4_file *fp;
1322 1323 1324 1325 1326 1327 1328

	might_sleep();

	while (!list_empty(reaplist)) {
		stp = list_first_entry(reaplist, struct nfs4_ol_stateid,
				       st_locks);
		list_del(&stp->st_locks);
1329
		fp = stp->st_stid.sc_file;
1330
		stp->st_stid.sc_free(&stp->st_stid);
1331 1332
		if (fp)
			put_nfs4_file(fp);
1333 1334 1335
	}
}

1336 1337
static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp,
				       struct list_head *reaplist)
1338 1339 1340
{
	struct nfs4_ol_stateid *stp;

1341 1342
	lockdep_assert_held(&open_stp->st_stid.sc_client->cl_lock);

1343 1344 1345
	while (!list_empty(&open_stp->st_locks)) {
		stp = list_entry(open_stp->st_locks.next,
				struct nfs4_ol_stateid, st_locks);
1346
		WARN_ON(!unhash_lock_stateid(stp));
1347
		put_ol_stateid_locked(stp, reaplist);
1348 1349 1350
	}
}

1351
static bool unhash_open_stateid(struct nfs4_ol_stateid *stp,
1352
				struct list_head *reaplist)
1353
{
1354 1355
	lockdep_assert_held(&stp->st_stid.sc_client->cl_lock);

1356 1357
	if (!unhash_ol_stateid(stp))
		return false;
1358
	release_open_stateid_locks(stp, reaplist);
1359
	return true;
1360 1361 1362 1363
}

static void release_open_stateid(struct nfs4_ol_stateid *stp)
{
1364 1365 1366
	LIST_HEAD(reaplist);

	spin_lock(&stp->st_stid.sc_client->cl_lock);
1367 1368
	if (unhash_open_stateid(stp, &reaplist))
		put_ol_stateid_locked(stp, &reaplist);
1369 1370
	spin_unlock(&stp->st_stid.sc_client->cl_lock);
	free_ol_stateid_reaplist(&reaplist);
1371 1372
}

1373
static void unhash_openowner_locked(struct nfs4_openowner *oo)
1374
{
1375
	struct nfs4_client *clp = oo->oo_owner.so_client;
1376

1377
	lockdep_assert_held(&clp->cl_lock);
1378

1379 1380
	list_del_init(&oo->oo_owner.so_strhash);
	list_del_init(&oo->oo_perclient);
1381 1382
}

1383 1384
static void release_last_closed_stateid(struct nfs4_openowner *oo)
{
1385 1386 1387
	struct nfsd_net *nn = net_generic(oo->oo_owner.so_client->net,
					  nfsd_net_id);
	struct nfs4_ol_stateid *s;
1388

1389 1390
	spin_lock(&nn->client_lock);
	s = oo->oo_last_closed_stid;
1391
	if (s) {
1392
		list_del_init(&oo->oo_close_lru);
1393 1394
		oo->oo_last_closed_stid = NULL;
	}
1395 1396 1397
	spin_unlock(&nn->client_lock);
	if (s)
		nfs4_put_stid(&s->st_stid);
1398 1399
}

1400
static void release_openowner(struct nfs4_openowner *oo)
1401 1402
{
	struct nfs4_ol_stateid *stp;
1403
	struct nfs4_client *clp = oo->oo_owner.so_client;
1404
	struct list_head reaplist;
1405

1406
	INIT_LIST_HEAD(&reaplist);
1407

1408 1409
	spin_lock(&clp->cl_lock);
	unhash_openowner_locked(oo);
1410 1411 1412
	while (!list_empty(&oo->oo_owner.so_stateids)) {
		stp = list_first_entry(&oo->oo_owner.so_stateids,
				struct nfs4_ol_stateid, st_perstateowner);
1413 1414
		if (unhash_open_stateid(stp, &reaplist))
			put_ol_stateid_locked(stp, &reaplist);
1415
	}
1416
	spin_unlock(&clp->cl_lock);
1417
	free_ol_stateid_reaplist(&reaplist);
1418
	release_last_closed_stateid(oo);
1419
	nfs4_put_stateowner(&oo->oo_owner);
1420 1421
}

Marc Eshel's avatar
Marc Eshel committed
1422 1423 1424 1425 1426 1427 1428 1429
static inline int
hash_sessionid(struct nfs4_sessionid *sessionid)
{
	struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)sessionid;

	return sid->sequence % SESSION_HASH_SIZE;
}

Mark Salter's avatar
Mark Salter committed
1430
#ifdef CONFIG_SUNRPC_DEBUG
Marc Eshel's avatar
Marc Eshel committed
1431 1432 1433 1434 1435 1436
static inline void
dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
{
	u32 *ptr = (u32 *)(&sessionid->data[0]);
	dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]);
}
1437 1438 1439 1440 1441 1442 1443
#else
static inline void
dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
{
}
#endif

1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
/*
 * Bump the seqid on cstate->replay_owner, and clear replay_owner if it
 * won't be used for replay.
 */
void nfsd4_bump_seqid(struct nfsd4_compound_state *cstate, __be32 nfserr)
{
	struct nfs4_stateowner *so = cstate->replay_owner;

	if (nfserr == nfserr_replay_me)
		return;

	if (!seqid_mutating_err(ntohl(nfserr))) {
1456
		nfsd4_cstate_clear_replay(cstate);
1457 1458 1459 1460 1461 1462 1463 1464 1465
		return;
	}
	if (!so)
		return;
	if (so->so_is_open_owner)
		release_last_closed_stateid(openowner(so));
	so->so_seqid++;
	return;
}
Marc Eshel's avatar
Marc Eshel committed
1466

1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479
static void
gen_sessionid(struct nfsd4_session *ses)
{
	struct nfs4_client *clp = ses->se_client;
	struct nfsd4_sessionid *sid;

	sid = (struct nfsd4_sessionid *)ses->se_sessionid.data;
	sid->clientid = clp->cl_clientid;
	sid->sequence = current_sessionid++;
	sid->reserved = 0;
}

/*
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492
 * The protocol defines ca_maxresponssize_cached to include the size of
 * the rpc header, but all we need to cache is the data starting after
 * the end of the initial SEQUENCE operation--the rest we regenerate
 * each time.  Therefore we can advertise a ca_maxresponssize_cached
 * value that is the number of bytes in our cache plus a few additional
 * bytes.  In order to stay on the safe side, and not promise more than
 * we can cache, those additional bytes must be the minimum possible: 24
 * bytes of rpc header (xid through accept state, with AUTH_NULL
 * verifier), 12 for the compound header (with zero-length tag), and 44
 * for the SEQUENCE op response:
 */
#define NFSD_MIN_HDR_SEQ_SZ  (24 + 12 + 44)

1493 1494 1495 1496 1497
static void
free_session_slots(struct nfsd4_session *ses)
{
	int i;

1498 1499
	for (i = 0; i < ses->se_fchannel.maxreqs; i++) {
		free_svc_cred(&ses->se_slots[i]->sl_cred);
1500
		kfree(ses->se_slots[i]);
1501
	}
1502 1503
}

1504
/*
1505 1506 1507
 * We don't actually need to cache the rpc and session headers, so we
 * can allocate a little less for each slot:
 */
1508
static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca)
1509
{
1510
	u32 size;
1511

1512 1513 1514 1515 1516
	if (ca->maxresp_cached < NFSD_MIN_HDR_SEQ_SZ)
		size = 0;
	else
		size = ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
	return size + sizeof(struct nfsd4_slot);
1517
}
1518

1519 1520
/*
 * XXX: If we run out of reserved DRC memory we could (up to a point)
1521
 * re-negotiate active sessions and reduce their slot usage to make
1522
 * room for new connections. For now we just fail the create session.
1523
 */
1524
static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
1525
{
1526 1527
	u32 slotsize = slot_bytes(ca);
	u32 num = ca->maxreqs;
1528
	unsigned long avail, total_avail;
1529

1530
	spin_lock(&nfsd_drc_lock);
1531 1532
	total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used;
	avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail);
1533 1534 1535 1536
	/*
	 * Never use more than a third of the remaining memory,
	 * unless it's the only way to give this client a slot:
	 */
1537
	avail = clamp_t(unsigned long, avail, slotsize, total_avail/3);
1538 1539 1540
	num = min_t(int, num, avail / slotsize);
	nfsd_drc_mem_used += num * slotsize;
	spin_unlock(&nfsd_drc_lock);
1541

1542 1543
	return num;
}
1544

1545
static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca)
1546
{
1547 1548
	int slotsize = slot_bytes(ca);

1549
	spin_lock(&nfsd_drc_lock);
1550
	nfsd_drc_mem_used -= slotsize * ca->maxreqs;
1551
	spin_unlock(&nfsd_drc_lock);
1552
}
1553

1554 1555
static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs,
					   struct nfsd4_channel_attrs *battrs)
1556
{
1557 1558
	int numslots = fattrs->maxreqs;
	int slotsize = slot_bytes(fattrs);
1559 1560
	struct nfsd4_session *new;
	int mem, i;
1561

1562 1563 1564
	BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
			+ sizeof(struct nfsd4_session) > PAGE_SIZE);
	mem = numslots * sizeof(struct nfsd4_slot *);
1565

1566 1567 1568
	new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
	if (!new)
		return NULL;
1569
	/* allocate each struct nfsd4_slot and data cache in one piece */
1570
	for (i = 0; i < numslots; i++) {
1571
		new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL);
1572
		if (!new->se_slots[i])
1573 1574
			goto out_free;
	}
1575 1576 1577 1578

	memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs));
	memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs));

1579 1580 1581 1582 1583 1584
	return new;
out_free:
	while (i--)
		kfree(new->se_slots[i]);
	kfree(new);
	return NULL;
1585 1586
}

1587 1588 1589 1590 1591
static void free_conn(struct nfsd4_conn *c)
{
	svc_xprt_put(c->cn_xprt);
	kfree(c);
}
1592

1593 1594 1595 1596
static void nfsd4_conn_lost(struct svc_xpt_user *u)
{
	struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user);
	struct nfs4_client *clp = c->cn_session->se_client;
1597

1598 1599 1600 1601 1602
	spin_lock(&clp->cl_lock);
	if (!list_empty(&c->cn_persession)) {
		list_del(&c->cn_persession);
		free_conn(c);
	}
1603
	nfsd4_probe_callback(clp);
1604
	spin_unlock(&clp->cl_lock);
1605
}
1606

1607
static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
1608 1609
{
	struct nfsd4_conn *conn;
1610

1611 1612
	conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL);
	if (!conn)
1613
		return NULL;
1614 1615
	svc_xprt_get(rqstp->rq_xprt);
	conn->cn_xprt = rqstp->rq_xprt;
1616
	conn->cn_flags = flags;
1617 1618 1619
	INIT_LIST_HEAD(&conn->cn_xpt_user.list);
	return conn;
}
1620

1621 1622 1623 1624
static void __nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
{
	conn->cn_session = ses;
	list_add(&conn->cn_persession, &ses->se_conns);
1625 1626
}

1627
static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
1628
{
1629
	struct nfs4_client *clp = ses->se_client;
1630

1631
	spin_lock(&clp->cl_lock);
1632
	__nfsd4_hash_conn(conn, ses);
1633
	spin_unlock(&clp->cl_lock);
1634 1635
}

1636
static int nfsd4_register_conn(struct nfsd4_conn *conn)
1637
{
1638
	conn->cn_xpt_user.callback = nfsd4_conn_lost;
1639
	return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
1640 1641
}

1642
static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses)
1643
{
1644
	int ret;
1645

1646
	nfsd4_hash_conn(conn, ses);
1647 1648 1649 1650
	ret = nfsd4_register_conn(conn);
	if (ret)
		/* oops; xprt is already down: */
		nfsd4_conn_lost(&conn->cn_xpt_user);
1651 1652
	/* We may have gained or lost a callback channel: */
	nfsd4_probe_callback_sync(ses->se_client);
1653
}
1654

1655
static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses)
1656 1657 1658
{
	u32 dir = NFS4_CDFC4_FORE;

1659
	if (cses->flags & SESSION4_BACK_CHAN)
1660
		dir |= NFS4_CDFC4_BACK;
1661
	return alloc_conn(rqstp, dir);
1662 1663 1664
}

/* must be called under client_lock */
1665
static void nfsd4_del_conns(struct nfsd4_session *s)
1666
{
1667 1668
	struct nfs4_client *clp = s->se_client;
	struct nfsd4_conn *c;
1669

1670 1671 1672 1673 1674
	spin_lock(&clp->cl_lock);
	while (!list_empty(&s->se_conns)) {
		c = list_first_entry(&s->se_conns, struct nfsd4_conn, cn_persession);
		list_del_init(&c->cn_persession);
		spin_unlock(&clp->cl_lock);
1675

1676 1677
		unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user);
		free_conn(c);
1678

1679 1680 1681
		spin_lock(&clp->cl_lock);
	}
	spin_unlock(&clp->cl_lock);
1682
}
1683

1684 1685 1686 1687 1688 1689
static void __free_session(struct nfsd4_session *ses)
{
	free_session_slots(ses);
	kfree(ses);
}

1690
static void free_session(struct nfsd4_session *ses)
1691
{
1692
	nfsd4_del_conns(ses);
1693
	nfsd4_put_drc_mem(&ses->se_fchannel);
1694
	__free_session(ses);
1695 1696
}

1697
static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
1698 1699
{
	int idx;
1700
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1701

1702 1703 1704
	new->se_client = clp;
	gen_sessionid(new);

1705 1706
	INIT_LIST_HEAD(&new->se_conns);

1707
	new->se_cb_seq_nr = 1;
1708
	new->se_flags = cses->flags;
1709
	new->se_cb_prog = cses->callback_prog;
1710
	new->se_cb_sec = cses->cb_sec;
1711
	atomic_set(&new->se_ref, 0);
1712
	idx = hash_sessionid(&new->se_sessionid);
1713
	list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
1714
	spin_lock(&clp->cl_lock);
1715
	list_add(&new->se_perclnt, &clp->cl_sessions);
1716
	spin_unlock(&clp->cl_lock);
1717

1718
	{
1719
		struct sockaddr *sa = svc_addr(rqstp);
1720 1721 1722 1723 1724 1725 1726
		/*
		 * This is a little silly; with sessions there's no real
		 * use for the callback address.  Use the peer address
		 * as a reasonable default for now, but consider fixing
		 * the rpc client not to require an address in the
		 * future:
		 */
1727 1728 1729
		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
	}
1730 1731
}

1732
/* caller must hold client_lock */
Marc Eshel's avatar
Marc Eshel committed
1733
static struct nfsd4_session *
1734
__find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net)
Marc Eshel's avatar
Marc Eshel committed
1735 1736 1737
{
	struct nfsd4_session *elem;
	int idx;
1738
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
Marc Eshel's avatar
Marc Eshel committed
1739

1740 1741
	lockdep_assert_held(&nn->client_lock);

Marc Eshel's avatar
Marc Eshel committed
1742 1743 1744
	dump_sessionid(__func__, sessionid);
	idx = hash_sessionid(sessionid);
	/* Search in the appropriate list */
1745
	list_for_each_entry(elem, &nn->sessionid_hashtbl[idx], se_hash) {
Marc Eshel's avatar
Marc Eshel committed
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755
		if (!memcmp(elem->se_sessionid.data, sessionid->data,
			    NFS4_MAX_SESSIONID_LEN)) {
			return elem;
		}
	}

	dprintk("%s: session not found\n", __func__);
	return NULL;
}

1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
static struct nfsd4_session *
find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net,
		__be32 *ret)
{
	struct nfsd4_session *session;
	__be32 status = nfserr_badsession;

	session = __find_in_sessionid_hashtbl(sessionid, net);
	if (!session)
		goto out;
	status = nfsd4_get_session_locked(session);
	if (status)
		session = NULL;
out:
	*ret = status;
	return session;
}

1774
/* caller must hold client_lock */
1775
static void
Marc Eshel's avatar
Marc Eshel committed
1776
unhash_session(struct nfsd4_session *ses)
1777
{
1778 1779 1780 1781 1782
	struct nfs4_client *clp = ses->se_client;
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	lockdep_assert_held(&nn->client_lock);

1783
	list_del(&ses->se_hash);
1784
	spin_lock(&ses->se_client->cl_lock);
1785
	list_del(&ses->se_perclnt);
1786
	spin_unlock(&ses->se_client->cl_lock);
Marc Eshel's avatar
Marc Eshel committed
1787 1788
}

Linus Torvalds's avatar
Linus Torvalds committed
1789 1790
/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
static int
1791
STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
1792
{
1793 1794 1795 1796 1797 1798
	/*
	 * We're assuming the clid was not given out from a boot
	 * precisely 2^32 (about 136 years) before this one.  That seems
	 * a safe assumption:
	 */
	if (clid->cl_boot == (u32)nn->boot_time)
Linus Torvalds's avatar
Linus Torvalds committed
1799
		return 0;
Andy Adamson's avatar
Andy Adamson committed
1800
	dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n",
1801
		clid->cl_boot, clid->cl_id, nn->boot_time);
Linus Torvalds's avatar
Linus Torvalds committed
1802 1803 1804 1805 1806 1807 1808 1809
	return 1;
}

/* 
 * XXX Should we use a slab cache ?
 * This type of memory management is somewhat inefficient, but we use it
 * anyway since SETCLIENTID is not a common operation.
 */
1810
static struct nfs4_client *alloc_client(struct xdr_netobj name)
Linus Torvalds's avatar
Linus Torvalds committed
1811 1812
{
	struct nfs4_client *clp;
1813
	int i;
Linus Torvalds's avatar
Linus Torvalds committed
1814

1815
	clp = kmem_cache_zalloc(client_slab, GFP_KERNEL);
1816 1817
	if (clp == NULL)
		return NULL;
1818
	clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL);
1819 1820
	if (clp->cl_name.data == NULL)
		goto err_no_name;
1821 1822 1823
	clp->cl_ownerstr_hashtbl = kmalloc_array(OWNER_HASH_SIZE,
						 sizeof(struct list_head),
						 GFP_KERNEL);
1824 1825 1826 1827
	if (!clp->cl_ownerstr_hashtbl)
		goto err_no_hashtbl;
	for (i = 0; i < OWNER_HASH_SIZE; i++)
		INIT_LIST_HEAD(&clp->cl_ownerstr_hashtbl[i]);
1828
	clp->cl_name.len = name.len;
1829 1830 1831 1832 1833 1834 1835 1836 1837
	INIT_LIST_HEAD(&clp->cl_sessions);
	idr_init(&clp->cl_stateids);
	atomic_set(&clp->cl_refcount, 0);
	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
	INIT_LIST_HEAD(&clp->cl_idhash);
	INIT_LIST_HEAD(&clp->cl_openowners);
	INIT_LIST_HEAD(&clp->cl_delegations);
	INIT_LIST_HEAD(&clp->cl_lru);
	INIT_LIST_HEAD(&clp->cl_revoked);
1838 1839 1840
#ifdef CONFIG_NFSD_PNFS
	INIT_LIST_HEAD(&clp->cl_lo_states);
#endif
1841 1842
	spin_lock_init(&clp->cl_lock);
	rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
Linus Torvalds's avatar
Linus Torvalds committed
1843
	return clp;
1844 1845 1846
err_no_hashtbl:
	kfree(clp->cl_name.data);
err_no_name:
1847
	kmem_cache_free(client_slab, clp);
1848
	return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
1849 1850
}

1851
static void
Linus Torvalds's avatar
Linus Torvalds committed
1852 1853
free_client(struct nfs4_client *clp)
{
1854 1855 1856 1857 1858
	while (!list_empty(&clp->cl_sessions)) {
		struct nfsd4_session *ses;
		ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
				se_perclnt);
		list_del(&ses->se_perclnt);
1859 1860
		WARN_ON_ONCE(atomic_read(&ses->se_ref));
		free_session(ses);
1861
	}
1862
	rpc_destroy_wait_queue(&clp->cl_cb_waitq);
1863
	free_svc_cred(&clp->cl_cred);
1864
	kfree(clp->cl_ownerstr_hashtbl);
Linus Torvalds's avatar
Linus Torvalds committed
1865
	kfree(clp->cl_name.data);
majianpeng's avatar
majianpeng committed
1866
	idr_destroy(&clp->cl_stateids);
1867
	kmem_cache_free(client_slab, clp);
Linus Torvalds's avatar
Linus Torvalds committed
1868 1869
}

Benny Halevy's avatar
Benny Halevy committed
1870
/* must be called under the client_lock */
1871
static void
Benny Halevy's avatar
Benny Halevy committed
1872 1873
unhash_client_locked(struct nfs4_client *clp)
{
1874
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1875 1876
	struct nfsd4_session *ses;

1877 1878
	lockdep_assert_held(&nn->client_lock);

1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
	/* Mark the client as expired! */
	clp->cl_time = 0;
	/* Make it invisible */
	if (!list_empty(&clp->cl_idhash)) {
		list_del_init(&clp->cl_idhash);
		if (test_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags))
			rb_erase(&clp->cl_namenode, &nn->conf_name_tree);
		else
			rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
	}
	list_del_init(&clp->cl_lru);
1890
	spin_lock(&clp->cl_lock);
1891 1892
	list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
		list_del_init(&ses->se_hash);
1893
	spin_unlock(&clp->cl_lock);
Benny Halevy's avatar
Benny Halevy committed
1894 1895
}

Linus Torvalds's avatar
Linus Torvalds committed
1896
static void
1897 1898 1899 1900 1901 1902 1903 1904 1905
unhash_client(struct nfs4_client *clp)
{
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	spin_lock(&nn->client_lock);
	unhash_client_locked(clp);
	spin_unlock(&nn->client_lock);
}

1906 1907 1908 1909 1910 1911 1912 1913
static __be32 mark_client_expired_locked(struct nfs4_client *clp)
{
	if (atomic_read(&clp->cl_refcount))
		return nfserr_jukebox;
	unhash_client_locked(clp);
	return nfs_ok;
}

1914 1915
static void
__destroy_client(struct nfs4_client *clp)
Linus Torvalds's avatar
Linus Torvalds committed
1916
{
1917
	int i;
1918
	struct nfs4_openowner *oo;
Linus Torvalds's avatar
Linus Torvalds committed
1919 1920 1921 1922
	struct nfs4_delegation *dp;
	struct list_head reaplist;

	INIT_LIST_HEAD(&reaplist);
1923
	spin_lock(&state_lock);
1924 1925
	while (!list_empty(&clp->cl_delegations)) {
		dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
1926
		WARN_ON(!unhash_delegation_locked(dp));
1927
		list_add(&dp->dl_recall_lru, &reaplist);
Linus Torvalds's avatar
Linus Torvalds committed
1928
	}
1929
	spin_unlock(&state_lock);
Linus Torvalds's avatar
Linus Torvalds committed
1930 1931
	while (!list_empty(&reaplist)) {
		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
1932
		list_del_init(&dp->dl_recall_lru);
1933
		destroy_unhashed_deleg(dp);
Linus Torvalds's avatar
Linus Torvalds committed
1934
	}
1935
	while (!list_empty(&clp->cl_revoked)) {
1936
		dp = list_entry(clp->cl_revoked.next, struct nfs4_delegation, dl_recall_lru);
1937
		list_del_init(&dp->dl_recall_lru);
1938
		nfs4_put_stid(&dp->dl_stid);
1939
	}
1940
	while (!list_empty(&clp->cl_openowners)) {
1941
		oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient);
1942
		nfs4_get_stateowner(&oo->oo_owner);
1943
		release_openowner(oo);
Linus Torvalds's avatar
Linus Torvalds committed
1944
	}
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954
	for (i = 0; i < OWNER_HASH_SIZE; i++) {
		struct nfs4_stateowner *so, *tmp;

		list_for_each_entry_safe(so, tmp, &clp->cl_ownerstr_hashtbl[i],
					 so_strhash) {
			/* Should be no openowners at this point */
			WARN_ON_ONCE(so->so_is_open_owner);
			remove_blocked_locks(lockowner(so));
		}
	}
1955
	nfsd4_return_all_client_layouts(clp);
1956
	nfsd4_shutdown_callback(clp);
Benny Halevy's avatar
Benny Halevy committed
1957 1958
	if (clp->cl_cb_conn.cb_xprt)
		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
1959
	free_client(clp);
Linus Torvalds's avatar
Linus Torvalds committed
1960 1961
}

1962 1963 1964 1965 1966 1967 1968
static void
destroy_client(struct nfs4_client *clp)
{
	unhash_client(clp);
	__destroy_client(clp);
}

1969 1970
static void expire_client(struct nfs4_client *clp)
{
1971
	unhash_client(clp);
1972
	nfsd4_client_record_remove(clp);
1973
	__destroy_client(clp);
1974 1975
}

1976 1977 1978 1979
static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
{
	memcpy(target->cl_verifier.data, source->data,
			sizeof(target->cl_verifier.data));
Linus Torvalds's avatar
Linus Torvalds committed
1980 1981
}

1982 1983
static void copy_clid(struct nfs4_client *target, struct nfs4_client *source)
{
Linus Torvalds's avatar
Linus Torvalds committed
1984 1985 1986 1987
	target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; 
	target->cl_clientid.cl_id = source->cl_clientid.cl_id; 
}

1988 1989
static int copy_cred(struct svc_cred *target, struct svc_cred *source)
{
1990 1991 1992
	target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL);
	target->cr_raw_principal = kstrdup(source->cr_raw_principal,
								GFP_KERNEL);
1993 1994 1995 1996
	target->cr_targ_princ = kstrdup(source->cr_targ_princ, GFP_KERNEL);
	if ((source->cr_principal && !target->cr_principal) ||
	    (source->cr_raw_principal && !target->cr_raw_principal) ||
	    (source->cr_targ_princ && !target->cr_targ_princ))
1997
		return -ENOMEM;
1998

1999
	target->cr_flavor = source->cr_flavor;
Linus Torvalds's avatar
Linus Torvalds committed
2000 2001 2002 2003
	target->cr_uid = source->cr_uid;
	target->cr_gid = source->cr_gid;
	target->cr_group_info = source->cr_group_info;
	get_group_info(target->cr_group_info);
2004 2005 2006
	target->cr_gss_mech = source->cr_gss_mech;
	if (source->cr_gss_mech)
		gss_mech_get(source->cr_gss_mech);
2007
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
2008 2009
}

2010
static int
2011 2012
compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
{
2013 2014 2015 2016 2017
	if (o1->len < o2->len)
		return -1;
	if (o1->len > o2->len)
		return 1;
	return memcmp(o1->data, o2->data, o1->len);
2018 2019
}

2020
static int same_name(const char *n1, const char *n2)
2021
{
2022
	return 0 == memcmp(n1, n2, HEXDIR_LEN);
Linus Torvalds's avatar
Linus Torvalds committed
2023 2024 2025
}

static int
2026 2027 2028
same_verf(nfs4_verifier *v1, nfs4_verifier *v2)
{
	return 0 == memcmp(v1->data, v2->data, sizeof(v1->data));
Linus Torvalds's avatar
Linus Torvalds committed
2029 2030 2031
}

static int
2032 2033 2034
same_clid(clientid_t *cl1, clientid_t *cl2)
{
	return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id);
Linus Torvalds's avatar
Linus Torvalds committed
2035 2036
}

2037 2038 2039 2040 2041 2042 2043
static bool groups_equal(struct group_info *g1, struct group_info *g2)
{
	int i;

	if (g1->ngroups != g2->ngroups)
		return false;
	for (i=0; i<g1->ngroups; i++)
2044
		if (!gid_eq(g1->gid[i], g2->gid[i]))
2045 2046 2047 2048
			return false;
	return true;
}

2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
/*
 * RFC 3530 language requires clid_inuse be returned when the
 * "principal" associated with a requests differs from that previously
 * used.  We use uid, gid's, and gss principal string as our best
 * approximation.  We also don't want to allow non-gss use of a client
 * established using gss: in theory cr_principal should catch that
 * change, but in practice cr_principal can be null even in the gss case
 * since gssd doesn't always pass down a principal string.
 */
static bool is_gss_cred(struct svc_cred *cr)
{
	/* Is cr_flavor one of the gss "pseudoflavors"?: */
	return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR);
}


2065
static bool
2066 2067
same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
{
2068
	if ((is_gss_cred(cr1) != is_gss_cred(cr2))
2069 2070
		|| (!uid_eq(cr1->cr_uid, cr2->cr_uid))
		|| (!gid_eq(cr1->cr_gid, cr2->cr_gid))
2071 2072
		|| !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
		return false;
2073
	/* XXX: check that cr_targ_princ fields match ? */
2074 2075 2076 2077
	if (cr1->cr_principal == cr2->cr_principal)
		return true;
	if (!cr1->cr_principal || !cr2->cr_principal)
		return false;
2078
	return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
Linus Torvalds's avatar
Linus Torvalds committed
2079 2080
}

2081 2082 2083 2084 2085
static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
{
	struct svc_cred *cr = &rqstp->rq_cred;
	u32 service;

2086 2087
	if (!cr->cr_gss_mech)
		return false;
2088 2089 2090 2091 2092
	service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor);
	return service == RPC_GSS_SVC_INTEGRITY ||
	       service == RPC_GSS_SVC_PRIVACY;
}

2093
bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
2094 2095 2096 2097 2098 2099 2100 2101 2102
{
	struct svc_cred *cr = &rqstp->rq_cred;

	if (!cl->cl_mach_cred)
		return true;
	if (cl->cl_cred.cr_gss_mech != cr->cr_gss_mech)
		return false;
	if (!svc_rqst_integrity_protected(rqstp))
		return false;
2103 2104 2105
	if (cl->cl_cred.cr_raw_principal)
		return 0 == strcmp(cl->cl_cred.cr_raw_principal,
						cr->cr_raw_principal);
2106 2107 2108 2109 2110
	if (!cr->cr_principal)
		return false;
	return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
}

2111
static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn)
2112
{
2113
	__be32 verf[2];
Linus Torvalds's avatar
Linus Torvalds committed
2114

2115 2116 2117 2118 2119
	/*
	 * This is opaque to client, so no need to byte-swap. Use
	 * __force to keep sparse happy
	 */
	verf[0] = (__force __be32)get_seconds();
2120
	verf[1] = (__force __be32)nn->clverifier_counter++;
2121
	memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
Linus Torvalds's avatar
Linus Torvalds committed
2122 2123
}

2124 2125 2126 2127 2128 2129 2130
static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
{
	clp->cl_clientid.cl_boot = nn->boot_time;
	clp->cl_clientid.cl_id = nn->clientid_counter++;
	gen_confirm(clp, nn);
}

2131 2132
static struct nfs4_stid *
find_stateid_locked(struct nfs4_client *cl, stateid_t *t)
2133
{
2134 2135 2136 2137 2138 2139
	struct nfs4_stid *ret;

	ret = idr_find(&cl->cl_stateids, t->si_opaque.so_id);
	if (!ret || !ret->sc_type)
		return NULL;
	return ret;
2140 2141
}

2142 2143
static struct nfs4_stid *
find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask)
2144 2145
{
	struct nfs4_stid *s;
2146

2147 2148
	spin_lock(&cl->cl_lock);
	s = find_stateid_locked(cl, t);
2149 2150
	if (s != NULL) {
		if (typemask & s->sc_type)
2151
			refcount_inc(&s->sc_count);
2152 2153 2154
		else
			s = NULL;
	}
2155 2156
	spin_unlock(&cl->cl_lock);
	return s;
2157 2158
}

2159
static struct nfs4_client *create_client(struct xdr_netobj name,
2160 2161 2162 2163
		struct svc_rqst *rqstp, nfs4_verifier *verf)
{
	struct nfs4_client *clp;
	struct sockaddr *sa = svc_addr(rqstp);
2164
	int ret;
2165
	struct net *net = SVC_NET(rqstp);
2166 2167 2168 2169 2170

	clp = alloc_client(name);
	if (clp == NULL)
		return NULL;

2171 2172 2173 2174
	ret = copy_cred(&clp->cl_cred, &rqstp->rq_cred);
	if (ret) {
		free_client(clp);
		return NULL;
2175
	}
2176
	nfsd4_init_cb(&clp->cl_cb_null, clp, NULL, NFSPROC4_CLNT_CB_NULL);
Benny Halevy's avatar
Benny Halevy committed
2177
	clp->cl_time = get_seconds();
2178 2179 2180
	clear_bit(0, &clp->cl_cb_slot_busy);
	copy_verf(clp, verf);
	rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
2181
	clp->cl_cb_session = NULL;
2182
	clp->net = net;
2183 2184 2185
	return clp;
}

2186
static void
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208
add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root)
{
	struct rb_node **new = &(root->rb_node), *parent = NULL;
	struct nfs4_client *clp;

	while (*new) {
		clp = rb_entry(*new, struct nfs4_client, cl_namenode);
		parent = *new;

		if (compare_blob(&clp->cl_name, &new_clp->cl_name) > 0)
			new = &((*new)->rb_left);
		else
			new = &((*new)->rb_right);
	}

	rb_link_node(&new_clp->cl_namenode, parent, new);
	rb_insert_color(&new_clp->cl_namenode, root);
}

static struct nfs4_client *
find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root)
{
2209
	int cmp;
2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227
	struct rb_node *node = root->rb_node;
	struct nfs4_client *clp;

	while (node) {
		clp = rb_entry(node, struct nfs4_client, cl_namenode);
		cmp = compare_blob(&clp->cl_name, name);
		if (cmp > 0)
			node = node->rb_left;
		else if (cmp < 0)
			node = node->rb_right;
		else
			return clp;
	}
	return NULL;
}

static void
add_to_unconfirmed(struct nfs4_client *clp)
Linus Torvalds's avatar
Linus Torvalds committed
2228 2229
{
	unsigned int idhashval;
2230
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
2231

2232 2233
	lockdep_assert_held(&nn->client_lock);

2234
	clear_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
2235
	add_clp_to_name_tree(clp, &nn->unconf_name_tree);
Linus Torvalds's avatar
Linus Torvalds committed
2236
	idhashval = clientid_hashval(clp->cl_clientid.cl_id);
2237
	list_add(&clp->cl_idhash, &nn->unconf_id_hashtbl[idhashval]);
2238
	renew_client_locked(clp);
Linus Torvalds's avatar
Linus Torvalds committed
2239 2240
}

2241
static void
Linus Torvalds's avatar
Linus Torvalds committed
2242 2243 2244
move_to_confirmed(struct nfs4_client *clp)
{
	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
2245
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
2246

2247 2248
	lockdep_assert_held(&nn->client_lock);

Linus Torvalds's avatar
Linus Torvalds committed
2249
	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
2250
	list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);
2251
	rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
2252
	add_clp_to_name_tree(clp, &nn->conf_name_tree);
2253
	set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
2254
	renew_client_locked(clp);
Linus Torvalds's avatar
Linus Torvalds committed
2255 2256 2257
}

static struct nfs4_client *
2258
find_client_in_id_table(struct list_head *tbl, clientid_t *clid, bool sessions)
Linus Torvalds's avatar
Linus Torvalds committed
2259 2260 2261 2262
{
	struct nfs4_client *clp;
	unsigned int idhashval = clientid_hashval(clid->cl_id);

2263
	list_for_each_entry(clp, &tbl[idhashval], cl_idhash) {
2264
		if (same_clid(&clp->cl_clientid, clid)) {
2265 2266
			if ((bool)clp->cl_minorversion != sessions)
				return NULL;
2267
			renew_client_locked(clp);
Linus Torvalds's avatar
Linus Torvalds committed
2268
			return clp;
2269
		}
Linus Torvalds's avatar
Linus Torvalds committed
2270 2271 2272 2273
	}
	return NULL;
}

2274 2275 2276 2277 2278
static struct nfs4_client *
find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
{
	struct list_head *tbl = nn->conf_id_hashtbl;

2279
	lockdep_assert_held(&nn->client_lock);
2280 2281 2282
	return find_client_in_id_table(tbl, clid, sessions);
}

Linus Torvalds's avatar
Linus Torvalds committed
2283
static struct nfs4_client *
2284
find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
2285
{
2286
	struct list_head *tbl = nn->unconf_id_hashtbl;
Linus Torvalds's avatar
Linus Torvalds committed
2287

2288
	lockdep_assert_held(&nn->client_lock);
2289
	return find_client_in_id_table(tbl, clid, sessions);
Linus Torvalds's avatar
Linus Torvalds committed
2290 2291
}

2292
static bool clp_used_exchangeid(struct nfs4_client *clp)
2293
{
2294
	return clp->cl_exchange_flags != 0;
2295
} 
2296

2297
static struct nfs4_client *
2298
find_confirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
2299
{
2300
	lockdep_assert_held(&nn->client_lock);
2301
	return find_clp_in_name_tree(name, &nn->conf_name_tree);
2302 2303 2304
}

static struct nfs4_client *
2305
find_unconfirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
2306
{
2307
	lockdep_assert_held(&nn->client_lock);
2308
	return find_clp_in_name_tree(name, &nn->unconf_name_tree);
2309 2310
}

2311
static void
2312
gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp)
Linus Torvalds's avatar
Linus Torvalds committed
2313
{
2314
	struct nfs4_cb_conn *conn = &clp->cl_cb_conn;
2315 2316
	struct sockaddr	*sa = svc_addr(rqstp);
	u32 scopeid = rpc_get_scope_id(sa);
2317 2318 2319 2320 2321 2322 2323 2324 2325 2326
	unsigned short expected_family;

	/* Currently, we only support tcp and tcp6 for the callback channel */
	if (se->se_callback_netid_len == 3 &&
	    !memcmp(se->se_callback_netid_val, "tcp", 3))
		expected_family = AF_INET;
	else if (se->se_callback_netid_len == 4 &&
		 !memcmp(se->se_callback_netid_val, "tcp6", 4))
		expected_family = AF_INET6;
	else
Linus Torvalds's avatar
Linus Torvalds committed
2327 2328
		goto out_err;

2329
	conn->cb_addrlen = rpc_uaddr2sockaddr(clp->net, se->se_callback_addr_val,
2330
					    se->se_callback_addr_len,
2331 2332
					    (struct sockaddr *)&conn->cb_addr,
					    sizeof(conn->cb_addr));
2333

2334
	if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family)
Linus Torvalds's avatar
Linus Torvalds committed
2335
		goto out_err;
2336

2337 2338
	if (conn->cb_addr.ss_family == AF_INET6)
		((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid;
2339

2340 2341
	conn->cb_prog = se->se_callback_prog;
	conn->cb_ident = se->se_callback_ident;
2342
	memcpy(&conn->cb_saddr, &rqstp->rq_daddr, rqstp->rq_daddrlen);
Linus Torvalds's avatar
Linus Torvalds committed
2343 2344
	return;
out_err:
2345 2346
	conn->cb_addr.ss_family = AF_UNSPEC;
	conn->cb_addrlen = 0;
2347
	dprintk("NFSD: this client (clientid %08x/%08x) "
Linus Torvalds's avatar
Linus Torvalds committed
2348 2349 2350 2351 2352 2353
		"will not receive delegations\n",
		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);

	return;
}

2354
/*
2355
 * Cache a reply. nfsd4_check_resp_size() has bounded the cache size.
2356
 */
2357
static void
2358 2359
nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
{
2360
	struct xdr_buf *buf = resp->xdr.buf;
2361 2362
	struct nfsd4_slot *slot = resp->cstate.slot;
	unsigned int base;
2363

2364
	dprintk("--> %s slot %p\n", __func__, slot);
2365

2366
	slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
2367 2368
	slot->sl_opcnt = resp->opcnt;
	slot->sl_status = resp->cstate.status;
2369 2370
	free_svc_cred(&slot->sl_cred);
	copy_cred(&slot->sl_cred, &resp->rqstp->rq_cred);
2371

2372 2373
	if (!nfsd4_cache_this(resp)) {
		slot->sl_flags &= ~NFSD4_SLOT_CACHED;
2374
		return;
2375
	}
2376 2377
	slot->sl_flags |= NFSD4_SLOT_CACHED;

2378 2379 2380
	base = resp->cstate.data_offset;
	slot->sl_datalen = buf->len - base;
	if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen))
2381 2382
		WARN(1, "%s: sessions DRC could not cache compound\n",
		     __func__);
2383
	return;
2384 2385 2386
}

/*
2387 2388 2389 2390
 * Encode the replay sequence operation from the slot values.
 * If cachethis is FALSE encode the uncached rep error on the next
 * operation which sets resp->p and increments resp->opcnt for
 * nfs4svc_encode_compoundres.
2391 2392
 *
 */
2393 2394 2395
static __be32
nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,
			  struct nfsd4_compoundres *resp)
2396
{
2397 2398
	struct nfsd4_op *op;
	struct nfsd4_slot *slot = resp->cstate.slot;
2399

2400 2401 2402
	/* Encode the replayed sequence operation */
	op = &args->ops[resp->opcnt - 1];
	nfsd4_encode_operation(resp, op);
2403

2404 2405 2406 2407 2408 2409 2410 2411 2412 2413
	if (slot->sl_flags & NFSD4_SLOT_CACHED)
		return op->status;
	if (args->opcnt == 1) {
		/*
		 * The original operation wasn't a solo sequence--we
		 * always cache those--so this retry must not match the
		 * original:
		 */
		op->status = nfserr_seq_false_retry;
	} else {
2414 2415 2416
		op = &args->ops[resp->opcnt++];
		op->status = nfserr_retry_uncached_rep;
		nfsd4_encode_operation(resp, op);
2417
	}
2418
	return op->status;
2419 2420 2421
}

/*
2422 2423
 * The sequence operation is not cached because we can use the slot and
 * session values.
2424
 */
2425
static __be32
2426 2427
nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
			 struct nfsd4_sequence *seq)
2428
{
2429
	struct nfsd4_slot *slot = resp->cstate.slot;
2430 2431
	struct xdr_stream *xdr = &resp->xdr;
	__be32 *p;
2432 2433
	__be32 status;

2434
	dprintk("--> %s slot %p\n", __func__, slot);
2435

2436
	status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp);
2437
	if (status)
2438
		return status;
2439

2440 2441 2442 2443 2444 2445 2446
	p = xdr_reserve_space(xdr, slot->sl_datalen);
	if (!p) {
		WARN_ON_ONCE(1);
		return nfserr_serverfault;
	}
	xdr_encode_opaque_fixed(p, slot->sl_data, slot->sl_datalen);
	xdr_commit_encode(xdr);
2447

2448
	resp->opcnt = slot->sl_opcnt;
2449
	return slot->sl_status;
2450 2451
}

Andy Adamson's avatar
Andy Adamson committed
2452 2453 2454 2455 2456 2457
/*
 * Set the exchange_id flags returned by the server.
 */
static void
nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid)
{
2458 2459 2460
#ifdef CONFIG_NFSD_PNFS
	new->cl_exchange_flags |= EXCHGID4_FLAG_USE_PNFS_MDS;
#else
Andy Adamson's avatar
Andy Adamson committed
2461
	new->cl_exchange_flags |= EXCHGID4_FLAG_USE_NON_PNFS;
2462
#endif
Andy Adamson's avatar
Andy Adamson committed
2463 2464 2465 2466 2467 2468 2469 2470

	/* Referrals are supported, Migration is not. */
	new->cl_exchange_flags |= EXCHGID4_FLAG_SUPP_MOVED_REFER;

	/* set the wire flags to return to client. */
	clid->flags = new->cl_exchange_flags;
}

2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481
static bool client_has_openowners(struct nfs4_client *clp)
{
	struct nfs4_openowner *oo;

	list_for_each_entry(oo, &clp->cl_openowners, oo_perclient) {
		if (!list_empty(&oo->oo_owner.so_stateids))
			return true;
	}
	return false;
}

2482 2483
static bool client_has_state(struct nfs4_client *clp)
{
2484
	return client_has_openowners(clp)
2485 2486 2487
#ifdef CONFIG_NFSD_PNFS
		|| !list_empty(&clp->cl_lo_states)
#endif
2488 2489
		|| !list_empty(&clp->cl_delegations)
		|| !list_empty(&clp->cl_sessions);
2490 2491
}

Andy Adamson's avatar
Andy Adamson committed
2492
__be32
2493 2494
nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
Andy Adamson's avatar
Andy Adamson committed
2495
{
2496
	struct nfsd4_exchange_id *exid = &u->exchange_id;
2497 2498
	struct nfs4_client *conf, *new;
	struct nfs4_client *unconf = NULL;
J. Bruce Fields's avatar
J. Bruce Fields committed
2499
	__be32 status;
2500
	char			addr_str[INET6_ADDRSTRLEN];
Andy Adamson's avatar
Andy Adamson committed
2501
	nfs4_verifier		verf = exid->verifier;
2502
	struct sockaddr		*sa = svc_addr(rqstp);
2503
	bool	update = exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A;
2504
	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Andy Adamson's avatar
Andy Adamson committed
2505

2506
	rpc_ntop(sa, addr_str, sizeof(addr_str));
Andy Adamson's avatar
Andy Adamson committed
2507
	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
2508
		"ip_addr=%s flags %x, spa_how %d\n",
Andy Adamson's avatar
Andy Adamson committed
2509
		__func__, rqstp, exid, exid->clname.len, exid->clname.data,
2510
		addr_str, exid->flags, exid->spa_how);
Andy Adamson's avatar
Andy Adamson committed
2511

2512
	if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
Andy Adamson's avatar
Andy Adamson committed
2513 2514
		return nfserr_inval;

2515 2516 2517 2518
	new = create_client(exid->clname, rqstp, &verf);
	if (new == NULL)
		return nfserr_jukebox;

Andy Adamson's avatar
Andy Adamson committed
2519
	switch (exid->spa_how) {
2520
	case SP4_MACH_CRED:
2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536
		exid->spo_must_enforce[0] = 0;
		exid->spo_must_enforce[1] = (
			1 << (OP_BIND_CONN_TO_SESSION - 32) |
			1 << (OP_EXCHANGE_ID - 32) |
			1 << (OP_CREATE_SESSION - 32) |
			1 << (OP_DESTROY_SESSION - 32) |
			1 << (OP_DESTROY_CLIENTID - 32));

		exid->spo_must_allow[0] &= (1 << (OP_CLOSE) |
					1 << (OP_OPEN_DOWNGRADE) |
					1 << (OP_LOCKU) |
					1 << (OP_DELEGRETURN));

		exid->spo_must_allow[1] &= (
					1 << (OP_TEST_STATEID - 32) |
					1 << (OP_FREE_STATEID - 32));
2537 2538 2539
		if (!svc_rqst_integrity_protected(rqstp)) {
			status = nfserr_inval;
			goto out_nolock;
2540 2541 2542 2543 2544 2545
		}
		/*
		 * Sometimes userspace doesn't give us a principal.
		 * Which is a bug, really.  Anyway, we can't enforce
		 * MACH_CRED in that case, better to give up now:
		 */
2546 2547
		if (!new->cl_cred.cr_principal &&
					!new->cl_cred.cr_raw_principal) {
2548 2549
			status = nfserr_serverfault;
			goto out_nolock;
2550 2551
		}
		new->cl_mach_cred = true;
Andy Adamson's avatar
Andy Adamson committed
2552 2553
	case SP4_NONE:
		break;
2554 2555
	default:				/* checked by xdr code */
		WARN_ON_ONCE(1);
Andy Adamson's avatar
Andy Adamson committed
2556
	case SP4_SSV:
2557 2558
		status = nfserr_encr_alg_unsupp;
		goto out_nolock;
Andy Adamson's avatar
Andy Adamson committed
2559 2560
	}

2561
	/* Cases below refer to rfc 5661 section 18.35.4: */
2562
	spin_lock(&nn->client_lock);
2563
	conf = find_confirmed_client_by_name(&exid->clname, nn);
Andy Adamson's avatar
Andy Adamson committed
2564
	if (conf) {
2565 2566 2567
		bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
		bool verfs_match = same_verf(&verf, &conf->cl_verifier);

2568 2569
		if (update) {
			if (!clp_used_exchangeid(conf)) { /* buggy client */
2570
				status = nfserr_inval;
2571 2572
				goto out;
			}
2573
			if (!nfsd4_mach_creds_match(conf, rqstp)) {
2574 2575 2576
				status = nfserr_wrong_cred;
				goto out;
			}
2577
			if (!creds_match) { /* case 9 */
2578
				status = nfserr_perm;
2579 2580 2581
				goto out;
			}
			if (!verfs_match) { /* case 8 */
Andy Adamson's avatar
Andy Adamson committed
2582 2583 2584
				status = nfserr_not_same;
				goto out;
			}
2585 2586 2587
			/* case 6 */
			exid->flags |= EXCHGID4_FLAG_CONFIRMED_R;
			goto out_copy;
Andy Adamson's avatar
Andy Adamson committed
2588
		}
2589
		if (!creds_match) { /* case 3 */
2590 2591
			if (client_has_state(conf)) {
				status = nfserr_clid_inuse;
Andy Adamson's avatar
Andy Adamson committed
2592 2593 2594 2595
				goto out;
			}
			goto out_new;
		}
2596
		if (verfs_match) { /* case 2 */
2597
			conf->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R;
2598 2599 2600
			goto out_copy;
		}
		/* case 5, client reboot */
2601
		conf = NULL;
2602
		goto out_new;
2603 2604
	}

2605
	if (update) { /* case 7 */
2606 2607
		status = nfserr_noent;
		goto out;
Andy Adamson's avatar
Andy Adamson committed
2608 2609
	}

2610
	unconf  = find_unconfirmed_client_by_name(&exid->clname, nn);
2611
	if (unconf) /* case 4, possible retry or client restart */
2612
		unhash_client_locked(unconf);
Andy Adamson's avatar
Andy Adamson committed
2613

2614
	/* case 1 (normal case) */
Andy Adamson's avatar
Andy Adamson committed
2615
out_new:
2616 2617 2618 2619 2620
	if (conf) {
		status = mark_client_expired_locked(conf);
		if (status)
			goto out;
	}
2621
	new->cl_minorversion = cstate->minorversion;
2622 2623
	new->cl_spo_must_allow.u.words[0] = exid->spo_must_allow[0];
	new->cl_spo_must_allow.u.words[1] = exid->spo_must_allow[1];
Andy Adamson's avatar
Andy Adamson committed
2624

2625
	gen_clid(new, nn);
2626
	add_to_unconfirmed(new);
2627
	swap(new, conf);
Andy Adamson's avatar
Andy Adamson committed
2628
out_copy:
2629 2630
	exid->clientid.cl_boot = conf->cl_clientid.cl_boot;
	exid->clientid.cl_id = conf->cl_clientid.cl_id;
Andy Adamson's avatar
Andy Adamson committed
2631

2632 2633
	exid->seqid = conf->cl_cs_slot.sl_seqid + 1;
	nfsd4_set_ex_flags(conf, exid);
Andy Adamson's avatar
Andy Adamson committed
2634 2635

	dprintk("nfsd4_exchange_id seqid %d flags %x\n",
2636
		conf->cl_cs_slot.sl_seqid, conf->cl_exchange_flags);
Andy Adamson's avatar
Andy Adamson committed
2637 2638 2639
	status = nfs_ok;

out:
2640
	spin_unlock(&nn->client_lock);
2641
out_nolock:
2642
	if (new)
2643 2644 2645
		expire_client(new);
	if (unconf)
		expire_client(unconf);
Andy Adamson's avatar
Andy Adamson committed
2646
	return status;
Andy Adamson's avatar
Andy Adamson committed
2647 2648
}

J. Bruce Fields's avatar
J. Bruce Fields committed
2649
static __be32
2650
check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse)
Benny Halevy's avatar
Benny Halevy committed
2651
{
2652 2653
	dprintk("%s enter. seqid %d slot_seqid %d\n", __func__, seqid,
		slot_seqid);
Benny Halevy's avatar
Benny Halevy committed
2654 2655

	/* The slot is in use, and no response has been sent. */
2656 2657
	if (slot_inuse) {
		if (seqid == slot_seqid)
Benny Halevy's avatar
Benny Halevy committed
2658 2659 2660 2661
			return nfserr_jukebox;
		else
			return nfserr_seq_misordered;
	}
2662
	/* Note unsigned 32-bit arithmetic handles wraparound: */
2663
	if (likely(seqid == slot_seqid + 1))
Benny Halevy's avatar
Benny Halevy committed
2664
		return nfs_ok;
2665
	if (seqid == slot_seqid)
Benny Halevy's avatar
Benny Halevy committed
2666 2667 2668 2669
		return nfserr_replay_cache;
	return nfserr_seq_misordered;
}

2670 2671 2672 2673 2674 2675 2676
/*
 * Cache the create session result into the create session single DRC
 * slot cache by saving the xdr structure. sl_seqid has been set.
 * Do this for solo or embedded create session operations.
 */
static void
nfsd4_cache_create_session(struct nfsd4_create_session *cr_ses,
J. Bruce Fields's avatar
J. Bruce Fields committed
2677
			   struct nfsd4_clid_slot *slot, __be32 nfserr)
2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690
{
	slot->sl_status = nfserr;
	memcpy(&slot->sl_cr_ses, cr_ses, sizeof(*cr_ses));
}

static __be32
nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
			    struct nfsd4_clid_slot *slot)
{
	memcpy(cr_ses, &slot->sl_cr_ses, sizeof(*cr_ses));
	return slot->sl_status;
}

2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707
#define NFSD_MIN_REQ_HDR_SEQ_SZ	((\
			2 * 2 + /* credential,verifier: AUTH_NULL, length 0 */ \
			1 +	/* MIN tag is length with zero, only length */ \
			3 +	/* version, opcount, opcode */ \
			XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
				/* seqid, slotID, slotID, cache */ \
			4 ) * sizeof(__be32))

#define NFSD_MIN_RESP_HDR_SEQ_SZ ((\
			2 +	/* verifier: AUTH_NULL, length 0 */\
			1 +	/* status */ \
			1 +	/* MIN tag is length with zero, only length */ \
			3 +	/* opcount, opcode, opstatus*/ \
			XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
				/* seqid, slotID, slotID, slotID, status */ \
			5 ) * sizeof(__be32))

2708
static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn)
2709
{
2710 2711
	u32 maxrpc = nn->nfsd_serv->sv_max_mesg;

2712 2713 2714 2715
	if (ca->maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ)
		return nfserr_toosmall;
	if (ca->maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ)
		return nfserr_toosmall;
2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734
	ca->headerpadsz = 0;
	ca->maxreq_sz = min_t(u32, ca->maxreq_sz, maxrpc);
	ca->maxresp_sz = min_t(u32, ca->maxresp_sz, maxrpc);
	ca->maxops = min_t(u32, ca->maxops, NFSD_MAX_OPS_PER_COMPOUND);
	ca->maxresp_cached = min_t(u32, ca->maxresp_cached,
			NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ);
	ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION);
	/*
	 * Note decreasing slot size below client's request may make it
	 * difficult for client to function correctly, whereas
	 * decreasing the number of slots will (just?) affect
	 * performance.  When short on memory we therefore prefer to
	 * decrease number of slots instead of their size.  Clients that
	 * request larger slots than they need will get poor results:
	 */
	ca->maxreqs = nfsd4_get_drc_mem(ca);
	if (!ca->maxreqs)
		return nfserr_jukebox;

2735
	return nfs_ok;
2736 2737
}

2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
/*
 * Server's NFSv4.1 backchannel support is AUTH_SYS-only for now.
 * These are based on similar macros in linux/sunrpc/msg_prot.h .
 */
#define RPC_MAX_HEADER_WITH_AUTH_SYS \
	(RPC_CALLHDRSIZE + 2 * (2 + UNX_CALLSLACK))

#define RPC_MAX_REPHEADER_WITH_AUTH_SYS \
	(RPC_REPHDRSIZE + (2 + NUL_REPLYSLACK))

2748
#define NFSD_CB_MAX_REQ_SZ	((NFS4_enc_cb_recall_sz + \
2749
				 RPC_MAX_HEADER_WITH_AUTH_SYS) * sizeof(__be32))
2750
#define NFSD_CB_MAX_RESP_SZ	((NFS4_dec_cb_recall_sz + \
2751 2752
				 RPC_MAX_REPHEADER_WITH_AUTH_SYS) * \
				 sizeof(__be32))
2753

2754
static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
2755
{
2756 2757
	ca->headerpadsz = 0;

2758
	if (ca->maxreq_sz < NFSD_CB_MAX_REQ_SZ)
2759
		return nfserr_toosmall;
2760
	if (ca->maxresp_sz < NFSD_CB_MAX_RESP_SZ)
2761 2762 2763 2764 2765 2766
		return nfserr_toosmall;
	ca->maxresp_cached = 0;
	if (ca->maxops < 2)
		return nfserr_toosmall;

	return nfs_ok;
2767 2768
}

2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786
static __be32 nfsd4_check_cb_sec(struct nfsd4_cb_sec *cbs)
{
	switch (cbs->flavor) {
	case RPC_AUTH_NULL:
	case RPC_AUTH_UNIX:
		return nfs_ok;
	default:
		/*
		 * GSS case: the spec doesn't allow us to return this
		 * error.  But it also doesn't allow us not to support
		 * GSS.
		 * I'd rather this fail hard than return some error the
		 * client might think it can already handle:
		 */
		return nfserr_encr_alg_unsupp;
	}
}

Andy Adamson's avatar
Andy Adamson committed
2787 2788
__be32
nfsd4_create_session(struct svc_rqst *rqstp,
2789
		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
Andy Adamson's avatar
Andy Adamson committed
2790
{
2791
	struct nfsd4_create_session *cr_ses = &u->create_session;
2792
	struct sockaddr *sa = svc_addr(rqstp);
2793
	struct nfs4_client *conf, *unconf;
2794
	struct nfs4_client *old = NULL;
2795
	struct nfsd4_session *new;
2796
	struct nfsd4_conn *conn;
2797
	struct nfsd4_clid_slot *cs_slot = NULL;
J. Bruce Fields's avatar
J. Bruce Fields committed
2798
	__be32 status = 0;
2799
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2800

2801 2802
	if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
		return nfserr_inval;
2803 2804 2805
	status = nfsd4_check_cb_sec(&cr_ses->cb_sec);
	if (status)
		return status;
2806
	status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
2807 2808 2809
	if (status)
		return status;
	status = check_backchannel_attrs(&cr_ses->back_channel);
2810
	if (status)
2811
		goto out_release_drc_mem;
2812
	status = nfserr_jukebox;
2813
	new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel);
2814 2815
	if (!new)
		goto out_release_drc_mem;
2816 2817 2818
	conn = alloc_conn_from_crses(rqstp, cr_ses);
	if (!conn)
		goto out_free_session;
2819

2820
	spin_lock(&nn->client_lock);
2821
	unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
2822
	conf = find_confirmed_client(&cr_ses->clientid, true, nn);
2823
	WARN_ON_ONCE(conf && unconf);
2824 2825

	if (conf) {
2826
		status = nfserr_wrong_cred;
2827
		if (!nfsd4_mach_creds_match(conf, rqstp))
2828
			goto out_free_conn;
2829 2830
		cs_slot = &conf->cl_cs_slot;
		status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
2831 2832 2833
		if (status) {
			if (status == nfserr_replay_cache)
				status = nfsd4_replay_create_session(cr_ses, cs_slot);
2834
			goto out_free_conn;
2835 2836 2837
		}
	} else if (unconf) {
		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
2838
		    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
2839
			status = nfserr_clid_inuse;
2840
			goto out_free_conn;
2841
		}
2842
		status = nfserr_wrong_cred;
2843
		if (!nfsd4_mach_creds_match(unconf, rqstp))
2844
			goto out_free_conn;
2845 2846
		cs_slot = &unconf->cl_cs_slot;
		status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
2847 2848
		if (status) {
			/* an unconfirmed replay returns misordered */
2849
			status = nfserr_seq_misordered;
2850
			goto out_free_conn;
2851
		}
2852
		old = find_confirmed_client_by_name(&unconf->cl_name, nn);
2853
		if (old) {
2854
			status = mark_client_expired_locked(old);
2855 2856
			if (status) {
				old = NULL;
2857
				goto out_free_conn;
2858
			}
2859
		}
2860
		move_to_confirmed(unconf);
2861 2862 2863
		conf = unconf;
	} else {
		status = nfserr_stale_clientid;
2864
		goto out_free_conn;
2865
	}
2866
	status = nfs_ok;
2867
	/* Persistent sessions are not supported */
2868
	cr_ses->flags &= ~SESSION4_PERSIST;
2869
	/* Upshifting from TCP to RDMA is not supported */
2870 2871
	cr_ses->flags &= ~SESSION4_RDMA;

2872
	init_session(rqstp, new, conf, cr_ses);
2873
	nfsd4_get_session_locked(new);
2874

2875
	memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
2876
	       NFS4_MAX_SESSIONID_LEN);
2877
	cs_slot->sl_seqid++;
2878
	cr_ses->seqid = cs_slot->sl_seqid;
2879

2880
	/* cache solo and embedded create sessions under the client_lock */
2881
	nfsd4_cache_create_session(cr_ses, cs_slot, status);
2882 2883 2884 2885 2886 2887
	spin_unlock(&nn->client_lock);
	/* init connection and backchannel */
	nfsd4_init_conn(rqstp, conn, new);
	nfsd4_put_session(new);
	if (old)
		expire_client(old);
2888
	return status;
2889
out_free_conn:
2890
	spin_unlock(&nn->client_lock);
2891
	free_conn(conn);
2892 2893
	if (old)
		expire_client(old);
2894 2895
out_free_session:
	__free_session(new);
2896 2897
out_release_drc_mem:
	nfsd4_put_drc_mem(&cr_ses->fore_channel);
2898
	return status;
Andy Adamson's avatar
Andy Adamson committed
2899 2900
}

2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914
static __be32 nfsd4_map_bcts_dir(u32 *dir)
{
	switch (*dir) {
	case NFS4_CDFC4_FORE:
	case NFS4_CDFC4_BACK:
		return nfs_ok;
	case NFS4_CDFC4_FORE_OR_BOTH:
	case NFS4_CDFC4_BACK_OR_BOTH:
		*dir = NFS4_CDFC4_BOTH;
		return nfs_ok;
	};
	return nfserr_inval;
}

2915 2916 2917
__be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp,
		struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
2918
{
2919
	struct nfsd4_backchannel_ctl *bc = &u->backchannel_ctl;
2920
	struct nfsd4_session *session = cstate->session;
2921
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2922
	__be32 status;
2923

2924 2925 2926
	status = nfsd4_check_cb_sec(&bc->bc_cb_sec);
	if (status)
		return status;
2927
	spin_lock(&nn->client_lock);
2928 2929
	session->se_cb_prog = bc->bc_cb_program;
	session->se_cb_sec = bc->bc_cb_sec;
2930
	spin_unlock(&nn->client_lock);
2931 2932 2933 2934 2935 2936

	nfsd4_probe_callback(session->se_client);

	return nfs_ok;
}

2937 2938
__be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
		     struct nfsd4_compound_state *cstate,
2939
		     union nfsd4_op_u *u)
2940
{
2941
	struct nfsd4_bind_conn_to_session *bcts = &u->bind_conn_to_session;
2942
	__be32 status;
2943
	struct nfsd4_conn *conn;
2944
	struct nfsd4_session *session;
2945 2946
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2947 2948 2949

	if (!nfsd4_last_compound_op(rqstp))
		return nfserr_not_only_op;
2950
	spin_lock(&nn->client_lock);
2951
	session = find_in_sessionid_hashtbl(&bcts->sessionid, net, &status);
2952
	spin_unlock(&nn->client_lock);
2953
	if (!session)
2954
		goto out_no_session;
2955
	status = nfserr_wrong_cred;
2956
	if (!nfsd4_mach_creds_match(session->se_client, rqstp))
2957
		goto out;
2958
	status = nfsd4_map_bcts_dir(&bcts->dir);
2959
	if (status)
2960
		goto out;
2961
	conn = alloc_conn(rqstp, bcts->dir);
2962
	status = nfserr_jukebox;
2963
	if (!conn)
2964 2965 2966 2967
		goto out;
	nfsd4_init_conn(rqstp, conn, session);
	status = nfs_ok;
out:
2968 2969
	nfsd4_put_session(session);
out_no_session:
2970
	return status;
2971 2972
}

2973
static bool nfsd4_compound_in_session(struct nfsd4_compound_state *cstate, struct nfs4_sessionid *sid)
2974
{
2975
	if (!cstate->session)
2976
		return false;
2977
	return !memcmp(sid, &cstate->session->se_sessionid, sizeof(*sid));
2978 2979
}

Andy Adamson's avatar
Andy Adamson committed
2980
__be32
2981 2982
nfsd4_destroy_session(struct svc_rqst *r, struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
Andy Adamson's avatar
Andy Adamson committed
2983
{
2984
	struct nfs4_sessionid *sessionid = &u->destroy_session.sessionid;
2985
	struct nfsd4_session *ses;
2986
	__be32 status;
2987
	int ref_held_by_me = 0;
2988 2989
	struct net *net = SVC_NET(r);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2990

2991
	status = nfserr_not_only_op;
2992
	if (nfsd4_compound_in_session(cstate, sessionid)) {
2993
		if (!nfsd4_last_compound_op(r))
2994
			goto out;
2995
		ref_held_by_me++;
2996
	}
2997
	dump_sessionid(__func__, sessionid);
2998
	spin_lock(&nn->client_lock);
2999
	ses = find_in_sessionid_hashtbl(sessionid, net, &status);
3000 3001
	if (!ses)
		goto out_client_lock;
3002
	status = nfserr_wrong_cred;
3003
	if (!nfsd4_mach_creds_match(ses->se_client, r))
3004
		goto out_put_session;
3005
	status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
3006
	if (status)
3007
		goto out_put_session;
3008
	unhash_session(ses);
3009
	spin_unlock(&nn->client_lock);
3010

3011
	nfsd4_probe_callback_sync(ses->se_client);
3012

3013
	spin_lock(&nn->client_lock);
3014
	status = nfs_ok;
3015
out_put_session:
3016
	nfsd4_put_session_locked(ses);
3017 3018
out_client_lock:
	spin_unlock(&nn->client_lock);
3019 3020
out:
	return status;
Andy Adamson's avatar
Andy Adamson committed
3021 3022
}

3023
static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
3024 3025 3026 3027
{
	struct nfsd4_conn *c;

	list_for_each_entry(c, &s->se_conns, cn_persession) {
3028
		if (c->cn_xprt == xpt) {
3029 3030 3031 3032 3033 3034
			return c;
		}
	}
	return NULL;
}

3035
static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
3036 3037
{
	struct nfs4_client *clp = ses->se_client;
3038
	struct nfsd4_conn *c;
3039
	__be32 status = nfs_ok;
3040
	int ret;
3041 3042

	spin_lock(&clp->cl_lock);
3043
	c = __nfsd4_find_conn(new->cn_xprt, ses);
3044 3045 3046 3047 3048
	if (c)
		goto out_free;
	status = nfserr_conn_not_bound_to_session;
	if (clp->cl_mach_cred)
		goto out_free;
3049 3050
	__nfsd4_hash_conn(new, ses);
	spin_unlock(&clp->cl_lock);
3051 3052 3053 3054
	ret = nfsd4_register_conn(new);
	if (ret)
		/* oops; xprt is already down: */
		nfsd4_conn_lost(&new->cn_xpt_user);
3055 3056 3057 3058 3059
	return nfs_ok;
out_free:
	spin_unlock(&clp->cl_lock);
	free_conn(new);
	return status;
3060 3061
}

3062 3063 3064 3065 3066 3067 3068
static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session)
{
	struct nfsd4_compoundargs *args = rqstp->rq_argp;

	return args->opcnt > session->se_fchannel.maxops;
}

3069 3070 3071 3072 3073 3074 3075 3076
static bool nfsd4_request_too_big(struct svc_rqst *rqstp,
				  struct nfsd4_session *session)
{
	struct xdr_buf *xb = &rqstp->rq_arg;

	return xb->len > session->se_fchannel.maxreq_sz;
}

3077 3078 3079 3080 3081 3082 3083 3084 3085
static bool replay_matches_cache(struct svc_rqst *rqstp,
		 struct nfsd4_sequence *seq, struct nfsd4_slot *slot)
{
	struct nfsd4_compoundargs *argp = rqstp->rq_argp;

	if ((bool)(slot->sl_flags & NFSD4_SLOT_CACHETHIS) !=
	    (bool)seq->cachethis)
		return false;
	/*
3086 3087
	 * If there's an error then the reply can have fewer ops than
	 * the call.
3088
	 */
3089 3090 3091 3092 3093 3094 3095 3096
	if (slot->sl_opcnt < argp->opcnt && !slot->sl_status)
		return false;
	/*
	 * But if we cached a reply with *more* ops than the call you're
	 * sending us now, then this new call is clearly not really a
	 * replay of the old one:
	 */
	if (slot->sl_opcnt > argp->opcnt)
3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109
		return false;
	/* This is the only check explicitly called by spec: */
	if (!same_creds(&rqstp->rq_cred, &slot->sl_cred))
		return false;
	/*
	 * There may be more comparisons we could actually do, but the
	 * spec doesn't require us to catch every case where the calls
	 * don't match (that would require caching the call as well as
	 * the reply), so we don't bother.
	 */
	return true;
}

Andy Adamson's avatar
Andy Adamson committed
3110
__be32
3111 3112
nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
Andy Adamson's avatar
Andy Adamson committed
3113
{
3114
	struct nfsd4_sequence *seq = &u->sequence;
3115
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
3116
	struct xdr_stream *xdr = &resp->xdr;
Benny Halevy's avatar
Benny Halevy committed
3117
	struct nfsd4_session *session;
3118
	struct nfs4_client *clp;
Benny Halevy's avatar
Benny Halevy committed
3119
	struct nfsd4_slot *slot;
3120
	struct nfsd4_conn *conn;
J. Bruce Fields's avatar
J. Bruce Fields committed
3121
	__be32 status;
3122
	int buflen;
3123 3124
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
Benny Halevy's avatar
Benny Halevy committed
3125

3126 3127 3128
	if (resp->opcnt != 1)
		return nfserr_sequence_pos;

3129 3130 3131 3132 3133 3134 3135 3136
	/*
	 * Will be either used or freed by nfsd4_sequence_check_conn
	 * below.
	 */
	conn = alloc_conn(rqstp, NFS4_CDFC4_FORE);
	if (!conn)
		return nfserr_jukebox;

3137
	spin_lock(&nn->client_lock);
3138
	session = find_in_sessionid_hashtbl(&seq->sessionid, net, &status);
Benny Halevy's avatar
Benny Halevy committed
3139
	if (!session)
3140 3141
		goto out_no_session;
	clp = session->se_client;
Benny Halevy's avatar
Benny Halevy committed
3142

3143 3144
	status = nfserr_too_many_ops;
	if (nfsd4_session_too_many_ops(rqstp, session))
3145
		goto out_put_session;
3146

3147 3148
	status = nfserr_req_too_big;
	if (nfsd4_request_too_big(rqstp, session))
3149
		goto out_put_session;
3150

Benny Halevy's avatar
Benny Halevy committed
3151
	status = nfserr_badslot;
3152
	if (seq->slotid >= session->se_fchannel.maxreqs)
3153
		goto out_put_session;
Benny Halevy's avatar
Benny Halevy committed
3154

3155
	slot = session->se_slots[seq->slotid];
Benny Halevy's avatar
Benny Halevy committed
3156 3157
	dprintk("%s: slotid %d\n", __func__, seq->slotid);

3158 3159 3160 3161 3162
	/* We do not negotiate the number of slots yet, so set the
	 * maxslots to the session maxreqs which is used to encode
	 * sr_highest_slotid and the sr_target_slot id to maxslots */
	seq->maxslots = session->se_fchannel.maxreqs;

3163 3164
	status = check_slot_seqid(seq->seqid, slot->sl_seqid,
					slot->sl_flags & NFSD4_SLOT_INUSE);
Benny Halevy's avatar
Benny Halevy committed
3165
	if (status == nfserr_replay_cache) {
3166 3167
		status = nfserr_seq_misordered;
		if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
3168
			goto out_put_session;
3169 3170 3171
		status = nfserr_seq_false_retry;
		if (!replay_matches_cache(rqstp, seq, slot))
			goto out_put_session;
Benny Halevy's avatar
Benny Halevy committed
3172 3173
		cstate->slot = slot;
		cstate->session = session;
3174
		cstate->clp = clp;
Andy Adamson's avatar
Andy Adamson committed
3175
		/* Return the cached reply status and set cstate->status
3176
		 * for nfsd4_proc_compound processing */
3177
		status = nfsd4_replay_cache_entry(resp, seq);
Andy Adamson's avatar
Andy Adamson committed
3178
		cstate->status = nfserr_replay_cache;
3179
		goto out;
Benny Halevy's avatar
Benny Halevy committed
3180 3181
	}
	if (status)
3182
		goto out_put_session;
Benny Halevy's avatar
Benny Halevy committed
3183

3184
	status = nfsd4_sequence_check_conn(conn, session);
3185
	conn = NULL;
3186 3187
	if (status)
		goto out_put_session;
3188

3189 3190 3191 3192 3193
	buflen = (seq->cachethis) ?
			session->se_fchannel.maxresp_cached :
			session->se_fchannel.maxresp_sz;
	status = (seq->cachethis) ? nfserr_rep_too_big_to_cache :
				    nfserr_rep_too_big;
3194
	if (xdr_restrict_buflen(xdr, buflen - rqstp->rq_auth_slack))
3195
		goto out_put_session;
3196
	svc_reserve(rqstp, buflen);
3197 3198

	status = nfs_ok;
Benny Halevy's avatar
Benny Halevy committed
3199 3200
	/* Success! bump slot seqid */
	slot->sl_seqid = seq->seqid;
3201
	slot->sl_flags |= NFSD4_SLOT_INUSE;
3202 3203
	if (seq->cachethis)
		slot->sl_flags |= NFSD4_SLOT_CACHETHIS;
3204 3205
	else
		slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
Benny Halevy's avatar
Benny Halevy committed
3206 3207 3208

	cstate->slot = slot;
	cstate->session = session;
3209
	cstate->clp = clp;
Benny Halevy's avatar
Benny Halevy committed
3210 3211

out:
3212 3213 3214 3215 3216 3217 3218 3219 3220
	switch (clp->cl_cb_state) {
	case NFSD4_CB_DOWN:
		seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN;
		break;
	case NFSD4_CB_FAULT:
		seq->status_flags = SEQ4_STATUS_BACKCHANNEL_FAULT;
		break;
	default:
		seq->status_flags = 0;
3221
	}
3222 3223
	if (!list_empty(&clp->cl_revoked))
		seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED;
3224
out_no_session:
3225 3226
	if (conn)
		free_conn(conn);
3227
	spin_unlock(&nn->client_lock);
Benny Halevy's avatar
Benny Halevy committed
3228
	return status;
3229
out_put_session:
3230
	nfsd4_put_session_locked(session);
3231
	goto out_no_session;
Andy Adamson's avatar
Andy Adamson committed
3232 3233
}

3234 3235 3236 3237 3238 3239 3240 3241 3242 3243
void
nfsd4_sequence_done(struct nfsd4_compoundres *resp)
{
	struct nfsd4_compound_state *cs = &resp->cstate;

	if (nfsd4_has_session(cs)) {
		if (cs->status != nfserr_replay_cache) {
			nfsd4_store_cache_entry(resp);
			cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
		}
3244
		/* Drop session reference that was taken in nfsd4_sequence() */
3245
		nfsd4_put_session(cs->session);
3246 3247
	} else if (cs->clp)
		put_client_renew(cs->clp);
3248 3249
}

3250
__be32
3251 3252 3253
nfsd4_destroy_clientid(struct svc_rqst *rqstp,
		struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
3254
{
3255
	struct nfsd4_destroy_clientid *dc = &u->destroy_clientid;
3256 3257
	struct nfs4_client *conf, *unconf;
	struct nfs4_client *clp = NULL;
J. Bruce Fields's avatar
J. Bruce Fields committed
3258
	__be32 status = 0;
3259
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
3260

3261
	spin_lock(&nn->client_lock);
3262
	unconf = find_unconfirmed_client(&dc->clientid, true, nn);
3263
	conf = find_confirmed_client(&dc->clientid, true, nn);
3264
	WARN_ON_ONCE(conf && unconf);
3265 3266

	if (conf) {
3267
		if (client_has_state(conf)) {
3268 3269 3270
			status = nfserr_clientid_busy;
			goto out;
		}
3271 3272 3273
		status = mark_client_expired_locked(conf);
		if (status)
			goto out;
3274
		clp = conf;
3275 3276 3277 3278 3279 3280
	} else if (unconf)
		clp = unconf;
	else {
		status = nfserr_stale_clientid;
		goto out;
	}
3281
	if (!nfsd4_mach_creds_match(clp, rqstp)) {
3282
		clp = NULL;
3283 3284 3285
		status = nfserr_wrong_cred;
		goto out;
	}
3286
	unhash_client_locked(clp);
3287
out:
3288 3289 3290
	spin_unlock(&nn->client_lock);
	if (clp)
		expire_client(clp);
3291 3292 3293
	return status;
}

3294
__be32
3295 3296
nfsd4_reclaim_complete(struct svc_rqst *rqstp,
		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
3297
{
3298
	struct nfsd4_reclaim_complete *rc = &u->reclaim_complete;
J. Bruce Fields's avatar
J. Bruce Fields committed
3299
	__be32 status = 0;
3300

3301 3302 3303 3304 3305 3306 3307
	if (rc->rca_one_fs) {
		if (!cstate->current_fh.fh_dentry)
			return nfserr_nofilehandle;
		/*
		 * We don't take advantage of the rca_one_fs case.
		 * That's OK, it's optional, we can safely ignore it.
		 */
3308
		return nfs_ok;
3309
	}
3310 3311

	status = nfserr_complete_already;
3312 3313
	if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
			     &cstate->session->se_client->cl_flags))
3314 3315 3316 3317
		goto out;

	status = nfserr_stale_clientid;
	if (is_client_expired(cstate->session->se_client))
3318 3319 3320 3321 3322 3323 3324
		/*
		 * The following error isn't really legal.
		 * But we only get here if the client just explicitly
		 * destroyed the client.  Surely it no longer cares what
		 * error it gets back on an operation for the dead
		 * client.
		 */
3325 3326 3327
		goto out;

	status = nfs_ok;
3328
	nfsd4_client_record_create(cstate->session->se_client);
3329 3330
out:
	return status;
3331 3332
}

3333
__be32
3334
nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3335
		  union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
3336
{
3337
	struct nfsd4_setclientid *setclid = &u->setclientid;
3338
	struct xdr_netobj 	clname = setclid->se_name;
Linus Torvalds's avatar
Linus Torvalds committed
3339
	nfs4_verifier		clverifier = setclid->se_verf;
3340 3341
	struct nfs4_client	*conf, *new;
	struct nfs4_client	*unconf = NULL;
3342
	__be32 			status;
3343 3344
	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);

3345 3346 3347
	new = create_client(clname, rqstp, &clverifier);
	if (new == NULL)
		return nfserr_jukebox;
3348
	/* Cases below refer to rfc 3530 section 14.2.33: */
3349
	spin_lock(&nn->client_lock);
3350
	conf = find_confirmed_client_by_name(&clname, nn);
3351
	if (conf && client_has_state(conf)) {
3352
		/* case 0: */
Linus Torvalds's avatar
Linus Torvalds committed
3353
		status = nfserr_clid_inuse;
3354 3355
		if (clp_used_exchangeid(conf))
			goto out;
3356
		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
3357 3358 3359 3360 3361
			char addr_str[INET6_ADDRSTRLEN];
			rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str,
				 sizeof(addr_str));
			dprintk("NFSD: setclientid: string in use by client "
				"at %s\n", addr_str);
Linus Torvalds's avatar
Linus Torvalds committed
3362 3363 3364
			goto out;
		}
	}
3365
	unconf = find_unconfirmed_client_by_name(&clname, nn);
3366
	if (unconf)
3367
		unhash_client_locked(unconf);
3368
	if (conf && same_verf(&conf->cl_verifier, &clverifier)) {
3369
		/* case 1: probable callback update */
Linus Torvalds's avatar
Linus Torvalds committed
3370
		copy_clid(new, conf);
3371 3372
		gen_confirm(new, nn);
	} else /* case 4 (new client) or cases 2, 3 (client reboot): */
3373
		gen_clid(new, nn);
3374
	new->cl_minorversion = 0;
3375
	gen_callback(new, setclid, rqstp);
3376
	add_to_unconfirmed(new);
Linus Torvalds's avatar
Linus Torvalds committed
3377 3378 3379
	setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
	setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
	memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));
3380
	new = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
3381 3382
	status = nfs_ok;
out:
3383
	spin_unlock(&nn->client_lock);
3384 3385
	if (new)
		free_client(new);
3386 3387
	if (unconf)
		expire_client(unconf);
Linus Torvalds's avatar
Linus Torvalds committed
3388 3389 3390 3391
	return status;
}


3392
__be32
3393
nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
3394 3395
			struct nfsd4_compound_state *cstate,
			union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
3396
{
3397 3398
	struct nfsd4_setclientid_confirm *setclientid_confirm =
			&u->setclientid_confirm;
3399
	struct nfs4_client *conf, *unconf;
3400
	struct nfs4_client *old = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
3401 3402
	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
	clientid_t * clid = &setclientid_confirm->sc_clientid;
3403
	__be32 status;
3404
	struct nfsd_net	*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
3405

3406
	if (STALE_CLIENTID(clid, nn))
Linus Torvalds's avatar
Linus Torvalds committed
3407
		return nfserr_stale_clientid;
3408

3409
	spin_lock(&nn->client_lock);
3410
	conf = find_confirmed_client(clid, false, nn);
3411
	unconf = find_unconfirmed_client(clid, false, nn);
3412
	/*
3413 3414
	 * We try hard to give out unique clientid's, so if we get an
	 * attempt to confirm the same clientid with a different cred,
3415 3416 3417
	 * the client may be buggy; this should never happen.
	 *
	 * Nevertheless, RFC 7530 recommends INUSE for this case:
3418
	 */
3419
	status = nfserr_clid_inuse;
3420 3421 3422 3423
	if (unconf && !same_creds(&unconf->cl_cred, &rqstp->rq_cred))
		goto out;
	if (conf && !same_creds(&conf->cl_cred, &rqstp->rq_cred))
		goto out;
3424
	/* cases below refer to rfc 3530 section 14.2.34: */
3425
	if (!unconf || !same_verf(&confirm, &unconf->cl_confirm)) {
3426 3427
		if (conf && same_verf(&confirm, &conf->cl_confirm)) {
			/* case 2: probable retransmit */
Linus Torvalds's avatar
Linus Torvalds committed
3428
			status = nfs_ok;
3429
		} else /* case 4: client hasn't noticed we rebooted yet? */
3430 3431 3432 3433 3434
			status = nfserr_stale_clientid;
		goto out;
	}
	status = nfs_ok;
	if (conf) { /* case 1: callback update */
3435 3436
		old = unconf;
		unhash_client_locked(old);
3437
		nfsd4_change_callback(conf, &unconf->cl_cb_conn);
3438
	} else { /* case 3: normal case; new or rebooted client */
3439 3440
		old = find_confirmed_client_by_name(&unconf->cl_name, nn);
		if (old) {
3441 3442 3443 3444 3445
			status = nfserr_clid_inuse;
			if (client_has_state(old)
					&& !same_creds(&unconf->cl_cred,
							&old->cl_cred))
				goto out;
3446
			status = mark_client_expired_locked(old);
3447 3448
			if (status) {
				old = NULL;
3449
				goto out;
3450
			}
3451
		}
3452
		move_to_confirmed(unconf);
3453
		conf = unconf;
3454
	}
3455 3456 3457 3458 3459
	get_client_locked(conf);
	spin_unlock(&nn->client_lock);
	nfsd4_probe_callback(conf);
	spin_lock(&nn->client_lock);
	put_client_renew_locked(conf);
Linus Torvalds's avatar
Linus Torvalds committed
3460
out:
3461 3462 3463
	spin_unlock(&nn->client_lock);
	if (old)
		expire_client(old);
Linus Torvalds's avatar
Linus Torvalds committed
3464 3465 3466
	return status;
}

3467 3468 3469 3470 3471
static struct nfs4_file *nfsd4_alloc_file(void)
{
	return kmem_cache_alloc(file_slab, GFP_KERNEL);
}

Linus Torvalds's avatar
Linus Torvalds committed
3472
/* OPEN Share state helper functions */
3473 3474
static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval,
				struct nfs4_file *fp)
Linus Torvalds's avatar
Linus Torvalds committed
3475
{
3476 3477
	lockdep_assert_held(&state_lock);

3478
	refcount_set(&fp->fi_ref, 1);
3479
	spin_lock_init(&fp->fi_lock);
3480 3481
	INIT_LIST_HEAD(&fp->fi_stateids);
	INIT_LIST_HEAD(&fp->fi_delegations);
3482
	INIT_LIST_HEAD(&fp->fi_clnt_odstate);
3483
	fh_copy_shallow(&fp->fi_fhandle, fh);
3484
	fp->fi_deleg_file = NULL;
3485
	fp->fi_had_conflict = false;
3486
	fp->fi_share_deny = 0;
3487 3488
	memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
	memset(fp->fi_access, 0, sizeof(fp->fi_access));
3489 3490
#ifdef CONFIG_NFSD_PNFS
	INIT_LIST_HEAD(&fp->fi_lo_states);
3491
	atomic_set(&fp->fi_lo_recalls, 0);
3492
#endif
3493
	hlist_add_head_rcu(&fp->fi_hash, &file_hashtbl[hashval]);
Linus Torvalds's avatar
Linus Torvalds committed
3494 3495
}

3496
void
Linus Torvalds's avatar
Linus Torvalds committed
3497 3498
nfsd4_free_slabs(void)
{
3499
	kmem_cache_destroy(client_slab);
3500 3501 3502 3503 3504
	kmem_cache_destroy(openowner_slab);
	kmem_cache_destroy(lockowner_slab);
	kmem_cache_destroy(file_slab);
	kmem_cache_destroy(stateid_slab);
	kmem_cache_destroy(deleg_slab);
3505
	kmem_cache_destroy(odstate_slab);
3506
}
Linus Torvalds's avatar
Linus Torvalds committed
3507

3508
int
3509 3510
nfsd4_init_slabs(void)
{
3511 3512 3513 3514
	client_slab = kmem_cache_create("nfsd4_clients",
			sizeof(struct nfs4_client), 0, 0, NULL);
	if (client_slab == NULL)
		goto out;
3515 3516 3517
	openowner_slab = kmem_cache_create("nfsd4_openowners",
			sizeof(struct nfs4_openowner), 0, 0, NULL);
	if (openowner_slab == NULL)
3518
		goto out_free_client_slab;
3519
	lockowner_slab = kmem_cache_create("nfsd4_lockowners",
3520
			sizeof(struct nfs4_lockowner), 0, 0, NULL);
3521
	if (lockowner_slab == NULL)
3522
		goto out_free_openowner_slab;
3523
	file_slab = kmem_cache_create("nfsd4_files",
3524
			sizeof(struct nfs4_file), 0, 0, NULL);
3525
	if (file_slab == NULL)
3526
		goto out_free_lockowner_slab;
NeilBrown's avatar
NeilBrown committed
3527
	stateid_slab = kmem_cache_create("nfsd4_stateids",
3528
			sizeof(struct nfs4_ol_stateid), 0, 0, NULL);
NeilBrown's avatar
NeilBrown committed
3529
	if (stateid_slab == NULL)
3530
		goto out_free_file_slab;
3531
	deleg_slab = kmem_cache_create("nfsd4_delegations",
3532
			sizeof(struct nfs4_delegation), 0, 0, NULL);
3533
	if (deleg_slab == NULL)
3534
		goto out_free_stateid_slab;
3535 3536 3537 3538
	odstate_slab = kmem_cache_create("nfsd4_odstate",
			sizeof(struct nfs4_clnt_odstate), 0, 0, NULL);
	if (odstate_slab == NULL)
		goto out_free_deleg_slab;
3539
	return 0;
3540

3541 3542
out_free_deleg_slab:
	kmem_cache_destroy(deleg_slab);
3543 3544 3545 3546 3547 3548 3549 3550
out_free_stateid_slab:
	kmem_cache_destroy(stateid_slab);
out_free_file_slab:
	kmem_cache_destroy(file_slab);
out_free_lockowner_slab:
	kmem_cache_destroy(lockowner_slab);
out_free_openowner_slab:
	kmem_cache_destroy(openowner_slab);
3551 3552
out_free_client_slab:
	kmem_cache_destroy(client_slab);
3553
out:
3554 3555
	dprintk("nfsd4: out of memory while initializing nfsv4\n");
	return -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
3556 3557
}

3558
static void init_nfs4_replay(struct nfs4_replay *rp)
Linus Torvalds's avatar
Linus Torvalds committed
3559
{
3560 3561 3562
	rp->rp_status = nfserr_serverfault;
	rp->rp_buflen = 0;
	rp->rp_buf = rp->rp_ibuf;
3563 3564 3565 3566 3567 3568 3569 3570
	mutex_init(&rp->rp_mutex);
}

static void nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate,
		struct nfs4_stateowner *so)
{
	if (!nfsd4_has_session(cstate)) {
		mutex_lock(&so->so_replay.rp_mutex);
3571
		cstate->replay_owner = nfs4_get_stateowner(so);
3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
	}
}

void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate)
{
	struct nfs4_stateowner *so = cstate->replay_owner;

	if (so != NULL) {
		cstate->replay_owner = NULL;
		mutex_unlock(&so->so_replay.rp_mutex);
		nfs4_put_stateowner(so);
	}
Linus Torvalds's avatar
Linus Torvalds committed
3584 3585
}

3586
static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj *owner, struct nfs4_client *clp)
3587
{
Linus Torvalds's avatar
Linus Torvalds committed
3588 3589
	struct nfs4_stateowner *sop;

3590
	sop = kmem_cache_alloc(slab, GFP_KERNEL);
3591 3592 3593 3594 3595
	if (!sop)
		return NULL;

	sop->so_owner.data = kmemdup(owner->data, owner->len, GFP_KERNEL);
	if (!sop->so_owner.data) {
3596
		kmem_cache_free(slab, sop);
Linus Torvalds's avatar
Linus Torvalds committed
3597
		return NULL;
3598 3599 3600
	}
	sop->so_owner.len = owner->len;

3601
	INIT_LIST_HEAD(&sop->so_stateids);
3602 3603
	sop->so_client = clp;
	init_nfs4_replay(&sop->so_replay);
3604
	atomic_set(&sop->so_count, 1);
3605 3606 3607
	return sop;
}

3608
static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
3609
{
3610
	lockdep_assert_held(&clp->cl_lock);
3611

3612 3613
	list_add(&oo->oo_owner.so_strhash,
		 &clp->cl_ownerstr_hashtbl[strhashval]);
3614
	list_add(&oo->oo_perclient, &clp->cl_openowners);
3615 3616
}

3617 3618
static void nfs4_unhash_openowner(struct nfs4_stateowner *so)
{
3619
	unhash_openowner_locked(openowner(so));
3620 3621
}

3622 3623 3624 3625 3626 3627 3628 3629
static void nfs4_free_openowner(struct nfs4_stateowner *so)
{
	struct nfs4_openowner *oo = openowner(so);

	kmem_cache_free(openowner_slab, oo);
}

static const struct nfs4_stateowner_operations openowner_ops = {
3630 3631
	.so_unhash =	nfs4_unhash_openowner,
	.so_free =	nfs4_free_openowner,
3632 3633
};

3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645
static struct nfs4_ol_stateid *
nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
{
	struct nfs4_ol_stateid *local, *ret = NULL;
	struct nfs4_openowner *oo = open->op_openowner;

	lockdep_assert_held(&fp->fi_lock);

	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
		/* ignore lock owners */
		if (local->st_stateowner->so_is_open_owner == 0)
			continue;
3646 3647 3648
		if (local->st_stateowner != &oo->oo_owner)
			continue;
		if (local->st_stid.sc_type == NFS4_OPEN_STID) {
3649
			ret = local;
3650
			refcount_inc(&ret->st_stid.sc_count);
3651 3652 3653 3654 3655 3656
			break;
		}
	}
	return ret;
}

3657 3658 3659 3660 3661 3662 3663 3664
static __be32
nfsd4_verify_open_stid(struct nfs4_stid *s)
{
	__be32 ret = nfs_ok;

	switch (s->sc_type) {
	default:
		break;
3665
	case 0:
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681
	case NFS4_CLOSED_STID:
	case NFS4_CLOSED_DELEG_STID:
		ret = nfserr_bad_stateid;
		break;
	case NFS4_REVOKED_DELEG_STID:
		ret = nfserr_deleg_revoked;
	}
	return ret;
}

/* Lock the stateid st_mutex, and deal with races with CLOSE */
static __be32
nfsd4_lock_ol_stateid(struct nfs4_ol_stateid *stp)
{
	__be32 ret;

3682
	mutex_lock_nested(&stp->st_mutex, LOCK_STATEID_MUTEX);
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703
	ret = nfsd4_verify_open_stid(&stp->st_stid);
	if (ret != nfs_ok)
		mutex_unlock(&stp->st_mutex);
	return ret;
}

static struct nfs4_ol_stateid *
nfsd4_find_and_lock_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
{
	struct nfs4_ol_stateid *stp;
	for (;;) {
		spin_lock(&fp->fi_lock);
		stp = nfsd4_find_existing_open(fp, open);
		spin_unlock(&fp->fi_lock);
		if (!stp || nfsd4_lock_ol_stateid(stp) == nfs_ok)
			break;
		nfs4_put_stid(&stp->st_stid);
	}
	return stp;
}

3704
static struct nfs4_openowner *
3705
alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
3706 3707
			   struct nfsd4_compound_state *cstate)
{
3708
	struct nfs4_client *clp = cstate->clp;
3709
	struct nfs4_openowner *oo, *ret;
3710

3711 3712
	oo = alloc_stateowner(openowner_slab, &open->op_owner, clp);
	if (!oo)
3713
		return NULL;
3714
	oo->oo_owner.so_ops = &openowner_ops;
3715 3716
	oo->oo_owner.so_is_open_owner = 1;
	oo->oo_owner.so_seqid = open->op_seqid;
3717
	oo->oo_flags = 0;
3718 3719
	if (nfsd4_has_session(cstate))
		oo->oo_flags |= NFS4_OO_CONFIRMED;
3720
	oo->oo_time = 0;
3721
	oo->oo_last_closed_stid = NULL;
3722
	INIT_LIST_HEAD(&oo->oo_close_lru);
3723 3724
	spin_lock(&clp->cl_lock);
	ret = find_openstateowner_str_locked(strhashval, open, clp);
3725 3726 3727 3728
	if (ret == NULL) {
		hash_openowner(oo, clp, strhashval);
		ret = oo;
	} else
3729 3730
		nfs4_free_stateowner(&oo->oo_owner);

3731
	spin_unlock(&clp->cl_lock);
3732
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
3733 3734
}

3735
static struct nfs4_ol_stateid *
3736
init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
3737 3738
{

3739
	struct nfs4_openowner *oo = open->op_openowner;
3740
	struct nfs4_ol_stateid *retstp = NULL;
3741
	struct nfs4_ol_stateid *stp;
Linus Torvalds's avatar
Linus Torvalds committed
3742

3743
	stp = open->op_stp;
3744 3745
	/* We are moving these outside of the spinlocks to avoid the warnings */
	mutex_init(&stp->st_mutex);
3746
	mutex_lock_nested(&stp->st_mutex, OPEN_STATEID_MUTEX);
3747

3748
retry:
3749 3750 3751 3752 3753 3754
	spin_lock(&oo->oo_owner.so_client->cl_lock);
	spin_lock(&fp->fi_lock);

	retstp = nfsd4_find_existing_open(fp, open);
	if (retstp)
		goto out_unlock;
3755 3756

	open->op_stp = NULL;
3757
	refcount_inc(&stp->st_stid.sc_count);
3758
	stp->st_stid.sc_type = NFS4_OPEN_STID;
3759
	INIT_LIST_HEAD(&stp->st_locks);
3760
	stp->st_stateowner = nfs4_get_stateowner(&oo->oo_owner);
3761
	get_nfs4_file(fp);
3762
	stp->st_stid.sc_file = fp;
Linus Torvalds's avatar
Linus Torvalds committed
3763 3764
	stp->st_access_bmap = 0;
	stp->st_deny_bmap = 0;
3765
	stp->st_openstp = NULL;
3766
	list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
3767
	list_add(&stp->st_perfile, &fp->fi_stateids);
3768 3769

out_unlock:
3770
	spin_unlock(&fp->fi_lock);
3771
	spin_unlock(&oo->oo_owner.so_client->cl_lock);
3772
	if (retstp) {
3773 3774 3775 3776 3777
		/* Handle races with CLOSE */
		if (nfsd4_lock_ol_stateid(retstp) != nfs_ok) {
			nfs4_put_stid(&retstp->st_stid);
			goto retry;
		}
3778
		/* To keep mutex tracking happy */
3779
		mutex_unlock(&stp->st_mutex);
3780
		stp = retstp;
3781
	}
3782
	return stp;
Linus Torvalds's avatar
Linus Torvalds committed
3783 3784
}

3785 3786 3787 3788 3789
/*
 * In the 4.0 case we need to keep the owners around a little while to handle
 * CLOSE replay. We still do need to release any file access that is held by
 * them before returning however.
 */
3790
static void
3791
move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net)
Linus Torvalds's avatar
Linus Torvalds committed
3792
{
3793
	struct nfs4_ol_stateid *last;
3794 3795 3796
	struct nfs4_openowner *oo = openowner(s->st_stateowner);
	struct nfsd_net *nn = net_generic(s->st_stid.sc_client->net,
						nfsd_net_id);
3797

3798
	dprintk("NFSD: move_to_close_lru nfs4_openowner %p\n", oo);
Linus Torvalds's avatar
Linus Torvalds committed
3799

3800 3801 3802 3803 3804 3805 3806 3807 3808
	/*
	 * We know that we hold one reference via nfsd4_close, and another
	 * "persistent" reference for the client. If the refcount is higher
	 * than 2, then there are still calls in progress that are using this
	 * stateid. We can't put the sc_file reference until they are finished.
	 * Wait for the refcount to drop to 2. Since it has been unhashed,
	 * there should be no danger of the refcount going back up again at
	 * this point.
	 */
3809
	wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2);
3810

3811 3812 3813 3814 3815
	release_all_access(s);
	if (s->st_stid.sc_file) {
		put_nfs4_file(s->st_stid.sc_file);
		s->st_stid.sc_file = NULL;
	}
3816 3817 3818

	spin_lock(&nn->client_lock);
	last = oo->oo_last_closed_stid;
3819
	oo->oo_last_closed_stid = s;
3820
	list_move_tail(&oo->oo_close_lru, &nn->close_lru);
3821
	oo->oo_time = get_seconds();
3822 3823 3824
	spin_unlock(&nn->client_lock);
	if (last)
		nfs4_put_stid(&last->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
3825 3826 3827 3828
}

/* search file_hashtbl[] for file */
static struct nfs4_file *
3829
find_file_locked(struct knfsd_fh *fh, unsigned int hashval)
Linus Torvalds's avatar
Linus Torvalds committed
3830 3831 3832
{
	struct nfs4_file *fp;

3833
	hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) {
3834
		if (fh_match(&fp->fi_fhandle, fh)) {
3835
			if (refcount_inc_not_zero(&fp->fi_ref))
3836
				return fp;
3837
		}
Linus Torvalds's avatar
Linus Torvalds committed
3838 3839 3840 3841
	}
	return NULL;
}

3842
struct nfs4_file *
3843
find_file(struct knfsd_fh *fh)
3844 3845
{
	struct nfs4_file *fp;
3846
	unsigned int hashval = file_hashval(fh);
3847

3848 3849 3850
	rcu_read_lock();
	fp = find_file_locked(fh, hashval);
	rcu_read_unlock();
3851 3852 3853 3854
	return fp;
}

static struct nfs4_file *
3855
find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh)
3856 3857
{
	struct nfs4_file *fp;
3858 3859 3860 3861 3862 3863 3864
	unsigned int hashval = file_hashval(fh);

	rcu_read_lock();
	fp = find_file_locked(fh, hashval);
	rcu_read_unlock();
	if (fp)
		return fp;
3865 3866

	spin_lock(&state_lock);
3867 3868 3869
	fp = find_file_locked(fh, hashval);
	if (likely(fp == NULL)) {
		nfsd4_init_file(fh, hashval, new);
3870 3871 3872 3873 3874 3875 3876
		fp = new;
	}
	spin_unlock(&state_lock);

	return fp;
}

Linus Torvalds's avatar
Linus Torvalds committed
3877 3878 3879 3880
/*
 * Called to check deny when READ with all zero stateid or
 * WRITE with all zero or all one stateid
 */
3881
static __be32
Linus Torvalds's avatar
Linus Torvalds committed
3882 3883 3884
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{
	struct nfs4_file *fp;
3885
	__be32 ret = nfs_ok;
Linus Torvalds's avatar
Linus Torvalds committed
3886

3887
	fp = find_file(&current_fh->fh_handle);
3888
	if (!fp)
3889 3890
		return ret;
	/* Check for conflicting share reservations */
3891
	spin_lock(&fp->fi_lock);
3892 3893
	if (fp->fi_share_deny & deny_type)
		ret = nfserr_locked;
3894
	spin_unlock(&fp->fi_lock);
3895 3896
	put_nfs4_file(fp);
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
3897 3898
}

3899
static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb)
Linus Torvalds's avatar
Linus Torvalds committed
3900
{
3901
	struct nfs4_delegation *dp = cb_to_delegation(cb);
3902 3903
	struct nfsd_net *nn = net_generic(dp->dl_stid.sc_client->net,
					  nfsd_net_id);
3904

3905
	block_delegations(&dp->dl_stid.sc_file->fi_fhandle);
3906

3907
	/*
3908 3909 3910
	 * We can't do this in nfsd_break_deleg_cb because it is
	 * already holding inode->i_lock.
	 *
3911 3912 3913
	 * If the dl_time != 0, then we know that it has already been
	 * queued for a lease break. Don't queue it again.
	 */
3914
	spin_lock(&state_lock);
3915 3916
	if (dp->dl_time == 0) {
		dp->dl_time = get_seconds();
3917
		list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru);
3918
	}
3919 3920
	spin_unlock(&state_lock);
}
Linus Torvalds's avatar
Linus Torvalds committed
3921

3922 3923 3924 3925 3926
static int nfsd4_cb_recall_done(struct nfsd4_callback *cb,
		struct rpc_task *task)
{
	struct nfs4_delegation *dp = cb_to_delegation(cb);

3927 3928 3929
	if (dp->dl_stid.sc_type == NFS4_CLOSED_DELEG_STID)
	        return 1;

3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955
	switch (task->tk_status) {
	case 0:
		return 1;
	case -EBADHANDLE:
	case -NFS4ERR_BAD_STATEID:
		/*
		 * Race: client probably got cb_recall before open reply
		 * granting delegation.
		 */
		if (dp->dl_retries--) {
			rpc_delay(task, 2 * HZ);
			return 0;
		}
		/*FALLTHRU*/
	default:
		return -1;
	}
}

static void nfsd4_cb_recall_release(struct nfsd4_callback *cb)
{
	struct nfs4_delegation *dp = cb_to_delegation(cb);

	nfs4_put_stid(&dp->dl_stid);
}

3956
static const struct nfsd4_callback_ops nfsd4_cb_recall_ops = {
3957 3958 3959 3960 3961
	.prepare	= nfsd4_cb_recall_prepare,
	.done		= nfsd4_cb_recall_done,
	.release	= nfsd4_cb_recall_release,
};

3962 3963 3964 3965 3966
static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
{
	/*
	 * We're assuming the state code never drops its reference
	 * without first removing the lease.  Since we're in this lease
3967 3968 3969
	 * callback (and since the lease code is serialized by the
	 * i_lock) we know the server hasn't removed the lease yet, and
	 * we know it's safe to take a reference.
3970
	 */
3971
	refcount_inc(&dp->dl_stid.sc_count);
3972
	nfsd4_run_cb(&dp->dl_recall);
3973 3974
}

3975
/* Called from break_lease() with i_lock held. */
3976 3977
static bool
nfsd_break_deleg_cb(struct file_lock *fl)
3978
{
3979
	bool ret = false;
3980 3981
	struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
	struct nfs4_file *fp = dp->dl_stid.sc_file;
3982

3983 3984
	/*
	 * We don't want the locks code to timeout the lease for us;
3985
	 * we'll remove it ourself if a delegation isn't returned
3986
	 * in time:
3987 3988
	 */
	fl->fl_break_time = 0;
Linus Torvalds's avatar
Linus Torvalds committed
3989

3990
	spin_lock(&fp->fi_lock);
3991
	fp->fi_had_conflict = true;
3992
	nfsd_break_one_deleg(dp);
3993
	spin_unlock(&fp->fi_lock);
3994
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
3995 3996
}

3997
static int
3998 3999
nfsd_change_deleg_cb(struct file_lock *onlist, int arg,
		     struct list_head *dispose)
Linus Torvalds's avatar
Linus Torvalds committed
4000 4001
{
	if (arg & F_UNLCK)
4002
		return lease_modify(onlist, arg, dispose);
Linus Torvalds's avatar
Linus Torvalds committed
4003 4004 4005 4006
	else
		return -EAGAIN;
}

4007
static const struct lock_manager_operations nfsd_lease_mng_ops = {
4008 4009
	.lm_break = nfsd_break_deleg_cb,
	.lm_change = nfsd_change_deleg_cb,
Linus Torvalds's avatar
Linus Torvalds committed
4010 4011
};

4012 4013 4014 4015 4016 4017 4018 4019 4020 4021
static __be32 nfsd4_check_seqid(struct nfsd4_compound_state *cstate, struct nfs4_stateowner *so, u32 seqid)
{
	if (nfsd4_has_session(cstate))
		return nfs_ok;
	if (seqid == so->so_seqid - 1)
		return nfserr_replay_me;
	if (seqid == so->so_seqid)
		return nfs_ok;
	return nfserr_bad_seqid;
}
Linus Torvalds's avatar
Linus Torvalds committed
4022

4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044
static __be32 lookup_clientid(clientid_t *clid,
		struct nfsd4_compound_state *cstate,
		struct nfsd_net *nn)
{
	struct nfs4_client *found;

	if (cstate->clp) {
		found = cstate->clp;
		if (!same_clid(&found->cl_clientid, clid))
			return nfserr_stale_clientid;
		return nfs_ok;
	}

	if (STALE_CLIENTID(clid, nn))
		return nfserr_stale_clientid;

	/*
	 * For v4.1+ we get the client in the SEQUENCE op. If we don't have one
	 * cached already then we know this is for is for v4.0 and "sessions"
	 * will be false.
	 */
	WARN_ON_ONCE(cstate->session);
4045
	spin_lock(&nn->client_lock);
4046
	found = find_confirmed_client(clid, false, nn);
4047 4048
	if (!found) {
		spin_unlock(&nn->client_lock);
4049
		return nfserr_expired;
4050 4051 4052
	}
	atomic_inc(&found->cl_refcount);
	spin_unlock(&nn->client_lock);
4053 4054 4055 4056 4057 4058

	/* Cache the nfs4_client in cstate! */
	cstate->clp = found;
	return nfs_ok;
}

4059
__be32
Andy Adamson's avatar
Andy Adamson committed
4060
nfsd4_process_open1(struct nfsd4_compound_state *cstate,
4061
		    struct nfsd4_open *open, struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
4062 4063 4064 4065
{
	clientid_t *clientid = &open->op_clientid;
	struct nfs4_client *clp = NULL;
	unsigned int strhashval;
4066
	struct nfs4_openowner *oo = NULL;
4067
	__be32 status;
Linus Torvalds's avatar
Linus Torvalds committed
4068

4069
	if (STALE_CLIENTID(&open->op_clientid, nn))
Linus Torvalds's avatar
Linus Torvalds committed
4070
		return nfserr_stale_clientid;
4071 4072 4073 4074 4075 4076 4077
	/*
	 * In case we need it later, after we've already created the
	 * file and don't want to risk a further failure:
	 */
	open->op_file = nfsd4_alloc_file();
	if (open->op_file == NULL)
		return nfserr_jukebox;
Linus Torvalds's avatar
Linus Torvalds committed
4078

4079 4080 4081 4082 4083
	status = lookup_clientid(clientid, cstate, nn);
	if (status)
		return status;
	clp = cstate->clp;

4084 4085
	strhashval = ownerstr_hashval(&open->op_owner);
	oo = find_openstateowner_str(strhashval, open, clp);
4086 4087
	open->op_openowner = oo;
	if (!oo) {
4088
		goto new_owner;
Linus Torvalds's avatar
Linus Torvalds committed
4089
	}
4090
	if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
4091
		/* Replace unconfirmed owners without checking for replay. */
4092 4093
		release_openowner(oo);
		open->op_openowner = NULL;
4094
		goto new_owner;
4095
	}
4096 4097 4098 4099
	status = nfsd4_check_seqid(cstate, &oo->oo_owner, open->op_seqid);
	if (status)
		return status;
	goto alloc_stateid;
4100
new_owner:
4101
	oo = alloc_init_open_stateowner(strhashval, open, cstate);
4102 4103 4104
	if (oo == NULL)
		return nfserr_jukebox;
	open->op_openowner = oo;
4105
alloc_stateid:
4106
	open->op_stp = nfs4_alloc_open_stateid(clp);
4107 4108
	if (!open->op_stp)
		return nfserr_jukebox;
4109 4110 4111 4112 4113 4114 4115 4116

	if (nfsd4_has_session(cstate) &&
	    (cstate->current_fh.fh_export->ex_flags & NFSEXP_PNFS)) {
		open->op_odstate = alloc_clnt_odstate(clp);
		if (!open->op_odstate)
			return nfserr_jukebox;
	}

4117
	return nfs_ok;
Linus Torvalds's avatar
Linus Torvalds committed
4118 4119
}

4120
static inline __be32
4121 4122 4123 4124 4125 4126 4127 4128
nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
{
	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
		return nfserr_openmode;
	else
		return nfs_ok;
}

4129
static int share_access_to_flags(u32 share_access)
4130
{
4131
	return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE;
4132 4133
}

4134
static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, stateid_t *s)
4135
{
4136
	struct nfs4_stid *ret;
4137

4138 4139
	ret = find_stateid_by_type(cl, s,
				NFS4_DELEG_STID|NFS4_REVOKED_DELEG_STID);
4140 4141 4142
	if (!ret)
		return NULL;
	return delegstateid(ret);
4143 4144
}

4145 4146 4147 4148 4149 4150
static bool nfsd4_is_deleg_cur(struct nfsd4_open *open)
{
	return open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR ||
	       open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH;
}

4151
static __be32
4152
nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
4153 4154 4155
		struct nfs4_delegation **dp)
{
	int flags;
4156
	__be32 status = nfserr_bad_stateid;
4157
	struct nfs4_delegation *deleg;
4158

4159 4160
	deleg = find_deleg_stateid(cl, &open->op_delegate_stateid);
	if (deleg == NULL)
4161
		goto out;
4162 4163 4164 4165 4166 4167
	if (deleg->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) {
		nfs4_put_stid(&deleg->dl_stid);
		if (cl->cl_minorversion)
			status = nfserr_deleg_revoked;
		goto out;
	}
4168
	flags = share_access_to_flags(open->op_share_access);
4169 4170 4171 4172 4173 4174
	status = nfs4_check_delegmode(deleg, flags);
	if (status) {
		nfs4_put_stid(&deleg->dl_stid);
		goto out;
	}
	*dp = deleg;
4175
out:
4176
	if (!nfsd4_is_deleg_cur(open))
4177 4178 4179
		return nfs_ok;
	if (status)
		return status;
4180
	open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
4181
	return nfs_ok;
4182 4183
}

4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194
static inline int nfs4_access_to_access(u32 nfs4_access)
{
	int flags = 0;

	if (nfs4_access & NFS4_SHARE_ACCESS_READ)
		flags |= NFSD_MAY_READ;
	if (nfs4_access & NFS4_SHARE_ACCESS_WRITE)
		flags |= NFSD_MAY_WRITE;
	return flags;
}

4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209
static inline __be32
nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
		struct nfsd4_open *open)
{
	struct iattr iattr = {
		.ia_valid = ATTR_SIZE,
		.ia_size = 0,
	};
	if (!open->op_truncate)
		return 0;
	if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
		return nfserr_inval;
	return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
}

4210
static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
4211 4212
		struct svc_fh *cur_fh, struct nfs4_ol_stateid *stp,
		struct nfsd4_open *open)
4213
{
4214
	struct file *filp = NULL;
4215
	__be32 status;
4216 4217
	int oflag = nfs4_access_to_omode(open->op_share_access);
	int access = nfs4_access_to_access(open->op_share_access);
4218
	unsigned char old_access_bmap, old_deny_bmap;
4219

4220
	spin_lock(&fp->fi_lock);
4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247

	/*
	 * Are we trying to set a deny mode that would conflict with
	 * current access?
	 */
	status = nfs4_file_check_deny(fp, open->op_share_deny);
	if (status != nfs_ok) {
		spin_unlock(&fp->fi_lock);
		goto out;
	}

	/* set access to the file */
	status = nfs4_file_get_access(fp, open->op_share_access);
	if (status != nfs_ok) {
		spin_unlock(&fp->fi_lock);
		goto out;
	}

	/* Set access bits in stateid */
	old_access_bmap = stp->st_access_bmap;
	set_access(open->op_share_access, stp);

	/* Set new deny mask */
	old_deny_bmap = stp->st_deny_bmap;
	set_deny(open->op_share_deny, stp);
	fp->fi_share_deny |= (open->op_share_deny & NFS4_SHARE_DENY_BOTH);

4248
	if (!fp->fi_fds[oflag]) {
4249 4250
		spin_unlock(&fp->fi_lock);
		status = nfsd_open(rqstp, cur_fh, S_IFREG, access, &filp);
4251
		if (status)
4252
			goto out_put_access;
4253 4254 4255 4256 4257
		spin_lock(&fp->fi_lock);
		if (!fp->fi_fds[oflag]) {
			fp->fi_fds[oflag] = filp;
			filp = NULL;
		}
4258
	}
4259 4260 4261
	spin_unlock(&fp->fi_lock);
	if (filp)
		fput(filp);
4262

4263 4264 4265 4266 4267
	status = nfsd4_truncate(rqstp, cur_fh, open);
	if (status)
		goto out_put_access;
out:
	return status;
4268 4269 4270 4271 4272
out_put_access:
	stp->st_access_bmap = old_access_bmap;
	nfs4_file_put_access(fp, open->op_share_access);
	reset_union_bmap_deny(bmap_to_share_mode(old_deny_bmap), stp);
	goto out;
Linus Torvalds's avatar
Linus Torvalds committed
4273 4274
}

4275
static __be32
4276
nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_ol_stateid *stp, struct nfsd4_open *open)
Linus Torvalds's avatar
Linus Torvalds committed
4277
{
4278
	__be32 status;
4279
	unsigned char old_deny_bmap = stp->st_deny_bmap;
Linus Torvalds's avatar
Linus Torvalds committed
4280

4281
	if (!test_access(open->op_share_access, stp))
4282
		return nfs4_get_vfs_file(rqstp, fp, cur_fh, stp, open);
4283

4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294
	/* test and set deny mode */
	spin_lock(&fp->fi_lock);
	status = nfs4_file_check_deny(fp, open->op_share_deny);
	if (status == nfs_ok) {
		set_deny(open->op_share_deny, stp);
		fp->fi_share_deny |=
				(open->op_share_deny & NFS4_SHARE_DENY_BOTH);
	}
	spin_unlock(&fp->fi_lock);

	if (status != nfs_ok)
Linus Torvalds's avatar
Linus Torvalds committed
4295 4296
		return status;

4297 4298 4299 4300 4301
	status = nfsd4_truncate(rqstp, cur_fh, open);
	if (status != nfs_ok)
		reset_union_bmap_deny(old_deny_bmap, stp);
	return status;
}
Linus Torvalds's avatar
Linus Torvalds committed
4302

4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315
/* Should we give out recallable state?: */
static bool nfsd4_cb_channel_good(struct nfs4_client *clp)
{
	if (clp->cl_cb_state == NFSD4_CB_UP)
		return true;
	/*
	 * In the sessions case, since we don't have to establish a
	 * separate connection for callbacks, we assume it's OK
	 * until we hear otherwise:
	 */
	return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN;
}

4316 4317
static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp,
						int flag)
4318 4319 4320 4321 4322 4323 4324
{
	struct file_lock *fl;

	fl = locks_alloc_lock();
	if (!fl)
		return NULL;
	fl->fl_lmops = &nfsd_lease_mng_ops;
4325
	fl->fl_flags = FL_DELEG;
4326 4327
	fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
	fl->fl_end = OFFSET_MAX;
4328
	fl->fl_owner = (fl_owner_t)dp;
4329
	fl->fl_pid = current->tgid;
4330
	fl->fl_file = dp->dl_stid.sc_file->fi_deleg_file;
4331 4332 4333
	return fl;
}

4334 4335
static struct nfs4_delegation *
nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
4336
		    struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
4337
{
4338
	int status = 0;
4339
	struct nfs4_delegation *dp;
4340 4341
	struct file *filp;
	struct file_lock *fl;
4342

4343 4344 4345 4346 4347
	/*
	 * The fi_had_conflict and nfs_get_existing_delegation checks
	 * here are just optimizations; we'll need to recheck them at
	 * the end:
	 */
4348
	if (fp->fi_had_conflict)
4349 4350
		return ERR_PTR(-EAGAIN);

4351 4352 4353 4354 4355 4356
	filp = find_readable_file(fp);
	if (!filp) {
		/* We should always have a readable file here */
		WARN_ON_ONCE(1);
		return ERR_PTR(-EBADF);
	}
4357 4358
	spin_lock(&state_lock);
	spin_lock(&fp->fi_lock);
4359 4360
	if (nfs4_delegation_exists(clp, fp))
		status = -EAGAIN;
4361 4362 4363 4364 4365 4366 4367 4368
	else if (!fp->fi_deleg_file) {
		fp->fi_deleg_file = filp;
		/* increment early to prevent fi_deleg_file from being
		 * cleared */
		fp->fi_delegees = 1;
		filp = NULL;
	} else
		fp->fi_delegees++;
4369 4370
	spin_unlock(&fp->fi_lock);
	spin_unlock(&state_lock);
4371 4372
	if (filp)
		fput(filp);
4373 4374 4375
	if (status)
		return ERR_PTR(status);

4376
	status = -ENOMEM;
4377
	dp = alloc_init_deleg(clp, fp, fh, odstate);
4378
	if (!dp)
4379 4380 4381 4382
		goto out_delegees;

	fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
	if (!fl)
4383
		goto out_clnt_odstate;
4384 4385 4386 4387 4388 4389

	status = vfs_setlease(fp->fi_deleg_file, fl->fl_type, &fl, NULL);
	if (fl)
		locks_free_lock(fl);
	if (status)
		goto out_clnt_odstate;
4390

4391 4392
	spin_lock(&state_lock);
	spin_lock(&fp->fi_lock);
4393
	if (fp->fi_had_conflict)
4394
		status = -EAGAIN;
4395 4396
	else
		status = hash_delegation_locked(dp, fp);
4397
	spin_unlock(&fp->fi_lock);
4398
	spin_unlock(&state_lock);
4399 4400

	if (status)
4401 4402
		goto out_unlock;

4403
	return dp;
4404 4405
out_unlock:
	vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp);
4406 4407 4408 4409 4410 4411
out_clnt_odstate:
	put_clnt_odstate(dp->dl_clnt_odstate);
	nfs4_put_stid(&dp->dl_stid);
out_delegees:
	put_deleg_file(fp);
	return ERR_PTR(status);
4412 4413
}

4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429
static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
{
	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
	if (status == -EAGAIN)
		open->op_why_no_deleg = WND4_CONTENTION;
	else {
		open->op_why_no_deleg = WND4_RESOURCE;
		switch (open->op_deleg_want) {
		case NFS4_SHARE_WANT_READ_DELEG:
		case NFS4_SHARE_WANT_WRITE_DELEG:
		case NFS4_SHARE_WANT_ANY_DELEG:
			break;
		case NFS4_SHARE_WANT_CANCEL:
			open->op_why_no_deleg = WND4_CANCELLED;
			break;
		case NFS4_SHARE_WANT_NO_DELEG:
4430
			WARN_ON_ONCE(1);
4431 4432 4433 4434
		}
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
4435 4436
/*
 * Attempt to hand out a delegation.
4437 4438 4439
 *
 * Note we don't support write delegations, and won't until the vfs has
 * proper support for them.
Linus Torvalds's avatar
Linus Torvalds committed
4440 4441
 */
static void
4442 4443
nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
			struct nfs4_ol_stateid *stp)
Linus Torvalds's avatar
Linus Torvalds committed
4444 4445
{
	struct nfs4_delegation *dp;
4446 4447
	struct nfs4_openowner *oo = openowner(stp->st_stateowner);
	struct nfs4_client *clp = stp->st_stid.sc_client;
4448
	int cb_up;
4449
	int status = 0;
Linus Torvalds's avatar
Linus Torvalds committed
4450

4451
	cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
4452 4453 4454
	open->op_recall = 0;
	switch (open->op_claim_type) {
		case NFS4_OPEN_CLAIM_PREVIOUS:
4455
			if (!cb_up)
4456
				open->op_recall = 1;
4457 4458
			if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
				goto out_no_deleg;
4459 4460
			break;
		case NFS4_OPEN_CLAIM_NULL:
4461
		case NFS4_OPEN_CLAIM_FH:
4462 4463
			/*
			 * Let's not give out any delegations till everyone's
4464 4465
			 * had the chance to reclaim theirs, *and* until
			 * NLM locks have all been reclaimed:
4466
			 */
4467
			if (locks_in_grace(clp->net))
4468
				goto out_no_deleg;
4469
			if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
4470
				goto out_no_deleg;
4471 4472 4473 4474 4475 4476 4477
			/*
			 * Also, if the file was opened for write or
			 * create, there's a good chance the client's
			 * about to write to it, resulting in an
			 * immediate recall (since we don't support
			 * write delegations):
			 */
4478
			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
4479 4480 4481
				goto out_no_deleg;
			if (open->op_create == NFS4_OPEN_CREATE)
				goto out_no_deleg;
4482 4483
			break;
		default:
4484
			goto out_no_deleg;
4485
	}
4486
	dp = nfs4_set_delegation(clp, fh, stp->st_stid.sc_file, stp->st_clnt_odstate);
4487
	if (IS_ERR(dp))
4488
		goto out_no_deleg;
Linus Torvalds's avatar
Linus Torvalds committed
4489

4490
	memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
Linus Torvalds's avatar
Linus Torvalds committed
4491

4492
	dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
4493
		STATEID_VAL(&dp->dl_stid.sc_stateid));
4494
	open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
4495
	nfs4_put_stid(&dp->dl_stid);
4496 4497
	return;
out_no_deleg:
4498 4499
	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
4500
	    open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) {
4501
		dprintk("NFSD: WARNING: refusing delegation reclaim\n");
4502 4503
		open->op_recall = 1;
	}
4504 4505 4506 4507 4508

	/* 4.1 client asking for a delegation? */
	if (open->op_deleg_want)
		nfsd4_open_deleg_none_ext(open, status);
	return;
Linus Torvalds's avatar
Linus Torvalds committed
4509 4510
}

4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528
static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
					struct nfs4_delegation *dp)
{
	if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG &&
	    dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
		open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
		open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE;
	} else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG &&
		   dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
		open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
		open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE;
	}
	/* Otherwise the client must be confused wanting a delegation
	 * it already has, therefore we don't return
	 * NFS4_OPEN_DELEGATE_NONE_EXT and reason.
	 */
}

4529
__be32
Linus Torvalds's avatar
Linus Torvalds committed
4530 4531
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
Andy Adamson's avatar
Andy Adamson committed
4532
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
4533
	struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
Linus Torvalds's avatar
Linus Torvalds committed
4534
	struct nfs4_file *fp = NULL;
4535
	struct nfs4_ol_stateid *stp = NULL;
4536
	struct nfs4_delegation *dp = NULL;
4537
	__be32 status;
4538
	bool new_stp = false;
Linus Torvalds's avatar
Linus Torvalds committed
4539 4540 4541 4542 4543 4544

	/*
	 * Lookup file; if found, lookup stateid and check open request,
	 * and check for delegations in the process of being recalled.
	 * If not found, create the nfs4_file struct
	 */
4545
	fp = find_or_add_file(open->op_file, &current_fh->fh_handle);
4546
	if (fp != open->op_file) {
4547
		status = nfs4_check_deleg(cl, open, &dp);
4548 4549
		if (status)
			goto out;
4550
		stp = nfsd4_find_and_lock_existing_open(fp, open);
Linus Torvalds's avatar
Linus Torvalds committed
4551
	} else {
4552
		open->op_file = NULL;
4553
		status = nfserr_bad_stateid;
4554
		if (nfsd4_is_deleg_cur(open))
4555
			goto out;
Linus Torvalds's avatar
Linus Torvalds committed
4556 4557
	}

4558 4559 4560 4561 4562 4563
	if (!stp) {
		stp = init_open_stateid(fp, open);
		if (!open->op_stp)
			new_stp = true;
	}

Linus Torvalds's avatar
Linus Torvalds committed
4564 4565 4566
	/*
	 * OPEN the file, or upgrade an existing OPEN.
	 * If truncate fails, the OPEN fails.
4567 4568
	 *
	 * stp is already locked.
Linus Torvalds's avatar
Linus Torvalds committed
4569
	 */
4570
	if (!new_stp) {
Linus Torvalds's avatar
Linus Torvalds committed
4571
		/* Stateid was found, this is an OPEN upgrade */
4572
		status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
4573
		if (status) {
4574
			mutex_unlock(&stp->st_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
4575
			goto out;
4576
		}
Linus Torvalds's avatar
Linus Torvalds committed
4577
	} else {
4578 4579
		status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
		if (status) {
4580
			stp->st_stid.sc_type = NFS4_CLOSED_STID;
4581
			release_open_stateid(stp);
4582
			mutex_unlock(&stp->st_mutex);
4583 4584
			goto out;
		}
4585 4586 4587 4588 4589

		stp->st_clnt_odstate = find_or_hash_clnt_odstate(fp,
							open->op_odstate);
		if (stp->st_clnt_odstate == open->op_odstate)
			open->op_odstate = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
4590
	}
4591

4592
	nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
4593
	mutex_unlock(&stp->st_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
4594

4595 4596 4597 4598 4599 4600 4601 4602
	if (nfsd4_has_session(&resp->cstate)) {
		if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
			open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
			open->op_why_no_deleg = WND4_NOT_WANTED;
			goto nodeleg;
		}
	}

Linus Torvalds's avatar
Linus Torvalds committed
4603 4604 4605 4606
	/*
	* Attempt to hand out a delegation. No error return, because the
	* OPEN succeeds even if we fail.
	*/
4607
	nfs4_open_delegation(current_fh, open, stp);
4608
nodeleg:
Linus Torvalds's avatar
Linus Torvalds committed
4609 4610
	status = nfs_ok;

4611
	dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
4612
		STATEID_VAL(&stp->st_stid.sc_stateid));
Linus Torvalds's avatar
Linus Torvalds committed
4613
out:
4614 4615
	/* 4.1 client trying to upgrade/downgrade delegation? */
	if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
4616 4617
	    open->op_deleg_want)
		nfsd4_deleg_xgrade_none_ext(open, dp);
4618

4619 4620
	if (fp)
		put_nfs4_file(fp);
4621
	if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
4622
		open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
Linus Torvalds's avatar
Linus Torvalds committed
4623 4624 4625 4626
	/*
	* To finish the open response, we just need to set the rflags.
	*/
	open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
4627 4628 4629
	if (nfsd4_has_session(&resp->cstate))
		open->op_rflags |= NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK;
	else if (!(open->op_openowner->oo_flags & NFS4_OO_CONFIRMED))
Linus Torvalds's avatar
Linus Torvalds committed
4630
		open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
4631

4632 4633
	if (dp)
		nfs4_put_stid(&dp->dl_stid);
4634 4635
	if (stp)
		nfs4_put_stid(&stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
4636 4637 4638 4639

	return status;
}

4640
void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
4641
			      struct nfsd4_open *open)
4642 4643
{
	if (open->op_openowner) {
4644 4645 4646 4647
		struct nfs4_stateowner *so = &open->op_openowner->oo_owner;

		nfsd4_cstate_assign_replay(cstate, so);
		nfs4_put_stateowner(so);
4648
	}
4649
	if (open->op_file)
4650
		kmem_cache_free(file_slab, open->op_file);
4651
	if (open->op_stp)
4652
		nfs4_put_stid(&open->op_stp->st_stid);
4653 4654
	if (open->op_odstate)
		kmem_cache_free(odstate_slab, open->op_odstate);
4655 4656
}

4657
__be32
4658
nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4659
	    union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
4660
{
4661
	clientid_t *clid = &u->renew;
Linus Torvalds's avatar
Linus Torvalds committed
4662
	struct nfs4_client *clp;
4663
	__be32 status;
4664
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
4665 4666 4667

	dprintk("process_renew(%08x/%08x): starting\n", 
			clid->cl_boot, clid->cl_id);
4668
	status = lookup_clientid(clid, cstate, nn);
4669
	if (status)
Linus Torvalds's avatar
Linus Torvalds committed
4670
		goto out;
4671
	clp = cstate->clp;
Linus Torvalds's avatar
Linus Torvalds committed
4672
	status = nfserr_cb_path_down;
4673
	if (!list_empty(&clp->cl_delegations)
4674
			&& clp->cl_cb_state != NFSD4_CB_UP)
Linus Torvalds's avatar
Linus Torvalds committed
4675 4676 4677 4678 4679 4680
		goto out;
	status = nfs_ok;
out:
	return status;
}

4681
void
4682
nfsd4_end_grace(struct nfsd_net *nn)
4683
{
4684
	/* do nothing if grace period already ended */
4685
	if (nn->grace_ended)
4686 4687
		return;

4688
	dprintk("NFSD: end of grace period\n");
4689
	nn->grace_ended = true;
4690 4691 4692 4693 4694 4695
	/*
	 * If the server goes down again right now, an NFSv4
	 * client will still be allowed to reclaim after it comes back up,
	 * even if it hasn't yet had a chance to reclaim state this time.
	 *
	 */
4696
	nfsd4_record_grace_done(nn);
4697 4698 4699 4700 4701 4702 4703 4704 4705
	/*
	 * At this point, NFSv4 clients can still reclaim.  But if the
	 * server crashes, any that have not yet reclaimed will be out
	 * of luck on the next boot.
	 *
	 * (NFSv4.1+ clients are considered to have reclaimed once they
	 * call RECLAIM_COMPLETE.  NFSv4.0 clients are considered to
	 * have reclaimed after their first OPEN.)
	 */
4706
	locks_end_grace(&nn->nfsd4_manager);
4707 4708 4709 4710 4711
	/*
	 * At this point, and once lockd and/or any other containers
	 * exit their grace period, further reclaims will fail and
	 * regular locking can resume.
	 */
4712 4713
}

4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735
/*
 * If we've waited a lease period but there are still clients trying to
 * reclaim, wait a little longer to give them a chance to finish.
 */
static bool clients_still_reclaiming(struct nfsd_net *nn)
{
	unsigned long now = get_seconds();
	unsigned long double_grace_period_end = nn->boot_time +
						2 * nn->nfsd4_lease;

	if (!nn->somebody_reclaimed)
		return false;
	nn->somebody_reclaimed = false;
	/*
	 * If we've given them *two* lease times to reclaim, and they're
	 * still not done, give up:
	 */
	if (time_after(now, double_grace_period_end))
		return false;
	return true;
}

4736
static time_t
4737
nfs4_laundromat(struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
4738 4739
{
	struct nfs4_client *clp;
4740
	struct nfs4_openowner *oo;
Linus Torvalds's avatar
Linus Torvalds committed
4741
	struct nfs4_delegation *dp;
4742
	struct nfs4_ol_stateid *stp;
4743
	struct nfsd4_blocked_lock *nbl;
Linus Torvalds's avatar
Linus Torvalds committed
4744
	struct list_head *pos, *next, reaplist;
4745
	time_t cutoff = get_seconds() - nn->nfsd4_lease;
4746
	time_t t, new_timeo = nn->nfsd4_lease;
Linus Torvalds's avatar
Linus Torvalds committed
4747 4748

	dprintk("NFSD: laundromat service - starting\n");
4749 4750 4751 4752 4753

	if (clients_still_reclaiming(nn)) {
		new_timeo = 0;
		goto out;
	}
4754
	nfsd4_end_grace(nn);
4755
	INIT_LIST_HEAD(&reaplist);
4756
	spin_lock(&nn->client_lock);
4757
	list_for_each_safe(pos, next, &nn->client_lru) {
Linus Torvalds's avatar
Linus Torvalds committed
4758 4759 4760
		clp = list_entry(pos, struct nfs4_client, cl_lru);
		if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
			t = clp->cl_time - cutoff;
4761
			new_timeo = min(new_timeo, t);
Linus Torvalds's avatar
Linus Torvalds committed
4762 4763
			break;
		}
4764
		if (mark_client_expired_locked(clp)) {
4765 4766 4767 4768
			dprintk("NFSD: client in use (clientid %08x)\n",
				clp->cl_clientid.cl_id);
			continue;
		}
4769
		list_add(&clp->cl_lru, &reaplist);
4770
	}
4771
	spin_unlock(&nn->client_lock);
4772 4773
	list_for_each_safe(pos, next, &reaplist) {
		clp = list_entry(pos, struct nfs4_client, cl_lru);
Linus Torvalds's avatar
Linus Torvalds committed
4774 4775
		dprintk("NFSD: purging unused client (clientid %08x)\n",
			clp->cl_clientid.cl_id);
4776
		list_del_init(&clp->cl_lru);
Linus Torvalds's avatar
Linus Torvalds committed
4777 4778
		expire_client(clp);
	}
4779
	spin_lock(&state_lock);
4780
	list_for_each_safe(pos, next, &nn->del_recall_lru) {
Linus Torvalds's avatar
Linus Torvalds committed
4781 4782
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
		if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
4783 4784
			t = dp->dl_time - cutoff;
			new_timeo = min(new_timeo, t);
Linus Torvalds's avatar
Linus Torvalds committed
4785 4786
			break;
		}
4787
		WARN_ON(!unhash_delegation_locked(dp));
4788
		list_add(&dp->dl_recall_lru, &reaplist);
Linus Torvalds's avatar
Linus Torvalds committed
4789
	}
4790
	spin_unlock(&state_lock);
4791 4792 4793 4794
	while (!list_empty(&reaplist)) {
		dp = list_first_entry(&reaplist, struct nfs4_delegation,
					dl_recall_lru);
		list_del_init(&dp->dl_recall_lru);
4795
		revoke_delegation(dp);
Linus Torvalds's avatar
Linus Torvalds committed
4796
	}
4797 4798 4799 4800 4801 4802 4803

	spin_lock(&nn->client_lock);
	while (!list_empty(&nn->close_lru)) {
		oo = list_first_entry(&nn->close_lru, struct nfs4_openowner,
					oo_close_lru);
		if (time_after((unsigned long)oo->oo_time,
			       (unsigned long)cutoff)) {
4804 4805
			t = oo->oo_time - cutoff;
			new_timeo = min(new_timeo, t);
Linus Torvalds's avatar
Linus Torvalds committed
4806 4807
			break;
		}
4808 4809 4810 4811 4812 4813
		list_del_init(&oo->oo_close_lru);
		stp = oo->oo_last_closed_stid;
		oo->oo_last_closed_stid = NULL;
		spin_unlock(&nn->client_lock);
		nfs4_put_stid(&stp->st_stid);
		spin_lock(&nn->client_lock);
Linus Torvalds's avatar
Linus Torvalds committed
4814
	}
4815 4816
	spin_unlock(&nn->client_lock);

4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828
	/*
	 * It's possible for a client to try and acquire an already held lock
	 * that is being held for a long time, and then lose interest in it.
	 * So, we clean out any un-revisited request after a lease period
	 * under the assumption that the client is no longer interested.
	 *
	 * RFC5661, sec. 9.6 states that the client must not rely on getting
	 * notifications and must continue to poll for locks, even when the
	 * server supports them. Thus this shouldn't lead to clients blocking
	 * indefinitely once the lock does become free.
	 */
	BUG_ON(!list_empty(&reaplist));
4829
	spin_lock(&nn->blocked_locks_lock);
4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841
	while (!list_empty(&nn->blocked_locks_lru)) {
		nbl = list_first_entry(&nn->blocked_locks_lru,
					struct nfsd4_blocked_lock, nbl_lru);
		if (time_after((unsigned long)nbl->nbl_time,
			       (unsigned long)cutoff)) {
			t = nbl->nbl_time - cutoff;
			new_timeo = min(new_timeo, t);
			break;
		}
		list_move(&nbl->nbl_lru, &reaplist);
		list_del_init(&nbl->nbl_list);
	}
4842
	spin_unlock(&nn->blocked_locks_lock);
4843 4844

	while (!list_empty(&reaplist)) {
4845
		nbl = list_first_entry(&reaplist,
4846 4847 4848 4849 4850
					struct nfsd4_blocked_lock, nbl_lru);
		list_del_init(&nbl->nbl_lru);
		posix_unblock_lock(&nbl->nbl_lock);
		free_blocked_lock(nbl);
	}
4851
out:
4852 4853
	new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT);
	return new_timeo;
Linus Torvalds's avatar
Linus Torvalds committed
4854 4855
}

Harvey Harrison's avatar
Harvey Harrison committed
4856 4857 4858 4859
static struct workqueue_struct *laundry_wq;
static void laundromat_main(struct work_struct *);

static void
4860
laundromat_main(struct work_struct *laundry)
Linus Torvalds's avatar
Linus Torvalds committed
4861 4862
{
	time_t t;
Geliang Tang's avatar
Geliang Tang committed
4863
	struct delayed_work *dwork = to_delayed_work(laundry);
4864 4865
	struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
					   laundromat_work);
Linus Torvalds's avatar
Linus Torvalds committed
4866

4867
	t = nfs4_laundromat(nn);
Linus Torvalds's avatar
Linus Torvalds committed
4868
	dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
4869
	queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ);
Linus Torvalds's avatar
Linus Torvalds committed
4870 4871
}

4872
static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stid *stp)
Linus Torvalds's avatar
Linus Torvalds committed
4873
{
4874
	if (!fh_match(&fhp->fh_handle, &stp->sc_file->fi_fhandle))
4875 4876
		return nfserr_bad_stateid;
	return nfs_ok;
Linus Torvalds's avatar
Linus Torvalds committed
4877 4878 4879
}

static inline int
4880
access_permit_read(struct nfs4_ol_stateid *stp)
Linus Torvalds's avatar
Linus Torvalds committed
4881
{
4882 4883 4884
	return test_access(NFS4_SHARE_ACCESS_READ, stp) ||
		test_access(NFS4_SHARE_ACCESS_BOTH, stp) ||
		test_access(NFS4_SHARE_ACCESS_WRITE, stp);
Linus Torvalds's avatar
Linus Torvalds committed
4885 4886 4887
}

static inline int
4888
access_permit_write(struct nfs4_ol_stateid *stp)
Linus Torvalds's avatar
Linus Torvalds committed
4889
{
4890 4891
	return test_access(NFS4_SHARE_ACCESS_WRITE, stp) ||
		test_access(NFS4_SHARE_ACCESS_BOTH, stp);
Linus Torvalds's avatar
Linus Torvalds committed
4892 4893 4894
}

static
4895
__be32 nfs4_check_openmode(struct nfs4_ol_stateid *stp, int flags)
Linus Torvalds's avatar
Linus Torvalds committed
4896
{
4897
        __be32 status = nfserr_openmode;
Linus Torvalds's avatar
Linus Torvalds committed
4898

4899 4900 4901
	/* For lock stateid's, we test the parent open, not the lock: */
	if (stp->st_openstp)
		stp = stp->st_openstp;
4902
	if ((flags & WR_STATE) && !access_permit_write(stp))
Linus Torvalds's avatar
Linus Torvalds committed
4903
                goto out;
4904
	if ((flags & RD_STATE) && !access_permit_read(stp))
Linus Torvalds's avatar
Linus Torvalds committed
4905 4906 4907 4908 4909 4910
                goto out;
	status = nfs_ok;
out:
	return status;
}

4911
static inline __be32
4912
check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid, int flags)
Linus Torvalds's avatar
Linus Torvalds committed
4913
{
4914
	if (ONE_STATEID(stateid) && (flags & RD_STATE))
Linus Torvalds's avatar
Linus Torvalds committed
4915
		return nfs_ok;
4916
	else if (opens_in_grace(net)) {
Lucas De Marchi's avatar
Lucas De Marchi committed
4917
		/* Answer in remaining cases depends on existence of
Linus Torvalds's avatar
Linus Torvalds committed
4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932
		 * conflicting state; so we must wait out the grace period. */
		return nfserr_grace;
	} else if (flags & WR_STATE)
		return nfs4_share_conflict(current_fh,
				NFS4_SHARE_DENY_WRITE);
	else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */
		return nfs4_share_conflict(current_fh,
				NFS4_SHARE_DENY_READ);
}

/*
 * Allow READ/WRITE during grace period on recovered state only for files
 * that are not able to provide mandatory locking.
 */
static inline int
4933
grace_disallows_io(struct net *net, struct inode *inode)
Linus Torvalds's avatar
Linus Torvalds committed
4934
{
4935
	return opens_in_grace(net) && mandatory_lock(inode);
Linus Torvalds's avatar
Linus Torvalds committed
4936 4937
}

J. Bruce Fields's avatar
J. Bruce Fields committed
4938
static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
4939
{
Andy Adamson's avatar
Andy Adamson committed
4940 4941 4942 4943
	/*
	 * When sessions are used the stateid generation number is ignored
	 * when it is zero.
	 */
J. Bruce Fields's avatar
J. Bruce Fields committed
4944
	if (has_session && in->si_generation == 0)
4945 4946 4947 4948
		return nfs_ok;

	if (in->si_generation == ref->si_generation)
		return nfs_ok;
Andy Adamson's avatar
Andy Adamson committed
4949

4950
	/* If the client sends us a stateid from the future, it's buggy: */
4951
	if (nfsd4_stateid_generation_after(in, ref))
4952 4953
		return nfserr_bad_stateid;
	/*
4954 4955 4956 4957 4958 4959 4960 4961
	 * However, we could see a stateid from the past, even from a
	 * non-buggy client.  For example, if the client sends a lock
	 * while some IO is outstanding, the lock may bump si_generation
	 * while the IO is still in flight.  The client could avoid that
	 * situation by waiting for responses on all the IO requests,
	 * but better performance may result in retrying IO that
	 * receives an old_stateid error if requests are rarely
	 * reordered in flight:
4962
	 */
4963
	return nfserr_old_stateid;
4964 4965
}

4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977
static __be32 nfsd4_stid_check_stateid_generation(stateid_t *in, struct nfs4_stid *s, bool has_session)
{
	__be32 ret;

	spin_lock(&s->sc_lock);
	ret = nfsd4_verify_open_stid(s);
	if (ret == nfs_ok)
		ret = check_stateid_generation(in, &s->sc_stateid, has_session);
	spin_unlock(&s->sc_lock);
	return ret;
}

4978 4979 4980 4981 4982 4983 4984 4985
static __be32 nfsd4_check_openowner_confirmed(struct nfs4_ol_stateid *ols)
{
	if (ols->st_stateowner->so_is_open_owner &&
	    !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
		return nfserr_bad_stateid;
	return nfs_ok;
}

4986
static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
4987
{
4988
	struct nfs4_stid *s;
4989
	__be32 status = nfserr_bad_stateid;
4990

4991 4992
	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
		CLOSE_STATEID(stateid))
4993
		return status;
4994 4995 4996 4997 4998 4999 5000
	/* Client debugging aid. */
	if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
		char addr_str[INET6_ADDRSTRLEN];
		rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str,
				 sizeof(addr_str));
		pr_warn_ratelimited("NFSD: client %s testing state ID "
					"with incorrect client ID\n", addr_str);
5001
		return status;
5002
	}
5003 5004
	spin_lock(&cl->cl_lock);
	s = find_stateid_locked(cl, stateid);
5005
	if (!s)
5006
		goto out_unlock;
5007
	status = nfsd4_stid_check_stateid_generation(stateid, s, 1);
5008
	if (status)
5009
		goto out_unlock;
5010 5011
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
5012 5013
		status = nfs_ok;
		break;
5014
	case NFS4_REVOKED_DELEG_STID:
5015 5016
		status = nfserr_deleg_revoked;
		break;
5017 5018
	case NFS4_OPEN_STID:
	case NFS4_LOCK_STID:
5019
		status = nfsd4_check_openowner_confirmed(openlockstateid(s));
5020
		break;
5021 5022
	default:
		printk("unknown stateid type %x\n", s->sc_type);
5023
		/* Fallthrough */
5024
	case NFS4_CLOSED_STID:
5025
	case NFS4_CLOSED_DELEG_STID:
5026
		status = nfserr_bad_stateid;
5027
	}
5028 5029 5030
out_unlock:
	spin_unlock(&cl->cl_lock);
	return status;
5031 5032
}

5033
__be32
5034 5035 5036
nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
		     stateid_t *stateid, unsigned char typemask,
		     struct nfs4_stid **s, struct nfsd_net *nn)
5037
{
5038
	__be32 status;
5039 5040 5041 5042 5043 5044 5045 5046 5047 5048
	bool return_revoked = false;

	/*
	 *  only return revoked delegations if explicitly asked.
	 *  otherwise we report revoked or bad_stateid status.
	 */
	if (typemask & NFS4_REVOKED_DELEG_STID)
		return_revoked = true;
	else if (typemask & NFS4_DELEG_STID)
		typemask |= NFS4_REVOKED_DELEG_STID;
5049

5050 5051
	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
		CLOSE_STATEID(stateid))
5052
		return nfserr_bad_stateid;
5053
	status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn);
5054
	if (status == nfserr_stale_clientid) {
5055
		if (cstate->session)
5056
			return nfserr_bad_stateid;
5057
		return nfserr_stale_stateid;
5058
	}
5059 5060
	if (status)
		return status;
5061
	*s = find_stateid_by_type(cstate->clp, stateid, typemask);
5062 5063
	if (!*s)
		return nfserr_bad_stateid;
5064 5065 5066 5067 5068 5069
	if (((*s)->sc_type == NFS4_REVOKED_DELEG_STID) && !return_revoked) {
		nfs4_put_stid(*s);
		if (cstate->minorversion)
			return nfserr_deleg_revoked;
		return nfserr_bad_stateid;
	}
5070 5071 5072
	return nfs_ok;
}

5073 5074 5075
static struct file *
nfs4_find_file(struct nfs4_stid *s, int flags)
{
5076 5077 5078
	if (!s)
		return NULL;

5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
		if (WARN_ON_ONCE(!s->sc_file->fi_deleg_file))
			return NULL;
		return get_file(s->sc_file->fi_deleg_file);
	case NFS4_OPEN_STID:
	case NFS4_LOCK_STID:
		if (flags & RD_STATE)
			return find_readable_file(s->sc_file);
		else
			return find_writeable_file(s->sc_file);
		break;
	}

	return NULL;
}

static __be32
nfs4_check_olstateid(struct svc_fh *fhp, struct nfs4_ol_stateid *ols, int flags)
{
	__be32 status;

	status = nfsd4_check_openowner_confirmed(ols);
	if (status)
		return status;
	return nfs4_check_openmode(ols, flags);
}

5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136
static __be32
nfs4_check_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfs4_stid *s,
		struct file **filpp, bool *tmp_file, int flags)
{
	int acc = (flags & RD_STATE) ? NFSD_MAY_READ : NFSD_MAY_WRITE;
	struct file *file;
	__be32 status;

	file = nfs4_find_file(s, flags);
	if (file) {
		status = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
				acc | NFSD_MAY_OWNER_OVERRIDE);
		if (status) {
			fput(file);
			return status;
		}

		*filpp = file;
	} else {
		status = nfsd_open(rqstp, fhp, S_IFREG, acc, filpp);
		if (status)
			return status;

		if (tmp_file)
			*tmp_file = true;
	}

	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
5137
/*
5138 5139
 * Checks for stateid operations
 */
5140
__be32
5141
nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
5142 5143
		struct nfsd4_compound_state *cstate, struct svc_fh *fhp,
		stateid_t *stateid, int flags, struct file **filpp, bool *tmp_file)
Linus Torvalds's avatar
Linus Torvalds committed
5144
{
5145
	struct inode *ino = d_inode(fhp->fh_dentry);
5146
	struct net *net = SVC_NET(rqstp);
5147
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
5148
	struct nfs4_stid *s = NULL;
5149
	__be32 status;
Linus Torvalds's avatar
Linus Torvalds committed
5150 5151 5152

	if (filpp)
		*filpp = NULL;
5153 5154
	if (tmp_file)
		*tmp_file = false;
Linus Torvalds's avatar
Linus Torvalds committed
5155

5156
	if (grace_disallows_io(net, ino))
Linus Torvalds's avatar
Linus Torvalds committed
5157 5158
		return nfserr_grace;

5159 5160 5161 5162
	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
		status = check_special_stateids(net, fhp, stateid, flags);
		goto done;
	}
Linus Torvalds's avatar
Linus Torvalds committed
5163

5164
	status = nfsd4_lookup_stateid(cstate, stateid,
5165
				NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID,
5166
				&s, nn);
5167
	if (status)
5168
		return status;
5169
	status = nfsd4_stid_check_stateid_generation(stateid, s,
5170
			nfsd4_has_session(cstate));
5171 5172
	if (status)
		goto out;
5173

5174 5175
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
5176
		status = nfs4_check_delegmode(delegstateid(s), flags);
5177 5178 5179
		break;
	case NFS4_OPEN_STID:
	case NFS4_LOCK_STID:
5180
		status = nfs4_check_olstateid(fhp, openlockstateid(s), flags);
5181 5182
		break;
	default:
5183
		status = nfserr_bad_stateid;
5184 5185
		break;
	}
5186 5187 5188
	if (status)
		goto out;
	status = nfs4_check_fh(fhp, s);
5189

5190 5191 5192
done:
	if (!status && filpp)
		status = nfs4_check_file(rqstp, fhp, s, filpp, tmp_file, flags);
Linus Torvalds's avatar
Linus Torvalds committed
5193
out:
5194 5195
	if (s)
		nfs4_put_stid(s);
Linus Torvalds's avatar
Linus Torvalds committed
5196 5197 5198
	return status;
}

5199 5200 5201 5202 5203
/*
 * Test if the stateid is valid
 */
__be32
nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5204
		   union nfsd4_op_u *u)
5205
{
5206
	struct nfsd4_test_stateid *test_stateid = &u->test_stateid;
5207 5208 5209 5210
	struct nfsd4_test_stateid_id *stateid;
	struct nfs4_client *cl = cstate->session->se_client;

	list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
5211 5212
		stateid->ts_id_status =
			nfsd4_validate_stateid(cl, &stateid->ts_id_stateid);
5213

5214 5215 5216
	return nfs_ok;
}

5217 5218 5219 5220 5221 5222
static __be32
nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)
{
	struct nfs4_ol_stateid *stp = openlockstateid(s);
	__be32 ret;

5223 5224 5225
	ret = nfsd4_lock_ol_stateid(stp);
	if (ret)
		goto out_put_stid;
5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240

	ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
	if (ret)
		goto out;

	ret = nfserr_locks_held;
	if (check_for_locks(stp->st_stid.sc_file,
			    lockowner(stp->st_stateowner)))
		goto out;

	release_lock_stateid(stp);
	ret = nfs_ok;

out:
	mutex_unlock(&stp->st_mutex);
5241
out_put_stid:
5242 5243 5244 5245
	nfs4_put_stid(s);
	return ret;
}

5246 5247
__be32
nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5248
		   union nfsd4_op_u *u)
5249
{
5250
	struct nfsd4_free_stateid *free_stateid = &u->free_stateid;
5251
	stateid_t *stateid = &free_stateid->fr_stateid;
5252
	struct nfs4_stid *s;
5253
	struct nfs4_delegation *dp;
5254
	struct nfs4_client *cl = cstate->session->se_client;
5255
	__be32 ret = nfserr_bad_stateid;
5256

5257 5258
	spin_lock(&cl->cl_lock);
	s = find_stateid_locked(cl, stateid);
5259
	if (!s)
5260
		goto out_unlock;
5261
	spin_lock(&s->sc_lock);
5262 5263
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
5264
		ret = nfserr_locks_held;
5265
		break;
5266 5267 5268
	case NFS4_OPEN_STID:
		ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
		if (ret)
5269 5270
			break;
		ret = nfserr_locks_held;
5271
		break;
5272
	case NFS4_LOCK_STID:
5273
		spin_unlock(&s->sc_lock);
5274
		refcount_inc(&s->sc_count);
5275
		spin_unlock(&cl->cl_lock);
5276
		ret = nfsd4_free_lock_stateid(stateid, s);
5277
		goto out;
5278
	case NFS4_REVOKED_DELEG_STID:
5279
		spin_unlock(&s->sc_lock);
5280
		dp = delegstateid(s);
5281 5282
		list_del_init(&dp->dl_recall_lru);
		spin_unlock(&cl->cl_lock);
5283
		nfs4_put_stid(s);
5284
		ret = nfs_ok;
5285 5286
		goto out;
	/* Default falls through and returns nfserr_bad_stateid */
5287
	}
5288
	spin_unlock(&s->sc_lock);
5289 5290
out_unlock:
	spin_unlock(&cl->cl_lock);
5291 5292 5293 5294
out:
	return ret;
}

5295 5296 5297 5298 5299 5300
static inline int
setlkflg (int type)
{
	return (type == NFS4_READW_LT || type == NFS4_READ_LT) ?
		RD_STATE : WR_STATE;
}
Linus Torvalds's avatar
Linus Torvalds committed
5301

5302
static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_t *stateid, u32 seqid, struct nfs4_ol_stateid *stp)
5303 5304 5305 5306 5307 5308 5309 5310
{
	struct svc_fh *current_fh = &cstate->current_fh;
	struct nfs4_stateowner *sop = stp->st_stateowner;
	__be32 status;

	status = nfsd4_check_seqid(cstate, sop, seqid);
	if (status)
		return status;
5311 5312 5313
	status = nfsd4_lock_ol_stateid(stp);
	if (status != nfs_ok)
		return status;
5314
	status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
5315 5316 5317
	if (status == nfs_ok)
		status = nfs4_check_fh(current_fh, &stp->st_stid);
	if (status != nfs_ok)
5318
		mutex_unlock(&stp->st_mutex);
5319
	return status;
5320 5321
}

Linus Torvalds's avatar
Linus Torvalds committed
5322 5323 5324
/* 
 * Checks for sequence id mutating operations. 
 */
5325
static __be32
5326
nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
5327
			 stateid_t *stateid, char typemask,
5328 5329
			 struct nfs4_ol_stateid **stpp,
			 struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
5330
{
5331
	__be32 status;
5332
	struct nfs4_stid *s;
5333
	struct nfs4_ol_stateid *stp = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
5334

5335 5336
	dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__,
		seqid, STATEID_VAL(stateid));
5337

Linus Torvalds's avatar
Linus Torvalds committed
5338
	*stpp = NULL;
5339
	status = nfsd4_lookup_stateid(cstate, stateid, typemask, &s, nn);
5340 5341
	if (status)
		return status;
5342
	stp = openlockstateid(s);
5343
	nfsd4_cstate_assign_replay(cstate, stp->st_stateowner);
Linus Torvalds's avatar
Linus Torvalds committed
5344

5345
	status = nfs4_seqid_op_checks(cstate, stateid, seqid, stp);
5346
	if (!status)
5347
		*stpp = stp;
5348 5349
	else
		nfs4_put_stid(&stp->st_stid);
5350
	return status;
5351
}
5352

5353 5354
static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
						 stateid_t *stateid, struct nfs4_ol_stateid **stpp, struct nfsd_net *nn)
5355 5356 5357
{
	__be32 status;
	struct nfs4_openowner *oo;
5358
	struct nfs4_ol_stateid *stp;
Linus Torvalds's avatar
Linus Torvalds committed
5359

5360
	status = nfs4_preprocess_seqid_op(cstate, seqid, stateid,
5361
						NFS4_OPEN_STID, &stp, nn);
5362 5363
	if (status)
		return status;
5364 5365
	oo = openowner(stp->st_stateowner);
	if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
5366
		mutex_unlock(&stp->st_mutex);
5367
		nfs4_put_stid(&stp->st_stid);
5368
		return nfserr_bad_stateid;
5369 5370
	}
	*stpp = stp;
5371
	return nfs_ok;
Linus Torvalds's avatar
Linus Torvalds committed
5372 5373
}

5374
__be32
5375
nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5376
		   union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
5377
{
5378
	struct nfsd4_open_confirm *oc = &u->open_confirm;
5379
	__be32 status;
5380
	struct nfs4_openowner *oo;
5381
	struct nfs4_ol_stateid *stp;
5382
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
5383

Al Viro's avatar
Al Viro committed
5384 5385
	dprintk("NFSD: nfsd4_open_confirm on file %pd\n",
			cstate->current_fh.fh_dentry);
Linus Torvalds's avatar
Linus Torvalds committed
5386

5387
	status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
5388 5389
	if (status)
		return status;
Linus Torvalds's avatar
Linus Torvalds committed
5390

5391
	status = nfs4_preprocess_seqid_op(cstate,
5392
					oc->oc_seqid, &oc->oc_req_stateid,
5393
					NFS4_OPEN_STID, &stp, nn);
5394
	if (status)
5395
		goto out;
5396
	oo = openowner(stp->st_stateowner);
5397
	status = nfserr_bad_stateid;
5398
	if (oo->oo_flags & NFS4_OO_CONFIRMED) {
5399
		mutex_unlock(&stp->st_mutex);
5400
		goto put_stateid;
5401
	}
5402
	oo->oo_flags |= NFS4_OO_CONFIRMED;
5403
	nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
5404
	mutex_unlock(&stp->st_mutex);
5405
	dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
5406
		__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
5407

5408
	nfsd4_client_record_create(oo->oo_owner.so_client);
5409
	status = nfs_ok;
5410 5411
put_stateid:
	nfs4_put_stid(&stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
5412
out:
5413
	nfsd4_bump_seqid(cstate, status);
Linus Torvalds's avatar
Linus Torvalds committed
5414 5415 5416
	return status;
}

5417
static inline void nfs4_stateid_downgrade_bit(struct nfs4_ol_stateid *stp, u32 access)
Linus Torvalds's avatar
Linus Torvalds committed
5418
{
5419
	if (!test_access(access, stp))
5420
		return;
5421
	nfs4_file_put_access(stp->st_stid.sc_file, access);
5422
	clear_access(access, stp);
5423
}
5424

5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438
static inline void nfs4_stateid_downgrade(struct nfs4_ol_stateid *stp, u32 to_access)
{
	switch (to_access) {
	case NFS4_SHARE_ACCESS_READ:
		nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_WRITE);
		nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_BOTH);
		break;
	case NFS4_SHARE_ACCESS_WRITE:
		nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_READ);
		nfs4_stateid_downgrade_bit(stp, NFS4_SHARE_ACCESS_BOTH);
		break;
	case NFS4_SHARE_ACCESS_BOTH:
		break;
	default:
5439
		WARN_ON_ONCE(1);
Linus Torvalds's avatar
Linus Torvalds committed
5440 5441 5442
	}
}

5443
__be32
5444
nfsd4_open_downgrade(struct svc_rqst *rqstp,
5445
		     struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
5446
{
5447
	struct nfsd4_open_downgrade *od = &u->open_downgrade;
5448
	__be32 status;
5449
	struct nfs4_ol_stateid *stp;
5450
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
5451

Al Viro's avatar
Al Viro committed
5452 5453
	dprintk("NFSD: nfsd4_open_downgrade on file %pd\n", 
			cstate->current_fh.fh_dentry);
Linus Torvalds's avatar
Linus Torvalds committed
5454

5455
	/* We don't yet support WANT bits: */
5456 5457 5458
	if (od->od_deleg_want)
		dprintk("NFSD: %s: od_deleg_want=0x%x ignored\n", __func__,
			od->od_deleg_want);
Linus Torvalds's avatar
Linus Torvalds committed
5459

5460
	status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
5461
					&od->od_stateid, &stp, nn);
5462
	if (status)
Linus Torvalds's avatar
Linus Torvalds committed
5463 5464
		goto out; 
	status = nfserr_inval;
5465
	if (!test_access(od->od_share_access, stp)) {
5466
		dprintk("NFSD: access not a subset of current bitmap: 0x%hhx, input access=%08x\n",
Linus Torvalds's avatar
Linus Torvalds committed
5467
			stp->st_access_bmap, od->od_share_access);
5468
		goto put_stateid;
Linus Torvalds's avatar
Linus Torvalds committed
5469
	}
5470
	if (!test_deny(od->od_share_deny, stp)) {
5471
		dprintk("NFSD: deny not a subset of current bitmap: 0x%hhx, input deny=%08x\n",
Linus Torvalds's avatar
Linus Torvalds committed
5472
			stp->st_deny_bmap, od->od_share_deny);
5473
		goto put_stateid;
Linus Torvalds's avatar
Linus Torvalds committed
5474
	}
5475
	nfs4_stateid_downgrade(stp, od->od_share_access);
5476
	reset_union_bmap_deny(od->od_share_deny, stp);
5477
	nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
5478
	status = nfs_ok;
5479
put_stateid:
5480
	mutex_unlock(&stp->st_mutex);
5481
	nfs4_put_stid(&stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
5482
out:
5483
	nfsd4_bump_seqid(cstate, status);
Linus Torvalds's avatar
Linus Torvalds committed
5484 5485 5486
	return status;
}

5487 5488
static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s)
{
5489
	struct nfs4_client *clp = s->st_stid.sc_client;
5490
	bool unhashed;
5491
	LIST_HEAD(reaplist);
5492

5493
	spin_lock(&clp->cl_lock);
5494
	unhashed = unhash_open_stateid(s, &reaplist);
5495

5496
	if (clp->cl_minorversion) {
5497 5498
		if (unhashed)
			put_ol_stateid_locked(s, &reaplist);
5499 5500 5501 5502 5503
		spin_unlock(&clp->cl_lock);
		free_ol_stateid_reaplist(&reaplist);
	} else {
		spin_unlock(&clp->cl_lock);
		free_ol_stateid_reaplist(&reaplist);
5504 5505
		if (unhashed)
			move_to_close_lru(s, clp->net);
5506
	}
5507 5508
}

Linus Torvalds's avatar
Linus Torvalds committed
5509 5510 5511
/*
 * nfs4_unlock_state() called after encode
 */
5512
__be32
5513
nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5514
		union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
5515
{
5516
	struct nfsd4_close *close = &u->close;
5517
	__be32 status;
5518
	struct nfs4_ol_stateid *stp;
5519 5520
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
5521

Al Viro's avatar
Al Viro committed
5522 5523
	dprintk("NFSD: nfsd4_close on file %pd\n", 
			cstate->current_fh.fh_dentry);
Linus Torvalds's avatar
Linus Torvalds committed
5524

5525 5526 5527
	status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid,
					&close->cl_stateid,
					NFS4_OPEN_STID|NFS4_CLOSED_STID,
5528
					&stp, nn);
5529
	nfsd4_bump_seqid(cstate, status);
5530
	if (status)
Linus Torvalds's avatar
Linus Torvalds committed
5531
		goto out; 
5532 5533

	stp->st_stid.sc_type = NFS4_CLOSED_STID;
5534 5535 5536 5537 5538 5539 5540

	/*
	 * Technically we don't _really_ have to increment or copy it, since
	 * it should just be gone after this operation and we clobber the
	 * copied value below, but we continue to do so here just to ensure
	 * that racing ops see that there was a state change.
	 */
5541
	nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
5542

5543
	nfsd4_close_open_stateid(stp);
5544
	mutex_unlock(&stp->st_mutex);
5545

5546 5547 5548 5549 5550 5551 5552 5553
	/* v4.1+ suggests that we send a special stateid in here, since the
	 * clients should just ignore this anyway. Since this is not useful
	 * for v4.0 clients either, we set it to the special close_stateid
	 * universally.
	 *
	 * See RFC5661 section 18.2.4, and RFC7530 section 16.2.5
	 */
	memcpy(&close->cl_stateid, &close_stateid, sizeof(close->cl_stateid));
5554

5555 5556
	/* put reference from nfs4_preprocess_seqid_op */
	nfs4_put_stid(&stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
5557 5558 5559 5560
out:
	return status;
}

5561
__be32
5562
nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5563
		  union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
5564
{
5565
	struct nfsd4_delegreturn *dr = &u->delegreturn;
5566 5567
	struct nfs4_delegation *dp;
	stateid_t *stateid = &dr->dr_stateid;
5568
	struct nfs4_stid *s;
5569
	__be32 status;
5570
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
5571

5572
	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
5573
		return status;
Linus Torvalds's avatar
Linus Torvalds committed
5574

5575
	status = nfsd4_lookup_stateid(cstate, stateid, NFS4_DELEG_STID, &s, nn);
5576
	if (status)
5577
		goto out;
5578
	dp = delegstateid(s);
5579
	status = nfsd4_stid_check_stateid_generation(stateid, &dp->dl_stid, nfsd4_has_session(cstate));
5580
	if (status)
5581
		goto put_stateid;
5582

5583
	destroy_delegation(dp);
5584 5585
put_stateid:
	nfs4_put_stid(&dp->dl_stid);
Linus Torvalds's avatar
Linus Torvalds committed
5586 5587 5588 5589
out:
	return status;
}

Benny Halevy's avatar
Benny Halevy committed
5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604
static inline u64
end_offset(u64 start, u64 len)
{
	u64 end;

	end = start + len;
	return end >= start ? end: NFS4_MAX_UINT64;
}

/* last octet in a range */
static inline u64
last_byte_offset(u64 start, u64 len)
{
	u64 end;

5605
	WARN_ON_ONCE(!len);
Benny Halevy's avatar
Benny Halevy committed
5606 5607 5608 5609
	end = start + len;
	return end > start ? end - 1: NFS4_MAX_UINT64;
}

Linus Torvalds's avatar
Linus Torvalds committed
5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626
/*
 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
 * byte, because of sign extension problems.  Since NFSv4 calls for 64-bit
 * locking, this prevents us from being completely protocol-compliant.  The
 * real solution to this problem is to start using unsigned file offsets in
 * the VFS, but this is a very deep change!
 */
static inline void
nfs4_transform_lock_offset(struct file_lock *lock)
{
	if (lock->fl_start < 0)
		lock->fl_start = OFFSET_MAX;
	if (lock->fl_end < 0)
		lock->fl_end = OFFSET_MAX;
}

5627 5628
static fl_owner_t
nfsd4_fl_get_owner(fl_owner_t owner)
5629
{
5630 5631 5632 5633
	struct nfs4_lockowner *lo = (struct nfs4_lockowner *)owner;

	nfs4_get_stateowner(&lo->lo_owner);
	return owner;
5634 5635
}

5636 5637
static void
nfsd4_fl_put_owner(fl_owner_t owner)
5638
{
5639
	struct nfs4_lockowner *lo = (struct nfs4_lockowner *)owner;
5640

5641
	if (lo)
5642 5643 5644
		nfs4_put_stateowner(&lo->lo_owner);
}

5645 5646 5647 5648 5649 5650 5651 5652 5653 5654
static void
nfsd4_lm_notify(struct file_lock *fl)
{
	struct nfs4_lockowner		*lo = (struct nfs4_lockowner *)fl->fl_owner;
	struct net			*net = lo->lo_owner.so_client->net;
	struct nfsd_net			*nn = net_generic(net, nfsd_net_id);
	struct nfsd4_blocked_lock	*nbl = container_of(fl,
						struct nfsd4_blocked_lock, nbl_lock);
	bool queue = false;

5655
	/* An empty list means that something else is going to be using it */
5656
	spin_lock(&nn->blocked_locks_lock);
5657 5658
	if (!list_empty(&nbl->nbl_list)) {
		list_del_init(&nbl->nbl_list);
5659
		list_del_init(&nbl->nbl_lru);
5660 5661
		queue = true;
	}
5662
	spin_unlock(&nn->blocked_locks_lock);
5663 5664 5665 5666 5667

	if (queue)
		nfsd4_run_cb(&nbl->nbl_cb);
}

5668
static const struct lock_manager_operations nfsd_posix_mng_ops  = {
5669
	.lm_notify = nfsd4_lm_notify,
5670 5671
	.lm_get_owner = nfsd4_fl_get_owner,
	.lm_put_owner = nfsd4_fl_put_owner,
5672
};
Linus Torvalds's avatar
Linus Torvalds committed
5673 5674 5675 5676

static inline void
nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
{
5677
	struct nfs4_lockowner *lo;
Linus Torvalds's avatar
Linus Torvalds committed
5678

5679
	if (fl->fl_lmops == &nfsd_posix_mng_ops) {
5680 5681 5682
		lo = (struct nfs4_lockowner *) fl->fl_owner;
		deny->ld_owner.data = kmemdup(lo->lo_owner.so_owner.data,
					lo->lo_owner.so_owner.len, GFP_KERNEL);
5683 5684 5685
		if (!deny->ld_owner.data)
			/* We just don't care that much */
			goto nevermind;
5686 5687
		deny->ld_owner.len = lo->lo_owner.so_owner.len;
		deny->ld_clientid = lo->lo_owner.so_client->cl_clientid;
5688
	} else {
5689 5690 5691
nevermind:
		deny->ld_owner.len = 0;
		deny->ld_owner.data = NULL;
5692 5693
		deny->ld_clientid.cl_boot = 0;
		deny->ld_clientid.cl_id = 0;
Linus Torvalds's avatar
Linus Torvalds committed
5694 5695
	}
	deny->ld_start = fl->fl_start;
Benny Halevy's avatar
Benny Halevy committed
5696 5697
	deny->ld_length = NFS4_MAX_UINT64;
	if (fl->fl_end != NFS4_MAX_UINT64)
Linus Torvalds's avatar
Linus Torvalds committed
5698 5699 5700 5701 5702 5703
		deny->ld_length = fl->fl_end - fl->fl_start + 1;        
	deny->ld_type = NFS4_READ_LT;
	if (fl->fl_type != F_RDLCK)
		deny->ld_type = NFS4_WRITE_LT;
}

5704
static struct nfs4_lockowner *
5705
find_lockowner_str_locked(struct nfs4_client *clp, struct xdr_netobj *owner)
Linus Torvalds's avatar
Linus Torvalds committed
5706
{
5707
	unsigned int strhashval = ownerstr_hashval(owner);
5708
	struct nfs4_stateowner *so;
Linus Torvalds's avatar
Linus Torvalds committed
5709

5710 5711
	lockdep_assert_held(&clp->cl_lock);

5712 5713
	list_for_each_entry(so, &clp->cl_ownerstr_hashtbl[strhashval],
			    so_strhash) {
5714 5715
		if (so->so_is_open_owner)
			continue;
5716 5717
		if (same_owner_str(so, owner))
			return lockowner(nfs4_get_stateowner(so));
Linus Torvalds's avatar
Linus Torvalds committed
5718 5719 5720 5721
	}
	return NULL;
}

5722
static struct nfs4_lockowner *
5723
find_lockowner_str(struct nfs4_client *clp, struct xdr_netobj *owner)
5724 5725 5726
{
	struct nfs4_lockowner *lo;

5727
	spin_lock(&clp->cl_lock);
5728
	lo = find_lockowner_str_locked(clp, owner);
5729
	spin_unlock(&clp->cl_lock);
5730 5731 5732
	return lo;
}

5733 5734
static void nfs4_unhash_lockowner(struct nfs4_stateowner *sop)
{
5735
	unhash_lockowner_locked(lockowner(sop));
5736 5737
}

5738 5739 5740 5741 5742 5743 5744 5745
static void nfs4_free_lockowner(struct nfs4_stateowner *sop)
{
	struct nfs4_lockowner *lo = lockowner(sop);

	kmem_cache_free(lockowner_slab, lo);
}

static const struct nfs4_stateowner_operations lockowner_ops = {
5746 5747
	.so_unhash =	nfs4_unhash_lockowner,
	.so_free =	nfs4_free_lockowner,
5748 5749
};

Linus Torvalds's avatar
Linus Torvalds committed
5750 5751 5752
/*
 * Alloc a lock owner structure.
 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 
Lucas De Marchi's avatar
Lucas De Marchi committed
5753
 * occurred. 
Linus Torvalds's avatar
Linus Torvalds committed
5754
 *
5755
 * strhashval = ownerstr_hashval
Linus Torvalds's avatar
Linus Torvalds committed
5756
 */
5757
static struct nfs4_lockowner *
5758 5759 5760 5761 5762
alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp,
			   struct nfs4_ol_stateid *open_stp,
			   struct nfsd4_lock *lock)
{
	struct nfs4_lockowner *lo, *ret;
Linus Torvalds's avatar
Linus Torvalds committed
5763

5764 5765
	lo = alloc_stateowner(lockowner_slab, &lock->lk_new_owner, clp);
	if (!lo)
Linus Torvalds's avatar
Linus Torvalds committed
5766
		return NULL;
5767
	INIT_LIST_HEAD(&lo->lo_blocked);
5768 5769
	INIT_LIST_HEAD(&lo->lo_owner.so_stateids);
	lo->lo_owner.so_is_open_owner = 0;
5770
	lo->lo_owner.so_seqid = lock->lk_new_lock_seqid;
5771
	lo->lo_owner.so_ops = &lockowner_ops;
5772
	spin_lock(&clp->cl_lock);
5773
	ret = find_lockowner_str_locked(clp, &lock->lk_new_owner);
5774 5775
	if (ret == NULL) {
		list_add(&lo->lo_owner.so_strhash,
5776
			 &clp->cl_ownerstr_hashtbl[strhashval]);
5777 5778
		ret = lo;
	} else
5779 5780
		nfs4_free_stateowner(&lo->lo_owner);

5781
	spin_unlock(&clp->cl_lock);
5782
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
5783 5784
}

5785
static struct nfs4_ol_stateid *
5786 5787
find_lock_stateid(const struct nfs4_lockowner *lo,
		  const struct nfs4_ol_stateid *ost)
5788 5789 5790
{
	struct nfs4_ol_stateid *lst;

5791
	lockdep_assert_held(&ost->st_stid.sc_client->cl_lock);
5792

5793 5794 5795 5796 5797 5798 5799
	/* If ost is not hashed, ost->st_locks will not be valid */
	if (!nfs4_ol_stateid_unhashed(ost))
		list_for_each_entry(lst, &ost->st_locks, st_locks) {
			if (lst->st_stateowner == &lo->lo_owner) {
				refcount_inc(&lst->st_stid.sc_count);
				return lst;
			}
5800 5801 5802 5803
		}
	return NULL;
}

5804
static struct nfs4_ol_stateid *
5805 5806 5807
init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
		  struct nfs4_file *fp, struct inode *inode,
		  struct nfs4_ol_stateid *open_stp)
Linus Torvalds's avatar
Linus Torvalds committed
5808
{
5809
	struct nfs4_client *clp = lo->lo_owner.so_client;
5810
	struct nfs4_ol_stateid *retstp;
Linus Torvalds's avatar
Linus Torvalds committed
5811

5812
	mutex_init(&stp->st_mutex);
5813
	mutex_lock_nested(&stp->st_mutex, OPEN_STATEID_MUTEX);
5814 5815
retry:
	spin_lock(&clp->cl_lock);
5816 5817 5818
	if (nfs4_ol_stateid_unhashed(open_stp))
		goto out_close;
	retstp = find_lock_stateid(lo, open_stp);
5819
	if (retstp)
5820
		goto out_found;
5821
	refcount_inc(&stp->st_stid.sc_count);
5822
	stp->st_stid.sc_type = NFS4_LOCK_STID;
5823
	stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
5824
	get_nfs4_file(fp);
5825
	stp->st_stid.sc_file = fp;
5826
	stp->st_access_bmap = 0;
Linus Torvalds's avatar
Linus Torvalds committed
5827
	stp->st_deny_bmap = open_stp->st_deny_bmap;
5828
	stp->st_openstp = open_stp;
5829
	spin_lock(&fp->fi_lock);
5830
	list_add(&stp->st_locks, &open_stp->st_locks);
5831
	list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
5832 5833
	list_add(&stp->st_perfile, &fp->fi_stateids);
	spin_unlock(&fp->fi_lock);
5834 5835
	spin_unlock(&clp->cl_lock);
	return stp;
5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848
out_found:
	spin_unlock(&clp->cl_lock);
	if (nfsd4_lock_ol_stateid(retstp) != nfs_ok) {
		nfs4_put_stid(&retstp->st_stid);
		goto retry;
	}
	/* To keep mutex tracking happy */
	mutex_unlock(&stp->st_mutex);
	return retstp;
out_close:
	spin_unlock(&clp->cl_lock);
	mutex_unlock(&stp->st_mutex);
	return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
5849 5850
}

5851 5852 5853 5854 5855 5856 5857 5858 5859 5860
static struct nfs4_ol_stateid *
find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi,
			    struct inode *inode, struct nfs4_ol_stateid *ost,
			    bool *new)
{
	struct nfs4_stid *ns = NULL;
	struct nfs4_ol_stateid *lst;
	struct nfs4_openowner *oo = openowner(ost->st_stateowner);
	struct nfs4_client *clp = oo->oo_owner.so_client;

5861
	*new = false;
5862
	spin_lock(&clp->cl_lock);
5863
	lst = find_lock_stateid(lo, ost);
5864
	spin_unlock(&clp->cl_lock);
5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877
	if (lst != NULL) {
		if (nfsd4_lock_ol_stateid(lst) == nfs_ok)
			goto out;
		nfs4_put_stid(&lst->st_stid);
	}
	ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid);
	if (ns == NULL)
		return NULL;

	lst = init_lock_stateid(openlockstateid(ns), lo, fi, inode, ost);
	if (lst == openlockstateid(ns))
		*new = true;
	else
5878
		nfs4_put_stid(ns);
5879
out:
5880 5881
	return lst;
}
5882

5883
static int
Linus Torvalds's avatar
Linus Torvalds committed
5884 5885
check_lock_length(u64 offset, u64 length)
{
5886 5887
	return ((length == 0) || ((length != NFS4_MAX_UINT64) &&
		(length > ~offset)));
Linus Torvalds's avatar
Linus Torvalds committed
5888 5889
}

5890
static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access)
5891
{
5892
	struct nfs4_file *fp = lock_stp->st_stid.sc_file;
5893

5894 5895
	lockdep_assert_held(&fp->fi_lock);

5896
	if (test_access(access, lock_stp))
5897
		return;
5898
	__nfs4_file_get_access(fp, access);
5899
	set_access(access, lock_stp);
5900 5901
}

5902 5903 5904 5905
static __be32
lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
			    struct nfs4_ol_stateid *ost,
			    struct nfsd4_lock *lock,
5906
			    struct nfs4_ol_stateid **plst, bool *new)
5907
{
5908
	__be32 status;
5909
	struct nfs4_file *fi = ost->st_stid.sc_file;
5910 5911
	struct nfs4_openowner *oo = openowner(ost->st_stateowner);
	struct nfs4_client *cl = oo->oo_owner.so_client;
5912
	struct inode *inode = d_inode(cstate->current_fh.fh_dentry);
5913
	struct nfs4_lockowner *lo;
5914
	struct nfs4_ol_stateid *lst;
5915 5916
	unsigned int strhashval;

5917
	lo = find_lockowner_str(cl, &lock->lk_new_owner);
5918
	if (!lo) {
5919
		strhashval = ownerstr_hashval(&lock->lk_new_owner);
5920 5921 5922 5923 5924
		lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock);
		if (lo == NULL)
			return nfserr_jukebox;
	} else {
		/* with an existing lockowner, seqids must be the same */
5925
		status = nfserr_bad_seqid;
5926 5927
		if (!cstate->minorversion &&
		    lock->lk_new_lock_seqid != lo->lo_owner.so_seqid)
5928
			goto out;
5929
	}
5930

5931 5932
	lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
	if (lst == NULL) {
5933 5934
		status = nfserr_jukebox;
		goto out;
5935
	}
5936

5937
	status = nfs_ok;
5938
	*plst = lst;
5939 5940 5941
out:
	nfs4_put_stateowner(&lo->lo_owner);
	return status;
5942 5943
}

Linus Torvalds's avatar
Linus Torvalds committed
5944 5945 5946
/*
 *  LOCK operation 
 */
5947
__be32
5948
nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5949
	   union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
5950
{
5951
	struct nfsd4_lock *lock = &u->lock;
5952 5953
	struct nfs4_openowner *open_sop = NULL;
	struct nfs4_lockowner *lock_sop = NULL;
5954
	struct nfs4_ol_stateid *lock_stp = NULL;
5955
	struct nfs4_ol_stateid *open_stp = NULL;
5956
	struct nfs4_file *fp;
5957
	struct file *filp = NULL;
5958
	struct nfsd4_blocked_lock *nbl = NULL;
5959 5960
	struct file_lock *file_lock = NULL;
	struct file_lock *conflock = NULL;
5961
	__be32 status = 0;
5962
	int lkflg;
5963
	int err;
5964
	bool new = false;
5965 5966
	unsigned char fl_type;
	unsigned int fl_flags = FL_POSIX;
5967 5968
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
5969 5970 5971 5972 5973 5974 5975 5976

	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
		(long long) lock->lk_offset,
		(long long) lock->lk_length);

	if (check_lock_length(lock->lk_offset, lock->lk_length))
		 return nfserr_inval;

5977
	if ((status = fh_verify(rqstp, &cstate->current_fh,
Miklos Szeredi's avatar
Miklos Szeredi committed
5978
				S_IFREG, NFSD_MAY_LOCK))) {
5979 5980 5981 5982
		dprintk("NFSD: nfsd4_lock: permission denied!\n");
		return status;
	}

Linus Torvalds's avatar
Linus Torvalds committed
5983
	if (lock->lk_is_new) {
5984 5985
		if (nfsd4_has_session(cstate))
			/* See rfc 5661 18.10.3: given clientid is ignored: */
5986
			memcpy(&lock->lk_new_clientid,
5987 5988 5989
				&cstate->session->se_client->cl_clientid,
				sizeof(clientid_t));

Linus Torvalds's avatar
Linus Torvalds committed
5990
		status = nfserr_stale_clientid;
5991
		if (STALE_CLIENTID(&lock->lk_new_clientid, nn))
Linus Torvalds's avatar
Linus Torvalds committed
5992 5993 5994
			goto out;

		/* validate and update open stateid and open seqid */
5995
		status = nfs4_preprocess_confirmed_seqid_op(cstate,
Linus Torvalds's avatar
Linus Torvalds committed
5996 5997
				        lock->lk_new_open_seqid,
		                        &lock->lk_new_open_stateid,
5998
					&open_stp, nn);
5999
		if (status)
Linus Torvalds's avatar
Linus Torvalds committed
6000
			goto out;
6001
		mutex_unlock(&open_stp->st_mutex);
6002
		open_sop = openowner(open_stp->st_stateowner);
6003
		status = nfserr_bad_stateid;
6004
		if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
6005
						&lock->lk_new_clientid))
6006
			goto out;
6007
		status = lookup_or_create_lock_state(cstate, open_stp, lock,
6008
							&lock_stp, &new);
6009
	} else {
6010
		status = nfs4_preprocess_seqid_op(cstate,
6011 6012
				       lock->lk_old_lock_seqid,
				       &lock->lk_old_lock_stateid,
6013
				       NFS4_LOCK_STID, &lock_stp, nn);
6014
	}
6015 6016
	if (status)
		goto out;
6017
	lock_sop = lockowner(lock_stp->st_stateowner);
Linus Torvalds's avatar
Linus Torvalds committed
6018

6019 6020 6021 6022 6023
	lkflg = setlkflg(lock->lk_type);
	status = nfs4_check_openmode(lock_stp, lkflg);
	if (status)
		goto out;

6024
	status = nfserr_grace;
6025
	if (locks_in_grace(net) && !lock->lk_reclaim)
6026 6027
		goto out;
	status = nfserr_no_grace;
6028
	if (!locks_in_grace(net) && lock->lk_reclaim)
6029 6030
		goto out;

6031
	fp = lock_stp->st_stid.sc_file;
Linus Torvalds's avatar
Linus Torvalds committed
6032 6033
	switch (lock->lk_type) {
		case NFS4_READW_LT:
6034 6035 6036 6037
			if (nfsd4_has_session(cstate))
				fl_flags |= FL_SLEEP;
			/* Fallthrough */
		case NFS4_READ_LT:
6038 6039
			spin_lock(&fp->fi_lock);
			filp = find_readable_file_locked(fp);
6040 6041
			if (filp)
				get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
6042
			spin_unlock(&fp->fi_lock);
6043
			fl_type = F_RDLCK;
6044
			break;
Linus Torvalds's avatar
Linus Torvalds committed
6045
		case NFS4_WRITEW_LT:
6046 6047 6048 6049
			if (nfsd4_has_session(cstate))
				fl_flags |= FL_SLEEP;
			/* Fallthrough */
		case NFS4_WRITE_LT:
6050 6051
			spin_lock(&fp->fi_lock);
			filp = find_writeable_file_locked(fp);
6052 6053
			if (filp)
				get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
6054
			spin_unlock(&fp->fi_lock);
6055
			fl_type = F_WRLCK;
6056
			break;
Linus Torvalds's avatar
Linus Torvalds committed
6057 6058 6059 6060
		default:
			status = nfserr_inval;
		goto out;
	}
6061

6062 6063 6064 6065
	if (!filp) {
		status = nfserr_openmode;
		goto out;
	}
6066

6067 6068 6069 6070 6071 6072 6073 6074 6075
	nbl = find_or_allocate_block(lock_sop, &fp->fi_fhandle, nn);
	if (!nbl) {
		dprintk("NFSD: %s: unable to allocate block!\n", __func__);
		status = nfserr_jukebox;
		goto out;
	}

	file_lock = &nbl->nbl_lock;
	file_lock->fl_type = fl_type;
6076
	file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lock_sop->lo_owner));
6077 6078
	file_lock->fl_pid = current->tgid;
	file_lock->fl_file = filp;
6079
	file_lock->fl_flags = fl_flags;
6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090
	file_lock->fl_lmops = &nfsd_posix_mng_ops;
	file_lock->fl_start = lock->lk_offset;
	file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
	nfs4_transform_lock_offset(file_lock);

	conflock = locks_alloc_lock();
	if (!conflock) {
		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
		status = nfserr_jukebox;
		goto out;
	}
Linus Torvalds's avatar
Linus Torvalds committed
6091

6092
	if (fl_flags & FL_SLEEP) {
6093
		nbl->nbl_time = get_seconds();
6094
		spin_lock(&nn->blocked_locks_lock);
6095
		list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked);
6096
		list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru);
6097
		spin_unlock(&nn->blocked_locks_lock);
6098 6099
	}

6100
	err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
6101
	switch (err) {
Linus Torvalds's avatar
Linus Torvalds committed
6102
	case 0: /* success! */
6103
		nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid);
6104
		status = 0;
6105 6106
		if (lock->lk_reclaim)
			nn->somebody_reclaimed = true;
6107
		break;
6108 6109 6110 6111
	case FILE_LOCK_DEFERRED:
		nbl = NULL;
		/* Fallthrough */
	case -EAGAIN:		/* conflock holds conflicting lock */
6112 6113
		status = nfserr_denied;
		dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
6114
		nfs4_set_lock_denied(conflock, &lock->lk_denied);
6115
		break;
6116
	case -EDEADLK:
Linus Torvalds's avatar
Linus Torvalds committed
6117
		status = nfserr_deadlock;
6118
		break;
6119
	default:
6120
		dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d\n",err);
6121
		status = nfserrno(err);
6122
		break;
Linus Torvalds's avatar
Linus Torvalds committed
6123 6124
	}
out:
6125 6126 6127
	if (nbl) {
		/* dequeue it if we queued it before */
		if (fl_flags & FL_SLEEP) {
6128
			spin_lock(&nn->blocked_locks_lock);
6129
			list_del_init(&nbl->nbl_list);
6130
			list_del_init(&nbl->nbl_lru);
6131
			spin_unlock(&nn->blocked_locks_lock);
6132 6133 6134
		}
		free_blocked_lock(nbl);
	}
6135 6136
	if (filp)
		fput(filp);
6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147
	if (lock_stp) {
		/* Bump seqid manually if the 4.0 replay owner is openowner */
		if (cstate->replay_owner &&
		    cstate->replay_owner != &lock_sop->lo_owner &&
		    seqid_mutating_err(ntohl(status)))
			lock_sop->lo_owner.so_seqid++;

		/*
		 * If this is a new, never-before-used stateid, and we are
		 * returning an error, then just go ahead and release it.
		 */
6148
		if (status && new)
6149
			release_lock_stateid(lock_stp);
6150 6151

		mutex_unlock(&lock_stp->st_mutex);
6152

6153
		nfs4_put_stid(&lock_stp->st_stid);
6154
	}
6155 6156
	if (open_stp)
		nfs4_put_stid(&open_stp->st_stid);
6157
	nfsd4_bump_seqid(cstate, status);
6158 6159
	if (conflock)
		locks_free_lock(conflock);
Linus Torvalds's avatar
Linus Torvalds committed
6160 6161 6162
	return status;
}

6163 6164 6165 6166 6167 6168
/*
 * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN,
 * so we do a temporary open here just to get an open file to pass to
 * vfs_test_lock.  (Arguably perhaps test_lock should be done with an
 * inode operation.)
 */
6169
static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
6170 6171
{
	struct file *file;
6172 6173 6174
	__be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
	if (!err) {
		err = nfserrno(vfs_test_lock(file, lock));
6175
		fput(file);
6176
	}
6177 6178 6179
	return err;
}

Linus Torvalds's avatar
Linus Torvalds committed
6180 6181 6182
/*
 * LOCKT operation
 */
6183
__be32
6184
nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
6185
	    union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
6186
{
6187
	struct nfsd4_lockt *lockt = &u->lockt;
6188
	struct file_lock *file_lock = NULL;
6189
	struct nfs4_lockowner *lo = NULL;
6190
	__be32 status;
6191
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
6192

6193
	if (locks_in_grace(SVC_NET(rqstp)))
Linus Torvalds's avatar
Linus Torvalds committed
6194 6195 6196 6197 6198
		return nfserr_grace;

	if (check_lock_length(lockt->lt_offset, lockt->lt_length))
		 return nfserr_inval;

6199
	if (!nfsd4_has_session(cstate)) {
6200
		status = lookup_clientid(&lockt->lt_clientid, cstate, nn);
6201 6202 6203
		if (status)
			goto out;
	}
Linus Torvalds's avatar
Linus Torvalds committed
6204

6205
	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
Linus Torvalds's avatar
Linus Torvalds committed
6206 6207
		goto out;

6208 6209 6210 6211 6212 6213
	file_lock = locks_alloc_lock();
	if (!file_lock) {
		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
		status = nfserr_jukebox;
		goto out;
	}
6214

Linus Torvalds's avatar
Linus Torvalds committed
6215 6216 6217
	switch (lockt->lt_type) {
		case NFS4_READ_LT:
		case NFS4_READW_LT:
6218
			file_lock->fl_type = F_RDLCK;
Linus Torvalds's avatar
Linus Torvalds committed
6219 6220 6221
		break;
		case NFS4_WRITE_LT:
		case NFS4_WRITEW_LT:
6222
			file_lock->fl_type = F_WRLCK;
Linus Torvalds's avatar
Linus Torvalds committed
6223 6224
		break;
		default:
6225
			dprintk("NFSD: nfs4_lockt: bad lock type!\n");
Linus Torvalds's avatar
Linus Torvalds committed
6226 6227 6228 6229
			status = nfserr_inval;
		goto out;
	}

6230
	lo = find_lockowner_str(cstate->clp, &lockt->lt_owner);
6231
	if (lo)
6232 6233 6234
		file_lock->fl_owner = (fl_owner_t)lo;
	file_lock->fl_pid = current->tgid;
	file_lock->fl_flags = FL_POSIX;
Linus Torvalds's avatar
Linus Torvalds committed
6235

6236 6237
	file_lock->fl_start = lockt->lt_offset;
	file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
Linus Torvalds's avatar
Linus Torvalds committed
6238

6239
	nfs4_transform_lock_offset(file_lock);
Linus Torvalds's avatar
Linus Torvalds committed
6240

6241
	status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
6242
	if (status)
6243
		goto out;
6244

6245
	if (file_lock->fl_type != F_UNLCK) {
Linus Torvalds's avatar
Linus Torvalds committed
6246
		status = nfserr_denied;
6247
		nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
Linus Torvalds's avatar
Linus Torvalds committed
6248 6249
	}
out:
6250 6251
	if (lo)
		nfs4_put_stateowner(&lo->lo_owner);
6252 6253
	if (file_lock)
		locks_free_lock(file_lock);
Linus Torvalds's avatar
Linus Torvalds committed
6254 6255 6256
	return status;
}

6257
__be32
6258
nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
6259
	    union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
6260
{
6261
	struct nfsd4_locku *locku = &u->locku;
6262
	struct nfs4_ol_stateid *stp;
Linus Torvalds's avatar
Linus Torvalds committed
6263
	struct file *filp = NULL;
6264
	struct file_lock *file_lock = NULL;
6265
	__be32 status;
6266
	int err;
6267 6268
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);

Linus Torvalds's avatar
Linus Torvalds committed
6269 6270 6271 6272 6273 6274 6275
	dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
		(long long) locku->lu_offset,
		(long long) locku->lu_length);

	if (check_lock_length(locku->lu_offset, locku->lu_length))
		 return nfserr_inval;

6276
	status = nfs4_preprocess_seqid_op(cstate, locku->lu_seqid,
6277 6278
					&locku->lu_stateid, NFS4_LOCK_STID,
					&stp, nn);
6279
	if (status)
Linus Torvalds's avatar
Linus Torvalds committed
6280
		goto out;
6281
	filp = find_any_file(stp->st_stid.sc_file);
6282 6283
	if (!filp) {
		status = nfserr_lock_range;
6284
		goto put_stateid;
6285
	}
6286 6287 6288 6289
	file_lock = locks_alloc_lock();
	if (!file_lock) {
		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
		status = nfserr_jukebox;
6290
		goto fput;
6291
	}
6292

6293
	file_lock->fl_type = F_UNLCK;
6294
	file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(stp->st_stateowner));
6295 6296 6297 6298 6299 6300 6301 6302 6303
	file_lock->fl_pid = current->tgid;
	file_lock->fl_file = filp;
	file_lock->fl_flags = FL_POSIX;
	file_lock->fl_lmops = &nfsd_posix_mng_ops;
	file_lock->fl_start = locku->lu_offset;

	file_lock->fl_end = last_byte_offset(locku->lu_offset,
						locku->lu_length);
	nfs4_transform_lock_offset(file_lock);
Linus Torvalds's avatar
Linus Torvalds committed
6304

6305
	err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
6306
	if (err) {
6307
		dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
Linus Torvalds's avatar
Linus Torvalds committed
6308 6309
		goto out_nfserr;
	}
6310
	nfs4_inc_and_copy_stateid(&locku->lu_stateid, &stp->st_stid);
6311 6312
fput:
	fput(filp);
6313
put_stateid:
6314
	mutex_unlock(&stp->st_mutex);
6315
	nfs4_put_stid(&stp->st_stid);
Linus Torvalds's avatar
Linus Torvalds committed
6316
out:
6317
	nfsd4_bump_seqid(cstate, status);
6318 6319
	if (file_lock)
		locks_free_lock(file_lock);
Linus Torvalds's avatar
Linus Torvalds committed
6320 6321 6322
	return status;

out_nfserr:
6323
	status = nfserrno(err);
6324
	goto fput;
Linus Torvalds's avatar
Linus Torvalds committed
6325 6326 6327 6328
}

/*
 * returns
6329 6330
 * 	true:  locks held by lockowner
 * 	false: no locks held by lockowner
Linus Torvalds's avatar
Linus Torvalds committed
6331
 */
6332 6333
static bool
check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
Linus Torvalds's avatar
Linus Torvalds committed
6334
{
6335
	struct file_lock *fl;
6336 6337 6338
	int status = false;
	struct file *filp = find_any_file(fp);
	struct inode *inode;
6339
	struct file_lock_context *flctx;
6340 6341 6342 6343 6344 6345 6346

	if (!filp) {
		/* Any valid lock stateid should have some sort of access */
		WARN_ON_ONCE(1);
		return status;
	}

6347
	inode = locks_inode(filp);
6348 6349 6350
	flctx = inode->i_flctx;

	if (flctx && !list_empty_careful(&flctx->flc_posix)) {
6351
		spin_lock(&flctx->flc_lock);
6352 6353 6354 6355 6356
		list_for_each_entry(fl, &flctx->flc_posix, fl_list) {
			if (fl->fl_owner == (fl_owner_t)lowner) {
				status = true;
				break;
			}
6357
		}
6358
		spin_unlock(&flctx->flc_lock);
Linus Torvalds's avatar
Linus Torvalds committed
6359
	}
6360
	fput(filp);
Linus Torvalds's avatar
Linus Torvalds committed
6361 6362 6363
	return status;
}

6364
__be32
6365 6366
nfsd4_release_lockowner(struct svc_rqst *rqstp,
			struct nfsd4_compound_state *cstate,
6367
			union nfsd4_op_u *u)
Linus Torvalds's avatar
Linus Torvalds committed
6368
{
6369
	struct nfsd4_release_lockowner *rlockowner = &u->release_lockowner;
Linus Torvalds's avatar
Linus Torvalds committed
6370
	clientid_t *clid = &rlockowner->rl_clientid;
6371 6372
	struct nfs4_stateowner *sop;
	struct nfs4_lockowner *lo = NULL;
6373
	struct nfs4_ol_stateid *stp;
Linus Torvalds's avatar
Linus Torvalds committed
6374
	struct xdr_netobj *owner = &rlockowner->rl_owner;
6375
	unsigned int hashval = ownerstr_hashval(owner);
6376
	__be32 status;
6377
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
6378
	struct nfs4_client *clp;
6379
	LIST_HEAD (reaplist);
Linus Torvalds's avatar
Linus Torvalds committed
6380 6381 6382 6383

	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
		clid->cl_boot, clid->cl_id);

6384
	status = lookup_clientid(clid, cstate, nn);
6385
	if (status)
6386
		return status;
6387

6388
	clp = cstate->clp;
6389
	/* Find the matching lock stateowner */
6390
	spin_lock(&clp->cl_lock);
6391
	list_for_each_entry(sop, &clp->cl_ownerstr_hashtbl[hashval],
6392
			    so_strhash) {
6393

6394 6395
		if (sop->so_is_open_owner || !same_owner_str(sop, owner))
			continue;
6396

6397 6398 6399 6400 6401 6402
		/* see if there are still any locks associated with it */
		lo = lockowner(sop);
		list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) {
			if (check_for_locks(stp->st_stid.sc_file, lo)) {
				status = nfserr_locks_held;
				spin_unlock(&clp->cl_lock);
6403
				return status;
6404
			}
6405
		}
6406

6407
		nfs4_get_stateowner(sop);
6408
		break;
Linus Torvalds's avatar
Linus Torvalds committed
6409
	}
6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422
	if (!lo) {
		spin_unlock(&clp->cl_lock);
		return status;
	}

	unhash_lockowner_locked(lo);
	while (!list_empty(&lo->lo_owner.so_stateids)) {
		stp = list_first_entry(&lo->lo_owner.so_stateids,
				       struct nfs4_ol_stateid,
				       st_perstateowner);
		WARN_ON(!unhash_lock_stateid(stp));
		put_ol_stateid_locked(stp, &reaplist);
	}
6423
	spin_unlock(&clp->cl_lock);
6424
	free_ol_stateid_reaplist(&reaplist);
6425
	remove_blocked_locks(lo);
6426 6427
	nfs4_put_stateowner(&lo->lo_owner);

Linus Torvalds's avatar
Linus Torvalds committed
6428 6429 6430 6431
	return status;
}

static inline struct nfs4_client_reclaim *
6432
alloc_reclaim(void)
Linus Torvalds's avatar
Linus Torvalds committed
6433
{
6434
	return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
6435 6436
}

6437
bool
6438
nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
6439
{
6440
	struct nfs4_client_reclaim *crp;
6441

6442
	crp = nfsd4_find_reclaim_client(name, nn);
6443
	return (crp && crp->cr_clp);
6444 6445
}

Linus Torvalds's avatar
Linus Torvalds committed
6446 6447 6448
/*
 * failure => all reset bets are off, nfserr_no_grace...
 */
6449
struct nfs4_client_reclaim *
6450
nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
6451 6452
{
	unsigned int strhashval;
6453
	struct nfs4_client_reclaim *crp;
Linus Torvalds's avatar
Linus Torvalds committed
6454

6455 6456
	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
	crp = alloc_reclaim();
6457 6458 6459
	if (crp) {
		strhashval = clientstr_hashval(name);
		INIT_LIST_HEAD(&crp->cr_strhash);
6460
		list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
6461
		memcpy(crp->cr_recdir, name, HEXDIR_LEN);
6462
		crp->cr_clp = NULL;
6463
		nn->reclaim_str_hashtbl_size++;
6464 6465
	}
	return crp;
Linus Torvalds's avatar
Linus Torvalds committed
6466 6467
}

6468
void
6469
nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
6470 6471 6472
{
	list_del(&crp->cr_strhash);
	kfree(crp);
6473
	nn->reclaim_str_hashtbl_size--;
6474 6475
}

6476
void
6477
nfs4_release_reclaim(struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
6478 6479 6480 6481 6482
{
	struct nfs4_client_reclaim *crp = NULL;
	int i;

	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
6483 6484
		while (!list_empty(&nn->reclaim_str_hashtbl[i])) {
			crp = list_entry(nn->reclaim_str_hashtbl[i].next,
Linus Torvalds's avatar
Linus Torvalds committed
6485
			                struct nfs4_client_reclaim, cr_strhash);
6486
			nfs4_remove_reclaim_record(crp, nn);
Linus Torvalds's avatar
Linus Torvalds committed
6487 6488
		}
	}
6489
	WARN_ON_ONCE(nn->reclaim_str_hashtbl_size);
Linus Torvalds's avatar
Linus Torvalds committed
6490 6491 6492 6493
}

/*
 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
6494
struct nfs4_client_reclaim *
6495
nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
6496 6497 6498 6499
{
	unsigned int strhashval;
	struct nfs4_client_reclaim *crp = NULL;

6500
	dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir);
Linus Torvalds's avatar
Linus Torvalds committed
6501

6502
	strhashval = clientstr_hashval(recdir);
6503
	list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
6504
		if (same_name(crp->cr_recdir, recdir)) {
Linus Torvalds's avatar
Linus Torvalds committed
6505 6506 6507 6508 6509 6510 6511 6512 6513
			return crp;
		}
	}
	return NULL;
}

/*
* Called from OPEN. Look for clientid in reclaim list.
*/
6514
__be32
6515 6516 6517
nfs4_check_open_reclaim(clientid_t *clid,
		struct nfsd4_compound_state *cstate,
		struct nfsd_net *nn)
Linus Torvalds's avatar
Linus Torvalds committed
6518
{
6519
	__be32 status;
6520 6521

	/* find clientid in conf_id_hashtbl */
6522 6523
	status = lookup_clientid(clid, cstate, nn);
	if (status)
6524 6525
		return nfserr_reclaim_bad;

6526 6527 6528
	if (test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, &cstate->clp->cl_flags))
		return nfserr_no_grace;

6529 6530 6531 6532
	if (nfsd4_client_record_check(cstate->clp))
		return nfserr_reclaim_bad;

	return nfs_ok;
Linus Torvalds's avatar
Linus Torvalds committed
6533 6534
}

6535
#ifdef CONFIG_NFSD_FAULT_INJECTION
6536 6537 6538 6539 6540 6541
static inline void
put_client(struct nfs4_client *clp)
{
	atomic_dec(&clp->cl_refcount);
}

6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558
static struct nfs4_client *
nfsd_find_client(struct sockaddr_storage *addr, size_t addr_size)
{
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
					  nfsd_net_id);

	if (!nfsd_netns_ready(nn))
		return NULL;

	list_for_each_entry(clp, &nn->client_lru, cl_lru) {
		if (memcmp(&clp->cl_addr, addr, addr_size) == 0)
			return clp;
	}
	return NULL;
}

6559
u64
6560
nfsd_inject_print_clients(void)
6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580
{
	struct nfs4_client *clp;
	u64 count = 0;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
					  nfsd_net_id);
	char buf[INET6_ADDRSTRLEN];

	if (!nfsd_netns_ready(nn))
		return 0;

	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru) {
		rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
		pr_info("NFS Client: %s\n", buf);
		++count;
	}
	spin_unlock(&nn->client_lock);

	return count;
}
6581

6582
u64
6583
nfsd_inject_forget_client(struct sockaddr_storage *addr, size_t addr_size)
6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608
{
	u64 count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
					  nfsd_net_id);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	clp = nfsd_find_client(addr, addr_size);
	if (clp) {
		if (mark_client_expired_locked(clp) == nfs_ok)
			++count;
		else
			clp = NULL;
	}
	spin_unlock(&nn->client_lock);

	if (clp)
		expire_client(clp);

	return count;
}

6609
u64
6610
nfsd_inject_forget_clients(u64 max)
6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636
{
	u64 count = 0;
	struct nfs4_client *clp, *next;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
		if (mark_client_expired_locked(clp) == nfs_ok) {
			list_add(&clp->cl_lru, &reaplist);
			if (max != 0 && ++count >= max)
				break;
		}
	}
	spin_unlock(&nn->client_lock);

	list_for_each_entry_safe(clp, next, &reaplist, cl_lru)
		expire_client(clp);

	return count;
}

6637 6638 6639 6640
static void nfsd_print_count(struct nfs4_client *clp, unsigned int count,
			     const char *type)
{
	char buf[INET6_ADDRSTRLEN];
6641
	rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
6642 6643 6644
	printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type);
}

6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660
static void
nfsd_inject_add_lock_to_list(struct nfs4_ol_stateid *lst,
			     struct list_head *collect)
{
	struct nfs4_client *clp = lst->st_stid.sc_client;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
					  nfsd_net_id);

	if (!collect)
		return;

	lockdep_assert_held(&nn->client_lock);
	atomic_inc(&clp->cl_refcount);
	list_add(&lst->st_locks, collect);
}

6661
static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max,
6662
				    struct list_head *collect,
6663
				    bool (*func)(struct nfs4_ol_stateid *))
6664 6665 6666
{
	struct nfs4_openowner *oop;
	struct nfs4_ol_stateid *stp, *st_next;
6667
	struct nfs4_ol_stateid *lst, *lst_next;
6668 6669
	u64 count = 0;

6670
	spin_lock(&clp->cl_lock);
6671
	list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) {
6672 6673 6674 6675
		list_for_each_entry_safe(stp, st_next,
				&oop->oo_owner.so_stateids, st_perstateowner) {
			list_for_each_entry_safe(lst, lst_next,
					&stp->st_locks, st_locks) {
6676
				if (func) {
6677 6678 6679
					if (func(lst))
						nfsd_inject_add_lock_to_list(lst,
									collect);
6680
				}
6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691
				++count;
				/*
				 * Despite the fact that these functions deal
				 * with 64-bit integers for "count", we must
				 * ensure that it doesn't blow up the
				 * clp->cl_refcount. Throw a warning if we
				 * start to approach INT_MAX here.
				 */
				WARN_ON_ONCE(count == (INT_MAX / 2));
				if (count == max)
					goto out;
6692 6693 6694
			}
		}
	}
6695 6696
out:
	spin_unlock(&clp->cl_lock);
6697 6698 6699 6700

	return count;
}

6701 6702 6703
static u64
nfsd_collect_client_locks(struct nfs4_client *clp, struct list_head *collect,
			  u64 max)
6704
{
6705
	return nfsd_foreach_client_lock(clp, max, collect, unhash_lock_stateid);
6706 6707
}

6708 6709
static u64
nfsd_print_client_locks(struct nfs4_client *clp)
6710
{
6711
	u64 count = nfsd_foreach_client_lock(clp, 0, NULL, NULL);
6712 6713 6714 6715
	nfsd_print_count(clp, count, "locked files");
	return count;
}

6716
u64
6717
nfsd_inject_print_locks(void)
6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749
{
	struct nfs4_client *clp;
	u64 count = 0;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);

	if (!nfsd_netns_ready(nn))
		return 0;

	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru)
		count += nfsd_print_client_locks(clp);
	spin_unlock(&nn->client_lock);

	return count;
}

static void
nfsd_reap_locks(struct list_head *reaplist)
{
	struct nfs4_client *clp;
	struct nfs4_ol_stateid *stp, *next;

	list_for_each_entry_safe(stp, next, reaplist, st_locks) {
		list_del_init(&stp->st_locks);
		clp = stp->st_stid.sc_client;
		nfs4_put_stid(&stp->st_stid);
		put_client(clp);
	}
}

u64
6750
nfsd_inject_forget_client_locks(struct sockaddr_storage *addr, size_t addr_size)
6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770
{
	unsigned int count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	clp = nfsd_find_client(addr, addr_size);
	if (clp)
		count = nfsd_collect_client_locks(clp, &reaplist, 0);
	spin_unlock(&nn->client_lock);
	nfsd_reap_locks(&reaplist);
	return count;
}

u64
6771
nfsd_inject_forget_locks(u64 max)
6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792
{
	u64 count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru) {
		count += nfsd_collect_client_locks(clp, &reaplist, max - count);
		if (max != 0 && count >= max)
			break;
	}
	spin_unlock(&nn->client_lock);
	nfsd_reap_locks(&reaplist);
	return count;
}

6793 6794 6795 6796
static u64
nfsd_foreach_client_openowner(struct nfs4_client *clp, u64 max,
			      struct list_head *collect,
			      void (*func)(struct nfs4_openowner *))
6797 6798
{
	struct nfs4_openowner *oop, *next;
6799 6800
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
6801 6802
	u64 count = 0;

6803 6804 6805
	lockdep_assert_held(&nn->client_lock);

	spin_lock(&clp->cl_lock);
6806
	list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) {
6807
		if (func) {
6808
			func(oop);
6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822
			if (collect) {
				atomic_inc(&clp->cl_refcount);
				list_add(&oop->oo_perclient, collect);
			}
		}
		++count;
		/*
		 * Despite the fact that these functions deal with
		 * 64-bit integers for "count", we must ensure that
		 * it doesn't blow up the clp->cl_refcount. Throw a
		 * warning if we start to approach INT_MAX here.
		 */
		WARN_ON_ONCE(count == (INT_MAX / 2));
		if (count == max)
6823 6824
			break;
	}
6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847
	spin_unlock(&clp->cl_lock);

	return count;
}

static u64
nfsd_print_client_openowners(struct nfs4_client *clp)
{
	u64 count = nfsd_foreach_client_openowner(clp, 0, NULL, NULL);

	nfsd_print_count(clp, count, "openowners");
	return count;
}

static u64
nfsd_collect_client_openowners(struct nfs4_client *clp,
			       struct list_head *collect, u64 max)
{
	return nfsd_foreach_client_openowner(clp, max, collect,
						unhash_openowner_locked);
}

u64
6848
nfsd_inject_print_openowners(void)
6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861
{
	struct nfs4_client *clp;
	u64 count = 0;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);

	if (!nfsd_netns_ready(nn))
		return 0;

	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru)
		count += nfsd_print_client_openowners(clp);
	spin_unlock(&nn->client_lock);
6862 6863 6864 6865

	return count;
}

6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880
static void
nfsd_reap_openowners(struct list_head *reaplist)
{
	struct nfs4_client *clp;
	struct nfs4_openowner *oop, *next;

	list_for_each_entry_safe(oop, next, reaplist, oo_perclient) {
		list_del_init(&oop->oo_perclient);
		clp = oop->oo_owner.so_client;
		release_openowner(oop);
		put_client(clp);
	}
}

u64
6881 6882
nfsd_inject_forget_client_openowners(struct sockaddr_storage *addr,
				     size_t addr_size)
6883
{
6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899
	unsigned int count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	clp = nfsd_find_client(addr, addr_size);
	if (clp)
		count = nfsd_collect_client_openowners(clp, &reaplist, 0);
	spin_unlock(&nn->client_lock);
	nfsd_reap_openowners(&reaplist);
	return count;
6900 6901
}

6902
u64
6903
nfsd_inject_forget_openowners(u64 max)
6904
{
6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922
	u64 count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru) {
		count += nfsd_collect_client_openowners(clp, &reaplist,
							max - count);
		if (max != 0 && count >= max)
			break;
	}
	spin_unlock(&nn->client_lock);
	nfsd_reap_openowners(&reaplist);
6923 6924 6925
	return count;
}

6926 6927 6928 6929
static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max,
				     struct list_head *victims)
{
	struct nfs4_delegation *dp, *next;
6930 6931
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
6932 6933
	u64 count = 0;

6934 6935 6936
	lockdep_assert_held(&nn->client_lock);

	spin_lock(&state_lock);
6937
	list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) {
6938 6939 6940 6941 6942 6943 6944 6945 6946 6947
		if (victims) {
			/*
			 * It's not safe to mess with delegations that have a
			 * non-zero dl_time. They might have already been broken
			 * and could be processed by the laundromat outside of
			 * the state_lock. Just leave them be.
			 */
			if (dp->dl_time != 0)
				continue;

6948
			atomic_inc(&clp->cl_refcount);
6949
			WARN_ON(!unhash_delegation_locked(dp));
6950
			list_add(&dp->dl_recall_lru, victims);
6951
		}
6952 6953 6954 6955 6956 6957 6958 6959 6960
		++count;
		/*
		 * Despite the fact that these functions deal with
		 * 64-bit integers for "count", we must ensure that
		 * it doesn't blow up the clp->cl_refcount. Throw a
		 * warning if we start to approach INT_MAX here.
		 */
		WARN_ON_ONCE(count == (INT_MAX / 2));
		if (count == max)
6961 6962
			break;
	}
6963
	spin_unlock(&state_lock);
6964 6965 6966
	return count;
}

6967 6968
static u64
nfsd_print_client_delegations(struct nfs4_client *clp)
6969
{
6970
	u64 count = nfsd_find_all_delegations(clp, 0, NULL);
6971

6972 6973 6974 6975 6976
	nfsd_print_count(clp, count, "delegations");
	return count;
}

u64
6977
nfsd_inject_print_delegations(void)
6978 6979 6980 6981 6982 6983 6984 6985
{
	struct nfs4_client *clp;
	u64 count = 0;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);

	if (!nfsd_netns_ready(nn))
		return 0;
6986

6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001
	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru)
		count += nfsd_print_client_delegations(clp);
	spin_unlock(&nn->client_lock);

	return count;
}

static void
nfsd_forget_delegations(struct list_head *reaplist)
{
	struct nfs4_client *clp;
	struct nfs4_delegation *dp, *next;

	list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) {
7002
		list_del_init(&dp->dl_recall_lru);
7003
		clp = dp->dl_stid.sc_client;
7004
		revoke_delegation(dp);
7005
		put_client(clp);
7006
	}
7007 7008 7009
}

u64
7010 7011
nfsd_inject_forget_client_delegations(struct sockaddr_storage *addr,
				      size_t addr_size)
7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030
{
	u64 count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	clp = nfsd_find_client(addr, addr_size);
	if (clp)
		count = nfsd_find_all_delegations(clp, 0, &reaplist);
	spin_unlock(&nn->client_lock);

	nfsd_forget_delegations(&reaplist);
	return count;
}
7031

7032
u64
7033
nfsd_inject_forget_delegations(u64 max)
7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051
{
	u64 count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	list_for_each_entry(clp, &nn->client_lru, cl_lru) {
		count += nfsd_find_all_delegations(clp, max - count, &reaplist);
		if (max != 0 && count >= max)
			break;
	}
	spin_unlock(&nn->client_lock);
	nfsd_forget_delegations(&reaplist);
7052 7053 7054
	return count;
}

7055 7056
static void
nfsd_recall_delegations(struct list_head *reaplist)
7057
{
7058 7059
	struct nfs4_client *clp;
	struct nfs4_delegation *dp, *next;
7060

7061
	list_for_each_entry_safe(dp, next, reaplist, dl_recall_lru) {
7062
		list_del_init(&dp->dl_recall_lru);
7063 7064 7065 7066 7067 7068 7069 7070
		clp = dp->dl_stid.sc_client;
		/*
		 * We skipped all entries that had a zero dl_time before,
		 * so we can now reset the dl_time back to 0. If a delegation
		 * break comes in now, then it won't make any difference since
		 * we're recalling it either way.
		 */
		spin_lock(&state_lock);
7071
		dp->dl_time = 0;
7072
		spin_unlock(&state_lock);
7073
		nfsd_break_one_deleg(dp);
7074
		put_client(clp);
7075
	}
7076
}
7077

7078
u64
7079
nfsd_inject_recall_client_delegations(struct sockaddr_storage *addr,
7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097
				      size_t addr_size)
{
	u64 count = 0;
	struct nfs4_client *clp;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);

	if (!nfsd_netns_ready(nn))
		return count;

	spin_lock(&nn->client_lock);
	clp = nfsd_find_client(addr, addr_size);
	if (clp)
		count = nfsd_find_all_delegations(clp, 0, &reaplist);
	spin_unlock(&nn->client_lock);

	nfsd_recall_delegations(&reaplist);
7098 7099 7100
	return count;
}

7101
u64
7102
nfsd_inject_recall_delegations(u64 max)
7103 7104
{
	u64 count = 0;
7105 7106 7107 7108
	struct nfs4_client *clp, *next;
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
						nfsd_net_id);
	LIST_HEAD(reaplist);
7109

7110 7111
	if (!nfsd_netns_ready(nn))
		return count;
7112

7113 7114 7115 7116 7117 7118 7119 7120
	spin_lock(&nn->client_lock);
	list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
		count += nfsd_find_all_delegations(clp, max - count, &reaplist);
		if (max != 0 && ++count >= max)
			break;
	}
	spin_unlock(&nn->client_lock);
	nfsd_recall_delegations(&reaplist);
7121 7122
	return count;
}
7123 7124
#endif /* CONFIG_NFSD_FAULT_INJECTION */

7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145
/*
 * Since the lifetime of a delegation isn't limited to that of an open, a
 * client may quite reasonably hang on to a delegation as long as it has
 * the inode cached.  This becomes an obvious problem the first time a
 * client's inode cache approaches the size of the server's total memory.
 *
 * For now we avoid this problem by imposing a hard limit on the number
 * of delegations, which varies according to the server's memory size.
 */
static void
set_max_delegations(void)
{
	/*
	 * Allow at most 4 delegations per megabyte of RAM.  Quick
	 * estimates suggest that in the worst case (where every delegation
	 * is for a different inode), a delegation could take about 1.5K,
	 * giving a worst case usage of about 6% of memory.
	 */
	max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
}

7146
static int nfs4_state_create_net(struct net *net)
7147 7148 7149 7150
{
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
	int i;

7151 7152 7153
	nn->conf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
					    sizeof(struct list_head),
					    GFP_KERNEL);
7154
	if (!nn->conf_id_hashtbl)
7155
		goto err;
7156 7157 7158
	nn->unconf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
					      sizeof(struct list_head),
					      GFP_KERNEL);
7159 7160
	if (!nn->unconf_id_hashtbl)
		goto err_unconf_id;
7161 7162 7163
	nn->sessionid_hashtbl = kmalloc_array(SESSION_HASH_SIZE,
					      sizeof(struct list_head),
					      GFP_KERNEL);
7164 7165
	if (!nn->sessionid_hashtbl)
		goto err_sessionid;
7166

7167
	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
7168
		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
7169
		INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
7170
	}
7171 7172
	for (i = 0; i < SESSION_HASH_SIZE; i++)
		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
7173
	nn->conf_name_tree = RB_ROOT;
7174
	nn->unconf_name_tree = RB_ROOT;
7175 7176 7177 7178
	nn->boot_time = get_seconds();
	nn->grace_ended = false;
	nn->nfsd4_manager.block_opens = true;
	INIT_LIST_HEAD(&nn->nfsd4_manager.list);
7179
	INIT_LIST_HEAD(&nn->client_lru);
7180
	INIT_LIST_HEAD(&nn->close_lru);
7181
	INIT_LIST_HEAD(&nn->del_recall_lru);
7182
	spin_lock_init(&nn->client_lock);
7183

7184 7185 7186
	spin_lock_init(&nn->blocked_locks_lock);
	INIT_LIST_HEAD(&nn->blocked_locks_lru);

7187
	INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
7188
	get_net(net);
7189

7190
	return 0;
7191

7192
err_sessionid:
7193
	kfree(nn->unconf_id_hashtbl);
7194 7195
err_unconf_id:
	kfree(nn->conf_id_hashtbl);
7196 7197
err:
	return -ENOMEM;
7198 7199 7200
}

static void
7201
nfs4_state_destroy_net(struct net *net)
7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212
{
	int i;
	struct nfs4_client *clp = NULL;
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);

	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
		while (!list_empty(&nn->conf_id_hashtbl[i])) {
			clp = list_entry(nn->conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
			destroy_client(clp);
		}
	}
7213

7214 7215
	WARN_ON(!list_empty(&nn->blocked_locks_lru));

7216 7217 7218 7219 7220
	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
		while (!list_empty(&nn->unconf_id_hashtbl[i])) {
			clp = list_entry(nn->unconf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
			destroy_client(clp);
		}
7221 7222
	}

7223
	kfree(nn->sessionid_hashtbl);
7224
	kfree(nn->unconf_id_hashtbl);
7225
	kfree(nn->conf_id_hashtbl);
7226
	put_net(net);
7227 7228
}

7229
int
7230
nfs4_state_start_net(struct net *net)
7231
{
7232
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
7233 7234
	int ret;

7235
	ret = nfs4_state_create_net(net);
7236 7237
	if (ret)
		return ret;
7238 7239
	locks_start_grace(net, &nn->nfsd4_manager);
	nfsd4_client_tracking_init(net);
7240 7241
	printk(KERN_INFO "NFSD: starting %ld-second grace period (net %x)\n",
	       nn->nfsd4_grace, net->ns.inum);
7242
	queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);
7243 7244 7245 7246 7247 7248 7249 7250 7251 7252
	return 0;
}

/* initialization to perform when the nfsd service is started: */

int
nfs4_state_start(void)
{
	int ret;

7253
	laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
7254 7255
	if (laundry_wq == NULL) {
		ret = -ENOMEM;
Chuck Lever's avatar
Chuck Lever committed
7256
		goto out;
7257
	}
7258 7259 7260
	ret = nfsd4_create_callback_queue();
	if (ret)
		goto out_free_laundry;
7261

7262
	set_max_delegations();
7263
	return 0;
7264

7265 7266
out_free_laundry:
	destroy_workqueue(laundry_wq);
Chuck Lever's avatar
Chuck Lever committed
7267
out:
7268
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
7269 7270
}

7271
void
7272
nfs4_state_shutdown_net(struct net *net)
Linus Torvalds's avatar
Linus Torvalds committed
7273 7274 7275
{
	struct nfs4_delegation *dp = NULL;
	struct list_head *pos, *next, reaplist;
7276
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
Linus Torvalds's avatar
Linus Torvalds committed
7277

7278 7279
	cancel_delayed_work_sync(&nn->laundromat_work);
	locks_end_grace(&nn->nfsd4_manager);
7280

Linus Torvalds's avatar
Linus Torvalds committed
7281
	INIT_LIST_HEAD(&reaplist);
7282
	spin_lock(&state_lock);
7283
	list_for_each_safe(pos, next, &nn->del_recall_lru) {
Linus Torvalds's avatar
Linus Torvalds committed
7284
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
7285
		WARN_ON(!unhash_delegation_locked(dp));
7286
		list_add(&dp->dl_recall_lru, &reaplist);
Linus Torvalds's avatar
Linus Torvalds committed
7287
	}
7288
	spin_unlock(&state_lock);
Linus Torvalds's avatar
Linus Torvalds committed
7289 7290
	list_for_each_safe(pos, next, &reaplist) {
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
7291
		list_del_init(&dp->dl_recall_lru);
7292
		destroy_unhashed_deleg(dp);
Linus Torvalds's avatar
Linus Torvalds committed
7293 7294
	}

7295
	nfsd4_client_tracking_exit(net);
7296
	nfs4_state_destroy_net(net);
Linus Torvalds's avatar
Linus Torvalds committed
7297 7298 7299 7300 7301
}

void
nfs4_state_shutdown(void)
{
7302
	destroy_workqueue(laundry_wq);
7303
	nfsd4_destroy_callback_queue();
Linus Torvalds's avatar
Linus Torvalds committed
7304
}
7305 7306 7307 7308

static void
get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
{
7309 7310
	if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG) && CURRENT_STATEID(stateid))
		memcpy(stateid, &cstate->current_stateid, sizeof(stateid_t));
7311 7312 7313 7314 7315
}

static void
put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
{
7316 7317 7318 7319 7320 7321 7322 7323 7324 7325
	if (cstate->minorversion) {
		memcpy(&cstate->current_stateid, stateid, sizeof(stateid_t));
		SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
	}
}

void
clear_current_stateid(struct nfsd4_compound_state *cstate)
{
	CLEAR_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
7326 7327
}

7328 7329 7330
/*
 * functions to set current state id
 */
7331
void
7332 7333
nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7334
{
7335
	put_stateid(cstate, &u->open_downgrade.od_stateid);
7336 7337
}

7338
void
7339 7340
nfsd4_set_openstateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7341
{
7342
	put_stateid(cstate, &u->open.op_stateid);
7343 7344
}

7345
void
7346 7347
nfsd4_set_closestateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7348
{
7349
	put_stateid(cstate, &u->close.cl_stateid);
7350 7351 7352
}

void
7353 7354
nfsd4_set_lockstateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7355
{
7356
	put_stateid(cstate, &u->lock.lk_resp_stateid);
7357 7358 7359 7360 7361
}

/*
 * functions to consume current state id
 */
7362

7363
void
7364 7365
nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7366
{
7367
	get_stateid(cstate, &u->open_downgrade.od_stateid);
7368 7369 7370
}

void
7371 7372
nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7373
{
7374
	get_stateid(cstate, &u->delegreturn.dr_stateid);
7375 7376
}

7377
void
7378 7379
nfsd4_get_freestateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7380
{
7381
	get_stateid(cstate, &u->free_stateid.fr_stateid);
7382 7383 7384
}

void
7385 7386
nfsd4_get_setattrstateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7387
{
7388
	get_stateid(cstate, &u->setattr.sa_stateid);
7389 7390
}

7391
void
7392 7393
nfsd4_get_closestateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7394
{
7395
	get_stateid(cstate, &u->close.cl_stateid);
7396 7397 7398
}

void
7399 7400
nfsd4_get_lockustateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7401
{
7402
	get_stateid(cstate, &u->locku.lu_stateid);
7403
}
7404 7405

void
7406 7407
nfsd4_get_readstateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7408
{
7409
	get_stateid(cstate, &u->read.rd_stateid);
7410 7411 7412
}

void
7413 7414
nfsd4_get_writestateid(struct nfsd4_compound_state *cstate,
		union nfsd4_op_u *u)
7415
{
7416
	get_stateid(cstate, &u->write.wr_stateid);
7417
}