nfs4state.c 147.1 KB
Newer Older
L
Linus Torvalds 已提交
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/hash.h>
45
#include "xdr4.h"
46
#include "xdr4cb.h"
47
#include "vfs.h"
48
#include "current_stateid.h"
L
Linus Torvalds 已提交
49

50 51
#include "netns.h"

L
Linus Torvalds 已提交
52 53
#define NFSDDBG_FACILITY                NFSDDBG_PROC

54 55 56 57 58 59 60 61
#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 */
};
62 63 64
static const stateid_t currentstateid = {
	.si_generation = 1,
};
65

A
Andy Adamson 已提交
66
static u64 current_sessionid = 1;
67

68 69
#define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t)))
#define ONE_STATEID(stateid)  (!memcmp((stateid), &one_stateid, sizeof(stateid_t)))
70
#define CURRENT_STATEID(stateid) (!memcmp((stateid), &currentstateid, sizeof(stateid_t)))
L
Linus Torvalds 已提交
71 72

/* forward declarations */
73
static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner);
L
Linus Torvalds 已提交
74

75 76 77
/* Locking: */

/* Currently used for almost all code touching nfsv4 state: */
I
Ingo Molnar 已提交
78
static DEFINE_MUTEX(client_mutex);
L
Linus Torvalds 已提交
79

80 81 82 83 84
/*
 * 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:
 */
85
static DEFINE_SPINLOCK(state_lock);
86

C
Christoph Hellwig 已提交
87 88 89 90 91
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;
N
NeilBrown 已提交
92

L
Linus Torvalds 已提交
93 94 95
void
nfs4_lock_state(void)
{
I
Ingo Molnar 已提交
96
	mutex_lock(&client_mutex);
L
Linus Torvalds 已提交
97 98
}

99
static void free_session(struct nfsd4_session *);
100

101
static bool is_session_dead(struct nfsd4_session *ses)
102
{
103
	return ses->se_flags & NFS4_SESSION_DEAD;
104 105
}

106
static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me)
107
{
108
	if (atomic_read(&ses->se_ref) > ref_held_by_me)
109 110 111
		return nfserr_jukebox;
	ses->se_flags |= NFS4_SESSION_DEAD;
	return nfs_ok;
112 113
}

L
Linus Torvalds 已提交
114 115 116
void
nfs4_unlock_state(void)
{
I
Ingo Molnar 已提交
117
	mutex_unlock(&client_mutex);
L
Linus Torvalds 已提交
118 119
}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
static bool is_client_expired(struct nfs4_client *clp)
{
	return clp->cl_time == 0;
}

static __be32 mark_client_expired_locked(struct nfs4_client *clp)
{
	if (atomic_read(&clp->cl_refcount))
		return nfserr_jukebox;
	clp->cl_time = 0;
	return nfs_ok;
}

static __be32 mark_client_expired(struct nfs4_client *clp)
{
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
	__be32 ret;

	spin_lock(&nn->client_lock);
	ret = mark_client_expired_locked(clp);
	spin_unlock(&nn->client_lock);
	return ret;
}

static __be32 get_client_locked(struct nfs4_client *clp)
{
	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();
}

static inline void
renew_client(struct nfs4_client *clp)
{
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

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

184
static void put_client_renew_locked(struct nfs4_client *clp)
185 186 187 188 189 190 191
{
	if (!atomic_dec_and_test(&clp->cl_refcount))
		return;
	if (!is_client_expired(clp))
		renew_client_locked(clp);
}

192 193 194 195
static void put_client_renew(struct nfs4_client *clp)
{
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

196 197 198 199
	if (!atomic_dec_and_lock(&clp->cl_refcount, &nn->client_lock))
		return;
	if (!is_client_expired(clp))
		renew_client_locked(clp);
200 201 202
	spin_unlock(&nn->client_lock);
}

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
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;

	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);
}


L
Linus Torvalds 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248
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;
}

249 250 251 252 253
static void nfsd4_free_file(struct nfs4_file *f)
{
	kmem_cache_free(file_slab, f);
}

254 255 256
static inline void
put_nfs4_file(struct nfs4_file *fi)
{
257 258
	might_lock(&state_lock);

259
	if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) {
260
		hlist_del(&fi->fi_hash);
261
		spin_unlock(&state_lock);
262
		iput(fi->fi_inode);
263
		nfsd4_free_file(fi);
264
	}
265 266 267 268 269
}

static inline void
get_nfs4_file(struct nfs4_file *fi)
{
270
	atomic_inc(&fi->fi_ref);
271 272
}

273 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 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 334 335 336 337 338 339 340 341 342 343 344 345
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;
}

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

	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;
}

346
static int num_delegations;
347
unsigned long max_delegations;
348 349 350 351 352

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

353 354 355 356
/* 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)
357

358
static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
359 360 361 362 363
{
	unsigned int ret;

	ret = opaque_hashval(ownername->data, ownername->len);
	ret += clientid;
364
	return ret & OWNER_HASH_MASK;
365
}
366 367 368 369

/* hash table for nfs4_file */
#define FILE_HASH_BITS                   8
#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
S
Shan Wei 已提交
370

371
static unsigned int nfsd_fh_hashval(struct knfsd_fh *fh)
372
{
373 374 375 376 377 378 379 380 381 382 383 384 385 386
	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);
}

static bool nfsd_fh_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
{
	return fh1->fh_size == fh2->fh_size &&
		!memcmp(fh1->fh_base.fh_pad,
				fh2->fh_base.fh_pad,
				fh1->fh_size);
387 388
}

389
static struct hlist_head file_hashtbl[FILE_HASH_SIZE];
390

391 392
static void
__nfs4_file_get_access(struct nfs4_file *fp, u32 access)
393
{
394 395
	lockdep_assert_held(&fp->fi_lock);

396 397 398 399
	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]);
400 401
}

402 403
static __be32
nfs4_file_get_access(struct nfs4_file *fp, u32 access)
404
{
405 406
	lockdep_assert_held(&fp->fi_lock);

407 408 409 410
	/* Does this access mode make sense? */
	if (access & ~NFS4_SHARE_ACCESS_BOTH)
		return nfserr_inval;

411 412 413 414
	/* Does it conflict with a deny mode already set? */
	if ((access & fp->fi_share_deny) != 0)
		return nfserr_share_denied;

415 416
	__nfs4_file_get_access(fp, access);
	return nfs_ok;
417 418
}

419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
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;
}

438
static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
439
{
440 441 442 443 444 445
	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;

J
Jeff Layton 已提交
446
		swap(f1, fp->fi_fds[oflag]);
447
		if (atomic_read(&fp->fi_access[1 - oflag]) == 0)
J
Jeff Layton 已提交
448
			swap(f2, fp->fi_fds[O_RDWR]);
449 450 451 452 453
		spin_unlock(&fp->fi_lock);
		if (f1)
			fput(f1);
		if (f2)
			fput(f2);
454 455 456
	}
}

457
static void nfs4_file_put_access(struct nfs4_file *fp, u32 access)
458
{
459 460 461
	WARN_ON_ONCE(access & ~NFS4_SHARE_ACCESS_BOTH);

	if (access & NFS4_SHARE_ACCESS_WRITE)
462
		__nfs4_file_put_access(fp, O_WRONLY);
463 464
	if (access & NFS4_SHARE_ACCESS_READ)
		__nfs4_file_put_access(fp, O_RDONLY);
465 466
}

J
J. Bruce Fields 已提交
467 468
static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct
kmem_cache *slab)
469
{
J
J. Bruce Fields 已提交
470 471
	struct idr *stateids = &cl->cl_stateids;
	struct nfs4_stid *stid;
J
J. Bruce Fields 已提交
472
	int new_id;
473

J
J. Bruce Fields 已提交
474 475 476 477
	stid = kmem_cache_alloc(slab, GFP_KERNEL);
	if (!stid)
		return NULL;

478
	new_id = idr_alloc_cyclic(stateids, stid, 0, 0, GFP_KERNEL);
T
Tejun Heo 已提交
479
	if (new_id < 0)
J
J. Bruce Fields 已提交
480
		goto out_free;
481
	stid->sc_client = cl;
J
J. Bruce Fields 已提交
482 483 484
	stid->sc_type = 0;
	stid->sc_stateid.si_opaque.so_id = new_id;
	stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
485
	/* Will be incremented before return to client: */
J
J. Bruce Fields 已提交
486
	stid->sc_stateid.si_generation = 0;
487
	atomic_set(&stid->sc_count, 1);
488 489

	/*
J
J. Bruce Fields 已提交
490 491 492 493 494 495 496
	 * 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):
497
	 */
J
J. Bruce Fields 已提交
498 499
	return stid;
out_free:
500
	kmem_cache_free(slab, stid);
J
J. Bruce Fields 已提交
501
	return NULL;
502 503
}

504 505 506 507 508
static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
{
	return openlockstateid(nfs4_alloc_stid(clp, stateid_slab));
}

509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
/*
 * 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.
 *
 * 'state_lock', which is always held when block_delegations() is called,
 * is used to manage concurrent access.  Testing does not need the lock
 * except when swapping the two filters.
 */
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) {
		spin_lock(&state_lock);
		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();
		}
		spin_unlock(&state_lock);
	}
	hash = arch_fast_hash(&fh->fh_base, fh->fh_size, 0);
	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;

572 573
	lockdep_assert_held(&state_lock);

574 575 576 577 578 579 580 581 582 583
	hash = arch_fast_hash(&fh->fh_base, fh->fh_size, 0);

	__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;
}

L
Linus Torvalds 已提交
584
static struct nfs4_delegation *
585
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
L
Linus Torvalds 已提交
586 587 588 589
{
	struct nfs4_delegation *dp;

	dprintk("NFSD alloc_init_deleg\n");
590
	if (num_delegations > max_delegations)
591
		return NULL;
592 593
	if (delegation_blocked(&current_fh->fh_handle))
		return NULL;
594
	dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab));
N
NeilBrown 已提交
595
	if (dp == NULL)
L
Linus Torvalds 已提交
596
		return dp;
597 598
	/*
	 * delegation seqid's are never incremented.  The 4.1 special
J
J. Bruce Fields 已提交
599 600
	 * meaning of seqid 0 isn't meaningful, really, but let's avoid
	 * 0 anyway just for consistency and use 1:
601 602
	 */
	dp->dl_stid.sc_stateid.si_generation = 1;
603
	num_delegations++;
604 605
	INIT_LIST_HEAD(&dp->dl_perfile);
	INIT_LIST_HEAD(&dp->dl_perclnt);
L
Linus Torvalds 已提交
606
	INIT_LIST_HEAD(&dp->dl_recall_lru);
607
	dp->dl_file = NULL;
608
	dp->dl_type = NFS4_OPEN_DELEGATE_READ;
609
	fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
L
Linus Torvalds 已提交
610
	dp->dl_time = 0;
611
	INIT_WORK(&dp->dl_recall.cb_work, nfsd4_run_cb_recall);
L
Linus Torvalds 已提交
612 613 614
	return dp;
}

615
static void remove_stid(struct nfs4_stid *s)
J
J. Bruce Fields 已提交
616 617 618 619 620 621
{
	struct idr *stateids = &s->sc_client->cl_stateids;

	idr_remove(stateids, s->sc_stateid.si_opaque.so_id);
}

B
Benny Halevy 已提交
622 623 624 625 626
static void nfs4_free_stid(struct kmem_cache *slab, struct nfs4_stid *s)
{
	kmem_cache_free(slab, s);
}

L
Linus Torvalds 已提交
627 628 629
void
nfs4_put_delegation(struct nfs4_delegation *dp)
{
630
	if (atomic_dec_and_test(&dp->dl_stid.sc_count)) {
631
		remove_stid(&dp->dl_stid);
B
Benny Halevy 已提交
632
		nfs4_free_stid(deleg_slab, &dp->dl_stid);
633
		num_delegations--;
L
Linus Torvalds 已提交
634 635 636
	}
}

637
static void nfs4_put_deleg_lease(struct nfs4_file *fp)
L
Linus Torvalds 已提交
638
{
639 640
	lockdep_assert_held(&state_lock);

641 642
	if (!fp->fi_lease)
		return;
643 644 645
	if (atomic_dec_and_test(&fp->fi_delegees)) {
		vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
		fp->fi_lease = NULL;
646
		fput(fp->fi_deleg_file);
647 648
		fp->fi_deleg_file = NULL;
	}
L
Linus Torvalds 已提交
649 650
}

J
J. Bruce Fields 已提交
651 652
static void unhash_stid(struct nfs4_stid *s)
{
J
J. Bruce Fields 已提交
653
	s->sc_type = 0;
J
J. Bruce Fields 已提交
654 655
}

656 657 658
static void
hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)
{
659
	lockdep_assert_held(&state_lock);
660
	lockdep_assert_held(&fp->fi_lock);
661

662
	dp->dl_stid.sc_type = NFS4_DELEG_STID;
663 664 665 666
	list_add(&dp->dl_perfile, &fp->fi_delegations);
	list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
}

L
Linus Torvalds 已提交
667 668 669 670
/* Called under the state lock. */
static void
unhash_delegation(struct nfs4_delegation *dp)
{
671 672
	struct nfs4_file *fp = dp->dl_file;

673
	spin_lock(&state_lock);
674
	dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID;
675 676
	/* Ensure that deleg break won't try to requeue it */
	++dp->dl_time;
677
	spin_lock(&fp->fi_lock);
678
	list_del_init(&dp->dl_perclnt);
L
Linus Torvalds 已提交
679
	list_del_init(&dp->dl_recall_lru);
680 681 682 683
	list_del_init(&dp->dl_perfile);
	spin_unlock(&fp->fi_lock);
	if (fp) {
		nfs4_put_deleg_lease(fp);
684 685
		dp->dl_file = NULL;
	}
686 687 688
	spin_unlock(&state_lock);
	if (fp)
		put_nfs4_file(fp);
689 690 691 692 693
}

static void destroy_revoked_delegation(struct nfs4_delegation *dp)
{
	list_del_init(&dp->dl_recall_lru);
L
Linus Torvalds 已提交
694 695 696
	nfs4_put_delegation(dp);
}

697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
static void destroy_delegation(struct nfs4_delegation *dp)
{
	unhash_delegation(dp);
	nfs4_put_delegation(dp);
}

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

	if (clp->cl_minorversion == 0)
		destroy_delegation(dp);
	else {
		unhash_delegation(dp);
		dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID;
		list_add(&dp->dl_recall_lru, &clp->cl_revoked);
	}
}

L
Linus Torvalds 已提交
716 717 718 719
/* 
 * SETCLIENTID state 
 */

720 721 722 723 724 725 726 727 728 729
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;
}

730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
/*
 * 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.
 */
748 749
static unsigned int
bmap_to_share_mode(unsigned long bmap) {
750
	int i;
751
	unsigned int access = 0;
752 753 754

	for (i = 1; i < 4; i++) {
		if (test_bit(i, &bmap))
755
			access |= i;
756
	}
757
	return access;
758 759
}

760 761 762 763
/* set share access for a given stateid */
static inline void
set_access(u32 access, struct nfs4_ol_stateid *stp)
{
764 765 766 767
	unsigned char mask = 1 << access;

	WARN_ON_ONCE(access > NFS4_SHARE_ACCESS_BOTH);
	stp->st_access_bmap |= mask;
768 769 770 771 772 773
}

/* clear share access for a given stateid */
static inline void
clear_access(u32 access, struct nfs4_ol_stateid *stp)
{
774 775 776 777
	unsigned char mask = 1 << access;

	WARN_ON_ONCE(access > NFS4_SHARE_ACCESS_BOTH);
	stp->st_access_bmap &= ~mask;
778 779 780 781 782 783
}

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

	return (bool)(stp->st_access_bmap & mask);
787 788
}

789 790
/* set share deny for a given stateid */
static inline void
791
set_deny(u32 deny, struct nfs4_ol_stateid *stp)
792
{
793 794 795 796
	unsigned char mask = 1 << deny;

	WARN_ON_ONCE(deny > NFS4_SHARE_DENY_BOTH);
	stp->st_deny_bmap |= mask;
797 798 799 800
}

/* clear share deny for a given stateid */
static inline void
801
clear_deny(u32 deny, struct nfs4_ol_stateid *stp)
802
{
803 804 805 806
	unsigned char mask = 1 << deny;

	WARN_ON_ONCE(deny > NFS4_SHARE_DENY_BOTH);
	stp->st_deny_bmap &= ~mask;
807 808 809 810
}

/* test whether a given stateid is denying specific access */
static inline bool
811
test_deny(u32 deny, struct nfs4_ol_stateid *stp)
812
{
813 814 815
	unsigned char mask = 1 << deny;

	return (bool)(stp->st_deny_bmap & mask);
816 817 818 819
}

static int nfs4_access_to_omode(u32 access)
{
820
	switch (access & NFS4_SHARE_ACCESS_BOTH) {
821 822 823 824 825 826 827
	case NFS4_SHARE_ACCESS_READ:
		return O_RDONLY;
	case NFS4_SHARE_ACCESS_WRITE:
		return O_WRONLY;
	case NFS4_SHARE_ACCESS_BOTH:
		return O_RDWR;
	}
828 829
	WARN_ON_ONCE(1);
	return O_RDONLY;
830 831
}

832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
/*
 * 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)
		recalculate_deny_mode(stp->st_file);
}

866 867 868 869 870
/* release all access and file references for a given stateid */
static void
release_all_access(struct nfs4_ol_stateid *stp)
{
	int i;
871 872 873 874
	struct nfs4_file *fp = stp->st_file;

	if (fp && stp->st_deny_bmap != 0)
		recalculate_deny_mode(fp);
875 876 877

	for (i = 1; i < 4; i++) {
		if (test_access(i, stp))
878
			nfs4_file_put_access(stp->st_file, i);
879 880 881 882
		clear_access(i, stp);
	}
}

883
static void unhash_generic_stateid(struct nfs4_ol_stateid *stp)
884
{
885 886 887
	struct nfs4_file *fp = stp->st_file;

	spin_lock(&fp->fi_lock);
888
	list_del(&stp->st_perfile);
889
	spin_unlock(&fp->fi_lock);
890 891 892
	list_del(&stp->st_perstateowner);
}

893
static void close_generic_stateid(struct nfs4_ol_stateid *stp)
894
{
895
	release_all_access(stp);
O
OGAWA Hirofumi 已提交
896
	put_nfs4_file(stp->st_file);
897 898 899
	stp->st_file = NULL;
}

900
static void free_generic_stateid(struct nfs4_ol_stateid *stp)
901
{
902
	remove_stid(&stp->st_stid);
B
Benny Halevy 已提交
903
	nfs4_free_stid(stateid_slab, &stp->st_stid);
904 905
}

906
static void __release_lock_stateid(struct nfs4_ol_stateid *stp)
907 908 909
{
	struct file *file;

910
	list_del(&stp->st_locks);
911
	unhash_generic_stateid(stp);
J
J. Bruce Fields 已提交
912
	unhash_stid(&stp->st_stid);
913
	file = find_any_file(stp->st_file);
914 915
	if (file)
		filp_close(file, (fl_owner_t)lockowner(stp->st_stateowner));
916
	close_generic_stateid(stp);
917 918 919
	free_generic_stateid(stp);
}

920
static void unhash_lockowner(struct nfs4_lockowner *lo)
921
{
922
	struct nfs4_ol_stateid *stp;
923

924 925 926
	list_del(&lo->lo_owner.so_strhash);
	while (!list_empty(&lo->lo_owner.so_stateids)) {
		stp = list_first_entry(&lo->lo_owner.so_stateids,
927
				struct nfs4_ol_stateid, st_perstateowner);
928
		__release_lock_stateid(stp);
929 930 931
	}
}

932 933 934 935 936 937
static void nfs4_free_lockowner(struct nfs4_lockowner *lo)
{
	kfree(lo->lo_owner.so_owner.data);
	kmem_cache_free(lockowner_slab, lo);
}

938
static void release_lockowner(struct nfs4_lockowner *lo)
939
{
940 941
	unhash_lockowner(lo);
	nfs4_free_lockowner(lo);
942 943
}

944 945 946 947 948 949 950
static void release_lockowner_if_empty(struct nfs4_lockowner *lo)
{
	if (list_empty(&lo->lo_owner.so_stateids))
		release_lockowner(lo);
}

static void release_lock_stateid(struct nfs4_ol_stateid *stp)
951
{
952
	struct nfs4_lockowner *lo;
953

954 955 956 957 958 959 960 961 962 963 964 965 966
	lo = lockowner(stp->st_stateowner);
	__release_lock_stateid(stp);
	release_lockowner_if_empty(lo);
}

static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp)
{
	struct nfs4_ol_stateid *stp;

	while (!list_empty(&open_stp->st_locks)) {
		stp = list_entry(open_stp->st_locks.next,
				struct nfs4_ol_stateid, st_locks);
		release_lock_stateid(stp);
967 968 969
	}
}

970
static void unhash_open_stateid(struct nfs4_ol_stateid *stp)
971 972
{
	unhash_generic_stateid(stp);
973
	release_open_stateid_locks(stp);
974 975 976 977 978 979
	close_generic_stateid(stp);
}

static void release_open_stateid(struct nfs4_ol_stateid *stp)
{
	unhash_open_stateid(stp);
980 981 982
	free_generic_stateid(stp);
}

983
static void unhash_openowner(struct nfs4_openowner *oo)
984
{
985
	struct nfs4_ol_stateid *stp;
986

987 988 989 990
	list_del(&oo->oo_owner.so_strhash);
	list_del(&oo->oo_perclient);
	while (!list_empty(&oo->oo_owner.so_stateids)) {
		stp = list_first_entry(&oo->oo_owner.so_stateids,
991
				struct nfs4_ol_stateid, st_perstateowner);
992
		release_open_stateid(stp);
993 994 995
	}
}

996 997 998 999 1000 1001 1002 1003 1004 1005
static void release_last_closed_stateid(struct nfs4_openowner *oo)
{
	struct nfs4_ol_stateid *s = oo->oo_last_closed_stid;

	if (s) {
		free_generic_stateid(s);
		oo->oo_last_closed_stid = NULL;
	}
}

1006 1007 1008 1009 1010 1011
static void nfs4_free_openowner(struct nfs4_openowner *oo)
{
	kfree(oo->oo_owner.so_owner.data);
	kmem_cache_free(openowner_slab, oo);
}

