nfs4proc.c 259.3 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 35 36 37 38 39 40 41
/*
 *  fs/nfs/nfs4proc.c
 *
 *  Client-side procedure declarations for NFSv4.
 *
 *  Copyright (c) 2002 The Regents of the University of Michigan.
 *  All rights reserved.
 *
 *  Kendrick Smith <kmsmith@umich.edu>
 *  Andy Adamson   <andros@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.
 */

#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/string.h>
42 43
#include <linux/ratelimit.h>
#include <linux/printk.h>
44
#include <linux/slab.h>
L
Linus Torvalds 已提交
45 46 47 48 49
#include <linux/sunrpc/clnt.h>
#include <linux/nfs.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
50
#include <linux/nfs_mount.h>
L
Linus Torvalds 已提交
51
#include <linux/namei.h>
52
#include <linux/mount.h>
B
Benny Halevy 已提交
53
#include <linux/module.h>
54
#include <linux/xattr.h>
55
#include <linux/utsname.h>
56
#include <linux/freezer.h>
J
Jeff Layton 已提交
57
#include <linux/iversion.h>
L
Linus Torvalds 已提交
58

59
#include "nfs4_fs.h"
L
Linus Torvalds 已提交
60
#include "delegation.h"
61
#include "internal.h"
62
#include "iostat.h"
A
Andy Adamson 已提交
63
#include "callback.h"
64
#include "pnfs.h"
65
#include "netns.h"
66
#include "nfs4idmap.h"
67
#include "nfs4session.h"
D
David Howells 已提交
68
#include "fscache.h"
L
Linus Torvalds 已提交
69

70 71
#include "nfs4trace.h"

L
Linus Torvalds 已提交
72 73
#define NFSDBG_FACILITY		NFSDBG_PROC

74
#define NFS4_POLL_RETRY_MIN	(HZ/10)
L
Linus Torvalds 已提交
75 76
#define NFS4_POLL_RETRY_MAX	(15*HZ)

77 78 79 80 81 82 83 84 85 86 87
/* file attributes which can be mapped to nfs attributes */
#define NFS4_VALID_ATTRS (ATTR_MODE \
	| ATTR_UID \
	| ATTR_GID \
	| ATTR_SIZE \
	| ATTR_ATIME \
	| ATTR_MTIME \
	| ATTR_CTIME \
	| ATTR_ATIME_SET \
	| ATTR_MTIME_SET)

88
struct nfs4_opendata;
89
static int _nfs4_proc_open(struct nfs4_opendata *data);
90
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
L
Linus Torvalds 已提交
91
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
92
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
93 94
static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label);
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
95 96
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			    struct nfs_fattr *fattr, struct iattr *sattr,
97
			    struct nfs_open_context *ctx, struct nfs4_label *ilabel,
98
			    struct nfs4_label *olabel);
99
#ifdef CONFIG_NFS_V4_1
100 101 102 103
static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
		struct rpc_cred *cred,
		struct nfs4_slot *slot,
		bool is_privileged);
104 105
static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
		struct rpc_cred *);
106 107
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
		struct rpc_cred *, bool);
108
#endif
109 110 111 112 113 114 115 116 117 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

#ifdef CONFIG_NFS_V4_SECURITY_LABEL
static inline struct nfs4_label *
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
	struct iattr *sattr, struct nfs4_label *label)
{
	int err;

	if (label == NULL)
		return NULL;

	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0)
		return NULL;

	err = security_dentry_init_security(dentry, sattr->ia_mode,
				&dentry->d_name, (void **)&label->label, &label->len);
	if (err == 0)
		return label;

	return NULL;
}
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
	if (label)
		security_release_secctx(label->label, label->len);
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
	if (label)
		return server->attr_bitmask;

	return server->attr_bitmask_nl;
}
#else
static inline struct nfs4_label *
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
	struct iattr *sattr, struct nfs4_label *l)
{ return NULL; }
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{ return; }
static inline u32 *
nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{ return server->attr_bitmask; }
#endif

L
Linus Torvalds 已提交
156
/* Prevent leaks of NFSv4 errors into userland */
157
static int nfs4_map_errors(int err)
L
Linus Torvalds 已提交
158
{
159 160 161 162
	if (err >= -1000)
		return err;
	switch (err) {
	case -NFS4ERR_RESOURCE:
163 164
	case -NFS4ERR_LAYOUTTRYLATER:
	case -NFS4ERR_RECALLCONFLICT:
165
		return -EREMOTEIO;
166
	case -NFS4ERR_WRONGSEC:
167
	case -NFS4ERR_WRONG_CRED:
168
		return -EPERM;
169 170 171
	case -NFS4ERR_BADOWNER:
	case -NFS4ERR_BADNAME:
		return -EINVAL;
172 173
	case -NFS4ERR_SHARE_DENIED:
		return -EACCES;
174 175
	case -NFS4ERR_MINOR_VERS_MISMATCH:
		return -EPROTONOSUPPORT;
176 177
	case -NFS4ERR_FILE_OPEN:
		return -EBUSY;
178
	default:
L
Linus Torvalds 已提交
179
		dprintk("%s could not handle NFSv4 error %d\n",
180
				__func__, -err);
181
		break;
L
Linus Torvalds 已提交
182
	}
183
	return -EIO;
L
Linus Torvalds 已提交
184 185 186 187 188
}

/*
 * This is our standard bitmap for GETATTR requests.
 */
189
const u32 nfs4_fattr_bitmap[3] = {
L
Linus Torvalds 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202
	FATTR4_WORD0_TYPE
	| FATTR4_WORD0_CHANGE
	| FATTR4_WORD0_SIZE
	| FATTR4_WORD0_FSID
	| FATTR4_WORD0_FILEID,
	FATTR4_WORD1_MODE
	| FATTR4_WORD1_NUMLINKS
	| FATTR4_WORD1_OWNER
	| FATTR4_WORD1_OWNER_GROUP
	| FATTR4_WORD1_RAWDEV
	| FATTR4_WORD1_SPACE_USED
	| FATTR4_WORD1_TIME_ACCESS
	| FATTR4_WORD1_TIME_METADATA
203 204
	| FATTR4_WORD1_TIME_MODIFY
	| FATTR4_WORD1_MOUNTED_ON_FILEID,
205 206 207
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	FATTR4_WORD2_SECURITY_LABEL
#endif
L
Linus Torvalds 已提交
208 209
};

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
static const u32 nfs4_pnfs_open_bitmap[3] = {
	FATTR4_WORD0_TYPE
	| FATTR4_WORD0_CHANGE
	| FATTR4_WORD0_SIZE
	| FATTR4_WORD0_FSID
	| FATTR4_WORD0_FILEID,
	FATTR4_WORD1_MODE
	| FATTR4_WORD1_NUMLINKS
	| FATTR4_WORD1_OWNER
	| FATTR4_WORD1_OWNER_GROUP
	| FATTR4_WORD1_RAWDEV
	| FATTR4_WORD1_SPACE_USED
	| FATTR4_WORD1_TIME_ACCESS
	| FATTR4_WORD1_TIME_METADATA
	| FATTR4_WORD1_TIME_MODIFY,
	FATTR4_WORD2_MDSTHRESHOLD
226 227 228
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	| FATTR4_WORD2_SECURITY_LABEL
#endif
229 230
};

231 232 233 234 235
static const u32 nfs4_open_noattr_bitmap[3] = {
	FATTR4_WORD0_TYPE
	| FATTR4_WORD0_FILEID,
};

236
const u32 nfs4_statfs_bitmap[3] = {
L
Linus Torvalds 已提交
237 238 239 240 241 242 243 244
	FATTR4_WORD0_FILES_AVAIL
	| FATTR4_WORD0_FILES_FREE
	| FATTR4_WORD0_FILES_TOTAL,
	FATTR4_WORD1_SPACE_AVAIL
	| FATTR4_WORD1_SPACE_FREE
	| FATTR4_WORD1_SPACE_TOTAL
};

245
const u32 nfs4_pathconf_bitmap[3] = {
L
Linus Torvalds 已提交
246 247 248 249 250
	FATTR4_WORD0_MAXLINK
	| FATTR4_WORD0_MAXNAME,
	0
};

251
const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE
L
Linus Torvalds 已提交
252 253 254
			| FATTR4_WORD0_MAXREAD
			| FATTR4_WORD0_MAXWRITE
			| FATTR4_WORD0_LEASE_TIME,
255
			FATTR4_WORD1_TIME_DELTA
256 257
			| FATTR4_WORD1_FS_LAYOUT_TYPES,
			FATTR4_WORD2_LAYOUT_BLKSIZE
258
			| FATTR4_WORD2_CLONE_BLKSIZE
L
Linus Torvalds 已提交
259 260
};

261
const u32 nfs4_fs_locations_bitmap[3] = {
C
Chuck Lever 已提交
262
	FATTR4_WORD0_CHANGE
263 264 265 266
	| FATTR4_WORD0_SIZE
	| FATTR4_WORD0_FSID
	| FATTR4_WORD0_FILEID
	| FATTR4_WORD0_FS_LOCATIONS,
C
Chuck Lever 已提交
267
	FATTR4_WORD1_OWNER
268 269 270 271 272 273
	| FATTR4_WORD1_OWNER_GROUP
	| FATTR4_WORD1_RAWDEV
	| FATTR4_WORD1_SPACE_USED
	| FATTR4_WORD1_TIME_ACCESS
	| FATTR4_WORD1_TIME_METADATA
	| FATTR4_WORD1_TIME_MODIFY
274
	| FATTR4_WORD1_MOUNTED_ON_FILEID,
275 276
};

A
Al Viro 已提交
277
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
L
Linus Torvalds 已提交
278 279
		struct nfs4_readdir_arg *readdir)
{
280
	unsigned int attrs = FATTR4_WORD0_FILEID | FATTR4_WORD0_TYPE;
281
	__be32 *start, *p;
L
Linus Torvalds 已提交
282 283

	if (cookie > 2) {
284
		readdir->cookie = cookie;
L
Linus Torvalds 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
		memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
		return;
	}

	readdir->cookie = 0;
	memset(&readdir->verifier, 0, sizeof(readdir->verifier));
	if (cookie == 2)
		return;
	
	/*
	 * NFSv4 servers do not return entries for '.' and '..'
	 * Therefore, we fake these entries here.  We let '.'
	 * have cookie 0 and '..' have cookie 1.  Note that
	 * when talking to the server, we always send cookie 0
	 * instead of 1 or 2.
	 */
301
	start = p = kmap_atomic(*readdir->pages);
L
Linus Torvalds 已提交
302 303 304 305 306 307 308 309 310
	
	if (cookie == 0) {
		*p++ = xdr_one;                                  /* next */
		*p++ = xdr_zero;                   /* cookie, first word */
		*p++ = xdr_one;                   /* cookie, second word */
		*p++ = xdr_one;                             /* entry len */
		memcpy(p, ".\0\0\0", 4);                        /* entry */
		p++;
		*p++ = xdr_one;                         /* bitmap length */
311 312 313
		*p++ = htonl(attrs);                           /* bitmap */
		*p++ = htonl(12);             /* attribute buffer length */
		*p++ = htonl(NF4DIR);
314
		p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
L
Linus Torvalds 已提交
315 316 317 318 319 320 321 322 323
	}
	
	*p++ = xdr_one;                                  /* next */
	*p++ = xdr_zero;                   /* cookie, first word */
	*p++ = xdr_two;                   /* cookie, second word */
	*p++ = xdr_two;                             /* entry len */
	memcpy(p, "..\0\0", 4);                         /* entry */
	p++;
	*p++ = xdr_one;                         /* bitmap length */
324 325 326
	*p++ = htonl(attrs);                           /* bitmap */
	*p++ = htonl(12);             /* attribute buffer length */
	*p++ = htonl(NF4DIR);
327
	p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));
L
Linus Torvalds 已提交
328 329 330

	readdir->pgbase = (char *)p - (char *)start;
	readdir->count -= readdir->pgbase;
331
	kunmap_atomic(start);
L
Linus Torvalds 已提交
332 333
}

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
static void nfs4_test_and_free_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;

	ops->test_and_free_expired(server, stateid, cred);
}

static void __nfs4_free_revoked_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	stateid->type = NFS4_REVOKED_STATEID_TYPE;
	nfs4_test_and_free_stateid(server, stateid, cred);
}

static void nfs4_free_revoked_stateid(struct nfs_server *server,
		const nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	nfs4_stateid tmp;

	nfs4_stateid_copy(&tmp, stateid);
	__nfs4_free_revoked_stateid(server, &tmp, cred);
}

361 362 363 364 365 366 367 368 369 370 371 372 373 374
static long nfs4_update_delay(long *timeout)
{
	long ret;
	if (!timeout)
		return NFS4_POLL_RETRY_MAX;
	if (*timeout <= 0)
		*timeout = NFS4_POLL_RETRY_MIN;
	if (*timeout > NFS4_POLL_RETRY_MAX)
		*timeout = NFS4_POLL_RETRY_MAX;
	ret = *timeout;
	*timeout <<= 1;
	return ret;
}

375 376 377 378 379 380
static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
{
	int res = 0;

	might_sleep();

381 382
	freezable_schedule_timeout_killable_unsafe(
		nfs4_update_delay(timeout));
383 384 385 386 387 388 389 390
	if (fatal_signal_pending(current))
		res = -ERESTARTSYS;
	return res;
}

/* This is the error handling routine for processes that are allowed
 * to sleep.
 */
391 392
static int nfs4_do_handle_exception(struct nfs_server *server,
		int errorcode, struct nfs4_exception *exception)
393 394
{
	struct nfs_client *clp = server->nfs_client;
395
	struct nfs4_state *state = exception->state;
396
	const nfs4_stateid *stateid = exception->stateid;
397
	struct inode *inode = exception->inode;
398 399
	int ret = errorcode;

400 401
	exception->delay = 0;
	exception->recovering = 0;
402
	exception->retry = 0;
403 404 405 406

	if (stateid == NULL && state != NULL)
		stateid = &state->stateid;

407 408 409
	switch(errorcode) {
		case 0:
			return 0;
410 411
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_ADMIN_REVOKED:
412
		case -NFS4ERR_EXPIRED:
413
		case -NFS4ERR_BAD_STATEID:
414 415 416 417 418 419
			if (inode != NULL && stateid != NULL) {
				nfs_inode_find_state_and_recover(inode,
						stateid);
				goto wait_on_recovery;
			}
		case -NFS4ERR_OPENMODE:
420 421 422 423 424 425 426 427 428 429 430 431
			if (inode) {
				int err;

				err = nfs_async_inode_return_delegation(inode,
						stateid);
				if (err == 0)
					goto wait_on_recovery;
				if (stateid != NULL && stateid->type == NFS4_DELEGATION_STATEID_TYPE) {
					exception->retry = 1;
					break;
				}
			}
432 433
			if (state == NULL)
				break;
434 435 436
			ret = nfs4_schedule_stateid_recovery(server, state);
			if (ret < 0)
				break;
437
			goto wait_on_recovery;
438
		case -NFS4ERR_STALE_STATEID:
439
		case -NFS4ERR_STALE_CLIENTID:
440 441
			nfs4_schedule_lease_recovery(clp);
			goto wait_on_recovery;
442 443 444 445 446
		case -NFS4ERR_MOVED:
			ret = nfs4_schedule_migration_recovery(server);
			if (ret < 0)
				break;
			goto wait_on_recovery;
447 448 449
		case -NFS4ERR_LEASE_MOVED:
			nfs4_schedule_lease_moved_recovery(clp);
			goto wait_on_recovery;
450
#if defined(CONFIG_NFS_V4_1)
451 452 453 454 455 456 457 458 459
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
		case -NFS4ERR_BAD_HIGH_SLOT:
		case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
		case -NFS4ERR_DEADSESSION:
		case -NFS4ERR_SEQ_FALSE_RETRY:
		case -NFS4ERR_SEQ_MISORDERED:
			dprintk("%s ERROR: %d Reset session\n", __func__,
				errorcode);
460
			nfs4_schedule_session_recovery(clp->cl_session, errorcode);
461
			goto wait_on_recovery;
462
#endif /* defined(CONFIG_NFS_V4_1) */
463
		case -NFS4ERR_FILE_OPEN:
464 465 466 467 468 469 470
			if (exception->timeout > HZ) {
				/* We have retried a decent amount, time to
				 * fail
				 */
				ret = -EBUSY;
				break;
			}
471
		case -NFS4ERR_DELAY:
472 473
			nfs_inc_server_stats(server, NFSIOS_DELAY);
		case -NFS4ERR_GRACE:
474
		case -NFS4ERR_LAYOUTTRYLATER:
475
		case -NFS4ERR_RECALLCONFLICT:
476 477 478
			exception->delay = 1;
			return 0;

479
		case -NFS4ERR_RETRY_UNCACHED_REP:
480 481
		case -NFS4ERR_OLD_STATEID:
			exception->retry = 1;
482 483 484 485 486 487 488 489 490 491 492 493 494
			break;
		case -NFS4ERR_BADOWNER:
			/* The following works around a Linux server bug! */
		case -NFS4ERR_BADNAME:
			if (server->caps & NFS_CAP_UIDGID_NOMAP) {
				server->caps &= ~NFS_CAP_UIDGID_NOMAP;
				exception->retry = 1;
				printk(KERN_WARNING "NFS: v4 server %s "
						"does not accept raw "
						"uid/gids. "
						"Reenabling the idmapper.\n",
						server->nfs_client->cl_hostname);
			}
495 496 497
	}
	/* We failed to handle the error */
	return nfs4_map_errors(ret);
498
wait_on_recovery:
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
	exception->recovering = 1;
	return 0;
}

/* This is the error handling routine for processes that are allowed
 * to sleep.
 */
int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
{
	struct nfs_client *clp = server->nfs_client;
	int ret;

	ret = nfs4_do_handle_exception(server, errorcode, exception);
	if (exception->delay) {
		ret = nfs4_delay(server->client, &exception->timeout);
		goto out_retry;
	}
	if (exception->recovering) {
		ret = nfs4_wait_clnt_recover(clp);
		if (test_bit(NFS_MIG_FAILED, &server->mig_status))
			return -EIO;
		goto out_retry;
	}
	return ret;
out_retry:
524 525 526
	if (ret == 0)
		exception->retry = 1;
	return ret;
527 528
}

529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
static int
nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
		int errorcode, struct nfs4_exception *exception)
{
	struct nfs_client *clp = server->nfs_client;
	int ret;

	ret = nfs4_do_handle_exception(server, errorcode, exception);
	if (exception->delay) {
		rpc_delay(task, nfs4_update_delay(&exception->timeout));
		goto out_retry;
	}
	if (exception->recovering) {
		rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
		if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
			rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
		goto out_retry;
	}
547
	if (test_bit(NFS_MIG_FAILED, &server->mig_status))
548 549 550
		ret = -EIO;
	return ret;
out_retry:
551 552 553
	if (ret == 0)
		exception->retry = 1;
	return ret;
554 555
}

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
static int
nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server,
			struct nfs4_state *state, long *timeout)
{
	struct nfs4_exception exception = {
		.state = state,
	};

	if (task->tk_status >= 0)
		return 0;
	if (timeout)
		exception.timeout = *timeout;
	task->tk_status = nfs4_async_handle_exception(task, server,
			task->tk_status,
			&exception);
	if (exception.delay && timeout)
		*timeout = exception.timeout;
	if (exception.retry)
		return -EAGAIN;
	return 0;
}

578 579 580 581 582 583 584
/*
 * Return 'true' if 'clp' is using an rpc_client that is integrity protected
 * or 'false' otherwise.
 */
static bool _nfs4_is_integrity_protected(struct nfs_client *clp)
{
	rpc_authflavor_t flavor = clp->cl_rpcclient->cl_auth->au_flavor;
585
	return (flavor == RPC_AUTH_GSS_KRB5I) || (flavor == RPC_AUTH_GSS_KRB5P);
586
}
587

588
static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp)
L
Linus Torvalds 已提交
589 590 591 592 593 594 595
{
	spin_lock(&clp->cl_lock);
	if (time_before(clp->cl_last_renewal,timestamp))
		clp->cl_last_renewal = timestamp;
	spin_unlock(&clp->cl_lock);
}

596 597
static void renew_lease(const struct nfs_server *server, unsigned long timestamp)
{
598 599 600 601
	struct nfs_client *clp = server->nfs_client;

	if (!nfs4_has_session(clp))
		do_renew_lease(clp, timestamp);
602 603
}

604 605 606 607 608 609
struct nfs4_call_sync_data {
	const struct nfs_server *seq_server;
	struct nfs4_sequence_args *seq_args;
	struct nfs4_sequence_res *seq_res;
};

610 611
void nfs4_init_sequence(struct nfs4_sequence_args *args,
			struct nfs4_sequence_res *res, int cache_reply)
612 613 614 615 616 617 618 619 620 621 622 623 624
{
	args->sa_slot = NULL;
	args->sa_cache_this = cache_reply;
	args->sa_privileged = 0;

	res->sr_slot = NULL;
}

static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
{
	args->sa_privileged = 1;
}

625
static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
C
Chuck Lever 已提交
626 627 628 629 630 631 632 633 634 635 636
{
	struct nfs4_slot *slot = res->sr_slot;
	struct nfs4_slot_table *tbl;

	tbl = slot->table;
	spin_lock(&tbl->slot_tbl_lock);
	if (!nfs41_wake_and_assign_slot(tbl, slot))
		nfs4_free_slot(tbl, slot);
	spin_unlock(&tbl->slot_tbl_lock);

	res->sr_slot = NULL;
637 638 639 640 641 642 643
}

static int nfs40_sequence_done(struct rpc_task *task,
			       struct nfs4_sequence_res *res)
{
	if (res->sr_slot != NULL)
		nfs40_sequence_free_slot(res);
C
Chuck Lever 已提交
644 645 646
	return 1;
}

A
Andy Adamson 已提交
647 648
#if defined(CONFIG_NFS_V4_1)

649
static void nfs41_release_slot(struct nfs4_slot *slot)
A
Andy Adamson 已提交
650
{
651
	struct nfs4_session *session;
A
Andy Adamson 已提交
652
	struct nfs4_slot_table *tbl;
653
	bool send_new_highest_used_slotid = false;
A
Andy Adamson 已提交
654

655 656
	if (!slot)
		return;
657
	tbl = slot->table;
658
	session = tbl->session;
659

660 661 662 663 664
	/* Bump the slot sequence number */
	if (slot->seq_done)
		slot->seq_nr++;
	slot->seq_done = 0;

665
	spin_lock(&tbl->slot_tbl_lock);
666 667 668 669 670 671
	/* Be nice to the server: try to ensure that the last transmitted
	 * value for highest_user_slotid <= target_highest_slotid
	 */
	if (tbl->highest_used_slotid > tbl->target_highest_slotid)
		send_new_highest_used_slotid = true;

672
	if (nfs41_wake_and_assign_slot(tbl, slot)) {
673 674 675
		send_new_highest_used_slotid = false;
		goto out_unlock;
	}
676
	nfs4_free_slot(tbl, slot);
677 678 679

	if (tbl->highest_used_slotid != NFS4_NO_SLOT)
		send_new_highest_used_slotid = false;
680
out_unlock:
681
	spin_unlock(&tbl->slot_tbl_lock);
682
	if (send_new_highest_used_slotid)
683
		nfs41_notify_server(session->clp);
684 685
	if (waitqueue_active(&tbl->slot_waitq))
		wake_up_all(&tbl->slot_waitq);
A
Andy Adamson 已提交
686 687
}

688 689 690 691 692 693
static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
{
	nfs41_release_slot(res->sr_slot);
	res->sr_slot = NULL;
}

694 695
static int nfs41_sequence_process(struct rpc_task *task,
		struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
696
{
697
	struct nfs4_session *session;
698
	struct nfs4_slot *slot = res->sr_slot;
699
	struct nfs_client *clp;
700
	bool interrupted = false;
701
	int ret = 1;
A
Andy Adamson 已提交
702

703 704
	if (slot == NULL)
		goto out_noaction;
705 706
	/* don't increment the sequence number if the task wasn't sent */
	if (!RPC_WAS_SENT(task))
A
Andy Adamson 已提交
707 708
		goto out;

709
	session = slot->table->session;
710

711
	if (slot->interrupted) {
712 713
		if (res->sr_status != -NFS4ERR_DELAY)
			slot->interrupted = 0;
714 715 716
		interrupted = true;
	}

717
	trace_nfs4_sequence_done(session, res);
A
Andy Adamson 已提交
718
	/* Check the SEQUENCE operation status */
719 720
	switch (res->sr_status) {
	case 0:
A
Andy Adamson 已提交
721
		/* Update the slot's sequence and clientid lease timer */
722
		slot->seq_done = 1;
723
		clp = session->clp;
724
		do_renew_lease(clp, res->sr_timestamp);
725
		/* Check sequence flags */
726 727
		nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
				!!slot->privileged);
728
		nfs41_update_target_slotid(slot->table, slot, res);
729
		break;
730 731 732 733 734 735 736 737 738
	case 1:
		/*
		 * sr_status remains 1 if an RPC level error occurred.
		 * The server may or may not have processed the sequence
		 * operation..
		 * Mark the slot as having hosted an interrupted RPC call.
		 */
		slot->interrupted = 1;
		goto out;
739 740 741 742 743
	case -NFS4ERR_DELAY:
		/* The server detected a resend of the RPC call and
		 * returned NFS4ERR_DELAY as per Section 2.10.6.2
		 * of RFC5661.
		 */
744
		dprintk("%s: slot=%u seq=%u: Operation in progress\n",
745
			__func__,
746
			slot->slot_nr,
747
			slot->seq_nr);
748
		goto out_retry;
749 750 751 752 753
	case -NFS4ERR_BADSLOT:
		/*
		 * The slot id we used was probably retired. Try again
		 * using a different slot id.
		 */
754 755
		if (slot->seq_nr < slot->table->target_highest_slotid)
			goto session_recover;
756 757
		goto retry_nowait;
	case -NFS4ERR_SEQ_MISORDERED:
758 759 760 761
		/*
		 * Was the last operation on this sequence interrupted?
		 * If so, retry after bumping the sequence number.
		 */
762 763
		if (interrupted)
			goto retry_new_seq;
764 765 766 767
		/*
		 * Could this slot have been previously retired?
		 * If so, then the server may be expecting seq_nr = 1!
		 */
768 769 770 771
		if (slot->seq_nr != 1) {
			slot->seq_nr = 1;
			goto retry_nowait;
		}
772
		goto session_recover;
773
	case -NFS4ERR_SEQ_FALSE_RETRY:
774 775 776
		if (interrupted)
			goto retry_new_seq;
		goto session_recover;
777 778
	default:
		/* Just update the slot sequence no. */
779
		slot->seq_done = 1;
A
Andy Adamson 已提交
780 781 782 783
	}
out:
	/* The session may be reset by one of the error handlers. */
	dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
784
out_noaction:
785
	return ret;
786 787 788 789 790
session_recover:
	nfs4_schedule_session_recovery(session, res->sr_status);
	goto retry_nowait;
retry_new_seq:
	++slot->seq_nr;
791 792
retry_nowait:
	if (rpc_restart_call_prepare(task)) {
793
		nfs41_sequence_free_slot(res);
794 795 796 797
		task->tk_status = 0;
		ret = 0;
	}
	goto out;
798
out_retry:
799
	if (!rpc_restart_call(task))
800 801 802
		goto out;
	rpc_delay(task, NFS4_POLL_RETRY_MAX);
	return 0;
A
Andy Adamson 已提交
803
}
804 805 806 807 808 809 810 811 812 813

int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
{
	if (!nfs41_sequence_process(task, res))
		return 0;
	if (res->sr_slot != NULL)
		nfs41_sequence_free_slot(res);
	return 1;

}
814
EXPORT_SYMBOL_GPL(nfs41_sequence_done);
A
Andy Adamson 已提交
815

816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res)
{
	if (res->sr_slot == NULL)
		return 1;
	if (res->sr_slot->table->session != NULL)
		return nfs41_sequence_process(task, res);
	return nfs40_sequence_done(task, res);
}

static void nfs4_sequence_free_slot(struct nfs4_sequence_res *res)
{
	if (res->sr_slot != NULL) {
		if (res->sr_slot->table->session != NULL)
			nfs41_sequence_free_slot(res);
		else
			nfs40_sequence_free_slot(res);
	}
}

P
Peng Tao 已提交
835
int nfs4_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
836
{
837
	if (res->sr_slot == NULL)
838
		return 1;
C
Chuck Lever 已提交
839 840
	if (!res->sr_slot->table->session)
		return nfs40_sequence_done(task, res);
841
	return nfs41_sequence_done(task, res);
842
}
P
Peng Tao 已提交
843
EXPORT_SYMBOL_GPL(nfs4_sequence_done);
844

A
Andy Adamson 已提交
845 846
static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
{
847
	struct nfs4_call_sync_data *data = calldata;
A
Andy Adamson 已提交
848

849 850
	dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server);

851 852
	nfs4_setup_sequence(data->seq_server->nfs_client,
			    data->seq_args, data->seq_res, task);
A
Andy Adamson 已提交
853 854
}

A
Andy Adamson 已提交
855 856
static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
{
857
	struct nfs4_call_sync_data *data = calldata;
A
Andy Adamson 已提交
858

859
	nfs41_sequence_done(task, data->seq_res);
A
Andy Adamson 已提交
860 861
}

862
static const struct rpc_call_ops nfs41_call_sync_ops = {
A
Andy Adamson 已提交
863
	.rpc_call_prepare = nfs41_call_sync_prepare,
A
Andy Adamson 已提交
864
	.rpc_call_done = nfs41_call_sync_done,
A
Andy Adamson 已提交
865 866
};

867 868 869 870 871 872 873 874 875 876 877
static void
nfs4_sequence_process_interrupted(struct nfs_client *client,
		struct nfs4_slot *slot, struct rpc_cred *cred)
{
	struct rpc_task *task;

	task = _nfs41_proc_sequence(client, cred, slot, true);
	if (!IS_ERR(task))
		rpc_put_task_async(task);
}

C
Chuck Lever 已提交
878 879
#else	/* !CONFIG_NFS_V4_1 */

880 881 882 883 884 885 886 887 888 889 890
static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res)
{
	return nfs40_sequence_done(task, res);
}

static void nfs4_sequence_free_slot(struct nfs4_sequence_res *res)
{
	if (res->sr_slot != NULL)
		nfs40_sequence_free_slot(res);
}

P
Peng Tao 已提交
891 892
int nfs4_sequence_done(struct rpc_task *task,
		       struct nfs4_sequence_res *res)
893
{
C
Chuck Lever 已提交
894
	return nfs40_sequence_done(task, res);
895
}
P
Peng Tao 已提交
896
EXPORT_SYMBOL_GPL(nfs4_sequence_done);
C
Chuck Lever 已提交
897

898 899 900 901 902 903 904 905
static void
nfs4_sequence_process_interrupted(struct nfs_client *client,
		struct nfs4_slot *slot, struct rpc_cred *cred)
{
	WARN_ON_ONCE(1);
	slot->interrupted = 0;
}

C
Chuck Lever 已提交
906
#endif	/* !CONFIG_NFS_V4_1 */
907

908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
static
void nfs4_sequence_attach_slot(struct nfs4_sequence_args *args,
		struct nfs4_sequence_res *res,
		struct nfs4_slot *slot)
{
	if (!slot)
		return;
	slot->privileged = args->sa_privileged ? 1 : 0;
	args->sa_slot = slot;

	res->sr_slot = slot;
	res->sr_timestamp = jiffies;
	res->sr_status_flags = 0;
	res->sr_status = 1;

}

int nfs4_setup_sequence(struct nfs_client *client,
926 927 928 929 930
			struct nfs4_sequence_args *args,
			struct nfs4_sequence_res *res,
			struct rpc_task *task)
{
	struct nfs4_session *session = nfs4_get_session(client);
931
	struct nfs4_slot_table *tbl  = client->cl_slot_tbl;
932
	struct nfs4_slot *slot;
933

934 935 936 937
	/* slot already allocated? */
	if (res->sr_slot != NULL)
		goto out_start;

938 939 940 941 942
	if (session) {
		tbl = &session->fc_slot_table;
		task->tk_timeout = 0;
	}

943 944 945 946 947 948 949 950 951 952 953 954 955 956
	for (;;) {
		spin_lock(&tbl->slot_tbl_lock);
		/* The state manager will wait until the slot table is empty */
		if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged)
			goto out_sleep;

		slot = nfs4_alloc_slot(tbl);
		if (IS_ERR(slot)) {
			/* Try again in 1/4 second */
			if (slot == ERR_PTR(-ENOMEM))
				task->tk_timeout = HZ >> 2;
			goto out_sleep;
		}
		spin_unlock(&tbl->slot_tbl_lock);
957

958 959 960 961
		if (likely(!slot->interrupted))
			break;
		nfs4_sequence_process_interrupted(client,
				slot, task->tk_msg.rpc_cred);
962 963
	}

964
	nfs4_sequence_attach_slot(args, res, slot);
965

966
	trace_nfs4_setup_sequence(session, args);
967 968 969
out_start:
	rpc_call_start(task);
	return 0;
970 971 972 973 974 975 976 977 978

out_sleep:
	if (args->sa_privileged)
		rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task,
				NULL, RPC_PRIORITY_PRIVILEGED);
	else
		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
	spin_unlock(&tbl->slot_tbl_lock);
	return -EAGAIN;
979 980 981
}
EXPORT_SYMBOL_GPL(nfs4_setup_sequence);

982 983 984
static void nfs40_call_sync_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_call_sync_data *data = calldata;
985
	nfs4_setup_sequence(data->seq_server->nfs_client,
986 987 988 989 990 991 992 993 994 995 996 997 998 999
				data->seq_args, data->seq_res, task);
}

static void nfs40_call_sync_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_call_sync_data *data = calldata;
	nfs4_sequence_done(task, data->seq_res);
}

static const struct rpc_call_ops nfs40_call_sync_ops = {
	.rpc_call_prepare = nfs40_call_sync_prepare,
	.rpc_call_done = nfs40_call_sync_done,
};

1000 1001
static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
				   struct nfs_server *server,
A
Andy Adamson 已提交
1002 1003
				   struct rpc_message *msg,
				   struct nfs4_sequence_args *args,
1004
				   struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
1005 1006 1007
{
	int ret;
	struct rpc_task *task;
1008
	struct nfs_client *clp = server->nfs_client;
1009
	struct nfs4_call_sync_data data = {
1010
		.seq_server = server,
A
Andy Adamson 已提交
1011 1012 1013 1014
		.seq_args = args,
		.seq_res = res,
	};
	struct rpc_task_setup task_setup = {
1015
		.rpc_client = clnt,
A
Andy Adamson 已提交
1016
		.rpc_message = msg,
1017
		.callback_ops = clp->cl_mvops->call_sync_ops,
A
Andy Adamson 已提交
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
		.callback_data = &data
	};

	task = rpc_run_task(&task_setup);
	if (IS_ERR(task))
		ret = PTR_ERR(task);
	else {
		ret = task->tk_status;
		rpc_put_task(task);
	}
	return ret;
}

1031 1032
int nfs4_call_sync(struct rpc_clnt *clnt,
		   struct nfs_server *server,
1033 1034 1035 1036 1037
		   struct rpc_message *msg,
		   struct nfs4_sequence_args *args,
		   struct nfs4_sequence_res *res,
		   int cache_reply)
{
1038
	nfs4_init_sequence(args, res, cache_reply);
1039
	return nfs4_call_sync_sequence(clnt, server, msg, args, res);
1040
}
A
Andy Adamson 已提交
1041

1042 1043
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
		unsigned long timestamp)
L
Linus Torvalds 已提交
1044
{
1045
	struct nfs_inode *nfsi = NFS_I(dir);
L
Linus Torvalds 已提交
1046

1047
	spin_lock(&dir->i_lock);
1048 1049 1050
	nfsi->cache_validity |= NFS_INO_INVALID_CTIME
		| NFS_INO_INVALID_MTIME
		| NFS_INO_INVALID_DATA;
J
Jeff Layton 已提交
1051
	if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(dir)) {
1052 1053 1054
		nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
		nfsi->attrtimeo_timestamp = jiffies;
	} else {
1055
		nfs_force_lookup_revalidate(dir);
J
Jeff Layton 已提交
1056
		if (cinfo->before != inode_peek_iversion_raw(dir))
1057 1058 1059
			nfsi->cache_validity |= NFS_INO_INVALID_ACCESS |
				NFS_INO_INVALID_ACL;
	}
J
Jeff Layton 已提交
1060
	inode_set_iversion_raw(dir, cinfo->after);
1061
	nfsi->read_cache_jiffies = timestamp;
1062
	nfsi->attr_gencount = nfs_inc_attr_generation_counter();
D
David Howells 已提交
1063
	nfs_fscache_invalidate(dir);
1064
	spin_unlock(&dir->i_lock);
L
Linus Torvalds 已提交
1065 1066
}

1067
struct nfs4_opendata {
1068
	struct kref kref;
1069 1070
	struct nfs_openargs o_arg;
	struct nfs_openres o_res;
1071 1072
	struct nfs_open_confirmargs c_arg;
	struct nfs_open_confirmres c_res;
1073 1074
	struct nfs4_string owner_name;
	struct nfs4_string group_name;
1075
	struct nfs4_label *a_label;
1076
	struct nfs_fattr f_attr;
1077
	struct nfs4_label *f_label;
1078
	struct dentry *dir;
1079
	struct dentry *dentry;
1080
	struct nfs4_state_owner *owner;
1081
	struct nfs4_state *state;
1082
	struct iattr attrs;
1083
	unsigned long timestamp;
B
Benjamin Coddington 已提交
1084 1085 1086 1087
	bool rpc_done;
	bool file_created;
	bool is_recover;
	bool cancelled;
1088
	int rpc_status;
1089 1090
};

1091 1092 1093 1094 1095 1096
struct nfs4_open_createattrs {
	struct nfs4_label *label;
	struct iattr *sattr;
	const __u32 verf[2];
};

1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server,
		int err, struct nfs4_exception *exception)
{
	if (err != -EINVAL)
		return false;
	if (!(server->caps & NFS_CAP_ATOMIC_OPEN_V1))
		return false;
	server->caps &= ~NFS_CAP_ATOMIC_OPEN_V1;
	exception->retry = 1;
	return true;
}

1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
static u32
nfs4_map_atomic_open_share(struct nfs_server *server,
		fmode_t fmode, int openflags)
{
	u32 res = 0;

	switch (fmode & (FMODE_READ | FMODE_WRITE)) {
	case FMODE_READ:
		res = NFS4_SHARE_ACCESS_READ;
		break;
	case FMODE_WRITE:
		res = NFS4_SHARE_ACCESS_WRITE;
		break;
	case FMODE_READ|FMODE_WRITE:
		res = NFS4_SHARE_ACCESS_BOTH;
	}
	if (!(server->caps & NFS_CAP_ATOMIC_OPEN_V1))
		goto out;
	/* Want no delegation if we're using O_DIRECT */
	if (openflags & O_DIRECT)
		res |= NFS4_SHARE_WANT_NO_DELEG;
out:
	return res;
}

1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
static enum open_claim_type4
nfs4_map_atomic_open_claim(struct nfs_server *server,
		enum open_claim_type4 claim)
{
	if (server->caps & NFS_CAP_ATOMIC_OPEN_V1)
		return claim;
	switch (claim) {
	default:
		return claim;
	case NFS4_OPEN_CLAIM_FH:
		return NFS4_OPEN_CLAIM_NULL;
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
		return NFS4_OPEN_CLAIM_DELEGATE_CUR;
	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
		return NFS4_OPEN_CLAIM_DELEGATE_PREV;
	}
}
1151 1152 1153 1154

static void nfs4_init_opendata_res(struct nfs4_opendata *p)
{
	p->o_res.f_attr = &p->f_attr;
1155
	p->o_res.f_label = p->f_label;
1156 1157
	p->o_res.seqid = p->o_arg.seqid;
	p->c_res.seqid = p->c_arg.seqid;
1158
	p->o_res.server = p->o_arg.server;
1159
	p->o_res.access_request = p->o_arg.access;
1160
	nfs_fattr_init(&p->f_attr);
1161
	nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name);
1162 1163
}

1164
static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
1165
		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
1166
		const struct nfs4_open_createattrs *c,
1167
		enum open_claim_type4 claim,
1168
		gfp_t gfp_mask)
1169
{
1170
	struct dentry *parent = dget_parent(dentry);
1171
	struct inode *dir = d_inode(parent);
1172
	struct nfs_server *server = NFS_SERVER(dir);
1173
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
1174
	struct nfs4_label *label = (c != NULL) ? c->label : NULL;
1175 1176
	struct nfs4_opendata *p;

1177
	p = kzalloc(sizeof(*p), gfp_mask);
1178 1179
	if (p == NULL)
		goto err;
1180 1181 1182 1183 1184

	p->f_label = nfs4_label_alloc(server, gfp_mask);
	if (IS_ERR(p->f_label))
		goto err_free_p;

1185 1186 1187 1188
	p->a_label = nfs4_label_alloc(server, gfp_mask);
	if (IS_ERR(p->a_label))
		goto err_free_f;

1189 1190
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask);
1191
	if (IS_ERR(p->o_arg.seqid))
1192
		goto err_free_label;
1193 1194
	nfs_sb_active(dentry->d_sb);
	p->dentry = dget(dentry);
1195 1196 1197
	p->dir = parent;
	p->owner = sp;
	atomic_inc(&sp->so_count);
1198 1199
	p->o_arg.open_flags = flags;
	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
1200
	p->o_arg.umask = current_umask();
1201
	p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
1202 1203
	p->o_arg.share_access = nfs4_map_atomic_open_share(server,
			fmode, flags);
1204 1205 1206 1207 1208
	/* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS
	 * will return permission denied for all bits until close */
	if (!(flags & O_EXCL)) {
		/* ask server to check for all possible rights as results
		 * are cached */
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
		switch (p->o_arg.claim) {
		default:
			break;
		case NFS4_OPEN_CLAIM_NULL:
		case NFS4_OPEN_CLAIM_FH:
			p->o_arg.access = NFS4_ACCESS_READ |
				NFS4_ACCESS_MODIFY |
				NFS4_ACCESS_EXTEND |
				NFS4_ACCESS_EXECUTE;
		}
1219
	}
1220
	p->o_arg.clientid = server->nfs_client->cl_clientid;
1221 1222
	p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
	p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
1223
	p->o_arg.name = &dentry->d_name;
1224
	p->o_arg.server = server;
1225
	p->o_arg.bitmask = nfs4_bitmask(server, label);
1226
	p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
1227
	p->o_arg.label = nfs4_label_copy(p->a_label, label);
1228
	switch (p->o_arg.claim) {
1229 1230 1231 1232 1233 1234 1235 1236 1237
	case NFS4_OPEN_CLAIM_NULL:
	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
		p->o_arg.fh = NFS_FH(dir);
		break;
	case NFS4_OPEN_CLAIM_PREVIOUS:
	case NFS4_OPEN_CLAIM_FH:
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
1238
		p->o_arg.fh = NFS_FH(d_inode(dentry));
1239
	}
1240
	if (c != NULL && c->sattr != NULL && c->sattr->ia_valid != 0) {
1241
		p->o_arg.u.attrs = &p->attrs;
1242
		memcpy(&p->attrs, c->sattr, sizeof(p->attrs));
1243

1244
		memcpy(p->o_arg.u.verifier.data, c->verf,
1245
				sizeof(p->o_arg.u.verifier.data));
1246
	}
1247 1248 1249
	p->c_arg.fh = &p->o_res.fh;
	p->c_arg.stateid = &p->o_res.stateid;
	p->c_arg.seqid = p->o_arg.seqid;
1250
	nfs4_init_opendata_res(p);
1251
	kref_init(&p->kref);
1252
	return p;
1253 1254

err_free_label:
1255 1256
	nfs4_label_free(p->a_label);
err_free_f:
1257 1258
	nfs4_label_free(p->f_label);
err_free_p:
1259 1260 1261 1262 1263 1264
	kfree(p);
err:
	dput(parent);
	return NULL;
}

1265
static void nfs4_opendata_free(struct kref *kref)
1266
{
1267 1268
	struct nfs4_opendata *p = container_of(kref,
			struct nfs4_opendata, kref);
1269
	struct super_block *sb = p->dentry->d_sb;
1270 1271

	nfs_free_seqid(p->o_arg.seqid);
1272
	nfs4_sequence_free_slot(&p->o_res.seq_res);
1273 1274
	if (p->state != NULL)
		nfs4_put_open_state(p->state);
1275
	nfs4_put_state_owner(p->owner);
1276

1277
	nfs4_label_free(p->a_label);
1278 1279
	nfs4_label_free(p->f_label);

1280
	dput(p->dir);
1281 1282
	dput(p->dentry);
	nfs_sb_deactive(sb);
1283
	nfs_fattr_free_names(&p->f_attr);
1284
	kfree(p->f_attr.mdsthreshold);
1285 1286 1287 1288 1289 1290 1291
	kfree(p);
}

static void nfs4_opendata_put(struct nfs4_opendata *p)
{
	if (p != NULL)
		kref_put(&p->kref, nfs4_opendata_free);
1292 1293
}

1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
static bool nfs4_mode_match_open_stateid(struct nfs4_state *state,
		fmode_t fmode)
{
	switch(fmode & (FMODE_READ|FMODE_WRITE)) {
	case FMODE_READ|FMODE_WRITE:
		return state->n_rdwr != 0;
	case FMODE_WRITE:
		return state->n_wronly != 0;
	case FMODE_READ:
		return state->n_rdonly != 0;
	}
	WARN_ON_ONCE(1);
	return false;
}

1309
static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
1310 1311
{
	int ret = 0;
1312

1313
	if (open_mode & (O_EXCL|O_TRUNC))
1314 1315
		goto out;
	switch (mode & (FMODE_READ|FMODE_WRITE)) {
1316
		case FMODE_READ:
1317 1318
			ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0
				&& state->n_rdonly != 0;
1319 1320
			break;
		case FMODE_WRITE:
1321 1322
			ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0
				&& state->n_wronly != 0;
1323 1324
			break;
		case FMODE_READ|FMODE_WRITE:
1325 1326
			ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0
				&& state->n_rdwr != 0;
1327
	}
1328
out:
1329 1330 1331
	return ret;
}

1332 1333
static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,
		enum open_claim_type4 claim)
1334
{
1335 1336
	if (delegation == NULL)
		return 0;
1337
	if ((delegation->type & fmode) != fmode)
1338
		return 0;
1339 1340
	if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
		return 0;
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
	switch (claim) {
	case NFS4_OPEN_CLAIM_NULL:
	case NFS4_OPEN_CLAIM_FH:
		break;
	case NFS4_OPEN_CLAIM_PREVIOUS:
		if (!test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
			break;
	default:
		return 0;
	}
1351
	nfs_mark_delegation_referenced(delegation);
1352 1353 1354
	return 1;
}

1355
static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
1356
{
1357
	switch (fmode) {
1358 1359 1360 1361 1362 1363 1364 1365 1366
		case FMODE_WRITE:
			state->n_wronly++;
			break;
		case FMODE_READ:
			state->n_rdonly++;
			break;
		case FMODE_READ|FMODE_WRITE:
			state->n_rdwr++;
	}
1367
	nfs4_state_set_mode_locked(state, state->state | fmode);
1368 1369
}

1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
#ifdef CONFIG_NFS_V4_1
static bool nfs_open_stateid_recover_openmode(struct nfs4_state *state)
{
	if (state->n_rdonly && !test_bit(NFS_O_RDONLY_STATE, &state->flags))
		return true;
	if (state->n_wronly && !test_bit(NFS_O_WRONLY_STATE, &state->flags))
		return true;
	if (state->n_rdwr && !test_bit(NFS_O_RDWR_STATE, &state->flags))
		return true;
	return false;
}
#endif /* CONFIG_NFS_V4_1 */

T
Trond Myklebust 已提交
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
static void nfs_state_log_update_open_stateid(struct nfs4_state *state)
{
	if (test_and_clear_bit(NFS_STATE_CHANGE_WAIT, &state->flags))
		wake_up_all(&state->waitq);
}

static void nfs_state_log_out_of_order_open_stateid(struct nfs4_state *state,
		const nfs4_stateid *stateid)
{
	u32 state_seqid = be32_to_cpu(state->open_stateid.seqid);
	u32 stateid_seqid = be32_to_cpu(stateid->seqid);

	if (stateid_seqid == state_seqid + 1U ||
	    (stateid_seqid == 1U && state_seqid == 0xffffffffU))
		nfs_state_log_update_open_stateid(state);
	else
		set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
}

1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
{
	struct nfs_client *clp = state->owner->so_server->nfs_client;
	bool need_recover = false;

	if (test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags) && state->n_rdonly)
		need_recover = true;
	if (test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags) && state->n_wronly)
		need_recover = true;
	if (test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags) && state->n_rdwr)
		need_recover = true;
	if (need_recover)
		nfs4_state_mark_reclaim_nograce(clp, state);
}

T
Trond Myklebust 已提交
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
/*
 * Check for whether or not the caller may update the open stateid
 * to the value passed in by stateid.
 *
 * Note: This function relies heavily on the server implementing
 * RFC7530 Section 9.1.4.2, and RFC5661 Section 8.2.2
 * correctly.
 * i.e. The stateid seqids have to be initialised to 1, and
 * are then incremented on every state transition.
 */
1427
static bool nfs_need_update_open_stateid(struct nfs4_state *state,
T
Trond Myklebust 已提交
1428
		const nfs4_stateid *stateid)
1429
{
T
Trond Myklebust 已提交
1430 1431 1432 1433 1434 1435
	if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 ||
	    !nfs4_stateid_match_other(stateid, &state->open_stateid)) {
		if (stateid->seqid == cpu_to_be32(1))
			nfs_state_log_update_open_stateid(state);
		else
			set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
1436
		return true;
1437
	}
T
Trond Myklebust 已提交
1438 1439 1440

	if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
		nfs_state_log_out_of_order_open_stateid(state, stateid);
1441
		return true;
T
Trond Myklebust 已提交
1442
	}
1443 1444 1445
	return false;
}

T
Trond Myklebust 已提交
1446 1447
static void nfs_resync_open_stateid_locked(struct nfs4_state *state)
{
1448 1449
	if (!(state->n_wronly || state->n_rdonly || state->n_rdwr))
		return;
T
Trond Myklebust 已提交
1450 1451 1452 1453 1454 1455
	if (state->n_wronly)
		set_bit(NFS_O_WRONLY_STATE, &state->flags);
	if (state->n_rdonly)
		set_bit(NFS_O_RDONLY_STATE, &state->flags);
	if (state->n_rdwr)
		set_bit(NFS_O_RDWR_STATE, &state->flags);
1456
	set_bit(NFS_OPEN_STATE, &state->flags);
T
Trond Myklebust 已提交
1457 1458
}

1459 1460
static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
		nfs4_stateid *stateid, fmode_t fmode)
1461
{
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
	clear_bit(NFS_O_RDWR_STATE, &state->flags);
	switch (fmode & (FMODE_READ|FMODE_WRITE)) {
	case FMODE_WRITE:
		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
		break;
	case FMODE_READ:
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
		break;
	case 0:
		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
		clear_bit(NFS_OPEN_STATE, &state->flags);
	}
	if (stateid == NULL)
		return;
T
Trond Myklebust 已提交
1477 1478 1479
	/* Handle OPEN+OPEN_DOWNGRADE races */
	if (nfs4_stateid_match_other(stateid, &state->open_stateid) &&
	    !nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
T
Trond Myklebust 已提交
1480
		nfs_resync_open_stateid_locked(state);
T
Trond Myklebust 已提交
1481
		goto out;
T
Trond Myklebust 已提交
1482
	}
1483
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1484 1485
		nfs4_stateid_copy(&state->stateid, stateid);
	nfs4_stateid_copy(&state->open_stateid, stateid);
1486
	trace_nfs4_open_stateid_update(state->inode, stateid, 0);
T
Trond Myklebust 已提交
1487 1488
out:
	nfs_state_log_update_open_stateid(state);
1489 1490
}

1491 1492 1493
static void nfs_clear_open_stateid(struct nfs4_state *state,
	nfs4_stateid *arg_stateid,
	nfs4_stateid *stateid, fmode_t fmode)
1494 1495
{
	write_seqlock(&state->seqlock);
T
Trond Myklebust 已提交
1496 1497 1498
	/* Ignore, if the CLOSE argment doesn't match the current stateid */
	if (nfs4_state_match_open_stateid_other(state, arg_stateid))
		nfs_clear_open_stateid_locked(state, stateid, fmode);
1499
	write_sequnlock(&state->seqlock);
1500 1501
	if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
		nfs4_schedule_state_manager(state->owner->so_server->nfs_client);
1502 1503
}

1504
static void nfs_set_open_stateid_locked(struct nfs4_state *state,
T
Trond Myklebust 已提交
1505
		const nfs4_stateid *stateid, nfs4_stateid *freeme)
1506
{
T
Trond Myklebust 已提交
1507 1508 1509 1510 1511 1512 1513
	DEFINE_WAIT(wait);
	int status = 0;
	for (;;) {

		if (!nfs_need_update_open_stateid(state, stateid))
			return;
		if (!test_bit(NFS_STATE_CHANGE_WAIT, &state->flags))
1514
			break;
T
Trond Myklebust 已提交
1515
		if (status)
1516
			break;
T
Trond Myklebust 已提交
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
		/* Rely on seqids for serialisation with NFSv4.0 */
		if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client))
			break;

		prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE);
		/*
		 * Ensure we process the state changes in the same order
		 * in which the server processed them by delaying the
		 * update of the stateid until we are in sequence.
		 */
		write_sequnlock(&state->seqlock);
		spin_unlock(&state->owner->so_lock);
		rcu_read_unlock();
1530
		trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);
T
Trond Myklebust 已提交
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
		if (!signal_pending(current)) {
			if (schedule_timeout(5*HZ) == 0)
				status = -EAGAIN;
			else
				status = 0;
		} else
			status = -EINTR;
		finish_wait(&state->waitq, &wait);
		rcu_read_lock();
		spin_lock(&state->owner->so_lock);
		write_seqlock(&state->seqlock);
1542
	}
T
Trond Myklebust 已提交
1543

1544 1545
	if (test_bit(NFS_OPEN_STATE, &state->flags) &&
	    !nfs4_stateid_match_other(stateid, &state->open_stateid)) {
T
Trond Myklebust 已提交
1546 1547 1548 1549
		nfs4_stateid_copy(freeme, &state->open_stateid);
		nfs_test_and_clear_all_open_stateid(state);
	}

1550 1551 1552
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
		nfs4_stateid_copy(&state->stateid, stateid);
	nfs4_stateid_copy(&state->open_stateid, stateid);
1553
	trace_nfs4_open_stateid_update(state->inode, stateid, status);
T
Trond Myklebust 已提交
1554
	nfs_state_log_update_open_stateid(state);
1555 1556
}

T
Trond Myklebust 已提交
1557
static void nfs_state_set_open_stateid(struct nfs4_state *state,
1558 1559 1560
		const nfs4_stateid *open_stateid,
		fmode_t fmode,
		nfs4_stateid *freeme)
L
Linus Torvalds 已提交
1561
{
1562 1563 1564 1565 1566
	/*
	 * Protect the call to nfs4_state_set_mode_locked and
	 * serialise the stateid update
	 */
	write_seqlock(&state->seqlock);
T
Trond Myklebust 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
	nfs_set_open_stateid_locked(state, open_stateid, freeme);
	switch (fmode) {
	case FMODE_READ:
		set_bit(NFS_O_RDONLY_STATE, &state->flags);
		break;
	case FMODE_WRITE:
		set_bit(NFS_O_WRONLY_STATE, &state->flags);
		break;
	case FMODE_READ|FMODE_WRITE:
		set_bit(NFS_O_RDWR_STATE, &state->flags);
1577
	}
T
Trond Myklebust 已提交
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
	set_bit(NFS_OPEN_STATE, &state->flags);
	write_sequnlock(&state->seqlock);
}

static void nfs_state_set_delegation(struct nfs4_state *state,
		const nfs4_stateid *deleg_stateid,
		fmode_t fmode)
{
	/*
	 * Protect the call to nfs4_state_set_mode_locked and
	 * serialise the stateid update
	 */
	write_seqlock(&state->seqlock);
	nfs4_stateid_copy(&state->stateid, deleg_stateid);
	set_bit(NFS_DELEGATED_STATE, &state->flags);
1593
	write_sequnlock(&state->seqlock);
L
Linus Torvalds 已提交
1594 1595
}

1596 1597 1598 1599
static int update_open_stateid(struct nfs4_state *state,
		const nfs4_stateid *open_stateid,
		const nfs4_stateid *delegation,
		fmode_t fmode)
1600
{
1601 1602
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs_client *clp = server->nfs_client;
1603 1604
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_delegation *deleg_cur;
A
Arnd Bergmann 已提交
1605
	nfs4_stateid freeme = { };
1606 1607
	int ret = 0;

1608
	fmode &= (FMODE_READ|FMODE_WRITE);
1609 1610

	rcu_read_lock();
T
Trond Myklebust 已提交
1611 1612 1613 1614 1615 1616
	spin_lock(&state->owner->so_lock);
	if (open_stateid != NULL) {
		nfs_state_set_open_stateid(state, open_stateid, fmode, &freeme);
		ret = 1;
	}

1617 1618 1619 1620 1621
	deleg_cur = rcu_dereference(nfsi->delegation);
	if (deleg_cur == NULL)
		goto no_delegation;

	spin_lock(&deleg_cur->lock);
1622
	if (rcu_dereference(nfsi->delegation) != deleg_cur ||
1623
	   test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) ||
1624
	    (deleg_cur->type & fmode) != fmode)
1625 1626 1627 1628
		goto no_delegation_unlock;

	if (delegation == NULL)
		delegation = &deleg_cur->stateid;
1629
	else if (!nfs4_stateid_match(&deleg_cur->stateid, delegation))
1630 1631
		goto no_delegation_unlock;

1632
	nfs_mark_delegation_referenced(deleg_cur);
T
Trond Myklebust 已提交
1633
	nfs_state_set_delegation(state, &deleg_cur->stateid, fmode);
1634 1635 1636 1637
	ret = 1;
no_delegation_unlock:
	spin_unlock(&deleg_cur->lock);
no_delegation:
T
Trond Myklebust 已提交
1638 1639 1640
	if (ret)
		update_open_stateflags(state, fmode);
	spin_unlock(&state->owner->so_lock);
1641 1642
	rcu_read_unlock();

1643
	if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
1644 1645 1646 1647
		nfs4_schedule_state_manager(clp);
	if (freeme.type != 0)
		nfs4_test_and_free_stateid(server, &freeme,
				state->owner->so_cred);
1648 1649 1650 1651

	return ret;
}

1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
static bool nfs4_update_lock_stateid(struct nfs4_lock_state *lsp,
		const nfs4_stateid *stateid)
{
	struct nfs4_state *state = lsp->ls_state;
	bool ret = false;

	spin_lock(&state->state_lock);
	if (!nfs4_stateid_match_other(stateid, &lsp->ls_stateid))
		goto out_noupdate;
	if (!nfs4_stateid_is_newer(stateid, &lsp->ls_stateid))
		goto out_noupdate;
	nfs4_stateid_copy(&lsp->ls_stateid, stateid);
	ret = true;
out_noupdate:
	spin_unlock(&state->state_lock);
	return ret;
}
1669

1670
static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmode)
1671 1672 1673
{
	struct nfs_delegation *delegation;

1674
	fmode &= FMODE_READ|FMODE_WRITE;
1675 1676
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(inode)->delegation);
1677
	if (delegation == NULL || (delegation->type & fmode) == fmode) {
1678 1679 1680 1681
		rcu_read_unlock();
		return;
	}
	rcu_read_unlock();
1682
	nfs4_inode_return_delegation(inode);
1683 1684
}

1685
static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
1686 1687 1688 1689
{
	struct nfs4_state *state = opendata->state;
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_delegation *delegation;
1690
	int open_mode = opendata->o_arg.open_flags;
1691
	fmode_t fmode = opendata->o_arg.fmode;
1692
	enum open_claim_type4 claim = opendata->o_arg.claim;
1693 1694 1695 1696
	nfs4_stateid stateid;
	int ret = -EAGAIN;

	for (;;) {
1697
		spin_lock(&state->owner->so_lock);
1698
		if (can_open_cached(state, fmode, open_mode)) {
1699
			update_open_stateflags(state, fmode);
1700
			spin_unlock(&state->owner->so_lock);
1701
			goto out_return_state;
1702
		}
1703
		spin_unlock(&state->owner->so_lock);
1704 1705
		rcu_read_lock();
		delegation = rcu_dereference(nfsi->delegation);
1706
		if (!can_open_delegated(delegation, fmode, claim)) {
1707
			rcu_read_unlock();
1708
			break;
1709
		}
1710
		/* Save the delegation */
1711
		nfs4_stateid_copy(&stateid, &delegation->stateid);
1712
		rcu_read_unlock();
1713
		nfs_release_seqid(opendata->o_arg.seqid);
1714 1715 1716 1717 1718
		if (!opendata->is_recover) {
			ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
			if (ret != 0)
				goto out;
		}
1719
		ret = -EAGAIN;
1720 1721

		/* Try to update the stateid using the delegation */
1722
		if (update_open_stateid(state, NULL, &stateid, fmode))
1723
			goto out_return_state;
1724 1725 1726 1727 1728 1729 1730 1731
	}
out:
	return ERR_PTR(ret);
out_return_state:
	atomic_inc(&state->count);
	return state;
}

1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743
static void
nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
{
	struct nfs_client *clp = NFS_SERVER(state->inode)->nfs_client;
	struct nfs_delegation *delegation;
	int delegation_flags = 0;

	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
	if (delegation)
		delegation_flags = delegation->flags;
	rcu_read_unlock();
1744 1745 1746 1747 1748
	switch (data->o_arg.claim) {
	default:
		break;
	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
1749 1750 1751 1752
		pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
				   "returning a delegation for "
				   "OPEN(CLAIM_DELEGATE_CUR)\n",
				   clp->cl_hostname);
1753 1754 1755
		return;
	}
	if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775
		nfs_inode_set_delegation(state->inode,
					 data->owner->so_cred,
					 &data->o_res);
	else
		nfs_inode_reclaim_delegation(state->inode,
					     data->owner->so_cred,
					     &data->o_res);
}

/*
 * Check the inode attributes against the CLAIM_PREVIOUS returned attributes
 * and update the nfs4_state.
 */
static struct nfs4_state *
_nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
{
	struct inode *inode = data->state->inode;
	struct nfs4_state *state = data->state;
	int ret;

1776
	if (!data->rpc_done) {
1777 1778
		if (data->rpc_status)
			return ERR_PTR(data->rpc_status);
1779 1780
		/* cached opens have already been processed */
		goto update;
1781 1782 1783 1784
	}

	ret = nfs_refresh_inode(inode, &data->f_attr);
	if (ret)
1785
		return ERR_PTR(ret);
1786 1787 1788

	if (data->o_res.delegation_type != 0)
		nfs4_opendata_check_deleg(data, state);
1789
update:
1790 1791
	update_open_stateid(state, &data->o_res.stateid, NULL,
			    data->o_arg.fmode);
1792
	atomic_inc(&state->count);
1793 1794 1795 1796

	return state;
}

1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
static struct inode *
nfs4_opendata_get_inode(struct nfs4_opendata *data)
{
	struct inode *inode;

	switch (data->o_arg.claim) {
	case NFS4_OPEN_CLAIM_NULL:
	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
		if (!(data->f_attr.valid & NFS_ATTR_FATTR))
			return ERR_PTR(-EAGAIN);
		inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh,
				&data->f_attr, data->f_label);
		break;
	default:
		inode = d_inode(data->dentry);
		ihold(inode);
		nfs_refresh_inode(inode, &data->f_attr);
	}
	return inode;
}

1819
static struct nfs4_state *
1820
nfs4_opendata_find_nfs4_state(struct nfs4_opendata *data)
1821
{
1822
	struct nfs4_state *state;
1823
	struct inode *inode;
1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842

	inode = nfs4_opendata_get_inode(data);
	if (IS_ERR(inode))
		return ERR_CAST(inode);
	if (data->state != NULL && data->state->inode == inode) {
		state = data->state;
		atomic_inc(&state->count);
	} else
		state = nfs4_get_open_state(inode, data->owner);
	iput(inode);
	if (state == NULL)
		state = ERR_PTR(-ENOMEM);
	return state;
}

static struct nfs4_state *
_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
{
	struct nfs4_state *state;
1843

1844
	if (!data->rpc_done) {
1845
		state = nfs4_try_open_cached(data);
1846
		trace_nfs4_cached_open(data->state);
1847 1848 1849
		goto out;
	}

1850 1851 1852 1853
	state = nfs4_opendata_find_nfs4_state(data);
	if (IS_ERR(state))
		goto out;

1854 1855
	if (data->o_res.delegation_type != 0)
		nfs4_opendata_check_deleg(data, state);
1856
	update_open_stateid(state, &data->o_res.stateid, NULL,
1857
			data->o_arg.fmode);
1858
out:
1859
	nfs_release_seqid(data->o_arg.seqid);
1860 1861 1862
	return state;
}

1863 1864 1865
static struct nfs4_state *
nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
{
1866 1867
	struct nfs4_state *ret;

1868
	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
1869 1870 1871 1872 1873
		ret =_nfs4_opendata_reclaim_to_nfs4_state(data);
	else
		ret = _nfs4_opendata_to_nfs4_state(data);
	nfs4_sequence_free_slot(&data->o_res.seq_res);
	return ret;
1874 1875
}

1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
{
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_open_context *ctx;

	spin_lock(&state->inode->i_lock);
	list_for_each_entry(ctx, &nfsi->open_files, list) {
		if (ctx->state != state)
			continue;
		get_nfs_open_context(ctx);
		spin_unlock(&state->inode->i_lock);
		return ctx;
	}
	spin_unlock(&state->inode->i_lock);
	return ERR_PTR(-ENOENT);
}

1893 1894
static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx,
		struct nfs4_state *state, enum open_claim_type4 claim)
T
Trond Myklebust 已提交
1895 1896 1897
{
	struct nfs4_opendata *opendata;

1898
	opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0,
1899
			NULL, claim, GFP_NOFS);
T
Trond Myklebust 已提交
1900 1901 1902 1903 1904 1905 1906
	if (opendata == NULL)
		return ERR_PTR(-ENOMEM);
	opendata->state = state;
	atomic_inc(&state->count);
	return opendata;
}

1907 1908
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
		fmode_t fmode)
1909
{
1910
	struct nfs4_state *newstate;
1911 1912
	int ret;

1913
	if (!nfs4_mode_match_open_stateid(opendata->state, fmode))
1914
		return 0;
1915 1916
	opendata->o_arg.open_flags = 0;
	opendata->o_arg.fmode = fmode;
1917 1918 1919
	opendata->o_arg.share_access = nfs4_map_atomic_open_share(
			NFS_SB(opendata->dentry->d_sb),
			fmode, 0);
1920 1921 1922
	memset(&opendata->o_res, 0, sizeof(opendata->o_res));
	memset(&opendata->c_res, 0, sizeof(opendata->c_res));
	nfs4_init_opendata_res(opendata);
1923
	ret = _nfs4_recover_proc_open(opendata);
1924 1925
	if (ret != 0)
		return ret; 
1926
	newstate = nfs4_opendata_to_nfs4_state(opendata);
1927 1928
	if (IS_ERR(newstate))
		return PTR_ERR(newstate);
1929 1930
	if (newstate != opendata->state)
		ret = -ESTALE;
1931
	nfs4_close_state(newstate, fmode);
1932
	return ret;
1933 1934 1935 1936 1937 1938
}

static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
{
	int ret;

1939 1940 1941 1942
	/* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
	clear_bit(NFS_O_RDWR_STATE, &state->flags);
	clear_bit(NFS_O_WRONLY_STATE, &state->flags);
	clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1943
	/* memory barrier prior to reading state->n_* */
1944
	clear_bit(NFS_DELEGATED_STATE, &state->flags);
1945
	clear_bit(NFS_OPEN_STATE, &state->flags);
1946
	smp_rmb();
1947 1948 1949 1950 1951 1952 1953 1954 1955
	ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
	if (ret != 0)
		return ret;
	ret = nfs4_open_recover_helper(opendata, FMODE_WRITE);
	if (ret != 0)
		return ret;
	ret = nfs4_open_recover_helper(opendata, FMODE_READ);
	if (ret != 0)
		return ret;
1956 1957 1958 1959 1960
	/*
	 * We may have performed cached opens for all three recoveries.
	 * Check if we need to update the current stateid.
	 */
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
1961
	    !nfs4_stateid_match(&state->stateid, &state->open_stateid)) {
1962
		write_seqlock(&state->seqlock);
1963
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1964
			nfs4_stateid_copy(&state->stateid, &state->open_stateid);
1965
		write_sequnlock(&state->seqlock);
1966
	}
1967 1968 1969
	return 0;
}

L
Linus Torvalds 已提交
1970 1971 1972 1973
/*
 * OPEN_RECLAIM:
 * 	reclaim state on the server after a reboot.
 */
1974
static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1975
{
1976
	struct nfs_delegation *delegation;
1977
	struct nfs4_opendata *opendata;
1978
	fmode_t delegation_type = 0;
L
Linus Torvalds 已提交
1979 1980
	int status;

1981 1982
	opendata = nfs4_open_recoverdata_alloc(ctx, state,
			NFS4_OPEN_CLAIM_PREVIOUS);
T
Trond Myklebust 已提交
1983 1984
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
1985 1986
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
1987
	if (delegation != NULL && test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) != 0)
1988
		delegation_type = delegation->type;
1989
	rcu_read_unlock();
1990 1991
	opendata->o_arg.u.delegation_type = delegation_type;
	status = nfs4_open_recover(opendata, state);
1992
	nfs4_opendata_put(opendata);
L
Linus Torvalds 已提交
1993 1994 1995
	return status;
}

1996
static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1997 1998 1999 2000 2001
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_exception exception = { };
	int err;
	do {
2002
		err = _nfs4_do_open_reclaim(ctx, state);
2003
		trace_nfs4_open_reclaim(ctx, 0, err);
2004 2005
		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
			continue;
2006
		if (err != -NFS4ERR_DELAY)
2007 2008
			break;
		nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
2009 2010 2011 2012
	} while (exception.retry);
	return err;
}

2013 2014 2015 2016 2017 2018 2019
static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
	struct nfs_open_context *ctx;
	int ret;

	ctx = nfs4_state_find_open_context(state);
	if (IS_ERR(ctx))
2020
		return -EAGAIN;
2021
	ret = nfs4_do_open_reclaim(ctx, state);
2022 2023 2024 2025
	put_nfs_open_context(ctx);
	return ret;
}

2026
static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, struct file_lock *fl, int err)
L
Linus Torvalds 已提交
2027
{
2028 2029 2030 2031 2032 2033
	switch (err) {
		default:
			printk(KERN_ERR "NFS: %s: unhandled error "
					"%d.\n", __func__, err);
		case 0:
		case -ENOENT:
2034
		case -EAGAIN:
2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
		case -ESTALE:
			break;
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
		case -NFS4ERR_BAD_HIGH_SLOT:
		case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
		case -NFS4ERR_DEADSESSION:
			set_bit(NFS_DELEGATED_STATE, &state->flags);
			nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
			return -EAGAIN;
		case -NFS4ERR_STALE_CLIENTID:
		case -NFS4ERR_STALE_STATEID:
			set_bit(NFS_DELEGATED_STATE, &state->flags);
			/* Don't recall a delegation if it was lost */
			nfs4_schedule_lease_recovery(server->nfs_client);
			return -EAGAIN;
2051 2052 2053
		case -NFS4ERR_MOVED:
			nfs4_schedule_migration_recovery(server);
			return -EAGAIN;
2054 2055 2056
		case -NFS4ERR_LEASE_MOVED:
			nfs4_schedule_lease_moved_recovery(server->nfs_client);
			return -EAGAIN;
2057 2058
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_ADMIN_REVOKED:
2059
		case -NFS4ERR_EXPIRED:
2060
		case -NFS4ERR_BAD_STATEID:
2061
		case -NFS4ERR_OPENMODE:
2062 2063 2064
			nfs_inode_find_state_and_recover(state->inode,
					stateid);
			nfs4_schedule_stateid_recovery(server, state);
2065
			return -EAGAIN;
2066 2067 2068 2069 2070
		case -NFS4ERR_DELAY:
		case -NFS4ERR_GRACE:
			set_bit(NFS_DELEGATED_STATE, &state->flags);
			ssleep(1);
			return -EAGAIN;
2071 2072
		case -ENOMEM:
		case -NFS4ERR_DENIED:
2073 2074 2075 2076 2077
			if (fl) {
				struct nfs4_lock_state *lsp = fl->fl_u.nfs4_fl.owner;
				if (lsp)
					set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
			}
2078
			return 0;
2079
	}
L
Linus Torvalds 已提交
2080 2081 2082
	return err;
}

2083 2084 2085
int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
		struct nfs4_state *state, const nfs4_stateid *stateid,
		fmode_t type)
2086 2087 2088
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_opendata *opendata;
2089
	int err = 0;
2090 2091 2092 2093 2094 2095

	opendata = nfs4_open_recoverdata_alloc(ctx, state,
			NFS4_OPEN_CLAIM_DELEG_CUR_FH);
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
	nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
2096 2097 2098
	write_seqlock(&state->seqlock);
	nfs4_stateid_copy(&state->stateid, &state->open_stateid);
	write_sequnlock(&state->seqlock);
2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111
	clear_bit(NFS_DELEGATED_STATE, &state->flags);
	switch (type & (FMODE_READ|FMODE_WRITE)) {
	case FMODE_READ|FMODE_WRITE:
	case FMODE_WRITE:
		err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
		if (err)
			break;
		err = nfs4_open_recover_helper(opendata, FMODE_WRITE);
		if (err)
			break;
	case FMODE_READ:
		err = nfs4_open_recover_helper(opendata, FMODE_READ);
	}
2112
	nfs4_opendata_put(opendata);
2113
	return nfs4_handle_delegation_recall_error(server, state, stateid, NULL, err);
2114 2115
}

2116 2117 2118 2119
static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;

2120 2121
	nfs4_setup_sequence(data->o_arg.server->nfs_client,
			   &data->c_arg.seq_args, &data->c_res.seq_res, task);
2122 2123
}

2124 2125 2126 2127
static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;

2128
	nfs40_sequence_done(task, &data->c_res.seq_res);
2129

2130
	data->rpc_status = task->tk_status;
2131
	if (data->rpc_status == 0) {
2132
		nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid);
2133
		nfs_confirm_seqid(&data->owner->so_seqid, 0);
2134
		renew_lease(data->o_res.server, data->timestamp);
B
Benjamin Coddington 已提交
2135
		data->rpc_done = true;
2136
	}
2137 2138 2139 2140 2141 2142 2143 2144
}

static void nfs4_open_confirm_release(void *calldata)
{
	struct nfs4_opendata *data = calldata;
	struct nfs4_state *state = NULL;

	/* If this request hasn't been cancelled, do nothing */
B
Benjamin Coddington 已提交
2145
	if (!data->cancelled)
2146 2147
		goto out_free;
	/* In case of error, no cleanup! */
2148
	if (!data->rpc_done)
2149 2150
		goto out_free;
	state = nfs4_opendata_to_nfs4_state(data);
2151
	if (!IS_ERR(state))
2152
		nfs4_close_state(state, data->o_arg.fmode);
2153
out_free:
2154
	nfs4_opendata_put(data);
2155 2156 2157
}

static const struct rpc_call_ops nfs4_open_confirm_ops = {
2158
	.rpc_call_prepare = nfs4_open_confirm_prepare,
2159 2160 2161 2162 2163 2164 2165 2166 2167
	.rpc_call_done = nfs4_open_confirm_done,
	.rpc_release = nfs4_open_confirm_release,
};

/*
 * Note: On error, nfs4_proc_open_confirm will free the struct nfs4_opendata
 */
static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
{
2168
	struct nfs_server *server = NFS_SERVER(d_inode(data->dir));
2169
	struct rpc_task *task;
2170 2171 2172 2173 2174 2175
	struct  rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
		.rpc_argp = &data->c_arg,
		.rpc_resp = &data->c_res,
		.rpc_cred = data->owner->so_cred,
	};
T
Trond Myklebust 已提交
2176 2177
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
2178
		.rpc_message = &msg,
T
Trond Myklebust 已提交
2179 2180
		.callback_ops = &nfs4_open_confirm_ops,
		.callback_data = data,
2181
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
2182 2183
		.flags = RPC_TASK_ASYNC,
	};
L
Linus Torvalds 已提交
2184 2185
	int status;

2186
	nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
2187
	kref_get(&data->kref);
B
Benjamin Coddington 已提交
2188
	data->rpc_done = false;
2189
	data->rpc_status = 0;
2190
	data->timestamp = jiffies;
2191 2192
	if (data->is_recover)
		nfs4_set_sequence_privileged(&data->c_arg.seq_args);
T
Trond Myklebust 已提交
2193
	task = rpc_run_task(&task_setup_data);
2194
	if (IS_ERR(task))
2195
		return PTR_ERR(task);
2196
	status = rpc_wait_for_completion_task(task);
2197
	if (status != 0) {
B
Benjamin Coddington 已提交
2198
		data->cancelled = true;
2199 2200 2201
		smp_wmb();
	} else
		status = data->rpc_status;
2202
	rpc_put_task(task);
L
Linus Torvalds 已提交
2203 2204 2205
	return status;
}

2206
static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
2207
{
2208 2209
	struct nfs4_opendata *data = calldata;
	struct nfs4_state_owner *sp = data->owner;
2210
	struct nfs_client *clp = sp->so_server->nfs_client;
2211
	enum open_claim_type4 claim = data->o_arg.claim;
2212

2213
	if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
2214
		goto out_wait;
2215 2216 2217 2218 2219 2220 2221
	/*
	 * Check if we still need to send an OPEN call, or if we can use
	 * a delegation instead.
	 */
	if (data->state != NULL) {
		struct nfs_delegation *delegation;

2222
		if (can_open_cached(data->state, data->o_arg.fmode, data->o_arg.open_flags))
2223
			goto out_no_action;
2224 2225
		rcu_read_lock();
		delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
2226
		if (can_open_delegated(delegation, data->o_arg.fmode, claim))
2227
			goto unlock_no_action;
2228 2229
		rcu_read_unlock();
	}
2230
	/* Update client id. */
2231
	data->o_arg.clientid = clp->cl_clientid;
2232 2233 2234
	switch (claim) {
	default:
		break;
2235 2236 2237
	case NFS4_OPEN_CLAIM_PREVIOUS:
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
2238
		data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
2239 2240
	case NFS4_OPEN_CLAIM_FH:
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
T
Trond Myklebust 已提交
2241
	}
2242
	data->timestamp = jiffies;
2243
	if (nfs4_setup_sequence(data->o_arg.server->nfs_client,
2244
				&data->o_arg.seq_args,
2245 2246 2247
				&data->o_res.seq_res,
				task) != 0)
		nfs_release_seqid(data->o_arg.seqid);
2248 2249 2250 2251 2252 2253 2254 2255 2256 2257

	/* Set the create mode (note dependency on the session type) */
	data->o_arg.createmode = NFS4_CREATE_UNCHECKED;
	if (data->o_arg.open_flags & O_EXCL) {
		data->o_arg.createmode = NFS4_CREATE_EXCLUSIVE;
		if (nfs4_has_persistent_session(clp))
			data->o_arg.createmode = NFS4_CREATE_GUARDED;
		else if (clp->cl_mvops->minor_version > 0)
			data->o_arg.createmode = NFS4_CREATE_EXCLUSIVE4_1;
	}
2258
	return;
2259
unlock_no_action:
2260
	trace_nfs4_cached_open(data->state);
2261
	rcu_read_unlock();
2262 2263
out_no_action:
	task->tk_action = NULL;
2264
out_wait:
2265
	nfs4_sequence_done(task, &data->o_res.seq_res);
2266 2267
}

2268 2269 2270
static void nfs4_open_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;
L
Linus Torvalds 已提交
2271

2272
	data->rpc_status = task->tk_status;
2273

2274
	if (!nfs4_sequence_process(task, &data->o_res.seq_res))
2275
		return;
2276

2277
	if (task->tk_status == 0) {
2278 2279
		if (data->o_res.f_attr->valid & NFS_ATTR_FATTR_TYPE) {
			switch (data->o_res.f_attr->mode & S_IFMT) {
2280 2281 2282
			case S_IFREG:
				break;
			case S_IFLNK:
2283
				data->rpc_status = -ELOOP;
2284 2285
				break;
			case S_IFDIR:
2286
				data->rpc_status = -EISDIR;
2287 2288
				break;
			default:
2289
				data->rpc_status = -ENOTDIR;
2290
			}
2291
		}
2292
		renew_lease(data->o_res.server, data->timestamp);
2293 2294
		if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
			nfs_confirm_seqid(&data->owner->so_seqid, 0);
2295
	}
B
Benjamin Coddington 已提交
2296
	data->rpc_done = true;
2297
}
2298

2299 2300 2301 2302 2303 2304
static void nfs4_open_release(void *calldata)
{
	struct nfs4_opendata *data = calldata;
	struct nfs4_state *state = NULL;

	/* If this request hasn't been cancelled, do nothing */
B
Benjamin Coddington 已提交
2305
	if (!data->cancelled)
2306 2307
		goto out_free;
	/* In case of error, no cleanup! */
2308
	if (data->rpc_status != 0 || !data->rpc_done)
2309 2310 2311 2312 2313
		goto out_free;
	/* In case we need an open_confirm, no cleanup! */
	if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
		goto out_free;
	state = nfs4_opendata_to_nfs4_state(data);
2314
	if (!IS_ERR(state))
2315
		nfs4_close_state(state, data->o_arg.fmode);
2316
out_free:
2317
	nfs4_opendata_put(data);
2318 2319 2320 2321 2322 2323 2324 2325
}

static const struct rpc_call_ops nfs4_open_ops = {
	.rpc_call_prepare = nfs4_open_prepare,
	.rpc_call_done = nfs4_open_done,
	.rpc_release = nfs4_open_release,
};

2326
static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
2327
{
2328
	struct inode *dir = d_inode(data->dir);
2329 2330 2331 2332
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs_openargs *o_arg = &data->o_arg;
	struct nfs_openres *o_res = &data->o_res;
	struct rpc_task *task;
2333 2334 2335 2336 2337 2338
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
		.rpc_argp = o_arg,
		.rpc_resp = o_res,
		.rpc_cred = data->owner->so_cred,
	};
T
Trond Myklebust 已提交
2339 2340
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
2341
		.rpc_message = &msg,
T
Trond Myklebust 已提交
2342 2343
		.callback_ops = &nfs4_open_ops,
		.callback_data = data,
2344
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
2345 2346
		.flags = RPC_TASK_ASYNC,
	};
2347 2348
	int status;

2349
	nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
2350
	kref_get(&data->kref);
B
Benjamin Coddington 已提交
2351
	data->rpc_done = false;
2352
	data->rpc_status = 0;
B
Benjamin Coddington 已提交
2353 2354
	data->cancelled = false;
	data->is_recover = false;
2355
	if (isrecover) {
2356
		nfs4_set_sequence_privileged(&o_arg->seq_args);
B
Benjamin Coddington 已提交
2357
		data->is_recover = true;
2358
	}
T
Trond Myklebust 已提交
2359
	task = rpc_run_task(&task_setup_data);
2360 2361
	if (IS_ERR(task))
		return PTR_ERR(task);
2362
	status = rpc_wait_for_completion_task(task);
2363
	if (status != 0) {
B
Benjamin Coddington 已提交
2364
		data->cancelled = true;
2365 2366 2367 2368
		smp_wmb();
	} else
		status = data->rpc_status;
	rpc_put_task(task);
2369 2370 2371 2372 2373 2374

	return status;
}

static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
{
2375
	struct inode *dir = d_inode(data->dir);
2376
	struct nfs_openres *o_res = &data->o_res;
2377
	int status;
2378 2379 2380 2381 2382

	status = nfs4_run_open_task(data, 1);
	if (status != 0 || !data->rpc_done)
		return status;

2383 2384
	nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr);

2385
	if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM)
2386 2387 2388 2389 2390
		status = _nfs4_proc_open_confirm(data);

	return status;
}

2391 2392 2393 2394 2395 2396 2397 2398
/*
 * Additional permission checks in order to distinguish between an
 * open for read, and an open for execute. This works around the
 * fact that NFSv4 OPEN treats read and execute permissions as being
 * the same.
 * Note that in the non-execute case, we want to turn off permission
 * checking if we just created a new file (POSIX open() semantics).
 */
2399 2400
static int nfs4_opendata_access(struct rpc_cred *cred,
				struct nfs4_opendata *opendata,
2401 2402
				struct nfs4_state *state, fmode_t fmode,
				int openflags)
2403 2404
{
	struct nfs_access_entry cache;
2405
	u32 mask, flags;
2406 2407 2408 2409 2410 2411 2412

	/* access call failed or for some reason the server doesn't
	 * support any access modes -- defer access call until later */
	if (opendata->o_res.access_supported == 0)
		return 0;

	mask = 0;
2413 2414 2415 2416
	/*
	 * Use openflags to check for exec, because fmode won't
	 * always have FMODE_EXEC set when file open for exec.
	 */
2417 2418
	if (openflags & __FMODE_EXEC) {
		/* ONLY check for exec rights */
2419 2420 2421 2422
		if (S_ISDIR(state->inode->i_mode))
			mask = NFS4_ACCESS_LOOKUP;
		else
			mask = NFS4_ACCESS_EXECUTE;
2423
	} else if ((fmode & FMODE_READ) && !opendata->file_created)
2424
		mask = NFS4_ACCESS_READ;
2425 2426 2427 2428 2429

	cache.cred = cred;
	nfs_access_set_mask(&cache, opendata->o_res.access_result);
	nfs_access_add_cache(state->inode, &cache);

2430 2431
	flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP;
	if ((mask & ~cache.mask & flags) == 0)
2432 2433
		return 0;

2434
	return -EACCES;
2435 2436
}

2437 2438 2439 2440 2441
/*
 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
 */
static int _nfs4_proc_open(struct nfs4_opendata *data)
{
2442
	struct inode *dir = d_inode(data->dir);
2443 2444 2445 2446 2447 2448
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs_openargs *o_arg = &data->o_arg;
	struct nfs_openres *o_res = &data->o_res;
	int status;

	status = nfs4_run_open_task(data, 0);
2449 2450 2451 2452 2453 2454
	if (!data->rpc_done)
		return status;
	if (status != 0) {
		if (status == -NFS4ERR_BADNAME &&
				!(o_arg->open_flags & O_CREAT))
			return -ENOENT;
2455
		return status;
2456
	}
2457

2458 2459
	nfs_fattr_map_and_free_names(server, &data->f_attr);

2460 2461
	if (o_arg->open_flags & O_CREAT) {
		if (o_arg->open_flags & O_EXCL)
B
Benjamin Coddington 已提交
2462
			data->file_created = true;
2463
		else if (o_res->cinfo.before != o_res->cinfo.after)
B
Benjamin Coddington 已提交
2464
			data->file_created = true;
J
Jeff Layton 已提交
2465 2466
		if (data->file_created ||
		    inode_peek_iversion_raw(dir) != o_res->cinfo.after)
2467 2468
			update_changeattr(dir, &o_res->cinfo,
					o_res->f_attr->time_start);
2469
	}
T
Trond Myklebust 已提交
2470 2471
	if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
		server->caps &= ~NFS_CAP_POSIX_LOCK;
L
Linus Torvalds 已提交
2472
	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
2473
		status = _nfs4_proc_open_confirm(data);
L
Linus Torvalds 已提交
2474
		if (status != 0)
2475
			return status;
L
Linus Torvalds 已提交
2476
	}
2477 2478
	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) {
		nfs4_sequence_free_slot(&o_res->seq_res);
2479
		nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
2480
	}
2481
	return 0;
L
Linus Torvalds 已提交
2482 2483 2484 2485 2486 2487 2488
}

/*
 * OPEN_EXPIRED:
 * 	reclaim state on the server after a network partition.
 * 	Assumes caller holds the appropriate lock
 */
2489
static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
2490
{
2491
	struct nfs4_opendata *opendata;
2492
	int ret;
L
Linus Torvalds 已提交
2493

2494
	opendata = nfs4_open_recoverdata_alloc(ctx, state,
2495
			NFS4_OPEN_CLAIM_FH);
T
Trond Myklebust 已提交
2496 2497
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
2498
	ret = nfs4_open_recover(opendata, state);
2499
	if (ret == -ESTALE)
2500
		d_drop(ctx->dentry);
2501
	nfs4_opendata_put(opendata);
2502
	return ret;
L
Linus Torvalds 已提交
2503 2504
}

2505
static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
2506
{
2507
	struct nfs_server *server = NFS_SERVER(state->inode);
2508 2509 2510 2511
	struct nfs4_exception exception = { };
	int err;

	do {
2512
		err = _nfs4_open_expired(ctx, state);
2513
		trace_nfs4_open_expired(ctx, 0, err);
2514 2515
		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
			continue;
2516 2517 2518 2519 2520 2521 2522 2523
		switch (err) {
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
2524
	} while (exception.retry);
2525
out:
2526 2527 2528
	return err;
}

L
Linus Torvalds 已提交
2529 2530 2531
static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
	struct nfs_open_context *ctx;
2532
	int ret;
L
Linus Torvalds 已提交
2533

2534 2535
	ctx = nfs4_state_find_open_context(state);
	if (IS_ERR(ctx))
2536
		return -EAGAIN;
2537
	ret = nfs4_do_open_expired(ctx, state);
2538 2539
	put_nfs_open_context(ctx);
	return ret;
L
Linus Torvalds 已提交
2540 2541
}

2542 2543
static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state,
		const nfs4_stateid *stateid)
2544
{
2545
	nfs_remove_bad_delegation(state->inode, stateid);
2546 2547 2548 2549 2550 2551 2552 2553 2554
	write_seqlock(&state->seqlock);
	nfs4_stateid_copy(&state->stateid, &state->open_stateid);
	write_sequnlock(&state->seqlock);
	clear_bit(NFS_DELEGATED_STATE, &state->flags);
}

static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
{
	if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
2555
		nfs_finish_clear_delegation_stateid(state, NULL);
2556 2557 2558 2559 2560 2561 2562 2563 2564
}

static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
	/* NFSv4.0 doesn't allow for delegation recovery on open expire */
	nfs40_clear_delegation_stateid(state);
	return nfs4_open_expired(sp, state);
}

2565 2566 2567 2568 2569 2570 2571
static int nfs40_test_and_free_expired_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	return -NFS4ERR_BAD_STATEID;
}

2572
#if defined(CONFIG_NFS_V4_1)
2573 2574 2575 2576 2577 2578
static int nfs41_test_and_free_expired_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	int status;

2579 2580 2581 2582 2583 2584 2585 2586 2587
	switch (stateid->type) {
	default:
		break;
	case NFS4_INVALID_STATEID_TYPE:
	case NFS4_SPECIAL_STATEID_TYPE:
		return -NFS4ERR_BAD_STATEID;
	case NFS4_REVOKED_STATEID_TYPE:
		goto out_free;
	}
2588

2589
	status = nfs41_test_stateid(server, stateid, cred);
2590 2591 2592 2593
	switch (status) {
	case -NFS4ERR_EXPIRED:
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_DELEG_REVOKED:
2594 2595
		break;
	default:
2596 2597
		return status;
	}
2598 2599
out_free:
	/* Ack the revoked state to the server */
2600
	nfs41_free_stateid(server, stateid, cred, true);
2601
	return -NFS4ERR_EXPIRED;
2602 2603
}

2604
static void nfs41_check_delegation_stateid(struct nfs4_state *state)
2605 2606
{
	struct nfs_server *server = NFS_SERVER(state->inode);
2607
	nfs4_stateid stateid;
2608
	struct nfs_delegation *delegation;
2609 2610
	struct rpc_cred *cred;
	int status;
2611

2612 2613 2614
	/* Get the delegation credential for use by test/free_stateid */
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
2615
	if (delegation == NULL) {
2616
		rcu_read_unlock();
2617 2618 2619 2620
		return;
	}

	nfs4_stateid_copy(&stateid, &delegation->stateid);
2621 2622 2623
	if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) ||
		!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
			&delegation->flags)) {
2624
		rcu_read_unlock();
2625
		nfs_finish_clear_delegation_stateid(state, &stateid);
2626 2627
		return;
	}
2628 2629 2630

	cred = get_rpccred(delegation->cred);
	rcu_read_unlock();
2631
	status = nfs41_test_and_free_expired_stateid(server, &stateid, cred);
2632
	trace_nfs4_test_delegation_stateid(state, NULL, status);
2633
	if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
2634
		nfs_finish_clear_delegation_stateid(state, &stateid);
2635

2636
	put_rpccred(cred);
2637 2638
}

2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649
/**
 * nfs41_check_expired_locks - possibly free a lock stateid
 *
 * @state: NFSv4 state for an inode
 *
 * Returns NFS_OK if recovery for this stateid is now finished.
 * Otherwise a negative NFS4ERR value is returned.
 */
static int nfs41_check_expired_locks(struct nfs4_state *state)
{
	int status, ret = NFS_OK;
2650
	struct nfs4_lock_state *lsp, *prev = NULL;
2651 2652 2653 2654
	struct nfs_server *server = NFS_SERVER(state->inode);

	if (!test_bit(LK_STATE_IN_USE, &state->flags))
		goto out;
2655 2656

	spin_lock(&state->state_lock);
2657 2658 2659 2660
	list_for_each_entry(lsp, &state->lock_states, ls_locks) {
		if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
			struct rpc_cred *cred = lsp->ls_state->owner->so_cred;

2661
			refcount_inc(&lsp->ls_count);
2662 2663 2664 2665 2666
			spin_unlock(&state->state_lock);

			nfs4_put_lock_state(prev);
			prev = lsp;

2667 2668 2669 2670 2671 2672 2673
			status = nfs41_test_and_free_expired_stateid(server,
					&lsp->ls_stateid,
					cred);
			trace_nfs4_test_lock_stateid(state, lsp, status);
			if (status == -NFS4ERR_EXPIRED ||
			    status == -NFS4ERR_BAD_STATEID) {
				clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
2674
				lsp->ls_stateid.type = NFS4_INVALID_STATEID_TYPE;
2675 2676 2677 2678
				if (!recover_lost_locks)
					set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
			} else if (status != NFS_OK) {
				ret = status;
2679 2680
				nfs4_put_lock_state(prev);
				goto out;
2681
			}
2682
			spin_lock(&state->state_lock);
2683
		}
2684 2685 2686
	}
	spin_unlock(&state->state_lock);
	nfs4_put_lock_state(prev);
2687 2688 2689 2690
out:
	return ret;
}

2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701
/**
 * nfs41_check_open_stateid - possibly free an open stateid
 *
 * @state: NFSv4 state for an inode
 *
 * Returns NFS_OK if recovery for this stateid is now finished.
 * Otherwise a negative NFS4ERR value is returned.
 */
static int nfs41_check_open_stateid(struct nfs4_state *state)
{
	struct nfs_server *server = NFS_SERVER(state->inode);
2702
	nfs4_stateid *stateid = &state->open_stateid;
2703
	struct rpc_cred *cred = state->owner->so_cred;
2704 2705
	int status;

2706
	if (test_bit(NFS_OPEN_STATE, &state->flags) == 0) {
2707 2708 2709 2710 2711
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)  {
			if (nfs4_have_delegation(state->inode, state->state))
				return NFS_OK;
			return -NFS4ERR_OPENMODE;
		}
2712
		return -NFS4ERR_BAD_STATEID;
2713
	}
2714
	status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
2715
	trace_nfs4_test_open_stateid(state, NULL, status);
2716
	if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) {
2717 2718 2719
		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
		clear_bit(NFS_O_RDWR_STATE, &state->flags);
2720
		clear_bit(NFS_OPEN_STATE, &state->flags);
2721
		stateid->type = NFS4_INVALID_STATEID_TYPE;
2722
		return status;
2723
	}
2724 2725 2726
	if (nfs_open_stateid_recover_openmode(state))
		return -NFS4ERR_OPENMODE;
	return NFS_OK;
2727 2728 2729 2730
}

static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
2731
	int status;
2732

2733
	nfs41_check_delegation_stateid(state);
2734 2735 2736
	status = nfs41_check_expired_locks(state);
	if (status != NFS_OK)
		return status;
2737
	status = nfs41_check_open_stateid(state);
2738 2739 2740
	if (status != NFS_OK)
		status = nfs4_open_expired(sp, state);
	return status;
2741 2742 2743
}
#endif

2744 2745 2746 2747 2748
/*
 * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
 * fields corresponding to attributes that were used to store the verifier.
 * Make sure we clobber those fields in the later setattr call
 */
2749 2750
static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
				struct iattr *sattr, struct nfs4_label **label)
2751
{
2752 2753 2754
	const u32 *attrset = opendata->o_res.attrset;

	if ((attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
2755 2756 2757
	    !(sattr->ia_valid & ATTR_ATIME_SET))
		sattr->ia_valid |= ATTR_ATIME;

2758
	if ((attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
2759 2760
	    !(sattr->ia_valid & ATTR_MTIME_SET))
		sattr->ia_valid |= ATTR_MTIME;
2761 2762

	/* Except MODE, it seems harmless of setting twice. */
2763
	if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
2764 2765
		(attrset[1] & FATTR4_WORD1_MODE ||
		 attrset[2] & FATTR4_WORD2_MODE_UMASK))
2766 2767 2768 2769
		sattr->ia_valid &= ~ATTR_MODE;

	if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
		*label = NULL;
2770 2771
}

2772 2773 2774
static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
		fmode_t fmode,
		int flags,
2775
		struct nfs_open_context *ctx)
2776 2777 2778
{
	struct nfs4_state_owner *sp = opendata->owner;
	struct nfs_server *server = sp->so_server;
2779
	struct dentry *dentry;
2780 2781 2782 2783 2784 2785 2786
	struct nfs4_state *state;
	unsigned int seq;
	int ret;

	seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);

	ret = _nfs4_proc_open(opendata);
2787
	if (ret != 0)
2788 2789 2790 2791 2792 2793
		goto out;

	state = nfs4_opendata_to_nfs4_state(opendata);
	ret = PTR_ERR(state);
	if (IS_ERR(state))
		goto out;
2794
	ctx->state = state;
2795 2796
	if (server->caps & NFS_CAP_POSIX_LOCK)
		set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
2797 2798
	if (opendata->o_res.rflags & NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK)
		set_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags);
2799

2800
	dentry = opendata->dentry;
2801
	if (d_really_is_negative(dentry)) {
2802
		struct dentry *alias;
2803
		d_drop(dentry);
2804 2805 2806 2807 2808
		alias = d_exact_alias(dentry, state->inode);
		if (!alias)
			alias = d_splice_alias(igrab(state->inode), dentry);
		/* d_splice_alias() can't fail here - it's a non-directory */
		if (alias) {
2809
			dput(ctx->dentry);
2810
			ctx->dentry = dentry = alias;
2811 2812
		}
		nfs_set_verifier(dentry,
2813
				nfs_save_change_attribute(d_inode(opendata->dir)));
2814 2815
	}

2816 2817 2818 2819
	ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags);
	if (ret != 0)
		goto out;

2820
	if (d_inode(dentry) == state->inode) {
2821 2822 2823 2824
		nfs_inode_attach_open_context(ctx);
		if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
			nfs4_schedule_stateid_recovery(server, state);
	}
2825 2826 2827 2828
out:
	return ret;
}

L
Linus Torvalds 已提交
2829
/*
2830
 * Returns a referenced nfs4_state
L
Linus Torvalds 已提交
2831
 */
2832
static int _nfs4_do_open(struct inode *dir,
2833
			struct nfs_open_context *ctx,
2834
			int flags,
2835
			const struct nfs4_open_createattrs *c,
2836
			int *opened)
L
Linus Torvalds 已提交
2837 2838 2839 2840
{
	struct nfs4_state_owner  *sp;
	struct nfs4_state     *state = NULL;
	struct nfs_server       *server = NFS_SERVER(dir);
2841
	struct nfs4_opendata *opendata;
2842 2843 2844 2845
	struct dentry *dentry = ctx->dentry;
	struct rpc_cred *cred = ctx->cred;
	struct nfs4_threshold **ctx_th = &ctx->mdsthreshold;
	fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC);
2846
	enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL;
2847 2848
	struct iattr *sattr = c->sattr;
	struct nfs4_label *label = c->label;
2849
	struct nfs4_label *olabel = NULL;
2850
	int status;
L
Linus Torvalds 已提交
2851 2852 2853

	/* Protect against reboot recovery conflicts */
	status = -ENOMEM;
2854 2855
	sp = nfs4_get_state_owner(server, cred, GFP_KERNEL);
	if (sp == NULL) {
L
Linus Torvalds 已提交
2856 2857 2858
		dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
		goto out_err;
	}
2859
	status = nfs4_client_recover_expired_lease(server->nfs_client);
2860
	if (status != 0)
2861
		goto err_put_state_owner;
2862 2863
	if (d_really_is_positive(dentry))
		nfs4_return_incompatible_delegation(d_inode(dentry), fmode);
2864
	status = -ENOMEM;
2865
	if (d_really_is_positive(dentry))
2866
		claim = NFS4_OPEN_CLAIM_FH;
2867 2868
	opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags,
			c, claim, GFP_KERNEL);
2869
	if (opendata == NULL)
T
Trond Myklebust 已提交
2870
		goto err_put_state_owner;
L
Linus Torvalds 已提交
2871

2872 2873 2874 2875 2876 2877 2878 2879
	if (label) {
		olabel = nfs4_label_alloc(server, GFP_KERNEL);
		if (IS_ERR(olabel)) {
			status = PTR_ERR(olabel);
			goto err_opendata_put;
		}
	}

2880 2881 2882 2883 2884 2885
	if (server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
		if (!opendata->f_attr.mdsthreshold) {
			opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
			if (!opendata->f_attr.mdsthreshold)
				goto err_free_label;
		}
2886
		opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
2887
	}
2888 2889
	if (d_really_is_positive(dentry))
		opendata->state = nfs4_get_open_state(d_inode(dentry), sp);
2890

2891
	status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx);
2892
	if (status != 0)
2893
		goto err_free_label;
2894
	state = ctx->state;
2895

2896
	if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) &&
2897
	    (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
2898
		nfs4_exclusive_attrset(opendata, sattr, &label);
2899 2900 2901 2902 2903 2904 2905 2906
		/*
		 * send create attributes which was not set by open
		 * with an extra setattr.
		 */
		if (sattr->ia_valid & NFS4_VALID_ATTRS) {
			nfs_fattr_init(opendata->o_res.f_attr);
			status = nfs4_do_setattr(state->inode, cred,
					opendata->o_res.f_attr, sattr,
2907
					ctx, label, olabel);
2908 2909 2910 2911 2912
			if (status == 0) {
				nfs_setattr_update_inode(state->inode, sattr,
						opendata->o_res.f_attr);
				nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
			}
2913
		}
2914
	}
2915
	if (opened && opendata->file_created)
2916
		*opened |= FILE_CREATED;
2917

2918
	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) {
2919
		*ctx_th = opendata->f_attr.mdsthreshold;
2920 2921
		opendata->f_attr.mdsthreshold = NULL;
	}
2922

2923 2924
	nfs4_label_free(olabel);

2925
	nfs4_opendata_put(opendata);
L
Linus Torvalds 已提交
2926 2927
	nfs4_put_state_owner(sp);
	return 0;
2928 2929
err_free_label:
	nfs4_label_free(olabel);
2930 2931
err_opendata_put:
	nfs4_opendata_put(opendata);
2932 2933
err_put_state_owner:
	nfs4_put_state_owner(sp);
L
Linus Torvalds 已提交
2934 2935 2936 2937 2938
out_err:
	return status;
}


2939
static struct nfs4_state *nfs4_do_open(struct inode *dir,
2940
					struct nfs_open_context *ctx,
2941 2942
					int flags,
					struct iattr *sattr,
2943 2944
					struct nfs4_label *label,
					int *opened)
L
Linus Torvalds 已提交
2945
{
2946
	struct nfs_server *server = NFS_SERVER(dir);
L
Linus Torvalds 已提交
2947 2948
	struct nfs4_exception exception = { };
	struct nfs4_state *res;
2949 2950 2951 2952 2953 2954 2955 2956
	struct nfs4_open_createattrs c = {
		.label = label,
		.sattr = sattr,
		.verf = {
			[0] = (__u32)jiffies,
			[1] = (__u32)current->pid,
		},
	};
L
Linus Torvalds 已提交
2957 2958 2959
	int status;

	do {
2960
		status = _nfs4_do_open(dir, ctx, flags, &c, opened);
2961
		res = ctx->state;
2962
		trace_nfs4_open_file(ctx, flags, status);
L
Linus Torvalds 已提交
2963 2964 2965 2966 2967 2968 2969 2970
		if (status == 0)
			break;
		/* NOTE: BAD_SEQID means the server and client disagree about the
		 * book-keeping w.r.t. state-changing operations
		 * (OPEN/CLOSE/LOCK/LOCKU...)
		 * It is actually a sign of a bug on the client or on the server.
		 *
		 * If we receive a BAD_SEQID error in the particular case of
2971
		 * doing an OPEN, we assume that nfs_increment_open_seqid() will
L
Linus Torvalds 已提交
2972 2973 2974 2975 2976
		 * have unhashed the old state_owner for us, and that we can
		 * therefore safely retry using a new one. We should still warn
		 * the user though...
		 */
		if (status == -NFS4ERR_BAD_SEQID) {
2977
			pr_warn_ratelimited("NFS: v4 server %s "
2978 2979
					" returned a bad sequence-id error!\n",
					NFS_SERVER(dir)->nfs_client->cl_hostname);
L
Linus Torvalds 已提交
2980 2981 2982
			exception.retry = 1;
			continue;
		}
2983 2984 2985 2986 2987 2988 2989 2990 2991 2992
		/*
		 * BAD_STATEID on OPEN means that the server cancelled our
		 * state before it received the OPEN_CONFIRM.
		 * Recover by retrying the request as per the discussion
		 * on Page 181 of RFC3530.
		 */
		if (status == -NFS4ERR_BAD_STATEID) {
			exception.retry = 1;
			continue;
		}
2993 2994 2995 2996 2997
		if (status == -EAGAIN) {
			/* We must have found a delegation */
			exception.retry = 1;
			continue;
		}
2998 2999 3000
		if (nfs4_clear_cap_atomic_open_v1(server, status, &exception))
			continue;
		res = ERR_PTR(nfs4_handle_exception(server,
L
Linus Torvalds 已提交
3001 3002 3003 3004 3005
					status, &exception));
	} while (exception.retry);
	return res;
}

3006 3007 3008 3009
static int _nfs4_do_setattr(struct inode *inode,
			    struct nfs_setattrargs *arg,
			    struct nfs_setattrres *res,
			    struct rpc_cred *cred,
3010
			    struct nfs_open_context *ctx)
L
Linus Torvalds 已提交
3011
{
3012
	struct nfs_server *server = NFS_SERVER(inode);
3013
	struct rpc_message msg = {
3014
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
3015 3016
		.rpc_argp	= arg,
		.rpc_resp	= res,
3017
		.rpc_cred	= cred,
3018
	};
3019
	struct rpc_cred *delegation_cred = NULL;
3020
	unsigned long timestamp = jiffies;
3021 3022
	fmode_t fmode;
	bool truncate;
3023
	int status;
L
Linus Torvalds 已提交
3024

3025
	nfs_fattr_init(res->fattr);
L
Linus Torvalds 已提交
3026

3027
	/* Servers should only apply open mode checks for file size changes */
3028
	truncate = (arg->iap->ia_valid & ATTR_SIZE) ? true : false;
3029 3030
	fmode = truncate ? FMODE_WRITE : FMODE_READ;

3031
	if (nfs4_copy_delegation_stateid(inode, fmode, &arg->stateid, &delegation_cred)) {
3032
		/* Use that stateid */
3033
	} else if (truncate && ctx != NULL) {
3034
		struct nfs_lock_context *l_ctx;
3035
		if (!nfs4_valid_open_stateid(ctx->state))
3036
			return -EBADF;
3037 3038 3039
		l_ctx = nfs_get_lock_context(ctx);
		if (IS_ERR(l_ctx))
			return PTR_ERR(l_ctx);
3040 3041 3042 3043
		status = nfs4_select_rw_stateid(ctx->state, FMODE_WRITE, l_ctx,
						&arg->stateid, &delegation_cred);
		nfs_put_lock_context(l_ctx);
		if (status == -EIO)
3044
			return -EBADF;
3045
	} else
3046
		nfs4_stateid_copy(&arg->stateid, &zero_stateid);
3047 3048
	if (delegation_cred)
		msg.rpc_cred = delegation_cred;
L
Linus Torvalds 已提交
3049

3050
	status = nfs4_call_sync(server->client, server, &msg, &arg->seq_args, &res->seq_res, 1);
3051 3052

	put_rpccred(delegation_cred);
3053
	if (status == 0 && ctx != NULL)
3054
		renew_lease(server, timestamp);
3055
	trace_nfs4_setattr(inode, &arg->stateid, status);
3056
	return status;
L
Linus Torvalds 已提交
3057 3058
}

3059 3060
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			   struct nfs_fattr *fattr, struct iattr *sattr,
3061
			   struct nfs_open_context *ctx, struct nfs4_label *ilabel,
3062
			   struct nfs4_label *olabel)
L
Linus Torvalds 已提交
3063
{
3064
	struct nfs_server *server = NFS_SERVER(inode);
3065
	struct nfs4_state *state = ctx ? ctx->state : NULL;
3066 3067 3068
	struct nfs_setattrargs	arg = {
		.fh		= NFS_FH(inode),
		.iap		= sattr,
3069 3070 3071
		.server		= server,
		.bitmask = server->attr_bitmask,
		.label		= ilabel,
3072 3073
	};
	struct nfs_setattrres  res = {
3074 3075 3076
		.fattr		= fattr,
		.label		= olabel,
		.server		= server,
3077
	};
3078 3079
	struct nfs4_exception exception = {
		.state = state,
3080
		.inode = inode,
3081
		.stateid = &arg.stateid,
3082
	};
L
Linus Torvalds 已提交
3083
	int err;
3084 3085 3086 3087 3088

	arg.bitmask = nfs4_bitmask(server, ilabel);
	if (ilabel)
		arg.bitmask = nfs4_bitmask(server, olabel);

L
Linus Torvalds 已提交
3089
	do {
3090
		err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx);
3091 3092
		switch (err) {
		case -NFS4ERR_OPENMODE:
3093 3094 3095 3096 3097 3098 3099
			if (!(sattr->ia_valid & ATTR_SIZE)) {
				pr_warn_once("NFSv4: server %s is incorrectly "
						"applying open mode checks to "
						"a SETATTR that is not "
						"changing file size.\n",
						server->nfs_client->cl_hostname);
			}
3100 3101 3102 3103 3104 3105 3106 3107
			if (state && !(state->state & FMODE_WRITE)) {
				err = -EBADF;
				if (sattr->ia_valid & ATTR_OPEN)
					err = -EACCES;
				goto out;
			}
		}
		err = nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
3108
	} while (exception.retry);
3109
out:
L
Linus Torvalds 已提交
3110 3111 3112
	return err;
}

3113 3114 3115 3116 3117 3118 3119 3120 3121
static bool
nfs4_wait_on_layoutreturn(struct inode *inode, struct rpc_task *task)
{
	if (inode == NULL || !nfs_have_layout(inode))
		return false;

	return pnfs_wait_on_layoutreturn(inode, task);
}

L
Linus Torvalds 已提交
3122 3123 3124 3125 3126
struct nfs4_closedata {
	struct inode *inode;
	struct nfs4_state *state;
	struct nfs_closeargs arg;
	struct nfs_closeres res;
3127 3128 3129
	struct {
		struct nfs4_layoutreturn_args arg;
		struct nfs4_layoutreturn_res res;
3130
		struct nfs4_xdr_opaque_data ld_private;
3131 3132 3133
		u32 roc_barrier;
		bool roc;
	} lr;
3134
	struct nfs_fattr fattr;
3135
	unsigned long timestamp;
L
Linus Torvalds 已提交
3136 3137
};

3138
static void nfs4_free_closedata(void *data)
3139
{
3140 3141
	struct nfs4_closedata *calldata = data;
	struct nfs4_state_owner *sp = calldata->state->owner;
3142
	struct super_block *sb = calldata->state->inode->i_sb;
3143

3144
	if (calldata->lr.roc)
3145 3146
		pnfs_roc_release(&calldata->lr.arg, &calldata->lr.res,
				calldata->res.lr_ret);
3147 3148 3149
	nfs4_put_open_state(calldata->state);
	nfs_free_seqid(calldata->arg.seqid);
	nfs4_put_state_owner(sp);
3150
	nfs_sb_deactive(sb);
3151 3152 3153
	kfree(calldata);
}

3154
static void nfs4_close_done(struct rpc_task *task, void *data)
L
Linus Torvalds 已提交
3155
{
3156
	struct nfs4_closedata *calldata = data;
L
Linus Torvalds 已提交
3157 3158
	struct nfs4_state *state = calldata->state;
	struct nfs_server *server = NFS_SERVER(calldata->inode);
3159
	nfs4_stateid *res_stateid = NULL;
3160 3161 3162 3163 3164
	struct nfs4_exception exception = {
		.state = state,
		.inode = calldata->inode,
		.stateid = &calldata->arg.stateid,
	};
L
Linus Torvalds 已提交
3165

3166
	dprintk("%s: begin!\n", __func__);
3167 3168
	if (!nfs4_sequence_done(task, &calldata->res.seq_res))
		return;
3169
	trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status);
3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180

	/* Handle Layoutreturn errors */
	if (calldata->arg.lr_args && task->tk_status != 0) {
		switch (calldata->res.lr_ret) {
		default:
			calldata->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
			break;
		case 0:
			calldata->arg.lr_args = NULL;
			calldata->res.lr_res = NULL;
			break;
3181 3182
		case -NFS4ERR_OLD_STATEID:
			if (nfs4_refresh_layout_stateid(&calldata->arg.lr_args->stateid,
T
Trond Myklebust 已提交
3183 3184
						calldata->inode))
				goto lr_restart;
3185
			/* Fallthrough */
3186 3187 3188 3189 3190 3191 3192 3193
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_EXPIRED:
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
		case -NFS4ERR_WRONG_CRED:
			calldata->arg.lr_args = NULL;
			calldata->res.lr_res = NULL;
T
Trond Myklebust 已提交
3194
			goto lr_restart;
3195 3196 3197
		}
	}

3198
	/* hmm. we are done with the inode, and in the process of freeing
L
Linus Torvalds 已提交
3199 3200 3201 3202
	 * the state_owner. we keep this around to process errors
	 */
	switch (task->tk_status) {
		case 0:
3203
			res_stateid = &calldata->res.stateid;
3204
			renew_lease(server, calldata->timestamp);
3205
			break;
3206 3207 3208 3209
		case -NFS4ERR_ACCESS:
			if (calldata->arg.bitmask != NULL) {
				calldata->arg.bitmask = NULL;
				calldata->res.fattr = NULL;
T
Trond Myklebust 已提交
3210
				goto out_restart;
3211 3212 3213

			}
			break;
3214 3215 3216
		case -NFS4ERR_OLD_STATEID:
			/* Did we race with OPEN? */
			if (nfs4_refresh_open_stateid(&calldata->arg.stateid,
T
Trond Myklebust 已提交
3217 3218
						state))
				goto out_restart;
3219
			goto out_release;
3220
		case -NFS4ERR_ADMIN_REVOKED:
L
Linus Torvalds 已提交
3221
		case -NFS4ERR_STALE_STATEID:
3222 3223 3224 3225
		case -NFS4ERR_EXPIRED:
			nfs4_free_revoked_stateid(server,
					&calldata->arg.stateid,
					task->tk_msg.rpc_cred);
3226
			/* Fallthrough */
3227
		case -NFS4ERR_BAD_STATEID:
3228
			break;
L
Linus Torvalds 已提交
3229
		default:
3230 3231 3232
			task->tk_status = nfs4_async_handle_exception(task,
					server, task->tk_status, &exception);
			if (exception.retry)
T
Trond Myklebust 已提交
3233
				goto out_restart;
L
Linus Torvalds 已提交
3234
	}
3235 3236
	nfs_clear_open_stateid(state, &calldata->arg.stateid,
			res_stateid, calldata->arg.fmode);
3237
out_release:
T
Trond Myklebust 已提交
3238
	task->tk_status = 0;
3239
	nfs_release_seqid(calldata->arg.seqid);
3240
	nfs_refresh_inode(calldata->inode, &calldata->fattr);
3241
	dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
T
Trond Myklebust 已提交
3242 3243 3244 3245 3246 3247 3248
	return;
lr_restart:
	calldata->res.lr_ret = 0;
out_restart:
	task->tk_status = 0;
	rpc_restart_call_prepare(task);
	goto out_release;
L
Linus Torvalds 已提交
3249 3250
}

T
Trond Myklebust 已提交
3251
static void nfs4_close_prepare(struct rpc_task *task, void *data)
L
Linus Torvalds 已提交
3252
{
T
Trond Myklebust 已提交
3253
	struct nfs4_closedata *calldata = data;
3254
	struct nfs4_state *state = calldata->state;
3255
	struct inode *inode = calldata->inode;
3256
	bool is_rdonly, is_wronly, is_rdwr;
3257
	int call_close = 0;
3258

3259
	dprintk("%s: begin!\n", __func__);
3260
	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
3261
		goto out_wait;
3262

3263
	task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
3264
	spin_lock(&state->owner->so_lock);
3265 3266 3267
	is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
	is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
	is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
3268
	/* Calculate the change in open mode */
3269
	calldata->arg.fmode = 0;
3270
	if (state->n_rdwr == 0) {
3271 3272 3273 3274 3275 3276 3277 3278
		if (state->n_rdonly == 0)
			call_close |= is_rdonly;
		else if (is_rdonly)
			calldata->arg.fmode |= FMODE_READ;
		if (state->n_wronly == 0)
			call_close |= is_wronly;
		else if (is_wronly)
			calldata->arg.fmode |= FMODE_WRITE;
3279 3280
		if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
			call_close |= is_rdwr;
3281 3282 3283
	} else if (is_rdwr)
		calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;

3284
	if (!nfs4_valid_open_stateid(state) ||
3285
	    !nfs4_refresh_open_stateid(&calldata->arg.stateid, state))
3286
		call_close = 0;
3287
	spin_unlock(&state->owner->so_lock);
3288 3289

	if (!call_close) {
3290
		/* Note: exit _without_ calling nfs4_close_done */
3291
		goto out_no_action;
3292
	}
3293

3294
	if (!calldata->lr.roc && nfs4_wait_on_layoutreturn(inode, task)) {
3295 3296 3297 3298
		nfs_release_seqid(calldata->arg.seqid);
		goto out_wait;
	}

3299
	if (calldata->arg.fmode == 0)
3300
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
3301

3302
	if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) {
3303 3304 3305 3306 3307 3308
		/* Close-to-open cache consistency revalidation */
		if (!nfs4_have_delegation(inode, FMODE_READ))
			calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
		else
			calldata->arg.bitmask = NULL;
	}
3309

3310 3311 3312
	calldata->arg.share_access =
		nfs4_map_atomic_open_share(NFS_SERVER(inode),
				calldata->arg.fmode, 0);
3313

3314 3315 3316 3317
	if (calldata->res.fattr == NULL)
		calldata->arg.bitmask = NULL;
	else if (calldata->arg.bitmask == NULL)
		calldata->res.fattr = NULL;
3318
	calldata->timestamp = jiffies;
3319
	if (nfs4_setup_sequence(NFS_SERVER(inode)->nfs_client,
3320 3321
				&calldata->arg.seq_args,
				&calldata->res.seq_res,
3322 3323
				task) != 0)
		nfs_release_seqid(calldata->arg.seqid);
3324
	dprintk("%s: done!\n", __func__);
3325 3326 3327 3328 3329
	return;
out_no_action:
	task->tk_action = NULL;
out_wait:
	nfs4_sequence_done(task, &calldata->res.seq_res);
L
Linus Torvalds 已提交
3330 3331
}

3332
static const struct rpc_call_ops nfs4_close_ops = {
T
Trond Myklebust 已提交
3333
	.rpc_call_prepare = nfs4_close_prepare,
3334 3335 3336 3337
	.rpc_call_done = nfs4_close_done,
	.rpc_release = nfs4_free_closedata,
};

L
Linus Torvalds 已提交
3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348
/* 
 * It is possible for data to be read/written from a mem-mapped file 
 * after the sys_close call (which hits the vfs layer as a flush).
 * This means that we can't safely call nfsv4 close on a file until 
 * the inode is cleared. This in turn means that we are not good
 * NFSv4 citizens - we do not indicate to the server to update the file's 
 * share state even when we are done with one of the three share 
 * stateid's in the inode.
 *
 * NOTE: Caller must be holding the sp->so_owner semaphore!
 */
3349
int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
L
Linus Torvalds 已提交
3350
{
3351
	struct nfs_server *server = NFS_SERVER(state->inode);
3352
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
L
Linus Torvalds 已提交
3353
	struct nfs4_closedata *calldata;
3354 3355
	struct nfs4_state_owner *sp = state->owner;
	struct rpc_task *task;
3356 3357 3358 3359
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
		.rpc_cred = state->owner->so_cred,
	};
T
Trond Myklebust 已提交
3360 3361
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
3362
		.rpc_message = &msg,
T
Trond Myklebust 已提交
3363
		.callback_ops = &nfs4_close_ops,
3364
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
3365 3366
		.flags = RPC_TASK_ASYNC,
	};
3367
	int status = -ENOMEM;
L
Linus Torvalds 已提交
3368

3369 3370 3371
	nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_CLEANUP,
		&task_setup_data.rpc_client, &msg);

3372
	calldata = kzalloc(sizeof(*calldata), gfp_mask);
L
Linus Torvalds 已提交
3373
	if (calldata == NULL)
3374
		goto out;
3375
	nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1);
3376
	calldata->inode = state->inode;
L
Linus Torvalds 已提交
3377
	calldata->state = state;
3378
	calldata->arg.fh = NFS_FH(state->inode);
3379 3380
	if (!nfs4_copy_open_stateid(&calldata->arg.stateid, state))
		goto out_free_calldata;
L
Linus Torvalds 已提交
3381
	/* Serialization for the sequence id */
3382 3383
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask);
3384
	if (IS_ERR(calldata->arg.seqid))
3385
		goto out_free_calldata;
3386
	nfs_fattr_init(&calldata->fattr);
3387
	calldata->arg.fmode = 0;
3388
	calldata->lr.arg.ld_private = &calldata->lr.ld_private;
3389
	calldata->res.fattr = &calldata->fattr;
3390
	calldata->res.seqid = calldata->arg.seqid;
3391
	calldata->res.server = server;
3392
	calldata->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
3393 3394 3395 3396 3397 3398
	calldata->lr.roc = pnfs_roc(state->inode,
			&calldata->lr.arg, &calldata->lr.res, msg.rpc_cred);
	if (calldata->lr.roc) {
		calldata->arg.lr_args = &calldata->lr.arg;
		calldata->res.lr_res = &calldata->lr.res;
	}
3399
	nfs_sb_active(calldata->inode->i_sb);
3400

3401 3402
	msg.rpc_argp = &calldata->arg;
	msg.rpc_resp = &calldata->res;
T
Trond Myklebust 已提交
3403 3404
	task_setup_data.callback_data = calldata;
	task = rpc_run_task(&task_setup_data);
3405 3406
	if (IS_ERR(task))
		return PTR_ERR(task);
3407 3408 3409
	status = 0;
	if (wait)
		status = rpc_wait_for_completion_task(task);
3410
	rpc_put_task(task);
3411
	return status;
3412 3413 3414
out_free_calldata:
	kfree(calldata);
out:
3415 3416
	nfs4_put_open_state(state);
	nfs4_put_state_owner(sp);
3417
	return status;
L
Linus Torvalds 已提交
3418 3419
}

3420
static struct inode *
3421 3422
nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
		int open_flags, struct iattr *attr, int *opened)
L
Linus Torvalds 已提交
3423 3424
{
	struct nfs4_state *state;
3425 3426 3427
	struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;

	label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);
L
Linus Torvalds 已提交
3428

T
Trond Myklebust 已提交
3429
	/* Protect against concurrent sillydeletes */
3430
	state = nfs4_do_open(dir, ctx, open_flags, attr, label, opened);
3431 3432 3433

	nfs4_label_release_security(label);

3434 3435
	if (IS_ERR(state))
		return ERR_CAST(state);
3436
	return state->inode;
L
Linus Torvalds 已提交
3437 3438
}

3439
static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
T
Trond Myklebust 已提交
3440 3441 3442 3443
{
	if (ctx->state == NULL)
		return;
	if (is_sync)
3444
		nfs4_close_sync(ctx->state, ctx->mode);
T
Trond Myklebust 已提交
3445
	else
3446
		nfs4_close_state(ctx->state, ctx->mode);
T
Trond Myklebust 已提交
3447
}
L
Linus Torvalds 已提交
3448

3449 3450
#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL)
#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL)
3451
#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_MODE_UMASK - 1UL)
3452

L
Linus Torvalds 已提交
3453 3454
static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
3455
	u32 bitmask[3] = {}, minorversion = server->nfs_client->cl_minorversion;
B
Benny Halevy 已提交
3456 3457
	struct nfs4_server_caps_arg args = {
		.fhandle = fhandle,
3458
		.bitmask = bitmask,
B
Benny Halevy 已提交
3459
	};
L
Linus Torvalds 已提交
3460 3461 3462
	struct nfs4_server_caps_res res = {};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
B
Benny Halevy 已提交
3463
		.rpc_argp = &args,
L
Linus Torvalds 已提交
3464 3465 3466
		.rpc_resp = &res,
	};
	int status;
3467
	int i;
L
Linus Torvalds 已提交
3468

3469 3470 3471 3472 3473 3474 3475 3476
	bitmask[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
		     FATTR4_WORD0_FH_EXPIRE_TYPE |
		     FATTR4_WORD0_LINK_SUPPORT |
		     FATTR4_WORD0_SYMLINK_SUPPORT |
		     FATTR4_WORD0_ACLSUPPORT;
	if (minorversion)
		bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT;

3477
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3478
	if (status == 0) {
3479
		/* Sanity check the server answers */
3480
		switch (minorversion) {
3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
		case 0:
			res.attr_bitmask[1] &= FATTR4_WORD1_NFS40_MASK;
			res.attr_bitmask[2] = 0;
			break;
		case 1:
			res.attr_bitmask[2] &= FATTR4_WORD2_NFS41_MASK;
			break;
		case 2:
			res.attr_bitmask[2] &= FATTR4_WORD2_NFS42_MASK;
		}
L
Linus Torvalds 已提交
3491
		memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
3492 3493 3494 3495
		server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS|
				NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
				NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|
				NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME|
3496 3497
				NFS_CAP_CTIME|NFS_CAP_MTIME|
				NFS_CAP_SECURITY_LABEL);
3498 3499
		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL &&
				res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
L
Linus Torvalds 已提交
3500 3501 3502 3503 3504
			server->caps |= NFS_CAP_ACLS;
		if (res.has_links != 0)
			server->caps |= NFS_CAP_HARDLINKS;
		if (res.has_symlinks != 0)
			server->caps |= NFS_CAP_SYMLINKS;
3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
		if (res.attr_bitmask[0] & FATTR4_WORD0_FILEID)
			server->caps |= NFS_CAP_FILEID;
		if (res.attr_bitmask[1] & FATTR4_WORD1_MODE)
			server->caps |= NFS_CAP_MODE;
		if (res.attr_bitmask[1] & FATTR4_WORD1_NUMLINKS)
			server->caps |= NFS_CAP_NLINK;
		if (res.attr_bitmask[1] & FATTR4_WORD1_OWNER)
			server->caps |= NFS_CAP_OWNER;
		if (res.attr_bitmask[1] & FATTR4_WORD1_OWNER_GROUP)
			server->caps |= NFS_CAP_OWNER_GROUP;
		if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_ACCESS)
			server->caps |= NFS_CAP_ATIME;
		if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_METADATA)
			server->caps |= NFS_CAP_CTIME;
		if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY)
			server->caps |= NFS_CAP_MTIME;
3521 3522 3523 3524 3525 3526
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
		if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
			server->caps |= NFS_CAP_SECURITY_LABEL;
#endif
		memcpy(server->attr_bitmask_nl, res.attr_bitmask,
				sizeof(server->attr_bitmask));
3527
		server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
3528

3529 3530 3531
		memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask));
		server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
		server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
3532
		server->cache_consistency_bitmask[2] = 0;
3533 3534 3535 3536

		/* Avoid a regression due to buggy server */
		for (i = 0; i < ARRAY_SIZE(res.exclcreat_bitmask); i++)
			res.exclcreat_bitmask[i] &= res.attr_bitmask[i];
3537 3538
		memcpy(server->exclcreat_bitmask, res.exclcreat_bitmask,
			sizeof(server->exclcreat_bitmask));
3539

L
Linus Torvalds 已提交
3540
		server->acl_bitmask = res.acl_bitmask;
3541
		server->fh_expire_type = res.fh_expire_type;
L
Linus Torvalds 已提交
3542
	}
A
Andy Adamson 已提交
3543

L
Linus Torvalds 已提交
3544 3545 3546
	return status;
}

3547
int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
L
Linus Torvalds 已提交
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561
{
	struct nfs4_exception exception = { };
	int err;
	do {
		err = nfs4_handle_exception(server,
				_nfs4_server_capabilities(server, fhandle),
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_fsinfo *info)
{
3562
	u32 bitmask[3];
L
Linus Torvalds 已提交
3563
	struct nfs4_lookup_root_arg args = {
3564
		.bitmask = bitmask,
L
Linus Torvalds 已提交
3565 3566 3567
	};
	struct nfs4_lookup_res res = {
		.server = server,
3568
		.fattr = info->fattr,
L
Linus Torvalds 已提交
3569 3570 3571 3572 3573 3574 3575
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
3576

3577 3578 3579 3580 3581 3582 3583
	bitmask[0] = nfs4_fattr_bitmap[0];
	bitmask[1] = nfs4_fattr_bitmap[1];
	/*
	 * Process the label in the upcoming getfattr
	 */
	bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL;

3584
	nfs_fattr_init(info->fattr);
3585
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3586 3587 3588 3589 3590 3591 3592 3593
}

static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_fsinfo *info)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3594
		err = _nfs4_lookup_root(server, fhandle, info);
3595
		trace_nfs4_lookup_root(server, fhandle, info->fattr, err);
3596 3597 3598
		switch (err) {
		case 0:
		case -NFS4ERR_WRONGSEC:
3599
			goto out;
3600 3601 3602
		default:
			err = nfs4_handle_exception(server, err, &exception);
		}
L
Linus Torvalds 已提交
3603
	} while (exception.retry);
3604
out:
L
Linus Torvalds 已提交
3605 3606 3607
	return err;
}

3608 3609 3610
static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fsinfo *info, rpc_authflavor_t flavor)
{
3611 3612 3613
	struct rpc_auth_create_args auth_args = {
		.pseudoflavor = flavor,
	};
3614 3615
	struct rpc_auth *auth;

3616
	auth = rpcauth_create(&auth_args, server->client);
3617 3618 3619
	if (IS_ERR(auth))
		return -EACCES;
	return nfs4_lookup_root(server, fhandle, info);
3620 3621
}

3622 3623 3624 3625 3626 3627 3628 3629 3630
/*
 * Retry pseudoroot lookup with various security flavors.  We do this when:
 *
 *   NFSv4.0: the PUTROOTFH operation returns NFS4ERR_WRONGSEC
 *   NFSv4.1: the server does not support the SECINFO_NO_NAME operation
 *
 * Returns zero on success, or a negative NFS4ERR value, or a
 * negative errno value.
 */
3631
static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
3632
			      struct nfs_fsinfo *info)
L
Linus Torvalds 已提交
3633
{
3634 3635 3636 3637 3638
	/* Per 3530bis 15.33.5 */
	static const rpc_authflavor_t flav_array[] = {
		RPC_AUTH_GSS_KRB5P,
		RPC_AUTH_GSS_KRB5I,
		RPC_AUTH_GSS_KRB5,
3639
		RPC_AUTH_UNIX,			/* courtesy */
3640 3641 3642 3643
		RPC_AUTH_NULL,
	};
	int status = -EPERM;
	size_t i;
C
Chuck Lever 已提交
3644

3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
	if (server->auth_info.flavor_len > 0) {
		/* try each flavor specified by user */
		for (i = 0; i < server->auth_info.flavor_len; i++) {
			status = nfs4_lookup_root_sec(server, fhandle, info,
						server->auth_info.flavors[i]);
			if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
				continue;
			break;
		}
	} else {
		/* no flavors specified by user, try default list */
		for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
			status = nfs4_lookup_root_sec(server, fhandle, info,
						      flav_array[i]);
			if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
				continue;
			break;
		}
3663
	}
3664

3665 3666 3667 3668 3669 3670 3671 3672 3673
	/*
	 * -EACCESS could mean that the user doesn't have correct permissions
	 * to access the mount.  It could also mean that we tried to mount
	 * with a gss auth flavor, but rpc.gssd isn't running.  Either way,
	 * existing mount programs don't handle -EACCES very well so it should
	 * be mapped to -EPERM instead.
	 */
	if (status == -EACCES)
		status = -EPERM;
3674 3675 3676
	return status;
}

C
Chuck Lever 已提交
3677 3678 3679 3680 3681
/**
 * nfs4_proc_get_rootfh - get file handle for server's pseudoroot
 * @server: initialized nfs_server handle
 * @fhandle: we fill in the pseudo-fs root file handle
 * @info: we fill in an FSINFO struct
3682
 * @auth_probe: probe the auth flavours
C
Chuck Lever 已提交
3683 3684
 *
 * Returns zero on success, or a negative errno.
3685
 */
3686
int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
3687 3688
			 struct nfs_fsinfo *info,
			 bool auth_probe)
3689
{
3690
	int status = 0;
C
Chuck Lever 已提交
3691

3692
	if (!auth_probe)
3693
		status = nfs4_lookup_root(server, fhandle, info);
3694 3695

	if (auth_probe || status == NFS4ERR_WRONGSEC)
3696 3697
		status = server->nfs_client->cl_mvops->find_root_sec(server,
				fhandle, info);
C
Chuck Lever 已提交
3698

L
Linus Torvalds 已提交
3699 3700 3701 3702
	if (status == 0)
		status = nfs4_server_capabilities(server, fhandle);
	if (status == 0)
		status = nfs4_do_fsinfo(server, fhandle, info);
C
Chuck Lever 已提交
3703

3704
	return nfs4_map_errors(status);
L
Linus Torvalds 已提交
3705 3706
}

3707 3708 3709 3710 3711
static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh,
			      struct nfs_fsinfo *info)
{
	int error;
	struct nfs_fattr *fattr = info->fattr;
3712
	struct nfs4_label *label = NULL;
3713 3714 3715 3716 3717 3718 3719

	error = nfs4_server_capabilities(server, mntfh);
	if (error < 0) {
		dprintk("nfs4_get_root: getcaps error = %d\n", -error);
		return error;
	}

3720 3721 3722 3723
	label = nfs4_label_alloc(server, GFP_KERNEL);
	if (IS_ERR(label))
		return PTR_ERR(label);

3724
	error = nfs4_proc_getattr(server, mntfh, fattr, label);
3725 3726
	if (error < 0) {
		dprintk("nfs4_get_root: getattr error = %d\n", -error);
3727
		goto err_free_label;
3728 3729 3730 3731 3732 3733
	}

	if (fattr->valid & NFS_ATTR_FATTR_FSID &&
	    !nfs_fsid_equal(&server->fsid, &fattr->fsid))
		memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));

3734 3735 3736
err_free_label:
	nfs4_label_free(label);

3737 3738 3739
	return error;
}

M
Manoj Naik 已提交
3740 3741 3742 3743 3744
/*
 * Get locations and (maybe) other attributes of a referral.
 * Note that we'll actually follow the referral later when
 * we detect fsid mismatch in inode revalidation
 */
3745 3746 3747
static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
			     const struct qstr *name, struct nfs_fattr *fattr,
			     struct nfs_fh *fhandle)
M
Manoj Naik 已提交
3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759
{
	int status = -ENOMEM;
	struct page *page = NULL;
	struct nfs4_fs_locations *locations = NULL;

	page = alloc_page(GFP_KERNEL);
	if (page == NULL)
		goto out;
	locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
	if (locations == NULL)
		goto out;

3760
	status = nfs4_proc_fs_locations(client, dir, name, locations, page);
M
Manoj Naik 已提交
3761 3762
	if (status != 0)
		goto out;
3763 3764 3765 3766 3767 3768

	/*
	 * If the fsid didn't change, this is a migration event, not a
	 * referral.  Cause us to drop into the exception handler, which
	 * will kick off migration recovery.
	 */
M
Manoj Naik 已提交
3769
	if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
3770 3771
		dprintk("%s: server did not return a different fsid for"
			" a referral at %s\n", __func__, name->name);
3772
		status = -NFS4ERR_MOVED;
M
Manoj Naik 已提交
3773 3774
		goto out;
	}
3775 3776
	/* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
	nfs_fixup_referral_attributes(&locations->fattr);
M
Manoj Naik 已提交
3777

3778
	/* replace the lookup nfs_fattr with the locations nfs_fattr */
M
Manoj Naik 已提交
3779 3780 3781 3782 3783
	memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
	memset(fhandle, 0, sizeof(struct nfs_fh));
out:
	if (page)
		__free_page(page);
3784
	kfree(locations);
M
Manoj Naik 已提交
3785 3786 3787
	return status;
}

3788 3789
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3790 3791 3792 3793 3794 3795 3796
{
	struct nfs4_getattr_arg args = {
		.fh = fhandle,
		.bitmask = server->attr_bitmask,
	};
	struct nfs4_getattr_res res = {
		.fattr = fattr,
3797
		.label = label,
L
Linus Torvalds 已提交
3798 3799 3800 3801 3802 3803 3804
		.server = server,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
3805 3806 3807

	args.bitmask = nfs4_bitmask(server, label);

3808
	nfs_fattr_init(fattr);
3809
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3810 3811
}

3812 3813
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3814 3815 3816 3817
{
	struct nfs4_exception exception = { };
	int err;
	do {
3818 3819 3820
		err = _nfs4_proc_getattr(server, fhandle, fattr, label);
		trace_nfs4_getattr(server, fhandle, fattr, err);
		err = nfs4_handle_exception(server, err,
L
Linus Torvalds 已提交
3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846
				&exception);
	} while (exception.retry);
	return err;
}

/* 
 * The file is not closed if it is opened due to the a request to change
 * the size of the file. The open call will not be needed once the
 * VFS layer lookup-intents are implemented.
 *
 * Close is called when the inode is destroyed.
 * If we haven't opened the file for O_WRONLY, we
 * need to in the size_change case to obtain a stateid.
 *
 * Got race?
 * Because OPEN is always done by name in nfsv4, it is
 * possible that we opened a different file by the same
 * name.  We can recognize this race condition, but we
 * can't do anything about it besides returning an error.
 *
 * This will be fixed with VFS changes (lookup-intent).
 */
static int
nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
		  struct iattr *sattr)
{
3847
	struct inode *inode = d_inode(dentry);
3848
	struct rpc_cred *cred = NULL;
3849
	struct nfs_open_context *ctx = NULL;
3850
	struct nfs4_label *label = NULL;
L
Linus Torvalds 已提交
3851 3852
	int status;

3853 3854 3855
	if (pnfs_ld_layoutret_on_setattr(inode) &&
	    sattr->ia_valid & ATTR_SIZE &&
	    sattr->ia_size < i_size_read(inode))
3856
		pnfs_commit_and_return_layout(inode);
B
Benny Halevy 已提交
3857

3858
	nfs_fattr_init(fattr);
L
Linus Torvalds 已提交
3859
	
3860 3861
	/* Deal with open(O_TRUNC) */
	if (sattr->ia_valid & ATTR_OPEN)
3862
		sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME);
3863 3864

	/* Optimization: if the end result is no change, don't RPC */
3865
	if ((sattr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)
3866 3867
		return 0;

3868
	/* Search for an existing open(O_WRITE) file */
3869 3870 3871
	if (sattr->ia_valid & ATTR_FILE) {

		ctx = nfs_file_open_context(sattr->ia_file);
3872
		if (ctx)
N
Neil Brown 已提交
3873
			cred = ctx->cred;
3874
	}
3875

3876 3877 3878 3879
	label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
	if (IS_ERR(label))
		return PTR_ERR(label);

3880 3881
	/* Return any delegations if we're going to change ACLs */
	if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
3882
		nfs4_inode_make_writeable(inode);
3883

3884
	status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label);
3885
	if (status == 0) {
3886
		nfs_setattr_update_inode(inode, sattr, fattr);
3887 3888
		nfs_setsecurity(inode, fattr, label);
	}
3889
	nfs4_label_free(label);
L
Linus Torvalds 已提交
3890 3891 3892
	return status;
}

3893 3894
static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
		const struct qstr *name, struct nfs_fh *fhandle,
3895
		struct nfs_fattr *fattr, struct nfs4_label *label)
D
David Howells 已提交
3896
{
3897
	struct nfs_server *server = NFS_SERVER(dir);
D
David Howells 已提交
3898 3899 3900
	int		       status;
	struct nfs4_lookup_arg args = {
		.bitmask = server->attr_bitmask,
3901
		.dir_fh = NFS_FH(dir),
D
David Howells 已提交
3902 3903 3904 3905 3906
		.name = name,
	};
	struct nfs4_lookup_res res = {
		.server = server,
		.fattr = fattr,
3907
		.label = label,
D
David Howells 已提交
3908 3909 3910 3911 3912 3913 3914 3915
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};

3916 3917
	args.bitmask = nfs4_bitmask(server, label);

D
David Howells 已提交
3918 3919
	nfs_fattr_init(fattr);

L
Linus Torvalds 已提交
3920
	dprintk("NFS call  lookup %s\n", name->name);
3921
	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3922 3923 3924 3925
	dprintk("NFS reply lookup: %d\n", status);
	return status;
}

3926
static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
3927 3928
{
	fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
3929
		NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT;
3930 3931 3932 3933
	fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
	fattr->nlink = 2;
}

3934
static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
A
Al Viro 已提交
3935
				   const struct qstr *name, struct nfs_fh *fhandle,
3936
				   struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3937 3938
{
	struct nfs4_exception exception = { };
3939
	struct rpc_clnt *client = *clnt;
L
Linus Torvalds 已提交
3940 3941
	int err;
	do {
3942
		err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label);
3943
		trace_nfs4_lookup(dir, name, err);
3944
		switch (err) {
3945
		case -NFS4ERR_BADNAME:
3946 3947
			err = -ENOENT;
			goto out;
3948
		case -NFS4ERR_MOVED:
3949
			err = nfs4_get_referral(client, dir, name, fattr, fhandle);
3950 3951
			if (err == -NFS4ERR_MOVED)
				err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
3952
			goto out;
3953
		case -NFS4ERR_WRONGSEC:
3954 3955 3956
			err = -EPERM;
			if (client != *clnt)
				goto out;
3957
			client = nfs4_negotiate_security(client, dir, name);
3958 3959 3960 3961 3962 3963 3964
			if (IS_ERR(client))
				return PTR_ERR(client);

			exception.retry = 1;
			break;
		default:
			err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
3965
		}
L
Linus Torvalds 已提交
3966
	} while (exception.retry);
3967 3968 3969 3970 3971 3972 3973

out:
	if (err == 0)
		*clnt = client;
	else if (client != *clnt)
		rpc_shutdown_client(client);

L
Linus Torvalds 已提交
3974 3975 3976
	return err;
}

A
Al Viro 已提交
3977
static int nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
3978 3979
			    struct nfs_fh *fhandle, struct nfs_fattr *fattr,
			    struct nfs4_label *label)
3980 3981 3982 3983
{
	int status;
	struct rpc_clnt *client = NFS_CLIENT(dir);

3984
	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label);
3985 3986 3987 3988 3989 3990 3991
	if (client != NFS_CLIENT(dir)) {
		rpc_shutdown_client(client);
		nfs_fixup_secinfo_attributes(fattr);
	}
	return status;
}

3992
struct rpc_clnt *
A
Al Viro 已提交
3993
nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
3994 3995
			    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
3996
	struct rpc_clnt *client = NFS_CLIENT(dir);
3997 3998
	int status;

3999
	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL);
4000
	if (status < 0)
4001
		return ERR_PTR(status);
4002
	return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
4003 4004
}

J
Jeff Layton 已提交
4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052
static int _nfs4_proc_lookupp(struct inode *inode,
		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
		struct nfs4_label *label)
{
	struct rpc_clnt *clnt = NFS_CLIENT(inode);
	struct nfs_server *server = NFS_SERVER(inode);
	int		       status;
	struct nfs4_lookupp_arg args = {
		.bitmask = server->attr_bitmask,
		.fh = NFS_FH(inode),
	};
	struct nfs4_lookupp_res res = {
		.server = server,
		.fattr = fattr,
		.label = label,
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};

	args.bitmask = nfs4_bitmask(server, label);

	nfs_fattr_init(fattr);

	dprintk("NFS call  lookupp ino=0x%lx\n", inode->i_ino);
	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
				&res.seq_res, 0);
	dprintk("NFS reply lookupp: %d\n", status);
	return status;
}

static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
			     struct nfs_fattr *fattr, struct nfs4_label *label)
{
	struct nfs4_exception exception = { };
	int err;
	do {
		err = _nfs4_proc_lookupp(inode, fhandle, fattr, label);
		trace_nfs4_lookupp(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
				&exception);
	} while (exception.retry);
	return err;
}

L
Linus Torvalds 已提交
4053 4054
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
4055
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
4056 4057
	struct nfs4_accessargs args = {
		.fh = NFS_FH(inode),
4058
		.access = entry->mask,
4059 4060 4061
	};
	struct nfs4_accessres res = {
		.server = server,
L
Linus Torvalds 已提交
4062 4063 4064 4065 4066 4067 4068
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
		.rpc_argp = &args,
		.rpc_resp = &res,
		.rpc_cred = entry->cred,
	};
4069
	int status = 0;
L
Linus Torvalds 已提交
4070

4071 4072 4073 4074 4075 4076
	if (!nfs_have_delegated_attributes(inode)) {
		res.fattr = nfs_alloc_fattr();
		if (res.fattr == NULL)
			return -ENOMEM;
		args.bitmask = server->cache_consistency_bitmask;
	}
4077

4078
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4079
	if (!status) {
4080
		nfs_access_set_mask(entry, res.access);
4081 4082
		if (res.fattr)
			nfs_refresh_inode(inode, res.fattr);
L
Linus Torvalds 已提交
4083
	}
4084
	nfs_free_fattr(res.fattr);
L
Linus Torvalds 已提交
4085 4086 4087 4088 4089 4090 4091 4092
	return status;
}

static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
	struct nfs4_exception exception = { };
	int err;
	do {
4093 4094 4095
		err = _nfs4_proc_access(inode, entry);
		trace_nfs4_access(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
L
Linus Torvalds 已提交
4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117
				&exception);
	} while (exception.retry);
	return err;
}

/*
 * TODO: For the time being, we don't try to get any attributes
 * along with any of the zero-copy operations READ, READDIR,
 * READLINK, WRITE.
 *
 * In the case of the first three, we want to put the GETATTR
 * after the read-type operation -- this is because it is hard
 * to predict the length of a GETATTR response in v4, and thus
 * align the READ data correctly.  This means that the GETATTR
 * may end up partially falling into the page cache, and we should
 * shift it into the 'tail' of the xdr_buf before processing.
 * To do this efficiently, we need to know the total length
 * of data received, which doesn't seem to be available outside
 * of the RPC layer.
 *
 * In the case of WRITE, we also want to put the GETATTR after
 * the operation -- in this case because we want to make sure
4118
 * we get the post-operation mtime and size.
L
Linus Torvalds 已提交
4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131
 *
 * Both of these changes to the XDR layer would in fact be quite
 * minor, but I decided to leave them for a subsequent patch.
 */
static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs4_readlink args = {
		.fh       = NFS_FH(inode),
		.pgbase	  = pgbase,
		.pglen    = pglen,
		.pages    = &page,
	};
B
Benny Halevy 已提交
4132
	struct nfs4_readlink_res res;
L
Linus Torvalds 已提交
4133 4134 4135
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4136
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4137 4138
	};

4139
	return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4140 4141 4142 4143 4144 4145 4146 4147
}

static int nfs4_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs4_exception exception = { };
	int err;
	do {
4148 4149 4150
		err = _nfs4_proc_readlink(inode, page, pgbase, pglen);
		trace_nfs4_readlink(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
L
Linus Torvalds 已提交
4151 4152 4153 4154 4155 4156
				&exception);
	} while (exception.retry);
	return err;
}

/*
4157
 * This is just for mknod.  open(O_CREAT) will always do ->open_context().
L
Linus Torvalds 已提交
4158 4159 4160
 */
static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
4161
		 int flags)
L
Linus Torvalds 已提交
4162
{
4163
	struct nfs_server *server = NFS_SERVER(dir);
4164
	struct nfs4_label l, *ilabel = NULL;
4165
	struct nfs_open_context *ctx;
L
Linus Torvalds 已提交
4166 4167 4168
	struct nfs4_state *state;
	int status = 0;

N
NeilBrown 已提交
4169
	ctx = alloc_nfs_open_context(dentry, FMODE_READ, NULL);
4170 4171 4172
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

4173 4174
	ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);

4175 4176
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
4177
	state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL);
L
Linus Torvalds 已提交
4178 4179
	if (IS_ERR(state)) {
		status = PTR_ERR(state);
4180
		goto out;
L
Linus Torvalds 已提交
4181 4182
	}
out:
4183
	nfs4_label_release_security(ilabel);
4184
	put_nfs_open_context(ctx);
L
Linus Torvalds 已提交
4185 4186 4187
	return status;
}

A
Al Viro 已提交
4188
static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4189
{
4190
	struct nfs_server *server = NFS_SERVER(dir);
4191
	struct nfs_removeargs args = {
L
Linus Torvalds 已提交
4192
		.fh = NFS_FH(dir),
4193
		.name = *name,
4194
	};
4195
	struct nfs_removeres res = {
4196
		.server = server,
L
Linus Torvalds 已提交
4197 4198
	};
	struct rpc_message msg = {
4199 4200 4201
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
		.rpc_argp = &args,
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4202
	};
4203
	unsigned long timestamp = jiffies;
4204
	int status;
L
Linus Torvalds 已提交
4205

4206
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
4207
	if (status == 0)
4208
		update_changeattr(dir, &res.cinfo, timestamp);
L
Linus Torvalds 已提交
4209 4210 4211
	return status;
}

4212
static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)
L
Linus Torvalds 已提交
4213 4214
{
	struct nfs4_exception exception = { };
4215
	struct inode *inode = d_inode(dentry);
L
Linus Torvalds 已提交
4216
	int err;
4217

4218 4219 4220 4221 4222 4223
	if (inode) {
		if (inode->i_nlink == 1)
			nfs4_inode_return_delegation(inode);
		else
			nfs4_inode_make_writeable(inode);
	}
4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237
	do {
		err = _nfs4_proc_remove(dir, &dentry->d_name);
		trace_nfs4_remove(dir, &dentry->d_name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
				&exception);
	} while (exception.retry);
	return err;
}

static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
{
	struct nfs4_exception exception = { };
	int err;

L
Linus Torvalds 已提交
4238
	do {
4239 4240 4241
		err = _nfs4_proc_remove(dir, name);
		trace_nfs4_remove(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
L
Linus Torvalds 已提交
4242 4243 4244 4245 4246
				&exception);
	} while (exception.retry);
	return err;
}

4247
static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
L
Linus Torvalds 已提交
4248
{
4249 4250
	struct nfs_removeargs *args = msg->rpc_argp;
	struct nfs_removeres *res = msg->rpc_resp;
4251
	struct inode *inode = d_inode(dentry);
L
Linus Torvalds 已提交
4252

4253
	res->server = NFS_SB(dentry->d_sb);
L
Linus Torvalds 已提交
4254
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
4255
	nfs4_init_sequence(&args->seq_args, &res->seq_res, 1);
4256 4257

	nfs_fattr_init(res->dir_attr);
4258 4259 4260

	if (inode)
		nfs4_inode_return_delegation(inode);
L
Linus Torvalds 已提交
4261 4262
}

4263 4264
static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
{
4265
	nfs4_setup_sequence(NFS_SB(data->dentry->d_sb)->nfs_client,
4266 4267 4268
			&data->args.seq_args,
			&data->res.seq_res,
			task);
L
Linus Torvalds 已提交
4269 4270
}

4271
static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
L
Linus Torvalds 已提交
4272
{
4273 4274
	struct nfs_unlinkdata *data = task->tk_calldata;
	struct nfs_removeres *res = &data->res;
4275

4276 4277
	if (!nfs4_sequence_done(task, &res->seq_res))
		return 0;
4278 4279
	if (nfs4_async_handle_error(task, res->server, NULL,
				    &data->timeout) == -EAGAIN)
4280
		return 0;
4281
	if (task->tk_status == 0)
4282
		update_changeattr(dir, &res->cinfo, res->dir_attr->time_start);
4283
	return 1;
L
Linus Torvalds 已提交
4284 4285
}

4286 4287 4288
static void nfs4_proc_rename_setup(struct rpc_message *msg,
		struct dentry *old_dentry,
		struct dentry *new_dentry)
4289 4290 4291
{
	struct nfs_renameargs *arg = msg->rpc_argp;
	struct nfs_renameres *res = msg->rpc_resp;
4292 4293
	struct inode *old_inode = d_inode(old_dentry);
	struct inode *new_inode = d_inode(new_dentry);
4294

4295
	if (old_inode)
4296
		nfs4_inode_make_writeable(old_inode);
4297 4298
	if (new_inode)
		nfs4_inode_return_delegation(new_inode);
4299
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
4300
	res->server = NFS_SB(old_dentry->d_sb);
4301
	nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1);
4302 4303
}

4304 4305
static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
{
4306
	nfs4_setup_sequence(NFS_SERVER(data->old_dir)->nfs_client,
4307 4308 4309
			&data->args.seq_args,
			&data->res.seq_res,
			task);
4310 4311 4312 4313 4314
}

static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
				 struct inode *new_dir)
{
4315 4316
	struct nfs_renamedata *data = task->tk_calldata;
	struct nfs_renameres *res = &data->res;
4317 4318 4319

	if (!nfs4_sequence_done(task, &res->seq_res))
		return 0;
4320
	if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN)
4321 4322
		return 0;

4323
	if (task->tk_status == 0) {
4324
		update_changeattr(old_dir, &res->old_cinfo, res->old_fattr->time_start);
4325
		if (new_dir != old_dir)
4326
			update_changeattr(new_dir, &res->new_cinfo, res->new_fattr->time_start);
4327
	}
4328 4329 4330
	return 1;
}

A
Al Viro 已提交
4331
static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4332
{
4333
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
4334 4335 4336 4337
	struct nfs4_link_arg arg = {
		.fh     = NFS_FH(inode),
		.dir_fh = NFS_FH(dir),
		.name   = name,
4338 4339 4340 4341
		.bitmask = server->attr_bitmask,
	};
	struct nfs4_link_res res = {
		.server = server,
4342
		.label = NULL,
L
Linus Torvalds 已提交
4343 4344 4345 4346
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
		.rpc_argp = &arg,
4347
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4348
	};
4349 4350 4351
	int status = -ENOMEM;

	res.fattr = nfs_alloc_fattr();
4352
	if (res.fattr == NULL)
4353
		goto out;
L
Linus Torvalds 已提交
4354

4355 4356 4357 4358 4359
	res.label = nfs4_label_alloc(server, GFP_KERNEL);
	if (IS_ERR(res.label)) {
		status = PTR_ERR(res.label);
		goto out;
	}
4360
	arg.bitmask = nfs4_bitmask(server, res.label);
4361

4362
	nfs4_inode_make_writeable(inode);
4363

4364
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
4365
	if (!status) {
4366
		update_changeattr(dir, &res.cinfo, res.fattr->time_start);
4367 4368 4369
		status = nfs_post_op_update_inode(inode, res.fattr);
		if (!status)
			nfs_setsecurity(inode, res.fattr, res.label);
4370
	}
4371 4372 4373 4374


	nfs4_label_free(res.label);

4375 4376
out:
	nfs_free_fattr(res.fattr);
L
Linus Torvalds 已提交
4377 4378 4379
	return status;
}

A
Al Viro 已提交
4380
static int nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391
{
	struct nfs4_exception exception = { };
	int err;
	do {
		err = nfs4_handle_exception(NFS_SERVER(inode),
				_nfs4_proc_link(inode, dir, name),
				&exception);
	} while (exception.retry);
	return err;
}

4392 4393 4394 4395 4396 4397
struct nfs4_createdata {
	struct rpc_message msg;
	struct nfs4_create_arg arg;
	struct nfs4_create_res res;
	struct nfs_fh fh;
	struct nfs_fattr fattr;
4398
	struct nfs4_label *label;
4399 4400 4401
};

static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
A
Al Viro 已提交
4402
		const struct qstr *name, struct iattr *sattr, u32 ftype)
4403 4404 4405 4406 4407 4408 4409
{
	struct nfs4_createdata *data;

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (data != NULL) {
		struct nfs_server *server = NFS_SERVER(dir);

4410 4411 4412 4413
		data->label = nfs4_label_alloc(server, GFP_KERNEL);
		if (IS_ERR(data->label))
			goto out_free;

4414 4415 4416 4417 4418 4419 4420 4421
		data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
		data->msg.rpc_argp = &data->arg;
		data->msg.rpc_resp = &data->res;
		data->arg.dir_fh = NFS_FH(dir);
		data->arg.server = server;
		data->arg.name = name;
		data->arg.attrs = sattr;
		data->arg.ftype = ftype;
4422
		data->arg.bitmask = nfs4_bitmask(server, data->label);
4423
		data->arg.umask = current_umask();
4424 4425 4426
		data->res.server = server;
		data->res.fh = &data->fh;
		data->res.fattr = &data->fattr;
4427
		data->res.label = data->label;
4428 4429 4430
		nfs_fattr_init(data->res.fattr);
	}
	return data;
4431 4432 4433
out_free:
	kfree(data);
	return NULL;
4434 4435 4436 4437
}

static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
{
4438
	int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
4439
				    &data->arg.seq_args, &data->res.seq_res, 1);
4440
	if (status == 0) {
4441 4442
		update_changeattr(dir, &data->res.dir_cinfo,
				data->res.fattr->time_start);
4443
		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
4444 4445 4446 4447 4448 4449
	}
	return status;
}

static void nfs4_free_createdata(struct nfs4_createdata *data)
{
4450
	nfs4_label_free(data->label);
4451 4452 4453
	kfree(data);
}

4454
static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
4455 4456
		struct page *page, unsigned int len, struct iattr *sattr,
		struct nfs4_label *label)
L
Linus Torvalds 已提交
4457
{
4458 4459
	struct nfs4_createdata *data;
	int status = -ENAMETOOLONG;
L
Linus Torvalds 已提交
4460

4461
	if (len > NFS4_MAXPATHLEN)
4462
		goto out;
4463

4464 4465 4466 4467 4468 4469 4470 4471
	status = -ENOMEM;
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4LNK);
	if (data == NULL)
		goto out;

	data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
	data->arg.u.symlink.pages = &page;
	data->arg.u.symlink.len = len;
4472
	data->arg.label = label;
L
Linus Torvalds 已提交
4473
	
4474 4475 4476 4477
	status = nfs4_do_create(dir, dentry, data);

	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
4478 4479 4480
	return status;
}

4481
static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
4482
		struct page *page, unsigned int len, struct iattr *sattr)
L
Linus Torvalds 已提交
4483 4484
{
	struct nfs4_exception exception = { };
4485
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
4486
	int err;
4487 4488 4489

	label = nfs4_label_init_security(dir, dentry, sattr, &l);

L
Linus Torvalds 已提交
4490
	do {
4491 4492 4493
		err = _nfs4_proc_symlink(dir, dentry, page, len, sattr, label);
		trace_nfs4_symlink(dir, &dentry->d_name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
L
Linus Torvalds 已提交
4494 4495
				&exception);
	} while (exception.retry);
4496 4497

	nfs4_label_release_security(label);
L
Linus Torvalds 已提交
4498 4499 4500 4501
	return err;
}

static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
4502
		struct iattr *sattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
4503
{
4504 4505
	struct nfs4_createdata *data;
	int status = -ENOMEM;
L
Linus Torvalds 已提交
4506

4507 4508 4509 4510
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
	if (data == NULL)
		goto out;

4511
	data->arg.label = label;
4512 4513 4514 4515
	status = nfs4_do_create(dir, dentry, data);

	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
4516 4517 4518 4519 4520 4521
	return status;
}

static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr)
{
4522
	struct nfs_server *server = NFS_SERVER(dir);
L
Linus Torvalds 已提交
4523
	struct nfs4_exception exception = { };
4524
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
4525
	int err;
A
Aneesh Kumar K.V 已提交
4526

4527 4528
	label = nfs4_label_init_security(dir, dentry, sattr, &l);

4529 4530
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
L
Linus Torvalds 已提交
4531
	do {
4532 4533 4534
		err = _nfs4_proc_mkdir(dir, dentry, sattr, label);
		trace_nfs4_mkdir(dir, &dentry->d_name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
L
Linus Torvalds 已提交
4535 4536
				&exception);
	} while (exception.retry);
4537 4538
	nfs4_label_release_security(label);

L
Linus Torvalds 已提交
4539 4540 4541 4542
	return err;
}

static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
B
Benjamin Coddington 已提交
4543
		u64 cookie, struct page **pages, unsigned int count, bool plus)
L
Linus Torvalds 已提交
4544
{
4545
	struct inode		*dir = d_inode(dentry);
L
Linus Torvalds 已提交
4546 4547
	struct nfs4_readdir_arg args = {
		.fh = NFS_FH(dir),
B
Bryan Schumaker 已提交
4548
		.pages = pages,
L
Linus Torvalds 已提交
4549 4550
		.pgbase = 0,
		.count = count,
4551
		.bitmask = NFS_SERVER(d_inode(dentry))->attr_bitmask,
B
Bryan Schumaker 已提交
4552
		.plus = plus,
L
Linus Torvalds 已提交
4553 4554 4555 4556 4557 4558 4559 4560 4561 4562
	};
	struct nfs4_readdir_res res;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READDIR],
		.rpc_argp = &args,
		.rpc_resp = &res,
		.rpc_cred = cred,
	};
	int			status;

4563 4564
	dprintk("%s: dentry = %pd2, cookie = %Lu\n", __func__,
			dentry,
4565
			(unsigned long long)cookie);
4566
	nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
L
Linus Torvalds 已提交
4567
	res.pgbase = args.pgbase;
4568
	status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
4569
	if (status >= 0) {
4570
		memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
4571 4572
		status += args.pgbase;
	}
4573 4574 4575

	nfs_invalidate_atime(dir);

4576
	dprintk("%s: returns %d\n", __func__, status);
L
Linus Torvalds 已提交
4577 4578 4579 4580
	return status;
}

static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
B
Benjamin Coddington 已提交
4581
		u64 cookie, struct page **pages, unsigned int count, bool plus)
L
Linus Torvalds 已提交
4582 4583 4584 4585
{
	struct nfs4_exception exception = { };
	int err;
	do {
4586 4587
		err = _nfs4_proc_readdir(dentry, cred, cookie,
				pages, count, plus);
4588 4589
		trace_nfs4_readdir(d_inode(dentry), err);
		err = nfs4_handle_exception(NFS_SERVER(d_inode(dentry)), err,
L
Linus Torvalds 已提交
4590 4591 4592 4593 4594 4595
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
4596
		struct iattr *sattr, struct nfs4_label *label, dev_t rdev)
L
Linus Torvalds 已提交
4597
{
4598 4599 4600
	struct nfs4_createdata *data;
	int mode = sattr->ia_mode;
	int status = -ENOMEM;
L
Linus Torvalds 已提交
4601

4602 4603 4604 4605
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
	if (data == NULL)
		goto out;

L
Linus Torvalds 已提交
4606
	if (S_ISFIFO(mode))
4607
		data->arg.ftype = NF4FIFO;
L
Linus Torvalds 已提交
4608
	else if (S_ISBLK(mode)) {
4609 4610 4611
		data->arg.ftype = NF4BLK;
		data->arg.u.device.specdata1 = MAJOR(rdev);
		data->arg.u.device.specdata2 = MINOR(rdev);
L
Linus Torvalds 已提交
4612 4613
	}
	else if (S_ISCHR(mode)) {
4614 4615 4616
		data->arg.ftype = NF4CHR;
		data->arg.u.device.specdata1 = MAJOR(rdev);
		data->arg.u.device.specdata2 = MINOR(rdev);
4617 4618 4619
	} else if (!S_ISSOCK(mode)) {
		status = -EINVAL;
		goto out_free;
L
Linus Torvalds 已提交
4620
	}
4621

4622
	data->arg.label = label;
4623
	status = nfs4_do_create(dir, dentry, data);
4624
out_free:
4625 4626
	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
4627 4628 4629 4630 4631 4632
	return status;
}

static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr, dev_t rdev)
{
4633
	struct nfs_server *server = NFS_SERVER(dir);
L
Linus Torvalds 已提交
4634
	struct nfs4_exception exception = { };
4635
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
4636
	int err;
A
Aneesh Kumar K.V 已提交
4637

4638 4639
	label = nfs4_label_init_security(dir, dentry, sattr, &l);

4640 4641
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
L
Linus Torvalds 已提交
4642
	do {
4643 4644 4645
		err = _nfs4_proc_mknod(dir, dentry, sattr, label, rdev);
		trace_nfs4_mknod(dir, &dentry->d_name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
L
Linus Torvalds 已提交
4646 4647
				&exception);
	} while (exception.retry);
4648 4649 4650

	nfs4_label_release_security(label);

L
Linus Torvalds 已提交
4651 4652 4653 4654 4655 4656 4657 4658 4659 4660
	return err;
}

static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
		 struct nfs_fsstat *fsstat)
{
	struct nfs4_statfs_arg args = {
		.fh = fhandle,
		.bitmask = server->attr_bitmask,
	};
B
Benny Halevy 已提交
4661 4662 4663
	struct nfs4_statfs_res res = {
		.fsstat = fsstat,
	};
L
Linus Torvalds 已提交
4664 4665 4666
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4667
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4668 4669
	};

4670
	nfs_fattr_init(fsstat->fattr);
4671
	return  nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692
}

static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
{
	struct nfs4_exception exception = { };
	int err;
	do {
		err = nfs4_handle_exception(server,
				_nfs4_proc_statfs(server, fhandle, fsstat),
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_fsinfo *fsinfo)
{
	struct nfs4_fsinfo_arg args = {
		.fh = fhandle,
		.bitmask = server->attr_bitmask,
	};
B
Benny Halevy 已提交
4693 4694 4695
	struct nfs4_fsinfo_res res = {
		.fsinfo = fsinfo,
	};
L
Linus Torvalds 已提交
4696 4697 4698
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4699
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4700 4701
	};

4702
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4703 4704 4705 4706 4707
}

static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
	struct nfs4_exception exception = { };
4708
	unsigned long now = jiffies;
L
Linus Torvalds 已提交
4709 4710 4711
	int err;

	do {
4712
		err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
4713
		trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err);
4714
		if (err == 0) {
4715 4716 4717
			nfs4_set_lease_period(server->nfs_client,
					fsinfo->lease_time * HZ,
					now);
4718 4719 4720
			break;
		}
		err = nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
4721 4722 4723 4724 4725 4726
	} while (exception.retry);
	return err;
}

static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
4727 4728
	int error;

4729
	nfs_fattr_init(fsinfo->fattr);
4730
	error = nfs4_do_fsinfo(server, fhandle, fsinfo);
4731 4732 4733
	if (error == 0) {
		/* block layout checks this! */
		server->pnfs_blksize = fsinfo->blksize;
4734
		set_pnfs_layoutdriver(server, fhandle, fsinfo);
4735
	}
4736 4737

	return error;
L
Linus Torvalds 已提交
4738 4739 4740 4741 4742 4743 4744 4745 4746
}

static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_pathconf *pathconf)
{
	struct nfs4_pathconf_arg args = {
		.fh = fhandle,
		.bitmask = server->attr_bitmask,
	};
B
Benny Halevy 已提交
4747 4748 4749
	struct nfs4_pathconf_res res = {
		.pathconf = pathconf,
	};
L
Linus Torvalds 已提交
4750 4751 4752
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4753
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4754 4755 4756 4757 4758 4759 4760 4761
	};

	/* None of the pathconf attributes are mandatory to implement */
	if ((args.bitmask[0] & nfs4_pathconf_bitmap[0]) == 0) {
		memset(pathconf, 0, sizeof(*pathconf));
		return 0;
	}

4762
	nfs_fattr_init(pathconf->fattr);
4763
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779
}

static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_pathconf *pathconf)
{
	struct nfs4_exception exception = { };
	int err;

	do {
		err = nfs4_handle_exception(server,
				_nfs4_proc_pathconf(server, fhandle, pathconf),
				&exception);
	} while (exception.retry);
	return err;
}

4780
int nfs4_set_rw_stateid(nfs4_stateid *stateid,
4781 4782 4783 4784
		const struct nfs_open_context *ctx,
		const struct nfs_lock_context *l_ctx,
		fmode_t fmode)
{
4785
	return nfs4_select_rw_stateid(ctx->state, fmode, l_ctx, stateid, NULL);
4786 4787 4788
}
EXPORT_SYMBOL_GPL(nfs4_set_rw_stateid);

4789 4790 4791 4792 4793 4794 4795
static bool nfs4_stateid_is_current(nfs4_stateid *stateid,
		const struct nfs_open_context *ctx,
		const struct nfs_lock_context *l_ctx,
		fmode_t fmode)
{
	nfs4_stateid current_stateid;

4796 4797 4798
	/* If the current stateid represents a lost lock, then exit */
	if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode) == -EIO)
		return true;
4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816
	return nfs4_stateid_match(stateid, &current_stateid);
}

static bool nfs4_error_stateid_expired(int err)
{
	switch (err) {
	case -NFS4ERR_DELEG_REVOKED:
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_STALE_STATEID:
	case -NFS4ERR_OLD_STATEID:
	case -NFS4ERR_OPENMODE:
	case -NFS4ERR_EXPIRED:
		return true;
	}
	return false;
}

4817
static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr)
L
Linus Torvalds 已提交
4818
{
4819
	struct nfs_server *server = NFS_SERVER(hdr->inode);
L
Linus Torvalds 已提交
4820

4821
	trace_nfs4_read(hdr, task->tk_status);
4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833
	if (task->tk_status < 0) {
		struct nfs4_exception exception = {
			.inode = hdr->inode,
			.state = hdr->args.context->state,
			.stateid = &hdr->args.stateid,
		};
		task->tk_status = nfs4_async_handle_exception(task,
				server, task->tk_status, &exception);
		if (exception.retry) {
			rpc_restart_call_prepare(task);
			return -EAGAIN;
		}
L
Linus Torvalds 已提交
4834
	}
4835

L
Linus Torvalds 已提交
4836
	if (task->tk_status > 0)
4837
		renew_lease(server, hdr->timestamp);
T
Trond Myklebust 已提交
4838
	return 0;
L
Linus Torvalds 已提交
4839 4840
}

4841
static bool nfs4_read_stateid_changed(struct rpc_task *task,
4842
		struct nfs_pgio_args *args)
4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854
{

	if (!nfs4_error_stateid_expired(task->tk_status) ||
		nfs4_stateid_is_current(&args->stateid,
				args->context,
				args->lock_context,
				FMODE_READ))
		return false;
	rpc_restart_call_prepare(task);
	return true;
}

4855
static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
4856 4857 4858 4859
{

	dprintk("--> %s\n", __func__);

4860
	if (!nfs4_sequence_done(task, &hdr->res.seq_res))
4861
		return -EAGAIN;
4862
	if (nfs4_read_stateid_changed(task, &hdr->args))
4863
		return -EAGAIN;
4864 4865
	if (task->tk_status > 0)
		nfs_invalidate_atime(hdr->inode);
4866 4867
	return hdr->pgio_done_cb ? hdr->pgio_done_cb(task, hdr) :
				    nfs4_read_done_cb(task, hdr);
4868 4869
}

4870 4871
static void nfs4_proc_read_setup(struct nfs_pgio_header *hdr,
				 struct rpc_message *msg)
L
Linus Torvalds 已提交
4872
{
4873
	hdr->timestamp   = jiffies;
4874 4875
	if (!hdr->pgio_done_cb)
		hdr->pgio_done_cb = nfs4_read_done_cb;
4876
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
4877
	nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0);
L
Linus Torvalds 已提交
4878 4879
}

4880 4881
static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task,
				      struct nfs_pgio_header *hdr)
4882
{
4883
	if (nfs4_setup_sequence(NFS_SERVER(hdr->inode)->nfs_client,
4884 4885
			&hdr->args.seq_args,
			&hdr->res.seq_res,
4886
			task))
4887
		return 0;
4888 4889
	if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
				hdr->args.lock_context,
4890
				hdr->rw_mode) == -EIO)
4891
		return -EIO;
4892
	if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags)))
4893 4894
		return -EIO;
	return 0;
L
Linus Torvalds 已提交
4895 4896
}

4897 4898
static int nfs4_write_done_cb(struct rpc_task *task,
			      struct nfs_pgio_header *hdr)
L
Linus Torvalds 已提交
4899
{
4900
	struct inode *inode = hdr->inode;
4901

4902
	trace_nfs4_write(hdr, task->tk_status);
4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915
	if (task->tk_status < 0) {
		struct nfs4_exception exception = {
			.inode = hdr->inode,
			.state = hdr->args.context->state,
			.stateid = &hdr->args.stateid,
		};
		task->tk_status = nfs4_async_handle_exception(task,
				NFS_SERVER(inode), task->tk_status,
				&exception);
		if (exception.retry) {
			rpc_restart_call_prepare(task);
			return -EAGAIN;
		}
L
Linus Torvalds 已提交
4916
	}
4917
	if (task->tk_status >= 0) {
4918
		renew_lease(NFS_SERVER(inode), hdr->timestamp);
4919
		nfs_writeback_update_inode(hdr);
4920
	}
4921
	return 0;
L
Linus Torvalds 已提交
4922 4923
}

4924
static bool nfs4_write_stateid_changed(struct rpc_task *task,
4925
		struct nfs_pgio_args *args)
4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937
{

	if (!nfs4_error_stateid_expired(task->tk_status) ||
		nfs4_stateid_is_current(&args->stateid,
				args->context,
				args->lock_context,
				FMODE_WRITE))
		return false;
	rpc_restart_call_prepare(task);
	return true;
}

4938
static int nfs4_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
4939
{
4940
	if (!nfs4_sequence_done(task, &hdr->res.seq_res))
4941
		return -EAGAIN;
4942
	if (nfs4_write_stateid_changed(task, &hdr->args))
4943
		return -EAGAIN;
4944 4945
	return hdr->pgio_done_cb ? hdr->pgio_done_cb(task, hdr) :
		nfs4_write_done_cb(task, hdr);
4946 4947
}

4948
static
4949
bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
4950
{
4951
	/* Don't request attributes for pNFS or O_DIRECT writes */
4952
	if (hdr->ds_clp != NULL || hdr->dreq != NULL)
4953 4954 4955 4956
		return false;
	/* Otherwise, request attributes if and only if we don't hold
	 * a delegation
	 */
4957
	return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
4958 4959
}

4960 4961
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
				  struct rpc_message *msg)
L
Linus Torvalds 已提交
4962
{
4963
	struct nfs_server *server = NFS_SERVER(hdr->inode);
4964

4965 4966 4967
	if (!nfs4_write_need_cache_consistency_data(hdr)) {
		hdr->args.bitmask = NULL;
		hdr->res.fattr = NULL;
4968
	} else
4969
		hdr->args.bitmask = server->cache_consistency_bitmask;
4970

4971 4972 4973 4974
	if (!hdr->pgio_done_cb)
		hdr->pgio_done_cb = nfs4_write_done_cb;
	hdr->res.server = server;
	hdr->timestamp   = jiffies;
L
Linus Torvalds 已提交
4975

4976
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
4977
	nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1);
L
Linus Torvalds 已提交
4978 4979
}

4980
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
4981
{
4982
	nfs4_setup_sequence(NFS_SERVER(data->inode)->nfs_client,
4983 4984 4985
			&data->args.seq_args,
			&data->res.seq_res,
			task);
L
Linus Torvalds 已提交
4986 4987
}

4988
static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
L
Linus Torvalds 已提交
4989 4990
{
	struct inode *inode = data->inode;
4991

4992
	trace_nfs4_commit(data, task->tk_status);
4993 4994
	if (nfs4_async_handle_error(task, NFS_SERVER(inode),
				    NULL, NULL) == -EAGAIN) {
4995
		rpc_restart_call_prepare(task);
4996
		return -EAGAIN;
L
Linus Torvalds 已提交
4997
	}
4998
	return 0;
L
Linus Torvalds 已提交
4999 5000
}

5001
static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
5002 5003 5004
{
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return -EAGAIN;
5005
	return data->commit_done_cb(task, data);
5006 5007
}

5008
static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
L
Linus Torvalds 已提交
5009
{
5010
	struct nfs_server *server = NFS_SERVER(data->inode);
5011

5012 5013
	if (data->commit_done_cb == NULL)
		data->commit_done_cb = nfs4_commit_done_cb;
5014
	data->res.server = server;
5015
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
5016
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
L
Linus Torvalds 已提交
5017 5018
}

5019 5020 5021 5022 5023
struct nfs4_renewdata {
	struct nfs_client	*client;
	unsigned long		timestamp;
};

L
Linus Torvalds 已提交
5024 5025 5026 5027
/*
 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
 * standalone procedure for queueing an asynchronous RENEW.
 */
5028
static void nfs4_renew_release(void *calldata)
5029
{
5030 5031
	struct nfs4_renewdata *data = calldata;
	struct nfs_client *clp = data->client;
5032

5033
	if (refcount_read(&clp->cl_count) > 1)
5034 5035
		nfs4_schedule_state_renewal(clp);
	nfs_put_client(clp);
5036
	kfree(data);
5037 5038
}

5039
static void nfs4_renew_done(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
5040
{
5041 5042 5043
	struct nfs4_renewdata *data = calldata;
	struct nfs_client *clp = data->client;
	unsigned long timestamp = data->timestamp;
L
Linus Torvalds 已提交
5044

5045
	trace_nfs4_renew_async(clp, task->tk_status);
5046 5047 5048 5049 5050 5051 5052
	switch (task->tk_status) {
	case 0:
		break;
	case -NFS4ERR_LEASE_MOVED:
		nfs4_schedule_lease_moved_recovery(clp);
		break;
	default:
5053
		/* Unless we're shutting down, schedule state recovery! */
5054 5055 5056
		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
			return;
		if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
5057
			nfs4_schedule_lease_recovery(clp);
5058 5059 5060
			return;
		}
		nfs4_schedule_path_down_recovery(clp);
L
Linus Torvalds 已提交
5061
	}
5062
	do_renew_lease(clp, timestamp);
L
Linus Torvalds 已提交
5063 5064
}

5065 5066
static const struct rpc_call_ops nfs4_renew_ops = {
	.rpc_call_done = nfs4_renew_done,
5067
	.rpc_release = nfs4_renew_release,
5068 5069
};

5070
static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
L
Linus Torvalds 已提交
5071 5072 5073 5074
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
		.rpc_argp	= clp,
5075
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
5076
	};
5077
	struct nfs4_renewdata *data;
L
Linus Torvalds 已提交
5078

5079 5080
	if (renew_flags == 0)
		return 0;
5081
	if (!refcount_inc_not_zero(&clp->cl_count))
5082
		return -EIO;
5083
	data = kmalloc(sizeof(*data), GFP_NOFS);
5084 5085
	if (data == NULL) {
		nfs_put_client(clp);
5086
		return -ENOMEM;
5087
	}
5088 5089
	data->client = clp;
	data->timestamp = jiffies;
5090
	return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
5091
			&nfs4_renew_ops, data);
L
Linus Torvalds 已提交
5092 5093
}

5094
static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
L
Linus Torvalds 已提交
5095 5096 5097 5098
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
		.rpc_argp	= clp,
5099
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
5100 5101 5102 5103
	};
	unsigned long now = jiffies;
	int status;

5104
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
L
Linus Torvalds 已提交
5105 5106
	if (status < 0)
		return status;
5107
	do_renew_lease(clp, now);
L
Linus Torvalds 已提交
5108 5109 5110
	return 0;
}

5111 5112
static inline int nfs4_server_supports_acls(struct nfs_server *server)
{
5113
	return server->caps & NFS_CAP_ACLS;
5114 5115
}

5116 5117
/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that
 * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on
5118 5119
 * the stack.
 */
5120
#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
5121

5122
static int buf_to_pages_noslab(const void *buf, size_t buflen,
5123
		struct page **pages)
5124 5125 5126 5127 5128 5129 5130
{
	struct page *newpage, **spages;
	int rc = 0;
	size_t len;
	spages = pages;

	do {
5131
		len = min_t(size_t, PAGE_SIZE, buflen);
5132 5133 5134 5135 5136
		newpage = alloc_page(GFP_KERNEL);

		if (newpage == NULL)
			goto unwind;
		memcpy(page_address(newpage), buf, len);
5137 5138
		buf += len;
		buflen -= len;
5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150
		*pages++ = newpage;
		rc++;
	} while (buflen != 0);

	return rc;

unwind:
	for(; rc > 0; rc--)
		__free_page(spages[rc-1]);
	return -ENOMEM;
}

5151 5152 5153
struct nfs4_cached_acl {
	int cached;
	size_t len;
A
Andrew Morton 已提交
5154
	char data[0];
5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196
};

static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
{
	struct nfs_inode *nfsi = NFS_I(inode);

	spin_lock(&inode->i_lock);
	kfree(nfsi->nfs4_acl);
	nfsi->nfs4_acl = acl;
	spin_unlock(&inode->i_lock);
}

static void nfs4_zap_acl_attr(struct inode *inode)
{
	nfs4_set_cached_acl(inode, NULL);
}

static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
{
	struct nfs_inode *nfsi = NFS_I(inode);
	struct nfs4_cached_acl *acl;
	int ret = -ENOENT;

	spin_lock(&inode->i_lock);
	acl = nfsi->nfs4_acl;
	if (acl == NULL)
		goto out;
	if (buf == NULL) /* user is just asking for length */
		goto out_len;
	if (acl->cached == 0)
		goto out;
	ret = -ERANGE; /* see getxattr(2) man page */
	if (acl->len > buflen)
		goto out;
	memcpy(buf, acl->data, acl->len);
out_len:
	ret = acl->len;
out:
	spin_unlock(&inode->i_lock);
	return ret;
}

5197
static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
5198 5199
{
	struct nfs4_cached_acl *acl;
5200
	size_t buflen = sizeof(*acl) + acl_len;
5201

5202
	if (buflen <= PAGE_SIZE) {
5203
		acl = kmalloc(buflen, GFP_KERNEL);
5204 5205 5206
		if (acl == NULL)
			goto out;
		acl->cached = 1;
5207
		_copy_from_pages(acl->data, pages, pgbase, acl_len);
5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218
	} else {
		acl = kmalloc(sizeof(*acl), GFP_KERNEL);
		if (acl == NULL)
			goto out;
		acl->cached = 0;
	}
	acl->len = acl_len;
out:
	nfs4_set_cached_acl(inode, acl);
}

5219 5220 5221 5222 5223 5224 5225 5226 5227 5228
/*
 * The getxattr API returns the required buffer length when called with a
 * NULL buf. The NFSv4 acl tool then calls getxattr again after allocating
 * the required buf.  On a NULL buf, we send a page of data to the server
 * guessing that the ACL request can be serviced by a page. If so, we cache
 * up to the page of ACL data, and the 2nd call to getxattr is serviced by
 * the cache. If not so, we throw away the page, and cache the required
 * length. The next getxattr call will then produce another round trip to
 * the server, this time with the input buf of the required size.
 */
5229
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
5230
{
5231
	struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, };
5232 5233 5234 5235 5236
	struct nfs_getaclargs args = {
		.fh = NFS_FH(inode),
		.acl_pages = pages,
		.acl_len = buflen,
	};
B
Benny Halevy 已提交
5237 5238 5239
	struct nfs_getaclres res = {
		.acl_len = buflen,
	};
5240 5241 5242
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
		.rpc_argp = &args,
B
Benny Halevy 已提交
5243
		.rpc_resp = &res,
5244
	};
5245
	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
5246
	int ret = -ENOMEM, i;
5247

5248 5249
	if (npages > ARRAY_SIZE(pages))
		return -ERANGE;
5250

5251 5252 5253 5254
	for (i = 0; i < npages; i++) {
		pages[i] = alloc_page(GFP_KERNEL);
		if (!pages[i])
			goto out_free;
5255
	}
5256 5257 5258 5259 5260 5261

	/* for decoding across pages */
	res.acl_scratch = alloc_page(GFP_KERNEL);
	if (!res.acl_scratch)
		goto out_free;

5262
	args.acl_len = npages * PAGE_SIZE;
5263

5264
	dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
5265 5266 5267
		__func__, buf, buflen, npages, args.acl_len);
	ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode),
			     &msg, &args.seq_args, &res.seq_res, 0);
5268 5269
	if (ret)
		goto out_free;
5270

5271 5272 5273 5274 5275
	/* Handle the case where the passed-in buffer is too short */
	if (res.acl_flags & NFS4_ACL_TRUNC) {
		/* Did the user only issue a request for the acl length? */
		if (buf == NULL)
			goto out_ok;
5276
		ret = -ERANGE;
5277
		goto out_free;
5278
	}
5279
	nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
5280 5281 5282 5283 5284
	if (buf) {
		if (res.acl_len > buflen) {
			ret = -ERANGE;
			goto out_free;
		}
5285
		_copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
5286
	}
5287 5288
out_ok:
	ret = res.acl_len;
5289
out_free:
5290 5291 5292
	for (i = 0; i < npages; i++)
		if (pages[i])
			__free_page(pages[i]);
5293 5294
	if (res.acl_scratch)
		__free_page(res.acl_scratch);
5295 5296 5297
	return ret;
}

5298 5299 5300 5301 5302 5303
static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
{
	struct nfs4_exception exception = { };
	ssize_t ret;
	do {
		ret = __nfs4_get_acl_uncached(inode, buf, buflen);
5304
		trace_nfs4_get_acl(inode, ret);
5305 5306 5307 5308 5309 5310 5311
		if (ret >= 0)
			break;
		ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
	} while (exception.retry);
	return ret;
}

5312 5313 5314 5315 5316 5317 5318 5319 5320 5321
static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
{
	struct nfs_server *server = NFS_SERVER(inode);
	int ret;

	if (!nfs4_server_supports_acls(server))
		return -EOPNOTSUPP;
	ret = nfs_revalidate_inode(server, inode);
	if (ret < 0)
		return ret;
5322 5323
	if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
		nfs_zap_acl_cache(inode);
5324 5325
	ret = nfs4_read_cached_acl(inode, buf, buflen);
	if (ret != -ENOENT)
5326 5327
		/* -ENOENT is returned if there is no ACL or if there is an ACL
		 * but no cached acl data, just the acl length */
5328 5329 5330 5331
		return ret;
	return nfs4_get_acl_uncached(inode, buf, buflen);
}

5332
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
5333 5334 5335 5336 5337 5338 5339 5340
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct page *pages[NFS4ACL_MAXPAGES];
	struct nfs_setaclargs arg = {
		.fh		= NFS_FH(inode),
		.acl_pages	= pages,
		.acl_len	= buflen,
	};
B
Benny Halevy 已提交
5341
	struct nfs_setaclres res;
5342 5343 5344
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETACL],
		.rpc_argp	= &arg,
B
Benny Halevy 已提交
5345
		.rpc_resp	= &res,
5346
	};
5347
	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
5348
	int ret, i;
5349 5350 5351

	if (!nfs4_server_supports_acls(server))
		return -EOPNOTSUPP;
5352 5353
	if (npages > ARRAY_SIZE(pages))
		return -ERANGE;
5354
	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages);
5355 5356
	if (i < 0)
		return i;
5357
	nfs4_inode_make_writeable(inode);
5358
	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
5359 5360 5361 5362 5363 5364 5365 5366

	/*
	 * Free each page after tx, so the only ref left is
	 * held by the network stack
	 */
	for (; i > 0; i--)
		put_page(pages[i-1]);

5367 5368 5369 5370 5371
	/*
	 * Acl update can result in inode attribute update.
	 * so mark the attribute cache invalid.
	 */
	spin_lock(&inode->i_lock);
5372 5373
	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
		| NFS_INO_INVALID_CTIME;
5374
	spin_unlock(&inode->i_lock);
5375 5376
	nfs_access_zap_cache(inode);
	nfs_zap_acl_cache(inode);
5377 5378 5379
	return ret;
}

5380 5381 5382 5383 5384
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
{
	struct nfs4_exception exception = { };
	int err;
	do {
5385 5386 5387
		err = __nfs4_proc_set_acl(inode, buf, buflen);
		trace_nfs4_set_acl(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
5388 5389 5390 5391 5392
				&exception);
	} while (exception.retry);
	return err;
}

5393 5394 5395 5396 5397 5398 5399 5400 5401
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
static int _nfs4_get_security_label(struct inode *inode, void *buf,
					size_t buflen)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_fattr fattr;
	struct nfs4_label label = {0, 0, buflen, buf};

	u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL };
5402
	struct nfs4_getattr_arg arg = {
5403 5404 5405 5406 5407 5408 5409 5410 5411 5412
		.fh		= NFS_FH(inode),
		.bitmask	= bitmask,
	};
	struct nfs4_getattr_res res = {
		.fattr		= &fattr,
		.label		= &label,
		.server		= server,
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
5413
		.rpc_argp	= &arg,
5414 5415 5416 5417 5418 5419
		.rpc_resp	= &res,
	};
	int ret;

	nfs_fattr_init(&fattr);

5420
	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 0);
5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439
	if (ret)
		return ret;
	if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL))
		return -ENOENT;
	if (buflen < label.len)
		return -ERANGE;
	return 0;
}

static int nfs4_get_security_label(struct inode *inode, void *buf,
					size_t buflen)
{
	struct nfs4_exception exception = { };
	int err;

	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
		return -EOPNOTSUPP;

	do {
5440 5441 5442
		err = _nfs4_get_security_label(inode, buf, buflen);
		trace_nfs4_get_security_label(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_do_set_security_label(struct inode *inode,
		struct nfs4_label *ilabel,
		struct nfs_fattr *fattr,
		struct nfs4_label *olabel)
{

	struct iattr sattr = {0};
	struct nfs_server *server = NFS_SERVER(inode);
	const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL };
5457
	struct nfs_setattrargs arg = {
5458 5459
		.fh		= NFS_FH(inode),
		.iap		= &sattr,
5460 5461 5462 5463 5464 5465 5466 5467 5468 5469
		.server		= server,
		.bitmask	= bitmask,
		.label		= ilabel,
	};
	struct nfs_setattrres res = {
		.fattr		= fattr,
		.label		= olabel,
		.server		= server,
	};
	struct rpc_message msg = {
5470 5471 5472
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
5473 5474 5475
	};
	int status;

5476
	nfs4_stateid_copy(&arg.stateid, &zero_stateid);
5477

5478
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493
	if (status)
		dprintk("%s failed: %d\n", __func__, status);

	return status;
}

static int nfs4_do_set_security_label(struct inode *inode,
		struct nfs4_label *ilabel,
		struct nfs_fattr *fattr,
		struct nfs4_label *olabel)
{
	struct nfs4_exception exception = { };
	int err;

	do {
5494 5495 5496 5497
		err = _nfs4_do_set_security_label(inode, ilabel,
				fattr, olabel);
		trace_nfs4_set_security_label(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
5498 5499 5500 5501 5502 5503
				&exception);
	} while (exception.retry);
	return err;
}

static int
5504
nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542
{
	struct nfs4_label ilabel, *olabel = NULL;
	struct nfs_fattr fattr;
	struct rpc_cred *cred;
	int status;

	if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
		return -EOPNOTSUPP;

	nfs_fattr_init(&fattr);

	ilabel.pi = 0;
	ilabel.lfs = 0;
	ilabel.label = (char *)buf;
	ilabel.len = buflen;

	cred = rpc_lookup_cred();
	if (IS_ERR(cred))
		return PTR_ERR(cred);

	olabel = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
	if (IS_ERR(olabel)) {
		status = -PTR_ERR(olabel);
		goto out;
	}

	status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel);
	if (status == 0)
		nfs_setsecurity(inode, &fattr, olabel);

	nfs4_label_free(olabel);
out:
	put_rpccred(cred);
	return status;
}
#endif	/* CONFIG_NFS_V4_SECURITY_LABEL */


5543 5544
static void nfs4_init_boot_verifier(const struct nfs_client *clp,
				    nfs4_verifier *bootverf)
5545 5546 5547
{
	__be32 verf[2];

5548 5549 5550
	if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
		/* An impossible timestamp guarantees this value
		 * will never match a generated boot time. */
5551 5552
		verf[0] = cpu_to_be32(U32_MAX);
		verf[1] = cpu_to_be32(U32_MAX);
5553
	} else {
5554
		struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
5555 5556 5557 5558
		u64 ns = ktime_to_ns(nn->boot_time);

		verf[0] = cpu_to_be32(ns >> 32);
		verf[1] = cpu_to_be32(ns);
5559
	}
5560 5561 5562
	memcpy(bootverf->data, verf, sizeof(bootverf->data));
}

5563 5564
static int
nfs4_init_nonuniform_client_string(struct nfs_client *clp)
5565
{
5566 5567
	size_t len;
	char *str;
5568

5569
	if (clp->cl_owner_id != NULL)
5570
		return 0;
5571

5572
	rcu_read_lock();
5573
	len = 14 + strlen(clp->cl_ipaddr) + 1 +
5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590
		strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
		1 +
		strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)) +
		1;
	rcu_read_unlock();

	if (len > NFS4_OPAQUE_LIMIT + 1)
		return -EINVAL;

	/*
	 * Since this string is allocated at mount time, and held until the
	 * nfs_client is destroyed, we can use GFP_KERNEL here w/o worrying
	 * about a memory-reclaim deadlock.
	 */
	str = kmalloc(len, GFP_KERNEL);
	if (!str)
		return -ENOMEM;
5591

5592
	rcu_read_lock();
5593
	scnprintf(str, len, "Linux NFSv4.0 %s/%s %s",
5594 5595 5596
			clp->cl_ipaddr,
			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO));
5597
	rcu_read_unlock();
5598 5599 5600

	clp->cl_owner_id = str;
	return 0;
5601 5602
}

5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624
static int
nfs4_init_uniquifier_client_string(struct nfs_client *clp)
{
	size_t len;
	char *str;

	len = 10 + 10 + 1 + 10 + 1 +
		strlen(nfs4_client_id_uniquifier) + 1 +
		strlen(clp->cl_rpcclient->cl_nodename) + 1;

	if (len > NFS4_OPAQUE_LIMIT + 1)
		return -EINVAL;

	/*
	 * Since this string is allocated at mount time, and held until the
	 * nfs_client is destroyed, we can use GFP_KERNEL here w/o worrying
	 * about a memory-reclaim deadlock.
	 */
	str = kmalloc(len, GFP_KERNEL);
	if (!str)
		return -ENOMEM;

5625
	scnprintf(str, len, "Linux NFSv%u.%u %s/%s",
5626 5627 5628 5629 5630 5631 5632 5633 5634
			clp->rpc_ops->version, clp->cl_minorversion,
			nfs4_client_id_uniquifier,
			clp->cl_rpcclient->cl_nodename);
	clp->cl_owner_id = str;
	return 0;
}

static int
nfs4_init_uniform_client_string(struct nfs_client *clp)
5635
{
5636 5637
	size_t len;
	char *str;
5638 5639

	if (clp->cl_owner_id != NULL)
5640
		return 0;
5641 5642

	if (nfs4_client_id_uniquifier[0] != '\0')
5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659
		return nfs4_init_uniquifier_client_string(clp);

	len = 10 + 10 + 1 + 10 + 1 +
		strlen(clp->cl_rpcclient->cl_nodename) + 1;

	if (len > NFS4_OPAQUE_LIMIT + 1)
		return -EINVAL;

	/*
	 * Since this string is allocated at mount time, and held until the
	 * nfs_client is destroyed, we can use GFP_KERNEL here w/o worrying
	 * about a memory-reclaim deadlock.
	 */
	str = kmalloc(len, GFP_KERNEL);
	if (!str)
		return -ENOMEM;

5660
	scnprintf(str, len, "Linux NFSv%u.%u %s",
5661 5662 5663 5664
			clp->rpc_ops->version, clp->cl_minorversion,
			clp->cl_rpcclient->cl_nodename);
	clp->cl_owner_id = str;
	return 0;
5665 5666
}

5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680
/*
 * nfs4_callback_up_net() starts only "tcp" and "tcp6" callback
 * services.  Advertise one based on the address family of the
 * clientaddr.
 */
static unsigned int
nfs4_init_callback_netid(const struct nfs_client *clp, char *buf, size_t len)
{
	if (strchr(clp->cl_ipaddr, ':') != NULL)
		return scnprintf(buf, len, "tcp6");
	else
		return scnprintf(buf, len, "tcp");
}

5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692
static void nfs4_setclientid_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_setclientid *sc = calldata;

	if (task->tk_status == 0)
		sc->sc_cred = get_rpccred(task->tk_rqstp->rq_cred);
}

static const struct rpc_call_ops nfs4_setclientid_ops = {
	.rpc_call_done = nfs4_setclientid_done,
};

5693 5694 5695 5696 5697 5698 5699 5700 5701 5702
/**
 * nfs4_proc_setclientid - Negotiate client ID
 * @clp: state data structure
 * @program: RPC program for NFSv4 callback service
 * @port: IP port number for NFS4 callback service
 * @cred: RPC credential to use for this call
 * @res: where to place the result
 *
 * Returns zero, a negative errno, or a negative NFS4ERR status code.
 */
5703 5704 5705
int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
		unsigned short port, struct rpc_cred *cred,
		struct nfs4_setclientid_res *res)
L
Linus Torvalds 已提交
5706 5707 5708 5709 5710
{
	nfs4_verifier sc_verifier;
	struct nfs4_setclientid setclientid = {
		.sc_verifier = &sc_verifier,
		.sc_prog = program,
5711
		.sc_clnt = clp,
L
Linus Torvalds 已提交
5712 5713 5714 5715
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
		.rpc_argp = &setclientid,
5716
		.rpc_resp = res,
5717
		.rpc_cred = cred,
L
Linus Torvalds 已提交
5718
	};
5719 5720 5721 5722 5723 5724 5725 5726
	struct rpc_task *task;
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.rpc_message = &msg,
		.callback_ops = &nfs4_setclientid_ops,
		.callback_data = &setclientid,
		.flags = RPC_TASK_TIMEOUT,
	};
5727
	int status;
L
Linus Torvalds 已提交
5728

5729
	/* nfs_client_id4 */
5730
	nfs4_init_boot_verifier(clp, &sc_verifier);
5731 5732 5733 5734

	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags))
		status = nfs4_init_uniform_client_string(clp);
	else
5735
		status = nfs4_init_nonuniform_client_string(clp);
5736 5737 5738

	if (status)
		goto out;
5739

5740
	/* cb_client4 */
5741 5742 5743 5744
	setclientid.sc_netid_len =
				nfs4_init_callback_netid(clp,
						setclientid.sc_netid,
						sizeof(setclientid.sc_netid));
5745
	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
5746
				sizeof(setclientid.sc_uaddr), "%s.%u.%u",
L
Linus Torvalds 已提交
5747 5748
				clp->cl_ipaddr, port >> 8, port & 255);

5749
	dprintk("NFS call  setclientid auth=%s, '%s'\n",
5750
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
5751
		clp->cl_owner_id);
5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task)) {
		status = PTR_ERR(task);
		goto out;
	}
	status = task->tk_status;
	if (setclientid.sc_cred) {
		clp->cl_acceptor = rpcauth_stringify_acceptor(setclientid.sc_cred);
		put_rpccred(setclientid.sc_cred);
	}
	rpc_put_task(task);
out:
5764
	trace_nfs4_setclientid(clp, status);
5765 5766
	dprintk("NFS reply setclientid: %d\n", status);
	return status;
L
Linus Torvalds 已提交
5767 5768
}

5769 5770 5771 5772 5773 5774 5775 5776
/**
 * nfs4_proc_setclientid_confirm - Confirm client ID
 * @clp: state data structure
 * @res: result of a previous SETCLIENTID
 * @cred: RPC credential to use for this call
 *
 * Returns zero, a negative errno, or a negative NFS4ERR status code.
 */
5777
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
5778 5779
		struct nfs4_setclientid_res *arg,
		struct rpc_cred *cred)
L
Linus Torvalds 已提交
5780 5781 5782
{
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
5783
		.rpc_argp = arg,
5784
		.rpc_cred = cred,
L
Linus Torvalds 已提交
5785 5786 5787
	};
	int status;

5788 5789 5790
	dprintk("NFS call  setclientid_confirm auth=%s, (client ID %llx)\n",
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
		clp->cl_clientid);
5791
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
5792
	trace_nfs4_setclientid_confirm(clp, status);
5793
	dprintk("NFS reply setclientid_confirm: %d\n", status);
L
Linus Torvalds 已提交
5794 5795 5796
	return status;
}

5797 5798
struct nfs4_delegreturndata {
	struct nfs4_delegreturnargs args;
5799
	struct nfs4_delegreturnres res;
5800 5801
	struct nfs_fh fh;
	nfs4_stateid stateid;
5802
	unsigned long timestamp;
5803 5804 5805
	struct {
		struct nfs4_layoutreturn_args arg;
		struct nfs4_layoutreturn_res res;
5806
		struct nfs4_xdr_opaque_data ld_private;
5807 5808 5809
		u32 roc_barrier;
		bool roc;
	} lr;
5810
	struct nfs_fattr fattr;
5811
	int rpc_status;
5812
	struct inode *inode;
5813 5814 5815 5816 5817
};

static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_delegreturndata *data = calldata;
5818 5819 5820 5821
	struct nfs4_exception exception = {
		.inode = data->inode,
		.stateid = &data->stateid,
	};
5822

5823 5824
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return;
5825

5826
	trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837

	/* Handle Layoutreturn errors */
	if (data->args.lr_args && task->tk_status != 0) {
		switch(data->res.lr_ret) {
		default:
			data->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
			break;
		case 0:
			data->args.lr_args = NULL;
			data->res.lr_res = NULL;
			break;
5838 5839
		case -NFS4ERR_OLD_STATEID:
			if (nfs4_refresh_layout_stateid(&data->args.lr_args->stateid,
5840 5841
						data->inode))
				goto lr_restart;
5842
			/* Fallthrough */
5843 5844 5845 5846 5847 5848 5849 5850
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_EXPIRED:
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
		case -NFS4ERR_WRONG_CRED:
			data->args.lr_args = NULL;
			data->res.lr_res = NULL;
5851
			goto lr_restart;
5852 5853 5854
		}
	}

5855 5856
	switch (task->tk_status) {
	case 0:
5857
		renew_lease(data->res.server, data->timestamp);
5858
		break;
5859 5860
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_DELEG_REVOKED:
5861 5862 5863 5864
	case -NFS4ERR_EXPIRED:
		nfs4_free_revoked_stateid(data->res.server,
				data->args.stateid,
				task->tk_msg.rpc_cred);
5865
		/* Fallthrough */
5866 5867 5868 5869
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_STALE_STATEID:
		task->tk_status = 0;
		break;
5870
	case -NFS4ERR_OLD_STATEID:
5871 5872
		if (nfs4_refresh_delegation_stateid(&data->stateid, data->inode))
			goto out_restart;
5873 5874
		task->tk_status = 0;
		break;
5875 5876 5877 5878
	case -NFS4ERR_ACCESS:
		if (data->args.bitmask) {
			data->args.bitmask = NULL;
			data->res.fattr = NULL;
5879
			goto out_restart;
5880
		}
5881
		/* Fallthrough */
5882
	default:
5883 5884 5885 5886
		task->tk_status = nfs4_async_handle_exception(task,
				data->res.server, task->tk_status,
				&exception);
		if (exception.retry)
5887
			goto out_restart;
5888 5889
	}
	data->rpc_status = task->tk_status;
5890 5891 5892 5893 5894 5895
	return;
lr_restart:
	data->res.lr_ret = 0;
out_restart:
	task->tk_status = 0;
	rpc_restart_call_prepare(task);
5896 5897 5898 5899
}

static void nfs4_delegreturn_release(void *calldata)
{
5900
	struct nfs4_delegreturndata *data = calldata;
5901
	struct inode *inode = data->inode;
5902

5903
	if (inode) {
5904
		if (data->lr.roc)
5905 5906
			pnfs_roc_release(&data->lr.arg, &data->lr.res,
					data->res.lr_ret);
5907
		nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
5908 5909
		nfs_iput_and_deactive(inode);
	}
5910 5911 5912
	kfree(calldata);
}

5913 5914 5915 5916 5917 5918
static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
{
	struct nfs4_delegreturndata *d_data;

	d_data = (struct nfs4_delegreturndata *)data;

5919
	if (!d_data->lr.roc && nfs4_wait_on_layoutreturn(d_data->inode, task))
5920 5921
		return;

5922
	nfs4_setup_sequence(d_data->res.server->nfs_client,
5923 5924 5925
			&d_data->args.seq_args,
			&d_data->res.seq_res,
			task);
5926 5927
}

5928
static const struct rpc_call_ops nfs4_delegreturn_ops = {
5929
	.rpc_call_prepare = nfs4_delegreturn_prepare,
5930 5931 5932 5933
	.rpc_call_done = nfs4_delegreturn_done,
	.rpc_release = nfs4_delegreturn_release,
};

5934
static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
5935 5936
{
	struct nfs4_delegreturndata *data;
5937
	struct nfs_server *server = NFS_SERVER(inode);
5938
	struct rpc_task *task;
5939 5940 5941 5942
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
		.rpc_cred = cred,
	};
T
Trond Myklebust 已提交
5943 5944
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
5945
		.rpc_message = &msg,
T
Trond Myklebust 已提交
5946 5947 5948
		.callback_ops = &nfs4_delegreturn_ops,
		.flags = RPC_TASK_ASYNC,
	};
5949
	int status = 0;
5950

5951
	data = kzalloc(sizeof(*data), GFP_NOFS);
5952 5953
	if (data == NULL)
		return -ENOMEM;
5954
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
5955 5956 5957 5958 5959

	nfs4_state_protect(server->nfs_client,
			NFS_SP4_MACH_CRED_CLEANUP,
			&task_setup_data.rpc_client, &msg);

5960 5961
	data->args.fhandle = &data->fh;
	data->args.stateid = &data->stateid;
5962
	data->args.bitmask = server->cache_consistency_bitmask;
5963
	nfs_copy_fh(&data->fh, NFS_FH(inode));
5964
	nfs4_stateid_copy(&data->stateid, stateid);
5965 5966
	data->res.fattr = &data->fattr;
	data->res.server = server;
5967
	data->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
5968
	data->lr.arg.ld_private = &data->lr.ld_private;
5969
	nfs_fattr_init(data->res.fattr);
5970
	data->timestamp = jiffies;
5971
	data->rpc_status = 0;
5972
	data->lr.roc = pnfs_roc(inode, &data->lr.arg, &data->lr.res, cred);
5973
	data->inode = nfs_igrab_and_active(inode);
5974 5975 5976 5977 5978
	if (data->inode) {
		if (data->lr.roc) {
			data->args.lr_args = &data->lr.arg;
			data->res.lr_res = &data->lr.res;
		}
5979 5980 5981
	} else if (data->lr.roc) {
		pnfs_roc_release(&data->lr.arg, &data->lr.res, 0);
		data->lr.roc = false;
5982
	}
5983

T
Trond Myklebust 已提交
5984
	task_setup_data.callback_data = data;
5985 5986
	msg.rpc_argp = &data->args;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
5987
	task = rpc_run_task(&task_setup_data);
5988
	if (IS_ERR(task))
5989
		return PTR_ERR(task);
5990 5991
	if (!issync)
		goto out;
5992
	status = rpc_wait_for_completion_task(task);
5993 5994 5995 5996
	if (status != 0)
		goto out;
	status = data->rpc_status;
out:
5997
	rpc_put_task(task);
5998
	return status;
L
Linus Torvalds 已提交
5999 6000
}

6001
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
L
Linus Torvalds 已提交
6002 6003 6004 6005 6006
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs4_exception exception = { };
	int err;
	do {
6007
		err = _nfs4_proc_delegreturn(inode, cred, stateid, issync);
6008
		trace_nfs4_delegreturn(inode, stateid, err);
L
Linus Torvalds 已提交
6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023
		switch (err) {
			case -NFS4ERR_STALE_STATEID:
			case -NFS4ERR_EXPIRED:
			case 0:
				return 0;
		}
		err = nfs4_handle_exception(server, err, &exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
	struct inode *inode = state->inode;
	struct nfs_server *server = NFS_SERVER(inode);
6024
	struct nfs_client *clp = server->nfs_client;
T
Trond Myklebust 已提交
6025
	struct nfs_lockt_args arg = {
L
Linus Torvalds 已提交
6026
		.fh = NFS_FH(inode),
T
Trond Myklebust 已提交
6027
		.fl = request,
L
Linus Torvalds 已提交
6028
	};
T
Trond Myklebust 已提交
6029 6030
	struct nfs_lockt_res res = {
		.denied = request,
L
Linus Torvalds 已提交
6031 6032 6033
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_LOCKT],
6034 6035
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
L
Linus Torvalds 已提交
6036 6037 6038 6039 6040
		.rpc_cred	= state->owner->so_cred,
	};
	struct nfs4_lock_state *lsp;
	int status;

T
Trond Myklebust 已提交
6041
	arg.lock_owner.clientid = clp->cl_clientid;
6042 6043 6044 6045
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		goto out;
	lsp = request->fl_u.nfs4_fl.owner;
6046
	arg.lock_owner.id = lsp->ls_seqid.owner_id;
6047
	arg.lock_owner.s_dev = server->s_dev;
6048
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
T
Trond Myklebust 已提交
6049 6050 6051 6052 6053 6054
	switch (status) {
		case 0:
			request->fl_type = F_UNLCK;
			break;
		case -NFS4ERR_DENIED:
			status = 0;
L
Linus Torvalds 已提交
6055
	}
6056
	request->fl_ops->fl_release_private(request);
6057
	request->fl_ops = NULL;
6058
out:
L
Linus Torvalds 已提交
6059 6060 6061 6062 6063 6064 6065 6066 6067
	return status;
}

static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
	struct nfs4_exception exception = { };
	int err;

	do {
6068 6069 6070
		err = _nfs4_proc_getlk(state, cmd, request);
		trace_nfs4_get_lock(request, state, cmd, err);
		err = nfs4_handle_exception(NFS_SERVER(state->inode), err,
L
Linus Torvalds 已提交
6071 6072 6073 6074 6075
				&exception);
	} while (exception.retry);
	return err;
}

6076
struct nfs4_unlockdata {
T
Trond Myklebust 已提交
6077 6078
	struct nfs_locku_args arg;
	struct nfs_locku_res res;
6079 6080
	struct nfs4_lock_state *lsp;
	struct nfs_open_context *ctx;
6081
	struct nfs_lock_context *l_ctx;
T
Trond Myklebust 已提交
6082
	struct file_lock fl;
6083
	struct nfs_server *server;
6084
	unsigned long timestamp;
6085 6086
};

T
Trond Myklebust 已提交
6087 6088 6089 6090 6091 6092 6093 6094
static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
		struct nfs_open_context *ctx,
		struct nfs4_lock_state *lsp,
		struct nfs_seqid *seqid)
{
	struct nfs4_unlockdata *p;
	struct inode *inode = lsp->ls_state->inode;

6095
	p = kzalloc(sizeof(*p), GFP_NOFS);
T
Trond Myklebust 已提交
6096 6097 6098 6099 6100
	if (p == NULL)
		return NULL;
	p->arg.fh = NFS_FH(inode);
	p->arg.fl = &p->fl;
	p->arg.seqid = seqid;
6101
	p->res.seqid = seqid;
T
Trond Myklebust 已提交
6102
	p->lsp = lsp;
6103
	refcount_inc(&lsp->ls_count);
T
Trond Myklebust 已提交
6104 6105
	/* Ensure we don't close file until we're done freeing locks! */
	p->ctx = get_nfs_open_context(ctx);
6106
	p->l_ctx = nfs_get_lock_context(ctx);
T
Trond Myklebust 已提交
6107 6108 6109 6110 6111
	memcpy(&p->fl, fl, sizeof(p->fl));
	p->server = NFS_SERVER(inode);
	return p;
}

6112
static void nfs4_locku_release_calldata(void *data)
6113
{
6114
	struct nfs4_unlockdata *calldata = data;
T
Trond Myklebust 已提交
6115
	nfs_free_seqid(calldata->arg.seqid);
6116
	nfs4_put_lock_state(calldata->lsp);
6117
	nfs_put_lock_context(calldata->l_ctx);
6118 6119
	put_nfs_open_context(calldata->ctx);
	kfree(calldata);
6120 6121
}

6122
static void nfs4_locku_done(struct rpc_task *task, void *data)
6123
{
6124
	struct nfs4_unlockdata *calldata = data;
6125 6126 6127 6128
	struct nfs4_exception exception = {
		.inode = calldata->lsp->ls_state->inode,
		.stateid = &calldata->arg.stateid,
	};
6129

6130 6131
	if (!nfs4_sequence_done(task, &calldata->res.seq_res))
		return;
6132 6133
	switch (task->tk_status) {
		case 0:
6134
			renew_lease(calldata->server, calldata->timestamp);
6135
			locks_lock_inode_wait(calldata->lsp->ls_state->inode, &calldata->fl);
6136 6137 6138
			if (nfs4_update_lock_stateid(calldata->lsp,
					&calldata->res.stateid))
				break;
6139 6140 6141 6142 6143
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_EXPIRED:
			nfs4_free_revoked_stateid(calldata->server,
					&calldata->arg.stateid,
					task->tk_msg.rpc_cred);
6144 6145
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_OLD_STATEID:
6146
		case -NFS4ERR_STALE_STATEID:
6147 6148 6149
			if (!nfs4_stateid_match(&calldata->arg.stateid,
						&calldata->lsp->ls_stateid))
				rpc_restart_call_prepare(task);
6150 6151
			break;
		default:
6152 6153 6154 6155
			task->tk_status = nfs4_async_handle_exception(task,
					calldata->server, task->tk_status,
					&exception);
			if (exception.retry)
6156
				rpc_restart_call_prepare(task);
6157
	}
6158
	nfs_release_seqid(calldata->arg.seqid);
6159 6160
}

T
Trond Myklebust 已提交
6161
static void nfs4_locku_prepare(struct rpc_task *task, void *data)
6162
{
T
Trond Myklebust 已提交
6163
	struct nfs4_unlockdata *calldata = data;
6164

6165 6166 6167 6168
	if (test_bit(NFS_CONTEXT_UNLOCK, &calldata->l_ctx->open_context->flags) &&
		nfs_async_iocounter_wait(task, calldata->l_ctx))
		return;

T
Trond Myklebust 已提交
6169
	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
6170
		goto out_wait;
6171
	nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid);
6172
	if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
6173
		/* Note: exit _without_ running nfs4_locku_done */
6174
		goto out_no_action;
6175
	}
6176
	calldata->timestamp = jiffies;
6177
	if (nfs4_setup_sequence(calldata->server->nfs_client,
6178
				&calldata->arg.seq_args,
6179 6180 6181
				&calldata->res.seq_res,
				task) != 0)
		nfs_release_seqid(calldata->arg.seqid);
6182 6183 6184 6185 6186
	return;
out_no_action:
	task->tk_action = NULL;
out_wait:
	nfs4_sequence_done(task, &calldata->res.seq_res);
6187 6188
}

6189
static const struct rpc_call_ops nfs4_locku_ops = {
T
Trond Myklebust 已提交
6190
	.rpc_call_prepare = nfs4_locku_prepare,
6191
	.rpc_call_done = nfs4_locku_done,
6192
	.rpc_release = nfs4_locku_release_calldata,
6193 6194
};

6195 6196 6197 6198 6199 6200
static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
		struct nfs_open_context *ctx,
		struct nfs4_lock_state *lsp,
		struct nfs_seqid *seqid)
{
	struct nfs4_unlockdata *data;
6201 6202 6203 6204
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
		.rpc_cred = ctx->cred,
	};
T
Trond Myklebust 已提交
6205 6206
	struct rpc_task_setup task_setup_data = {
		.rpc_client = NFS_CLIENT(lsp->ls_state->inode),
6207
		.rpc_message = &msg,
T
Trond Myklebust 已提交
6208
		.callback_ops = &nfs4_locku_ops,
6209
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
6210 6211
		.flags = RPC_TASK_ASYNC,
	};
6212

6213 6214 6215
	nfs4_state_protect(NFS_SERVER(lsp->ls_state->inode)->nfs_client,
		NFS_SP4_MACH_CRED_CLEANUP, &task_setup_data.rpc_client, &msg);

6216 6217 6218 6219
	/* Ensure this is an unlock - when canceling a lock, the
	 * canceled lock is passed in, and it won't be an unlock.
	 */
	fl->fl_type = F_UNLCK;
6220 6221
	if (fl->fl_flags & FL_CLOSE)
		set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
6222

6223 6224 6225 6226 6227 6228
	data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
	if (data == NULL) {
		nfs_free_seqid(seqid);
		return ERR_PTR(-ENOMEM);
	}

6229
	nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
6230 6231
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
6232 6233
	task_setup_data.callback_data = data;
	return rpc_run_task(&task_setup_data);
6234 6235
}

6236 6237
static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
6238 6239 6240
	struct inode *inode = state->inode;
	struct nfs4_state_owner *sp = state->owner;
	struct nfs_inode *nfsi = NFS_I(inode);
T
Trond Myklebust 已提交
6241
	struct nfs_seqid *seqid;
L
Linus Torvalds 已提交
6242
	struct nfs4_lock_state *lsp;
6243
	struct rpc_task *task;
6244
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
6245
	int status = 0;
6246
	unsigned char fl_flags = request->fl_flags;
6247

6248
	status = nfs4_set_lock_state(state, request);
6249 6250
	/* Unlock _before_ we do the RPC call */
	request->fl_flags |= FL_EXISTS;
6251 6252 6253
	/* Exclude nfs_delegation_claim_locks() */
	mutex_lock(&sp->so_delegreturn_mutex);
	/* Exclude nfs4_reclaim_open_stateid() - note nesting! */
6254
	down_read(&nfsi->rwsem);
6255
	if (locks_lock_inode_wait(inode, request) == -ENOENT) {
6256
		up_read(&nfsi->rwsem);
6257
		mutex_unlock(&sp->so_delegreturn_mutex);
6258
		goto out;
6259 6260
	}
	up_read(&nfsi->rwsem);
6261
	mutex_unlock(&sp->so_delegreturn_mutex);
6262
	if (status != 0)
6263 6264
		goto out;
	/* Is this a delegated lock? */
6265
	lsp = request->fl_u.nfs4_fl.owner;
6266 6267
	if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0)
		goto out;
6268 6269
	alloc_seqid = NFS_SERVER(inode)->nfs_client->cl_mvops->alloc_seqid;
	seqid = alloc_seqid(&lsp->ls_seqid, GFP_KERNEL);
6270
	status = -ENOMEM;
6271
	if (IS_ERR(seqid))
6272
		goto out;
6273
	task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid);
6274 6275
	status = PTR_ERR(task);
	if (IS_ERR(task))
6276
		goto out;
6277
	status = rpc_wait_for_completion_task(task);
6278
	rpc_put_task(task);
6279
out:
6280
	request->fl_flags = fl_flags;
6281
	trace_nfs4_unlock(request, state, F_SETLK, status);
L
Linus Torvalds 已提交
6282 6283 6284
	return status;
}

6285 6286 6287 6288 6289 6290
struct nfs4_lockdata {
	struct nfs_lock_args arg;
	struct nfs_lock_res res;
	struct nfs4_lock_state *lsp;
	struct nfs_open_context *ctx;
	struct file_lock fl;
6291
	unsigned long timestamp;
6292 6293
	int rpc_status;
	int cancelled;
6294
	struct nfs_server *server;
6295 6296 6297
};

static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
6298 6299
		struct nfs_open_context *ctx, struct nfs4_lock_state *lsp,
		gfp_t gfp_mask)
L
Linus Torvalds 已提交
6300
{
6301 6302
	struct nfs4_lockdata *p;
	struct inode *inode = lsp->ls_state->inode;
L
Linus Torvalds 已提交
6303
	struct nfs_server *server = NFS_SERVER(inode);
6304
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
6305

6306
	p = kzalloc(sizeof(*p), gfp_mask);
6307 6308 6309 6310 6311
	if (p == NULL)
		return NULL;

	p->arg.fh = NFS_FH(inode);
	p->arg.fl = &p->fl;
6312
	p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask);
6313
	if (IS_ERR(p->arg.open_seqid))
6314
		goto out_free;
6315 6316
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	p->arg.lock_seqid = alloc_seqid(&lsp->ls_seqid, gfp_mask);
6317
	if (IS_ERR(p->arg.lock_seqid))
6318
		goto out_free_seqid;
6319
	p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
6320
	p->arg.lock_owner.id = lsp->ls_seqid.owner_id;
6321
	p->arg.lock_owner.s_dev = server->s_dev;
6322
	p->res.lock_seqid = p->arg.lock_seqid;
6323
	p->lsp = lsp;
6324
	p->server = server;
6325
	refcount_inc(&lsp->ls_count);
6326 6327 6328
	p->ctx = get_nfs_open_context(ctx);
	memcpy(&p->fl, fl, sizeof(p->fl));
	return p;
6329 6330
out_free_seqid:
	nfs_free_seqid(p->arg.open_seqid);
6331 6332 6333 6334 6335 6336 6337 6338 6339
out_free:
	kfree(p);
	return NULL;
}

static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_lockdata *data = calldata;
	struct nfs4_state *state = data->lsp->ls_state;
6340

6341
	dprintk("%s: begin!\n", __func__);
6342
	if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
6343
		goto out_wait;
6344
	/* Do we need to do an open_to_lock_owner? */
6345
	if (!test_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags)) {
6346
		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
6347
			goto out_release_lock_seqid;
6348
		}
6349 6350
		nfs4_stateid_copy(&data->arg.open_stateid,
				&state->open_stateid);
6351
		data->arg.new_lock_owner = 1;
6352
		data->res.open_seqid = data->arg.open_seqid;
6353
	} else {
6354
		data->arg.new_lock_owner = 0;
6355 6356 6357
		nfs4_stateid_copy(&data->arg.lock_stateid,
				&data->lsp->ls_stateid);
	}
6358 6359 6360 6361 6362
	if (!nfs4_valid_open_stateid(state)) {
		data->rpc_status = -EBADF;
		task->tk_action = NULL;
		goto out_release_open_seqid;
	}
6363
	data->timestamp = jiffies;
6364
	if (nfs4_setup_sequence(data->server->nfs_client,
6365
				&data->arg.seq_args,
6366
				&data->res.seq_res,
6367
				task) == 0)
6368
		return;
6369
out_release_open_seqid:
6370 6371 6372
	nfs_release_seqid(data->arg.open_seqid);
out_release_lock_seqid:
	nfs_release_seqid(data->arg.lock_seqid);
6373 6374
out_wait:
	nfs4_sequence_done(task, &data->res.seq_res);
6375
	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
6376 6377
}

6378 6379 6380
static void nfs4_lock_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_lockdata *data = calldata;
6381
	struct nfs4_lock_state *lsp = data->lsp;
6382

6383
	dprintk("%s: begin!\n", __func__);
6384

6385 6386
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return;
6387

6388
	data->rpc_status = task->tk_status;
6389 6390
	switch (task->tk_status) {
	case 0:
6391
		renew_lease(NFS_SERVER(d_inode(data->ctx->dentry)),
6392
				data->timestamp);
6393 6394
		if (data->arg.new_lock) {
			data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
6395
			if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0) {
6396 6397 6398 6399
				rpc_restart_call_prepare(task);
				break;
			}
		}
6400 6401 6402 6403 6404 6405
		if (data->arg.new_lock_owner != 0) {
			nfs_confirm_seqid(&lsp->ls_seqid, 0);
			nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid);
			set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
		} else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid))
			rpc_restart_call_prepare(task);
6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417
		break;
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_OLD_STATEID:
	case -NFS4ERR_STALE_STATEID:
	case -NFS4ERR_EXPIRED:
		if (data->arg.new_lock_owner != 0) {
			if (!nfs4_stateid_match(&data->arg.open_stateid,
						&lsp->ls_state->open_stateid))
				rpc_restart_call_prepare(task);
		} else if (!nfs4_stateid_match(&data->arg.lock_stateid,
						&lsp->ls_stateid))
				rpc_restart_call_prepare(task);
6418
	}
6419
	dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
6420 6421 6422 6423 6424 6425
}

static void nfs4_lock_release(void *calldata)
{
	struct nfs4_lockdata *data = calldata;

6426
	dprintk("%s: begin!\n", __func__);
6427
	nfs_free_seqid(data->arg.open_seqid);
B
Benjamin Coddington 已提交
6428
	if (data->cancelled) {
6429 6430 6431 6432
		struct rpc_task *task;
		task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
				data->arg.lock_seqid);
		if (!IS_ERR(task))
6433
			rpc_put_task_async(task);
6434
		dprintk("%s: cancelling lock!\n", __func__);
6435 6436 6437 6438 6439
	} else
		nfs_free_seqid(data->arg.lock_seqid);
	nfs4_put_lock_state(data->lsp);
	put_nfs_open_context(data->ctx);
	kfree(data);
6440
	dprintk("%s: done!\n", __func__);
6441 6442 6443 6444 6445 6446 6447 6448
}

static const struct rpc_call_ops nfs4_lock_ops = {
	.rpc_call_prepare = nfs4_lock_prepare,
	.rpc_call_done = nfs4_lock_done,
	.rpc_release = nfs4_lock_release,
};

6449 6450 6451 6452
static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
{
	switch (error) {
	case -NFS4ERR_ADMIN_REVOKED:
6453
	case -NFS4ERR_EXPIRED:
6454
	case -NFS4ERR_BAD_STATEID:
6455
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
6456
		if (new_lock_owner != 0 ||
6457
		   test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0)
6458
			nfs4_schedule_stateid_recovery(server, lsp->ls_state);
6459 6460 6461
		break;
	case -NFS4ERR_STALE_STATEID:
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
6462
		nfs4_schedule_lease_recovery(server->nfs_client);
6463 6464 6465
	};
}

6466
static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
6467 6468 6469
{
	struct nfs4_lockdata *data;
	struct rpc_task *task;
6470 6471 6472 6473
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
		.rpc_cred = state->owner->so_cred,
	};
T
Trond Myklebust 已提交
6474 6475
	struct rpc_task_setup task_setup_data = {
		.rpc_client = NFS_CLIENT(state->inode),
6476
		.rpc_message = &msg,
T
Trond Myklebust 已提交
6477
		.callback_ops = &nfs4_lock_ops,
6478
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
6479 6480
		.flags = RPC_TASK_ASYNC,
	};
6481 6482
	int ret;

6483
	dprintk("%s: begin!\n", __func__);
6484
	data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file),
6485 6486
			fl->fl_u.nfs4_fl.owner,
			recovery_type == NFS_LOCK_NEW ? GFP_KERNEL : GFP_NOFS);
6487 6488 6489 6490
	if (data == NULL)
		return -ENOMEM;
	if (IS_SETLKW(cmd))
		data->arg.block = 1;
6491
	nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
6492 6493
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
6494
	task_setup_data.callback_data = data;
6495 6496 6497 6498
	if (recovery_type > NFS_LOCK_NEW) {
		if (recovery_type == NFS_LOCK_RECLAIM)
			data->arg.reclaim = NFS_LOCK_RECLAIM;
		nfs4_set_sequence_privileged(&data->arg.seq_args);
6499 6500
	} else
		data->arg.new_lock = 1;
T
Trond Myklebust 已提交
6501
	task = rpc_run_task(&task_setup_data);
6502
	if (IS_ERR(task))
6503
		return PTR_ERR(task);
6504
	ret = rpc_wait_for_completion_task(task);
6505 6506
	if (ret == 0) {
		ret = data->rpc_status;
6507 6508 6509
		if (ret)
			nfs4_handle_setlk_error(data->server, data->lsp,
					data->arg.new_lock_owner, ret);
6510
	} else
B
Benjamin Coddington 已提交
6511
		data->cancelled = true;
6512
	rpc_put_task(task);
6513
	dprintk("%s: done, ret = %d!\n", __func__, ret);
6514
	trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret);
6515
	return ret;
L
Linus Torvalds 已提交
6516 6517 6518 6519
}

static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
6520
	struct nfs_server *server = NFS_SERVER(state->inode);
6521 6522 6523
	struct nfs4_exception exception = {
		.inode = state->inode,
	};
6524 6525 6526
	int err;

	do {
6527 6528 6529
		/* Cache the lock if possible... */
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
6530
		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
6531
		if (err != -NFS4ERR_DELAY)
6532 6533 6534 6535
			break;
		nfs4_handle_exception(server, err, &exception);
	} while (exception.retry);
	return err;
L
Linus Torvalds 已提交
6536 6537 6538 6539
}

static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
6540
	struct nfs_server *server = NFS_SERVER(state->inode);
6541 6542 6543
	struct nfs4_exception exception = {
		.inode = state->inode,
	};
6544 6545
	int err;

6546 6547 6548
	err = nfs4_set_lock_state(state, request);
	if (err != 0)
		return err;
6549
	if (!recover_lost_locks) {
6550 6551 6552
		set_bit(NFS_LOCK_LOST, &request->fl_u.nfs4_fl.owner->ls_flags);
		return 0;
	}
6553
	do {
6554 6555
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
6556
		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED);
6557 6558 6559 6560 6561 6562 6563 6564
		switch (err) {
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
6565
	} while (exception.retry);
6566
out:
6567
	return err;
L
Linus Torvalds 已提交
6568 6569
}

6570
#if defined(CONFIG_NFS_V4_1)
6571 6572
static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
6573 6574
	struct nfs4_lock_state *lsp;
	int status;
6575

6576 6577 6578 6579 6580 6581 6582
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		return status;
	lsp = request->fl_u.nfs4_fl.owner;
	if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) ||
	    test_bit(NFS_LOCK_LOST, &lsp->ls_flags))
		return 0;
6583
	return nfs4_lock_expired(state, request);
6584 6585 6586
}
#endif

L
Linus Torvalds 已提交
6587 6588
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
6589
	struct nfs_inode *nfsi = NFS_I(state->inode);
6590
	struct nfs4_state_owner *sp = state->owner;
6591
	unsigned char fl_flags = request->fl_flags;
6592
	int status;
L
Linus Torvalds 已提交
6593

6594
	request->fl_flags |= FL_ACCESS;
6595
	status = locks_lock_inode_wait(state->inode, request);
6596 6597
	if (status < 0)
		goto out;
6598
	mutex_lock(&sp->so_delegreturn_mutex);
6599
	down_read(&nfsi->rwsem);
6600 6601 6602
	if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
		/* Yes: cache locks! */
		/* ...but avoid races with delegation recall... */
6603
		request->fl_flags = fl_flags & ~FL_SLEEP;
6604
		status = locks_lock_inode_wait(state->inode, request);
6605
		up_read(&nfsi->rwsem);
6606
		mutex_unlock(&sp->so_delegreturn_mutex);
6607 6608
		goto out;
	}
6609
	up_read(&nfsi->rwsem);
6610
	mutex_unlock(&sp->so_delegreturn_mutex);
6611
	status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW);
6612 6613
out:
	request->fl_flags = fl_flags;
L
Linus Torvalds 已提交
6614 6615 6616 6617 6618
	return status;
}

static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
6619 6620
	struct nfs4_exception exception = {
		.state = state,
6621
		.inode = state->inode,
6622
	};
L
Linus Torvalds 已提交
6623 6624 6625
	int err;

	do {
6626 6627 6628
		err = _nfs4_proc_setlk(state, cmd, request);
		if (err == -NFS4ERR_DENIED)
			err = -EAGAIN;
L
Linus Torvalds 已提交
6629
		err = nfs4_handle_exception(NFS_SERVER(state->inode),
6630
				err, &exception);
L
Linus Torvalds 已提交
6631 6632 6633 6634
	} while (exception.retry);
	return err;
}

6635 6636 6637 6638
#define NFS4_LOCK_MINTIMEOUT (1 * HZ)
#define NFS4_LOCK_MAXTIMEOUT (30 * HZ)

static int
6639 6640
nfs4_retry_setlk_simple(struct nfs4_state *state, int cmd,
			struct file_lock *request)
6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656
{
	int		status = -ERESTARTSYS;
	unsigned long	timeout = NFS4_LOCK_MINTIMEOUT;

	while(!signalled()) {
		status = nfs4_proc_setlk(state, cmd, request);
		if ((status != -EAGAIN) || IS_SETLK(cmd))
			break;
		freezable_schedule_timeout_interruptible(timeout);
		timeout *= 2;
		timeout = min_t(unsigned long, NFS4_LOCK_MAXTIMEOUT, timeout);
		status = -ERESTARTSYS;
	}
	return status;
}

6657 6658 6659 6660 6661 6662 6663 6664 6665
#ifdef CONFIG_NFS_V4_1
struct nfs4_lock_waiter {
	struct task_struct	*task;
	struct inode		*inode;
	struct nfs_lowner	*owner;
	bool			notified;
};

static int
6666
nfs4_wake_lock_waiter(wait_queue_entry_t *wait, unsigned int mode, int flags, void *key)
6667 6668 6669 6670
{
	int ret;
	struct nfs4_lock_waiter	*waiter	= wait->private;

6671 6672 6673 6674 6675
	/* NULL key means to wake up everyone */
	if (key) {
		struct cb_notify_lock_args	*cbnl = key;
		struct nfs_lowner		*lowner = &cbnl->cbnl_owner,
						*wowner = waiter->owner;
6676

6677 6678 6679
		/* Only wake if the callback was for the same owner. */
		if (lowner->id != wowner->id || lowner->s_dev != wowner->s_dev)
			return 0;
6680

6681 6682 6683 6684 6685 6686
		/* Make sure it's for the right inode */
		if (nfs_compare_fh(NFS_FH(waiter->inode), &cbnl->cbnl_fh))
			return 0;

		waiter->notified = true;
	}
6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710

	/* override "private" so we can use default_wake_function */
	wait->private = waiter->task;
	ret = autoremove_wake_function(wait, mode, flags, key);
	wait->private = waiter;
	return ret;
}

static int
nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
	int status = -ERESTARTSYS;
	unsigned long flags;
	struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs_client *clp = server->nfs_client;
	wait_queue_head_t *q = &clp->cl_lock_waitq;
	struct nfs_lowner owner = { .clientid = clp->cl_clientid,
				    .id = lsp->ls_seqid.owner_id,
				    .s_dev = server->s_dev };
	struct nfs4_lock_waiter waiter = { .task  = current,
					   .inode = state->inode,
					   .owner = &owner,
					   .notified = false };
6711
	wait_queue_entry_t wait;
6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722

	/* Don't bother with waitqueue if we don't expect a callback */
	if (!test_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags))
		return nfs4_retry_setlk_simple(state, cmd, request);

	init_wait(&wait);
	wait.private = &waiter;
	wait.func = nfs4_wake_lock_waiter;
	add_wait_queue(q, &wait);

	while(!signalled()) {
6723
		waiter.notified = false;
6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736
		status = nfs4_proc_setlk(state, cmd, request);
		if ((status != -EAGAIN) || IS_SETLK(cmd))
			break;

		status = -ERESTARTSYS;
		spin_lock_irqsave(&q->lock, flags);
		if (waiter.notified) {
			spin_unlock_irqrestore(&q->lock, flags);
			continue;
		}
		set_current_state(TASK_INTERRUPTIBLE);
		spin_unlock_irqrestore(&q->lock, flags);

6737
		freezable_schedule_timeout(NFS4_LOCK_MAXTIMEOUT);
6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750
	}

	finish_wait(q, &wait);
	return status;
}
#else /* !CONFIG_NFS_V4_1 */
static inline int
nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
	return nfs4_retry_setlk_simple(state, cmd, request);
}
#endif

L
Linus Torvalds 已提交
6751 6752 6753 6754 6755 6756 6757 6758
static int
nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
{
	struct nfs_open_context *ctx;
	struct nfs4_state *state;
	int status;

	/* verify open state */
6759
	ctx = nfs_file_open_context(filp);
L
Linus Torvalds 已提交
6760 6761
	state = ctx->state;

6762 6763 6764 6765 6766
	if (IS_GETLK(cmd)) {
		if (state != NULL)
			return nfs4_proc_getlk(state, F_GETLK, request);
		return 0;
	}
L
Linus Torvalds 已提交
6767 6768 6769 6770

	if (!(IS_SETLK(cmd) || IS_SETLKW(cmd)))
		return -EINVAL;

6771 6772 6773 6774 6775
	if (request->fl_type == F_UNLCK) {
		if (state != NULL)
			return nfs4_proc_unlck(state, cmd, request);
		return 0;
	}
L
Linus Torvalds 已提交
6776

6777 6778
	if (state == NULL)
		return -ENOLCK;
6779 6780 6781 6782 6783

	if ((request->fl_flags & FL_POSIX) &&
	    !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
		return -ENOLCK;

6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797
	/*
	 * Don't rely on the VFS having checked the file open mode,
	 * since it won't do this for flock() locks.
	 */
	switch (request->fl_type) {
	case F_RDLCK:
		if (!(filp->f_mode & FMODE_READ))
			return -EBADF;
		break;
	case F_WRLCK:
		if (!(filp->f_mode & FMODE_WRITE))
			return -EBADF;
	}

6798 6799 6800 6801
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		return status;

6802
	return nfs4_retry_setlk(state, cmd, request);
L
Linus Torvalds 已提交
6803 6804
}

6805
int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid)
6806 6807 6808 6809 6810 6811
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	int err;

	err = nfs4_set_lock_state(state, fl);
	if (err != 0)
6812
		return err;
6813
	err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
6814
	return nfs4_handle_delegation_recall_error(server, state, stateid, fl, err);
6815
}
6816

6817 6818
struct nfs_release_lockowner_data {
	struct nfs4_lock_state *lsp;
6819
	struct nfs_server *server;
6820
	struct nfs_release_lockowner_args args;
6821
	struct nfs_release_lockowner_res res;
6822
	unsigned long timestamp;
6823 6824
};

6825 6826 6827
static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs_release_lockowner_data *data = calldata;
6828
	struct nfs_server *server = data->server;
6829 6830
	nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
			   &data->res.seq_res, task);
6831
	data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
6832
	data->timestamp = jiffies;
6833 6834 6835 6836 6837
}

static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
{
	struct nfs_release_lockowner_data *data = calldata;
6838 6839
	struct nfs_server *server = data->server;

6840
	nfs40_sequence_done(task, &data->res.seq_res);
6841 6842 6843 6844 6845 6846 6847

	switch (task->tk_status) {
	case 0:
		renew_lease(server, data->timestamp);
		break;
	case -NFS4ERR_STALE_CLIENTID:
	case -NFS4ERR_EXPIRED:
6848 6849
		nfs4_schedule_lease_recovery(server->nfs_client);
		break;
6850 6851
	case -NFS4ERR_LEASE_MOVED:
	case -NFS4ERR_DELAY:
6852 6853
		if (nfs4_async_handle_error(task, server,
					    NULL, NULL) == -EAGAIN)
6854 6855
			rpc_restart_call_prepare(task);
	}
6856 6857
}

6858 6859
static void nfs4_release_lockowner_release(void *calldata)
{
6860
	struct nfs_release_lockowner_data *data = calldata;
6861
	nfs4_free_lock_state(data->server, data->lsp);
6862 6863 6864
	kfree(calldata);
}

6865
static const struct rpc_call_ops nfs4_release_lockowner_ops = {
6866 6867
	.rpc_call_prepare = nfs4_release_lockowner_prepare,
	.rpc_call_done = nfs4_release_lockowner_done,
6868 6869 6870
	.rpc_release = nfs4_release_lockowner_release,
};

6871 6872
static void
nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
6873
{
6874
	struct nfs_release_lockowner_data *data;
6875 6876 6877 6878 6879
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
	};

	if (server->nfs_client->cl_mvops->minor_version != 0)
6880
		return;
6881

6882 6883
	data = kmalloc(sizeof(*data), GFP_NOFS);
	if (!data)
6884
		return;
6885
	data->lsp = lsp;
6886
	data->server = server;
6887 6888 6889
	data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
	data->args.lock_owner.id = lsp->ls_seqid.owner_id;
	data->args.lock_owner.s_dev = server->s_dev;
6890

6891
	msg.rpc_argp = &data->args;
6892 6893
	msg.rpc_resp = &data->res;
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
6894
	rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
6895 6896
}

6897 6898
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"

6899
static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
6900 6901 6902
				   struct dentry *unused, struct inode *inode,
				   const char *key, const void *buf,
				   size_t buflen, int flags)
6903
{
6904
	return nfs4_proc_set_acl(inode, buf, buflen);
6905 6906
}

6907
static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
6908 6909
				   struct dentry *unused, struct inode *inode,
				   const char *key, void *buf, size_t buflen)
6910
{
6911
	return nfs4_proc_get_acl(inode, buf, buflen);
6912 6913
}

6914
static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
6915
{
6916
	return nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry)));
6917 6918
}

6919 6920
#ifdef CONFIG_NFS_V4_SECURITY_LABEL

6921
static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
6922 6923 6924
				     struct dentry *unused, struct inode *inode,
				     const char *key, const void *buf,
				     size_t buflen, int flags)
6925 6926
{
	if (security_ismaclabel(key))
6927
		return nfs4_set_security_label(inode, buf, buflen);
6928 6929 6930 6931

	return -EOPNOTSUPP;
}

6932
static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler,
6933 6934
				     struct dentry *unused, struct inode *inode,
				     const char *key, void *buf, size_t buflen)
6935 6936
{
	if (security_ismaclabel(key))
6937
		return nfs4_get_security_label(inode, buf, buflen);
6938 6939 6940
	return -EOPNOTSUPP;
}

6941 6942
static ssize_t
nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
6943
{
6944
	int len = 0;
6945

6946 6947 6948 6949
	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
		len = security_inode_listsecurity(inode, list, list_len);
		if (list_len && len > list_len)
			return -ERANGE;
6950 6951 6952 6953 6954 6955 6956 6957 6958 6959
	}
	return len;
}

static const struct xattr_handler nfs4_xattr_nfs4_label_handler = {
	.prefix = XATTR_SECURITY_PREFIX,
	.get	= nfs4_xattr_get_nfs4_label,
	.set	= nfs4_xattr_set_nfs4_label,
};

6960 6961 6962 6963 6964 6965 6966 6967 6968
#else

static ssize_t
nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
{
	return 0;
}

#endif
6969

6970 6971 6972
/*
 * nfs_fhget will use either the mounted_on_fileid or the fileid
 */
6973 6974
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
{
6975 6976 6977
	if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) ||
	       (fattr->valid & NFS_ATTR_FATTR_FILEID)) &&
	      (fattr->valid & NFS_ATTR_FATTR_FSID) &&
6978
	      (fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS)))
6979 6980 6981
		return;

	fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
6982
		NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_V4_REFERRAL;
6983 6984 6985 6986
	fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
	fattr->nlink = 2;
}

6987 6988 6989 6990
static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
				   const struct qstr *name,
				   struct nfs4_fs_locations *fs_locations,
				   struct page *page)
6991 6992
{
	struct nfs_server *server = NFS_SERVER(dir);
C
Chuck Lever 已提交
6993
	u32 bitmask[3];
6994 6995
	struct nfs4_fs_locations_arg args = {
		.dir_fh = NFS_FH(dir),
6996
		.name = name,
6997 6998 6999
		.page = page,
		.bitmask = bitmask,
	};
B
Benny Halevy 已提交
7000 7001 7002
	struct nfs4_fs_locations_res res = {
		.fs_locations = fs_locations,
	};
7003 7004 7005
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
		.rpc_argp = &args,
B
Benny Halevy 已提交
7006
		.rpc_resp = &res,
7007 7008 7009
	};
	int status;

7010
	dprintk("%s: start\n", __func__);
7011

C
Chuck Lever 已提交
7012 7013 7014
	bitmask[0] = nfs4_fattr_bitmap[0] | FATTR4_WORD0_FS_LOCATIONS;
	bitmask[1] = nfs4_fattr_bitmap[1];

7015 7016 7017
	/* Ask for the fileid of the absent filesystem if mounted_on_fileid
	 * is not supported */
	if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
C
Chuck Lever 已提交
7018
		bitmask[0] &= ~FATTR4_WORD0_FILEID;
7019
	else
C
Chuck Lever 已提交
7020
		bitmask[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
7021

7022
	nfs_fattr_init(&fs_locations->fattr);
7023
	fs_locations->server = server;
7024
	fs_locations->nlocations = 0;
7025
	status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0);
7026
	dprintk("%s: returned status = %d\n", __func__, status);
7027 7028 7029
	return status;
}

7030 7031 7032 7033
int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
			   const struct qstr *name,
			   struct nfs4_fs_locations *fs_locations,
			   struct page *page)
7034 7035 7036 7037
{
	struct nfs4_exception exception = { };
	int err;
	do {
7038 7039 7040 7041
		err = _nfs4_proc_fs_locations(client, dir, name,
				fs_locations, page);
		trace_nfs4_get_fs_locations(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
7042 7043 7044 7045 7046
				&exception);
	} while (exception.retry);
	return err;
}

7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197
/*
 * This operation also signals the server that this client is
 * performing migration recovery.  The server can stop returning
 * NFS4ERR_LEASE_MOVED to this client.  A RENEW operation is
 * appended to this compound to identify the client ID which is
 * performing recovery.
 */
static int _nfs40_proc_get_locations(struct inode *inode,
				     struct nfs4_fs_locations *locations,
				     struct page *page, struct rpc_cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct rpc_clnt *clnt = server->client;
	u32 bitmask[2] = {
		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
	};
	struct nfs4_fs_locations_arg args = {
		.clientid	= server->nfs_client->cl_clientid,
		.fh		= NFS_FH(inode),
		.page		= page,
		.bitmask	= bitmask,
		.migration	= 1,		/* skip LOOKUP */
		.renew		= 1,		/* append RENEW */
	};
	struct nfs4_fs_locations_res res = {
		.fs_locations	= locations,
		.migration	= 1,
		.renew		= 1,
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
		.rpc_argp	= &args,
		.rpc_resp	= &res,
		.rpc_cred	= cred,
	};
	unsigned long now = jiffies;
	int status;

	nfs_fattr_init(&locations->fattr);
	locations->server = server;
	locations->nlocations = 0;

	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
	nfs4_set_sequence_privileged(&args.seq_args);
	status = nfs4_call_sync_sequence(clnt, server, &msg,
					&args.seq_args, &res.seq_res);
	if (status)
		return status;

	renew_lease(server, now);
	return 0;
}

#ifdef CONFIG_NFS_V4_1

/*
 * This operation also signals the server that this client is
 * performing migration recovery.  The server can stop asserting
 * SEQ4_STATUS_LEASE_MOVED for this client.  The client ID
 * performing this operation is identified in the SEQUENCE
 * operation in this compound.
 *
 * When the client supports GETATTR(fs_locations_info), it can
 * be plumbed in here.
 */
static int _nfs41_proc_get_locations(struct inode *inode,
				     struct nfs4_fs_locations *locations,
				     struct page *page, struct rpc_cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct rpc_clnt *clnt = server->client;
	u32 bitmask[2] = {
		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
	};
	struct nfs4_fs_locations_arg args = {
		.fh		= NFS_FH(inode),
		.page		= page,
		.bitmask	= bitmask,
		.migration	= 1,		/* skip LOOKUP */
	};
	struct nfs4_fs_locations_res res = {
		.fs_locations	= locations,
		.migration	= 1,
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
		.rpc_argp	= &args,
		.rpc_resp	= &res,
		.rpc_cred	= cred,
	};
	int status;

	nfs_fattr_init(&locations->fattr);
	locations->server = server;
	locations->nlocations = 0;

	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
	nfs4_set_sequence_privileged(&args.seq_args);
	status = nfs4_call_sync_sequence(clnt, server, &msg,
					&args.seq_args, &res.seq_res);
	if (status == NFS4_OK &&
	    res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED)
		status = -NFS4ERR_LEASE_MOVED;
	return status;
}

#endif	/* CONFIG_NFS_V4_1 */

/**
 * nfs4_proc_get_locations - discover locations for a migrated FSID
 * @inode: inode on FSID that is migrating
 * @locations: result of query
 * @page: buffer
 * @cred: credential to use for this operation
 *
 * Returns NFS4_OK on success, a negative NFS4ERR status code if the
 * operation failed, or a negative errno if a local error occurred.
 *
 * On success, "locations" is filled in, but if the server has
 * no locations information, NFS_ATTR_FATTR_V4_LOCATIONS is not
 * asserted.
 *
 * -NFS4ERR_LEASE_MOVED is returned if the server still has leases
 * from this client that require migration recovery.
 */
int nfs4_proc_get_locations(struct inode *inode,
			    struct nfs4_fs_locations *locations,
			    struct page *page, struct rpc_cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_client *clp = server->nfs_client;
	const struct nfs4_mig_recovery_ops *ops =
					clp->cl_mvops->mig_recovery_ops;
	struct nfs4_exception exception = { };
	int status;

	dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
		(unsigned long long)server->fsid.major,
		(unsigned long long)server->fsid.minor,
		clp->cl_hostname);
	nfs_display_fhandle(NFS_FH(inode), __func__);

	do {
		status = ops->get_locations(inode, locations, page, cred);
		if (status != -NFS4ERR_DELAY)
			break;
		nfs4_handle_exception(server, status, &exception);
	} while (exception.retry);
	return status;
}

7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323
/*
 * This operation also signals the server that this client is
 * performing "lease moved" recovery.  The server can stop
 * returning NFS4ERR_LEASE_MOVED to this client.  A RENEW operation
 * is appended to this compound to identify the client ID which is
 * performing recovery.
 */
static int _nfs40_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
	struct rpc_clnt *clnt = server->client;
	struct nfs4_fsid_present_arg args = {
		.fh		= NFS_FH(inode),
		.clientid	= clp->cl_clientid,
		.renew		= 1,		/* append RENEW */
	};
	struct nfs4_fsid_present_res res = {
		.renew		= 1,
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
		.rpc_argp	= &args,
		.rpc_resp	= &res,
		.rpc_cred	= cred,
	};
	unsigned long now = jiffies;
	int status;

	res.fh = nfs_alloc_fhandle();
	if (res.fh == NULL)
		return -ENOMEM;

	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
	nfs4_set_sequence_privileged(&args.seq_args);
	status = nfs4_call_sync_sequence(clnt, server, &msg,
						&args.seq_args, &res.seq_res);
	nfs_free_fhandle(res.fh);
	if (status)
		return status;

	do_renew_lease(clp, now);
	return 0;
}

#ifdef CONFIG_NFS_V4_1

/*
 * This operation also signals the server that this client is
 * performing "lease moved" recovery.  The server can stop asserting
 * SEQ4_STATUS_LEASE_MOVED for this client.  The client ID performing
 * this operation is identified in the SEQUENCE operation in this
 * compound.
 */
static int _nfs41_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct rpc_clnt *clnt = server->client;
	struct nfs4_fsid_present_arg args = {
		.fh		= NFS_FH(inode),
	};
	struct nfs4_fsid_present_res res = {
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
		.rpc_argp	= &args,
		.rpc_resp	= &res,
		.rpc_cred	= cred,
	};
	int status;

	res.fh = nfs_alloc_fhandle();
	if (res.fh == NULL)
		return -ENOMEM;

	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
	nfs4_set_sequence_privileged(&args.seq_args);
	status = nfs4_call_sync_sequence(clnt, server, &msg,
						&args.seq_args, &res.seq_res);
	nfs_free_fhandle(res.fh);
	if (status == NFS4_OK &&
	    res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED)
		status = -NFS4ERR_LEASE_MOVED;
	return status;
}

#endif	/* CONFIG_NFS_V4_1 */

/**
 * nfs4_proc_fsid_present - Is this FSID present or absent on server?
 * @inode: inode on FSID to check
 * @cred: credential to use for this operation
 *
 * Server indicates whether the FSID is present, moved, or not
 * recognized.  This operation is necessary to clear a LEASE_MOVED
 * condition for this client ID.
 *
 * Returns NFS4_OK if the FSID is present on this server,
 * -NFS4ERR_MOVED if the FSID is no longer present, a negative
 *  NFS4ERR code if some error occurred on the server, or a
 *  negative errno if a local failure occurred.
 */
int nfs4_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs_client *clp = server->nfs_client;
	const struct nfs4_mig_recovery_ops *ops =
					clp->cl_mvops->mig_recovery_ops;
	struct nfs4_exception exception = { };
	int status;

	dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
		(unsigned long long)server->fsid.major,
		(unsigned long long)server->fsid.minor,
		clp->cl_hostname);
	nfs_display_fhandle(NFS_FH(inode), __func__);

	do {
		status = ops->fsid_present(inode, cred);
		if (status != -NFS4ERR_DELAY)
			break;
		nfs4_handle_exception(server, status, &exception);
	} while (exception.retry);
	return status;
}

7324
/**
7325 7326 7327 7328 7329
 * If 'use_integrity' is true and the state managment nfs_client
 * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient
 * and the machine credential as per RFC3530bis and RFC5661 Security
 * Considerations sections. Otherwise, just use the user cred with the
 * filesystem's rpc_client.
7330
 */
7331
static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors, bool use_integrity)
B
Bryan Schumaker 已提交
7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345
{
	int status;
	struct nfs4_secinfo_arg args = {
		.dir_fh = NFS_FH(dir),
		.name   = name,
	};
	struct nfs4_secinfo_res res = {
		.flavors     = flavors,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
7346
	struct rpc_clnt *clnt = NFS_SERVER(dir)->client;
7347
	struct rpc_cred *cred = NULL;
7348 7349 7350

	if (use_integrity) {
		clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient;
7351 7352
		cred = nfs4_get_clid_cred(NFS_SERVER(dir)->nfs_client);
		msg.rpc_cred = cred;
7353
	}
B
Bryan Schumaker 已提交
7354 7355

	dprintk("NFS call  secinfo %s\n", name->name);
7356 7357 7358 7359

	nfs4_state_protect(NFS_SERVER(dir)->nfs_client,
		NFS_SP4_MACH_CRED_SECINFO, &clnt, &msg);

7360 7361
	status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args,
				&res.seq_res, 0);
B
Bryan Schumaker 已提交
7362
	dprintk("NFS reply  secinfo: %d\n", status);
7363

7364 7365
	if (cred)
		put_rpccred(cred);
7366

B
Bryan Schumaker 已提交
7367 7368 7369
	return status;
}

7370 7371
int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
		      struct nfs4_secinfo_flavors *flavors)
B
Bryan Schumaker 已提交
7372 7373 7374 7375
{
	struct nfs4_exception exception = { };
	int err;
	do {
7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390
		err = -NFS4ERR_WRONGSEC;

		/* try to use integrity protection with machine cred */
		if (_nfs4_is_integrity_protected(NFS_SERVER(dir)->nfs_client))
			err = _nfs4_proc_secinfo(dir, name, flavors, true);

		/*
		 * if unable to use integrity protection, or SECINFO with
		 * integrity protection returns NFS4ERR_WRONGSEC (which is
		 * disallowed by spec, but exists in deployed servers) use
		 * the current filesystem's rpc_client and the user cred.
		 */
		if (err == -NFS4ERR_WRONGSEC)
			err = _nfs4_proc_secinfo(dir, name, flavors, false);

7391 7392
		trace_nfs4_secinfo(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
B
Bryan Schumaker 已提交
7393 7394 7395 7396 7397
				&exception);
	} while (exception.retry);
	return err;
}

7398
#ifdef CONFIG_NFS_V4_1
7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417
/*
 * Check the exchange flags returned by the server for invalid flags, having
 * both PNFS and NON_PNFS flags set, and not having one of NON_PNFS, PNFS, or
 * DS flags set.
 */
static int nfs4_check_cl_exchange_flags(u32 flags)
{
	if (flags & ~EXCHGID4_FLAG_MASK_R)
		goto out_inval;
	if ((flags & EXCHGID4_FLAG_USE_PNFS_MDS) &&
	    (flags & EXCHGID4_FLAG_USE_NON_PNFS))
		goto out_inval;
	if (!(flags & (EXCHGID4_FLAG_MASK_PNFS)))
		goto out_inval;
	return NFS_OK;
out_inval:
	return -NFS4ERR_INVAL;
}

7418
static bool
7419 7420
nfs41_same_server_scope(struct nfs41_server_scope *a,
			struct nfs41_server_scope *b)
7421
{
7422 7423 7424
	if (a->server_scope_sz != b->server_scope_sz)
		return false;
	return memcmp(a->server_scope, b->server_scope, a->server_scope_sz) == 0;
7425 7426
}

7427 7428 7429 7430 7431 7432 7433 7434 7435
static void
nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
{
}

static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = {
	.rpc_call_done =  &nfs4_bind_one_conn_to_session_done,
};

7436
/*
7437
 * nfs4_proc_bind_one_conn_to_session()
7438 7439 7440 7441
 *
 * The 4.1 client currently uses the same TCP connection for the
 * fore and backchannel.
 */
7442 7443 7444 7445 7446
static
int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt,
		struct nfs_client *clp,
		struct rpc_cred *cred)
7447 7448
{
	int status;
7449 7450 7451 7452
	struct nfs41_bind_conn_to_session_args args = {
		.client = clp,
		.dir = NFS4_CDFC4_FORE_OR_BOTH,
	};
7453 7454 7455 7456
	struct nfs41_bind_conn_to_session_res res;
	struct rpc_message msg = {
		.rpc_proc =
			&nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
7457
		.rpc_argp = &args,
7458
		.rpc_resp = &res,
7459
		.rpc_cred = cred,
7460
	};
7461 7462 7463
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clnt,
		.rpc_xprt = xprt,
7464
		.callback_ops = &nfs4_bind_one_conn_to_session_ops,
7465 7466 7467 7468
		.rpc_message = &msg,
		.flags = RPC_TASK_TIMEOUT,
	};
	struct rpc_task *task;
7469

7470 7471 7472
	nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
	if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
		args.dir = NFS4_CDFC4_FORE;
7473

7474 7475 7476 7477 7478 7479 7480 7481 7482 7483
	/* Do not set the backchannel flag unless this is clnt->cl_xprt */
	if (xprt != rcu_access_pointer(clnt->cl_xprt))
		args.dir = NFS4_CDFC4_FORE;

	task = rpc_run_task(&task_setup_data);
	if (!IS_ERR(task)) {
		status = task->tk_status;
		rpc_put_task(task);
	} else
		status = PTR_ERR(task);
7484
	trace_nfs4_bind_conn_to_session(clp, status);
7485
	if (status == 0) {
7486
		if (memcmp(res.sessionid.data,
7487 7488
		    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
			dprintk("NFS: %s: Session ID mismatch\n", __func__);
7489
			return -EIO;
7490
		}
7491
		if ((res.dir & args.dir) != res.dir || res.dir == 0) {
7492 7493
			dprintk("NFS: %s: Unexpected direction from server\n",
				__func__);
7494
			return -EIO;
7495
		}
7496
		if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
7497 7498
			dprintk("NFS: %s: Server returned RDMA mode = true\n",
				__func__);
7499
			return -EIO;
7500 7501
		}
	}
7502

7503 7504 7505
	return status;
}

7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530
struct rpc_bind_conn_calldata {
	struct nfs_client *clp;
	struct rpc_cred *cred;
};

static int
nfs4_proc_bind_conn_to_session_callback(struct rpc_clnt *clnt,
		struct rpc_xprt *xprt,
		void *calldata)
{
	struct rpc_bind_conn_calldata *p = calldata;

	return nfs4_proc_bind_one_conn_to_session(clnt, xprt, p->clp, p->cred);
}

int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
{
	struct rpc_bind_conn_calldata data = {
		.clp = clp,
		.cred = cred,
	};
	return rpc_clnt_iterate_for_each_xprt(clp->cl_rpcclient,
			nfs4_proc_bind_conn_to_session_callback, &data);
}

B
Benny Halevy 已提交
7531
/*
7532 7533
 * Minimum set of SP4_MACH_CRED operations from RFC 5661 in the enforce map
 * and operations we'd like to see to enable certain features in the allow map
7534 7535 7536 7537 7538 7539 7540 7541 7542
 */
static const struct nfs41_state_protection nfs4_sp4_mach_cred_request = {
	.how = SP4_MACH_CRED,
	.enforce.u.words = {
		[1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) |
		      1 << (OP_EXCHANGE_ID - 32) |
		      1 << (OP_CREATE_SESSION - 32) |
		      1 << (OP_DESTROY_SESSION - 32) |
		      1 << (OP_DESTROY_CLIENTID - 32)
7543 7544 7545
	},
	.allow.u.words = {
		[0] = 1 << (OP_CLOSE) |
7546
		      1 << (OP_OPEN_DOWNGRADE) |
7547
		      1 << (OP_LOCKU) |
7548
		      1 << (OP_DELEGRETURN) |
7549
		      1 << (OP_COMMIT),
7550
		[1] = 1 << (OP_SECINFO - 32) |
7551
		      1 << (OP_SECINFO_NO_NAME - 32) |
7552
		      1 << (OP_LAYOUTRETURN - 32) |
7553
		      1 << (OP_TEST_STATEID - 32) |
7554 7555
		      1 << (OP_FREE_STATEID - 32) |
		      1 << (OP_WRITE - 32)
7556 7557 7558 7559 7560 7561
	}
};

/*
 * Select the state protection mode for client `clp' given the server results
 * from exchange_id in `sp'.
B
Benny Halevy 已提交
7562
 *
7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574
 * Returns 0 on success, negative errno otherwise.
 */
static int nfs4_sp4_select_mode(struct nfs_client *clp,
				 struct nfs41_state_protection *sp)
{
	static const u32 supported_enforce[NFS4_OP_MAP_NUM_WORDS] = {
		[1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) |
		      1 << (OP_EXCHANGE_ID - 32) |
		      1 << (OP_CREATE_SESSION - 32) |
		      1 << (OP_DESTROY_SESSION - 32) |
		      1 << (OP_DESTROY_CLIENTID - 32)
	};
7575
	unsigned long flags = 0;
7576
	unsigned int i;
7577
	int ret = 0;
7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592

	if (sp->how == SP4_MACH_CRED) {
		/* Print state protect result */
		dfprintk(MOUNT, "Server SP4_MACH_CRED support:\n");
		for (i = 0; i <= LAST_NFS4_OP; i++) {
			if (test_bit(i, sp->enforce.u.longs))
				dfprintk(MOUNT, "  enforce op %d\n", i);
			if (test_bit(i, sp->allow.u.longs))
				dfprintk(MOUNT, "  allow op %d\n", i);
		}

		/* make sure nothing is on enforce list that isn't supported */
		for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++) {
			if (sp->enforce.u.words[i] & ~supported_enforce[i]) {
				dfprintk(MOUNT, "sp4_mach_cred: disabled\n");
7593 7594
				ret = -EINVAL;
				goto out;
7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612
			}
		}

		/*
		 * Minimal mode - state operations are allowed to use machine
		 * credential.  Note this already happens by default, so the
		 * client doesn't have to do anything more than the negotiation.
		 *
		 * NOTE: we don't care if EXCHANGE_ID is in the list -
		 *       we're already using the machine cred for exchange_id
		 *       and will never use a different cred.
		 */
		if (test_bit(OP_BIND_CONN_TO_SESSION, sp->enforce.u.longs) &&
		    test_bit(OP_CREATE_SESSION, sp->enforce.u.longs) &&
		    test_bit(OP_DESTROY_SESSION, sp->enforce.u.longs) &&
		    test_bit(OP_DESTROY_CLIENTID, sp->enforce.u.longs)) {
			dfprintk(MOUNT, "sp4_mach_cred:\n");
			dfprintk(MOUNT, "  minimal mode enabled\n");
7613
			__set_bit(NFS_SP4_MACH_CRED_MINIMAL, &flags);
7614 7615
		} else {
			dfprintk(MOUNT, "sp4_mach_cred: disabled\n");
7616 7617
			ret = -EINVAL;
			goto out;
7618
		}
7619 7620

		if (test_bit(OP_CLOSE, sp->allow.u.longs) &&
7621 7622
		    test_bit(OP_OPEN_DOWNGRADE, sp->allow.u.longs) &&
		    test_bit(OP_DELEGRETURN, sp->allow.u.longs) &&
7623 7624
		    test_bit(OP_LOCKU, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  cleanup mode enabled\n");
7625
			__set_bit(NFS_SP4_MACH_CRED_CLEANUP, &flags);
7626
		}
7627

7628 7629
		if (test_bit(OP_LAYOUTRETURN, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  pnfs cleanup mode enabled\n");
7630
			__set_bit(NFS_SP4_MACH_CRED_PNFS_CLEANUP, &flags);
7631 7632
		}

7633 7634 7635
		if (test_bit(OP_SECINFO, sp->allow.u.longs) &&
		    test_bit(OP_SECINFO_NO_NAME, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  secinfo mode enabled\n");
7636
			__set_bit(NFS_SP4_MACH_CRED_SECINFO, &flags);
7637
		}
7638 7639 7640 7641

		if (test_bit(OP_TEST_STATEID, sp->allow.u.longs) &&
		    test_bit(OP_FREE_STATEID, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  stateid mode enabled\n");
7642
			__set_bit(NFS_SP4_MACH_CRED_STATEID, &flags);
7643
		}
7644 7645 7646

		if (test_bit(OP_WRITE, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  write mode enabled\n");
7647
			__set_bit(NFS_SP4_MACH_CRED_WRITE, &flags);
7648 7649 7650 7651
		}

		if (test_bit(OP_COMMIT, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  commit mode enabled\n");
7652
			__set_bit(NFS_SP4_MACH_CRED_COMMIT, &flags);
7653
		}
7654
	}
7655 7656
out:
	clp->cl_sp4_flags = flags;
7657 7658 7659
	return 0;
}

A
Andy Adamson 已提交
7660 7661 7662 7663 7664 7665 7666 7667 7668 7669
struct nfs41_exchange_id_data {
	struct nfs41_exchange_id_res res;
	struct nfs41_exchange_id_args args;
};

static void nfs4_exchange_id_release(void *data)
{
	struct nfs41_exchange_id_data *cdata =
					(struct nfs41_exchange_id_data *)data;

7670
	nfs_put_client(cdata->args.client);
A
Andy Adamson 已提交
7671 7672 7673 7674 7675 7676 7677 7678 7679 7680
	kfree(cdata->res.impl_id);
	kfree(cdata->res.server_scope);
	kfree(cdata->res.server_owner);
	kfree(cdata);
}

static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
	.rpc_release = nfs4_exchange_id_release,
};

7681 7682
/*
 * _nfs4_proc_exchange_id()
7683
 *
7684
 * Wrapper for EXCHANGE_ID operation.
B
Benny Halevy 已提交
7685
 */
7686 7687
static struct rpc_task *
nfs4_run_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7688
			u32 sp4_how, struct rpc_xprt *xprt)
B
Benny Halevy 已提交
7689 7690 7691 7692 7693
{
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID],
		.rpc_cred = cred,
	};
A
Andy Adamson 已提交
7694 7695 7696 7697
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.callback_ops = &nfs4_exchange_id_call_ops,
		.rpc_message = &msg,
7698
		.flags = RPC_TASK_TIMEOUT,
A
Andy Adamson 已提交
7699 7700
	};
	struct nfs41_exchange_id_data *calldata;
7701
	int status;
A
Andy Adamson 已提交
7702

7703
	if (!refcount_inc_not_zero(&clp->cl_count))
7704
		return ERR_PTR(-EIO);
A
Andy Adamson 已提交
7705

7706
	status = -ENOMEM;
A
Andy Adamson 已提交
7707
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
7708 7709
	if (!calldata)
		goto out;
B
Benny Halevy 已提交
7710

7711
	nfs4_init_boot_verifier(clp, &calldata->args.verifier);
7712 7713 7714

	status = nfs4_init_uniform_client_string(clp);
	if (status)
A
Andy Adamson 已提交
7715
		goto out_calldata;
7716

A
Andy Adamson 已提交
7717 7718 7719 7720 7721
	calldata->res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
						GFP_NOFS);
	status = -ENOMEM;
	if (unlikely(calldata->res.server_owner == NULL))
		goto out_calldata;
7722

A
Andy Adamson 已提交
7723
	calldata->res.server_scope = kzalloc(sizeof(struct nfs41_server_scope),
7724
					GFP_NOFS);
A
Andy Adamson 已提交
7725
	if (unlikely(calldata->res.server_scope == NULL))
7726
		goto out_server_owner;
7727

A
Andy Adamson 已提交
7728 7729
	calldata->res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_NOFS);
	if (unlikely(calldata->res.impl_id == NULL))
7730 7731
		goto out_server_scope;

7732 7733
	switch (sp4_how) {
	case SP4_NONE:
A
Andy Adamson 已提交
7734
		calldata->args.state_protect.how = SP4_NONE;
7735 7736 7737
		break;

	case SP4_MACH_CRED:
A
Andy Adamson 已提交
7738
		calldata->args.state_protect = nfs4_sp4_mach_cred_request;
7739 7740 7741 7742 7743 7744
		break;

	default:
		/* unsupported! */
		WARN_ON_ONCE(1);
		status = -EINVAL;
7745
		goto out_impl_id;
7746
	}
7747 7748
	if (xprt) {
		task_setup_data.rpc_xprt = xprt;
7749
		task_setup_data.flags |= RPC_TASK_SOFTCONN;
7750 7751
		memcpy(calldata->args.verifier.data, clp->cl_confirm.data,
				sizeof(calldata->args.verifier.data));
7752
	}
A
Andy Adamson 已提交
7753 7754
	calldata->args.client = clp;
	calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
7755 7756 7757
	EXCHGID4_FLAG_BIND_PRINC_STATEID;
#ifdef CONFIG_NFS_V4_1_MIGRATION
	calldata->args.flags |= EXCHGID4_FLAG_SUPP_MOVED_MIGR;
A
Andy Adamson 已提交
7758 7759 7760 7761
#endif
	msg.rpc_argp = &calldata->args;
	msg.rpc_resp = &calldata->res;
	task_setup_data.callback_data = calldata;
7762

7763
	return rpc_run_task(&task_setup_data);
A
Andy Adamson 已提交
7764 7765 7766 7767 7768 7769 7770 7771 7772

out_impl_id:
	kfree(calldata->res.impl_id);
out_server_scope:
	kfree(calldata->res.server_scope);
out_server_owner:
	kfree(calldata->res.server_owner);
out_calldata:
	kfree(calldata);
7773
out:
7774
	nfs_put_client(clp);
7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835
	return ERR_PTR(status);
}

/*
 * _nfs4_proc_exchange_id()
 *
 * Wrapper for EXCHANGE_ID operation.
 */
static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
			u32 sp4_how)
{
	struct rpc_task *task;
	struct nfs41_exchange_id_args *argp;
	struct nfs41_exchange_id_res *resp;
	int status;

	task = nfs4_run_exchange_id(clp, cred, sp4_how, NULL);
	if (IS_ERR(task))
		return PTR_ERR(task);

	argp = task->tk_msg.rpc_argp;
	resp = task->tk_msg.rpc_resp;
	status = task->tk_status;
	if (status  != 0)
		goto out;

	status = nfs4_check_cl_exchange_flags(resp->flags);
	if (status  != 0)
		goto out;

	status = nfs4_sp4_select_mode(clp, &resp->state_protect);
	if (status != 0)
		goto out;

	clp->cl_clientid = resp->clientid;
	clp->cl_exchange_flags = resp->flags;
	clp->cl_seqid = resp->seqid;
	/* Client ID is not confirmed */
	if (!(resp->flags & EXCHGID4_FLAG_CONFIRMED_R))
		clear_bit(NFS4_SESSION_ESTABLISHED,
			  &clp->cl_session->session_state);

	if (clp->cl_serverscope != NULL &&
	    !nfs41_same_server_scope(clp->cl_serverscope,
				resp->server_scope)) {
		dprintk("%s: server_scope mismatch detected\n",
			__func__);
		set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
	}

	swap(clp->cl_serverowner, resp->server_owner);
	swap(clp->cl_serverscope, resp->server_scope);
	swap(clp->cl_implid, resp->impl_id);

	/* Save the EXCHANGE_ID verifier session trunk tests */
	memcpy(clp->cl_confirm.data, argp->verifier.data,
	       sizeof(clp->cl_confirm.data));
out:
	trace_nfs4_exchange_id(clp, status);
	rpc_put_task(task);
	return status;
B
Benny Halevy 已提交
7836 7837
}

7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857
/*
 * nfs4_proc_exchange_id()
 *
 * Returns zero, a negative errno, or a negative NFS4ERR status code.
 *
 * Since the clientid has expired, all compounds using sessions
 * associated with the stale clientid will be returning
 * NFS4ERR_BADSESSION in the sequence operation, and will therefore
 * be in some phase of session reset.
 *
 * Will attempt to negotiate SP4_MACH_CRED if krb5i / krb5p auth is used.
 */
int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
{
	rpc_authflavor_t authflavor = clp->cl_rpcclient->cl_auth->au_flavor;
	int status;

	/* try SP4_MACH_CRED if krb5i/p	*/
	if (authflavor == RPC_AUTH_GSS_KRB5I ||
	    authflavor == RPC_AUTH_GSS_KRB5P) {
7858
		status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED);
7859 7860 7861 7862 7863
		if (!status)
			return 0;
	}

	/* try SP4_NONE */
7864
	return _nfs4_proc_exchange_id(clp, cred, SP4_NONE);
7865 7866
}

7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885
/**
 * nfs4_test_session_trunk
 *
 * This is an add_xprt_test() test function called from
 * rpc_clnt_setup_test_and_add_xprt.
 *
 * The rpc_xprt_switch is referrenced by rpc_clnt_setup_test_and_add_xprt
 * and is dereferrenced in nfs4_exchange_id_release
 *
 * Upon success, add the new transport to the rpc_clnt
 *
 * @clnt: struct rpc_clnt to get new transport
 * @xprt: the rpc_xprt to test
 * @data: call data for _nfs4_proc_exchange_id.
 */
int nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
			    void *data)
{
	struct nfs4_add_xprt_data *adata = (struct nfs4_add_xprt_data *)data;
7886 7887 7888
	struct rpc_task *task;
	int status;

7889 7890 7891 7892 7893 7894 7895 7896
	u32 sp4_how;

	dprintk("--> %s try %s\n", __func__,
		xprt->address_strings[RPC_DISPLAY_ADDR]);

	sp4_how = (adata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED);

	/* Test connection for session trunking. Async exchange_id call */
7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907
	task = nfs4_run_exchange_id(adata->clp, adata->cred, sp4_how, xprt);
	if (IS_ERR(task))
		return PTR_ERR(task);

	status = task->tk_status;
	if (status == 0)
		status = nfs4_detect_session_trunking(adata->clp,
				task->tk_msg.rpc_resp, xprt);

	rpc_put_task(task);
	return status;
7908
}
7909
EXPORT_SYMBOL_GPL(nfs4_test_session_trunk);
7910

T
Trond Myklebust 已提交
7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921
static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
		struct rpc_cred *cred)
{
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_CLIENTID],
		.rpc_argp = clp,
		.rpc_cred = cred,
	};
	int status;

	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
7922
	trace_nfs4_destroy_clientid(clp, status);
T
Trond Myklebust 已提交
7923
	if (status)
7924
		dprintk("NFS: Got error %d from the server %s on "
T
Trond Myklebust 已提交
7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957
			"DESTROY_CLIENTID.", status, clp->cl_hostname);
	return status;
}

static int nfs4_proc_destroy_clientid(struct nfs_client *clp,
		struct rpc_cred *cred)
{
	unsigned int loop;
	int ret;

	for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
		ret = _nfs4_proc_destroy_clientid(clp, cred);
		switch (ret) {
		case -NFS4ERR_DELAY:
		case -NFS4ERR_CLIENTID_BUSY:
			ssleep(1);
			break;
		default:
			return ret;
		}
	}
	return 0;
}

int nfs4_destroy_clientid(struct nfs_client *clp)
{
	struct rpc_cred *cred;
	int ret = 0;

	if (clp->cl_mvops->minor_version < 1)
		goto out;
	if (clp->cl_exchange_flags == 0)
		goto out;
7958 7959
	if (clp->cl_preserve_clid)
		goto out;
7960
	cred = nfs4_get_clid_cred(clp);
T
Trond Myklebust 已提交
7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972
	ret = nfs4_proc_destroy_clientid(clp, cred);
	if (cred)
		put_rpccred(cred);
	switch (ret) {
	case 0:
	case -NFS4ERR_STALE_CLIENTID:
		clp->cl_exchange_flags = 0;
	}
out:
	return ret;
}

A
Andy Adamson 已提交
7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987
struct nfs4_get_lease_time_data {
	struct nfs4_get_lease_time_args *args;
	struct nfs4_get_lease_time_res *res;
	struct nfs_client *clp;
};

static void nfs4_get_lease_time_prepare(struct rpc_task *task,
					void *calldata)
{
	struct nfs4_get_lease_time_data *data =
			(struct nfs4_get_lease_time_data *)calldata;

	dprintk("--> %s\n", __func__);
	/* just setup sequence, do not trigger session recovery
	   since we're invoked within one */
7988
	nfs4_setup_sequence(data->clp,
7989 7990 7991
			&data->args->la_seq_args,
			&data->res->lr_seq_res,
			task);
A
Andy Adamson 已提交
7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004
	dprintk("<-- %s\n", __func__);
}

/*
 * Called from nfs4_state_manager thread for session setup, so don't recover
 * from sequence operation or clientid errors.
 */
static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_get_lease_time_data *data =
			(struct nfs4_get_lease_time_data *)calldata;

	dprintk("--> %s\n", __func__);
8005 8006
	if (!nfs41_sequence_done(task, &data->res->lr_seq_res))
		return;
A
Andy Adamson 已提交
8007 8008 8009 8010 8011 8012
	switch (task->tk_status) {
	case -NFS4ERR_DELAY:
	case -NFS4ERR_GRACE:
		dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
		rpc_delay(task, NFS4_POLL_RETRY_MIN);
		task->tk_status = 0;
8013 8014
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
8015
		rpc_restart_call_prepare(task);
A
Andy Adamson 已提交
8016 8017 8018 8019 8020
		return;
	}
	dprintk("<-- %s\n", __func__);
}

8021
static const struct rpc_call_ops nfs4_get_lease_time_ops = {
A
Andy Adamson 已提交
8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046
	.rpc_call_prepare = nfs4_get_lease_time_prepare,
	.rpc_call_done = nfs4_get_lease_time_done,
};

int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
{
	struct rpc_task *task;
	struct nfs4_get_lease_time_args args;
	struct nfs4_get_lease_time_res res = {
		.lr_fsinfo = fsinfo,
	};
	struct nfs4_get_lease_time_data data = {
		.args = &args,
		.res = &res,
		.clp = clp,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GET_LEASE_TIME],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
	struct rpc_task_setup task_setup = {
		.rpc_client = clp->cl_rpcclient,
		.rpc_message = &msg,
		.callback_ops = &nfs4_get_lease_time_ops,
8047 8048
		.callback_data = &data,
		.flags = RPC_TASK_TIMEOUT,
A
Andy Adamson 已提交
8049 8050 8051
	};
	int status;

8052
	nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
8053
	nfs4_set_sequence_privileged(&args.la_seq_args);
A
Andy Adamson 已提交
8054 8055 8056
	task = rpc_run_task(&task_setup);

	if (IS_ERR(task))
8057
		return PTR_ERR(task);
A
Andy Adamson 已提交
8058

8059 8060
	status = task->tk_status;
	rpc_put_task(task);
A
Andy Adamson 已提交
8061 8062 8063
	return status;
}

A
Andy Adamson 已提交
8064 8065 8066 8067 8068 8069 8070 8071 8072
/*
 * Initialize the values to be used by the client in CREATE_SESSION
 * If nfs4_init_session set the fore channel request and response sizes,
 * use them.
 *
 * Set the back channel max_resp_sz_cached to zero to force the client to
 * always set csa_cachethis to FALSE because the current implementation
 * of the back channel DRC only supports caching the CB_SEQUENCE operation.
 */
8073 8074
static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args,
				    struct rpc_clnt *clnt)
A
Andy Adamson 已提交
8075
{
8076
	unsigned int max_rqst_sz, max_resp_sz;
8077
	unsigned int max_bc_payload = rpc_max_bc_payload(clnt);
8078 8079 8080

	max_rqst_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxwrite_overhead;
	max_resp_sz = NFS_MAX_FILE_IO_SIZE + nfs41_maxread_overhead;
A
Andy Adamson 已提交
8081 8082

	/* Fore channel attributes */
8083 8084
	args->fc_attrs.max_rqst_sz = max_rqst_sz;
	args->fc_attrs.max_resp_sz = max_resp_sz;
A
Andy Adamson 已提交
8085
	args->fc_attrs.max_ops = NFS4_MAX_OPS;
8086
	args->fc_attrs.max_reqs = max_session_slots;
A
Andy Adamson 已提交
8087 8088

	dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
8089
		"max_ops=%u max_reqs=%u\n",
A
Andy Adamson 已提交
8090 8091
		__func__,
		args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
8092
		args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
A
Andy Adamson 已提交
8093 8094

	/* Back channel attributes */
8095 8096
	args->bc_attrs.max_rqst_sz = max_bc_payload;
	args->bc_attrs.max_resp_sz = max_bc_payload;
A
Andy Adamson 已提交
8097 8098
	args->bc_attrs.max_resp_sz_cached = 0;
	args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
8099
	args->bc_attrs.max_reqs = min_t(unsigned short, max_session_cb_slots, 1);
A
Andy Adamson 已提交
8100 8101 8102 8103 8104 8105 8106 8107 8108

	dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u "
		"max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
		__func__,
		args->bc_attrs.max_rqst_sz, args->bc_attrs.max_resp_sz,
		args->bc_attrs.max_resp_sz_cached, args->bc_attrs.max_ops,
		args->bc_attrs.max_reqs);
}

8109 8110
static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
		struct nfs41_create_session_res *res)
8111
{
8112
	struct nfs4_channel_attrs *sent = &args->fc_attrs;
8113
	struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126

	if (rcvd->max_resp_sz > sent->max_resp_sz)
		return -EINVAL;
	/*
	 * Our requested max_ops is the minimum we need; we're not
	 * prepared to break up compounds into smaller pieces than that.
	 * So, no point even trying to continue if the server won't
	 * cooperate:
	 */
	if (rcvd->max_ops < sent->max_ops)
		return -EINVAL;
	if (rcvd->max_reqs == 0)
		return -EINVAL;
8127 8128
	if (rcvd->max_reqs > NFS4_MAX_SLOT_TABLE)
		rcvd->max_reqs = NFS4_MAX_SLOT_TABLE;
8129
	return 0;
8130 8131
}

8132 8133
static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
		struct nfs41_create_session_res *res)
8134 8135
{
	struct nfs4_channel_attrs *sent = &args->bc_attrs;
8136
	struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
8137

8138 8139
	if (!(res->flags & SESSION4_BACK_CHAN))
		goto out;
8140 8141 8142 8143 8144 8145
	if (rcvd->max_rqst_sz > sent->max_rqst_sz)
		return -EINVAL;
	if (rcvd->max_resp_sz < sent->max_resp_sz)
		return -EINVAL;
	if (rcvd->max_resp_sz_cached > sent->max_resp_sz_cached)
		return -EINVAL;
8146
	if (rcvd->max_ops > sent->max_ops)
8147
		return -EINVAL;
8148
	if (rcvd->max_reqs > sent->max_reqs)
8149
		return -EINVAL;
8150
out:
8151 8152
	return 0;
}
8153 8154

static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
8155
				     struct nfs41_create_session_res *res)
8156
{
8157
	int ret;
8158

8159
	ret = nfs4_verify_fore_channel_attrs(args, res);
8160 8161
	if (ret)
		return ret;
8162 8163 8164 8165 8166 8167 8168
	return nfs4_verify_back_channel_attrs(args, res);
}

static void nfs4_update_session(struct nfs4_session *session,
		struct nfs41_create_session_res *res)
{
	nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
8169 8170 8171
	/* Mark client id and session as being confirmed */
	session->clp->cl_exchange_flags |= EXCHGID4_FLAG_CONFIRMED_R;
	set_bit(NFS4_SESSION_ESTABLISHED, &session->session_state);
8172 8173
	session->flags = res->flags;
	memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
8174 8175 8176
	if (res->flags & SESSION4_BACK_CHAN)
		memcpy(&session->bc_attrs, &res->bc_attrs,
				sizeof(session->bc_attrs));
8177 8178
}

8179 8180
static int _nfs4_proc_create_session(struct nfs_client *clp,
		struct rpc_cred *cred)
A
Andy Adamson 已提交
8181 8182 8183 8184
{
	struct nfs4_session *session = clp->cl_session;
	struct nfs41_create_session_args args = {
		.client = clp,
8185 8186
		.clientid = clp->cl_clientid,
		.seqid = clp->cl_seqid,
A
Andy Adamson 已提交
8187 8188
		.cb_program = NFS4_CALLBACK,
	};
8189 8190
	struct nfs41_create_session_res res;

A
Andy Adamson 已提交
8191 8192 8193 8194
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
		.rpc_argp = &args,
		.rpc_resp = &res,
8195
		.rpc_cred = cred,
A
Andy Adamson 已提交
8196 8197 8198
	};
	int status;

8199
	nfs4_init_channel_attrs(&args, clp->cl_rpcclient);
8200
	args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
A
Andy Adamson 已提交
8201

8202
	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8203
	trace_nfs4_create_session(clp, status);
A
Andy Adamson 已提交
8204

8205 8206 8207 8208 8209 8210 8211 8212 8213 8214
	switch (status) {
	case -NFS4ERR_STALE_CLIENTID:
	case -NFS4ERR_DELAY:
	case -ETIMEDOUT:
	case -EACCES:
	case -EAGAIN:
		goto out;
	};

	clp->cl_seqid++;
8215
	if (!status) {
8216
		/* Verify the session's negotiated channel_attrs values */
8217
		status = nfs4_verify_channel_attrs(&args, &res);
A
Andy Adamson 已提交
8218
		/* Increment the clientid slot sequence id */
8219 8220 8221
		if (status)
			goto out;
		nfs4_update_session(session, &res);
A
Andy Adamson 已提交
8222
	}
8223
out:
A
Andy Adamson 已提交
8224 8225 8226 8227 8228 8229 8230 8231
	return status;
}

/*
 * Issues a CREATE_SESSION operation to the server.
 * It is the responsibility of the caller to verify the session is
 * expired before calling this routine.
 */
8232
int nfs4_proc_create_session(struct nfs_client *clp, struct rpc_cred *cred)
A
Andy Adamson 已提交
8233 8234 8235 8236 8237 8238 8239
{
	int status;
	unsigned *ptr;
	struct nfs4_session *session = clp->cl_session;

	dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);

8240
	status = _nfs4_proc_create_session(clp, cred);
A
Andy Adamson 已提交
8241 8242 8243
	if (status)
		goto out;

8244 8245 8246
	/* Init or reset the session slot tables */
	status = nfs4_setup_session_slot_tables(session);
	dprintk("slot table setup returned %d\n", status);
A
Andy Adamson 已提交
8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257
	if (status)
		goto out;

	ptr = (unsigned *)&session->sess_id.data[0];
	dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__,
		clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]);
out:
	dprintk("<-- %s\n", __func__);
	return status;
}

A
Andy Adamson 已提交
8258 8259 8260 8261
/*
 * Issue the over-the-wire RPC DESTROY_SESSION.
 * The caller must serialize access to this routine.
 */
8262 8263
int nfs4_proc_destroy_session(struct nfs4_session *session,
		struct rpc_cred *cred)
A
Andy Adamson 已提交
8264
{
8265 8266 8267 8268 8269
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION],
		.rpc_argp = session,
		.rpc_cred = cred,
	};
A
Andy Adamson 已提交
8270 8271 8272 8273 8274
	int status = 0;

	dprintk("--> nfs4_proc_destroy_session\n");

	/* session is still being setup */
8275 8276
	if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state))
		return 0;
A
Andy Adamson 已提交
8277

8278
	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8279
	trace_nfs4_destroy_session(session->clp, status);
A
Andy Adamson 已提交
8280 8281

	if (status)
8282
		dprintk("NFS: Got error %d from the server on DESTROY_SESSION. "
A
Andy Adamson 已提交
8283 8284 8285 8286 8287 8288
			"Session has been destroyed regardless...\n", status);

	dprintk("<-- nfs4_proc_destroy_session\n");
	return status;
}

A
Andy Adamson 已提交
8289 8290 8291
/*
 * Renew the cl_session lease.
 */
8292 8293 8294 8295 8296 8297
struct nfs4_sequence_data {
	struct nfs_client *clp;
	struct nfs4_sequence_args args;
	struct nfs4_sequence_res res;
};

8298 8299
static void nfs41_sequence_release(void *data)
{
8300 8301
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
8302

8303
	if (refcount_read(&clp->cl_count) > 1)
8304 8305
		nfs4_schedule_state_renewal(clp);
	nfs_put_client(clp);
8306
	kfree(calldata);
8307 8308
}

8309 8310 8311 8312 8313 8314 8315
static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client *clp)
{
	switch(task->tk_status) {
	case -NFS4ERR_DELAY:
		rpc_delay(task, NFS4_POLL_RETRY_MAX);
		return -EAGAIN;
	default:
8316
		nfs4_schedule_lease_recovery(clp);
8317 8318 8319 8320
	}
	return 0;
}

8321
static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
A
Andy Adamson 已提交
8322
{
8323 8324
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
A
Andy Adamson 已提交
8325

8326 8327
	if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp))
		return;
A
Andy Adamson 已提交
8328

8329
	trace_nfs4_sequence(clp, task->tk_status);
A
Andy Adamson 已提交
8330 8331
	if (task->tk_status < 0) {
		dprintk("%s ERROR %d\n", __func__, task->tk_status);
8332
		if (refcount_read(&clp->cl_count) == 1)
8333
			goto out;
A
Andy Adamson 已提交
8334

8335 8336
		if (nfs41_sequence_handle_errors(task, clp) == -EAGAIN) {
			rpc_restart_call_prepare(task);
A
Andy Adamson 已提交
8337 8338 8339 8340
			return;
		}
	}
	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
8341
out:
A
Andy Adamson 已提交
8342 8343 8344 8345 8346
	dprintk("<-- %s\n", __func__);
}

static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
{
8347 8348
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
A
Andy Adamson 已提交
8349 8350 8351 8352 8353 8354
	struct nfs4_sequence_args *args;
	struct nfs4_sequence_res *res;

	args = task->tk_msg.rpc_argp;
	res = task->tk_msg.rpc_resp;

8355
	nfs4_setup_sequence(clp, args, res, task);
A
Andy Adamson 已提交
8356 8357 8358 8359 8360
}

static const struct rpc_call_ops nfs41_sequence_ops = {
	.rpc_call_done = nfs41_sequence_call_done,
	.rpc_call_prepare = nfs41_sequence_prepare,
8361
	.rpc_release = nfs41_sequence_release,
A
Andy Adamson 已提交
8362 8363
};

8364 8365
static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
		struct rpc_cred *cred,
8366
		struct nfs4_slot *slot,
8367
		bool is_privileged)
A
Andy Adamson 已提交
8368
{
8369
	struct nfs4_sequence_data *calldata;
A
Andy Adamson 已提交
8370 8371 8372 8373
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
		.rpc_cred = cred,
	};
8374 8375 8376
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.rpc_message = &msg,
8377
		.callback_ops = &nfs41_sequence_ops,
8378
		.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
8379
	};
8380
	struct rpc_task *ret;
A
Andy Adamson 已提交
8381

8382
	ret = ERR_PTR(-EIO);
8383
	if (!refcount_inc_not_zero(&clp->cl_count))
8384 8385 8386
		goto out_err;

	ret = ERR_PTR(-ENOMEM);
8387
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
8388 8389
	if (calldata == NULL)
		goto out_put_clp;
8390
	nfs4_init_sequence(&calldata->args, &calldata->res, 0);
8391
	nfs4_sequence_attach_slot(&calldata->args, &calldata->res, slot);
8392 8393
	if (is_privileged)
		nfs4_set_sequence_privileged(&calldata->args);
8394 8395 8396
	msg.rpc_argp = &calldata->args;
	msg.rpc_resp = &calldata->res;
	calldata->clp = clp;
8397
	task_setup_data.callback_data = calldata;
A
Andy Adamson 已提交
8398

8399 8400 8401 8402 8403 8404 8405 8406 8407
	ret = rpc_run_task(&task_setup_data);
	if (IS_ERR(ret))
		goto out_err;
	return ret;
out_put_clp:
	nfs_put_client(clp);
out_err:
	nfs41_release_slot(slot);
	return ret;
8408 8409
}

8410
static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
8411 8412 8413 8414
{
	struct rpc_task *task;
	int ret = 0;

8415
	if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
8416
		return -EAGAIN;
8417
	task = _nfs41_proc_sequence(clp, cred, NULL, false);
8418 8419 8420
	if (IS_ERR(task))
		ret = PTR_ERR(task);
	else
8421
		rpc_put_task_async(task);
8422 8423 8424 8425 8426 8427 8428 8429 8430
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
}

static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
{
	struct rpc_task *task;
	int ret;

8431
	task = _nfs41_proc_sequence(clp, cred, NULL, true);
8432 8433 8434 8435 8436
	if (IS_ERR(task)) {
		ret = PTR_ERR(task);
		goto out;
	}
	ret = rpc_wait_for_completion_task(task);
8437
	if (!ret)
8438 8439 8440 8441 8442
		ret = task->tk_status;
	rpc_put_task(task);
out:
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
A
Andy Adamson 已提交
8443 8444
}

8445 8446 8447 8448 8449 8450 8451 8452 8453 8454
struct nfs4_reclaim_complete_data {
	struct nfs_client *clp;
	struct nfs41_reclaim_complete_args arg;
	struct nfs41_reclaim_complete_res res;
};

static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
{
	struct nfs4_reclaim_complete_data *calldata = data;

8455
	nfs4_setup_sequence(calldata->clp,
8456 8457 8458
			&calldata->arg.seq_args,
			&calldata->res.seq_res,
			task);
8459 8460
}

8461 8462 8463 8464
static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp)
{
	switch(task->tk_status) {
	case 0:
8465 8466
		wake_up_all(&clp->cl_lock_waitq);
		/* Fallthrough */
8467 8468 8469 8470 8471
	case -NFS4ERR_COMPLETE_ALREADY:
	case -NFS4ERR_WRONG_CRED: /* What to do here? */
		break;
	case -NFS4ERR_DELAY:
		rpc_delay(task, NFS4_POLL_RETRY_MAX);
8472 8473
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
8474
		return -EAGAIN;
8475 8476 8477 8478 8479 8480
	case -NFS4ERR_BADSESSION:
	case -NFS4ERR_DEADSESSION:
	case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
		nfs4_schedule_session_recovery(clp->cl_session,
				task->tk_status);
		break;
8481
	default:
8482
		nfs4_schedule_lease_recovery(clp);
8483 8484 8485 8486
	}
	return 0;
}

8487 8488 8489 8490 8491 8492 8493
static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
{
	struct nfs4_reclaim_complete_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
	struct nfs4_sequence_res *res = &calldata->res.seq_res;

	dprintk("--> %s\n", __func__);
8494 8495
	if (!nfs41_sequence_done(task, res))
		return;
8496

8497
	trace_nfs4_reclaim_complete(clp, task->tk_status);
8498 8499 8500 8501
	if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) {
		rpc_restart_call_prepare(task);
		return;
	}
8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520
	dprintk("<-- %s\n", __func__);
}

static void nfs4_free_reclaim_complete_data(void *data)
{
	struct nfs4_reclaim_complete_data *calldata = data;

	kfree(calldata);
}

static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = {
	.rpc_call_prepare = nfs4_reclaim_complete_prepare,
	.rpc_call_done = nfs4_reclaim_complete_done,
	.rpc_release = nfs4_free_reclaim_complete_data,
};

/*
 * Issue a global reclaim complete.
 */
8521 8522
static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
		struct rpc_cred *cred)
8523 8524 8525 8526 8527
{
	struct nfs4_reclaim_complete_data *calldata;
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE],
8528
		.rpc_cred = cred,
8529 8530 8531 8532 8533 8534 8535 8536 8537 8538
	};
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.rpc_message = &msg,
		.callback_ops = &nfs4_reclaim_complete_call_ops,
		.flags = RPC_TASK_ASYNC,
	};
	int status = -ENOMEM;

	dprintk("--> %s\n", __func__);
8539
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
8540 8541 8542 8543 8544
	if (calldata == NULL)
		goto out;
	calldata->clp = clp;
	calldata->arg.one_fs = 0;

8545
	nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
8546
	nfs4_set_sequence_privileged(&calldata->arg.seq_args);
8547 8548 8549 8550
	msg.rpc_argp = &calldata->arg;
	msg.rpc_resp = &calldata->res;
	task_setup_data.callback_data = calldata;
	task = rpc_run_task(&task_setup_data);
8551
	if (IS_ERR(task)) {
8552
		status = PTR_ERR(task);
8553 8554
		goto out;
	}
8555
	status = rpc_wait_for_completion_task(task);
8556 8557
	if (status == 0)
		status = task->tk_status;
8558 8559 8560 8561 8562
	rpc_put_task(task);
out:
	dprintk("<-- %s status=%d\n", __func__, status);
	return status;
}
8563 8564 8565 8566 8567

static void
nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
F
Fred Isaman 已提交
8568
	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
8569 8570

	dprintk("--> %s\n", __func__);
8571
	nfs4_setup_sequence(server->nfs_client, &lgp->args.seq_args,
8572 8573
				&lgp->res.seq_res, task);
	dprintk("<-- %s\n", __func__);
8574 8575 8576 8577 8578
}

static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
8579 8580

	dprintk("--> %s\n", __func__);
8581
	nfs41_sequence_process(task, &lgp->res.seq_res);
8582 8583 8584 8585 8586 8587 8588
	dprintk("<-- %s\n", __func__);
}

static int
nfs4_layoutget_handle_exception(struct rpc_task *task,
		struct nfs4_layoutget *lgp, struct nfs4_exception *exception)
{
8589 8590 8591
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
	struct pnfs_layout_hdr *lo;
8592 8593
	int nfs4err = task->tk_status;
	int err, status = 0;
8594
	LIST_HEAD(head);
8595

8596
	dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
8597

8598
	switch (nfs4err) {
8599
	case 0:
8600
		goto out;
8601 8602 8603 8604 8605 8606 8607

	/*
	 * NFS4ERR_LAYOUTUNAVAILABLE means we are not supposed to use pnfs
	 * on the file. set tk_status to -ENODATA to tell upper layer to
	 * retry go inband.
	 */
	case -NFS4ERR_LAYOUTUNAVAILABLE:
8608
		status = -ENODATA;
8609
		goto out;
8610 8611 8612 8613 8614
	/*
	 * NFS4ERR_BADLAYOUT means the MDS cannot return a layout of
	 * length lgp->args.minlength != 0 (see RFC5661 section 18.43.3).
	 */
	case -NFS4ERR_BADLAYOUT:
8615 8616
		status = -EOVERFLOW;
		goto out;
8617 8618
	/*
	 * NFS4ERR_LAYOUTTRYLATER is a conflict with another client
8619 8620
	 * (or clients) writing to the same RAID stripe except when
	 * the minlength argument is 0 (see RFC5661 section 18.43.3).
8621 8622 8623
	 *
	 * Treat it like we would RECALLCONFLICT -- we retry for a little
	 * while, and then eventually give up.
8624
	 */
8625
	case -NFS4ERR_LAYOUTTRYLATER:
8626 8627 8628
		if (lgp->args.minlength == 0) {
			status = -EOVERFLOW;
			goto out;
8629
		}
8630 8631
		status = -EBUSY;
		break;
8632 8633
	case -NFS4ERR_RECALLCONFLICT:
		status = -ERECALLCONFLICT;
8634
		break;
8635 8636
	case -NFS4ERR_DELEG_REVOKED:
	case -NFS4ERR_ADMIN_REVOKED:
8637 8638
	case -NFS4ERR_EXPIRED:
	case -NFS4ERR_BAD_STATEID:
8639
		exception->timeout = 0;
8640
		spin_lock(&inode->i_lock);
8641 8642 8643
		lo = NFS_I(inode)->layout;
		/* If the open stateid was bad, then recover it. */
		if (!lo || test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) ||
8644
		    !nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) {
8645
			spin_unlock(&inode->i_lock);
8646
			exception->state = lgp->args.ctx->state;
8647
			exception->stateid = &lgp->args.stateid;
8648 8649
			break;
		}
8650 8651 8652 8653

		/*
		 * Mark the bad layout state as invalid, then retry
		 */
T
Trond Myklebust 已提交
8654
		pnfs_mark_layout_stateid_invalid(lo, &head);
8655
		spin_unlock(&inode->i_lock);
8656
		nfs_commit_inode(inode, 0);
8657 8658 8659
		pnfs_free_lseg_list(&head);
		status = -EAGAIN;
		goto out;
8660
	}
8661

8662
	nfs4_sequence_free_slot(&lgp->res.seq_res);
8663 8664 8665 8666 8667 8668 8669
	err = nfs4_handle_exception(server, nfs4err, exception);
	if (!status) {
		if (exception->retry)
			status = -EAGAIN;
		else
			status = err;
	}
8670
out:
8671
	dprintk("<-- %s\n", __func__);
8672
	return status;
8673 8674
}

8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718
static size_t max_response_pages(struct nfs_server *server)
{
	u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
	return nfs_page_array_len(0, max_resp_sz);
}

static void nfs4_free_pages(struct page **pages, size_t size)
{
	int i;

	if (!pages)
		return;

	for (i = 0; i < size; i++) {
		if (!pages[i])
			break;
		__free_page(pages[i]);
	}
	kfree(pages);
}

static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
{
	struct page **pages;
	int i;

	pages = kcalloc(size, sizeof(struct page *), gfp_flags);
	if (!pages) {
		dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
		return NULL;
	}

	for (i = 0; i < size; i++) {
		pages[i] = alloc_page(gfp_flags);
		if (!pages[i]) {
			dprintk("%s: failed to allocate page\n", __func__);
			nfs4_free_pages(pages, size);
			return NULL;
		}
	}

	return pages;
}

8719 8720 8721
static void nfs4_layoutget_release(void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
8722 8723
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
8724
	size_t max_pages = max_response_pages(server);
8725 8726

	dprintk("--> %s\n", __func__);
8727
	nfs4_sequence_free_slot(&lgp->res.seq_res);
8728
	nfs4_free_pages(lgp->args.layout.pages, max_pages);
8729
	pnfs_put_layout_hdr(NFS_I(inode)->layout);
8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740
	put_nfs_open_context(lgp->args.ctx);
	kfree(calldata);
	dprintk("<-- %s\n", __func__);
}

static const struct rpc_call_ops nfs4_layoutget_call_ops = {
	.rpc_call_prepare = nfs4_layoutget_prepare,
	.rpc_call_done = nfs4_layoutget_done,
	.rpc_release = nfs4_layoutget_release,
};

8741
struct pnfs_layout_segment *
8742
nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
8743
{
8744 8745
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
8746
	size_t max_pages = max_response_pages(server);
8747 8748 8749 8750 8751
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
		.rpc_argp = &lgp->args,
		.rpc_resp = &lgp->res,
8752
		.rpc_cred = lgp->cred,
8753 8754 8755 8756 8757 8758 8759 8760
	};
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
		.rpc_message = &msg,
		.callback_ops = &nfs4_layoutget_call_ops,
		.callback_data = lgp,
		.flags = RPC_TASK_ASYNC,
	};
8761
	struct pnfs_layout_segment *lseg = NULL;
8762 8763 8764 8765
	struct nfs4_exception exception = {
		.inode = inode,
		.timeout = *timeout,
	};
8766 8767 8768 8769
	int status = 0;

	dprintk("--> %s\n", __func__);

8770 8771 8772
	/* nfs4_layoutget_release calls pnfs_put_layout_hdr */
	pnfs_get_layout_hdr(NFS_I(inode)->layout);

8773 8774 8775
	lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
	if (!lgp->args.layout.pages) {
		nfs4_layoutget_release(lgp);
8776
		return ERR_PTR(-ENOMEM);
8777 8778 8779
	}
	lgp->args.layout.pglen = max_pages * PAGE_SIZE;

8780
	lgp->res.layoutp = &lgp->args.layout;
8781
	lgp->res.seq_res.sr_slot = NULL;
8782
	nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
8783

8784 8785
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
8786
		return ERR_CAST(task);
8787
	status = rpc_wait_for_completion_task(task);
8788 8789 8790 8791 8792
	if (status == 0) {
		status = nfs4_layoutget_handle_exception(task, lgp, &exception);
		*timeout = exception.timeout;
	}

8793 8794 8795
	trace_nfs4_layoutget(lgp->args.ctx,
			&lgp->args.range,
			&lgp->res.range,
8796
			&lgp->res.stateid,
8797
			status);
8798

8799 8800
	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
	if (status == 0 && lgp->res.layoutp->len)
8801
		lseg = pnfs_layout_process(lgp);
8802 8803
	rpc_put_task(task);
	dprintk("<-- %s status=%d\n", __func__, status);
8804 8805 8806
	if (status)
		return ERR_PTR(status);
	return lseg;
8807 8808
}

B
Benny Halevy 已提交
8809 8810 8811 8812 8813 8814
static void
nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;

	dprintk("--> %s\n", __func__);
8815
	nfs4_setup_sequence(lrp->clp,
8816 8817 8818
			&lrp->args.seq_args,
			&lrp->res.seq_res,
			task);
B
Benny Halevy 已提交
8819 8820 8821 8822 8823 8824 8825 8826 8827
}

static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;
	struct nfs_server *server;

	dprintk("--> %s\n", __func__);

8828
	if (!nfs41_sequence_process(task, &lrp->res.seq_res))
B
Benny Halevy 已提交
8829 8830 8831
		return;

	server = NFS_SERVER(lrp->args.inode);
8832
	switch (task->tk_status) {
8833 8834 8835 8836 8837
	case -NFS4ERR_OLD_STATEID:
		if (nfs4_refresh_layout_stateid(&lrp->args.stateid,
					lrp->args.inode))
			goto out_restart;
		/* Fallthrough */
8838 8839
	default:
		task->tk_status = 0;
8840
		/* Fallthrough */
8841 8842 8843
	case 0:
		break;
	case -NFS4ERR_DELAY:
8844
		if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
8845
			break;
8846
		goto out_restart;
B
Benny Halevy 已提交
8847 8848
	}
	dprintk("<-- %s\n", __func__);
8849 8850 8851 8852 8853
	return;
out_restart:
	task->tk_status = 0;
	nfs4_sequence_free_slot(&lrp->res.seq_res);
	rpc_restart_call_prepare(task);
B
Benny Halevy 已提交
8854 8855 8856 8857 8858
}

static void nfs4_layoutreturn_release(void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;
8859
	struct pnfs_layout_hdr *lo = lrp->args.layout;
B
Benny Halevy 已提交
8860 8861

	dprintk("--> %s\n", __func__);
8862
	pnfs_layoutreturn_free_lsegs(lo, &lrp->args.stateid, &lrp->args.range,
8863
			lrp->res.lrs_present ? &lrp->res.stateid : NULL);
8864
	nfs4_sequence_free_slot(&lrp->res.seq_res);
8865 8866
	if (lrp->ld_private.ops && lrp->ld_private.ops->free)
		lrp->ld_private.ops->free(&lrp->ld_private);
8867 8868
	pnfs_put_layout_hdr(lrp->args.layout);
	nfs_iput_and_deactive(lrp->inode);
B
Benny Halevy 已提交
8869 8870 8871 8872 8873 8874 8875 8876 8877 8878
	kfree(calldata);
	dprintk("<-- %s\n", __func__);
}

static const struct rpc_call_ops nfs4_layoutreturn_call_ops = {
	.rpc_call_prepare = nfs4_layoutreturn_prepare,
	.rpc_call_done = nfs4_layoutreturn_done,
	.rpc_release = nfs4_layoutreturn_release,
};

8879
int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
B
Benny Halevy 已提交
8880 8881 8882 8883 8884 8885
{
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN],
		.rpc_argp = &lrp->args,
		.rpc_resp = &lrp->res,
8886
		.rpc_cred = lrp->cred,
B
Benny Halevy 已提交
8887 8888
	};
	struct rpc_task_setup task_setup_data = {
8889
		.rpc_client = NFS_SERVER(lrp->args.inode)->client,
B
Benny Halevy 已提交
8890 8891 8892 8893
		.rpc_message = &msg,
		.callback_ops = &nfs4_layoutreturn_call_ops,
		.callback_data = lrp,
	};
8894
	int status = 0;
B
Benny Halevy 已提交
8895

8896 8897 8898 8899
	nfs4_state_protect(NFS_SERVER(lrp->args.inode)->nfs_client,
			NFS_SP4_MACH_CRED_PNFS_CLEANUP,
			&task_setup_data.rpc_client, &msg);

B
Benny Halevy 已提交
8900
	dprintk("--> %s\n", __func__);
8901 8902 8903 8904 8905 8906 8907 8908
	if (!sync) {
		lrp->inode = nfs_igrab_and_active(lrp->args.inode);
		if (!lrp->inode) {
			nfs4_layoutreturn_release(lrp);
			return -EAGAIN;
		}
		task_setup_data.flags |= RPC_TASK_ASYNC;
	}
8909
	nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1);
B
Benny Halevy 已提交
8910 8911 8912
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
		return PTR_ERR(task);
8913 8914
	if (sync)
		status = task->tk_status;
8915
	trace_nfs4_layoutreturn(lrp->args.inode, &lrp->args.stateid, status);
B
Benny Halevy 已提交
8916 8917 8918 8919 8920
	dprintk("<-- %s status=%d\n", __func__, status);
	rpc_put_task(task);
	return status;
}

8921
static int
8922 8923 8924
_nfs4_proc_getdeviceinfo(struct nfs_server *server,
		struct pnfs_device *pdev,
		struct rpc_cred *cred)
8925 8926 8927
{
	struct nfs4_getdeviceinfo_args args = {
		.pdev = pdev,
8928 8929
		.notify_types = NOTIFY_DEVICEID4_CHANGE |
			NOTIFY_DEVICEID4_DELETE,
8930 8931 8932 8933 8934 8935 8936 8937
	};
	struct nfs4_getdeviceinfo_res res = {
		.pdev = pdev,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO],
		.rpc_argp = &args,
		.rpc_resp = &res,
8938
		.rpc_cred = cred,
8939 8940 8941 8942
	};
	int status;

	dprintk("--> %s\n", __func__);
8943
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
8944 8945
	if (res.notification & ~args.notify_types)
		dprintk("%s: unsupported notification\n", __func__);
8946 8947
	if (res.notification != args.notify_types)
		pdev->nocache = 1;
8948

8949 8950 8951 8952 8953
	dprintk("<-- %s status=%d\n", __func__, status);

	return status;
}

8954 8955 8956
int nfs4_proc_getdeviceinfo(struct nfs_server *server,
		struct pnfs_device *pdev,
		struct rpc_cred *cred)
8957 8958 8959 8960 8961 8962
{
	struct nfs4_exception exception = { };
	int err;

	do {
		err = nfs4_handle_exception(server,
8963
					_nfs4_proc_getdeviceinfo(server, pdev, cred),
8964 8965 8966 8967 8968 8969
					&exception);
	} while (exception.retry);
	return err;
}
EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);

A
Andy Adamson 已提交
8970 8971 8972 8973 8974
static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutcommit_data *data = calldata;
	struct nfs_server *server = NFS_SERVER(data->args.inode);

8975
	nfs4_setup_sequence(server->nfs_client,
8976 8977 8978
			&data->args.seq_args,
			&data->res.seq_res,
			task);
A
Andy Adamson 已提交
8979 8980 8981 8982 8983 8984 8985 8986
}

static void
nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutcommit_data *data = calldata;
	struct nfs_server *server = NFS_SERVER(data->args.inode);

8987
	if (!nfs41_sequence_done(task, &data->res.seq_res))
A
Andy Adamson 已提交
8988 8989 8990
		return;

	switch (task->tk_status) { /* Just ignore these failures */
8991 8992 8993 8994
	case -NFS4ERR_DELEG_REVOKED: /* layout was recalled */
	case -NFS4ERR_BADIOMODE:     /* no IOMODE_RW layout for range */
	case -NFS4ERR_BADLAYOUT:     /* no layout */
	case -NFS4ERR_GRACE:	    /* loca_recalim always false */
A
Andy Adamson 已提交
8995
		task->tk_status = 0;
8996 8997 8998
	case 0:
		break;
	default:
8999
		if (nfs4_async_handle_error(task, server, NULL, NULL) == -EAGAIN) {
9000 9001 9002 9003
			rpc_restart_call_prepare(task);
			return;
		}
	}
A
Andy Adamson 已提交
9004 9005 9006 9007 9008 9009
}

static void nfs4_layoutcommit_release(void *calldata)
{
	struct nfs4_layoutcommit_data *data = calldata;

A
Andy Adamson 已提交
9010
	pnfs_cleanup_layoutcommit(data);
9011 9012
	nfs_post_op_update_inode_force_wcc(data->args.inode,
					   data->res.fattr);
A
Andy Adamson 已提交
9013
	put_rpccred(data->cred);
9014
	nfs_iput_and_deactive(data->inode);
A
Andy Adamson 已提交
9015 9016 9017 9018 9019 9020 9021 9022 9023 9024
	kfree(data);
}

static const struct rpc_call_ops nfs4_layoutcommit_ops = {
	.rpc_call_prepare = nfs4_layoutcommit_prepare,
	.rpc_call_done = nfs4_layoutcommit_done,
	.rpc_release = nfs4_layoutcommit_release,
};

int
9025
nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
A
Andy Adamson 已提交
9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042
{
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT],
		.rpc_argp = &data->args,
		.rpc_resp = &data->res,
		.rpc_cred = data->cred,
	};
	struct rpc_task_setup task_setup_data = {
		.task = &data->task,
		.rpc_client = NFS_CLIENT(data->args.inode),
		.rpc_message = &msg,
		.callback_ops = &nfs4_layoutcommit_ops,
		.callback_data = data,
	};
	struct rpc_task *task;
	int status = 0;

9043 9044
	dprintk("NFS: initiating layoutcommit call. sync %d "
		"lbw: %llu inode %lu\n", sync,
A
Andy Adamson 已提交
9045 9046 9047
		data->args.lastbytewritten,
		data->args.inode->i_ino);

9048 9049 9050 9051 9052 9053 9054 9055
	if (!sync) {
		data->inode = nfs_igrab_and_active(data->args.inode);
		if (data->inode == NULL) {
			nfs4_layoutcommit_release(data);
			return -EAGAIN;
		}
		task_setup_data.flags = RPC_TASK_ASYNC;
	}
9056
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
A
Andy Adamson 已提交
9057 9058 9059
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
		return PTR_ERR(task);
9060 9061
	if (sync)
		status = task->tk_status;
9062
	trace_nfs4_layoutcommit(data->args.inode, &data->args.stateid, status);
A
Andy Adamson 已提交
9063 9064 9065 9066
	dprintk("%s: status %d\n", __func__, status);
	rpc_put_task(task);
	return status;
}
9067

9068 9069 9070 9071
/**
 * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
 * possible) as per RFC3530bis and RFC5661 Security Considerations sections
 */
9072 9073
static int
_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
9074 9075
		    struct nfs_fsinfo *info,
		    struct nfs4_secinfo_flavors *flavors, bool use_integrity)
9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087
{
	struct nfs41_secinfo_no_name_args args = {
		.style = SECINFO_STYLE_CURRENT_FH,
	};
	struct nfs4_secinfo_res res = {
		.flavors = flavors,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO_NO_NAME],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
9088
	struct rpc_clnt *clnt = server->client;
9089
	struct rpc_cred *cred = NULL;
9090 9091 9092 9093
	int status;

	if (use_integrity) {
		clnt = server->nfs_client->cl_rpcclient;
9094 9095
		cred = nfs4_get_clid_cred(server->nfs_client);
		msg.rpc_cred = cred;
9096 9097 9098 9099 9100 9101 9102
	}

	dprintk("--> %s\n", __func__);
	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
				&res.seq_res, 0);
	dprintk("<-- %s status=%d\n", __func__, status);

9103 9104
	if (cred)
		put_rpccred(cred);
9105 9106

	return status;
9107 9108 9109 9110 9111 9112 9113 9114 9115
}

static int
nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
			   struct nfs_fsinfo *info, struct nfs4_secinfo_flavors *flavors)
{
	struct nfs4_exception exception = { };
	int err;
	do {
9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133
		/* first try using integrity protection */
		err = -NFS4ERR_WRONGSEC;

		/* try to use integrity protection with machine cred */
		if (_nfs4_is_integrity_protected(server->nfs_client))
			err = _nfs41_proc_secinfo_no_name(server, fhandle, info,
							  flavors, true);

		/*
		 * if unable to use integrity protection, or SECINFO with
		 * integrity protection returns NFS4ERR_WRONGSEC (which is
		 * disallowed by spec, but exists in deployed servers) use
		 * the current filesystem's rpc_client and the user cred.
		 */
		if (err == -NFS4ERR_WRONGSEC)
			err = _nfs41_proc_secinfo_no_name(server, fhandle, info,
							  flavors, false);

9134 9135 9136
		switch (err) {
		case 0:
		case -NFS4ERR_WRONGSEC:
9137
		case -ENOTSUPP:
9138
			goto out;
9139 9140 9141 9142
		default:
			err = nfs4_handle_exception(server, err, &exception);
		}
	} while (exception.retry);
9143
out:
9144 9145 9146 9147 9148 9149 9150 9151 9152
	return err;
}

static int
nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
		    struct nfs_fsinfo *info)
{
	int err;
	struct page *page;
9153
	rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR;
9154
	struct nfs4_secinfo_flavors *flavors;
9155 9156
	struct nfs4_secinfo4 *secinfo;
	int i;
9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170

	page = alloc_page(GFP_KERNEL);
	if (!page) {
		err = -ENOMEM;
		goto out;
	}

	flavors = page_address(page);
	err = nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);

	/*
	 * Fall back on "guess and check" method if
	 * the server doesn't support SECINFO_NO_NAME
	 */
9171
	if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) {
9172 9173 9174 9175 9176 9177
		err = nfs4_find_root_sec(server, fhandle, info);
		goto out_freepage;
	}
	if (err)
		goto out_freepage;

9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192
	for (i = 0; i < flavors->num_flavors; i++) {
		secinfo = &flavors->flavors[i];

		switch (secinfo->flavor) {
		case RPC_AUTH_NULL:
		case RPC_AUTH_UNIX:
		case RPC_AUTH_GSS:
			flavor = rpcauth_get_pseudoflavor(secinfo->flavor,
					&secinfo->flavor_info);
			break;
		default:
			flavor = RPC_AUTH_MAXFLAVOR;
			break;
		}

9193 9194 9195
		if (!nfs_auth_info_match(&server->auth_info, flavor))
			flavor = RPC_AUTH_MAXFLAVOR;

9196 9197 9198 9199 9200 9201 9202 9203 9204 9205
		if (flavor != RPC_AUTH_MAXFLAVOR) {
			err = nfs4_lookup_root_sec(server, fhandle,
						   info, flavor);
			if (!err)
				break;
		}
	}

	if (flavor == RPC_AUTH_MAXFLAVOR)
		err = -EPERM;
9206 9207 9208 9209 9210 9211 9212 9213

out_freepage:
	put_page(page);
	if (err == -EACCES)
		return -EPERM;
out:
	return err;
}
9214

9215 9216 9217
static int _nfs41_test_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
9218 9219 9220
{
	int status;
	struct nfs41_test_stateid_args args = {
9221
		.stateid = stateid,
B
Bryan Schumaker 已提交
9222 9223 9224 9225 9226 9227
	};
	struct nfs41_test_stateid_res res;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID],
		.rpc_argp = &args,
		.rpc_resp = &res,
9228
		.rpc_cred = cred,
B
Bryan Schumaker 已提交
9229
	};
9230 9231 9232 9233
	struct rpc_clnt *rpc_client = server->client;

	nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
		&rpc_client, &msg);
9234

9235
	dprintk("NFS call  test_stateid %p\n", stateid);
9236
	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
9237
	nfs4_set_sequence_privileged(&args.seq_args);
9238
	status = nfs4_call_sync_sequence(rpc_client, server, &msg,
9239
			&args.seq_args, &res.seq_res);
9240 9241
	if (status != NFS_OK) {
		dprintk("NFS reply test_stateid: failed, %d\n", status);
9242
		return status;
9243 9244
	}
	dprintk("NFS reply test_stateid: succeeded, %d\n", -res.status);
9245
	return -res.status;
B
Bryan Schumaker 已提交
9246 9247
}

9248 9249 9250 9251 9252 9253
static void nfs4_handle_delay_or_session_error(struct nfs_server *server,
		int err, struct nfs4_exception *exception)
{
	exception->retry = 0;
	switch(err) {
	case -NFS4ERR_DELAY:
9254
	case -NFS4ERR_RETRY_UNCACHED_REP:
9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265
		nfs4_handle_exception(server, err, exception);
		break;
	case -NFS4ERR_BADSESSION:
	case -NFS4ERR_BADSLOT:
	case -NFS4ERR_BAD_HIGH_SLOT:
	case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
	case -NFS4ERR_DEADSESSION:
		nfs4_do_handle_exception(server, err, exception);
	}
}

9266 9267 9268 9269 9270
/**
 * nfs41_test_stateid - perform a TEST_STATEID operation
 *
 * @server: server / transport on which to perform the operation
 * @stateid: state ID to test
9271
 * @cred: credential
9272 9273 9274 9275 9276
 *
 * Returns NFS_OK if the server recognizes that "stateid" is valid.
 * Otherwise a negative NFS4ERR value is returned if the operation
 * failed or the state ID is not currently valid.
 */
9277 9278 9279
static int nfs41_test_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
9280 9281 9282 9283
{
	struct nfs4_exception exception = { };
	int err;
	do {
9284
		err = _nfs41_test_stateid(server, stateid, cred);
9285
		nfs4_handle_delay_or_session_error(server, err, &exception);
B
Bryan Schumaker 已提交
9286 9287 9288
	} while (exception.retry);
	return err;
}
B
Bryan Schumaker 已提交
9289

9290 9291 9292
struct nfs_free_stateid_data {
	struct nfs_server *server;
	struct nfs41_free_stateid_args args;
B
Bryan Schumaker 已提交
9293
	struct nfs41_free_stateid_res res;
9294 9295 9296 9297 9298
};

static void nfs41_free_stateid_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs_free_stateid_data *data = calldata;
9299
	nfs4_setup_sequence(data->server->nfs_client,
9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312
			&data->args.seq_args,
			&data->res.seq_res,
			task);
}

static void nfs41_free_stateid_done(struct rpc_task *task, void *calldata)
{
	struct nfs_free_stateid_data *data = calldata;

	nfs41_sequence_done(task, &data->res.seq_res);

	switch (task->tk_status) {
	case -NFS4ERR_DELAY:
9313
		if (nfs4_async_handle_error(task, data->server, NULL, NULL) == -EAGAIN)
9314 9315 9316 9317 9318 9319 9320 9321 9322
			rpc_restart_call_prepare(task);
	}
}

static void nfs41_free_stateid_release(void *calldata)
{
	kfree(calldata);
}

9323
static const struct rpc_call_ops nfs41_free_stateid_ops = {
9324 9325 9326 9327 9328 9329
	.rpc_call_prepare = nfs41_free_stateid_prepare,
	.rpc_call_done = nfs41_free_stateid_done,
	.rpc_release = nfs41_free_stateid_release,
};

static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
9330
		const nfs4_stateid *stateid,
9331
		struct rpc_cred *cred,
9332 9333
		bool privileged)
{
B
Bryan Schumaker 已提交
9334 9335
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID],
9336
		.rpc_cred = cred,
B
Bryan Schumaker 已提交
9337
	};
9338 9339 9340 9341 9342 9343 9344
	struct rpc_task_setup task_setup = {
		.rpc_client = server->client,
		.rpc_message = &msg,
		.callback_ops = &nfs41_free_stateid_ops,
		.flags = RPC_TASK_ASYNC,
	};
	struct nfs_free_stateid_data *data;
B
Bryan Schumaker 已提交
9345

9346 9347 9348
	nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
		&task_setup.rpc_client, &msg);

9349
	dprintk("NFS call  free_stateid %p\n", stateid);
9350 9351 9352 9353 9354 9355 9356 9357 9358 9359
	data = kmalloc(sizeof(*data), GFP_NOFS);
	if (!data)
		return ERR_PTR(-ENOMEM);
	data->server = server;
	nfs4_stateid_copy(&data->args.stateid, stateid);

	task_setup.callback_data = data;

	msg.rpc_argp = &data->args;
	msg.rpc_resp = &data->res;
9360
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
9361 9362 9363 9364
	if (privileged)
		nfs4_set_sequence_privileged(&data->args.seq_args);

	return rpc_run_task(&task_setup);
B
Bryan Schumaker 已提交
9365 9366
}

9367 9368 9369 9370 9371
/**
 * nfs41_free_stateid - perform a FREE_STATEID operation
 *
 * @server: server / transport on which to perform the operation
 * @stateid: state ID to release
9372
 * @cred: credential
9373
 * @is_recovery: set to true if this call needs to be privileged
9374
 *
9375
 * Note: this function is always asynchronous.
9376
 */
9377
static int nfs41_free_stateid(struct nfs_server *server,
9378 9379 9380
		const nfs4_stateid *stateid,
		struct rpc_cred *cred,
		bool is_recovery)
B
Bryan Schumaker 已提交
9381
{
9382 9383
	struct rpc_task *task;

9384
	task = _nfs41_free_stateid(server, stateid, cred, is_recovery);
9385 9386 9387
	if (IS_ERR(task))
		return PTR_ERR(task);
	rpc_put_task(task);
9388
	return 0;
B
Bryan Schumaker 已提交
9389
}
9390

9391 9392
static void
nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
9393
{
9394
	struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
9395

9396
	nfs41_free_stateid(server, &lsp->ls_stateid, cred, false);
9397 9398 9399
	nfs4_free_lock_state(server, lsp);
}

9400 9401 9402
static bool nfs41_match_stateid(const nfs4_stateid *s1,
		const nfs4_stateid *s2)
{
9403 9404 9405
	if (s1->type != s2->type)
		return false;

9406
	if (memcmp(s1->other, s2->other, sizeof(s1->other)) != 0)
9407 9408
		return false;

9409
	if (s1->seqid == s2->seqid)
9410 9411
		return true;

9412
	return s1->seqid == 0 || s2->seqid == 0;
9413 9414
}

9415 9416
#endif /* CONFIG_NFS_V4_1 */

9417 9418 9419
static bool nfs4_match_stateid(const nfs4_stateid *s1,
		const nfs4_stateid *s2)
{
9420
	return nfs4_stateid_match(s1, s2);
9421 9422 9423
}


9424
static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
9425
	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
9426
	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
L
Linus Torvalds 已提交
9427 9428
	.recover_open	= nfs4_open_reclaim,
	.recover_lock	= nfs4_lock_reclaim,
9429
	.establish_clid = nfs4_init_clientid,
9430
	.detect_trunking = nfs40_discover_server_trunking,
L
Linus Torvalds 已提交
9431 9432
};

9433
#if defined(CONFIG_NFS_V4_1)
9434
static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
9435 9436 9437 9438
	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
	.recover_open	= nfs4_open_reclaim,
	.recover_lock	= nfs4_lock_reclaim,
9439
	.establish_clid = nfs41_init_clientid,
9440
	.reclaim_complete = nfs41_proc_reclaim_complete,
9441
	.detect_trunking = nfs41_discover_server_trunking,
9442 9443 9444
};
#endif /* CONFIG_NFS_V4_1 */

9445
static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
9446 9447
	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
9448
	.recover_open	= nfs40_open_expired,
9449 9450 9451 9452 9453
	.recover_lock	= nfs4_lock_expired,
	.establish_clid = nfs4_init_clientid,
};

#if defined(CONFIG_NFS_V4_1)
9454
static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
9455
	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
9456
	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
9457 9458
	.recover_open	= nfs41_open_expired,
	.recover_lock	= nfs41_lock_expired,
9459
	.establish_clid = nfs41_init_clientid,
L
Linus Torvalds 已提交
9460
};
9461
#endif /* CONFIG_NFS_V4_1 */
L
Linus Torvalds 已提交
9462

9463
static const struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
B
Benny Halevy 已提交
9464
	.sched_state_renewal = nfs4_proc_async_renew,
9465
	.get_state_renewal_cred_locked = nfs4_get_renew_cred_locked,
9466
	.renew_lease = nfs4_proc_renew,
B
Benny Halevy 已提交
9467 9468 9469
};

#if defined(CONFIG_NFS_V4_1)
9470
static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
B
Benny Halevy 已提交
9471
	.sched_state_renewal = nfs41_proc_async_sequence,
9472
	.get_state_renewal_cred_locked = nfs4_get_machine_cred_locked,
9473
	.renew_lease = nfs4_proc_sequence,
B
Benny Halevy 已提交
9474 9475 9476
};
#endif

9477
static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = {
9478
	.get_locations = _nfs40_proc_get_locations,
9479
	.fsid_present = _nfs40_proc_fsid_present,
9480 9481 9482 9483
};

#if defined(CONFIG_NFS_V4_1)
static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = {
9484
	.get_locations = _nfs41_proc_get_locations,
9485
	.fsid_present = _nfs41_proc_fsid_present,
9486 9487 9488
};
#endif	/* CONFIG_NFS_V4_1 */

9489 9490
static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
	.minor_version = 0,
9491 9492 9493
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_POSIX_LOCK,
9494 9495
	.init_client = nfs40_init_client,
	.shutdown_client = nfs40_shutdown_client,
9496
	.match_stateid = nfs4_match_stateid,
9497
	.find_root_sec = nfs4_find_root_sec,
9498
	.free_lock_state = nfs4_release_lockowner,
9499
	.test_and_free_expired = nfs40_test_and_free_expired_stateid,
9500
	.alloc_seqid = nfs_alloc_seqid,
9501
	.call_sync_ops = &nfs40_call_sync_ops,
9502 9503 9504
	.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
	.state_renewal_ops = &nfs40_state_renewal_ops,
9505
	.mig_recovery_ops = &nfs40_mig_recovery_ops,
9506 9507 9508
};

#if defined(CONFIG_NFS_V4_1)
9509 9510 9511 9512 9513 9514
static struct nfs_seqid *
nfs_alloc_no_seqid(struct nfs_seqid_counter *arg1, gfp_t arg2)
{
	return NULL;
}

9515 9516
static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
	.minor_version = 1,
9517 9518
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
9519
		| NFS_CAP_POSIX_LOCK
9520
		| NFS_CAP_STATEID_NFSV41
A
Anna Schumaker 已提交
9521
		| NFS_CAP_ATOMIC_OPEN_V1,
9522 9523
	.init_client = nfs41_init_client,
	.shutdown_client = nfs41_shutdown_client,
9524
	.match_stateid = nfs41_match_stateid,
9525
	.find_root_sec = nfs41_find_root_sec,
9526
	.free_lock_state = nfs41_free_lock_state,
9527
	.test_and_free_expired = nfs41_test_and_free_expired_stateid,
9528
	.alloc_seqid = nfs_alloc_no_seqid,
9529
	.session_trunk = nfs4_test_session_trunk,
9530
	.call_sync_ops = &nfs41_call_sync_ops,
9531 9532 9533
	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
	.state_renewal_ops = &nfs41_state_renewal_ops,
9534
	.mig_recovery_ops = &nfs41_mig_recovery_ops,
9535 9536 9537
};
#endif

9538 9539 9540
#if defined(CONFIG_NFS_V4_2)
static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
	.minor_version = 2,
9541 9542 9543 9544
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_POSIX_LOCK
		| NFS_CAP_STATEID_NFSV41
A
Anna Schumaker 已提交
9545
		| NFS_CAP_ATOMIC_OPEN_V1
A
Anna Schumaker 已提交
9546
		| NFS_CAP_ALLOCATE
A
Anna Schumaker 已提交
9547
		| NFS_CAP_COPY
A
Anna Schumaker 已提交
9548
		| NFS_CAP_DEALLOCATE
9549
		| NFS_CAP_SEEK
P
Peng Tao 已提交
9550 9551
		| NFS_CAP_LAYOUTSTATS
		| NFS_CAP_CLONE,
9552 9553
	.init_client = nfs41_init_client,
	.shutdown_client = nfs41_shutdown_client,
9554 9555
	.match_stateid = nfs41_match_stateid,
	.find_root_sec = nfs41_find_root_sec,
9556
	.free_lock_state = nfs41_free_lock_state,
9557
	.call_sync_ops = &nfs41_call_sync_ops,
9558
	.test_and_free_expired = nfs41_test_and_free_expired_stateid,
9559
	.alloc_seqid = nfs_alloc_no_seqid,
9560
	.session_trunk = nfs4_test_session_trunk,
9561 9562 9563
	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
	.state_renewal_ops = &nfs41_state_renewal_ops,
9564
	.mig_recovery_ops = &nfs41_mig_recovery_ops,
9565 9566 9567
};
#endif

9568 9569 9570 9571 9572
const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
	[0] = &nfs_v4_0_minor_ops,
#if defined(CONFIG_NFS_V4_1)
	[1] = &nfs_v4_1_minor_ops,
#endif
9573 9574 9575
#if defined(CONFIG_NFS_V4_2)
	[2] = &nfs_v4_2_minor_ops,
#endif
9576 9577
};

9578
static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595
{
	ssize_t error, error2;

	error = generic_listxattr(dentry, list, size);
	if (error < 0)
		return error;
	if (list) {
		list += error;
		size -= error;
	}

	error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, size);
	if (error2 < 0)
		return error2;
	return error + error2;
}

9596
static const struct inode_operations nfs4_dir_inode_operations = {
9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609
	.create		= nfs_create,
	.lookup		= nfs_lookup,
	.atomic_open	= nfs_atomic_open,
	.link		= nfs_link,
	.unlink		= nfs_unlink,
	.symlink	= nfs_symlink,
	.mkdir		= nfs_mkdir,
	.rmdir		= nfs_rmdir,
	.mknod		= nfs_mknod,
	.rename		= nfs_rename,
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
9610
	.listxattr	= nfs4_listxattr,
9611 9612
};

9613
static const struct inode_operations nfs4_file_inode_operations = {
9614 9615 9616
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
9617
	.listxattr	= nfs4_listxattr,
9618 9619
};

D
David Howells 已提交
9620
const struct nfs_rpc_ops nfs_v4_clientops = {
L
Linus Torvalds 已提交
9621 9622 9623
	.version	= 4,			/* protocol version */
	.dentry_ops	= &nfs4_dentry_operations,
	.dir_inode_ops	= &nfs4_dir_inode_operations,
9624
	.file_inode_ops	= &nfs4_file_inode_operations,
9625
	.file_ops	= &nfs4_file_operations,
L
Linus Torvalds 已提交
9626
	.getroot	= nfs4_proc_get_root,
B
Bryan Schumaker 已提交
9627
	.submount	= nfs4_submount,
B
Bryan Schumaker 已提交
9628
	.try_mount	= nfs4_try_mount,
L
Linus Torvalds 已提交
9629 9630 9631
	.getattr	= nfs4_proc_getattr,
	.setattr	= nfs4_proc_setattr,
	.lookup		= nfs4_proc_lookup,
J
Jeff Layton 已提交
9632
	.lookupp	= nfs4_proc_lookupp,
L
Linus Torvalds 已提交
9633 9634 9635 9636 9637
	.access		= nfs4_proc_access,
	.readlink	= nfs4_proc_readlink,
	.create		= nfs4_proc_create,
	.remove		= nfs4_proc_remove,
	.unlink_setup	= nfs4_proc_unlink_setup,
9638
	.unlink_rpc_prepare = nfs4_proc_unlink_rpc_prepare,
L
Linus Torvalds 已提交
9639
	.unlink_done	= nfs4_proc_unlink_done,
9640
	.rename_setup	= nfs4_proc_rename_setup,
9641
	.rename_rpc_prepare = nfs4_proc_rename_rpc_prepare,
9642
	.rename_done	= nfs4_proc_rename_done,
L
Linus Torvalds 已提交
9643 9644 9645
	.link		= nfs4_proc_link,
	.symlink	= nfs4_proc_symlink,
	.mkdir		= nfs4_proc_mkdir,
9646
	.rmdir		= nfs4_proc_rmdir,
L
Linus Torvalds 已提交
9647 9648 9649 9650 9651
	.readdir	= nfs4_proc_readdir,
	.mknod		= nfs4_proc_mknod,
	.statfs		= nfs4_proc_statfs,
	.fsinfo		= nfs4_proc_fsinfo,
	.pathconf	= nfs4_proc_pathconf,
9652
	.set_capabilities = nfs4_server_capabilities,
L
Linus Torvalds 已提交
9653
	.decode_dirent	= nfs4_decode_dirent,
9654
	.pgio_rpc_prepare = nfs4_proc_pgio_rpc_prepare,
L
Linus Torvalds 已提交
9655
	.read_setup	= nfs4_proc_read_setup,
T
Trond Myklebust 已提交
9656
	.read_done	= nfs4_read_done,
L
Linus Torvalds 已提交
9657
	.write_setup	= nfs4_proc_write_setup,
9658
	.write_done	= nfs4_write_done,
L
Linus Torvalds 已提交
9659
	.commit_setup	= nfs4_proc_commit_setup,
9660
	.commit_rpc_prepare = nfs4_proc_commit_rpc_prepare,
9661
	.commit_done	= nfs4_commit_done,
L
Linus Torvalds 已提交
9662
	.lock		= nfs4_proc_lock,
9663
	.clear_acl_cache = nfs4_zap_acl_attr,
T
Trond Myklebust 已提交
9664
	.close_context  = nfs4_close_context,
9665
	.open_context	= nfs4_atomic_open,
9666
	.have_delegation = nfs4_have_delegation,
9667
	.alloc_client	= nfs4_alloc_client,
9668
	.init_client	= nfs4_init_client,
9669
	.free_client	= nfs4_free_client,
9670 9671
	.create_server	= nfs4_create_server,
	.clone_server	= nfs_clone_server,
L
Linus Torvalds 已提交
9672 9673
};

9674
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
9675
	.name	= XATTR_NAME_NFSV4_ACL,
9676 9677 9678 9679 9680 9681 9682
	.list	= nfs4_xattr_list_nfs4_acl,
	.get	= nfs4_xattr_get_nfs4_acl,
	.set	= nfs4_xattr_set_nfs4_acl,
};

const struct xattr_handler *nfs4_xattr_handlers[] = {
	&nfs4_xattr_nfs4_acl_handler,
9683 9684 9685
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	&nfs4_xattr_nfs4_label_handler,
#endif
9686 9687 9688
	NULL
};

L
Linus Torvalds 已提交
9689 9690 9691 9692 9693
/*
 * Local variables:
 *  c-basic-offset: 8
 * End:
 */