1012
static void release_openowner(struct nfs4_openowner *oo)
1013
{
1014 1015
	unhash_openowner(oo);
	list_del(&oo->oo_close_lru);
1016
	release_last_closed_stateid(oo);
1017
	nfs4_free_openowner(oo);
1018 1019
}

M
Marc Eshel 已提交
1020 1021 1022 1023 1024 1025 1026 1027
static inline int
hash_sessionid(struct nfs4_sessionid *sessionid)
{
	struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)sessionid;

	return sid->sequence % SESSION_HASH_SIZE;
}

1028
#ifdef NFSD_DEBUG
M
Marc Eshel 已提交
1029 1030 1031 1032 1033 1034
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]);
}
1035 1036 1037 1038 1039 1040 1041
#else
static inline void
dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
{
}
#endif

1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
/*
 * 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))) {
		cstate->replay_owner = NULL;
		return;
	}
	if (!so)
		return;
	if (so->so_is_open_owner)
		release_last_closed_stateid(openowner(so));
	so->so_seqid++;
	return;
}
M
Marc Eshel 已提交
1064

A
Andy Adamson 已提交
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
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;
}

/*
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
 * 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)

1091 1092 1093 1094 1095 1096 1097 1098 1099
static void
free_session_slots(struct nfsd4_session *ses)
{
	int i;

	for (i = 0; i < ses->se_fchannel.maxreqs; i++)
		kfree(ses->se_slots[i]);
}

1100
/*
1101 1102 1103
 * We don't actually need to cache the rpc and session headers, so we
 * can allocate a little less for each slot:
 */
1104
static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca)
1105
{
1106
	u32 size;
1107

1108 1109 1110 1111 1112
	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);
1113
}
A
Andy Adamson 已提交
1114

1115 1116
/*
 * XXX: If we run out of reserved DRC memory we could (up to a point)
1117
 * re-negotiate active sessions and reduce their slot usage to make
1118
 * room for new connections. For now we just fail the create session.
A
Andy Adamson 已提交
1119
 */
1120
static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
A
Andy Adamson 已提交
1121
{
1122 1123
	u32 slotsize = slot_bytes(ca);
	u32 num = ca->maxreqs;
1124
	int avail;
A
Andy Adamson 已提交
1125

1126
	spin_lock(&nfsd_drc_lock);
1127 1128
	avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION,
		    nfsd_drc_max_mem - nfsd_drc_mem_used);
1129 1130 1131
	num = min_t(int, num, avail / slotsize);
	nfsd_drc_mem_used += num * slotsize;
	spin_unlock(&nfsd_drc_lock);
A
Andy Adamson 已提交
1132

1133 1134
	return num;
}
A
Andy Adamson 已提交
1135

1136
static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca)
1137
{
1138 1139
	int slotsize = slot_bytes(ca);

1140
	spin_lock(&nfsd_drc_lock);
1141
	nfsd_drc_mem_used -= slotsize * ca->maxreqs;
1142
	spin_unlock(&nfsd_drc_lock);
1143
}
A
Andy Adamson 已提交
1144

1145 1146
static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs,
					   struct nfsd4_channel_attrs *battrs)
1147
{
1148 1149
	int numslots = fattrs->maxreqs;
	int slotsize = slot_bytes(fattrs);
1150 1151
	struct nfsd4_session *new;
	int mem, i;
1152

1153 1154 1155
	BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
			+ sizeof(struct nfsd4_session) > PAGE_SIZE);
	mem = numslots * sizeof(struct nfsd4_slot *);
A
Andy Adamson 已提交
1156

1157 1158 1159
	new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
	if (!new)
		return NULL;
1160
	/* allocate each struct nfsd4_slot and data cache in one piece */
1161
	for (i = 0; i < numslots; i++) {
1162
		new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL);
1163
		if (!new->se_slots[i])
1164 1165
			goto out_free;
	}
1166 1167 1168 1169

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

1170 1171 1172 1173 1174 1175
	return new;
out_free:
	while (i--)
		kfree(new->se_slots[i]);
	kfree(new);
	return NULL;
A
Andy Adamson 已提交
1176 1177
}

1178 1179 1180 1181 1182
static void free_conn(struct nfsd4_conn *c)
{
	svc_xprt_put(c->cn_xprt);
	kfree(c);
}
A
Andy Adamson 已提交
1183

1184 1185 1186 1187
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;
A
Andy Adamson 已提交
1188

1189 1190 1191 1192 1193
	spin_lock(&clp->cl_lock);
	if (!list_empty(&c->cn_persession)) {
		list_del(&c->cn_persession);
		free_conn(c);
	}
1194
	nfsd4_probe_callback(clp);
1195
	spin_unlock(&clp->cl_lock);
1196
}
A
Andy Adamson 已提交
1197

1198
static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
1199 1200
{
	struct nfsd4_conn *conn;
A
Andy Adamson 已提交
1201

1202 1203
	conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL);
	if (!conn)
1204
		return NULL;
1205 1206
	svc_xprt_get(rqstp->rq_xprt);
	conn->cn_xprt = rqstp->rq_xprt;
1207
	conn->cn_flags = flags;
1208 1209 1210
	INIT_LIST_HEAD(&conn->cn_xpt_user.list);
	return conn;
}
1211

1212 1213 1214 1215
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);
A
Andy Adamson 已提交
1216 1217
}

1218
static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
1219
{
1220
	struct nfs4_client *clp = ses->se_client;
1221

1222
	spin_lock(&clp->cl_lock);
1223
	__nfsd4_hash_conn(conn, ses);
1224
	spin_unlock(&clp->cl_lock);
1225 1226
}

1227
static int nfsd4_register_conn(struct nfsd4_conn *conn)
1228
{
1229
	conn->cn_xpt_user.callback = nfsd4_conn_lost;
1230
	return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
1231 1232
}

1233
static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses)
A
Andy Adamson 已提交
1234
{
1235
	int ret;
A
Andy Adamson 已提交
1236

1237
	nfsd4_hash_conn(conn, ses);
1238 1239 1240 1241
	ret = nfsd4_register_conn(conn);
	if (ret)
		/* oops; xprt is already down: */
		nfsd4_conn_lost(&conn->cn_xpt_user);
1242 1243
	/* We may have gained or lost a callback channel: */
	nfsd4_probe_callback_sync(ses->se_client);
1244
}
A
Andy Adamson 已提交
1245

1246
static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses)
1247 1248 1249
{
	u32 dir = NFS4_CDFC4_FORE;

1250
	if (cses->flags & SESSION4_BACK_CHAN)
1251
		dir |= NFS4_CDFC4_BACK;
1252
	return alloc_conn(rqstp, dir);
1253 1254 1255
}

/* must be called under client_lock */
1256
static void nfsd4_del_conns(struct nfsd4_session *s)
1257
{
1258 1259
	struct nfs4_client *clp = s->se_client;
	struct nfsd4_conn *c;
A
Andy Adamson 已提交
1260

1261 1262 1263 1264 1265
	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);
1266

1267 1268
		unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user);
		free_conn(c);
A
Andy Adamson 已提交
1269

1270 1271 1272
		spin_lock(&clp->cl_lock);
	}
	spin_unlock(&clp->cl_lock);
1273
}
A
Andy Adamson 已提交
1274

1275 1276 1277 1278 1279 1280
static void __free_session(struct nfsd4_session *ses)
{
	free_session_slots(ses);
	kfree(ses);
}

1281
static void free_session(struct nfsd4_session *ses)
1282
{
1283
	struct nfsd_net *nn = net_generic(ses->se_client->net, nfsd_net_id);
1284 1285

	lockdep_assert_held(&nn->client_lock);
1286
	nfsd4_del_conns(ses);
1287
	nfsd4_put_drc_mem(&ses->se_fchannel);
1288
	__free_session(ses);
1289 1290
}

1291
static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
1292 1293
{
	int idx;
1294
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1295

A
Andy Adamson 已提交
1296 1297 1298
	new->se_client = clp;
	gen_sessionid(new);

1299 1300
	INIT_LIST_HEAD(&new->se_conns);

1301
	new->se_cb_seq_nr = 1;
A
Andy Adamson 已提交
1302
	new->se_flags = cses->flags;
1303
	new->se_cb_prog = cses->callback_prog;
1304
	new->se_cb_sec = cses->cb_sec;
1305
	atomic_set(&new->se_ref, 0);
1306
	idx = hash_sessionid(&new->se_sessionid);
1307
	spin_lock(&nn->client_lock);
1308
	list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
1309
	spin_lock(&clp->cl_lock);
A
Andy Adamson 已提交
1310
	list_add(&new->se_perclnt, &clp->cl_sessions);
1311
	spin_unlock(&clp->cl_lock);
1312
	spin_unlock(&nn->client_lock);
1313

1314
	if (cses->flags & SESSION4_BACK_CHAN) {
1315
		struct sockaddr *sa = svc_addr(rqstp);
1316 1317 1318 1319 1320 1321 1322
		/*
		 * 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:
		 */
1323 1324 1325
		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
	}
A
Andy Adamson 已提交
1326 1327
}

1328
/* caller must hold client_lock */
M
Marc Eshel 已提交
1329
static struct nfsd4_session *
1330
__find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net)
M
Marc Eshel 已提交
1331 1332 1333
{
	struct nfsd4_session *elem;
	int idx;
1334
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
M
Marc Eshel 已提交
1335 1336 1337 1338

	dump_sessionid(__func__, sessionid);
	idx = hash_sessionid(sessionid);
	/* Search in the appropriate list */
1339
	list_for_each_entry(elem, &nn->sessionid_hashtbl[idx], se_hash) {
M
Marc Eshel 已提交
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
		if (!memcmp(elem->se_sessionid.data, sessionid->data,
			    NFS4_MAX_SESSIONID_LEN)) {
			return elem;
		}
	}

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

1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367
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;
}

1368
/* caller must hold client_lock */
A
Andy Adamson 已提交
1369
static void
M
Marc Eshel 已提交
1370
unhash_session(struct nfsd4_session *ses)
A
Andy Adamson 已提交
1371 1372
{
	list_del(&ses->se_hash);
1373
	spin_lock(&ses->se_client->cl_lock);
A
Andy Adamson 已提交
1374
	list_del(&ses->se_perclnt);
1375
	spin_unlock(&ses->se_client->cl_lock);
M
Marc Eshel 已提交
1376 1377
}

L
Linus Torvalds 已提交
1378 1379
/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
static int
1380
STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
L
Linus Torvalds 已提交
1381
{
1382
	if (clid->cl_boot == nn->boot_time)
L
Linus Torvalds 已提交
1383
		return 0;
A
Andy Adamson 已提交
1384
	dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n",
1385
		clid->cl_boot, clid->cl_id, nn->boot_time);
L
Linus Torvalds 已提交
1386 1387 1388 1389 1390 1391 1392 1393
	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.
 */
1394
static struct nfs4_client *alloc_client(struct xdr_netobj name)
L
Linus Torvalds 已提交
1395 1396 1397
{
	struct nfs4_client *clp;

1398 1399 1400
	clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL);
	if (clp == NULL)
		return NULL;
1401
	clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL);
1402 1403 1404
	if (clp->cl_name.data == NULL) {
		kfree(clp);
		return NULL;
L
Linus Torvalds 已提交
1405
	}
1406
	clp->cl_name.len = name.len;
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
	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_callbacks);
	INIT_LIST_HEAD(&clp->cl_revoked);
	spin_lock_init(&clp->cl_lock);
	rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
L
Linus Torvalds 已提交
1419 1420 1421
	return clp;
}

1422
static void
L
Linus Torvalds 已提交
1423 1424
free_client(struct nfs4_client *clp)
{
1425
	struct nfsd_net __maybe_unused *nn = net_generic(clp->net, nfsd_net_id);
1426 1427

	lockdep_assert_held(&nn->client_lock);
1428 1429 1430 1431 1432
	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);
1433 1434
		WARN_ON_ONCE(atomic_read(&ses->se_ref));
		free_session(ses);
1435
	}
1436
	rpc_destroy_wait_queue(&clp->cl_cb_waitq);
1437
	free_svc_cred(&clp->cl_cred);
L
Linus Torvalds 已提交
1438
	kfree(clp->cl_name.data);
M
majianpeng 已提交
1439
	idr_destroy(&clp->cl_stateids);
L
Linus Torvalds 已提交
1440 1441 1442
	kfree(clp);
}

B
Benny Halevy 已提交
1443 1444 1445 1446
/* must be called under the client_lock */
static inline void
unhash_client_locked(struct nfs4_client *clp)
{
1447 1448
	struct nfsd4_session *ses;

B
Benny Halevy 已提交
1449
	list_del(&clp->cl_lru);
1450
	spin_lock(&clp->cl_lock);
1451 1452
	list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
		list_del_init(&ses->se_hash);
1453
	spin_unlock(&clp->cl_lock);
B
Benny Halevy 已提交
1454 1455
}

L
Linus Torvalds 已提交
1456
static void
1457
destroy_client(struct nfs4_client *clp)
L
Linus Torvalds 已提交
1458
{
1459
	struct nfs4_openowner *oo;
L
Linus Torvalds 已提交
1460 1461
	struct nfs4_delegation *dp;
	struct list_head reaplist;
1462
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
L
Linus Torvalds 已提交
1463 1464

	INIT_LIST_HEAD(&reaplist);
1465
	spin_lock(&state_lock);
1466 1467 1468
	while (!list_empty(&clp->cl_delegations)) {
		dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
		list_del_init(&dp->dl_perclnt);
1469 1470
		/* Ensure that deleg break won't try to requeue it */
		++dp->dl_time;
L
Linus Torvalds 已提交
1471 1472
		list_move(&dp->dl_recall_lru, &reaplist);
	}
1473
	spin_unlock(&state_lock);
L
Linus Torvalds 已提交
1474 1475
	while (!list_empty(&reaplist)) {
		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
1476
		destroy_delegation(dp);
L
Linus Torvalds 已提交
1477
	}
1478 1479 1480 1481 1482
	list_splice_init(&clp->cl_revoked, &reaplist);
	while (!list_empty(&reaplist)) {
		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
		destroy_revoked_delegation(dp);
	}
1483
	while (!list_empty(&clp->cl_openowners)) {
1484 1485
		oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient);
		release_openowner(oo);
L
Linus Torvalds 已提交
1486
	}
1487
	nfsd4_shutdown_callback(clp);
B
Benny Halevy 已提交
1488 1489
	if (clp->cl_cb_conn.cb_xprt)
		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
1490
	list_del(&clp->cl_idhash);
1491
	if (test_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags))
1492
		rb_erase(&clp->cl_namenode, &nn->conf_name_tree);
1493
	else
1494
		rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
1495
	spin_lock(&nn->client_lock);
B
Benny Halevy 已提交
1496
	unhash_client_locked(clp);
1497 1498
	WARN_ON_ONCE(atomic_read(&clp->cl_refcount));
	free_client(clp);
1499
	spin_unlock(&nn->client_lock);
L
Linus Torvalds 已提交
1500 1501
}

1502 1503 1504 1505 1506 1507
static void expire_client(struct nfs4_client *clp)
{
	nfsd4_client_record_remove(clp);
	destroy_client(clp);
}

1508 1509 1510 1511
static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
{
	memcpy(target->cl_verifier.data, source->data,
			sizeof(target->cl_verifier.data));
L
Linus Torvalds 已提交
1512 1513
}

1514 1515
static void copy_clid(struct nfs4_client *target, struct nfs4_client *source)
{
L
Linus Torvalds 已提交
1516 1517 1518 1519
	target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; 
	target->cl_clientid.cl_id = source->cl_clientid.cl_id; 
}

1520
static int copy_cred(struct svc_cred *target, struct svc_cred *source)
1521
{
1522 1523 1524 1525 1526 1527 1528
	if (source->cr_principal) {
		target->cr_principal =
				kstrdup(source->cr_principal, GFP_KERNEL);
		if (target->cr_principal == NULL)
			return -ENOMEM;
	} else
		target->cr_principal = NULL;
1529
	target->cr_flavor = source->cr_flavor;
L
Linus Torvalds 已提交
1530 1531 1532 1533
	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);
1534 1535 1536
	target->cr_gss_mech = source->cr_gss_mech;
	if (source->cr_gss_mech)
		gss_mech_get(source->cr_gss_mech);
1537
	return 0;
L
Linus Torvalds 已提交
1538 1539
}

1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
static long long
compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
{
	long long res;

	res = o1->len - o2->len;
	if (res)
		return res;
	return (long long)memcmp(o1->data, o2->data, o1->len);
}

1551
static int same_name(const char *n1, const char *n2)
1552
{
N
NeilBrown 已提交
1553
	return 0 == memcmp(n1, n2, HEXDIR_LEN);
L
Linus Torvalds 已提交
1554 1555 1556
}

static int
1557 1558 1559
same_verf(nfs4_verifier *v1, nfs4_verifier *v2)
{
	return 0 == memcmp(v1->data, v2->data, sizeof(v1->data));
L
Linus Torvalds 已提交
1560 1561 1562
}

static int
1563 1564 1565
same_clid(clientid_t *cl1, clientid_t *cl2)
{
	return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id);
L
Linus Torvalds 已提交
1566 1567
}

1568 1569 1570 1571 1572 1573 1574
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++)
1575
		if (!gid_eq(GROUP_AT(g1, i), GROUP_AT(g2, i)))
1576 1577 1578 1579
			return false;
	return true;
}

1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595
/*
 * 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);
}


1596
static bool
1597 1598
same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
{
1599
	if ((is_gss_cred(cr1) != is_gss_cred(cr2))
1600 1601
		|| (!uid_eq(cr1->cr_uid, cr2->cr_uid))
		|| (!gid_eq(cr1->cr_gid, cr2->cr_gid))
1602 1603 1604 1605 1606 1607
		|| !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
		return false;
	if (cr1->cr_principal == cr2->cr_principal)
		return true;
	if (!cr1->cr_principal || !cr2->cr_principal)
		return false;
1608
	return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
L
Linus Torvalds 已提交
1609 1610
}

1611 1612 1613 1614 1615
static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
{
	struct svc_cred *cr = &rqstp->rq_cred;
	u32 service;

1616 1617
	if (!cr->cr_gss_mech)
		return false;
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
	service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor);
	return service == RPC_GSS_SVC_INTEGRITY ||
	       service == RPC_GSS_SVC_PRIVACY;
}

static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
{
	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;
	if (!cr->cr_principal)
		return false;
	return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
}

1638
static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
1639 1640 1641
{
	static u32 current_clientid = 1;

1642
	clp->cl_clientid.cl_boot = nn->boot_time;
L
Linus Torvalds 已提交
1643 1644 1645
	clp->cl_clientid.cl_id = current_clientid++; 
}

1646 1647
static void gen_confirm(struct nfs4_client *clp)
{
1648
	__be32 verf[2];
1649
	static u32 i;
L
Linus Torvalds 已提交
1650

1651 1652 1653 1654 1655 1656
	/*
	 * This is opaque to client, so no need to byte-swap. Use
	 * __force to keep sparse happy
	 */
	verf[0] = (__force __be32)get_seconds();
	verf[1] = (__force __be32)i++;
1657
	memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
L
Linus Torvalds 已提交
1658 1659
}

1660
static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
1661
{
J
J. Bruce Fields 已提交
1662 1663 1664 1665 1666 1667
	struct nfs4_stid *ret;

	ret = idr_find(&cl->cl_stateids, t->si_opaque.so_id);
	if (!ret || !ret->sc_type)
		return NULL;
	return ret;
J
J. Bruce Fields 已提交
1668 1669
}

1670
static struct nfs4_stid *find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask)
1671 1672
{
	struct nfs4_stid *s;
J
J. Bruce Fields 已提交
1673

1674
	s = find_stateid(cl, t);
J
J. Bruce Fields 已提交
1675 1676
	if (!s)
		return NULL;
1677
	if (typemask & s->sc_type)
1678 1679 1680 1681
		return s;
	return NULL;
}

J
Jeff Layton 已提交
1682
static struct nfs4_client *create_client(struct xdr_netobj name,
1683 1684 1685 1686
		struct svc_rqst *rqstp, nfs4_verifier *verf)
{
	struct nfs4_client *clp;
	struct sockaddr *sa = svc_addr(rqstp);
1687
	int ret;
1688
	struct net *net = SVC_NET(rqstp);
1689
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1690 1691 1692 1693 1694

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

1695 1696
	ret = copy_cred(&clp->cl_cred, &rqstp->rq_cred);
	if (ret) {
1697
		spin_lock(&nn->client_lock);
1698
		free_client(clp);
1699
		spin_unlock(&nn->client_lock);
1700
		return NULL;
1701
	}
1702
	INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_run_cb_null);
B
Benny Halevy 已提交
1703
	clp->cl_time = get_seconds();
1704 1705 1706 1707
	clear_bit(0, &clp->cl_cb_slot_busy);
	copy_verf(clp, verf);
	rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
	gen_confirm(clp);
1708
	clp->cl_cb_session = NULL;
1709
	clp->net = net;
1710 1711 1712
	return clp;
}

1713
static void
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
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)
{
	long long cmp;
	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)
L
Linus Torvalds 已提交
1755 1756
{
	unsigned int idhashval;
1757
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
L
Linus Torvalds 已提交
1758

1759
	clear_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
1760
	add_clp_to_name_tree(clp, &nn->unconf_name_tree);
L
Linus Torvalds 已提交
1761
	idhashval = clientid_hashval(clp->cl_clientid.cl_id);
1762
	list_add(&clp->cl_idhash, &nn->unconf_id_hashtbl[idhashval]);
1763
	renew_client(clp);
L
Linus Torvalds 已提交
1764 1765
}

1766
static void
L
Linus Torvalds 已提交
1767 1768 1769
move_to_confirmed(struct nfs4_client *clp)
{
	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
1770
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
L
Linus Torvalds 已提交
1771 1772

	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
1773
	list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);
1774
	rb_erase(&clp->cl_namenode, &nn->unconf_name_tree);
1775
	add_clp_to_name_tree(clp, &nn->conf_name_tree);
1776
	set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
L
Linus Torvalds 已提交
1777 1778 1779 1780
	renew_client(clp);
}

static struct nfs4_client *
J
J. Bruce Fields 已提交
1781
find_client_in_id_table(struct list_head *tbl, clientid_t *clid, bool sessions)
L
Linus Torvalds 已提交
1782 1783 1784 1785
{
	struct nfs4_client *clp;
	unsigned int idhashval = clientid_hashval(clid->cl_id);

J
J. Bruce Fields 已提交
1786
	list_for_each_entry(clp, &tbl[idhashval], cl_idhash) {
1787
		if (same_clid(&clp->cl_clientid, clid)) {
1788 1789
			if ((bool)clp->cl_minorversion != sessions)
				return NULL;
1790
			renew_client(clp);
L
Linus Torvalds 已提交
1791
			return clp;
1792
		}
L
Linus Torvalds 已提交
1793 1794 1795 1796
	}
	return NULL;
}

J
J. Bruce Fields 已提交
1797 1798 1799 1800 1801 1802 1803 1804
static struct nfs4_client *
find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
{
	struct list_head *tbl = nn->conf_id_hashtbl;

	return find_client_in_id_table(tbl, clid, sessions);
}

L
Linus Torvalds 已提交
1805
static struct nfs4_client *
1806
find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
L
Linus Torvalds 已提交
1807
{
J
J. Bruce Fields 已提交
1808
	struct list_head *tbl = nn->unconf_id_hashtbl;
L
Linus Torvalds 已提交
1809

J
J. Bruce Fields 已提交
1810
	return find_client_in_id_table(tbl, clid, sessions);
L
Linus Torvalds 已提交
1811 1812
}

1813
static bool clp_used_exchangeid(struct nfs4_client *clp)
1814
{
1815
	return clp->cl_exchange_flags != 0;
1816
} 
1817

1818
static struct nfs4_client *
1819
find_confirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
1820
{
1821
	return find_clp_in_name_tree(name, &nn->conf_name_tree);
1822 1823 1824
}

static struct nfs4_client *
1825
find_unconfirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
1826
{
1827
	return find_clp_in_name_tree(name, &nn->unconf_name_tree);
1828 1829
}

1830
static void
1831
gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp)
L
Linus Torvalds 已提交
1832
{
1833
	struct nfs4_cb_conn *conn = &clp->cl_cb_conn;
1834 1835
	struct sockaddr	*sa = svc_addr(rqstp);
	u32 scopeid = rpc_get_scope_id(sa);
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
	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
L
Linus Torvalds 已提交
1846 1847
		goto out_err;

1848
	conn->cb_addrlen = rpc_uaddr2sockaddr(clp->net, se->se_callback_addr_val,
1849
					    se->se_callback_addr_len,
1850 1851
					    (struct sockaddr *)&conn->cb_addr,
					    sizeof(conn->cb_addr));
1852

1853
	if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family)
L
Linus Torvalds 已提交
1854
		goto out_err;
1855

1856 1857
	if (conn->cb_addr.ss_family == AF_INET6)
		((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid;
1858

1859 1860
	conn->cb_prog = se->se_callback_prog;
	conn->cb_ident = se->se_callback_ident;
1861
	memcpy(&conn->cb_saddr, &rqstp->rq_daddr, rqstp->rq_daddrlen);
L
Linus Torvalds 已提交
1862 1863
	return;
out_err:
1864 1865
	conn->cb_addr.ss_family = AF_UNSPEC;
	conn->cb_addrlen = 0;
N
Neil Brown 已提交
1866
	dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
L
Linus Torvalds 已提交
1867 1868 1869 1870 1871 1872
		"will not receive delegations\n",
		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);

	return;
}

1873
/*
1874
 * Cache a reply. nfsd4_check_resp_size() has bounded the cache size.
1875
 */
1876
static void
1877 1878
nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
{
1879
	struct xdr_buf *buf = resp->xdr.buf;
1880 1881
	struct nfsd4_slot *slot = resp->cstate.slot;
	unsigned int base;
1882

1883
	dprintk("--> %s slot %p\n", __func__, slot);
1884

1885 1886
	slot->sl_opcnt = resp->opcnt;
	slot->sl_status = resp->cstate.status;
1887

1888
	slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
1889
	if (nfsd4_not_cached(resp)) {
1890
		slot->sl_datalen = 0;
1891
		return;
1892
	}
1893 1894 1895
	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))
1896 1897
		WARN("%s: sessions DRC could not cache compound\n", __func__);
	return;
1898 1899 1900
}

/*
1901 1902 1903 1904
 * 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.
1905 1906
 *
 */
1907 1908 1909
static __be32
nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,
			  struct nfsd4_compoundres *resp)
1910
{
1911 1912
	struct nfsd4_op *op;
	struct nfsd4_slot *slot = resp->cstate.slot;
1913

1914 1915 1916
	/* Encode the replayed sequence operation */
	op = &args->ops[resp->opcnt - 1];
	nfsd4_encode_operation(resp, op);
1917

1918
	/* Return nfserr_retry_uncached_rep in next operation. */
1919
	if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) {
1920 1921 1922
		op = &args->ops[resp->opcnt++];
		op->status = nfserr_retry_uncached_rep;
		nfsd4_encode_operation(resp, op);
1923
	}
1924
	return op->status;
1925 1926 1927
}

/*
1928 1929
 * The sequence operation is not cached because we can use the slot and
 * session values.
1930
 */
1931
static __be32
1932 1933
nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
			 struct nfsd4_sequence *seq)
1934
{
1935
	struct nfsd4_slot *slot = resp->cstate.slot;
1936 1937
	struct xdr_stream *xdr = &resp->xdr;
	__be32 *p;
1938 1939
	__be32 status;

1940
	dprintk("--> %s slot %p\n", __func__, slot);
1941

1942
	status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp);
1943
	if (status)
1944
		return status;
1945

1946 1947 1948 1949 1950 1951 1952
	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);
1953

1954
	resp->opcnt = slot->sl_opcnt;
1955
	return slot->sl_status;
1956 1957
}

A
Andy Adamson 已提交
1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973
/*
 * Set the exchange_id flags returned by the server.
 */
static void
nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid)
{
	/* pNFS is not supported */
	new->cl_exchange_flags |= EXCHGID4_FLAG_USE_NON_PNFS;

	/* 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;
}

1974 1975 1976 1977 1978 1979 1980 1981
static bool client_has_state(struct nfs4_client *clp)
{
	/*
	 * Note clp->cl_openowners check isn't quite right: there's no
	 * need to count owners without stateid's.
	 *
	 * Also note we should probably be using this in 4.0 case too.
	 */
1982 1983 1984
	return !list_empty(&clp->cl_openowners)
		|| !list_empty(&clp->cl_delegations)
		|| !list_empty(&clp->cl_sessions);
1985 1986
}

A
Andy Adamson 已提交
1987 1988 1989 1990 1991
__be32
nfsd4_exchange_id(struct svc_rqst *rqstp,
		  struct nfsd4_compound_state *cstate,
		  struct nfsd4_exchange_id *exid)
{
A
Andy Adamson 已提交
1992
	struct nfs4_client *unconf, *conf, *new;
J
J. Bruce Fields 已提交
1993
	__be32 status;
1994
	char			addr_str[INET6_ADDRSTRLEN];
A
Andy Adamson 已提交
1995
	nfs4_verifier		verf = exid->verifier;
1996
	struct sockaddr		*sa = svc_addr(rqstp);
1997
	bool	update = exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A;
1998
	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
A
Andy Adamson 已提交
1999

2000
	rpc_ntop(sa, addr_str, sizeof(addr_str));
A
Andy Adamson 已提交
2001
	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
2002
		"ip_addr=%s flags %x, spa_how %d\n",
A
Andy Adamson 已提交
2003
		__func__, rqstp, exid, exid->clname.len, exid->clname.data,
2004
		addr_str, exid->flags, exid->spa_how);
A
Andy Adamson 已提交
2005

2006
	if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
A
Andy Adamson 已提交
2007 2008 2009
		return nfserr_inval;

	switch (exid->spa_how) {
2010 2011 2012
	case SP4_MACH_CRED:
		if (!svc_rqst_integrity_protected(rqstp))
			return nfserr_inval;
A
Andy Adamson 已提交
2013 2014
	case SP4_NONE:
		break;
2015 2016
	default:				/* checked by xdr code */
		WARN_ON_ONCE(1);
A
Andy Adamson 已提交
2017
	case SP4_SSV:
2018
		return nfserr_encr_alg_unsupp;
A
Andy Adamson 已提交
2019 2020
	}

2021
	/* Cases below refer to rfc 5661 section 18.35.4: */
A
Andy Adamson 已提交
2022
	nfs4_lock_state();
2023
	conf = find_confirmed_client_by_name(&exid->clname, nn);
A
Andy Adamson 已提交
2024
	if (conf) {
2025 2026 2027
		bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
		bool verfs_match = same_verf(&verf, &conf->cl_verifier);

2028 2029
		if (update) {
			if (!clp_used_exchangeid(conf)) { /* buggy client */
2030
				status = nfserr_inval;
2031 2032
				goto out;
			}
2033 2034 2035 2036
			if (!mach_creds_match(conf, rqstp)) {
				status = nfserr_wrong_cred;
				goto out;
			}
2037
			if (!creds_match) { /* case 9 */
2038
				status = nfserr_perm;
2039 2040 2041
				goto out;
			}
			if (!verfs_match) { /* case 8 */
A
Andy Adamson 已提交
2042 2043 2044
				status = nfserr_not_same;
				goto out;
			}
2045 2046 2047 2048
			/* case 6 */
			exid->flags |= EXCHGID4_FLAG_CONFIRMED_R;
			new = conf;
			goto out_copy;
A
Andy Adamson 已提交
2049
		}
2050
		if (!creds_match) { /* case 3 */
2051 2052
			if (client_has_state(conf)) {
				status = nfserr_clid_inuse;
A
Andy Adamson 已提交
2053 2054 2055 2056 2057
				goto out;
			}
			expire_client(conf);
			goto out_new;
		}
2058
		if (verfs_match) { /* case 2 */
2059
			conf->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R;
2060 2061 2062 2063 2064
			new = conf;
			goto out_copy;
		}
		/* case 5, client reboot */
		goto out_new;
2065 2066
	}

2067
	if (update) { /* case 7 */
2068 2069
		status = nfserr_noent;
		goto out;
A
Andy Adamson 已提交
2070 2071
	}

2072
	unconf  = find_unconfirmed_client_by_name(&exid->clname, nn);
2073
	if (unconf) /* case 4, possible retry or client restart */
A
Andy Adamson 已提交
2074 2075
		expire_client(unconf);

2076
	/* case 1 (normal case) */
A
Andy Adamson 已提交
2077
out_new:
J
Jeff Layton 已提交
2078
	new = create_client(exid->clname, rqstp, &verf);
A
Andy Adamson 已提交
2079
	if (new == NULL) {
2080
		status = nfserr_jukebox;
A
Andy Adamson 已提交
2081 2082
		goto out;
	}
2083
	new->cl_minorversion = cstate->minorversion;
2084
	new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED);
A
Andy Adamson 已提交
2085

2086
	gen_clid(new, nn);
2087
	add_to_unconfirmed(new);
A
Andy Adamson 已提交
2088 2089 2090 2091
out_copy:
	exid->clientid.cl_boot = new->cl_clientid.cl_boot;
	exid->clientid.cl_id = new->cl_clientid.cl_id;

2092
	exid->seqid = new->cl_cs_slot.sl_seqid + 1;
A
Andy Adamson 已提交
2093 2094 2095
	nfsd4_set_ex_flags(new, exid);

	dprintk("nfsd4_exchange_id seqid %d flags %x\n",
2096
		new->cl_cs_slot.sl_seqid, new->cl_exchange_flags);
A
Andy Adamson 已提交
2097 2098 2099 2100 2101
	status = nfs_ok;

out:
	nfs4_unlock_state();
	return status;
A
Andy Adamson 已提交
2102 2103
}

J
J. Bruce Fields 已提交
2104
static __be32
2105
check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse)
B
Benny Halevy 已提交
2106
{
2107 2108
	dprintk("%s enter. seqid %d slot_seqid %d\n", __func__, seqid,
		slot_seqid);
B
Benny Halevy 已提交
2109 2110

	/* The slot is in use, and no response has been sent. */
2111 2112
	if (slot_inuse) {
		if (seqid == slot_seqid)
B
Benny Halevy 已提交
2113 2114 2115 2116
			return nfserr_jukebox;
		else
			return nfserr_seq_misordered;
	}
2117
	/* Note unsigned 32-bit arithmetic handles wraparound: */
2118
	if (likely(seqid == slot_seqid + 1))
B
Benny Halevy 已提交
2119
		return nfs_ok;
2120
	if (seqid == slot_seqid)
B
Benny Halevy 已提交
2121 2122 2123 2124
		return nfserr_replay_cache;
	return nfserr_seq_misordered;
}

2125 2126 2127 2128 2129 2130 2131
/*
 * 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
J. Bruce Fields 已提交
2132
			   struct nfsd4_clid_slot *slot, __be32 nfserr)
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145
{
	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;
}

2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162
#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))

2163
static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn)
2164
{
2165 2166
	u32 maxrpc = nn->nfsd_serv->sv_max_mesg;

2167 2168 2169 2170
	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;
2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189
	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;

2190
	return nfs_ok;
2191 2192
}

2193 2194 2195 2196 2197
#define NFSD_CB_MAX_REQ_SZ	((NFS4_enc_cb_recall_sz + \
				 RPC_MAX_HEADER_WITH_AUTH) * sizeof(__be32))
#define NFSD_CB_MAX_RESP_SZ	((NFS4_dec_cb_recall_sz + \
				 RPC_MAX_REPHEADER_WITH_AUTH) * sizeof(__be32))

2198
static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
2199
{
2200 2201 2202 2203 2204 2205 2206 2207
	ca->headerpadsz = 0;

	/*
	 * These RPC_MAX_HEADER macros are overkill, especially since we
	 * don't even do gss on the backchannel yet.  But this is still
	 * less than 1k.  Tighten up this estimate in the unlikely event
	 * it turns out to be a problem for some client:
	 */
2208
	if (ca->maxreq_sz < NFSD_CB_MAX_REQ_SZ)
2209
		return nfserr_toosmall;
2210
	if (ca->maxresp_sz < NFSD_CB_MAX_RESP_SZ)
2211 2212 2213 2214 2215 2216
		return nfserr_toosmall;
	ca->maxresp_cached = 0;
	if (ca->maxops < 2)
		return nfserr_toosmall;

	return nfs_ok;
2217 2218
}

2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
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;
	}
}

A
Andy Adamson 已提交
2237 2238 2239 2240 2241
__be32
nfsd4_create_session(struct svc_rqst *rqstp,
		     struct nfsd4_compound_state *cstate,
		     struct nfsd4_create_session *cr_ses)
{
2242
	struct sockaddr *sa = svc_addr(rqstp);
A
Andy Adamson 已提交
2243
	struct nfs4_client *conf, *unconf;
2244
	struct nfsd4_session *new;
2245
	struct nfsd4_conn *conn;
2246
	struct nfsd4_clid_slot *cs_slot = NULL;
J
J. Bruce Fields 已提交
2247
	__be32 status = 0;
2248
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
A
Andy Adamson 已提交
2249

2250 2251
	if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
		return nfserr_inval;
2252 2253 2254
	status = nfsd4_check_cb_sec(&cr_ses->cb_sec);
	if (status)
		return status;
2255
	status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
2256 2257 2258
	if (status)
		return status;
	status = check_backchannel_attrs(&cr_ses->back_channel);
2259
	if (status)
2260
		goto out_release_drc_mem;
2261
	status = nfserr_jukebox;
2262
	new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel);
2263 2264
	if (!new)
		goto out_release_drc_mem;
2265 2266 2267
	conn = alloc_conn_from_crses(rqstp, cr_ses);
	if (!conn)
		goto out_free_session;
2268

A
Andy Adamson 已提交
2269
	nfs4_lock_state();
2270
	unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
2271
	conf = find_confirmed_client(&cr_ses->clientid, true, nn);
2272
	WARN_ON_ONCE(conf && unconf);
A
Andy Adamson 已提交
2273 2274

	if (conf) {
2275 2276 2277
		status = nfserr_wrong_cred;
		if (!mach_creds_match(conf, rqstp))
			goto out_free_conn;
2278 2279
		cs_slot = &conf->cl_cs_slot;
		status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
2280
		if (status == nfserr_replay_cache) {
2281
			status = nfsd4_replay_create_session(cr_ses, cs_slot);
2282
			goto out_free_conn;
2283
		} else if (cr_ses->seqid != cs_slot->sl_seqid + 1) {
A
Andy Adamson 已提交
2284
			status = nfserr_seq_misordered;
2285
			goto out_free_conn;
A
Andy Adamson 已提交
2286 2287
		}
	} else if (unconf) {
J
J. Bruce Fields 已提交
2288
		struct nfs4_client *old;
A
Andy Adamson 已提交
2289
		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
2290
		    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
A
Andy Adamson 已提交
2291
			status = nfserr_clid_inuse;
2292
			goto out_free_conn;
A
Andy Adamson 已提交
2293
		}
2294 2295 2296
		status = nfserr_wrong_cred;
		if (!mach_creds_match(unconf, rqstp))
			goto out_free_conn;
2297 2298
		cs_slot = &unconf->cl_cs_slot;
		status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
2299 2300
		if (status) {
			/* an unconfirmed replay returns misordered */
A
Andy Adamson 已提交
2301
			status = nfserr_seq_misordered;
2302
			goto out_free_conn;
A
Andy Adamson 已提交
2303
		}
2304
		old = find_confirmed_client_by_name(&unconf->cl_name, nn);
2305 2306 2307 2308
		if (old) {
			status = mark_client_expired(old);
			if (status)
				goto out_free_conn;
J
J. Bruce Fields 已提交
2309
			expire_client(old);
2310
		}
J
J. Bruce Fields 已提交
2311
		move_to_confirmed(unconf);
A
Andy Adamson 已提交
2312 2313 2314
		conf = unconf;
	} else {
		status = nfserr_stale_clientid;
2315
		goto out_free_conn;
A
Andy Adamson 已提交
2316
	}
2317
	status = nfs_ok;
2318 2319 2320 2321 2322 2323
	/*
	 * We do not support RDMA or persistent sessions
	 */
	cr_ses->flags &= ~SESSION4_PERSIST;
	cr_ses->flags &= ~SESSION4_RDMA;

2324 2325 2326
	init_session(rqstp, new, conf, cr_ses);
	nfsd4_init_conn(rqstp, conn, new);

2327
	memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
A
Andy Adamson 已提交
2328
	       NFS4_MAX_SESSIONID_LEN);
2329
	cs_slot->sl_seqid++;
2330
	cr_ses->seqid = cs_slot->sl_seqid;
A
Andy Adamson 已提交
2331

2332 2333
	/* cache solo and embedded create sessions under the state lock */
	nfsd4_cache_create_session(cr_ses, cs_slot, status);
A
Andy Adamson 已提交
2334 2335
	nfs4_unlock_state();
	return status;
2336
out_free_conn:
2337
	nfs4_unlock_state();
2338 2339 2340
	free_conn(conn);
out_free_session:
	__free_session(new);
2341 2342
out_release_drc_mem:
	nfsd4_put_drc_mem(&cr_ses->fore_channel);
J
J. Bruce Fields 已提交
2343
	return status;
A
Andy Adamson 已提交
2344 2345
}

2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
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;
}

2360 2361 2362
__be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_backchannel_ctl *bc)
{
	struct nfsd4_session *session = cstate->session;
2363
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2364
	__be32 status;
2365

2366 2367 2368
	status = nfsd4_check_cb_sec(&bc->bc_cb_sec);
	if (status)
		return status;
2369
	spin_lock(&nn->client_lock);
2370 2371
	session->se_cb_prog = bc->bc_cb_program;
	session->se_cb_sec = bc->bc_cb_sec;
2372
	spin_unlock(&nn->client_lock);
2373 2374 2375 2376 2377 2378

	nfsd4_probe_callback(session->se_client);

	return nfs_ok;
}

2379 2380 2381 2382 2383
__be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
		     struct nfsd4_compound_state *cstate,
		     struct nfsd4_bind_conn_to_session *bcts)
{
	__be32 status;
2384
	struct nfsd4_conn *conn;
2385
	struct nfsd4_session *session;
2386 2387
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2388 2389 2390

	if (!nfsd4_last_compound_op(rqstp))
		return nfserr_not_only_op;
2391
	nfs4_lock_state();
2392
	spin_lock(&nn->client_lock);
2393
	session = find_in_sessionid_hashtbl(&bcts->sessionid, net, &status);
2394
	spin_unlock(&nn->client_lock);
2395
	if (!session)
2396
		goto out_no_session;
2397 2398 2399
	status = nfserr_wrong_cred;
	if (!mach_creds_match(session->se_client, rqstp))
		goto out;
2400
	status = nfsd4_map_bcts_dir(&bcts->dir);
2401
	if (status)
2402
		goto out;
2403
	conn = alloc_conn(rqstp, bcts->dir);
2404
	status = nfserr_jukebox;
2405
	if (!conn)
2406 2407 2408 2409
		goto out;
	nfsd4_init_conn(rqstp, conn, session);
	status = nfs_ok;
out:
2410 2411
	nfsd4_put_session(session);
out_no_session:
2412 2413
	nfs4_unlock_state();
	return status;
2414 2415
}

2416 2417 2418 2419 2420 2421 2422
static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
{
	if (!session)
		return 0;
	return !memcmp(sid, &session->se_sessionid, sizeof(*sid));
}

A
Andy Adamson 已提交
2423 2424 2425 2426 2427
__be32
nfsd4_destroy_session(struct svc_rqst *r,
		      struct nfsd4_compound_state *cstate,
		      struct nfsd4_destroy_session *sessionid)
{
B
Benny Halevy 已提交
2428
	struct nfsd4_session *ses;
2429
	__be32 status;
2430
	int ref_held_by_me = 0;
2431 2432
	struct net *net = SVC_NET(r);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
B
Benny Halevy 已提交
2433

2434 2435
	nfs4_lock_state();
	status = nfserr_not_only_op;
2436
	if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
2437
		if (!nfsd4_last_compound_op(r))
2438
			goto out;
2439
		ref_held_by_me++;
2440
	}
B
Benny Halevy 已提交
2441
	dump_sessionid(__func__, &sessionid->sessionid);
2442
	spin_lock(&nn->client_lock);
2443
	ses = find_in_sessionid_hashtbl(&sessionid->sessionid, net, &status);
2444 2445
	if (!ses)
		goto out_client_lock;
2446 2447
	status = nfserr_wrong_cred;
	if (!mach_creds_match(ses->se_client, r))
2448
		goto out_put_session;
2449
	status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
2450
	if (status)
2451
		goto out_put_session;
B
Benny Halevy 已提交
2452
	unhash_session(ses);
2453
	spin_unlock(&nn->client_lock);
B
Benny Halevy 已提交
2454

2455
	nfsd4_probe_callback_sync(ses->se_client);
2456

2457
	spin_lock(&nn->client_lock);
B
Benny Halevy 已提交
2458
	status = nfs_ok;
2459
out_put_session:
2460
	nfsd4_put_session_locked(ses);
2461 2462
out_client_lock:
	spin_unlock(&nn->client_lock);
B
Benny Halevy 已提交
2463
out:
2464
	nfs4_unlock_state();
B
Benny Halevy 已提交
2465
	return status;
A
Andy Adamson 已提交
2466 2467
}

2468
static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
2469 2470 2471 2472
{
	struct nfsd4_conn *c;

	list_for_each_entry(c, &s->se_conns, cn_persession) {
2473
		if (c->cn_xprt == xpt) {
2474 2475 2476 2477 2478 2479
			return c;
		}
	}
	return NULL;
}

2480
static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
2481 2482
{
	struct nfs4_client *clp = ses->se_client;
2483
	struct nfsd4_conn *c;
2484
	__be32 status = nfs_ok;
2485
	int ret;
2486 2487

	spin_lock(&clp->cl_lock);
2488
	c = __nfsd4_find_conn(new->cn_xprt, ses);
2489 2490 2491 2492 2493
	if (c)
		goto out_free;
	status = nfserr_conn_not_bound_to_session;
	if (clp->cl_mach_cred)
		goto out_free;
2494 2495
	__nfsd4_hash_conn(new, ses);
	spin_unlock(&clp->cl_lock);
2496 2497 2498 2499
	ret = nfsd4_register_conn(new);
	if (ret)
		/* oops; xprt is already down: */
		nfsd4_conn_lost(&new->cn_xpt_user);
2500 2501 2502 2503 2504
	return nfs_ok;
out_free:
	spin_unlock(&clp->cl_lock);
	free_conn(new);
	return status;
2505 2506
}

2507 2508 2509 2510 2511 2512 2513
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;
}

M
Mi Jinlong 已提交
2514 2515 2516 2517 2518 2519 2520 2521
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;
}

A
Andy Adamson 已提交
2522
__be32
B
Benny Halevy 已提交
2523
nfsd4_sequence(struct svc_rqst *rqstp,
A
Andy Adamson 已提交
2524 2525 2526
	       struct nfsd4_compound_state *cstate,
	       struct nfsd4_sequence *seq)
{
2527
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
2528
	struct xdr_stream *xdr = &resp->xdr;
B
Benny Halevy 已提交
2529
	struct nfsd4_session *session;
2530
	struct nfs4_client *clp;
B
Benny Halevy 已提交
2531
	struct nfsd4_slot *slot;
2532
	struct nfsd4_conn *conn;
J
J. Bruce Fields 已提交
2533
	__be32 status;
2534
	int buflen;
2535 2536
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
B
Benny Halevy 已提交
2537

2538 2539 2540
	if (resp->opcnt != 1)
		return nfserr_sequence_pos;

2541 2542 2543 2544 2545 2546 2547 2548
	/*
	 * Will be either used or freed by nfsd4_sequence_check_conn
	 * below.
	 */
	conn = alloc_conn(rqstp, NFS4_CDFC4_FORE);
	if (!conn)
		return nfserr_jukebox;

2549
	spin_lock(&nn->client_lock);
2550
	session = find_in_sessionid_hashtbl(&seq->sessionid, net, &status);
B
Benny Halevy 已提交
2551
	if (!session)
2552 2553
		goto out_no_session;
	clp = session->se_client;
B
Benny Halevy 已提交
2554

2555 2556
	status = nfserr_too_many_ops;
	if (nfsd4_session_too_many_ops(rqstp, session))
2557
		goto out_put_session;
2558

M
Mi Jinlong 已提交
2559 2560
	status = nfserr_req_too_big;
	if (nfsd4_request_too_big(rqstp, session))
2561
		goto out_put_session;
M
Mi Jinlong 已提交
2562

B
Benny Halevy 已提交
2563
	status = nfserr_badslot;
2564
	if (seq->slotid >= session->se_fchannel.maxreqs)
2565
		goto out_put_session;
B
Benny Halevy 已提交
2566

2567
	slot = session->se_slots[seq->slotid];
B
Benny Halevy 已提交
2568 2569
	dprintk("%s: slotid %d\n", __func__, seq->slotid);

2570 2571 2572 2573 2574
	/* 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;

2575 2576
	status = check_slot_seqid(seq->seqid, slot->sl_seqid,
					slot->sl_flags & NFSD4_SLOT_INUSE);
B
Benny Halevy 已提交
2577
	if (status == nfserr_replay_cache) {
2578 2579
		status = nfserr_seq_misordered;
		if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
2580
			goto out_put_session;
B
Benny Halevy 已提交
2581 2582
		cstate->slot = slot;
		cstate->session = session;
2583
		cstate->clp = clp;
A
Andy Adamson 已提交
2584
		/* Return the cached reply status and set cstate->status
2585
		 * for nfsd4_proc_compound processing */
2586
		status = nfsd4_replay_cache_entry(resp, seq);
A
Andy Adamson 已提交
2587
		cstate->status = nfserr_replay_cache;
2588
		goto out;
B
Benny Halevy 已提交
2589 2590
	}
	if (status)
2591
		goto out_put_session;
B
Benny Halevy 已提交
2592

2593
	status = nfsd4_sequence_check_conn(conn, session);
2594
	conn = NULL;
2595 2596
	if (status)
		goto out_put_session;
2597

2598 2599 2600 2601 2602
	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;
2603
	if (xdr_restrict_buflen(xdr, buflen - rqstp->rq_auth_slack))
2604
		goto out_put_session;
2605
	svc_reserve(rqstp, buflen);
2606 2607

	status = nfs_ok;
B
Benny Halevy 已提交
2608 2609
	/* Success! bump slot seqid */
	slot->sl_seqid = seq->seqid;
2610
	slot->sl_flags |= NFSD4_SLOT_INUSE;
2611 2612
	if (seq->cachethis)
		slot->sl_flags |= NFSD4_SLOT_CACHETHIS;
2613 2614
	else
		slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
B
Benny Halevy 已提交
2615 2616 2617

	cstate->slot = slot;
	cstate->session = session;
2618
	cstate->clp = clp;
B
Benny Halevy 已提交
2619 2620

out:
2621 2622 2623 2624 2625 2626 2627 2628 2629
	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;
2630
	}
2631 2632
	if (!list_empty(&clp->cl_revoked))
		seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED;
2633
out_no_session:
2634 2635
	if (conn)
		free_conn(conn);
2636
	spin_unlock(&nn->client_lock);
B
Benny Halevy 已提交
2637
	return status;
2638
out_put_session:
2639
	nfsd4_put_session_locked(session);
2640
	goto out_no_session;
A
Andy Adamson 已提交
2641 2642
}

2643 2644 2645 2646 2647 2648 2649 2650 2651 2652
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;
		}
2653
		/* Drop session reference that was taken in nfsd4_sequence() */
2654
		nfsd4_put_session(cs->session);
2655 2656
	} else if (cs->clp)
		put_client_renew(cs->clp);
2657 2658
}

2659 2660 2661 2662
__be32
nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_destroy_clientid *dc)
{
	struct nfs4_client *conf, *unconf, *clp;
J
J. Bruce Fields 已提交
2663
	__be32 status = 0;
2664
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2665 2666

	nfs4_lock_state();
2667
	unconf = find_unconfirmed_client(&dc->clientid, true, nn);
2668
	conf = find_confirmed_client(&dc->clientid, true, nn);
2669
	WARN_ON_ONCE(conf && unconf);
2670 2671 2672 2673

	if (conf) {
		clp = conf;

2674
		if (client_has_state(conf)) {
2675 2676 2677 2678 2679 2680 2681 2682 2683
			status = nfserr_clientid_busy;
			goto out;
		}
	} else if (unconf)
		clp = unconf;
	else {
		status = nfserr_stale_clientid;
		goto out;
	}
2684 2685 2686 2687
	if (!mach_creds_match(clp, rqstp)) {
		status = nfserr_wrong_cred;
		goto out;
	}
2688 2689 2690 2691 2692 2693
	expire_client(clp);
out:
	nfs4_unlock_state();
	return status;
}

2694 2695 2696
__be32
nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc)
{
J
J. Bruce Fields 已提交
2697
	__be32 status = 0;
2698

2699 2700 2701 2702 2703 2704 2705 2706 2707
	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.
		 */
		 return nfs_ok;
	}
2708

2709
	nfs4_lock_state();
2710
	status = nfserr_complete_already;
2711 2712
	if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
			     &cstate->session->se_client->cl_flags))
2713 2714 2715 2716
		goto out;

	status = nfserr_stale_clientid;
	if (is_client_expired(cstate->session->se_client))
2717 2718 2719 2720 2721 2722 2723
		/*
		 * 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.
		 */
2724 2725 2726
		goto out;

	status = nfs_ok;
2727
	nfsd4_client_record_create(cstate->session->se_client);
2728
out:
2729
	nfs4_unlock_state();
2730
	return status;
2731 2732
}

2733
__be32
2734 2735
nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		  struct nfsd4_setclientid *setclid)
L
Linus Torvalds 已提交
2736
{
2737
	struct xdr_netobj 	clname = setclid->se_name;
L
Linus Torvalds 已提交
2738
	nfs4_verifier		clverifier = setclid->se_verf;
2739
	struct nfs4_client	*conf, *unconf, *new;
2740
	__be32 			status;
2741 2742
	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);

2743
	/* Cases below refer to rfc 3530 section 14.2.33: */
L
Linus Torvalds 已提交
2744
	nfs4_lock_state();
2745
	conf = find_confirmed_client_by_name(&clname, nn);
2746
	if (conf) {
2747
		/* case 0: */
L
Linus Torvalds 已提交
2748
		status = nfserr_clid_inuse;
2749 2750
		if (clp_used_exchangeid(conf))
			goto out;
2751
		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
2752 2753 2754 2755 2756
			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);
L
Linus Torvalds 已提交
2757 2758 2759
			goto out;
		}
	}
2760
	unconf = find_unconfirmed_client_by_name(&clname, nn);
2761 2762
	if (unconf)
		expire_client(unconf);
2763
	status = nfserr_jukebox;
J
Jeff Layton 已提交
2764
	new = create_client(clname, rqstp, &clverifier);
2765 2766
	if (new == NULL)
		goto out;
2767
	if (conf && same_verf(&conf->cl_verifier, &clverifier))
2768
		/* case 1: probable callback update */
L
Linus Torvalds 已提交
2769
		copy_clid(new, conf);
2770
	else /* case 4 (new client) or cases 2, 3 (client reboot): */
2771
		gen_clid(new, nn);
2772
	new->cl_minorversion = 0;
2773
	gen_callback(new, setclid, rqstp);
2774
	add_to_unconfirmed(new);
L
Linus Torvalds 已提交
2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
	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));
	status = nfs_ok;
out:
	nfs4_unlock_state();
	return status;
}


2785
__be32
2786 2787 2788
nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
			 struct nfsd4_compound_state *cstate,
			 struct nfsd4_setclientid_confirm *setclientid_confirm)
L
Linus Torvalds 已提交
2789
{
2790
	struct nfs4_client *conf, *unconf;
L
Linus Torvalds 已提交
2791 2792
	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
	clientid_t * clid = &setclientid_confirm->sc_clientid;
2793
	__be32 status;
2794
	struct nfsd_net	*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
2795

2796
	if (STALE_CLIENTID(clid, nn))
L
Linus Torvalds 已提交
2797 2798
		return nfserr_stale_clientid;
	nfs4_lock_state();
2799

2800
	conf = find_confirmed_client(clid, false, nn);
2801
	unconf = find_unconfirmed_client(clid, false, nn);
2802
	/*
2803 2804 2805 2806
	 * We try hard to give out unique clientid's, so if we get an
	 * attempt to confirm the same clientid with a different cred,
	 * there's a bug somewhere.  Let's charitably assume it's our
	 * bug.
2807
	 */
2808 2809 2810 2811 2812
	status = nfserr_serverfault;
	if (unconf && !same_creds(&unconf->cl_cred, &rqstp->rq_cred))
		goto out;
	if (conf && !same_creds(&conf->cl_cred, &rqstp->rq_cred))
		goto out;
2813
	/* cases below refer to rfc 3530 section 14.2.34: */
2814 2815
	if (!unconf || !same_verf(&confirm, &unconf->cl_confirm)) {
		if (conf && !unconf) /* case 2: probable retransmit */
L
Linus Torvalds 已提交
2816
			status = nfs_ok;
2817 2818 2819 2820 2821 2822
		else /* case 4: client hasn't noticed we rebooted yet? */
			status = nfserr_stale_clientid;
		goto out;
	}
	status = nfs_ok;
	if (conf) { /* case 1: callback update */
2823 2824 2825
		nfsd4_change_callback(conf, &unconf->cl_cb_conn);
		nfsd4_probe_callback(conf);
		expire_client(unconf);
2826
	} else { /* case 3: normal case; new or rebooted client */
2827
		conf = find_confirmed_client_by_name(&unconf->cl_name, nn);
2828 2829 2830 2831
		if (conf) {
			status = mark_client_expired(conf);
			if (status)
				goto out;
2832
			expire_client(conf);
2833
		}
2834
		move_to_confirmed(unconf);
2835
		nfsd4_probe_callback(unconf);
2836
	}
L
Linus Torvalds 已提交
2837 2838 2839 2840 2841
out:
	nfs4_unlock_state();
	return status;
}

2842 2843 2844 2845 2846
static struct nfs4_file *nfsd4_alloc_file(void)
{
	return kmem_cache_alloc(file_slab, GFP_KERNEL);
}

L
Linus Torvalds 已提交
2847
/* OPEN Share state helper functions */
2848 2849
static void nfsd4_init_file(struct nfs4_file *fp, struct inode *ino,
		struct knfsd_fh *fh)
L
Linus Torvalds 已提交
2850
{
2851
	unsigned int hashval = file_hashval(fh);
L
Linus Torvalds 已提交
2852

2853 2854
	lockdep_assert_held(&state_lock);

2855
	atomic_set(&fp->fi_ref, 1);
2856
	spin_lock_init(&fp->fi_lock);
2857 2858
	INIT_LIST_HEAD(&fp->fi_stateids);
	INIT_LIST_HEAD(&fp->fi_delegations);
2859 2860
	ihold(ino);
	fp->fi_inode = ino;
2861
	fh_copy_shallow(&fp->fi_fhandle, fh);
2862 2863
	fp->fi_had_conflict = false;
	fp->fi_lease = NULL;
2864
	fp->fi_share_deny = 0;
2865 2866
	memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
	memset(fp->fi_access, 0, sizeof(fp->fi_access));
2867
	hlist_add_head(&fp->fi_hash, &file_hashtbl[hashval]);
L
Linus Torvalds 已提交
2868 2869
}

2870
void
L
Linus Torvalds 已提交
2871 2872
nfsd4_free_slabs(void)
{
C
Christoph Hellwig 已提交
2873 2874 2875 2876 2877
	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);
N
NeilBrown 已提交
2878
}
L
Linus Torvalds 已提交
2879

2880
int
N
NeilBrown 已提交
2881 2882
nfsd4_init_slabs(void)
{
2883 2884 2885
	openowner_slab = kmem_cache_create("nfsd4_openowners",
			sizeof(struct nfs4_openowner), 0, 0, NULL);
	if (openowner_slab == NULL)
C
Christoph Hellwig 已提交
2886
		goto out;
2887
	lockowner_slab = kmem_cache_create("nfsd4_lockowners",
2888
			sizeof(struct nfs4_lockowner), 0, 0, NULL);
2889
	if (lockowner_slab == NULL)
C
Christoph Hellwig 已提交
2890
		goto out_free_openowner_slab;
N
NeilBrown 已提交
2891
	file_slab = kmem_cache_create("nfsd4_files",
2892
			sizeof(struct nfs4_file), 0, 0, NULL);
N
NeilBrown 已提交
2893
	if (file_slab == NULL)
C
Christoph Hellwig 已提交
2894
		goto out_free_lockowner_slab;
N
NeilBrown 已提交
2895
	stateid_slab = kmem_cache_create("nfsd4_stateids",
2896
			sizeof(struct nfs4_ol_stateid), 0, 0, NULL);
N
NeilBrown 已提交
2897
	if (stateid_slab == NULL)
C
Christoph Hellwig 已提交
2898
		goto out_free_file_slab;
N
NeilBrown 已提交
2899
	deleg_slab = kmem_cache_create("nfsd4_delegations",
2900
			sizeof(struct nfs4_delegation), 0, 0, NULL);
N
NeilBrown 已提交
2901
	if (deleg_slab == NULL)
C
Christoph Hellwig 已提交
2902
		goto out_free_stateid_slab;
N
NeilBrown 已提交
2903
	return 0;
C
Christoph Hellwig 已提交
2904 2905 2906 2907 2908 2909 2910 2911 2912 2913

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);
out:
N
NeilBrown 已提交
2914 2915
	dprintk("nfsd4: out of memory while initializing nfsv4\n");
	return -ENOMEM;
L
Linus Torvalds 已提交
2916 2917
}

2918
static void init_nfs4_replay(struct nfs4_replay *rp)
L
Linus Torvalds 已提交
2919
{
2920 2921 2922
	rp->rp_status = nfserr_serverfault;
	rp->rp_buflen = 0;
	rp->rp_buf = rp->rp_ibuf;
L
Linus Torvalds 已提交
2923 2924
}

2925
static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj *owner, struct nfs4_client *clp)
2926
{
L
Linus Torvalds 已提交
2927 2928
	struct nfs4_stateowner *sop;

2929
	sop = kmem_cache_alloc(slab, GFP_KERNEL);
2930 2931 2932 2933 2934
	if (!sop)
		return NULL;

	sop->so_owner.data = kmemdup(owner->data, owner->len, GFP_KERNEL);
	if (!sop->so_owner.data) {
2935
		kmem_cache_free(slab, sop);
L
Linus Torvalds 已提交
2936
		return NULL;
2937 2938 2939
	}
	sop->so_owner.len = owner->len;

2940
	INIT_LIST_HEAD(&sop->so_stateids);
2941 2942 2943 2944 2945
	sop->so_client = clp;
	init_nfs4_replay(&sop->so_replay);
	return sop;
}

2946
static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
2947
{
2948 2949 2950
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

	list_add(&oo->oo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
2951
	list_add(&oo->oo_perclient, &clp->cl_openowners);
2952 2953
}

2954
static struct nfs4_openowner *
2955
alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
2956 2957
			   struct nfsd4_compound_state *cstate)
{
2958
	struct nfs4_client *clp = cstate->clp;
2959
	struct nfs4_openowner *oo;
2960

2961 2962
	oo = alloc_stateowner(openowner_slab, &open->op_owner, clp);
	if (!oo)
2963
		return NULL;
2964 2965
	oo->oo_owner.so_is_open_owner = 1;
	oo->oo_owner.so_seqid = open->op_seqid;
2966
	oo->oo_flags = NFS4_OO_NEW;
2967 2968
	if (nfsd4_has_session(cstate))
		oo->oo_flags |= NFS4_OO_CONFIRMED;
2969
	oo->oo_time = 0;
2970
	oo->oo_last_closed_stid = NULL;
2971 2972 2973
	INIT_LIST_HEAD(&oo->oo_close_lru);
	hash_openowner(oo, clp, strhashval);
	return oo;
L
Linus Torvalds 已提交
2974 2975
}

2976
static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
2977
	struct nfs4_openowner *oo = open->op_openowner;
L
Linus Torvalds 已提交
2978

J
J. Bruce Fields 已提交
2979
	stp->st_stid.sc_type = NFS4_OPEN_STID;
2980
	INIT_LIST_HEAD(&stp->st_locks);
2981 2982
	list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
	stp->st_stateowner = &oo->oo_owner;
2983
	get_nfs4_file(fp);
L
Linus Torvalds 已提交
2984 2985 2986
	stp->st_file = fp;
	stp->st_access_bmap = 0;
	stp->st_deny_bmap = 0;
2987
	stp->st_openstp = NULL;
2988 2989 2990
	spin_lock(&fp->fi_lock);
	list_add(&stp->st_perfile, &fp->fi_stateids);
	spin_unlock(&fp->fi_lock);
L
Linus Torvalds 已提交
2991 2992
}

2993
static void
2994
move_to_close_lru(struct nfs4_openowner *oo, struct net *net)
L
Linus Torvalds 已提交
2995
{
2996 2997
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);

2998
	dprintk("NFSD: move_to_close_lru nfs4_openowner %p\n", oo);
L
Linus Torvalds 已提交
2999

3000
	list_move_tail(&oo->oo_close_lru, &nn->close_lru);
3001
	oo->oo_time = get_seconds();
L
Linus Torvalds 已提交
3002 3003 3004
}

static int
3005 3006 3007 3008 3009 3010
same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
							clientid_t *clid)
{
	return (sop->so_owner.len == owner->len) &&
		0 == memcmp(sop->so_owner.data, owner->data, owner->len) &&
		(sop->so_client->cl_clientid.cl_id == clid->cl_id);
L
Linus Torvalds 已提交
3011 3012
}

3013
static struct nfs4_openowner *
3014 3015
find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open,
			bool sessions, struct nfsd_net *nn)
L
Linus Torvalds 已提交
3016
{
3017 3018
	struct nfs4_stateowner *so;
	struct nfs4_openowner *oo;
3019
	struct nfs4_client *clp;
L
Linus Torvalds 已提交
3020

3021
	list_for_each_entry(so, &nn->ownerstr_hashtbl[hashval], so_strhash) {
3022 3023
		if (!so->so_is_open_owner)
			continue;
3024 3025
		if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
			oo = openowner(so);
3026 3027 3028
			clp = oo->oo_owner.so_client;
			if ((bool)clp->cl_minorversion != sessions)
				return NULL;
3029 3030 3031
			renew_client(oo->oo_owner.so_client);
			return oo;
		}
L
Linus Torvalds 已提交
3032 3033 3034 3035 3036 3037
	}
	return NULL;
}

/* search file_hashtbl[] for file */
static struct nfs4_file *
3038
find_file_locked(struct knfsd_fh *fh)
L
Linus Torvalds 已提交
3039
{
3040
	unsigned int hashval = file_hashval(fh);
L
Linus Torvalds 已提交
3041 3042
	struct nfs4_file *fp;

3043 3044
	lockdep_assert_held(&state_lock);

3045
	hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
3046
		if (nfsd_fh_match(&fp->fi_fhandle, fh)) {
3047
			get_nfs4_file(fp);
L
Linus Torvalds 已提交
3048
			return fp;
3049
		}
L
Linus Torvalds 已提交
3050 3051 3052 3053
	}
	return NULL;
}

3054
static struct nfs4_file *
3055
find_file(struct knfsd_fh *fh)
3056 3057 3058 3059
{
	struct nfs4_file *fp;

	spin_lock(&state_lock);
3060
	fp = find_file_locked(fh);
3061 3062 3063 3064 3065
	spin_unlock(&state_lock);
	return fp;
}

static struct nfs4_file *
3066
find_or_add_file(struct inode *ino, struct nfs4_file *new, struct knfsd_fh *fh)
3067 3068 3069 3070
{
	struct nfs4_file *fp;

	spin_lock(&state_lock);
3071
	fp = find_file_locked(fh);
3072
	if (fp == NULL) {
3073
		nfsd4_init_file(new, ino, fh);
3074 3075 3076 3077 3078 3079 3080
		fp = new;
	}
	spin_unlock(&state_lock);

	return fp;
}

L
Linus Torvalds 已提交
3081 3082 3083 3084
/*
 * Called to check deny when READ with all zero stateid or
 * WRITE with all zero or all one stateid
 */
3085
static __be32
L
Linus Torvalds 已提交
3086 3087 3088
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{
	struct nfs4_file *fp;
3089
	__be32 ret = nfs_ok;
L
Linus Torvalds 已提交
3090

3091
	fp = find_file(&current_fh->fh_handle);
3092
	if (!fp)
3093 3094
		return ret;
	/* Check for conflicting share reservations */
3095
	spin_lock(&fp->fi_lock);
3096 3097
	if (fp->fi_share_deny & deny_type)
		ret = nfserr_locked;
3098
	spin_unlock(&fp->fi_lock);
3099 3100
	put_nfs4_file(fp);
	return ret;
L
Linus Torvalds 已提交
3101 3102
}

3103
void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp)
L
Linus Torvalds 已提交
3104
{
3105 3106 3107
	struct nfs4_client *clp = dp->dl_stid.sc_client;
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

3108 3109 3110 3111 3112 3113
	/*
	 * We can't do this in nfsd_break_deleg_cb because it is
	 * already holding inode->i_lock
	 */
	spin_lock(&state_lock);
	block_delegations(&dp->dl_fh);
3114 3115 3116 3117 3118 3119
	/*
	 * If the dl_time != 0, then we know that it has already been
	 * queued for a lease break. Don't queue it again.
	 */
	if (dp->dl_time == 0) {
		dp->dl_time = get_seconds();
3120
		list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru);
3121
	}
3122 3123
	spin_unlock(&state_lock);
}
L
Linus Torvalds 已提交
3124

3125 3126 3127 3128 3129 3130 3131 3132 3133
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
	 * callback (and since the lease code is serialized by the kernel
	 * lock) we know the server hasn't removed the lease yet, we know
	 * it's safe to take a reference.
	 */
3134
	atomic_inc(&dp->dl_stid.sc_count);
3135 3136 3137
	nfsd4_cb_recall(dp);
}

3138
/* Called from break_lease() with i_lock held. */
3139 3140
static void nfsd_break_deleg_cb(struct file_lock *fl)
{
3141 3142
	struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner;
	struct nfs4_delegation *dp;
3143

3144 3145 3146 3147 3148 3149 3150 3151
	if (!fp) {
		WARN(1, "(%p)->fl_owner NULL\n", fl);
		return;
	}
	if (fp->fi_had_conflict) {
		WARN(1, "duplicate break on %p\n", fp);
		return;
	}
3152 3153
	/*
	 * We don't want the locks code to timeout the lease for us;
3154
	 * we'll remove it ourself if a delegation isn't returned
3155
	 * in time:
3156 3157
	 */
	fl->fl_break_time = 0;
L
Linus Torvalds 已提交
3158

3159
	spin_lock(&fp->fi_lock);
3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171
	fp->fi_had_conflict = true;
	/*
	 * If there are no delegations on the list, then we can't count on this
	 * lease ever being cleaned up. Set the fl_break_time to jiffies so that
	 * time_out_leases will do it ASAP. The fact that fi_had_conflict is now
	 * true should keep any new delegations from being hashed.
	 */
	if (list_empty(&fp->fi_delegations))
		fl->fl_break_time = jiffies;
	else
		list_for_each_entry(dp, &fp->fi_delegations, dl_perfile)
			nfsd_break_one_deleg(dp);
3172
	spin_unlock(&fp->fi_lock);
L
Linus Torvalds 已提交
3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183
}

static
int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
{
	if (arg & F_UNLCK)
		return lease_modify(onlist, arg);
	else
		return -EAGAIN;
}

3184
static const struct lock_manager_operations nfsd_lease_mng_ops = {
J
J. Bruce Fields 已提交
3185 3186
	.lm_break = nfsd_break_deleg_cb,
	.lm_change = nfsd_change_deleg_cb,
L
Linus Torvalds 已提交
3187 3188
};

3189 3190 3191 3192 3193 3194 3195 3196 3197 3198
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;
}
L
Linus Torvalds 已提交
3199

3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231
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);
	found = find_confirmed_client(clid, false, nn);
	if (!found)
		return nfserr_expired;

	/* Cache the nfs4_client in cstate! */
	cstate->clp = found;
	atomic_inc(&found->cl_refcount);
	return nfs_ok;
}

3232
__be32
A
Andy Adamson 已提交
3233
nfsd4_process_open1(struct nfsd4_compound_state *cstate,
3234
		    struct nfsd4_open *open, struct nfsd_net *nn)
L
Linus Torvalds 已提交
3235 3236 3237 3238
{
	clientid_t *clientid = &open->op_clientid;
	struct nfs4_client *clp = NULL;
	unsigned int strhashval;
3239
	struct nfs4_openowner *oo = NULL;
3240
	__be32 status;
L
Linus Torvalds 已提交
3241

3242
	if (STALE_CLIENTID(&open->op_clientid, nn))
L
Linus Torvalds 已提交
3243
		return nfserr_stale_clientid;
3244 3245 3246 3247 3248 3249 3250
	/*
	 * 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;
L
Linus Torvalds 已提交
3251

3252 3253 3254 3255 3256
	status = lookup_clientid(clientid, cstate, nn);
	if (status)
		return status;
	clp = cstate->clp;

3257
	strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
3258
	oo = find_openstateowner_str(strhashval, open, cstate->minorversion, nn);
3259 3260
	open->op_openowner = oo;
	if (!oo) {
3261
		goto new_owner;
L
Linus Torvalds 已提交
3262
	}
3263
	if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
3264
		/* Replace unconfirmed owners without checking for replay. */
3265 3266
		release_openowner(oo);
		open->op_openowner = NULL;
3267
		goto new_owner;
3268
	}
3269 3270 3271 3272
	status = nfsd4_check_seqid(cstate, &oo->oo_owner, open->op_seqid);
	if (status)
		return status;
	goto alloc_stateid;
3273
new_owner:
3274
	oo = alloc_init_open_stateowner(strhashval, open, cstate);
3275 3276 3277
	if (oo == NULL)
		return nfserr_jukebox;
	open->op_openowner = oo;
3278 3279 3280 3281
alloc_stateid:
	open->op_stp = nfs4_alloc_stateid(clp);
	if (!open->op_stp)
		return nfserr_jukebox;
3282
	return nfs_ok;
L
Linus Torvalds 已提交
3283 3284
}

3285
static inline __be32
N
NeilBrown 已提交
3286 3287 3288 3289 3290 3291 3292 3293
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;
}

3294
static int share_access_to_flags(u32 share_access)
3295
{
3296
	return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE;
3297 3298
}

3299
static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, stateid_t *s)
3300
{
3301
	struct nfs4_stid *ret;
3302

3303
	ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID);
3304 3305 3306
	if (!ret)
		return NULL;
	return delegstateid(ret);
3307 3308
}

3309 3310 3311 3312 3313 3314
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;
}

3315
static __be32
3316
nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
3317 3318 3319
		struct nfs4_delegation **dp)
{
	int flags;
3320
	__be32 status = nfserr_bad_stateid;
3321

3322
	*dp = find_deleg_stateid(cl, &open->op_delegate_stateid);
3323
	if (*dp == NULL)
3324
		goto out;
3325
	flags = share_access_to_flags(open->op_share_access);
3326 3327 3328
	status = nfs4_check_delegmode(*dp, flags);
	if (status)
		*dp = NULL;
3329
out:
3330
	if (!nfsd4_is_deleg_cur(open))
3331 3332 3333
		return nfs_ok;
	if (status)
		return status;
3334
	open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
3335
	return nfs_ok;
3336 3337
}

3338 3339
static struct nfs4_ol_stateid *
nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open)
L
Linus Torvalds 已提交
3340
{
3341
	struct nfs4_ol_stateid *local, *ret = NULL;
3342
	struct nfs4_openowner *oo = open->op_openowner;
L
Linus Torvalds 已提交
3343

3344
	spin_lock(&fp->fi_lock);
3345
	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
L
Linus Torvalds 已提交
3346 3347 3348
		/* ignore lock owners */
		if (local->st_stateowner->so_is_open_owner == 0)
			continue;
3349
		if (local->st_stateowner == &oo->oo_owner) {
3350
			ret = local;
3351
			break;
3352
		}
L
Linus Torvalds 已提交
3353
	}
3354
	spin_unlock(&fp->fi_lock);
3355
	return ret;
L
Linus Torvalds 已提交
3356 3357
}

3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368
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;
}

3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383
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);
}

3384
static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
3385 3386
		struct svc_fh *cur_fh, struct nfs4_ol_stateid *stp,
		struct nfsd4_open *open)
3387
{
3388
	struct file *filp = NULL;
3389
	__be32 status;
3390 3391
	int oflag = nfs4_access_to_omode(open->op_share_access);
	int access = nfs4_access_to_access(open->op_share_access);
3392
	unsigned char old_access_bmap, old_deny_bmap;
3393

3394
	spin_lock(&fp->fi_lock);
3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421

	/*
	 * 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);

3422
	if (!fp->fi_fds[oflag]) {
3423 3424
		spin_unlock(&fp->fi_lock);
		status = nfsd_open(rqstp, cur_fh, S_IFREG, access, &filp);
3425
		if (status)
3426
			goto out_put_access;
3427 3428 3429 3430 3431
		spin_lock(&fp->fi_lock);
		if (!fp->fi_fds[oflag]) {
			fp->fi_fds[oflag] = filp;
			filp = NULL;
		}
3432
	}
3433 3434 3435
	spin_unlock(&fp->fi_lock);
	if (filp)
		fput(filp);
3436

3437 3438 3439 3440 3441
	status = nfsd4_truncate(rqstp, cur_fh, open);
	if (status)
		goto out_put_access;
out:
	return status;
3442 3443 3444 3445 3446
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;
L
Linus Torvalds 已提交
3447 3448
}

3449
static __be32
3450
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)
L
Linus Torvalds 已提交
3451
{
3452
	__be32 status;
3453
	unsigned char old_deny_bmap;
L
Linus Torvalds 已提交
3454

3455
	if (!test_access(open->op_share_access, stp))
3456
		return nfs4_get_vfs_file(rqstp, fp, cur_fh, stp, open);
3457

3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469
	/* test and set deny mode */
	spin_lock(&fp->fi_lock);
	status = nfs4_file_check_deny(fp, open->op_share_deny);
	if (status == nfs_ok) {
		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);
	}
	spin_unlock(&fp->fi_lock);

	if (status != nfs_ok)
L
Linus Torvalds 已提交
3470 3471
		return status;

3472 3473 3474 3475 3476
	status = nfsd4_truncate(rqstp, cur_fh, open);
	if (status != nfs_ok)
		reset_union_bmap_deny(old_deny_bmap, stp);
	return status;
}
L
Linus Torvalds 已提交
3477 3478

static void
3479
nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
L
Linus Torvalds 已提交
3480
{
3481
	open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
L
Linus Torvalds 已提交
3482 3483
}

3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496
/* 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;
}

3497
static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag)
3498 3499 3500 3501 3502 3503 3504 3505
{
	struct file_lock *fl;

	fl = locks_alloc_lock();
	if (!fl)
		return NULL;
	locks_init_lock(fl);
	fl->fl_lmops = &nfsd_lease_mng_ops;
3506
	fl->fl_flags = FL_DELEG;
3507 3508
	fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
	fl->fl_end = OFFSET_MAX;
3509
	fl->fl_owner = (fl_owner_t)fp;
3510 3511 3512 3513
	fl->fl_pid = current->tgid;
	return fl;
}

3514
static int nfs4_setlease(struct nfs4_delegation *dp)
3515
{
3516
	struct nfs4_file *fp = dp->dl_file;
3517
	struct file_lock *fl;
3518 3519
	struct file *filp;
	int status = 0;
3520

3521
	fl = nfs4_alloc_init_lease(fp, NFS4_OPEN_DELEGATE_READ);
3522 3523
	if (!fl)
		return -ENOMEM;
3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548
	filp = find_readable_file(fp);
	if (!filp) {
		/* We should always have a readable file here */
		WARN_ON_ONCE(1);
		return -EBADF;
	}
	fl->fl_file = filp;
	status = vfs_setlease(filp, fl->fl_type, &fl);
	if (status) {
		locks_free_lock(fl);
		goto out_fput;
	}
	spin_lock(&state_lock);
	spin_lock(&fp->fi_lock);
	/* Did the lease get broken before we took the lock? */
	status = -EAGAIN;
	if (fp->fi_had_conflict)
		goto out_unlock;
	/* Race breaker */
	if (fp->fi_lease) {
		status = 0;
		atomic_inc(&fp->fi_delegees);
		hash_delegation_locked(dp, fp);
		goto out_unlock;
	}
3549
	fp->fi_lease = fl;
3550
	fp->fi_deleg_file = filp;
3551
	atomic_set(&fp->fi_delegees, 1);
3552
	hash_delegation_locked(dp, fp);
3553
	spin_unlock(&fp->fi_lock);
3554
	spin_unlock(&state_lock);
3555
	return 0;
3556 3557 3558 3559 3560
out_unlock:
	spin_unlock(&fp->fi_lock);
	spin_unlock(&state_lock);
out_fput:
	fput(filp);
3561
	return status;
3562 3563
}

3564
static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
3565
{
3566 3567
	int status = 0;

3568 3569 3570
	if (fp->fi_had_conflict)
		return -EAGAIN;
	get_nfs4_file(fp);
3571 3572
	spin_lock(&state_lock);
	spin_lock(&fp->fi_lock);
3573
	dp->dl_file = fp;
3574 3575 3576
	if (!fp->fi_lease) {
		spin_unlock(&fp->fi_lock);
		spin_unlock(&state_lock);
3577
		return nfs4_setlease(dp);
3578
	}
3579
	atomic_inc(&fp->fi_delegees);
3580
	if (fp->fi_had_conflict) {
3581 3582
		status = -EAGAIN;
		goto out_unlock;
3583
	}
3584
	hash_delegation_locked(dp, fp);
3585 3586
out_unlock:
	spin_unlock(&fp->fi_lock);
3587
	spin_unlock(&state_lock);
3588
	return status;
3589 3590
}

3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606
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:
3607
			WARN_ON_ONCE(1);
3608 3609 3610 3611
		}
	}
}

L
Linus Torvalds 已提交
3612 3613
/*
 * Attempt to hand out a delegation.
3614 3615 3616
 *
 * Note we don't support write delegations, and won't until the vfs has
 * proper support for them.
L
Linus Torvalds 已提交
3617 3618
 */
static void
3619 3620
nfs4_open_delegation(struct net *net, struct svc_fh *fh,
		     struct nfsd4_open *open, struct nfs4_ol_stateid *stp)
L
Linus Torvalds 已提交
3621 3622
{
	struct nfs4_delegation *dp;
3623
	struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
3624
	int cb_up;
3625
	int status = 0;
L
Linus Torvalds 已提交
3626

3627
	cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
3628 3629 3630
	open->op_recall = 0;
	switch (open->op_claim_type) {
		case NFS4_OPEN_CLAIM_PREVIOUS:
3631
			if (!cb_up)
3632
				open->op_recall = 1;
3633 3634
			if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
				goto out_no_deleg;
3635 3636
			break;
		case NFS4_OPEN_CLAIM_NULL:
3637
		case NFS4_OPEN_CLAIM_FH:
3638 3639 3640 3641
			/*
			 * Let's not give out any delegations till everyone's
			 * had the chance to reclaim theirs....
			 */
3642
			if (locks_in_grace(net))
3643
				goto out_no_deleg;
3644
			if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
3645
				goto out_no_deleg;
3646 3647 3648 3649 3650 3651 3652
			/*
			 * 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):
			 */
3653
			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
3654 3655 3656
				goto out_no_deleg;
			if (open->op_create == NFS4_OPEN_CREATE)
				goto out_no_deleg;
3657 3658
			break;
		default:
3659
			goto out_no_deleg;
3660
	}
3661
	dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh);
3662 3663
	if (dp == NULL)
		goto out_no_deleg;
3664
	status = nfs4_set_delegation(dp, stp->st_file);
3665
	if (status)
3666
		goto out_free;
L
Linus Torvalds 已提交
3667

3668
	memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
L
Linus Torvalds 已提交
3669

3670
	dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
3671
		STATEID_VAL(&dp->dl_stid.sc_stateid));
3672
	open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
3673 3674
	return;
out_free:
3675
	destroy_delegation(dp);
3676
out_no_deleg:
3677 3678
	open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3679
	    open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) {
3680
		dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3681 3682
		open->op_recall = 1;
	}
3683 3684 3685 3686 3687

	/* 4.1 client asking for a delegation? */
	if (open->op_deleg_want)
		nfsd4_open_deleg_none_ext(open, status);
	return;
L
Linus Torvalds 已提交
3688 3689
}

3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707
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.
	 */
}

L
Linus Torvalds 已提交
3708 3709 3710
/*
 * called with nfs4_lock_state() held.
 */
3711
__be32
L
Linus Torvalds 已提交
3712 3713
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
A
Andy Adamson 已提交
3714
	struct nfsd4_compoundres *resp = rqstp->rq_resp;
3715
	struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
L
Linus Torvalds 已提交
3716 3717
	struct nfs4_file *fp = NULL;
	struct inode *ino = current_fh->fh_dentry->d_inode;
3718
	struct nfs4_ol_stateid *stp = NULL;
3719
	struct nfs4_delegation *dp = NULL;
3720
	__be32 status;
L
Linus Torvalds 已提交
3721 3722 3723 3724 3725 3726

	/*
	 * 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
	 */
3727
	fp = find_or_add_file(ino, open->op_file, &current_fh->fh_handle);
3728
	if (fp != open->op_file) {
3729
		status = nfs4_check_deleg(cl, open, &dp);
3730 3731
		if (status)
			goto out;
3732
		stp = nfsd4_find_existing_open(fp, open);
L
Linus Torvalds 已提交
3733
	} else {
3734
		open->op_file = NULL;
3735
		status = nfserr_bad_stateid;
3736
		if (nfsd4_is_deleg_cur(open))
3737
			goto out;
3738
		status = nfserr_jukebox;
L
Linus Torvalds 已提交
3739 3740 3741 3742 3743 3744 3745 3746
	}

	/*
	 * OPEN the file, or upgrade an existing OPEN.
	 * If truncate fails, the OPEN fails.
	 */
	if (stp) {
		/* Stateid was found, this is an OPEN upgrade */
3747
		status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
L
Linus Torvalds 已提交
3748 3749 3750
		if (status)
			goto out;
	} else {
3751 3752
		stp = open->op_stp;
		open->op_stp = NULL;
3753
		init_open_stateid(stp, fp, open);
3754 3755 3756 3757 3758
		status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
		if (status) {
			release_open_stateid(stp);
			goto out;
		}
L
Linus Torvalds 已提交
3759
	}
3760 3761
	update_stateid(&stp->st_stid.sc_stateid);
	memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
L
Linus Torvalds 已提交
3762

3763 3764 3765 3766 3767 3768 3769 3770
	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;
		}
	}

L
Linus Torvalds 已提交
3771 3772 3773 3774
	/*
	* Attempt to hand out a delegation. No error return, because the
	* OPEN succeeds even if we fail.
	*/
3775
	nfs4_open_delegation(SVC_NET(rqstp), current_fh, open, stp);
3776
nodeleg:
L
Linus Torvalds 已提交
3777 3778
	status = nfs_ok;

3779
	dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
3780
		STATEID_VAL(&stp->st_stid.sc_stateid));
L
Linus Torvalds 已提交
3781
out:
3782 3783
	/* 4.1 client trying to upgrade/downgrade delegation? */
	if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
3784 3785
	    open->op_deleg_want)
		nfsd4_deleg_xgrade_none_ext(open, dp);
3786

3787 3788
	if (fp)
		put_nfs4_file(fp);
3789
	if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
3790
		nfs4_set_claim_prev(open, nfsd4_has_session(&resp->cstate));
L
Linus Torvalds 已提交
3791 3792 3793 3794
	/*
	* To finish the open response, we just need to set the rflags.
	*/
	open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
3795
	if (!(open->op_openowner->oo_flags & NFS4_OO_CONFIRMED) &&
A
Andy Adamson 已提交
3796
	    !nfsd4_has_session(&resp->cstate))
L
Linus Torvalds 已提交
3797 3798 3799 3800 3801
		open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;

	return status;
}

3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816
void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
{
	if (open->op_openowner) {
		struct nfs4_openowner *oo = open->op_openowner;

		if (!list_empty(&oo->oo_owner.so_stateids))
			list_del_init(&oo->oo_close_lru);
		if (oo->oo_flags & NFS4_OO_NEW) {
			if (status) {
				release_openowner(oo);
				open->op_openowner = NULL;
			} else
				oo->oo_flags &= ~NFS4_OO_NEW;
		}
	}
3817 3818
	if (open->op_file)
		nfsd4_free_file(open->op_file);
3819
	if (open->op_stp)
3820
		free_generic_stateid(open->op_stp);
3821 3822
}

3823
__be32
3824 3825
nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	    clientid_t *clid)
L
Linus Torvalds 已提交
3826 3827
{
	struct nfs4_client *clp;
3828
	__be32 status;
3829
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
3830 3831 3832 3833

	nfs4_lock_state();
	dprintk("process_renew(%08x/%08x): starting\n", 
			clid->cl_boot, clid->cl_id);
3834
	status = lookup_clientid(clid, cstate, nn);
3835
	if (status)
L
Linus Torvalds 已提交
3836
		goto out;
3837
	clp = cstate->clp;
L
Linus Torvalds 已提交
3838
	status = nfserr_cb_path_down;
3839
	if (!list_empty(&clp->cl_delegations)
3840
			&& clp->cl_cb_state != NFSD4_CB_UP)
L
Linus Torvalds 已提交
3841 3842 3843 3844 3845 3846 3847
		goto out;
	status = nfs_ok;
out:
	nfs4_unlock_state();
	return status;
}

3848
static void
3849
nfsd4_end_grace(struct nfsd_net *nn)
3850
{
3851
	/* do nothing if grace period already ended */
3852
	if (nn->grace_ended)
3853 3854
		return;

3855
	dprintk("NFSD: end of grace period\n");
3856
	nn->grace_ended = true;
3857
	nfsd4_record_grace_done(nn, nn->boot_time);
3858
	locks_end_grace(&nn->nfsd4_manager);
3859 3860 3861 3862 3863
	/*
	 * Now that every NFSv4 client has had the chance to recover and
	 * to see the (possibly new, possibly shorter) lease time, we
	 * can safely set the next grace time to the current lease time:
	 */
3864
	nn->nfsd4_grace = nn->nfsd4_lease;
3865 3866
}

3867
static time_t
3868
nfs4_laundromat(struct nfsd_net *nn)
L
Linus Torvalds 已提交
3869 3870
{
	struct nfs4_client *clp;
3871
	struct nfs4_openowner *oo;
L
Linus Torvalds 已提交
3872 3873
	struct nfs4_delegation *dp;
	struct list_head *pos, *next, reaplist;
3874
	time_t cutoff = get_seconds() - nn->nfsd4_lease;
3875
	time_t t, new_timeo = nn->nfsd4_lease;
L
Linus Torvalds 已提交
3876 3877 3878 3879

	nfs4_lock_state();

	dprintk("NFSD: laundromat service - starting\n");
3880
	nfsd4_end_grace(nn);
3881
	INIT_LIST_HEAD(&reaplist);
3882
	spin_lock(&nn->client_lock);
3883
	list_for_each_safe(pos, next, &nn->client_lru) {
L
Linus Torvalds 已提交
3884 3885 3886
		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;
3887
			new_timeo = min(new_timeo, t);
L
Linus Torvalds 已提交
3888 3889
			break;
		}
3890
		if (mark_client_expired_locked(clp)) {
3891 3892 3893 3894
			dprintk("NFSD: client in use (clientid %08x)\n",
				clp->cl_clientid.cl_id);
			continue;
		}
3895
		list_move(&clp->cl_lru, &reaplist);
3896
	}
3897
	spin_unlock(&nn->client_lock);
3898 3899
	list_for_each_safe(pos, next, &reaplist) {
		clp = list_entry(pos, struct nfs4_client, cl_lru);
L
Linus Torvalds 已提交
3900 3901 3902 3903
		dprintk("NFSD: purging unused client (clientid %08x)\n",
			clp->cl_clientid.cl_id);
		expire_client(clp);
	}
3904
	spin_lock(&state_lock);
3905
	list_for_each_safe(pos, next, &nn->del_recall_lru) {
L
Linus Torvalds 已提交
3906
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
3907 3908
		if (net_generic(dp->dl_stid.sc_client->net, nfsd_net_id) != nn)
			continue;
L
Linus Torvalds 已提交
3909
		if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
3910 3911
			t = dp->dl_time - cutoff;
			new_timeo = min(new_timeo, t);
L
Linus Torvalds 已提交
3912 3913 3914 3915
			break;
		}
		list_move(&dp->dl_recall_lru, &reaplist);
	}
3916
	spin_unlock(&state_lock);
L
Linus Torvalds 已提交
3917 3918
	list_for_each_safe(pos, next, &reaplist) {
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
3919
		revoke_delegation(dp);
L
Linus Torvalds 已提交
3920
	}
3921
	list_for_each_safe(pos, next, &nn->close_lru) {
3922 3923
		oo = container_of(pos, struct nfs4_openowner, oo_close_lru);
		if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) {
3924 3925
			t = oo->oo_time - cutoff;
			new_timeo = min(new_timeo, t);
L
Linus Torvalds 已提交
3926 3927
			break;
		}
3928
		release_openowner(oo);
L
Linus Torvalds 已提交
3929
	}
3930
	new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT);
L
Linus Torvalds 已提交
3931
	nfs4_unlock_state();
3932
	return new_timeo;
L
Linus Torvalds 已提交
3933 3934
}

H
Harvey Harrison 已提交
3935 3936 3937 3938
static struct workqueue_struct *laundry_wq;
static void laundromat_main(struct work_struct *);

static void
3939
laundromat_main(struct work_struct *laundry)
L
Linus Torvalds 已提交
3940 3941
{
	time_t t;
3942 3943 3944 3945
	struct delayed_work *dwork = container_of(laundry, struct delayed_work,
						  work);
	struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
					   laundromat_work);
L
Linus Torvalds 已提交
3946

3947
	t = nfs4_laundromat(nn);
L
Linus Torvalds 已提交
3948
	dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
3949
	queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ);
L
Linus Torvalds 已提交
3950 3951
}

3952
static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp)
L
Linus Torvalds 已提交
3953
{
3954
	if (!nfsd_fh_match(&fhp->fh_handle, &stp->st_file->fi_fhandle))
3955 3956
		return nfserr_bad_stateid;
	return nfs_ok;
L
Linus Torvalds 已提交
3957 3958 3959
}

static inline int
3960
access_permit_read(struct nfs4_ol_stateid *stp)
L
Linus Torvalds 已提交
3961
{
3962 3963 3964
	return test_access(NFS4_SHARE_ACCESS_READ, stp) ||
		test_access(NFS4_SHARE_ACCESS_BOTH, stp) ||
		test_access(NFS4_SHARE_ACCESS_WRITE, stp);
L
Linus Torvalds 已提交
3965 3966 3967
}

static inline int
3968
access_permit_write(struct nfs4_ol_stateid *stp)
L
Linus Torvalds 已提交
3969
{
3970 3971
	return test_access(NFS4_SHARE_ACCESS_WRITE, stp) ||
		test_access(NFS4_SHARE_ACCESS_BOTH, stp);
L
Linus Torvalds 已提交
3972 3973 3974
}

static
3975
__be32 nfs4_check_openmode(struct nfs4_ol_stateid *stp, int flags)
L
Linus Torvalds 已提交
3976
{
3977
        __be32 status = nfserr_openmode;
L
Linus Torvalds 已提交
3978

3979 3980 3981
	/* For lock stateid's, we test the parent open, not the lock: */
	if (stp->st_openstp)
		stp = stp->st_openstp;
3982
	if ((flags & WR_STATE) && !access_permit_write(stp))
L
Linus Torvalds 已提交
3983
                goto out;
3984
	if ((flags & RD_STATE) && !access_permit_read(stp))
L
Linus Torvalds 已提交
3985 3986 3987 3988 3989 3990
                goto out;
	status = nfs_ok;
out:
	return status;
}

3991
static inline __be32
3992
check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid, int flags)
L
Linus Torvalds 已提交
3993
{
3994
	if (ONE_STATEID(stateid) && (flags & RD_STATE))
L
Linus Torvalds 已提交
3995
		return nfs_ok;
3996
	else if (locks_in_grace(net)) {
L
Lucas De Marchi 已提交
3997
		/* Answer in remaining cases depends on existence of
L
Linus Torvalds 已提交
3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012
		 * 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
4013
grace_disallows_io(struct net *net, struct inode *inode)
L
Linus Torvalds 已提交
4014
{
4015
	return locks_in_grace(net) && mandatory_lock(inode);
L
Linus Torvalds 已提交
4016 4017
}

4018 4019 4020
/* Returns true iff a is later than b: */
static bool stateid_generation_after(stateid_t *a, stateid_t *b)
{
J
Jim Rees 已提交
4021
	return (s32)(a->si_generation - b->si_generation) > 0;
4022 4023
}

J
J. Bruce Fields 已提交
4024
static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
4025
{
A
Andy Adamson 已提交
4026 4027 4028 4029
	/*
	 * When sessions are used the stateid generation number is ignored
	 * when it is zero.
	 */
J
J. Bruce Fields 已提交
4030
	if (has_session && in->si_generation == 0)
4031 4032 4033 4034
		return nfs_ok;

	if (in->si_generation == ref->si_generation)
		return nfs_ok;
A
Andy Adamson 已提交
4035

4036
	/* If the client sends us a stateid from the future, it's buggy: */
4037
	if (stateid_generation_after(in, ref))
4038 4039
		return nfserr_bad_stateid;
	/*
4040 4041 4042 4043 4044 4045 4046 4047
	 * 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:
4048
	 */
4049
	return nfserr_old_stateid;
4050 4051
}

4052
static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
4053
{
4054 4055 4056
	struct nfs4_stid *s;
	struct nfs4_ol_stateid *ols;
	__be32 status;
4057

4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068
	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
		return nfserr_bad_stateid;
	/* 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);
		return nfserr_bad_stateid;
	}
4069
	s = find_stateid(cl, stateid);
4070
	if (!s)
4071
		return nfserr_bad_stateid;
4072
	status = check_stateid_generation(stateid, &s->sc_stateid, 1);
4073
	if (status)
4074
		return status;
4075 4076
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
4077
		return nfs_ok;
4078 4079
	case NFS4_REVOKED_DELEG_STID:
		return nfserr_deleg_revoked;
4080 4081 4082 4083 4084 4085 4086
	case NFS4_OPEN_STID:
	case NFS4_LOCK_STID:
		ols = openlockstateid(s);
		if (ols->st_stateowner->so_is_open_owner
	    			&& !(openowner(ols->st_stateowner)->oo_flags
						& NFS4_OO_CONFIRMED))
			return nfserr_bad_stateid;
4087
		return nfs_ok;
4088 4089
	default:
		printk("unknown stateid type %x\n", s->sc_type);
4090
		/* Fallthrough */
4091
	case NFS4_CLOSED_STID:
4092
	case NFS4_CLOSED_DELEG_STID:
4093
		return nfserr_bad_stateid;
4094
	}
4095 4096
}

4097 4098 4099 4100
static __be32
nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
		     stateid_t *stateid, unsigned char typemask,
		     struct nfs4_stid **s, struct nfsd_net *nn)
4101
{
J
J. Bruce Fields 已提交
4102
	__be32 status;
4103 4104 4105

	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
		return nfserr_bad_stateid;
4106
	status = lookup_clientid(&stateid->si_opaque.so_clid, cstate, nn);
4107
	if (status == nfserr_stale_clientid) {
4108
		if (cstate->session)
4109
			return nfserr_bad_stateid;
4110
		return nfserr_stale_stateid;
4111
	}
J
J. Bruce Fields 已提交
4112 4113
	if (status)
		return status;
4114
	*s = find_stateid_by_type(cstate->clp, stateid, typemask);
4115 4116 4117 4118 4119
	if (!*s)
		return nfserr_bad_stateid;
	return nfs_ok;
}

L
Linus Torvalds 已提交
4120 4121 4122
/*
* Checks for stateid operations
*/
4123
__be32
4124
nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
4125
			   stateid_t *stateid, int flags, struct file **filpp)
L
Linus Torvalds 已提交
4126
{
4127
	struct nfs4_stid *s;
4128
	struct nfs4_ol_stateid *stp = NULL;
L
Linus Torvalds 已提交
4129
	struct nfs4_delegation *dp = NULL;
4130
	struct svc_fh *current_fh = &cstate->current_fh;
L
Linus Torvalds 已提交
4131
	struct inode *ino = current_fh->fh_dentry->d_inode;
4132
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4133
	struct file *file = NULL;
4134
	__be32 status;
L
Linus Torvalds 已提交
4135 4136 4137 4138

	if (filpp)
		*filpp = NULL;

4139
	if (grace_disallows_io(net, ino))
L
Linus Torvalds 已提交
4140 4141 4142
		return nfserr_grace;

	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
4143
		return check_special_stateids(net, current_fh, stateid, flags);
L
Linus Torvalds 已提交
4144

4145 4146
	nfs4_lock_state();

4147
	status = nfsd4_lookup_stateid(cstate, stateid,
4148
				NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID,
4149
				&s, nn);
4150
	if (status)
4151
		goto out;
4152 4153 4154
	status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
	if (status)
		goto out;
4155 4156
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
4157
		dp = delegstateid(s);
4158 4159 4160
		status = nfs4_check_delegmode(dp, flags);
		if (status)
			goto out;
4161
		if (filpp) {
4162 4163
			file = dp->dl_file->fi_deleg_file;
			if (!file) {
4164 4165 4166 4167
				WARN_ON_ONCE(1);
				status = nfserr_serverfault;
				goto out;
			}
4168
			get_file(file);
4169
		}
4170 4171 4172
		break;
	case NFS4_OPEN_STID:
	case NFS4_LOCK_STID:
4173
		stp = openlockstateid(s);
4174 4175
		status = nfs4_check_fh(current_fh, stp);
		if (status)
L
Linus Torvalds 已提交
4176
			goto out;
4177
		if (stp->st_stateowner->so_is_open_owner
4178
		    && !(openowner(stp->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
L
Linus Torvalds 已提交
4179
			goto out;
4180 4181
		status = nfs4_check_openmode(stp, flags);
		if (status)
L
Linus Torvalds 已提交
4182
			goto out;
4183 4184
		if (filpp) {
			if (flags & RD_STATE)
4185
				file = find_readable_file(stp->st_file);
4186
			else
4187
				file = find_writeable_file(stp->st_file);
4188
		}
4189 4190
		break;
	default:
4191 4192
		status = nfserr_bad_stateid;
		goto out;
L
Linus Torvalds 已提交
4193 4194
	}
	status = nfs_ok;
4195
	if (file)
4196
		*filpp = file;
L
Linus Torvalds 已提交
4197
out:
4198
	nfs4_unlock_state();
L
Linus Torvalds 已提交
4199 4200 4201
	return status;
}

4202
static __be32
4203
nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp)
4204
{
4205 4206 4207
	struct nfs4_lockowner *lo = lockowner(stp->st_stateowner);

	if (check_for_locks(stp->st_file, lo))
4208
		return nfserr_locks_held;
4209
	release_lockowner_if_empty(lo);
4210 4211 4212
	return nfs_ok;
}

4213 4214 4215 4216 4217 4218 4219
/*
 * Test if the stateid is valid
 */
__be32
nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		   struct nfsd4_test_stateid *test_stateid)
{
4220 4221 4222 4223 4224
	struct nfsd4_test_stateid_id *stateid;
	struct nfs4_client *cl = cstate->session->se_client;

	nfs4_lock_state();
	list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
4225 4226
		stateid->ts_id_status =
			nfsd4_validate_stateid(cl, &stateid->ts_id_stateid);
4227 4228
	nfs4_unlock_state();

4229 4230 4231
	return nfs_ok;
}

4232 4233 4234 4235 4236
__be32
nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		   struct nfsd4_free_stateid *free_stateid)
{
	stateid_t *stateid = &free_stateid->fr_stateid;
J
J. Bruce Fields 已提交
4237
	struct nfs4_stid *s;
4238
	struct nfs4_delegation *dp;
4239
	struct nfs4_client *cl = cstate->session->se_client;
J
J. Bruce Fields 已提交
4240
	__be32 ret = nfserr_bad_stateid;
4241 4242

	nfs4_lock_state();
4243
	s = find_stateid(cl, stateid);
J
J. Bruce Fields 已提交
4244
	if (!s)
4245
		goto out;
J
J. Bruce Fields 已提交
4246 4247
	switch (s->sc_type) {
	case NFS4_DELEG_STID:
4248 4249
		ret = nfserr_locks_held;
		goto out;
J
J. Bruce Fields 已提交
4250 4251 4252 4253 4254 4255 4256 4257 4258
	case NFS4_OPEN_STID:
	case NFS4_LOCK_STID:
		ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
		if (ret)
			goto out;
		if (s->sc_type == NFS4_LOCK_STID)
			ret = nfsd4_free_lock_stateid(openlockstateid(s));
		else
			ret = nfserr_locks_held;
4259
		break;
4260 4261 4262 4263 4264
	case NFS4_REVOKED_DELEG_STID:
		dp = delegstateid(s);
		destroy_revoked_delegation(dp);
		ret = nfs_ok;
		break;
4265 4266
	default:
		ret = nfserr_bad_stateid;
4267 4268 4269 4270 4271 4272
	}
out:
	nfs4_unlock_state();
	return ret;
}

4273 4274 4275 4276 4277 4278
static inline int
setlkflg (int type)
{
	return (type == NFS4_READW_LT || type == NFS4_READ_LT) ?
		RD_STATE : WR_STATE;
}
L
Linus Torvalds 已提交
4279

4280
static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_t *stateid, u32 seqid, struct nfs4_ol_stateid *stp)
4281 4282 4283 4284 4285 4286 4287 4288
{
	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;
4289 4290
	if (stp->st_stid.sc_type == NFS4_CLOSED_STID
		|| stp->st_stid.sc_type == NFS4_REVOKED_DELEG_STID)
4291 4292
		/*
		 * "Closed" stateid's exist *only* to return
4293 4294
		 * nfserr_replay_me from the previous step, and
		 * revoked delegations are kept only for free_stateid.
4295 4296 4297 4298 4299 4300
		 */
		return nfserr_bad_stateid;
	status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
	if (status)
		return status;
	return nfs4_check_fh(current_fh, stp);
4301 4302
}

L
Linus Torvalds 已提交
4303 4304 4305
/* 
 * Checks for sequence id mutating operations. 
 */
4306
static __be32
4307
nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
4308
			 stateid_t *stateid, char typemask,
4309 4310
			 struct nfs4_ol_stateid **stpp,
			 struct nfsd_net *nn)
L
Linus Torvalds 已提交
4311
{
4312
	__be32 status;
4313
	struct nfs4_stid *s;
4314
	struct nfs4_ol_stateid *stp = NULL;
L
Linus Torvalds 已提交
4315

4316 4317
	dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__,
		seqid, STATEID_VAL(stateid));
4318

L
Linus Torvalds 已提交
4319
	*stpp = NULL;
4320
	status = nfsd4_lookup_stateid(cstate, stateid, typemask, &s, nn);
4321 4322
	if (status)
		return status;
4323
	stp = openlockstateid(s);
4324
	if (!nfsd4_has_session(cstate))
4325
		cstate->replay_owner = stp->st_stateowner;
L
Linus Torvalds 已提交
4326

4327 4328 4329 4330
	status = nfs4_seqid_op_checks(cstate, stateid, seqid, stp);
	if (!status)
		*stpp = stp;
	return status;
4331
}
4332

4333 4334
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)
4335 4336 4337
{
	__be32 status;
	struct nfs4_openowner *oo;
L
Linus Torvalds 已提交
4338

4339
	status = nfs4_preprocess_seqid_op(cstate, seqid, stateid,
4340
						NFS4_OPEN_STID, stpp, nn);
4341 4342
	if (status)
		return status;
4343
	oo = openowner((*stpp)->st_stateowner);
4344
	if (!(oo->oo_flags & NFS4_OO_CONFIRMED))
4345 4346
		return nfserr_bad_stateid;
	return nfs_ok;
L
Linus Torvalds 已提交
4347 4348
}

4349
__be32
4350
nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4351
		   struct nfsd4_open_confirm *oc)
L
Linus Torvalds 已提交
4352
{
4353
	__be32 status;
4354
	struct nfs4_openowner *oo;
4355
	struct nfs4_ol_stateid *stp;
4356
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
4357

A
Al Viro 已提交
4358 4359
	dprintk("NFSD: nfsd4_open_confirm on file %pd\n",
			cstate->current_fh.fh_dentry);
L
Linus Torvalds 已提交
4360

4361
	status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
4362 4363
	if (status)
		return status;
L
Linus Torvalds 已提交
4364 4365 4366

	nfs4_lock_state();

4367
	status = nfs4_preprocess_seqid_op(cstate,
4368
					oc->oc_seqid, &oc->oc_req_stateid,
4369
					NFS4_OPEN_STID, &stp, nn);
4370
	if (status)
4371
		goto out;
4372
	oo = openowner(stp->st_stateowner);
4373
	status = nfserr_bad_stateid;
4374
	if (oo->oo_flags & NFS4_OO_CONFIRMED)
4375
		goto out;
4376
	oo->oo_flags |= NFS4_OO_CONFIRMED;
4377 4378
	update_stateid(&stp->st_stid.sc_stateid);
	memcpy(&oc->oc_resp_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4379
	dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
4380
		__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
4381

4382
	nfsd4_client_record_create(oo->oo_owner.so_client);
4383
	status = nfs_ok;
L
Linus Torvalds 已提交
4384
out:
4385
	nfsd4_bump_seqid(cstate, status);
4386 4387
	if (!cstate->replay_owner)
		nfs4_unlock_state();
L
Linus Torvalds 已提交
4388 4389 4390
	return status;
}

J
J. Bruce Fields 已提交
4391
static inline void nfs4_stateid_downgrade_bit(struct nfs4_ol_stateid *stp, u32 access)
L
Linus Torvalds 已提交
4392
{
4393
	if (!test_access(access, stp))
J
J. Bruce Fields 已提交
4394
		return;
4395
	nfs4_file_put_access(stp->st_file, access);
4396
	clear_access(access, stp);
J
J. Bruce Fields 已提交
4397
}
4398

J
J. Bruce Fields 已提交
4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412
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:
4413
		WARN_ON_ONCE(1);
L
Linus Torvalds 已提交
4414 4415 4416
	}
}

4417
__be32
4418 4419
nfsd4_open_downgrade(struct svc_rqst *rqstp,
		     struct nfsd4_compound_state *cstate,
4420
		     struct nfsd4_open_downgrade *od)
L
Linus Torvalds 已提交
4421
{
4422
	__be32 status;
4423
	struct nfs4_ol_stateid *stp;
4424
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
4425

A
Al Viro 已提交
4426 4427
	dprintk("NFSD: nfsd4_open_downgrade on file %pd\n", 
			cstate->current_fh.fh_dentry);
L
Linus Torvalds 已提交
4428

4429
	/* We don't yet support WANT bits: */
4430 4431 4432
	if (od->od_deleg_want)
		dprintk("NFSD: %s: od_deleg_want=0x%x ignored\n", __func__,
			od->od_deleg_want);
L
Linus Torvalds 已提交
4433 4434

	nfs4_lock_state();
4435
	status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
4436
					&od->od_stateid, &stp, nn);
4437
	if (status)
L
Linus Torvalds 已提交
4438 4439
		goto out; 
	status = nfserr_inval;
4440
	if (!test_access(od->od_share_access, stp)) {
4441
		dprintk("NFSD: access not a subset of current bitmap: 0x%hhx, input access=%08x\n",
L
Linus Torvalds 已提交
4442 4443 4444
			stp->st_access_bmap, od->od_share_access);
		goto out;
	}
4445
	if (!test_deny(od->od_share_deny, stp)) {
4446
		dprintk("NFSD: deny not a subset of current bitmap: 0x%hhx, input deny=%08x\n",
L
Linus Torvalds 已提交
4447 4448 4449
			stp->st_deny_bmap, od->od_share_deny);
		goto out;
	}
J
J. Bruce Fields 已提交
4450
	nfs4_stateid_downgrade(stp, od->od_share_access);
L
Linus Torvalds 已提交
4451

4452
	reset_union_bmap_deny(od->od_share_deny, stp);
L
Linus Torvalds 已提交
4453

4454 4455
	update_stateid(&stp->st_stid.sc_stateid);
	memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
L
Linus Torvalds 已提交
4456 4457
	status = nfs_ok;
out:
4458
	nfsd4_bump_seqid(cstate, status);
4459 4460
	if (!cstate->replay_owner)
		nfs4_unlock_state();
L
Linus Torvalds 已提交
4461 4462 4463
	return status;
}

4464 4465
static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s)
{
4466 4467 4468
	struct nfs4_client *clp = s->st_stid.sc_client;
	struct nfs4_openowner *oo = openowner(s->st_stateowner);

4469
	s->st_stid.sc_type = NFS4_CLOSED_STID;
4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484
	unhash_open_stateid(s);

	if (clp->cl_minorversion) {
		free_generic_stateid(s);
		if (list_empty(&oo->oo_owner.so_stateids))
			release_openowner(oo);
	} else {
		oo->oo_last_closed_stid = s;
		/*
		 * In the 4.0 case we need to keep the owners around a
		 * little while to handle CLOSE replay.
		 */
		if (list_empty(&oo->oo_owner.so_stateids))
			move_to_close_lru(oo, clp->net);
	}
4485 4486
}

L
Linus Torvalds 已提交
4487 4488 4489
/*
 * nfs4_unlock_state() called after encode
 */
4490
__be32
4491
nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4492
	    struct nfsd4_close *close)
L
Linus Torvalds 已提交
4493
{
4494
	__be32 status;
4495
	struct nfs4_ol_stateid *stp;
4496 4497
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
L
Linus Torvalds 已提交
4498

A
Al Viro 已提交
4499 4500
	dprintk("NFSD: nfsd4_close on file %pd\n", 
			cstate->current_fh.fh_dentry);
L
Linus Torvalds 已提交
4501 4502

	nfs4_lock_state();
4503 4504 4505
	status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid,
					&close->cl_stateid,
					NFS4_OPEN_STID|NFS4_CLOSED_STID,
4506
					&stp, nn);
4507
	nfsd4_bump_seqid(cstate, status);
4508
	if (status)
L
Linus Torvalds 已提交
4509
		goto out; 
4510 4511
	update_stateid(&stp->st_stid.sc_stateid);
	memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
L
Linus Torvalds 已提交
4512

4513
	nfsd4_close_open_stateid(stp);
L
Linus Torvalds 已提交
4514
out:
4515 4516
	if (!cstate->replay_owner)
		nfs4_unlock_state();
L
Linus Torvalds 已提交
4517 4518 4519
	return status;
}

4520
__be32
4521 4522
nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		  struct nfsd4_delegreturn *dr)
L
Linus Torvalds 已提交
4523
{
4524 4525
	struct nfs4_delegation *dp;
	stateid_t *stateid = &dr->dr_stateid;
4526
	struct nfs4_stid *s;
4527
	__be32 status;
4528
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
4529

4530
	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
4531
		return status;
L
Linus Torvalds 已提交
4532 4533

	nfs4_lock_state();
4534
	status = nfsd4_lookup_stateid(cstate, stateid, NFS4_DELEG_STID, &s, nn);
4535
	if (status)
4536
		goto out;
4537
	dp = delegstateid(s);
4538
	status = check_stateid_generation(stateid, &dp->dl_stid.sc_stateid, nfsd4_has_session(cstate));
4539 4540 4541
	if (status)
		goto out;

4542
	destroy_delegation(dp);
L
Linus Torvalds 已提交
4543
out:
4544 4545
	nfs4_unlock_state();

L
Linus Torvalds 已提交
4546 4547 4548 4549 4550 4551
	return status;
}


#define LOFF_OVERFLOW(start, len)      ((u64)(len) > ~(u64)(start))

B
Benny Halevy 已提交
4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566
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;

4567
	WARN_ON_ONCE(!len);
B
Benny Halevy 已提交
4568 4569 4570 4571
	end = start + len;
	return end > start ? end - 1: NFS4_MAX_UINT64;
}

L
Linus Torvalds 已提交
4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588
/*
 * 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;
}

4589 4590
/* Hack!: For now, we're defining this just so we can use a pointer to it
 * as a unique cookie to identify our (NFSv4's) posix locks. */
4591
static const struct lock_manager_operations nfsd_posix_mng_ops  = {
4592
};
L
Linus Torvalds 已提交
4593 4594 4595 4596

static inline void
nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
{
4597
	struct nfs4_lockowner *lo;
L
Linus Torvalds 已提交
4598

4599
	if (fl->fl_lmops == &nfsd_posix_mng_ops) {
4600 4601 4602
		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);
4603 4604 4605
		if (!deny->ld_owner.data)
			/* We just don't care that much */
			goto nevermind;
4606 4607
		deny->ld_owner.len = lo->lo_owner.so_owner.len;
		deny->ld_clientid = lo->lo_owner.so_client->cl_clientid;
4608
	} else {
4609 4610 4611
nevermind:
		deny->ld_owner.len = 0;
		deny->ld_owner.data = NULL;
4612 4613
		deny->ld_clientid.cl_boot = 0;
		deny->ld_clientid.cl_id = 0;
L
Linus Torvalds 已提交
4614 4615
	}
	deny->ld_start = fl->fl_start;
B
Benny Halevy 已提交
4616 4617
	deny->ld_length = NFS4_MAX_UINT64;
	if (fl->fl_end != NFS4_MAX_UINT64)
L
Linus Torvalds 已提交
4618 4619 4620 4621 4622 4623
		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;
}

4624
static struct nfs4_lockowner *
4625 4626
find_lockowner_str(clientid_t *clid, struct xdr_netobj *owner,
		struct nfsd_net *nn)
L
Linus Torvalds 已提交
4627
{
4628 4629
	unsigned int strhashval = ownerstr_hashval(clid->cl_id, owner);
	struct nfs4_stateowner *so;
L
Linus Torvalds 已提交
4630

4631 4632 4633 4634 4635 4636
	list_for_each_entry(so, &nn->ownerstr_hashtbl[strhashval], so_strhash) {
		if (so->so_is_open_owner)
			continue;
		if (!same_owner_str(so, owner, clid))
			continue;
		return lockowner(so);
L
Linus Torvalds 已提交
4637 4638 4639 4640 4641 4642 4643
	}
	return NULL;
}

/*
 * Alloc a lock owner structure.
 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 
L
Lucas De Marchi 已提交
4644
 * occurred. 
L
Linus Torvalds 已提交
4645
 *
4646
 * strhashval = ownerstr_hashval
L
Linus Torvalds 已提交
4647
 */
4648
static struct nfs4_lockowner *
4649
alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp, struct nfsd4_lock *lock) {
4650
	struct nfs4_lockowner *lo;
4651
	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
L
Linus Torvalds 已提交
4652

4653 4654
	lo = alloc_stateowner(lockowner_slab, &lock->lk_new_owner, clp);
	if (!lo)
L
Linus Torvalds 已提交
4655
		return NULL;
4656 4657
	INIT_LIST_HEAD(&lo->lo_owner.so_stateids);
	lo->lo_owner.so_is_open_owner = 0;
4658 4659
	/* It is the openowner seqid that will be incremented in encode in the
	 * case of new lockowners; so increment the lock seqid manually: */
4660
	lo->lo_owner.so_seqid = lock->lk_new_lock_seqid + 1;
4661
	list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
4662
	return lo;
L
Linus Torvalds 已提交
4663 4664
}

4665 4666
static struct nfs4_ol_stateid *
alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct nfs4_ol_stateid *open_stp)
L
Linus Torvalds 已提交
4667
{
4668
	struct nfs4_ol_stateid *stp;
4669
	struct nfs4_client *clp = lo->lo_owner.so_client;
L
Linus Torvalds 已提交
4670

4671
	stp = nfs4_alloc_stateid(clp);
N
NeilBrown 已提交
4672
	if (stp == NULL)
J
J. Bruce Fields 已提交
4673
		return NULL;
J
J. Bruce Fields 已提交
4674
	stp->st_stid.sc_type = NFS4_LOCK_STID;
4675 4676
	list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
	stp->st_stateowner = &lo->lo_owner;
4677
	get_nfs4_file(fp);
L
Linus Torvalds 已提交
4678
	stp->st_file = fp;
J
J. Bruce Fields 已提交
4679
	stp->st_access_bmap = 0;
L
Linus Torvalds 已提交
4680
	stp->st_deny_bmap = open_stp->st_deny_bmap;
4681
	stp->st_openstp = open_stp;
4682
	list_add(&stp->st_locks, &open_stp->st_locks);
4683 4684 4685
	spin_lock(&fp->fi_lock);
	list_add(&stp->st_perfile, &fp->fi_stateids);
	spin_unlock(&fp->fi_lock);
L
Linus Torvalds 已提交
4686 4687 4688
	return stp;
}

4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701
static struct nfs4_ol_stateid *
find_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp)
{
	struct nfs4_ol_stateid *lst;

	list_for_each_entry(lst, &lo->lo_owner.so_stateids, st_perstateowner) {
		if (lst->st_file == fp)
			return lst;
	}
	return NULL;
}


4702
static int
L
Linus Torvalds 已提交
4703 4704
check_lock_length(u64 offset, u64 length)
{
B
Benny Halevy 已提交
4705
	return ((length == 0)  || ((length != NFS4_MAX_UINT64) &&
L
Linus Torvalds 已提交
4706 4707 4708
	     LOFF_OVERFLOW(offset, length)));
}

4709
static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access)
J
J. Bruce Fields 已提交
4710 4711 4712
{
	struct nfs4_file *fp = lock_stp->st_file;

4713 4714
	lockdep_assert_held(&fp->fi_lock);

4715
	if (test_access(access, lock_stp))
J
J. Bruce Fields 已提交
4716
		return;
4717
	__nfs4_file_get_access(fp, access);
4718
	set_access(access, lock_stp);
J
J. Bruce Fields 已提交
4719 4720
}

J
J. Bruce Fields 已提交
4721
static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct nfs4_ol_stateid *ost, struct nfsd4_lock *lock, struct nfs4_ol_stateid **lst, bool *new)
4722 4723 4724 4725 4726 4727
{
	struct nfs4_file *fi = ost->st_file;
	struct nfs4_openowner *oo = openowner(ost->st_stateowner);
	struct nfs4_client *cl = oo->oo_owner.so_client;
	struct nfs4_lockowner *lo;
	unsigned int strhashval;
4728
	struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id);
4729

4730
	lo = find_lockowner_str(&cl->cl_clientid, &lock->v.new.owner, nn);
4731 4732 4733 4734 4735 4736 4737 4738 4739 4740
	if (!lo) {
		strhashval = ownerstr_hashval(cl->cl_clientid.cl_id,
				&lock->v.new.owner);
		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 */
		if (!cstate->minorversion &&
		    lock->lk_new_lock_seqid != lo->lo_owner.so_seqid)
4741 4742
			return nfserr_bad_seqid;
	}
4743 4744

	*lst = find_lock_stateid(lo, fi);
4745
	if (*lst == NULL) {
4746 4747 4748 4749 4750 4751
		*lst = alloc_init_lock_stateid(lo, fi, ost);
		if (*lst == NULL) {
			release_lockowner_if_empty(lo);
			return nfserr_jukebox;
		}
		*new = true;
4752 4753 4754 4755
	}
	return nfs_ok;
}

L
Linus Torvalds 已提交
4756 4757 4758
/*
 *  LOCK operation 
 */
4759
__be32
4760
nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4761
	   struct nfsd4_lock *lock)
L
Linus Torvalds 已提交
4762
{
4763 4764
	struct nfs4_openowner *open_sop = NULL;
	struct nfs4_lockowner *lock_sop = NULL;
4765
	struct nfs4_ol_stateid *lock_stp;
4766
	struct nfs4_file *fp;
4767
	struct file *filp = NULL;
4768 4769
	struct file_lock *file_lock = NULL;
	struct file_lock *conflock = NULL;
4770
	__be32 status = 0;
4771
	bool new_state = false;
4772
	int lkflg;
4773
	int err;
4774 4775
	struct net *net = SVC_NET(rqstp);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
L
Linus Torvalds 已提交
4776 4777 4778 4779 4780 4781 4782 4783

	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;

4784
	if ((status = fh_verify(rqstp, &cstate->current_fh,
M
Miklos Szeredi 已提交
4785
				S_IFREG, NFSD_MAY_LOCK))) {
A
Andy Adamson 已提交
4786 4787 4788 4789
		dprintk("NFSD: nfsd4_lock: permission denied!\n");
		return status;
	}

L
Linus Torvalds 已提交
4790 4791 4792
	nfs4_lock_state();

	if (lock->lk_is_new) {
4793
		struct nfs4_ol_stateid *open_stp = NULL;
4794 4795 4796 4797 4798 4799 4800

		if (nfsd4_has_session(cstate))
			/* See rfc 5661 18.10.3: given clientid is ignored: */
			memcpy(&lock->v.new.clientid,
				&cstate->session->se_client->cl_clientid,
				sizeof(clientid_t));

L
Linus Torvalds 已提交
4801
		status = nfserr_stale_clientid;
4802
		if (STALE_CLIENTID(&lock->lk_new_clientid, nn))
L
Linus Torvalds 已提交
4803 4804 4805
			goto out;

		/* validate and update open stateid and open seqid */
4806
		status = nfs4_preprocess_confirmed_seqid_op(cstate,
L
Linus Torvalds 已提交
4807 4808
				        lock->lk_new_open_seqid,
		                        &lock->lk_new_open_stateid,
4809
					&open_stp, nn);
4810
		if (status)
L
Linus Torvalds 已提交
4811
			goto out;
4812
		open_sop = openowner(open_stp->st_stateowner);
4813
		status = nfserr_bad_stateid;
4814
		if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
4815 4816
						&lock->v.new.clientid))
			goto out;
4817 4818
		status = lookup_or_create_lock_state(cstate, open_stp, lock,
							&lock_stp, &new_state);
J
J. Bruce Fields 已提交
4819
	} else
4820
		status = nfs4_preprocess_seqid_op(cstate,
4821 4822
				       lock->lk_old_lock_seqid,
				       &lock->lk_old_lock_stateid,
4823
				       NFS4_LOCK_STID, &lock_stp, nn);
J
J. Bruce Fields 已提交
4824 4825
	if (status)
		goto out;
4826
	lock_sop = lockowner(lock_stp->st_stateowner);
L
Linus Torvalds 已提交
4827

4828 4829 4830 4831 4832
	lkflg = setlkflg(lock->lk_type);
	status = nfs4_check_openmode(lock_stp, lkflg);
	if (status)
		goto out;

4833
	status = nfserr_grace;
4834
	if (locks_in_grace(net) && !lock->lk_reclaim)
4835 4836
		goto out;
	status = nfserr_no_grace;
4837
	if (!locks_in_grace(net) && lock->lk_reclaim)
4838 4839
		goto out;

4840 4841 4842 4843 4844 4845 4846
	file_lock = locks_alloc_lock();
	if (!file_lock) {
		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
		status = nfserr_jukebox;
		goto out;
	}

4847
	fp = lock_stp->st_file;
4848
	locks_init_lock(file_lock);
L
Linus Torvalds 已提交
4849 4850 4851
	switch (lock->lk_type) {
		case NFS4_READ_LT:
		case NFS4_READW_LT:
4852 4853
			spin_lock(&fp->fi_lock);
			filp = find_readable_file_locked(fp);
J
J. Bruce Fields 已提交
4854 4855
			if (filp)
				get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
4856
			spin_unlock(&fp->fi_lock);
4857
			file_lock->fl_type = F_RDLCK;
4858
			break;
L
Linus Torvalds 已提交
4859 4860
		case NFS4_WRITE_LT:
		case NFS4_WRITEW_LT:
4861 4862
			spin_lock(&fp->fi_lock);
			filp = find_writeable_file_locked(fp);
J
J. Bruce Fields 已提交
4863 4864
			if (filp)
				get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
4865
			spin_unlock(&fp->fi_lock);
4866
			file_lock->fl_type = F_WRLCK;
4867
			break;
L
Linus Torvalds 已提交
4868 4869 4870 4871
		default:
			status = nfserr_inval;
		goto out;
	}
4872 4873 4874 4875
	if (!filp) {
		status = nfserr_openmode;
		goto out;
	}
4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890
	file_lock->fl_owner = (fl_owner_t)lock_sop;
	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 = 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;
	}
L
Linus Torvalds 已提交
4891

4892
	err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
4893
	switch (-err) {
L
Linus Torvalds 已提交
4894
	case 0: /* success! */
4895 4896
		update_stateid(&lock_stp->st_stid.sc_stateid);
		memcpy(&lock->lk_resp_stateid, &lock_stp->st_stid.sc_stateid, 
L
Linus Torvalds 已提交
4897
				sizeof(stateid_t));
4898
		status = 0;
4899 4900 4901 4902
		break;
	case (EAGAIN):		/* conflock holds conflicting lock */
		status = nfserr_denied;
		dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
4903
		nfs4_set_lock_denied(conflock, &lock->lk_denied);
4904
		break;
L
Linus Torvalds 已提交
4905 4906
	case (EDEADLK):
		status = nfserr_deadlock;
4907
		break;
4908
	default:
4909
		dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d\n",err);
4910
		status = nfserrno(err);
4911
		break;
L
Linus Torvalds 已提交
4912 4913
	}
out:
4914 4915
	if (filp)
		fput(filp);
4916
	if (status && new_state)
4917
		release_lock_stateid(lock_stp);
4918
	nfsd4_bump_seqid(cstate, status);
4919 4920
	if (!cstate->replay_owner)
		nfs4_unlock_state();
4921 4922 4923 4924
	if (file_lock)
		locks_free_lock(file_lock);
	if (conflock)
		locks_free_lock(conflock);
L
Linus Torvalds 已提交
4925 4926 4927
	return status;
}

4928 4929 4930 4931 4932 4933
/*
 * 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.)
 */
4934
static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
4935 4936
{
	struct file *file;
4937 4938 4939 4940 4941
	__be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
	if (!err) {
		err = nfserrno(vfs_test_lock(file, lock));
		nfsd_close(file);
	}
4942 4943 4944
	return err;
}

L
Linus Torvalds 已提交
4945 4946 4947
/*
 * LOCKT operation
 */
4948
__be32
4949 4950
nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	    struct nfsd4_lockt *lockt)
L
Linus Torvalds 已提交
4951
{
4952
	struct file_lock *file_lock = NULL;
4953
	struct nfs4_lockowner *lo;
4954
	__be32 status;
4955
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
4956

4957
	if (locks_in_grace(SVC_NET(rqstp)))
L
Linus Torvalds 已提交
4958 4959 4960 4961 4962 4963 4964
		return nfserr_grace;

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

	nfs4_lock_state();

4965
	if (!nfsd4_has_session(cstate)) {
4966
		status = lookup_clientid(&lockt->lt_clientid, cstate, nn);
4967 4968 4969
		if (status)
			goto out;
	}
L
Linus Torvalds 已提交
4970

4971
	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
L
Linus Torvalds 已提交
4972 4973
		goto out;

4974 4975 4976 4977 4978 4979 4980
	file_lock = locks_alloc_lock();
	if (!file_lock) {
		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
		status = nfserr_jukebox;
		goto out;
	}
	locks_init_lock(file_lock);
L
Linus Torvalds 已提交
4981 4982 4983
	switch (lockt->lt_type) {
		case NFS4_READ_LT:
		case NFS4_READW_LT:
4984
			file_lock->fl_type = F_RDLCK;
L
Linus Torvalds 已提交
4985 4986 4987
		break;
		case NFS4_WRITE_LT:
		case NFS4_WRITEW_LT:
4988
			file_lock->fl_type = F_WRLCK;
L
Linus Torvalds 已提交
4989 4990
		break;
		default:
4991
			dprintk("NFSD: nfs4_lockt: bad lock type!\n");
L
Linus Torvalds 已提交
4992 4993 4994 4995
			status = nfserr_inval;
		goto out;
	}

4996
	lo = find_lockowner_str(&lockt->lt_clientid, &lockt->lt_owner, nn);
4997
	if (lo)
4998 4999 5000
		file_lock->fl_owner = (fl_owner_t)lo;
	file_lock->fl_pid = current->tgid;
	file_lock->fl_flags = FL_POSIX;
L
Linus Torvalds 已提交
5001

5002 5003
	file_lock->fl_start = lockt->lt_offset;
	file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
L
Linus Torvalds 已提交
5004

5005
	nfs4_transform_lock_offset(file_lock);
L
Linus Torvalds 已提交
5006

5007
	status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
5008
	if (status)
5009
		goto out;
5010

5011
	if (file_lock->fl_type != F_UNLCK) {
L
Linus Torvalds 已提交
5012
		status = nfserr_denied;
5013
		nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
L
Linus Torvalds 已提交
5014 5015 5016
	}
out:
	nfs4_unlock_state();
5017 5018
	if (file_lock)
		locks_free_lock(file_lock);
L
Linus Torvalds 已提交
5019 5020 5021
	return status;
}

5022
__be32
5023
nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5024
	    struct nfsd4_locku *locku)
L
Linus Torvalds 已提交
5025
{
5026
	struct nfs4_ol_stateid *stp;
L
Linus Torvalds 已提交
5027
	struct file *filp = NULL;
5028
	struct file_lock *file_lock = NULL;
5029
	__be32 status;
5030
	int err;
5031 5032
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);

L
Linus Torvalds 已提交
5033 5034 5035 5036 5037 5038 5039 5040 5041
	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;

	nfs4_lock_state();
									        
5042
	status = nfs4_preprocess_seqid_op(cstate, locku->lu_seqid,
5043 5044
					&locku->lu_stateid, NFS4_LOCK_STID,
					&stp, nn);
5045
	if (status)
L
Linus Torvalds 已提交
5046
		goto out;
5047 5048 5049 5050 5051
	filp = find_any_file(stp->st_file);
	if (!filp) {
		status = nfserr_lock_range;
		goto out;
	}
5052 5053 5054 5055
	file_lock = locks_alloc_lock();
	if (!file_lock) {
		dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
		status = nfserr_jukebox;
5056
		goto fput;
5057 5058 5059
	}
	locks_init_lock(file_lock);
	file_lock->fl_type = F_UNLCK;
5060
	file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
5061 5062 5063 5064 5065 5066 5067 5068 5069
	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);
L
Linus Torvalds 已提交
5070

5071
	err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
5072
	if (err) {
5073
		dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
L
Linus Torvalds 已提交
5074 5075
		goto out_nfserr;
	}
5076 5077
	update_stateid(&stp->st_stid.sc_stateid);
	memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
5078 5079
fput:
	fput(filp);
L
Linus Torvalds 已提交
5080
out:
5081
	nfsd4_bump_seqid(cstate, status);
5082 5083
	if (!cstate->replay_owner)
		nfs4_unlock_state();
5084 5085
	if (file_lock)
		locks_free_lock(file_lock);
L
Linus Torvalds 已提交
5086 5087 5088
	return status;

out_nfserr:
5089
	status = nfserrno(err);
5090
	goto fput;
L
Linus Torvalds 已提交
5091 5092 5093 5094 5095 5096 5097 5098
}

/*
 * returns
 * 	1: locks held by lockowner
 * 	0: no locks held by lockowner
 */
static int
5099
check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner)
L
Linus Torvalds 已提交
5100 5101
{
	struct file_lock **flpp;
5102
	struct inode *inode = filp->fi_inode;
L
Linus Torvalds 已提交
5103 5104
	int status = 0;

5105
	spin_lock(&inode->i_lock);
L
Linus Torvalds 已提交
5106
	for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
5107
		if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
L
Linus Torvalds 已提交
5108 5109
			status = 1;
			goto out;
5110
		}
L
Linus Torvalds 已提交
5111 5112
	}
out:
5113
	spin_unlock(&inode->i_lock);
L
Linus Torvalds 已提交
5114 5115 5116
	return status;
}

5117
__be32
5118 5119 5120
nfsd4_release_lockowner(struct svc_rqst *rqstp,
			struct nfsd4_compound_state *cstate,
			struct nfsd4_release_lockowner *rlockowner)
L
Linus Torvalds 已提交
5121 5122
{
	clientid_t *clid = &rlockowner->rl_clientid;
5123
	struct nfs4_stateowner *sop = NULL, *tmp;
5124
	struct nfs4_lockowner *lo;
5125
	struct nfs4_ol_stateid *stp;
L
Linus Torvalds 已提交
5126
	struct xdr_netobj *owner = &rlockowner->rl_owner;
5127
	unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
5128
	__be32 status;
5129
	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
L
Linus Torvalds 已提交
5130 5131 5132 5133 5134 5135

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

	nfs4_lock_state();

5136
	status = lookup_clientid(clid, cstate, nn);
5137 5138 5139
	if (status)
		goto out;

5140
	status = nfserr_locks_held;
5141

5142 5143 5144
	/* Find the matching lock stateowner */
	list_for_each_entry(tmp, &nn->ownerstr_hashtbl[hashval], so_strhash) {
		if (tmp->so_is_open_owner)
5145
			continue;
5146 5147 5148
		if (same_owner_str(tmp, owner, clid)) {
			sop = tmp;
			break;
L
Linus Torvalds 已提交
5149
		}
5150
	}
5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162

	/* No matching owner found, maybe a replay? Just declare victory... */
	if (!sop) {
		status = nfs_ok;
		goto out;
	}

	lo = lockowner(sop);
	/* see if there are still any locks associated with it */
	list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) {
		if (check_for_locks(stp->st_file, lo))
			goto out;
L
Linus Torvalds 已提交
5163
	}
5164 5165 5166

	status = nfs_ok;
	release_lockowner(lo);
L
Linus Torvalds 已提交
5167 5168 5169 5170 5171 5172
out:
	nfs4_unlock_state();
	return status;
}

static inline struct nfs4_client_reclaim *
N
NeilBrown 已提交
5173
alloc_reclaim(void)
L
Linus Torvalds 已提交
5174
{
N
NeilBrown 已提交
5175
	return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
L
Linus Torvalds 已提交
5176 5177
}

5178
bool
5179
nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
5180
{
5181
	struct nfs4_client_reclaim *crp;
5182

5183
	crp = nfsd4_find_reclaim_client(name, nn);
5184
	return (crp && crp->cr_clp);
5185 5186
}

L
Linus Torvalds 已提交
5187 5188 5189
/*
 * failure => all reset bets are off, nfserr_no_grace...
 */
5190
struct nfs4_client_reclaim *
5191
nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
L
Linus Torvalds 已提交
5192 5193
{
	unsigned int strhashval;
5194
	struct nfs4_client_reclaim *crp;
L
Linus Torvalds 已提交
5195

N
NeilBrown 已提交
5196 5197
	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
	crp = alloc_reclaim();
5198 5199 5200
	if (crp) {
		strhashval = clientstr_hashval(name);
		INIT_LIST_HEAD(&crp->cr_strhash);
5201
		list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
5202
		memcpy(crp->cr_recdir, name, HEXDIR_LEN);
5203
		crp->cr_clp = NULL;
5204
		nn->reclaim_str_hashtbl_size++;
5205 5206
	}
	return crp;
L
Linus Torvalds 已提交
5207 5208
}

5209
void
5210
nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
5211 5212 5213
{
	list_del(&crp->cr_strhash);
	kfree(crp);
5214
	nn->reclaim_str_hashtbl_size--;
5215 5216
}

5217
void
5218
nfs4_release_reclaim(struct nfsd_net *nn)
L
Linus Torvalds 已提交
5219 5220 5221 5222 5223
{
	struct nfs4_client_reclaim *crp = NULL;
	int i;

	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
5224 5225
		while (!list_empty(&nn->reclaim_str_hashtbl[i])) {
			crp = list_entry(nn->reclaim_str_hashtbl[i].next,
L
Linus Torvalds 已提交
5226
			                struct nfs4_client_reclaim, cr_strhash);
5227
			nfs4_remove_reclaim_record(crp, nn);
L
Linus Torvalds 已提交
5228 5229
		}
	}
5230
	WARN_ON_ONCE(nn->reclaim_str_hashtbl_size);
L
Linus Torvalds 已提交
5231 5232 5233 5234
}

/*
 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
5235
struct nfs4_client_reclaim *
5236
nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn)
L
Linus Torvalds 已提交
5237 5238 5239 5240
{
	unsigned int strhashval;
	struct nfs4_client_reclaim *crp = NULL;

5241
	dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir);
L
Linus Torvalds 已提交
5242

5243
	strhashval = clientstr_hashval(recdir);
5244
	list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
5245
		if (same_name(crp->cr_recdir, recdir)) {
L
Linus Torvalds 已提交
5246 5247 5248 5249 5250 5251 5252 5253 5254
			return crp;
		}
	}
	return NULL;
}

/*
* Called from OPEN. Look for clientid in reclaim list.
*/
5255
__be32
5256 5257 5258
nfs4_check_open_reclaim(clientid_t *clid,
		struct nfsd4_compound_state *cstate,
		struct nfsd_net *nn)
L
Linus Torvalds 已提交
5259
{
5260
	__be32 status;
5261 5262

	/* find clientid in conf_id_hashtbl */
5263 5264
	status = lookup_clientid(clid, cstate, nn);
	if (status)
5265 5266
		return nfserr_reclaim_bad;

5267 5268 5269 5270
	if (nfsd4_client_record_check(cstate->clp))
		return nfserr_reclaim_bad;

	return nfs_ok;
L
Linus Torvalds 已提交
5271 5272
}

B
Bryan Schumaker 已提交
5273 5274
#ifdef CONFIG_NFSD_FAULT_INJECTION

5275 5276
u64 nfsd_forget_client(struct nfs4_client *clp, u64 max)
{
5277 5278
	if (mark_client_expired(clp))
		return 0;
5279 5280 5281 5282
	expire_client(clp);
	return 1;
}

5283 5284 5285
u64 nfsd_print_client(struct nfs4_client *clp, u64 num)
{
	char buf[INET6_ADDRSTRLEN];
5286
	rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
5287 5288 5289 5290 5291 5292 5293 5294
	printk(KERN_INFO "NFS Client: %s\n", buf);
	return 1;
}

static void nfsd_print_count(struct nfs4_client *clp, unsigned int count,
			     const char *type)
{
	char buf[INET6_ADDRSTRLEN];
5295
	rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
5296 5297 5298
	printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type);
}

5299 5300
static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max,
				    void (*func)(struct nfs4_ol_stateid *))
B
Bryan Schumaker 已提交
5301 5302 5303
{
	struct nfs4_openowner *oop;
	struct nfs4_ol_stateid *stp, *st_next;
5304
	struct nfs4_ol_stateid *lst, *lst_next;
B
Bryan Schumaker 已提交
5305 5306 5307
	u64 count = 0;

	list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) {
5308 5309 5310 5311
		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) {
B
Bryan Schumaker 已提交
5312
				if (func)
5313
					func(lst);
B
Bryan Schumaker 已提交
5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324
				if (++count == max)
					return count;
			}
		}
	}

	return count;
}

u64 nfsd_forget_client_locks(struct nfs4_client *clp, u64 max)
{
5325
	return nfsd_foreach_client_lock(clp, max, release_lock_stateid);
B
Bryan Schumaker 已提交
5326 5327
}

5328 5329 5330 5331 5332 5333 5334
u64 nfsd_print_client_locks(struct nfs4_client *clp, u64 max)
{
	u64 count = nfsd_foreach_client_lock(clp, max, NULL);
	nfsd_print_count(clp, count, "locked files");
	return count;
}

5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354
static u64 nfsd_foreach_client_open(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_openowner *))
{
	struct nfs4_openowner *oop, *next;
	u64 count = 0;

	list_for_each_entry_safe(oop, next, &clp->cl_openowners, oo_perclient) {
		if (func)
			func(oop);
		if (++count == max)
			break;
	}

	return count;
}

u64 nfsd_forget_client_openowners(struct nfs4_client *clp, u64 max)
{
	return nfsd_foreach_client_open(clp, max, release_openowner);
}

5355 5356 5357 5358 5359 5360 5361
u64 nfsd_print_client_openowners(struct nfs4_client *clp, u64 max)
{
	u64 count = nfsd_foreach_client_open(clp, max, NULL);
	nfsd_print_count(clp, count, "open files");
	return count;
}

5362 5363 5364 5365 5366 5367
static u64 nfsd_find_all_delegations(struct nfs4_client *clp, u64 max,
				     struct list_head *victims)
{
	struct nfs4_delegation *dp, *next;
	u64 count = 0;

5368
	lockdep_assert_held(&state_lock);
5369
	list_for_each_entry_safe(dp, next, &clp->cl_delegations, dl_perclnt) {
5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384
		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;

			/*
			 * Increment dl_time to ensure that delegation breaks
			 * don't monkey with it now that we are.
			 */
			++dp->dl_time;
5385
			list_move(&dp->dl_recall_lru, victims);
5386
		}
5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398
		if (++count == max)
			break;
	}
	return count;
}

u64 nfsd_forget_client_delegations(struct nfs4_client *clp, u64 max)
{
	struct nfs4_delegation *dp, *next;
	LIST_HEAD(victims);
	u64 count;

5399
	spin_lock(&state_lock);
5400
	count = nfsd_find_all_delegations(clp, max, &victims);
5401
	spin_unlock(&state_lock);
5402 5403

	list_for_each_entry_safe(dp, next, &victims, dl_recall_lru)
5404
		revoke_delegation(dp);
5405 5406 5407 5408 5409 5410

	return count;
}

u64 nfsd_recall_client_delegations(struct nfs4_client *clp, u64 max)
{
5411
	struct nfs4_delegation *dp;
5412 5413 5414
	LIST_HEAD(victims);
	u64 count;

5415
	spin_lock(&state_lock);
5416
	count = nfsd_find_all_delegations(clp, max, &victims);
5417 5418 5419 5420 5421
	while (!list_empty(&victims)) {
		dp = list_first_entry(&victims, struct nfs4_delegation,
					dl_recall_lru);
		list_del_init(&dp->dl_recall_lru);
		dp->dl_time = 0;
5422
		nfsd_break_one_deleg(dp);
5423
	}
5424
	spin_unlock(&state_lock);
5425 5426 5427 5428

	return count;
}

5429 5430 5431 5432
u64 nfsd_print_client_delegations(struct nfs4_client *clp, u64 max)
{
	u64 count = 0;

5433
	spin_lock(&state_lock);
5434
	count = nfsd_find_all_delegations(clp, max, NULL);
5435
	spin_unlock(&state_lock);
5436 5437 5438 5439 5440

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

5441
u64 nfsd_for_n_state(u64 max, u64 (*func)(struct nfs4_client *, u64))
B
Bryan Schumaker 已提交
5442 5443
{
	struct nfs4_client *clp, *next;
5444
	u64 count = 0;
5445
	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, nfsd_net_id);
B
Bryan Schumaker 已提交
5446

5447 5448 5449
	if (!nfsd_netns_ready(nn))
		return 0;

5450
	list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
5451 5452
		count += func(clp, max - count);
		if ((max != 0) && (count >= max))
B
Bryan Schumaker 已提交
5453 5454 5455
			break;
	}

5456 5457 5458
	return count;
}

5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473
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;
}

B
Bryan Schumaker 已提交
5474 5475
#endif /* CONFIG_NFSD_FAULT_INJECTION */

5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496
/*
 * 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);
}

5497
static int nfs4_state_create_net(struct net *net)
5498 5499 5500 5501 5502 5503 5504
{
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
	int i;

	nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
			CLIENT_HASH_SIZE, GFP_KERNEL);
	if (!nn->conf_id_hashtbl)
5505
		goto err;
5506 5507 5508 5509
	nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) *
			CLIENT_HASH_SIZE, GFP_KERNEL);
	if (!nn->unconf_id_hashtbl)
		goto err_unconf_id;
5510 5511 5512 5513
	nn->ownerstr_hashtbl = kmalloc(sizeof(struct list_head) *
			OWNER_HASH_SIZE, GFP_KERNEL);
	if (!nn->ownerstr_hashtbl)
		goto err_ownerstr;
5514 5515 5516 5517
	nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
			SESSION_HASH_SIZE, GFP_KERNEL);
	if (!nn->sessionid_hashtbl)
		goto err_sessionid;
5518

5519
	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
5520
		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
5521
		INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
5522
	}
5523 5524
	for (i = 0; i < OWNER_HASH_SIZE; i++)
		INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
5525 5526
	for (i = 0; i < SESSION_HASH_SIZE; i++)
		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
5527
	nn->conf_name_tree = RB_ROOT;
5528
	nn->unconf_name_tree = RB_ROOT;
5529
	INIT_LIST_HEAD(&nn->client_lru);
5530
	INIT_LIST_HEAD(&nn->close_lru);
5531
	INIT_LIST_HEAD(&nn->del_recall_lru);
5532
	spin_lock_init(&nn->client_lock);
5533

5534
	INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
5535
	get_net(net);
5536

5537
	return 0;
5538

5539
err_sessionid:
5540
	kfree(nn->ownerstr_hashtbl);
5541 5542
err_ownerstr:
	kfree(nn->unconf_id_hashtbl);
5543 5544
err_unconf_id:
	kfree(nn->conf_id_hashtbl);
5545 5546
err:
	return -ENOMEM;
5547 5548 5549
}

static void
5550
nfs4_state_destroy_net(struct net *net)
5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561
{
	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);
		}
	}
5562

5563 5564 5565 5566 5567
	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);
		}
5568 5569
	}

5570
	kfree(nn->sessionid_hashtbl);
5571
	kfree(nn->ownerstr_hashtbl);
5572
	kfree(nn->unconf_id_hashtbl);
5573
	kfree(nn->conf_id_hashtbl);
5574
	put_net(net);
5575 5576
}

5577
int
5578
nfs4_state_start_net(struct net *net)
5579
{
5580
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
5581 5582
	int ret;

5583
	ret = nfs4_state_create_net(net);
5584 5585
	if (ret)
		return ret;
5586
	nfsd4_client_tracking_init(net);
5587
	nn->boot_time = get_seconds();
5588
	locks_start_grace(net, &nn->nfsd4_manager);
5589
	nn->grace_ended = false;
5590
	printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
5591 5592
	       nn->nfsd4_grace, net);
	queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);
5593 5594 5595 5596 5597 5598 5599 5600 5601 5602
	return 0;
}

/* initialization to perform when the nfsd service is started: */

int
nfs4_state_start(void)
{
	int ret;

5603
	ret = set_callback_cred();
5604 5605
	if (ret)
		return -ENOMEM;
5606
	laundry_wq = create_singlethread_workqueue("nfsd4");
5607 5608 5609 5610
	if (laundry_wq == NULL) {
		ret = -ENOMEM;
		goto out_recovery;
	}
5611 5612 5613
	ret = nfsd4_create_callback_queue();
	if (ret)
		goto out_free_laundry;
5614

5615
	set_max_delegations();
5616

5617
	return 0;
5618

5619 5620
out_free_laundry:
	destroy_workqueue(laundry_wq);
5621
out_recovery:
5622
	return ret;
L
Linus Torvalds 已提交
5623 5624
}

5625
void
5626
nfs4_state_shutdown_net(struct net *net)
L
Linus Torvalds 已提交
5627 5628 5629
{
	struct nfs4_delegation *dp = NULL;
	struct list_head *pos, *next, reaplist;
5630
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
L
Linus Torvalds 已提交
5631

5632 5633
	cancel_delayed_work_sync(&nn->laundromat_work);
	locks_end_grace(&nn->nfsd4_manager);
5634

5635
	nfs4_lock_state();
L
Linus Torvalds 已提交
5636
	INIT_LIST_HEAD(&reaplist);
5637
	spin_lock(&state_lock);
5638
	list_for_each_safe(pos, next, &nn->del_recall_lru) {
L
Linus Torvalds 已提交
5639 5640 5641
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
		list_move(&dp->dl_recall_lru, &reaplist);
	}
5642
	spin_unlock(&state_lock);
L
Linus Torvalds 已提交
5643 5644
	list_for_each_safe(pos, next, &reaplist) {
		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
5645
		destroy_delegation(dp);
L
Linus Torvalds 已提交
5646 5647
	}

5648
	nfsd4_client_tracking_exit(net);
5649
	nfs4_state_destroy_net(net);
5650
	nfs4_unlock_state();
L
Linus Torvalds 已提交
5651 5652 5653 5654 5655
}

void
nfs4_state_shutdown(void)
{
5656
	destroy_workqueue(laundry_wq);
5657
	nfsd4_destroy_callback_queue();
L
Linus Torvalds 已提交
5658
}
5659 5660 5661 5662

static void
get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
{
5663 5664
	if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG) && CURRENT_STATEID(stateid))
		memcpy(stateid, &cstate->current_stateid, sizeof(stateid_t));
5665 5666 5667 5668 5669
}

static void
put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
{
5670 5671 5672 5673 5674 5675 5676 5677 5678 5679
	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);
5680 5681
}

5682 5683 5684
/*
 * functions to set current state id
 */
5685 5686 5687 5688 5689 5690
void
nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp)
{
	put_stateid(cstate, &odp->od_stateid);
}

5691 5692 5693 5694 5695 5696
void
nfsd4_set_openstateid(struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
{
	put_stateid(cstate, &open->op_stateid);
}

5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711
void
nfsd4_set_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
{
	put_stateid(cstate, &close->cl_stateid);
}

void
nfsd4_set_lockstateid(struct nfsd4_compound_state *cstate, struct nfsd4_lock *lock)
{
	put_stateid(cstate, &lock->lk_resp_stateid);
}

/*
 * functions to consume current state id
 */
5712

5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724
void
nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp)
{
	get_stateid(cstate, &odp->od_stateid);
}

void
nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *cstate, struct nfsd4_delegreturn *drp)
{
	get_stateid(cstate, &drp->dr_stateid);
}

5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736
void
nfsd4_get_freestateid(struct nfsd4_compound_state *cstate, struct nfsd4_free_stateid *fsp)
{
	get_stateid(cstate, &fsp->fr_stateid);
}

void
nfsd4_get_setattrstateid(struct nfsd4_compound_state *cstate, struct nfsd4_setattr *setattr)
{
	get_stateid(cstate, &setattr->sa_stateid);
}

5737 5738 5739 5740 5741 5742 5743
void
nfsd4_get_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
{
	get_stateid(cstate, &close->cl_stateid);
}

void
5744
nfsd4_get_lockustateid(struct nfsd4_compound_state *cstate, struct nfsd4_locku *locku)
5745
{
5746
	get_stateid(cstate, &locku->lu_stateid);
5747
}
5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759

void
nfsd4_get_readstateid(struct nfsd4_compound_state *cstate, struct nfsd4_read *read)
{
	get_stateid(cstate, &read->rd_stateid);
}

void
nfsd4_get_writestateid(struct nfsd4_compound_state *cstate, struct nfsd4_write *write)
{
	get_stateid(cstate, &write->wr_stateid);
}