nfs4proc.c 254.6 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>
L
Linus Torvalds 已提交
57

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

69 70
#include "nfs4trace.h"

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

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

76 77 78 79 80 81 82 83 84 85 86
/* 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)

87
struct nfs4_opendata;
88
static int _nfs4_proc_open(struct nfs4_opendata *data);
89
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
L
Linus Torvalds 已提交
90
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
91
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
92 93
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);
94 95
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			    struct nfs_fattr *fattr, struct iattr *sattr,
96
			    struct nfs_open_context *ctx, struct nfs4_label *ilabel,
97
			    struct nfs4_label *olabel);
98
#ifdef CONFIG_NFS_V4_1
99 100
static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
		struct rpc_cred *);
101 102
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
		struct rpc_cred *, bool);
103
#endif
104 105 106 107 108 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

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

/*
 * This is our standard bitmap for GETATTR requests.
 */
184
const u32 nfs4_fattr_bitmap[3] = {
L
Linus Torvalds 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197
	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
198 199
	| FATTR4_WORD1_TIME_MODIFY
	| FATTR4_WORD1_MOUNTED_ON_FILEID,
200 201 202
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	FATTR4_WORD2_SECURITY_LABEL
#endif
L
Linus Torvalds 已提交
203 204
};

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
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
221 222 223
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	| FATTR4_WORD2_SECURITY_LABEL
#endif
224 225
};

226 227 228 229 230
static const u32 nfs4_open_noattr_bitmap[3] = {
	FATTR4_WORD0_TYPE
	| FATTR4_WORD0_FILEID,
};

231
const u32 nfs4_statfs_bitmap[3] = {
L
Linus Torvalds 已提交
232 233 234 235 236 237 238 239
	FATTR4_WORD0_FILES_AVAIL
	| FATTR4_WORD0_FILES_FREE
	| FATTR4_WORD0_FILES_TOTAL,
	FATTR4_WORD1_SPACE_AVAIL
	| FATTR4_WORD1_SPACE_FREE
	| FATTR4_WORD1_SPACE_TOTAL
};

240
const u32 nfs4_pathconf_bitmap[3] = {
L
Linus Torvalds 已提交
241 242 243 244 245
	FATTR4_WORD0_MAXLINK
	| FATTR4_WORD0_MAXNAME,
	0
};

246
const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE
L
Linus Torvalds 已提交
247 248 249
			| FATTR4_WORD0_MAXREAD
			| FATTR4_WORD0_MAXWRITE
			| FATTR4_WORD0_LEASE_TIME,
250
			FATTR4_WORD1_TIME_DELTA
251 252
			| FATTR4_WORD1_FS_LAYOUT_TYPES,
			FATTR4_WORD2_LAYOUT_BLKSIZE
253
			| FATTR4_WORD2_CLONE_BLKSIZE
L
Linus Torvalds 已提交
254 255
};

256
const u32 nfs4_fs_locations_bitmap[3] = {
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
	FATTR4_WORD0_TYPE
	| FATTR4_WORD0_CHANGE
	| FATTR4_WORD0_SIZE
	| FATTR4_WORD0_FSID
	| FATTR4_WORD0_FILEID
	| FATTR4_WORD0_FS_LOCATIONS,
	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
272
	| FATTR4_WORD1_MOUNTED_ON_FILEID,
273 274
};

A
Al Viro 已提交
275
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
L
Linus Torvalds 已提交
276 277
		struct nfs4_readdir_arg *readdir)
{
278
	__be32 *start, *p;
L
Linus Torvalds 已提交
279 280

	if (cookie > 2) {
281
		readdir->cookie = cookie;
L
Linus Torvalds 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
		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.
	 */
298
	start = p = kmap_atomic(*readdir->pages);
L
Linus Torvalds 已提交
299 300 301 302 303 304 305 306 307 308 309
	
	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 */
		*p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */
		*p++ = htonl(8);              /* attribute buffer length */
310
		p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
L
Linus Torvalds 已提交
311 312 313 314 315 316 317 318 319 320 321
	}
	
	*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 */
	*p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */
	*p++ = htonl(8);              /* attribute buffer length */
322
	p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));
L
Linus Torvalds 已提交
323 324 325

	readdir->pgbase = (char *)p - (char *)start;
	readdir->count -= readdir->pgbase;
326
	kunmap_atomic(start);
L
Linus Torvalds 已提交
327 328
}

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
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);
}

356 357 358 359 360 361 362 363 364 365 366 367 368 369
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;
}

370 371 372 373 374 375
static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
{
	int res = 0;

	might_sleep();

376 377
	freezable_schedule_timeout_killable_unsafe(
		nfs4_update_delay(timeout));
378 379 380 381 382 383 384 385
	if (fatal_signal_pending(current))
		res = -ERESTARTSYS;
	return res;
}

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

395 396
	exception->delay = 0;
	exception->recovering = 0;
397
	exception->retry = 0;
398 399 400 401

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

402 403 404
	switch(errorcode) {
		case 0:
			return 0;
405 406
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_ADMIN_REVOKED:
407
		case -NFS4ERR_EXPIRED:
408
		case -NFS4ERR_BAD_STATEID:
409 410 411 412 413 414
			if (inode != NULL && stateid != NULL) {
				nfs_inode_find_state_and_recover(inode,
						stateid);
				goto wait_on_recovery;
			}
		case -NFS4ERR_OPENMODE:
415 416 417 418 419 420 421 422 423 424 425 426
			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;
				}
			}
427 428
			if (state == NULL)
				break;
429 430 431
			ret = nfs4_schedule_stateid_recovery(server, state);
			if (ret < 0)
				break;
432
			goto wait_on_recovery;
433
		case -NFS4ERR_STALE_STATEID:
434
		case -NFS4ERR_STALE_CLIENTID:
435 436
			nfs4_schedule_lease_recovery(clp);
			goto wait_on_recovery;
437 438 439 440 441
		case -NFS4ERR_MOVED:
			ret = nfs4_schedule_migration_recovery(server);
			if (ret < 0)
				break;
			goto wait_on_recovery;
442 443 444
		case -NFS4ERR_LEASE_MOVED:
			nfs4_schedule_lease_moved_recovery(clp);
			goto wait_on_recovery;
445
#if defined(CONFIG_NFS_V4_1)
446 447 448 449 450 451 452 453 454
		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);
455
			nfs4_schedule_session_recovery(clp->cl_session, errorcode);
456
			goto wait_on_recovery;
457
#endif /* defined(CONFIG_NFS_V4_1) */
458
		case -NFS4ERR_FILE_OPEN:
459 460 461 462 463 464 465
			if (exception->timeout > HZ) {
				/* We have retried a decent amount, time to
				 * fail
				 */
				ret = -EBUSY;
				break;
			}
466
		case -NFS4ERR_DELAY:
467 468
			nfs_inc_server_stats(server, NFSIOS_DELAY);
		case -NFS4ERR_GRACE:
469
		case -NFS4ERR_LAYOUTTRYLATER:
470
		case -NFS4ERR_RECALLCONFLICT:
471 472 473
			exception->delay = 1;
			return 0;

474
		case -NFS4ERR_RETRY_UNCACHED_REP:
475 476
		case -NFS4ERR_OLD_STATEID:
			exception->retry = 1;
477 478 479 480 481 482 483 484 485 486 487 488 489
			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);
			}
490 491 492
	}
	/* We failed to handle the error */
	return nfs4_map_errors(ret);
493
wait_on_recovery:
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
	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:
519 520 521
	if (ret == 0)
		exception->retry = 1;
	return ret;
522 523
}

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
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;
	}
542
	if (test_bit(NFS_MIG_FAILED, &server->mig_status))
543 544 545
		ret = -EIO;
	return ret;
out_retry:
546 547 548
	if (ret == 0)
		exception->retry = 1;
	return ret;
549 550
}

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
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;
}

573 574 575 576 577 578 579 580 581 582 583 584 585 586
/*
 * 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;

	if (flavor == RPC_AUTH_GSS_KRB5I ||
	    flavor == RPC_AUTH_GSS_KRB5P)
		return true;

	return false;
}
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 626 627 628
int nfs40_setup_sequence(struct nfs4_slot_table *tbl,
			 struct nfs4_sequence_args *args,
			 struct nfs4_sequence_res *res,
			 struct rpc_task *task)
C
Chuck Lever 已提交
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
{
	struct nfs4_slot *slot;

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

	spin_lock(&tbl->slot_tbl_lock);
	if (nfs4_slot_tbl_draining(tbl) && !args->sa_privileged)
		goto out_sleep;

	slot = nfs4_alloc_slot(tbl);
	if (IS_ERR(slot)) {
		if (slot == ERR_PTR(-ENOMEM))
			task->tk_timeout = HZ >> 2;
		goto out_sleep;
	}
	spin_unlock(&tbl->slot_tbl_lock);

648
	slot->privileged = args->sa_privileged ? 1 : 0;
C
Chuck Lever 已提交
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
	args->sa_slot = slot;
	res->sr_slot = slot;

out_start:
	rpc_call_start(task);
	return 0;

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;
}
665
EXPORT_SYMBOL_GPL(nfs40_setup_sequence);
C
Chuck Lever 已提交
666

667
static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
C
Chuck Lever 已提交
668 669 670 671 672 673 674 675 676 677 678
{
	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;
679 680 681 682 683 684 685
}

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 已提交
686 687 688
	return 1;
}

A
Andy Adamson 已提交
689 690
#if defined(CONFIG_NFS_V4_1)

691
static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
692
{
693
	struct nfs4_session *session;
A
Andy Adamson 已提交
694
	struct nfs4_slot_table *tbl;
695
	struct nfs4_slot *slot = res->sr_slot;
696
	bool send_new_highest_used_slotid = false;
A
Andy Adamson 已提交
697

698
	tbl = slot->table;
699
	session = tbl->session;
700

701 702 703 704 705
	/* Bump the slot sequence number */
	if (slot->seq_done)
		slot->seq_nr++;
	slot->seq_done = 0;

706
	spin_lock(&tbl->slot_tbl_lock);
707 708 709 710 711 712
	/* 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;

713
	if (nfs41_wake_and_assign_slot(tbl, slot)) {
714 715 716
		send_new_highest_used_slotid = false;
		goto out_unlock;
	}
717
	nfs4_free_slot(tbl, slot);
718 719 720

	if (tbl->highest_used_slotid != NFS4_NO_SLOT)
		send_new_highest_used_slotid = false;
721
out_unlock:
722
	spin_unlock(&tbl->slot_tbl_lock);
723
	res->sr_slot = NULL;
724
	if (send_new_highest_used_slotid)
725
		nfs41_notify_server(session->clp);
726 727
	if (waitqueue_active(&tbl->slot_waitq))
		wake_up_all(&tbl->slot_waitq);
A
Andy Adamson 已提交
728 729
}

730 731
static int nfs41_sequence_process(struct rpc_task *task,
		struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
732
{
733
	struct nfs4_session *session;
734
	struct nfs4_slot *slot = res->sr_slot;
735
	struct nfs_client *clp;
736
	bool interrupted = false;
737
	int ret = 1;
A
Andy Adamson 已提交
738

739 740
	if (slot == NULL)
		goto out_noaction;
741 742
	/* don't increment the sequence number if the task wasn't sent */
	if (!RPC_WAS_SENT(task))
A
Andy Adamson 已提交
743 744
		goto out;

745
	session = slot->table->session;
746

747 748 749 750 751
	if (slot->interrupted) {
		slot->interrupted = 0;
		interrupted = true;
	}

752
	trace_nfs4_sequence_done(session, res);
A
Andy Adamson 已提交
753
	/* Check the SEQUENCE operation status */
754 755
	switch (res->sr_status) {
	case 0:
756 757 758 759 760 761 762
		/* If previous op on slot was interrupted and we reused
		 * the seq# and got a reply from the cache, then retry
		 */
		if (task->tk_status == -EREMOTEIO && interrupted) {
			++slot->seq_nr;
			goto retry_nowait;
		}
A
Andy Adamson 已提交
763
		/* Update the slot's sequence and clientid lease timer */
764
		slot->seq_done = 1;
765
		clp = session->clp;
766
		do_renew_lease(clp, res->sr_timestamp);
767
		/* Check sequence flags */
768 769
		nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
				!!slot->privileged);
770
		nfs41_update_target_slotid(slot->table, slot, res);
771
		break;
772 773 774 775 776 777 778 779 780
	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;
781 782 783 784 785
	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.
		 */
786
		dprintk("%s: slot=%u seq=%u: Operation in progress\n",
787
			__func__,
788
			slot->slot_nr,
789
			slot->seq_nr);
790
		goto out_retry;
791 792 793 794 795
	case -NFS4ERR_BADSLOT:
		/*
		 * The slot id we used was probably retired. Try again
		 * using a different slot id.
		 */
796 797
		goto retry_nowait;
	case -NFS4ERR_SEQ_MISORDERED:
798 799 800 801 802 803 804 805
		/*
		 * Was the last operation on this sequence interrupted?
		 * If so, retry after bumping the sequence number.
		 */
		if (interrupted) {
			++slot->seq_nr;
			goto retry_nowait;
		}
806 807 808 809
		/*
		 * Could this slot have been previously retired?
		 * If so, then the server may be expecting seq_nr = 1!
		 */
810 811 812 813 814
		if (slot->seq_nr != 1) {
			slot->seq_nr = 1;
			goto retry_nowait;
		}
		break;
815 816 817
	case -NFS4ERR_SEQ_FALSE_RETRY:
		++slot->seq_nr;
		goto retry_nowait;
818 819 820 821
	case -NFS4ERR_DEADSESSION:
	case -NFS4ERR_BADSESSION:
		nfs4_schedule_session_recovery(session, res->sr_status);
		goto retry_nowait;
822 823
	default:
		/* Just update the slot sequence no. */
824
		slot->seq_done = 1;
A
Andy Adamson 已提交
825 826 827 828
	}
out:
	/* The session may be reset by one of the error handlers. */
	dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
829
out_noaction:
830
	return ret;
831 832
retry_nowait:
	if (rpc_restart_call_prepare(task)) {
833
		nfs41_sequence_free_slot(res);
834 835 836 837
		task->tk_status = 0;
		ret = 0;
	}
	goto out;
838
out_retry:
839
	if (!rpc_restart_call(task))
840 841 842
		goto out;
	rpc_delay(task, NFS4_POLL_RETRY_MAX);
	return 0;
A
Andy Adamson 已提交
843
}
844 845 846 847 848 849 850 851 852 853

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;

}
854
EXPORT_SYMBOL_GPL(nfs41_sequence_done);
A
Andy Adamson 已提交
855

856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
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 已提交
875
int nfs4_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
876
{
877
	if (res->sr_slot == NULL)
878
		return 1;
C
Chuck Lever 已提交
879 880
	if (!res->sr_slot->table->session)
		return nfs40_sequence_done(task, res);
881
	return nfs41_sequence_done(task, res);
882
}
P
Peng Tao 已提交
883
EXPORT_SYMBOL_GPL(nfs4_sequence_done);
884

A
Andy Adamson 已提交
885
int nfs41_setup_sequence(struct nfs4_session *session,
A
Andy Adamson 已提交
886 887 888 889
				struct nfs4_sequence_args *args,
				struct nfs4_sequence_res *res,
				struct rpc_task *task)
{
A
Andy Adamson 已提交
890 891 892 893
	struct nfs4_slot *slot;
	struct nfs4_slot_table *tbl;

	dprintk("--> %s\n", __func__);
A
Andy Adamson 已提交
894
	/* slot already allocated? */
895
	if (res->sr_slot != NULL)
896
		goto out_success;
A
Andy Adamson 已提交
897

A
Andy Adamson 已提交
898 899
	tbl = &session->fc_slot_table;

900 901
	task->tk_timeout = 0;

A
Andy Adamson 已提交
902
	spin_lock(&tbl->slot_tbl_lock);
903
	if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state) &&
904
	    !args->sa_privileged) {
905 906
		/* The state manager will wait until the slot table is empty */
		dprintk("%s session is draining\n", __func__);
907
		goto out_sleep;
908 909
	}

910
	slot = nfs4_alloc_slot(tbl);
911 912 913 914
	if (IS_ERR(slot)) {
		/* If out of memory, try again in 1/4 second */
		if (slot == ERR_PTR(-ENOMEM))
			task->tk_timeout = HZ >> 2;
A
Andy Adamson 已提交
915
		dprintk("<-- %s: no free slots\n", __func__);
916
		goto out_sleep;
A
Andy Adamson 已提交
917 918 919
	}
	spin_unlock(&tbl->slot_tbl_lock);

920
	slot->privileged = args->sa_privileged ? 1 : 0;
921
	args->sa_slot = slot;
A
Andy Adamson 已提交
922

923
	dprintk("<-- %s slotid=%u seqid=%u\n", __func__,
924
			slot->slot_nr, slot->seq_nr);
A
Andy Adamson 已提交
925

926
	res->sr_slot = slot;
927
	res->sr_timestamp = jiffies;
928
	res->sr_status_flags = 0;
A
Andy Adamson 已提交
929 930 931 932 933
	/*
	 * sr_status is only set in decode_sequence, and so will remain
	 * set to 1 if an rpc level failure occurs.
	 */
	res->sr_status = 1;
934
	trace_nfs4_setup_sequence(session, args);
935 936
out_success:
	rpc_call_start(task);
A
Andy Adamson 已提交
937
	return 0;
938
out_sleep:
939 940
	/* Privileged tasks are queued with top priority */
	if (args->sa_privileged)
941 942 943 944
		rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task,
				NULL, RPC_PRIORITY_PRIVILEGED);
	else
		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
945 946
	spin_unlock(&tbl->slot_tbl_lock);
	return -EAGAIN;
A
Andy Adamson 已提交
947
}
A
Andy Adamson 已提交
948
EXPORT_SYMBOL_GPL(nfs41_setup_sequence);
A
Andy Adamson 已提交
949

950 951 952 953
static int nfs4_setup_sequence(const struct nfs_server *server,
			       struct nfs4_sequence_args *args,
			       struct nfs4_sequence_res *res,
			       struct rpc_task *task)
A
Andy Adamson 已提交
954
{
955
	struct nfs4_session *session = nfs4_get_session(server);
A
Andy Adamson 已提交
956 957
	int ret = 0;

C
Chuck Lever 已提交
958
	if (!session)
959 960
		return nfs40_setup_sequence(server->nfs_client->cl_slot_tbl,
					    args, res, task);
961

962
	dprintk("--> %s clp %p session %p sr_slot %u\n",
963
		__func__, session->clp, session, res->sr_slot ?
964
			res->sr_slot->slot_nr : NFS4_NO_SLOT);
A
Andy Adamson 已提交
965

966
	ret = nfs41_setup_sequence(session, args, res, task);
C
Chuck Lever 已提交
967

A
Andy Adamson 已提交
968 969 970 971 972 973
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
}

static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
{
974
	struct nfs4_call_sync_data *data = calldata;
975
	struct nfs4_session *session = nfs4_get_session(data->seq_server);
A
Andy Adamson 已提交
976

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

979
	nfs41_setup_sequence(session, data->seq_args, data->seq_res, task);
A
Andy Adamson 已提交
980 981
}

A
Andy Adamson 已提交
982 983
static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
{
984
	struct nfs4_call_sync_data *data = calldata;
A
Andy Adamson 已提交
985

986
	nfs41_sequence_done(task, data->seq_res);
A
Andy Adamson 已提交
987 988
}

989
static const struct rpc_call_ops nfs41_call_sync_ops = {
A
Andy Adamson 已提交
990
	.rpc_call_prepare = nfs41_call_sync_prepare,
A
Andy Adamson 已提交
991
	.rpc_call_done = nfs41_call_sync_done,
A
Andy Adamson 已提交
992 993
};

C
Chuck Lever 已提交
994 995
#else	/* !CONFIG_NFS_V4_1 */

996 997 998 999 1000
static int nfs4_setup_sequence(const struct nfs_server *server,
			       struct nfs4_sequence_args *args,
			       struct nfs4_sequence_res *res,
			       struct rpc_task *task)
{
1001 1002
	return nfs40_setup_sequence(server->nfs_client->cl_slot_tbl,
				    args, res, task);
1003 1004
}

1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
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 已提交
1016 1017
int nfs4_sequence_done(struct rpc_task *task,
		       struct nfs4_sequence_res *res)
1018
{
C
Chuck Lever 已提交
1019
	return nfs40_sequence_done(task, res);
1020
}
P
Peng Tao 已提交
1021
EXPORT_SYMBOL_GPL(nfs4_sequence_done);
C
Chuck Lever 已提交
1022 1023

#endif	/* !CONFIG_NFS_V4_1 */
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042

static void nfs40_call_sync_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_call_sync_data *data = calldata;
	nfs4_setup_sequence(data->seq_server,
				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,
};

1043 1044
static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
				   struct nfs_server *server,
A
Andy Adamson 已提交
1045 1046
				   struct rpc_message *msg,
				   struct nfs4_sequence_args *args,
1047
				   struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
1048 1049 1050
{
	int ret;
	struct rpc_task *task;
1051
	struct nfs_client *clp = server->nfs_client;
1052
	struct nfs4_call_sync_data data = {
1053
		.seq_server = server,
A
Andy Adamson 已提交
1054 1055 1056 1057
		.seq_args = args,
		.seq_res = res,
	};
	struct rpc_task_setup task_setup = {
1058
		.rpc_client = clnt,
A
Andy Adamson 已提交
1059
		.rpc_message = msg,
1060
		.callback_ops = clp->cl_mvops->call_sync_ops,
A
Andy Adamson 已提交
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
		.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;
}

1074 1075
int nfs4_call_sync(struct rpc_clnt *clnt,
		   struct nfs_server *server,
1076 1077 1078 1079 1080
		   struct rpc_message *msg,
		   struct nfs4_sequence_args *args,
		   struct nfs4_sequence_res *res,
		   int cache_reply)
{
1081
	nfs4_init_sequence(args, res, cache_reply);
1082
	return nfs4_call_sync_sequence(clnt, server, msg, args, res);
1083
}
A
Andy Adamson 已提交
1084

1085
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
L
Linus Torvalds 已提交
1086
{
1087
	struct nfs_inode *nfsi = NFS_I(dir);
L
Linus Torvalds 已提交
1088

1089
	spin_lock(&dir->i_lock);
1090
	nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
1091 1092 1093 1094
	if (cinfo->atomic && cinfo->before == dir->i_version) {
		nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
		nfsi->attrtimeo_timestamp = jiffies;
	} else {
1095
		nfs_force_lookup_revalidate(dir);
1096 1097 1098 1099
		if (cinfo->before != dir->i_version)
			nfsi->cache_validity |= NFS_INO_INVALID_ACCESS |
				NFS_INO_INVALID_ACL;
	}
1100
	dir->i_version = cinfo->after;
1101
	nfsi->attr_gencount = nfs_inc_attr_generation_counter();
D
David Howells 已提交
1102
	nfs_fscache_invalidate(dir);
1103
	spin_unlock(&dir->i_lock);
L
Linus Torvalds 已提交
1104 1105
}

1106
struct nfs4_opendata {
1107
	struct kref kref;
1108 1109
	struct nfs_openargs o_arg;
	struct nfs_openres o_res;
1110 1111
	struct nfs_open_confirmargs c_arg;
	struct nfs_open_confirmres c_res;
1112 1113
	struct nfs4_string owner_name;
	struct nfs4_string group_name;
1114
	struct nfs4_label *a_label;
1115
	struct nfs_fattr f_attr;
1116
	struct nfs4_label *f_label;
1117
	struct dentry *dir;
1118
	struct dentry *dentry;
1119
	struct nfs4_state_owner *owner;
1120
	struct nfs4_state *state;
1121
	struct iattr attrs;
1122
	unsigned long timestamp;
1123
	unsigned int rpc_done : 1;
1124
	unsigned int file_created : 1;
1125
	unsigned int is_recover : 1;
1126 1127
	int rpc_status;
	int cancelled;
1128 1129
};

1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
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;
}

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
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;
}

1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
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;
	}
}
1184 1185 1186 1187

static void nfs4_init_opendata_res(struct nfs4_opendata *p)
{
	p->o_res.f_attr = &p->f_attr;
1188
	p->o_res.f_label = p->f_label;
1189 1190
	p->o_res.seqid = p->o_arg.seqid;
	p->c_res.seqid = p->c_arg.seqid;
1191
	p->o_res.server = p->o_arg.server;
1192
	p->o_res.access_request = p->o_arg.access;
1193
	nfs_fattr_init(&p->f_attr);
1194
	nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name);
1195 1196
}

1197
static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
1198
		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
1199
		const struct iattr *attrs,
1200
		struct nfs4_label *label,
1201
		enum open_claim_type4 claim,
1202
		gfp_t gfp_mask)
1203
{
1204
	struct dentry *parent = dget_parent(dentry);
1205
	struct inode *dir = d_inode(parent);
1206
	struct nfs_server *server = NFS_SERVER(dir);
1207
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
1208 1209
	struct nfs4_opendata *p;

1210
	p = kzalloc(sizeof(*p), gfp_mask);
1211 1212
	if (p == NULL)
		goto err;
1213 1214 1215 1216 1217

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

1218 1219 1220 1221
	p->a_label = nfs4_label_alloc(server, gfp_mask);
	if (IS_ERR(p->a_label))
		goto err_free_f;

1222 1223
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask);
1224
	if (IS_ERR(p->o_arg.seqid))
1225
		goto err_free_label;
1226 1227
	nfs_sb_active(dentry->d_sb);
	p->dentry = dget(dentry);
1228 1229 1230
	p->dir = parent;
	p->owner = sp;
	atomic_inc(&sp->so_count);
1231 1232
	p->o_arg.open_flags = flags;
	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
1233
	p->o_arg.umask = current_umask();
1234
	p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
1235 1236
	p->o_arg.share_access = nfs4_map_atomic_open_share(server,
			fmode, flags);
1237 1238 1239 1240 1241
	/* 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 */
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
		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;
		}
1252
	}
1253
	p->o_arg.clientid = server->nfs_client->cl_clientid;
1254 1255
	p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
	p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
1256
	p->o_arg.name = &dentry->d_name;
1257
	p->o_arg.server = server;
1258
	p->o_arg.bitmask = nfs4_bitmask(server, label);
1259
	p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
1260
	p->o_arg.label = nfs4_label_copy(p->a_label, label);
1261
	switch (p->o_arg.claim) {
1262 1263 1264 1265 1266 1267 1268 1269 1270
	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:
1271
		p->o_arg.fh = NFS_FH(d_inode(dentry));
1272
	}
1273
	if (attrs != NULL && attrs->ia_valid != 0) {
1274
		__u32 verf[2];
1275

1276 1277
		p->o_arg.u.attrs = &p->attrs;
		memcpy(&p->attrs, attrs, sizeof(p->attrs));
1278 1279 1280 1281 1282

		verf[0] = jiffies;
		verf[1] = current->pid;
		memcpy(p->o_arg.u.verifier.data, verf,
				sizeof(p->o_arg.u.verifier.data));
1283
	}
1284 1285 1286
	p->c_arg.fh = &p->o_res.fh;
	p->c_arg.stateid = &p->o_res.stateid;
	p->c_arg.seqid = p->o_arg.seqid;
1287
	nfs4_init_opendata_res(p);
1288
	kref_init(&p->kref);
1289
	return p;
1290 1291

err_free_label:
1292 1293
	nfs4_label_free(p->a_label);
err_free_f:
1294 1295
	nfs4_label_free(p->f_label);
err_free_p:
1296 1297 1298 1299 1300 1301
	kfree(p);
err:
	dput(parent);
	return NULL;
}

1302
static void nfs4_opendata_free(struct kref *kref)
1303
{
1304 1305
	struct nfs4_opendata *p = container_of(kref,
			struct nfs4_opendata, kref);
1306
	struct super_block *sb = p->dentry->d_sb;
1307 1308

	nfs_free_seqid(p->o_arg.seqid);
1309
	nfs4_sequence_free_slot(&p->o_res.seq_res);
1310 1311
	if (p->state != NULL)
		nfs4_put_open_state(p->state);
1312
	nfs4_put_state_owner(p->owner);
1313

1314
	nfs4_label_free(p->a_label);
1315 1316
	nfs4_label_free(p->f_label);

1317
	dput(p->dir);
1318 1319
	dput(p->dentry);
	nfs_sb_deactive(sb);
1320
	nfs_fattr_free_names(&p->f_attr);
1321
	kfree(p->f_attr.mdsthreshold);
1322 1323 1324 1325 1326 1327 1328
	kfree(p);
}

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

1331 1332 1333 1334 1335 1336 1337 1338
static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
{
	int ret;

	ret = rpc_wait_for_completion_task(task);
	return ret;
}

1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
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;
}

1354
static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
1355 1356
{
	int ret = 0;
1357

1358
	if (open_mode & (O_EXCL|O_TRUNC))
1359 1360
		goto out;
	switch (mode & (FMODE_READ|FMODE_WRITE)) {
1361
		case FMODE_READ:
1362 1363
			ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0
				&& state->n_rdonly != 0;
1364 1365
			break;
		case FMODE_WRITE:
1366 1367
			ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0
				&& state->n_wronly != 0;
1368 1369
			break;
		case FMODE_READ|FMODE_WRITE:
1370 1371
			ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0
				&& state->n_rdwr != 0;
1372
	}
1373
out:
1374 1375 1376
	return ret;
}

1377 1378
static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,
		enum open_claim_type4 claim)
1379
{
1380 1381
	if (delegation == NULL)
		return 0;
1382
	if ((delegation->type & fmode) != fmode)
1383
		return 0;
1384 1385
	if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
		return 0;
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
	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;
	}
1396
	nfs_mark_delegation_referenced(delegation);
1397 1398 1399
	return 1;
}

1400
static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
1401
{
1402
	switch (fmode) {
1403 1404 1405 1406 1407 1408 1409 1410 1411
		case FMODE_WRITE:
			state->n_wronly++;
			break;
		case FMODE_READ:
			state->n_rdonly++;
			break;
		case FMODE_READ|FMODE_WRITE:
			state->n_rdwr++;
	}
1412
	nfs4_state_set_mode_locked(state, state->state | fmode);
1413 1414
}

1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
#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 */

1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442
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);
}

1443
static bool nfs_need_update_open_stateid(struct nfs4_state *state,
1444
		const nfs4_stateid *stateid, nfs4_stateid *freeme)
1445 1446 1447
{
	if (test_and_set_bit(NFS_OPEN_STATE, &state->flags) == 0)
		return true;
1448
	if (!nfs4_stateid_match_other(stateid, &state->open_stateid)) {
1449
		nfs4_stateid_copy(freeme, &state->open_stateid);
1450
		nfs_test_and_clear_all_open_stateid(state);
1451
		return true;
1452
	}
1453 1454 1455 1456 1457
	if (nfs4_stateid_is_newer(stateid, &state->open_stateid))
		return true;
	return false;
}

T
Trond Myklebust 已提交
1458 1459
static void nfs_resync_open_stateid_locked(struct nfs4_state *state)
{
1460 1461
	if (!(state->n_wronly || state->n_rdonly || state->n_rdwr))
		return;
T
Trond Myklebust 已提交
1462 1463 1464 1465 1466 1467
	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);
1468
	set_bit(NFS_OPEN_STATE, &state->flags);
T
Trond Myklebust 已提交
1469 1470
}

1471 1472
static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
		nfs4_stateid *stateid, fmode_t fmode)
1473
{
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
	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 已提交
1489 1490 1491
	/* 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 已提交
1492
		nfs_resync_open_stateid_locked(state);
1493
		return;
T
Trond Myklebust 已提交
1494
	}
1495
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1496 1497
		nfs4_stateid_copy(&state->stateid, stateid);
	nfs4_stateid_copy(&state->open_stateid, stateid);
1498 1499
}

1500 1501 1502
static void nfs_clear_open_stateid(struct nfs4_state *state,
	nfs4_stateid *arg_stateid,
	nfs4_stateid *stateid, fmode_t fmode)
1503 1504
{
	write_seqlock(&state->seqlock);
T
Trond Myklebust 已提交
1505 1506 1507
	/* 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);
1508
	write_sequnlock(&state->seqlock);
1509 1510
	if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
		nfs4_schedule_state_manager(state->owner->so_server->nfs_client);
1511 1512
}

1513 1514 1515
static void nfs_set_open_stateid_locked(struct nfs4_state *state,
		const nfs4_stateid *stateid, fmode_t fmode,
		nfs4_stateid *freeme)
1516
{
1517
	switch (fmode) {
1518 1519 1520 1521 1522 1523 1524 1525 1526
		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);
	}
1527
	if (!nfs_need_update_open_stateid(state, stateid, freeme))
1528 1529 1530 1531
		return;
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
		nfs4_stateid_copy(&state->stateid, stateid);
	nfs4_stateid_copy(&state->open_stateid, stateid);
1532 1533
}

1534 1535 1536 1537 1538
static void __update_open_stateid(struct nfs4_state *state,
		const nfs4_stateid *open_stateid,
		const nfs4_stateid *deleg_stateid,
		fmode_t fmode,
		nfs4_stateid *freeme)
L
Linus Torvalds 已提交
1539
{
1540 1541 1542 1543
	/*
	 * Protect the call to nfs4_state_set_mode_locked and
	 * serialise the stateid update
	 */
1544
	spin_lock(&state->owner->so_lock);
1545
	write_seqlock(&state->seqlock);
1546
	if (deleg_stateid != NULL) {
1547
		nfs4_stateid_copy(&state->stateid, deleg_stateid);
1548 1549 1550
		set_bit(NFS_DELEGATED_STATE, &state->flags);
	}
	if (open_stateid != NULL)
1551
		nfs_set_open_stateid_locked(state, open_stateid, fmode, freeme);
1552
	write_sequnlock(&state->seqlock);
1553
	update_open_stateflags(state, fmode);
1554
	spin_unlock(&state->owner->so_lock);
L
Linus Torvalds 已提交
1555 1556
}

1557 1558 1559 1560
static int update_open_stateid(struct nfs4_state *state,
		const nfs4_stateid *open_stateid,
		const nfs4_stateid *delegation,
		fmode_t fmode)
1561
{
1562 1563
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs_client *clp = server->nfs_client;
1564 1565
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_delegation *deleg_cur;
A
Arnd Bergmann 已提交
1566
	nfs4_stateid freeme = { };
1567 1568
	int ret = 0;

1569
	fmode &= (FMODE_READ|FMODE_WRITE);
1570 1571 1572 1573 1574 1575 1576

	rcu_read_lock();
	deleg_cur = rcu_dereference(nfsi->delegation);
	if (deleg_cur == NULL)
		goto no_delegation;

	spin_lock(&deleg_cur->lock);
1577
	if (rcu_dereference(nfsi->delegation) != deleg_cur ||
1578
	   test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) ||
1579
	    (deleg_cur->type & fmode) != fmode)
1580 1581 1582 1583
		goto no_delegation_unlock;

	if (delegation == NULL)
		delegation = &deleg_cur->stateid;
1584
	else if (!nfs4_stateid_match(&deleg_cur->stateid, delegation))
1585 1586
		goto no_delegation_unlock;

1587
	nfs_mark_delegation_referenced(deleg_cur);
1588 1589
	__update_open_stateid(state, open_stateid, &deleg_cur->stateid,
			fmode, &freeme);
1590 1591 1592 1593 1594 1595 1596
	ret = 1;
no_delegation_unlock:
	spin_unlock(&deleg_cur->lock);
no_delegation:
	rcu_read_unlock();

	if (!ret && open_stateid != NULL) {
1597
		__update_open_stateid(state, open_stateid, NULL, fmode, &freeme);
1598 1599
		ret = 1;
	}
1600
	if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags))
1601 1602 1603 1604
		nfs4_schedule_state_manager(clp);
	if (freeme.type != 0)
		nfs4_test_and_free_stateid(server, &freeme,
				state->owner->so_cred);
1605 1606 1607 1608

	return ret;
}

1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
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;
}
1626

1627
static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmode)
1628 1629 1630 1631 1632
{
	struct nfs_delegation *delegation;

	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(inode)->delegation);
1633
	if (delegation == NULL || (delegation->type & fmode) == fmode) {
1634 1635 1636 1637
		rcu_read_unlock();
		return;
	}
	rcu_read_unlock();
1638
	nfs4_inode_return_delegation(inode);
1639 1640
}

1641
static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
1642 1643 1644 1645
{
	struct nfs4_state *state = opendata->state;
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_delegation *delegation;
1646
	int open_mode = opendata->o_arg.open_flags;
1647
	fmode_t fmode = opendata->o_arg.fmode;
1648
	enum open_claim_type4 claim = opendata->o_arg.claim;
1649 1650 1651 1652
	nfs4_stateid stateid;
	int ret = -EAGAIN;

	for (;;) {
1653
		spin_lock(&state->owner->so_lock);
1654
		if (can_open_cached(state, fmode, open_mode)) {
1655
			update_open_stateflags(state, fmode);
1656
			spin_unlock(&state->owner->so_lock);
1657
			goto out_return_state;
1658
		}
1659
		spin_unlock(&state->owner->so_lock);
1660 1661
		rcu_read_lock();
		delegation = rcu_dereference(nfsi->delegation);
1662
		if (!can_open_delegated(delegation, fmode, claim)) {
1663
			rcu_read_unlock();
1664
			break;
1665
		}
1666
		/* Save the delegation */
1667
		nfs4_stateid_copy(&stateid, &delegation->stateid);
1668
		rcu_read_unlock();
1669
		nfs_release_seqid(opendata->o_arg.seqid);
1670 1671 1672 1673 1674
		if (!opendata->is_recover) {
			ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
			if (ret != 0)
				goto out;
		}
1675
		ret = -EAGAIN;
1676 1677

		/* Try to update the stateid using the delegation */
1678
		if (update_open_stateid(state, NULL, &stateid, fmode))
1679
			goto out_return_state;
1680 1681 1682 1683 1684 1685 1686 1687
	}
out:
	return ERR_PTR(ret);
out_return_state:
	atomic_inc(&state->count);
	return state;
}

1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
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();
1700 1701 1702 1703 1704
	switch (data->o_arg.claim) {
	default:
		break;
	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
1705 1706 1707 1708
		pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
				   "returning a delegation for "
				   "OPEN(CLAIM_DELEGATE_CUR)\n",
				   clp->cl_hostname);
1709 1710 1711
		return;
	}
	if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731
		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;

1732 1733 1734 1735 1736 1737 1738
	if (!data->rpc_done) {
		if (data->rpc_status) {
			ret = data->rpc_status;
			goto err;
		}
		/* cached opens have already been processed */
		goto update;
1739 1740 1741 1742 1743 1744 1745 1746
	}

	ret = nfs_refresh_inode(inode, &data->f_attr);
	if (ret)
		goto err;

	if (data->o_res.delegation_type != 0)
		nfs4_opendata_check_deleg(data, state);
1747
update:
1748 1749
	update_open_stateid(state, &data->o_res.stateid, NULL,
			    data->o_arg.fmode);
1750
	atomic_inc(&state->count);
1751 1752 1753 1754 1755 1756 1757 1758 1759

	return state;
err:
	return ERR_PTR(ret);

}

static struct nfs4_state *
_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
1760 1761 1762
{
	struct inode *inode;
	struct nfs4_state *state = NULL;
1763
	int ret;
1764

1765
	if (!data->rpc_done) {
1766
		state = nfs4_try_open_cached(data);
1767
		trace_nfs4_cached_open(data->state);
1768 1769 1770
		goto out;
	}

1771
	ret = -EAGAIN;
1772
	if (!(data->f_attr.valid & NFS_ATTR_FATTR))
1773
		goto err;
1774
	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr, data->f_label);
1775
	ret = PTR_ERR(inode);
1776
	if (IS_ERR(inode))
1777 1778
		goto err;
	ret = -ENOMEM;
1779 1780
	state = nfs4_get_open_state(inode, data->owner);
	if (state == NULL)
1781
		goto err_put_inode;
1782 1783
	if (data->o_res.delegation_type != 0)
		nfs4_opendata_check_deleg(data, state);
1784
	update_open_stateid(state, &data->o_res.stateid, NULL,
1785
			data->o_arg.fmode);
1786
	iput(inode);
1787
out:
1788
	nfs_release_seqid(data->o_arg.seqid);
1789
	return state;
1790 1791 1792 1793
err_put_inode:
	iput(inode);
err:
	return ERR_PTR(ret);
1794 1795
}

1796 1797 1798
static struct nfs4_state *
nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
{
1799 1800
	struct nfs4_state *ret;

1801
	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
1802 1803 1804 1805 1806
		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;
1807 1808
}

1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
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);
}

1826 1827
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 已提交
1828 1829 1830
{
	struct nfs4_opendata *opendata;

1831
	opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0,
1832
			NULL, NULL, claim, GFP_NOFS);
T
Trond Myklebust 已提交
1833 1834 1835 1836 1837 1838 1839
	if (opendata == NULL)
		return ERR_PTR(-ENOMEM);
	opendata->state = state;
	atomic_inc(&state->count);
	return opendata;
}

1840 1841
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
		fmode_t fmode)
1842
{
1843
	struct nfs4_state *newstate;
1844 1845
	int ret;

1846
	if (!nfs4_mode_match_open_stateid(opendata->state, fmode))
1847
		return 0;
1848 1849
	opendata->o_arg.open_flags = 0;
	opendata->o_arg.fmode = fmode;
1850 1851 1852
	opendata->o_arg.share_access = nfs4_map_atomic_open_share(
			NFS_SB(opendata->dentry->d_sb),
			fmode, 0);
1853 1854 1855
	memset(&opendata->o_res, 0, sizeof(opendata->o_res));
	memset(&opendata->c_res, 0, sizeof(opendata->c_res));
	nfs4_init_opendata_res(opendata);
1856
	ret = _nfs4_recover_proc_open(opendata);
1857 1858
	if (ret != 0)
		return ret; 
1859
	newstate = nfs4_opendata_to_nfs4_state(opendata);
1860 1861
	if (IS_ERR(newstate))
		return PTR_ERR(newstate);
1862 1863
	if (newstate != opendata->state)
		ret = -ESTALE;
1864
	nfs4_close_state(newstate, fmode);
1865
	return ret;
1866 1867 1868 1869 1870 1871
}

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

1872 1873 1874 1875
	/* 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);
1876
	/* memory barrier prior to reading state->n_* */
1877
	clear_bit(NFS_DELEGATED_STATE, &state->flags);
1878
	clear_bit(NFS_OPEN_STATE, &state->flags);
1879
	smp_rmb();
1880 1881 1882 1883 1884 1885 1886 1887 1888
	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;
1889 1890 1891 1892 1893
	/*
	 * 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 &&
1894
	    !nfs4_stateid_match(&state->stateid, &state->open_stateid)) {
1895
		write_seqlock(&state->seqlock);
1896
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1897
			nfs4_stateid_copy(&state->stateid, &state->open_stateid);
1898
		write_sequnlock(&state->seqlock);
1899
	}
1900 1901 1902
	return 0;
}

L
Linus Torvalds 已提交
1903 1904 1905 1906
/*
 * OPEN_RECLAIM:
 * 	reclaim state on the server after a reboot.
 */
1907
static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1908
{
1909
	struct nfs_delegation *delegation;
1910
	struct nfs4_opendata *opendata;
1911
	fmode_t delegation_type = 0;
L
Linus Torvalds 已提交
1912 1913
	int status;

1914 1915
	opendata = nfs4_open_recoverdata_alloc(ctx, state,
			NFS4_OPEN_CLAIM_PREVIOUS);
T
Trond Myklebust 已提交
1916 1917
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
1918 1919
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
1920
	if (delegation != NULL && test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) != 0)
1921
		delegation_type = delegation->type;
1922
	rcu_read_unlock();
1923 1924
	opendata->o_arg.u.delegation_type = delegation_type;
	status = nfs4_open_recover(opendata, state);
1925
	nfs4_opendata_put(opendata);
L
Linus Torvalds 已提交
1926 1927 1928
	return status;
}

1929
static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1930 1931 1932 1933 1934
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_exception exception = { };
	int err;
	do {
1935
		err = _nfs4_do_open_reclaim(ctx, state);
1936
		trace_nfs4_open_reclaim(ctx, 0, err);
1937 1938
		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
			continue;
1939
		if (err != -NFS4ERR_DELAY)
1940 1941
			break;
		nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
1942 1943 1944 1945
	} while (exception.retry);
	return err;
}

1946 1947 1948 1949 1950 1951 1952
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))
1953
		return -EAGAIN;
1954
	ret = nfs4_do_open_reclaim(ctx, state);
1955 1956 1957 1958
	put_nfs_open_context(ctx);
	return ret;
}

1959
static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, int err)
L
Linus Torvalds 已提交
1960
{
1961 1962 1963 1964 1965 1966
	switch (err) {
		default:
			printk(KERN_ERR "NFS: %s: unhandled error "
					"%d.\n", __func__, err);
		case 0:
		case -ENOENT:
1967
		case -EAGAIN:
1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
		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;
1984 1985 1986
		case -NFS4ERR_MOVED:
			nfs4_schedule_migration_recovery(server);
			return -EAGAIN;
1987 1988 1989
		case -NFS4ERR_LEASE_MOVED:
			nfs4_schedule_lease_moved_recovery(server->nfs_client);
			return -EAGAIN;
1990 1991
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_ADMIN_REVOKED:
1992
		case -NFS4ERR_EXPIRED:
1993
		case -NFS4ERR_BAD_STATEID:
1994
		case -NFS4ERR_OPENMODE:
1995 1996 1997
			nfs_inode_find_state_and_recover(state->inode,
					stateid);
			nfs4_schedule_stateid_recovery(server, state);
1998
			return -EAGAIN;
1999 2000 2001 2002 2003
		case -NFS4ERR_DELAY:
		case -NFS4ERR_GRACE:
			set_bit(NFS_DELEGATED_STATE, &state->flags);
			ssleep(1);
			return -EAGAIN;
2004 2005 2006 2007
		case -ENOMEM:
		case -NFS4ERR_DENIED:
			/* kill_proc(fl->fl_pid, SIGLOST, 1); */
			return 0;
2008
	}
L
Linus Torvalds 已提交
2009 2010 2011
	return err;
}

2012 2013 2014
int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
		struct nfs4_state *state, const nfs4_stateid *stateid,
		fmode_t type)
2015 2016 2017
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_opendata *opendata;
2018
	int err = 0;
2019 2020 2021 2022 2023 2024

	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);
2025 2026 2027
	write_seqlock(&state->seqlock);
	nfs4_stateid_copy(&state->stateid, &state->open_stateid);
	write_sequnlock(&state->seqlock);
2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040
	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);
	}
2041 2042 2043 2044
	nfs4_opendata_put(opendata);
	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
}

2045 2046 2047 2048
static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;

2049 2050
	nfs40_setup_sequence(data->o_arg.server->nfs_client->cl_slot_tbl,
			     &data->c_arg.seq_args, &data->c_res.seq_res, task);
2051 2052
}

2053 2054 2055 2056
static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;

2057
	nfs40_sequence_done(task, &data->c_res.seq_res);
2058

2059
	data->rpc_status = task->tk_status;
2060
	if (data->rpc_status == 0) {
2061
		nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid);
2062
		nfs_confirm_seqid(&data->owner->so_seqid, 0);
2063
		renew_lease(data->o_res.server, data->timestamp);
2064
		data->rpc_done = 1;
2065
	}
2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076
}

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 */
	if (data->cancelled == 0)
		goto out_free;
	/* In case of error, no cleanup! */
2077
	if (!data->rpc_done)
2078 2079
		goto out_free;
	state = nfs4_opendata_to_nfs4_state(data);
2080
	if (!IS_ERR(state))
2081
		nfs4_close_state(state, data->o_arg.fmode);
2082
out_free:
2083
	nfs4_opendata_put(data);
2084 2085 2086
}

static const struct rpc_call_ops nfs4_open_confirm_ops = {
2087
	.rpc_call_prepare = nfs4_open_confirm_prepare,
2088 2089 2090 2091 2092 2093 2094 2095 2096
	.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)
{
2097
	struct nfs_server *server = NFS_SERVER(d_inode(data->dir));
2098
	struct rpc_task *task;
2099 2100 2101 2102 2103 2104
	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 已提交
2105 2106
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
2107
		.rpc_message = &msg,
T
Trond Myklebust 已提交
2108 2109
		.callback_ops = &nfs4_open_confirm_ops,
		.callback_data = data,
2110
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
2111 2112
		.flags = RPC_TASK_ASYNC,
	};
L
Linus Torvalds 已提交
2113 2114
	int status;

2115
	nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
2116
	kref_get(&data->kref);
2117 2118
	data->rpc_done = 0;
	data->rpc_status = 0;
2119
	data->timestamp = jiffies;
2120 2121
	if (data->is_recover)
		nfs4_set_sequence_privileged(&data->c_arg.seq_args);
T
Trond Myklebust 已提交
2122
	task = rpc_run_task(&task_setup_data);
2123
	if (IS_ERR(task))
2124 2125 2126 2127 2128 2129 2130
		return PTR_ERR(task);
	status = nfs4_wait_for_completion_rpc_task(task);
	if (status != 0) {
		data->cancelled = 1;
		smp_wmb();
	} else
		status = data->rpc_status;
2131
	rpc_put_task(task);
L
Linus Torvalds 已提交
2132 2133 2134
	return status;
}

2135
static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
2136
{
2137 2138
	struct nfs4_opendata *data = calldata;
	struct nfs4_state_owner *sp = data->owner;
2139
	struct nfs_client *clp = sp->so_server->nfs_client;
2140
	enum open_claim_type4 claim = data->o_arg.claim;
2141

2142
	if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
2143
		goto out_wait;
2144 2145 2146 2147 2148 2149 2150
	/*
	 * 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;

2151
		if (can_open_cached(data->state, data->o_arg.fmode, data->o_arg.open_flags))
2152
			goto out_no_action;
2153 2154
		rcu_read_lock();
		delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
2155
		if (can_open_delegated(delegation, data->o_arg.fmode, claim))
2156
			goto unlock_no_action;
2157 2158
		rcu_read_unlock();
	}
2159
	/* Update client id. */
2160
	data->o_arg.clientid = clp->cl_clientid;
2161 2162 2163
	switch (claim) {
	default:
		break;
2164 2165 2166
	case NFS4_OPEN_CLAIM_PREVIOUS:
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
2167
		data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
2168 2169
	case NFS4_OPEN_CLAIM_FH:
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
T
Trond Myklebust 已提交
2170 2171
		nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
	}
2172
	data->timestamp = jiffies;
2173
	if (nfs4_setup_sequence(data->o_arg.server,
2174
				&data->o_arg.seq_args,
2175 2176 2177
				&data->o_res.seq_res,
				task) != 0)
		nfs_release_seqid(data->o_arg.seqid);
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187

	/* 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;
	}
2188
	return;
2189
unlock_no_action:
2190
	trace_nfs4_cached_open(data->state);
2191
	rcu_read_unlock();
2192 2193
out_no_action:
	task->tk_action = NULL;
2194
out_wait:
2195
	nfs4_sequence_done(task, &data->o_res.seq_res);
2196 2197
}

2198 2199 2200
static void nfs4_open_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;
L
Linus Torvalds 已提交
2201

2202
	data->rpc_status = task->tk_status;
2203

2204
	if (!nfs4_sequence_process(task, &data->o_res.seq_res))
2205
		return;
2206

2207
	if (task->tk_status == 0) {
2208 2209
		if (data->o_res.f_attr->valid & NFS_ATTR_FATTR_TYPE) {
			switch (data->o_res.f_attr->mode & S_IFMT) {
2210 2211 2212
			case S_IFREG:
				break;
			case S_IFLNK:
2213
				data->rpc_status = -ELOOP;
2214 2215
				break;
			case S_IFDIR:
2216
				data->rpc_status = -EISDIR;
2217 2218
				break;
			default:
2219
				data->rpc_status = -ENOTDIR;
2220
			}
2221
		}
2222
		renew_lease(data->o_res.server, data->timestamp);
2223 2224
		if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
			nfs_confirm_seqid(&data->owner->so_seqid, 0);
2225
	}
2226
	data->rpc_done = 1;
2227
}
2228

2229 2230 2231 2232 2233 2234 2235 2236 2237
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 */
	if (data->cancelled == 0)
		goto out_free;
	/* In case of error, no cleanup! */
2238
	if (data->rpc_status != 0 || !data->rpc_done)
2239 2240 2241 2242 2243
		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);
2244
	if (!IS_ERR(state))
2245
		nfs4_close_state(state, data->o_arg.fmode);
2246
out_free:
2247
	nfs4_opendata_put(data);
2248 2249 2250 2251 2252 2253 2254 2255
}

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

2256
static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
2257
{
2258
	struct inode *dir = d_inode(data->dir);
2259 2260 2261 2262
	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;
2263 2264 2265 2266 2267 2268
	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 已提交
2269 2270
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
2271
		.rpc_message = &msg,
T
Trond Myklebust 已提交
2272 2273
		.callback_ops = &nfs4_open_ops,
		.callback_data = data,
2274
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
2275 2276
		.flags = RPC_TASK_ASYNC,
	};
2277 2278
	int status;

2279
	nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
2280
	kref_get(&data->kref);
2281 2282
	data->rpc_done = 0;
	data->rpc_status = 0;
2283
	data->cancelled = 0;
2284 2285
	data->is_recover = 0;
	if (isrecover) {
2286
		nfs4_set_sequence_privileged(&o_arg->seq_args);
2287 2288
		data->is_recover = 1;
	}
T
Trond Myklebust 已提交
2289
	task = rpc_run_task(&task_setup_data);
2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304
        if (IS_ERR(task))
                return PTR_ERR(task);
        status = nfs4_wait_for_completion_rpc_task(task);
        if (status != 0) {
                data->cancelled = 1;
                smp_wmb();
        } else
                status = data->rpc_status;
        rpc_put_task(task);

	return status;
}

static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
{
2305
	struct inode *dir = d_inode(data->dir);
2306 2307 2308 2309 2310 2311 2312
	struct nfs_openres *o_res = &data->o_res;
        int status;

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

2313 2314
	nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr);

2315 2316 2317 2318 2319 2320 2321 2322 2323
	if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
		status = _nfs4_proc_open_confirm(data);
		if (status != 0)
			return status;
	}

	return status;
}

2324 2325 2326 2327 2328 2329 2330 2331
/*
 * 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).
 */
2332 2333
static int nfs4_opendata_access(struct rpc_cred *cred,
				struct nfs4_opendata *opendata,
2334 2335
				struct nfs4_state *state, fmode_t fmode,
				int openflags)
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345
{
	struct nfs_access_entry cache;
	u32 mask;

	/* 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;
2346 2347 2348 2349
	/*
	 * Use openflags to check for exec, because fmode won't
	 * always have FMODE_EXEC set when file open for exec.
	 */
2350 2351 2352
	if (openflags & __FMODE_EXEC) {
		/* ONLY check for exec rights */
		mask = MAY_EXEC;
2353
	} else if ((fmode & FMODE_READ) && !opendata->file_created)
2354
		mask = MAY_READ;
2355 2356 2357 2358 2359 2360

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

2361
	if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
2362 2363 2364 2365
		return 0;

	/* even though OPEN succeeded, access is denied. Close the file */
	nfs4_close_state(state, fmode);
2366
	return -EACCES;
2367 2368
}

2369 2370 2371 2372 2373
/*
 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
 */
static int _nfs4_proc_open(struct nfs4_opendata *data)
{
2374
	struct inode *dir = d_inode(data->dir);
2375 2376 2377 2378 2379 2380
	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);
2381 2382 2383 2384 2385 2386
	if (!data->rpc_done)
		return status;
	if (status != 0) {
		if (status == -NFS4ERR_BADNAME &&
				!(o_arg->open_flags & O_CREAT))
			return -ENOENT;
2387
		return status;
2388
	}
2389

2390 2391
	nfs_fattr_map_and_free_names(server, &data->f_attr);

2392
	if (o_arg->open_flags & O_CREAT) {
2393
		update_changeattr(dir, &o_res->cinfo);
2394 2395 2396 2397 2398
		if (o_arg->open_flags & O_EXCL)
			data->file_created = 1;
		else if (o_res->cinfo.before != o_res->cinfo.after)
			data->file_created = 1;
	}
T
Trond Myklebust 已提交
2399 2400
	if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
		server->caps &= ~NFS_CAP_POSIX_LOCK;
L
Linus Torvalds 已提交
2401
	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
2402
		status = _nfs4_proc_open_confirm(data);
L
Linus Torvalds 已提交
2403
		if (status != 0)
2404
			return status;
L
Linus Torvalds 已提交
2405 2406
	}
	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
2407
		nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
2408
	return 0;
L
Linus Torvalds 已提交
2409 2410
}

A
Andy Adamson 已提交
2411 2412 2413 2414 2415
static int nfs4_recover_expired_lease(struct nfs_server *server)
{
	return nfs4_client_recover_expired_lease(server->nfs_client);
}

L
Linus Torvalds 已提交
2416 2417 2418 2419 2420
/*
 * OPEN_EXPIRED:
 * 	reclaim state on the server after a network partition.
 * 	Assumes caller holds the appropriate lock
 */
2421
static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
2422
{
2423
	struct nfs4_opendata *opendata;
2424
	int ret;
L
Linus Torvalds 已提交
2425

2426
	opendata = nfs4_open_recoverdata_alloc(ctx, state,
2427
			NFS4_OPEN_CLAIM_FH);
T
Trond Myklebust 已提交
2428 2429
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
2430
	ret = nfs4_open_recover(opendata, state);
2431
	if (ret == -ESTALE)
2432
		d_drop(ctx->dentry);
2433
	nfs4_opendata_put(opendata);
2434
	return ret;
L
Linus Torvalds 已提交
2435 2436
}

2437
static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
2438
{
2439
	struct nfs_server *server = NFS_SERVER(state->inode);
2440 2441 2442 2443
	struct nfs4_exception exception = { };
	int err;

	do {
2444
		err = _nfs4_open_expired(ctx, state);
2445
		trace_nfs4_open_expired(ctx, 0, err);
2446 2447
		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
			continue;
2448 2449 2450 2451 2452 2453 2454 2455
		switch (err) {
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
2456
	} while (exception.retry);
2457
out:
2458 2459 2460
	return err;
}

L
Linus Torvalds 已提交
2461 2462 2463
static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
	struct nfs_open_context *ctx;
2464
	int ret;
L
Linus Torvalds 已提交
2465

2466 2467
	ctx = nfs4_state_find_open_context(state);
	if (IS_ERR(ctx))
2468
		return -EAGAIN;
2469
	ret = nfs4_do_open_expired(ctx, state);
2470 2471
	put_nfs_open_context(ctx);
	return ret;
L
Linus Torvalds 已提交
2472 2473
}

2474 2475
static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state,
		const nfs4_stateid *stateid)
2476
{
2477
	nfs_remove_bad_delegation(state->inode, stateid);
2478 2479 2480 2481 2482 2483 2484 2485 2486
	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)
2487
		nfs_finish_clear_delegation_stateid(state, NULL);
2488 2489 2490 2491 2492 2493 2494 2495 2496
}

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

2497 2498 2499 2500 2501 2502 2503
static int nfs40_test_and_free_expired_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	return -NFS4ERR_BAD_STATEID;
}

2504
#if defined(CONFIG_NFS_V4_1)
2505 2506 2507 2508 2509 2510
static int nfs41_test_and_free_expired_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	int status;

2511 2512 2513 2514 2515 2516 2517 2518 2519
	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;
	}
2520

2521
	status = nfs41_test_stateid(server, stateid, cred);
2522 2523 2524 2525
	switch (status) {
	case -NFS4ERR_EXPIRED:
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_DELEG_REVOKED:
2526 2527
		break;
	default:
2528 2529
		return status;
	}
2530 2531
out_free:
	/* Ack the revoked state to the server */
2532
	nfs41_free_stateid(server, stateid, cred, true);
2533
	return -NFS4ERR_EXPIRED;
2534 2535
}

2536
static void nfs41_check_delegation_stateid(struct nfs4_state *state)
2537 2538
{
	struct nfs_server *server = NFS_SERVER(state->inode);
2539
	nfs4_stateid stateid;
2540
	struct nfs_delegation *delegation;
2541 2542
	struct rpc_cred *cred;
	int status;
2543

2544 2545 2546
	/* Get the delegation credential for use by test/free_stateid */
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
2547
	if (delegation == NULL) {
2548
		rcu_read_unlock();
2549 2550 2551 2552
		return;
	}

	nfs4_stateid_copy(&stateid, &delegation->stateid);
2553 2554
	if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
		rcu_read_unlock();
2555
		nfs_finish_clear_delegation_stateid(state, &stateid);
2556 2557
		return;
	}
2558

2559 2560 2561 2562 2563
	if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags)) {
		rcu_read_unlock();
		return;
	}

2564 2565
	cred = get_rpccred(delegation->cred);
	rcu_read_unlock();
2566
	status = nfs41_test_and_free_expired_stateid(server, &stateid, cred);
2567
	trace_nfs4_test_delegation_stateid(state, NULL, status);
2568
	if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
2569
		nfs_finish_clear_delegation_stateid(state, &stateid);
2570

2571
	put_rpccred(cred);
2572 2573
}

2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584
/**
 * 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;
2585
	struct nfs4_lock_state *lsp, *prev = NULL;
2586 2587 2588 2589
	struct nfs_server *server = NFS_SERVER(state->inode);

	if (!test_bit(LK_STATE_IN_USE, &state->flags))
		goto out;
2590 2591

	spin_lock(&state->state_lock);
2592 2593 2594 2595
	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;

2596 2597 2598 2599 2600 2601
			atomic_inc(&lsp->ls_count);
			spin_unlock(&state->state_lock);

			nfs4_put_lock_state(prev);
			prev = lsp;

2602 2603 2604 2605 2606 2607 2608
			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);
2609
				lsp->ls_stateid.type = NFS4_INVALID_STATEID_TYPE;
2610 2611 2612 2613
				if (!recover_lost_locks)
					set_bit(NFS_LOCK_LOST, &lsp->ls_flags);
			} else if (status != NFS_OK) {
				ret = status;
2614 2615
				nfs4_put_lock_state(prev);
				goto out;
2616
			}
2617
			spin_lock(&state->state_lock);
2618
		}
2619 2620 2621
	}
	spin_unlock(&state->state_lock);
	nfs4_put_lock_state(prev);
2622 2623 2624 2625
out:
	return ret;
}

2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636
/**
 * 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);
2637
	nfs4_stateid *stateid = &state->open_stateid;
2638
	struct rpc_cred *cred = state->owner->so_cred;
2639 2640
	int status;

2641
	if (test_bit(NFS_OPEN_STATE, &state->flags) == 0) {
2642 2643 2644 2645 2646
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)  {
			if (nfs4_have_delegation(state->inode, state->state))
				return NFS_OK;
			return -NFS4ERR_OPENMODE;
		}
2647
		return -NFS4ERR_BAD_STATEID;
2648
	}
2649
	status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
2650
	trace_nfs4_test_open_stateid(state, NULL, status);
2651
	if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) {
2652 2653 2654
		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
		clear_bit(NFS_O_RDWR_STATE, &state->flags);
2655
		clear_bit(NFS_OPEN_STATE, &state->flags);
2656
		stateid->type = NFS4_INVALID_STATEID_TYPE;
2657
	}
2658 2659 2660 2661 2662
	if (status != NFS_OK)
		return status;
	if (nfs_open_stateid_recover_openmode(state))
		return -NFS4ERR_OPENMODE;
	return NFS_OK;
2663 2664 2665 2666
}

static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
2667
	int status;
2668

2669
	nfs41_check_delegation_stateid(state);
2670 2671 2672
	status = nfs41_check_expired_locks(state);
	if (status != NFS_OK)
		return status;
2673
	status = nfs41_check_open_stateid(state);
2674 2675 2676
	if (status != NFS_OK)
		status = nfs4_open_expired(sp, state);
	return status;
2677 2678 2679
}
#endif

2680 2681 2682 2683 2684
/*
 * 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
 */
2685 2686
static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
				struct iattr *sattr, struct nfs4_label **label)
2687
{
2688 2689 2690
	const u32 *attrset = opendata->o_res.attrset;

	if ((attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
2691 2692 2693
	    !(sattr->ia_valid & ATTR_ATIME_SET))
		sattr->ia_valid |= ATTR_ATIME;

2694
	if ((attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
2695 2696
	    !(sattr->ia_valid & ATTR_MTIME_SET))
		sattr->ia_valid |= ATTR_MTIME;
2697 2698 2699 2700 2701 2702 2703

	/* Except MODE, it seems harmless of setting twice. */
	if ((attrset[1] & FATTR4_WORD1_MODE))
		sattr->ia_valid &= ~ATTR_MODE;

	if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
		*label = NULL;
2704 2705
}

2706 2707 2708
static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
		fmode_t fmode,
		int flags,
2709
		struct nfs_open_context *ctx)
2710 2711 2712
{
	struct nfs4_state_owner *sp = opendata->owner;
	struct nfs_server *server = sp->so_server;
2713
	struct dentry *dentry;
2714 2715 2716 2717 2718 2719 2720
	struct nfs4_state *state;
	unsigned int seq;
	int ret;

	seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);

	ret = _nfs4_proc_open(opendata);
2721
	if (ret != 0)
2722 2723 2724 2725 2726 2727 2728 2729
		goto out;

	state = nfs4_opendata_to_nfs4_state(opendata);
	ret = PTR_ERR(state);
	if (IS_ERR(state))
		goto out;
	if (server->caps & NFS_CAP_POSIX_LOCK)
		set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
2730 2731
	if (opendata->o_res.rflags & NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK)
		set_bit(NFS_STATE_MAY_NOTIFY_LOCK, &state->flags);
2732

2733
	dentry = opendata->dentry;
2734
	if (d_really_is_negative(dentry)) {
2735
		struct dentry *alias;
2736
		d_drop(dentry);
2737 2738 2739 2740 2741
		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) {
2742
			dput(ctx->dentry);
2743
			ctx->dentry = dentry = alias;
2744 2745
		}
		nfs_set_verifier(dentry,
2746
				nfs_save_change_attribute(d_inode(opendata->dir)));
2747 2748
	}

2749 2750 2751 2752
	ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags);
	if (ret != 0)
		goto out;

2753
	ctx->state = state;
2754
	if (d_inode(dentry) == state->inode) {
2755 2756 2757 2758
		nfs_inode_attach_open_context(ctx);
		if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
			nfs4_schedule_stateid_recovery(server, state);
	}
2759 2760 2761 2762
out:
	return ret;
}

L
Linus Torvalds 已提交
2763
/*
2764
 * Returns a referenced nfs4_state
L
Linus Torvalds 已提交
2765
 */
2766
static int _nfs4_do_open(struct inode *dir,
2767
			struct nfs_open_context *ctx,
2768 2769
			int flags,
			struct iattr *sattr,
2770 2771
			struct nfs4_label *label,
			int *opened)
L
Linus Torvalds 已提交
2772 2773 2774 2775
{
	struct nfs4_state_owner  *sp;
	struct nfs4_state     *state = NULL;
	struct nfs_server       *server = NFS_SERVER(dir);
2776
	struct nfs4_opendata *opendata;
2777 2778 2779 2780
	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);
2781
	enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL;
2782
	struct nfs4_label *olabel = NULL;
2783
	int status;
L
Linus Torvalds 已提交
2784 2785 2786

	/* Protect against reboot recovery conflicts */
	status = -ENOMEM;
2787 2788
	sp = nfs4_get_state_owner(server, cred, GFP_KERNEL);
	if (sp == NULL) {
L
Linus Torvalds 已提交
2789 2790 2791
		dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
		goto out_err;
	}
2792 2793
	status = nfs4_recover_expired_lease(server);
	if (status != 0)
2794
		goto err_put_state_owner;
2795 2796
	if (d_really_is_positive(dentry))
		nfs4_return_incompatible_delegation(d_inode(dentry), fmode);
2797
	status = -ENOMEM;
2798
	if (d_really_is_positive(dentry))
2799
		claim = NFS4_OPEN_CLAIM_FH;
2800
	opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr,
2801
			label, claim, GFP_KERNEL);
2802
	if (opendata == NULL)
T
Trond Myklebust 已提交
2803
		goto err_put_state_owner;
L
Linus Torvalds 已提交
2804

2805 2806 2807 2808 2809 2810 2811 2812
	if (label) {
		olabel = nfs4_label_alloc(server, GFP_KERNEL);
		if (IS_ERR(olabel)) {
			status = PTR_ERR(olabel);
			goto err_opendata_put;
		}
	}

2813 2814 2815 2816 2817 2818
	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;
		}
2819
		opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
2820
	}
2821 2822
	if (d_really_is_positive(dentry))
		opendata->state = nfs4_get_open_state(d_inode(dentry), sp);
2823

2824
	status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx);
2825
	if (status != 0)
2826
		goto err_free_label;
2827
	state = ctx->state;
2828

2829
	if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) &&
2830
	    (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
2831
		nfs4_exclusive_attrset(opendata, sattr, &label);
2832 2833 2834 2835 2836 2837 2838 2839
		/*
		 * 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,
2840
					ctx, label, olabel);
2841 2842 2843 2844 2845
			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);
			}
2846
		}
2847
	}
2848
	if (opened && opendata->file_created)
2849
		*opened |= FILE_CREATED;
2850

2851
	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) {
2852
		*ctx_th = opendata->f_attr.mdsthreshold;
2853 2854
		opendata->f_attr.mdsthreshold = NULL;
	}
2855

2856 2857
	nfs4_label_free(olabel);

2858
	nfs4_opendata_put(opendata);
L
Linus Torvalds 已提交
2859 2860
	nfs4_put_state_owner(sp);
	return 0;
2861 2862
err_free_label:
	nfs4_label_free(olabel);
2863 2864
err_opendata_put:
	nfs4_opendata_put(opendata);
2865 2866
err_put_state_owner:
	nfs4_put_state_owner(sp);
L
Linus Torvalds 已提交
2867 2868 2869 2870 2871
out_err:
	return status;
}


2872
static struct nfs4_state *nfs4_do_open(struct inode *dir,
2873
					struct nfs_open_context *ctx,
2874 2875
					int flags,
					struct iattr *sattr,
2876 2877
					struct nfs4_label *label,
					int *opened)
L
Linus Torvalds 已提交
2878
{
2879
	struct nfs_server *server = NFS_SERVER(dir);
L
Linus Torvalds 已提交
2880 2881 2882 2883 2884
	struct nfs4_exception exception = { };
	struct nfs4_state *res;
	int status;

	do {
2885
		status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened);
2886
		res = ctx->state;
2887
		trace_nfs4_open_file(ctx, flags, status);
L
Linus Torvalds 已提交
2888 2889 2890 2891 2892 2893 2894 2895
		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
2896
		 * doing an OPEN, we assume that nfs_increment_open_seqid() will
L
Linus Torvalds 已提交
2897 2898 2899 2900 2901
		 * 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) {
2902
			pr_warn_ratelimited("NFS: v4 server %s "
2903 2904
					" returned a bad sequence-id error!\n",
					NFS_SERVER(dir)->nfs_client->cl_hostname);
L
Linus Torvalds 已提交
2905 2906 2907
			exception.retry = 1;
			continue;
		}
2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
		/*
		 * 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;
		}
2918 2919 2920 2921 2922
		if (status == -EAGAIN) {
			/* We must have found a delegation */
			exception.retry = 1;
			continue;
		}
2923 2924 2925
		if (nfs4_clear_cap_atomic_open_v1(server, status, &exception))
			continue;
		res = ERR_PTR(nfs4_handle_exception(server,
L
Linus Torvalds 已提交
2926 2927 2928 2929 2930
					status, &exception));
	} while (exception.retry);
	return res;
}

2931 2932 2933 2934
static int _nfs4_do_setattr(struct inode *inode,
			    struct nfs_setattrargs *arg,
			    struct nfs_setattrres *res,
			    struct rpc_cred *cred,
2935
			    struct nfs_open_context *ctx)
L
Linus Torvalds 已提交
2936
{
2937
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
2938
        struct rpc_message msg = {
2939
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
2940 2941
		.rpc_argp	= arg,
		.rpc_resp	= res,
2942
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
2943
        };
2944
	struct rpc_cred *delegation_cred = NULL;
2945
	unsigned long timestamp = jiffies;
2946 2947
	fmode_t fmode;
	bool truncate;
2948
	int status;
L
Linus Torvalds 已提交
2949

2950
	nfs_fattr_init(res->fattr);
L
Linus Torvalds 已提交
2951

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

2956
	if (nfs4_copy_delegation_stateid(inode, fmode, &arg->stateid, &delegation_cred)) {
2957
		/* Use that stateid */
2958
	} else if (truncate && ctx != NULL) {
2959
		struct nfs_lock_context *l_ctx;
2960
		if (!nfs4_valid_open_stateid(ctx->state))
2961
			return -EBADF;
2962 2963 2964
		l_ctx = nfs_get_lock_context(ctx);
		if (IS_ERR(l_ctx))
			return PTR_ERR(l_ctx);
2965 2966 2967 2968
		status = nfs4_select_rw_stateid(ctx->state, FMODE_WRITE, l_ctx,
						&arg->stateid, &delegation_cred);
		nfs_put_lock_context(l_ctx);
		if (status == -EIO)
2969
			return -EBADF;
2970
	} else
2971
		nfs4_stateid_copy(&arg->stateid, &zero_stateid);
2972 2973
	if (delegation_cred)
		msg.rpc_cred = delegation_cred;
L
Linus Torvalds 已提交
2974

2975
	status = nfs4_call_sync(server->client, server, &msg, &arg->seq_args, &res->seq_res, 1);
2976 2977

	put_rpccred(delegation_cred);
2978
	if (status == 0 && ctx != NULL)
2979
		renew_lease(server, timestamp);
2980
	trace_nfs4_setattr(inode, &arg->stateid, status);
2981
	return status;
L
Linus Torvalds 已提交
2982 2983
}

2984 2985
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			   struct nfs_fattr *fattr, struct iattr *sattr,
2986
			   struct nfs_open_context *ctx, struct nfs4_label *ilabel,
2987
			   struct nfs4_label *olabel)
L
Linus Torvalds 已提交
2988
{
2989
	struct nfs_server *server = NFS_SERVER(inode);
2990
	struct nfs4_state *state = ctx ? ctx->state : NULL;
2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002
        struct nfs_setattrargs  arg = {
                .fh             = NFS_FH(inode),
                .iap            = sattr,
		.server		= server,
		.bitmask = server->attr_bitmask,
		.label		= ilabel,
        };
        struct nfs_setattrres  res = {
		.fattr		= fattr,
		.label		= olabel,
		.server		= server,
        };
3003 3004
	struct nfs4_exception exception = {
		.state = state,
3005
		.inode = inode,
3006
		.stateid = &arg.stateid,
3007
	};
L
Linus Torvalds 已提交
3008
	int err;
3009 3010 3011 3012 3013

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

L
Linus Torvalds 已提交
3014
	do {
3015
		err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx);
3016 3017
		switch (err) {
		case -NFS4ERR_OPENMODE:
3018 3019 3020 3021 3022 3023 3024
			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);
			}
3025 3026 3027 3028 3029 3030 3031 3032
			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 已提交
3033
	} while (exception.retry);
3034
out:
L
Linus Torvalds 已提交
3035 3036 3037
	return err;
}

3038 3039 3040 3041 3042 3043 3044 3045 3046
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 已提交
3047 3048 3049 3050 3051
struct nfs4_closedata {
	struct inode *inode;
	struct nfs4_state *state;
	struct nfs_closeargs arg;
	struct nfs_closeres res;
3052 3053 3054
	struct {
		struct nfs4_layoutreturn_args arg;
		struct nfs4_layoutreturn_res res;
3055
		struct nfs4_xdr_opaque_data ld_private;
3056 3057 3058
		u32 roc_barrier;
		bool roc;
	} lr;
3059
	struct nfs_fattr fattr;
3060
	unsigned long timestamp;
L
Linus Torvalds 已提交
3061 3062
};

3063
static void nfs4_free_closedata(void *data)
3064
{
3065 3066
	struct nfs4_closedata *calldata = data;
	struct nfs4_state_owner *sp = calldata->state->owner;
3067
	struct super_block *sb = calldata->state->inode->i_sb;
3068

3069
	if (calldata->lr.roc)
3070 3071
		pnfs_roc_release(&calldata->lr.arg, &calldata->lr.res,
				calldata->res.lr_ret);
3072 3073 3074
	nfs4_put_open_state(calldata->state);
	nfs_free_seqid(calldata->arg.seqid);
	nfs4_put_state_owner(sp);
3075
	nfs_sb_deactive(sb);
3076 3077 3078
	kfree(calldata);
}

3079
static void nfs4_close_done(struct rpc_task *task, void *data)
L
Linus Torvalds 已提交
3080
{
3081
	struct nfs4_closedata *calldata = data;
L
Linus Torvalds 已提交
3082 3083
	struct nfs4_state *state = calldata->state;
	struct nfs_server *server = NFS_SERVER(calldata->inode);
3084
	nfs4_stateid *res_stateid = NULL;
L
Linus Torvalds 已提交
3085

3086
	dprintk("%s: begin!\n", __func__);
3087 3088
	if (!nfs4_sequence_done(task, &calldata->res.seq_res))
		return;
3089
	trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status);
3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115

	/* 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;
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_EXPIRED:
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_OLD_STATEID:
		case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
		case -NFS4ERR_WRONG_CRED:
			calldata->arg.lr_args = NULL;
			calldata->res.lr_res = NULL;
			calldata->res.lr_ret = 0;
			rpc_restart_call_prepare(task);
			return;
		}
	}

L
Linus Torvalds 已提交
3116 3117 3118 3119 3120
        /* hmm. we are done with the inode, and in the process of freeing
	 * the state_owner. we keep this around to process errors
	 */
	switch (task->tk_status) {
		case 0:
3121
			res_stateid = &calldata->res.stateid;
3122
			renew_lease(server, calldata->timestamp);
3123
			break;
3124 3125 3126 3127 3128 3129 3130 3131 3132 3133
		case -NFS4ERR_ACCESS:
			if (calldata->arg.bitmask != NULL) {
				calldata->arg.bitmask = NULL;
				calldata->res.fattr = NULL;
				task->tk_status = 0;
				rpc_restart_call_prepare(task);
				goto out_release;

			}
			break;
3134
		case -NFS4ERR_ADMIN_REVOKED:
L
Linus Torvalds 已提交
3135
		case -NFS4ERR_STALE_STATEID:
3136 3137 3138 3139
		case -NFS4ERR_EXPIRED:
			nfs4_free_revoked_stateid(server,
					&calldata->arg.stateid,
					task->tk_msg.rpc_cred);
3140 3141
		case -NFS4ERR_OLD_STATEID:
		case -NFS4ERR_BAD_STATEID:
3142
			if (!nfs4_stateid_match(&calldata->arg.stateid,
3143
						&state->open_stateid)) {
3144 3145 3146
				rpc_restart_call_prepare(task);
				goto out_release;
			}
3147
			if (calldata->arg.fmode == 0)
3148
				break;
L
Linus Torvalds 已提交
3149
		default:
3150
			if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) {
3151
				rpc_restart_call_prepare(task);
3152 3153
				goto out_release;
			}
L
Linus Torvalds 已提交
3154
	}
3155 3156
	nfs_clear_open_stateid(state, &calldata->arg.stateid,
			res_stateid, calldata->arg.fmode);
3157
out_release:
3158
	nfs_release_seqid(calldata->arg.seqid);
3159
	nfs_refresh_inode(calldata->inode, &calldata->fattr);
3160
	dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
L
Linus Torvalds 已提交
3161 3162
}

T
Trond Myklebust 已提交
3163
static void nfs4_close_prepare(struct rpc_task *task, void *data)
L
Linus Torvalds 已提交
3164
{
T
Trond Myklebust 已提交
3165
	struct nfs4_closedata *calldata = data;
3166
	struct nfs4_state *state = calldata->state;
3167
	struct inode *inode = calldata->inode;
3168
	bool is_rdonly, is_wronly, is_rdwr;
3169
	int call_close = 0;
3170

3171
	dprintk("%s: begin!\n", __func__);
3172
	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
3173
		goto out_wait;
3174

3175
	task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
3176
	spin_lock(&state->owner->so_lock);
3177 3178 3179
	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);
3180
	nfs4_stateid_copy(&calldata->arg.stateid, &state->open_stateid);
3181
	/* Calculate the change in open mode */
3182
	calldata->arg.fmode = 0;
3183
	if (state->n_rdwr == 0) {
3184 3185 3186 3187 3188 3189 3190 3191
		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;
3192 3193
		if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
			call_close |= is_rdwr;
3194 3195 3196
	} else if (is_rdwr)
		calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;

3197 3198
	if (!nfs4_valid_open_stateid(state) ||
	    test_bit(NFS_OPEN_STATE, &state->flags) == 0)
3199
		call_close = 0;
3200
	spin_unlock(&state->owner->so_lock);
3201 3202

	if (!call_close) {
3203
		/* Note: exit _without_ calling nfs4_close_done */
3204
		goto out_no_action;
3205
	}
3206

3207
	if (!calldata->lr.roc && nfs4_wait_on_layoutreturn(inode, task)) {
3208 3209 3210 3211
		nfs_release_seqid(calldata->arg.seqid);
		goto out_wait;
	}

3212
	if (calldata->arg.fmode == 0)
3213
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
3214

3215
	if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) {
3216 3217 3218 3219 3220 3221
		/* 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;
	}
3222

3223 3224 3225
	calldata->arg.share_access =
		nfs4_map_atomic_open_share(NFS_SERVER(inode),
				calldata->arg.fmode, 0);
3226

3227 3228 3229 3230
	if (calldata->res.fattr == NULL)
		calldata->arg.bitmask = NULL;
	else if (calldata->arg.bitmask == NULL)
		calldata->res.fattr = NULL;
3231
	calldata->timestamp = jiffies;
3232
	if (nfs4_setup_sequence(NFS_SERVER(inode),
3233 3234
				&calldata->arg.seq_args,
				&calldata->res.seq_res,
3235 3236
				task) != 0)
		nfs_release_seqid(calldata->arg.seqid);
3237
	dprintk("%s: done!\n", __func__);
3238 3239 3240 3241 3242
	return;
out_no_action:
	task->tk_action = NULL;
out_wait:
	nfs4_sequence_done(task, &calldata->res.seq_res);
L
Linus Torvalds 已提交
3243 3244
}

3245
static const struct rpc_call_ops nfs4_close_ops = {
T
Trond Myklebust 已提交
3246
	.rpc_call_prepare = nfs4_close_prepare,
3247 3248 3249 3250
	.rpc_call_done = nfs4_close_done,
	.rpc_release = nfs4_free_closedata,
};

L
Linus Torvalds 已提交
3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261
/* 
 * 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!
 */
3262
int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
L
Linus Torvalds 已提交
3263
{
3264
	struct nfs_server *server = NFS_SERVER(state->inode);
3265
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
L
Linus Torvalds 已提交
3266
	struct nfs4_closedata *calldata;
3267 3268
	struct nfs4_state_owner *sp = state->owner;
	struct rpc_task *task;
3269 3270 3271 3272
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
		.rpc_cred = state->owner->so_cred,
	};
T
Trond Myklebust 已提交
3273 3274
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
3275
		.rpc_message = &msg,
T
Trond Myklebust 已提交
3276
		.callback_ops = &nfs4_close_ops,
3277
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
3278 3279
		.flags = RPC_TASK_ASYNC,
	};
3280
	int status = -ENOMEM;
L
Linus Torvalds 已提交
3281

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

3285
	calldata = kzalloc(sizeof(*calldata), gfp_mask);
L
Linus Torvalds 已提交
3286
	if (calldata == NULL)
3287
		goto out;
3288
	nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1);
3289
	calldata->inode = state->inode;
L
Linus Torvalds 已提交
3290
	calldata->state = state;
3291
	calldata->arg.fh = NFS_FH(state->inode);
L
Linus Torvalds 已提交
3292
	/* Serialization for the sequence id */
3293 3294
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask);
3295
	if (IS_ERR(calldata->arg.seqid))
3296
		goto out_free_calldata;
3297
	nfs_fattr_init(&calldata->fattr);
3298
	calldata->arg.fmode = 0;
3299
	calldata->lr.arg.ld_private = &calldata->lr.ld_private;
3300
	calldata->res.fattr = &calldata->fattr;
3301
	calldata->res.seqid = calldata->arg.seqid;
3302
	calldata->res.server = server;
3303
	calldata->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
3304 3305 3306 3307 3308 3309
	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;
	}
3310
	nfs_sb_active(calldata->inode->i_sb);
3311

3312 3313
	msg.rpc_argp = &calldata->arg;
	msg.rpc_resp = &calldata->res;
T
Trond Myklebust 已提交
3314 3315
	task_setup_data.callback_data = calldata;
	task = rpc_run_task(&task_setup_data);
3316 3317
	if (IS_ERR(task))
		return PTR_ERR(task);
3318 3319 3320
	status = 0;
	if (wait)
		status = rpc_wait_for_completion_task(task);
3321
	rpc_put_task(task);
3322
	return status;
3323 3324 3325
out_free_calldata:
	kfree(calldata);
out:
3326 3327
	nfs4_put_open_state(state);
	nfs4_put_state_owner(sp);
3328
	return status;
L
Linus Torvalds 已提交
3329 3330
}

3331
static struct inode *
3332 3333
nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
		int open_flags, struct iattr *attr, int *opened)
L
Linus Torvalds 已提交
3334 3335
{
	struct nfs4_state *state;
3336 3337 3338
	struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;

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

T
Trond Myklebust 已提交
3340
	/* Protect against concurrent sillydeletes */
3341
	state = nfs4_do_open(dir, ctx, open_flags, attr, label, opened);
3342 3343 3344

	nfs4_label_release_security(label);

3345 3346
	if (IS_ERR(state))
		return ERR_CAST(state);
3347
	return state->inode;
L
Linus Torvalds 已提交
3348 3349
}

3350
static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
T
Trond Myklebust 已提交
3351 3352 3353 3354
{
	if (ctx->state == NULL)
		return;
	if (is_sync)
3355
		nfs4_close_sync(ctx->state, ctx->mode);
T
Trond Myklebust 已提交
3356
	else
3357
		nfs4_close_state(ctx->state, ctx->mode);
T
Trond Myklebust 已提交
3358
}
L
Linus Torvalds 已提交
3359

3360 3361
#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL)
#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL)
3362
#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_MODE_UMASK - 1UL)
3363

L
Linus Torvalds 已提交
3364 3365
static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
3366
	u32 bitmask[3] = {}, minorversion = server->nfs_client->cl_minorversion;
B
Benny Halevy 已提交
3367 3368
	struct nfs4_server_caps_arg args = {
		.fhandle = fhandle,
3369
		.bitmask = bitmask,
B
Benny Halevy 已提交
3370
	};
L
Linus Torvalds 已提交
3371 3372 3373
	struct nfs4_server_caps_res res = {};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
B
Benny Halevy 已提交
3374
		.rpc_argp = &args,
L
Linus Torvalds 已提交
3375 3376 3377 3378
		.rpc_resp = &res,
	};
	int status;

3379 3380 3381 3382 3383 3384 3385 3386
	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;

3387
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3388
	if (status == 0) {
3389
		/* Sanity check the server answers */
3390
		switch (minorversion) {
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400
		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 已提交
3401
		memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
3402 3403 3404 3405
		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|
3406 3407
				NFS_CAP_CTIME|NFS_CAP_MTIME|
				NFS_CAP_SECURITY_LABEL);
3408 3409
		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL &&
				res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
L
Linus Torvalds 已提交
3410 3411 3412 3413 3414
			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;
3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430
		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;
3431 3432 3433 3434 3435 3436
#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));
3437
		server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
3438

3439 3440 3441
		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;
3442
		server->cache_consistency_bitmask[2] = 0;
3443 3444
		memcpy(server->exclcreat_bitmask, res.exclcreat_bitmask,
			sizeof(server->exclcreat_bitmask));
L
Linus Torvalds 已提交
3445
		server->acl_bitmask = res.acl_bitmask;
3446
		server->fh_expire_type = res.fh_expire_type;
L
Linus Torvalds 已提交
3447
	}
A
Andy Adamson 已提交
3448

L
Linus Torvalds 已提交
3449 3450 3451
	return status;
}

3452
int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
L
Linus Torvalds 已提交
3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466
{
	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)
{
3467
	u32 bitmask[3];
L
Linus Torvalds 已提交
3468
	struct nfs4_lookup_root_arg args = {
3469
		.bitmask = bitmask,
L
Linus Torvalds 已提交
3470 3471 3472
	};
	struct nfs4_lookup_res res = {
		.server = server,
3473
		.fattr = info->fattr,
L
Linus Torvalds 已提交
3474 3475 3476 3477 3478 3479 3480
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
3481

3482 3483 3484 3485 3486 3487 3488
	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;

3489
	nfs_fattr_init(info->fattr);
3490
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3491 3492 3493 3494 3495 3496 3497 3498
}

static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_fsinfo *info)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3499
		err = _nfs4_lookup_root(server, fhandle, info);
3500
		trace_nfs4_lookup_root(server, fhandle, info->fattr, err);
3501 3502 3503
		switch (err) {
		case 0:
		case -NFS4ERR_WRONGSEC:
3504
			goto out;
3505 3506 3507
		default:
			err = nfs4_handle_exception(server, err, &exception);
		}
L
Linus Torvalds 已提交
3508
	} while (exception.retry);
3509
out:
L
Linus Torvalds 已提交
3510 3511 3512
	return err;
}

3513 3514 3515
static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fsinfo *info, rpc_authflavor_t flavor)
{
3516 3517 3518
	struct rpc_auth_create_args auth_args = {
		.pseudoflavor = flavor,
	};
3519 3520 3521
	struct rpc_auth *auth;
	int ret;

3522
	auth = rpcauth_create(&auth_args, server->client);
3523
	if (IS_ERR(auth)) {
3524
		ret = -EACCES;
3525 3526 3527 3528 3529 3530 3531
		goto out;
	}
	ret = nfs4_lookup_root(server, fhandle, info);
out:
	return ret;
}

3532 3533 3534 3535 3536 3537 3538 3539 3540
/*
 * 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.
 */
3541
static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
3542
			      struct nfs_fsinfo *info)
L
Linus Torvalds 已提交
3543
{
3544 3545 3546 3547 3548
	/* Per 3530bis 15.33.5 */
	static const rpc_authflavor_t flav_array[] = {
		RPC_AUTH_GSS_KRB5P,
		RPC_AUTH_GSS_KRB5I,
		RPC_AUTH_GSS_KRB5,
3549
		RPC_AUTH_UNIX,			/* courtesy */
3550 3551 3552 3553
		RPC_AUTH_NULL,
	};
	int status = -EPERM;
	size_t i;
C
Chuck Lever 已提交
3554

3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572
	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;
		}
3573
	}
3574

3575 3576 3577 3578 3579 3580 3581 3582 3583
	/*
	 * -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;
3584 3585 3586
	return status;
}

C
Chuck Lever 已提交
3587 3588 3589 3590 3591
/**
 * 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
3592
 * @auth_probe: probe the auth flavours
C
Chuck Lever 已提交
3593 3594
 *
 * Returns zero on success, or a negative errno.
3595
 */
3596
int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
3597 3598
			 struct nfs_fsinfo *info,
			 bool auth_probe)
3599
{
3600
	int status = 0;
C
Chuck Lever 已提交
3601

3602
	if (!auth_probe)
3603
		status = nfs4_lookup_root(server, fhandle, info);
3604 3605

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

L
Linus Torvalds 已提交
3609 3610 3611 3612
	if (status == 0)
		status = nfs4_server_capabilities(server, fhandle);
	if (status == 0)
		status = nfs4_do_fsinfo(server, fhandle, info);
C
Chuck Lever 已提交
3613

3614
	return nfs4_map_errors(status);
L
Linus Torvalds 已提交
3615 3616
}

3617 3618 3619 3620 3621
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;
3622
	struct nfs4_label *label = NULL;
3623 3624 3625 3626 3627 3628 3629

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

3630 3631 3632 3633
	label = nfs4_label_alloc(server, GFP_KERNEL);
	if (IS_ERR(label))
		return PTR_ERR(label);

3634
	error = nfs4_proc_getattr(server, mntfh, fattr, label);
3635 3636
	if (error < 0) {
		dprintk("nfs4_get_root: getattr error = %d\n", -error);
3637
		goto err_free_label;
3638 3639 3640 3641 3642 3643
	}

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

3644 3645 3646
err_free_label:
	nfs4_label_free(label);

3647 3648 3649
	return error;
}

M
Manoj Naik 已提交
3650 3651 3652 3653 3654
/*
 * 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
 */
3655 3656 3657
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 已提交
3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669
{
	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;

3670
	status = nfs4_proc_fs_locations(client, dir, name, locations, page);
M
Manoj Naik 已提交
3671 3672
	if (status != 0)
		goto out;
3673 3674 3675 3676 3677 3678

	/*
	 * 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 已提交
3679
	if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
3680 3681
		dprintk("%s: server did not return a different fsid for"
			" a referral at %s\n", __func__, name->name);
3682
		status = -NFS4ERR_MOVED;
M
Manoj Naik 已提交
3683 3684
		goto out;
	}
3685 3686
	/* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
	nfs_fixup_referral_attributes(&locations->fattr);
M
Manoj Naik 已提交
3687

3688
	/* replace the lookup nfs_fattr with the locations nfs_fattr */
M
Manoj Naik 已提交
3689 3690 3691 3692 3693
	memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
	memset(fhandle, 0, sizeof(struct nfs_fh));
out:
	if (page)
		__free_page(page);
3694
	kfree(locations);
M
Manoj Naik 已提交
3695 3696 3697
	return status;
}

3698 3699
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3700 3701 3702 3703 3704 3705 3706
{
	struct nfs4_getattr_arg args = {
		.fh = fhandle,
		.bitmask = server->attr_bitmask,
	};
	struct nfs4_getattr_res res = {
		.fattr = fattr,
3707
		.label = label,
L
Linus Torvalds 已提交
3708 3709 3710 3711 3712 3713 3714
		.server = server,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
3715 3716 3717

	args.bitmask = nfs4_bitmask(server, label);

3718
	nfs_fattr_init(fattr);
3719
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3720 3721
}

3722 3723
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3724 3725 3726 3727
{
	struct nfs4_exception exception = { };
	int err;
	do {
3728 3729 3730
		err = _nfs4_proc_getattr(server, fhandle, fattr, label);
		trace_nfs4_getattr(server, fhandle, fattr, err);
		err = nfs4_handle_exception(server, err,
L
Linus Torvalds 已提交
3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756
				&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)
{
3757
	struct inode *inode = d_inode(dentry);
3758
	struct rpc_cred *cred = NULL;
3759
	struct nfs_open_context *ctx = NULL;
3760
	struct nfs4_label *label = NULL;
L
Linus Torvalds 已提交
3761 3762
	int status;

3763 3764 3765
	if (pnfs_ld_layoutret_on_setattr(inode) &&
	    sattr->ia_valid & ATTR_SIZE &&
	    sattr->ia_size < i_size_read(inode))
3766
		pnfs_commit_and_return_layout(inode);
B
Benny Halevy 已提交
3767

3768
	nfs_fattr_init(fattr);
L
Linus Torvalds 已提交
3769
	
3770 3771
	/* Deal with open(O_TRUNC) */
	if (sattr->ia_valid & ATTR_OPEN)
3772
		sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME);
3773 3774

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

3778
	/* Search for an existing open(O_WRITE) file */
3779 3780 3781
	if (sattr->ia_valid & ATTR_FILE) {

		ctx = nfs_file_open_context(sattr->ia_file);
3782
		if (ctx)
N
Neil Brown 已提交
3783
			cred = ctx->cred;
3784
	}
3785

3786 3787 3788 3789
	label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
	if (IS_ERR(label))
		return PTR_ERR(label);

3790
	status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label);
3791
	if (status == 0) {
3792
		nfs_setattr_update_inode(inode, sattr, fattr);
3793 3794
		nfs_setsecurity(inode, fattr, label);
	}
3795
	nfs4_label_free(label);
L
Linus Torvalds 已提交
3796 3797 3798
	return status;
}

3799 3800
static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
		const struct qstr *name, struct nfs_fh *fhandle,
3801
		struct nfs_fattr *fattr, struct nfs4_label *label)
D
David Howells 已提交
3802
{
3803
	struct nfs_server *server = NFS_SERVER(dir);
D
David Howells 已提交
3804 3805 3806
	int		       status;
	struct nfs4_lookup_arg args = {
		.bitmask = server->attr_bitmask,
3807
		.dir_fh = NFS_FH(dir),
D
David Howells 已提交
3808 3809 3810 3811 3812
		.name = name,
	};
	struct nfs4_lookup_res res = {
		.server = server,
		.fattr = fattr,
3813
		.label = label,
D
David Howells 已提交
3814 3815 3816 3817 3818 3819 3820 3821
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};

3822 3823
	args.bitmask = nfs4_bitmask(server, label);

D
David Howells 已提交
3824 3825
	nfs_fattr_init(fattr);

L
Linus Torvalds 已提交
3826
	dprintk("NFS call  lookup %s\n", name->name);
3827
	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3828 3829 3830 3831
	dprintk("NFS reply lookup: %d\n", status);
	return status;
}

3832
static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
3833 3834
{
	fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
3835
		NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT;
3836 3837 3838 3839
	fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
	fattr->nlink = 2;
}

3840
static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
A
Al Viro 已提交
3841
				   const struct qstr *name, struct nfs_fh *fhandle,
3842
				   struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3843 3844
{
	struct nfs4_exception exception = { };
3845
	struct rpc_clnt *client = *clnt;
L
Linus Torvalds 已提交
3846 3847
	int err;
	do {
3848
		err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label);
3849
		trace_nfs4_lookup(dir, name, err);
3850
		switch (err) {
3851
		case -NFS4ERR_BADNAME:
3852 3853
			err = -ENOENT;
			goto out;
3854
		case -NFS4ERR_MOVED:
3855
			err = nfs4_get_referral(client, dir, name, fattr, fhandle);
3856 3857
			if (err == -NFS4ERR_MOVED)
				err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
3858
			goto out;
3859
		case -NFS4ERR_WRONGSEC:
3860 3861 3862
			err = -EPERM;
			if (client != *clnt)
				goto out;
3863
			client = nfs4_negotiate_security(client, dir, name);
3864 3865 3866 3867 3868 3869 3870
			if (IS_ERR(client))
				return PTR_ERR(client);

			exception.retry = 1;
			break;
		default:
			err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
3871
		}
L
Linus Torvalds 已提交
3872
	} while (exception.retry);
3873 3874 3875 3876 3877 3878 3879

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

L
Linus Torvalds 已提交
3880 3881 3882
	return err;
}

A
Al Viro 已提交
3883
static int nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
3884 3885
			    struct nfs_fh *fhandle, struct nfs_fattr *fattr,
			    struct nfs4_label *label)
3886 3887 3888 3889
{
	int status;
	struct rpc_clnt *client = NFS_CLIENT(dir);

3890
	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label);
3891 3892 3893 3894 3895 3896 3897
	if (client != NFS_CLIENT(dir)) {
		rpc_shutdown_client(client);
		nfs_fixup_secinfo_attributes(fattr);
	}
	return status;
}

3898
struct rpc_clnt *
A
Al Viro 已提交
3899
nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
3900 3901
			    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
3902
	struct rpc_clnt *client = NFS_CLIENT(dir);
3903 3904
	int status;

3905
	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL);
3906
	if (status < 0)
3907
		return ERR_PTR(status);
3908
	return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
3909 3910
}

L
Linus Torvalds 已提交
3911 3912
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
3913
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
3914 3915
	struct nfs4_accessargs args = {
		.fh = NFS_FH(inode),
3916
		.bitmask = server->cache_consistency_bitmask,
3917 3918 3919
	};
	struct nfs4_accessres res = {
		.server = server,
L
Linus Torvalds 已提交
3920 3921 3922 3923 3924 3925 3926 3927
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
		.rpc_argp = &args,
		.rpc_resp = &res,
		.rpc_cred = entry->cred,
	};
	int mode = entry->mask;
3928
	int status = 0;
L
Linus Torvalds 已提交
3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945

	/*
	 * Determine which access bits we want to ask for...
	 */
	if (mode & MAY_READ)
		args.access |= NFS4_ACCESS_READ;
	if (S_ISDIR(inode->i_mode)) {
		if (mode & MAY_WRITE)
			args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE;
		if (mode & MAY_EXEC)
			args.access |= NFS4_ACCESS_LOOKUP;
	} else {
		if (mode & MAY_WRITE)
			args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND;
		if (mode & MAY_EXEC)
			args.access |= NFS4_ACCESS_EXECUTE;
	}
3946 3947 3948 3949 3950

	res.fattr = nfs_alloc_fattr();
	if (res.fattr == NULL)
		return -ENOMEM;

3951
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3952
	if (!status) {
3953
		nfs_access_set_mask(entry, res.access);
3954
		nfs_refresh_inode(inode, res.fattr);
L
Linus Torvalds 已提交
3955
	}
3956
	nfs_free_fattr(res.fattr);
L
Linus Torvalds 已提交
3957 3958 3959 3960 3961 3962 3963 3964
	return status;
}

static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3965 3966 3967
		err = _nfs4_proc_access(inode, entry);
		trace_nfs4_access(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
L
Linus Torvalds 已提交
3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989
				&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
3990
 * we get the post-operation mtime and size.
L
Linus Torvalds 已提交
3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003
 *
 * 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 已提交
4004
	struct nfs4_readlink_res res;
L
Linus Torvalds 已提交
4005 4006 4007
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4008
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4009 4010
	};

4011
	return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4012 4013 4014 4015 4016 4017 4018 4019
}

static int nfs4_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs4_exception exception = { };
	int err;
	do {
4020 4021 4022
		err = _nfs4_proc_readlink(inode, page, pgbase, pglen);
		trace_nfs4_readlink(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
L
Linus Torvalds 已提交
4023 4024 4025 4026 4027 4028
				&exception);
	} while (exception.retry);
	return err;
}

/*
4029
 * This is just for mknod.  open(O_CREAT) will always do ->open_context().
L
Linus Torvalds 已提交
4030 4031 4032
 */
static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
4033
		 int flags)
L
Linus Torvalds 已提交
4034
{
4035
	struct nfs_server *server = NFS_SERVER(dir);
4036
	struct nfs4_label l, *ilabel = NULL;
4037
	struct nfs_open_context *ctx;
L
Linus Torvalds 已提交
4038 4039 4040
	struct nfs4_state *state;
	int status = 0;

N
NeilBrown 已提交
4041
	ctx = alloc_nfs_open_context(dentry, FMODE_READ, NULL);
4042 4043 4044
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

4045 4046
	ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);

4047 4048
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
4049
	state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL);
L
Linus Torvalds 已提交
4050 4051
	if (IS_ERR(state)) {
		status = PTR_ERR(state);
4052
		goto out;
L
Linus Torvalds 已提交
4053 4054
	}
out:
4055
	nfs4_label_release_security(ilabel);
4056
	put_nfs_open_context(ctx);
L
Linus Torvalds 已提交
4057 4058 4059
	return status;
}

A
Al Viro 已提交
4060
static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4061
{
4062
	struct nfs_server *server = NFS_SERVER(dir);
4063
	struct nfs_removeargs args = {
L
Linus Torvalds 已提交
4064
		.fh = NFS_FH(dir),
4065
		.name = *name,
4066
	};
4067
	struct nfs_removeres res = {
4068
		.server = server,
L
Linus Torvalds 已提交
4069 4070
	};
	struct rpc_message msg = {
4071 4072 4073
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
		.rpc_argp = &args,
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4074
	};
4075
	int status;
L
Linus Torvalds 已提交
4076

4077
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
4078
	if (status == 0)
4079
		update_changeattr(dir, &res.cinfo);
L
Linus Torvalds 已提交
4080 4081 4082
	return status;
}

A
Al Viro 已提交
4083
static int nfs4_proc_remove(struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4084 4085 4086 4087
{
	struct nfs4_exception exception = { };
	int err;
	do {
4088 4089 4090
		err = _nfs4_proc_remove(dir, name);
		trace_nfs4_remove(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
L
Linus Torvalds 已提交
4091 4092 4093 4094 4095
				&exception);
	} while (exception.retry);
	return err;
}

4096
static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
L
Linus Torvalds 已提交
4097
{
4098 4099 4100
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs_removeargs *args = msg->rpc_argp;
	struct nfs_removeres *res = msg->rpc_resp;
L
Linus Torvalds 已提交
4101

4102
	res->server = server;
L
Linus Torvalds 已提交
4103
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
4104
	nfs4_init_sequence(&args->seq_args, &res->seq_res, 1);
4105 4106

	nfs_fattr_init(res->dir_attr);
L
Linus Torvalds 已提交
4107 4108
}

4109 4110
static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
{
A
Al Viro 已提交
4111
	nfs4_setup_sequence(NFS_SB(data->dentry->d_sb),
4112 4113 4114
			&data->args.seq_args,
			&data->res.seq_res,
			task);
L
Linus Torvalds 已提交
4115 4116
}

4117
static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
L
Linus Torvalds 已提交
4118
{
4119 4120
	struct nfs_unlinkdata *data = task->tk_calldata;
	struct nfs_removeres *res = &data->res;
4121

4122 4123
	if (!nfs4_sequence_done(task, &res->seq_res))
		return 0;
4124 4125
	if (nfs4_async_handle_error(task, res->server, NULL,
				    &data->timeout) == -EAGAIN)
4126 4127 4128
		return 0;
	update_changeattr(dir, &res->cinfo);
	return 1;
L
Linus Torvalds 已提交
4129 4130
}

4131 4132 4133 4134 4135 4136 4137 4138
static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
{
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs_renameargs *arg = msg->rpc_argp;
	struct nfs_renameres *res = msg->rpc_resp;

	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
	res->server = server;
4139
	nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1);
4140 4141
}

4142 4143
static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
{
4144 4145 4146 4147
	nfs4_setup_sequence(NFS_SERVER(data->old_dir),
			&data->args.seq_args,
			&data->res.seq_res,
			task);
4148 4149 4150 4151 4152
}

static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
				 struct inode *new_dir)
{
4153 4154
	struct nfs_renamedata *data = task->tk_calldata;
	struct nfs_renameres *res = &data->res;
4155 4156 4157

	if (!nfs4_sequence_done(task, &res->seq_res))
		return 0;
4158
	if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN)
4159 4160 4161 4162 4163 4164 4165
		return 0;

	update_changeattr(old_dir, &res->old_cinfo);
	update_changeattr(new_dir, &res->new_cinfo);
	return 1;
}

A
Al Viro 已提交
4166
static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4167
{
4168
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
4169 4170 4171 4172
	struct nfs4_link_arg arg = {
		.fh     = NFS_FH(inode),
		.dir_fh = NFS_FH(dir),
		.name   = name,
4173 4174 4175 4176
		.bitmask = server->attr_bitmask,
	};
	struct nfs4_link_res res = {
		.server = server,
4177
		.label = NULL,
L
Linus Torvalds 已提交
4178 4179 4180 4181
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
		.rpc_argp = &arg,
4182
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4183
	};
4184 4185 4186
	int status = -ENOMEM;

	res.fattr = nfs_alloc_fattr();
4187
	if (res.fattr == NULL)
4188
		goto out;
L
Linus Torvalds 已提交
4189

4190 4191 4192 4193 4194
	res.label = nfs4_label_alloc(server, GFP_KERNEL);
	if (IS_ERR(res.label)) {
		status = PTR_ERR(res.label);
		goto out;
	}
4195
	arg.bitmask = nfs4_bitmask(server, res.label);
4196

4197
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
4198 4199
	if (!status) {
		update_changeattr(dir, &res.cinfo);
4200 4201 4202
		status = nfs_post_op_update_inode(inode, res.fattr);
		if (!status)
			nfs_setsecurity(inode, res.fattr, res.label);
4203
	}
4204 4205 4206 4207


	nfs4_label_free(res.label);

4208 4209
out:
	nfs_free_fattr(res.fattr);
L
Linus Torvalds 已提交
4210 4211 4212
	return status;
}

A
Al Viro 已提交
4213
static int nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
L
Linus Torvalds 已提交
4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224
{
	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;
}

4225 4226 4227 4228 4229 4230
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;
4231
	struct nfs4_label *label;
4232 4233 4234
};

static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
A
Al Viro 已提交
4235
		const struct qstr *name, struct iattr *sattr, u32 ftype)
4236 4237 4238 4239 4240 4241 4242
{
	struct nfs4_createdata *data;

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

4243 4244 4245 4246
		data->label = nfs4_label_alloc(server, GFP_KERNEL);
		if (IS_ERR(data->label))
			goto out_free;

4247 4248 4249 4250 4251 4252 4253 4254
		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;
4255
		data->arg.bitmask = nfs4_bitmask(server, data->label);
4256
		data->arg.umask = current_umask();
4257 4258 4259
		data->res.server = server;
		data->res.fh = &data->fh;
		data->res.fattr = &data->fattr;
4260
		data->res.label = data->label;
4261 4262 4263
		nfs_fattr_init(data->res.fattr);
	}
	return data;
4264 4265 4266
out_free:
	kfree(data);
	return NULL;
4267 4268 4269 4270
}

static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
{
4271
	int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
4272
				    &data->arg.seq_args, &data->res.seq_res, 1);
4273 4274
	if (status == 0) {
		update_changeattr(dir, &data->res.dir_cinfo);
4275
		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
4276 4277 4278 4279 4280 4281
	}
	return status;
}

static void nfs4_free_createdata(struct nfs4_createdata *data)
{
4282
	nfs4_label_free(data->label);
4283 4284 4285
	kfree(data);
}

4286
static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
4287 4288
		struct page *page, unsigned int len, struct iattr *sattr,
		struct nfs4_label *label)
L
Linus Torvalds 已提交
4289
{
4290 4291
	struct nfs4_createdata *data;
	int status = -ENAMETOOLONG;
L
Linus Torvalds 已提交
4292

4293
	if (len > NFS4_MAXPATHLEN)
4294
		goto out;
4295

4296 4297 4298 4299 4300 4301 4302 4303
	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;
4304
	data->arg.label = label;
L
Linus Torvalds 已提交
4305
	
4306 4307 4308 4309
	status = nfs4_do_create(dir, dentry, data);

	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
4310 4311 4312
	return status;
}

4313
static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
4314
		struct page *page, unsigned int len, struct iattr *sattr)
L
Linus Torvalds 已提交
4315 4316
{
	struct nfs4_exception exception = { };
4317
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
4318
	int err;
4319 4320 4321

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

L
Linus Torvalds 已提交
4322
	do {
4323 4324 4325
		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 已提交
4326 4327
				&exception);
	} while (exception.retry);
4328 4329

	nfs4_label_release_security(label);
L
Linus Torvalds 已提交
4330 4331 4332 4333
	return err;
}

static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
4334
		struct iattr *sattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
4335
{
4336 4337
	struct nfs4_createdata *data;
	int status = -ENOMEM;
L
Linus Torvalds 已提交
4338

4339 4340 4341 4342
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
	if (data == NULL)
		goto out;

4343
	data->arg.label = label;
4344 4345 4346 4347
	status = nfs4_do_create(dir, dentry, data);

	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
4348 4349 4350 4351 4352 4353
	return status;
}

static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr)
{
4354
	struct nfs_server *server = NFS_SERVER(dir);
L
Linus Torvalds 已提交
4355
	struct nfs4_exception exception = { };
4356
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
4357
	int err;
A
Aneesh Kumar K.V 已提交
4358

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

4361 4362
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
L
Linus Torvalds 已提交
4363
	do {
4364 4365 4366
		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 已提交
4367 4368
				&exception);
	} while (exception.retry);
4369 4370
	nfs4_label_release_security(label);

L
Linus Torvalds 已提交
4371 4372 4373 4374
	return err;
}

static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
B
Bryan Schumaker 已提交
4375
		u64 cookie, struct page **pages, unsigned int count, int plus)
L
Linus Torvalds 已提交
4376
{
4377
	struct inode		*dir = d_inode(dentry);
L
Linus Torvalds 已提交
4378 4379
	struct nfs4_readdir_arg args = {
		.fh = NFS_FH(dir),
B
Bryan Schumaker 已提交
4380
		.pages = pages,
L
Linus Torvalds 已提交
4381 4382
		.pgbase = 0,
		.count = count,
4383
		.bitmask = NFS_SERVER(d_inode(dentry))->attr_bitmask,
B
Bryan Schumaker 已提交
4384
		.plus = plus,
L
Linus Torvalds 已提交
4385 4386 4387 4388 4389 4390 4391 4392 4393 4394
	};
	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;

4395 4396
	dprintk("%s: dentry = %pd2, cookie = %Lu\n", __func__,
			dentry,
4397
			(unsigned long long)cookie);
4398
	nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
L
Linus Torvalds 已提交
4399
	res.pgbase = args.pgbase;
4400
	status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
4401
	if (status >= 0) {
4402
		memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
4403 4404
		status += args.pgbase;
	}
4405 4406 4407

	nfs_invalidate_atime(dir);

4408
	dprintk("%s: returns %d\n", __func__, status);
L
Linus Torvalds 已提交
4409 4410 4411 4412
	return status;
}

static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
B
Bryan Schumaker 已提交
4413
		u64 cookie, struct page **pages, unsigned int count, int plus)
L
Linus Torvalds 已提交
4414 4415 4416 4417
{
	struct nfs4_exception exception = { };
	int err;
	do {
4418 4419
		err = _nfs4_proc_readdir(dentry, cred, cookie,
				pages, count, plus);
4420 4421
		trace_nfs4_readdir(d_inode(dentry), err);
		err = nfs4_handle_exception(NFS_SERVER(d_inode(dentry)), err,
L
Linus Torvalds 已提交
4422 4423 4424 4425 4426 4427
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
4428
		struct iattr *sattr, struct nfs4_label *label, dev_t rdev)
L
Linus Torvalds 已提交
4429
{
4430 4431 4432
	struct nfs4_createdata *data;
	int mode = sattr->ia_mode;
	int status = -ENOMEM;
L
Linus Torvalds 已提交
4433

4434 4435 4436 4437
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
	if (data == NULL)
		goto out;

L
Linus Torvalds 已提交
4438
	if (S_ISFIFO(mode))
4439
		data->arg.ftype = NF4FIFO;
L
Linus Torvalds 已提交
4440
	else if (S_ISBLK(mode)) {
4441 4442 4443
		data->arg.ftype = NF4BLK;
		data->arg.u.device.specdata1 = MAJOR(rdev);
		data->arg.u.device.specdata2 = MINOR(rdev);
L
Linus Torvalds 已提交
4444 4445
	}
	else if (S_ISCHR(mode)) {
4446 4447 4448
		data->arg.ftype = NF4CHR;
		data->arg.u.device.specdata1 = MAJOR(rdev);
		data->arg.u.device.specdata2 = MINOR(rdev);
4449 4450 4451
	} else if (!S_ISSOCK(mode)) {
		status = -EINVAL;
		goto out_free;
L
Linus Torvalds 已提交
4452
	}
4453

4454
	data->arg.label = label;
4455
	status = nfs4_do_create(dir, dentry, data);
4456
out_free:
4457 4458
	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
4459 4460 4461 4462 4463 4464
	return status;
}

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

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

4472 4473
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
L
Linus Torvalds 已提交
4474
	do {
4475 4476 4477
		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 已提交
4478 4479
				&exception);
	} while (exception.retry);
4480 4481 4482

	nfs4_label_release_security(label);

L
Linus Torvalds 已提交
4483 4484 4485 4486 4487 4488 4489 4490 4491 4492
	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 已提交
4493 4494 4495
	struct nfs4_statfs_res res = {
		.fsstat = fsstat,
	};
L
Linus Torvalds 已提交
4496 4497 4498
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4499
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4500 4501
	};

4502
	nfs_fattr_init(fsstat->fattr);
4503
	return  nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524
}

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 已提交
4525 4526 4527
	struct nfs4_fsinfo_res res = {
		.fsinfo = fsinfo,
	};
L
Linus Torvalds 已提交
4528 4529 4530
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4531
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4532 4533
	};

4534
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4535 4536 4537 4538 4539
}

static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
	struct nfs4_exception exception = { };
4540
	unsigned long now = jiffies;
L
Linus Torvalds 已提交
4541 4542 4543
	int err;

	do {
4544
		err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
4545
		trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err);
4546
		if (err == 0) {
4547 4548 4549
			nfs4_set_lease_period(server->nfs_client,
					fsinfo->lease_time * HZ,
					now);
4550 4551 4552
			break;
		}
		err = nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
4553 4554 4555 4556 4557 4558
	} while (exception.retry);
	return err;
}

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

4561
	nfs_fattr_init(fsinfo->fattr);
4562
	error = nfs4_do_fsinfo(server, fhandle, fsinfo);
4563 4564 4565
	if (error == 0) {
		/* block layout checks this! */
		server->pnfs_blksize = fsinfo->blksize;
4566
		set_pnfs_layoutdriver(server, fhandle, fsinfo);
4567
	}
4568 4569

	return error;
L
Linus Torvalds 已提交
4570 4571 4572 4573 4574 4575 4576 4577 4578
}

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 已提交
4579 4580 4581
	struct nfs4_pathconf_res res = {
		.pathconf = pathconf,
	};
L
Linus Torvalds 已提交
4582 4583 4584
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4585
		.rpc_resp = &res,
L
Linus Torvalds 已提交
4586 4587 4588 4589 4590 4591 4592 4593
	};

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

4594
	nfs_fattr_init(pathconf->fattr);
4595
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611
}

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

4612
int nfs4_set_rw_stateid(nfs4_stateid *stateid,
4613 4614 4615 4616
		const struct nfs_open_context *ctx,
		const struct nfs_lock_context *l_ctx,
		fmode_t fmode)
{
4617
	return nfs4_select_rw_stateid(ctx->state, fmode, l_ctx, stateid, NULL);
4618 4619 4620
}
EXPORT_SYMBOL_GPL(nfs4_set_rw_stateid);

4621 4622 4623 4624 4625 4626 4627
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;

4628 4629 4630
	/* If the current stateid represents a lost lock, then exit */
	if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode) == -EIO)
		return true;
4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648
	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;
}

4649
static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr)
L
Linus Torvalds 已提交
4650
{
4651
	struct nfs_server *server = NFS_SERVER(hdr->inode);
L
Linus Torvalds 已提交
4652

4653
	trace_nfs4_read(hdr, task->tk_status);
4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665
	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 已提交
4666
	}
4667

L
Linus Torvalds 已提交
4668
	if (task->tk_status > 0)
4669
		renew_lease(server, hdr->timestamp);
T
Trond Myklebust 已提交
4670
	return 0;
L
Linus Torvalds 已提交
4671 4672
}

4673
static bool nfs4_read_stateid_changed(struct rpc_task *task,
4674
		struct nfs_pgio_args *args)
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686
{

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

4687
static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
4688 4689 4690 4691
{

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

4692
	if (!nfs4_sequence_done(task, &hdr->res.seq_res))
4693
		return -EAGAIN;
4694
	if (nfs4_read_stateid_changed(task, &hdr->args))
4695
		return -EAGAIN;
4696 4697
	if (task->tk_status > 0)
		nfs_invalidate_atime(hdr->inode);
4698 4699
	return hdr->pgio_done_cb ? hdr->pgio_done_cb(task, hdr) :
				    nfs4_read_done_cb(task, hdr);
4700 4701
}

4702 4703
static void nfs4_proc_read_setup(struct nfs_pgio_header *hdr,
				 struct rpc_message *msg)
L
Linus Torvalds 已提交
4704
{
4705
	hdr->timestamp   = jiffies;
4706 4707
	if (!hdr->pgio_done_cb)
		hdr->pgio_done_cb = nfs4_read_done_cb;
4708
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
4709
	nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0);
L
Linus Torvalds 已提交
4710 4711
}

4712 4713
static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task,
				      struct nfs_pgio_header *hdr)
4714
{
4715 4716 4717
	if (nfs4_setup_sequence(NFS_SERVER(hdr->inode),
			&hdr->args.seq_args,
			&hdr->res.seq_res,
4718
			task))
4719
		return 0;
4720 4721 4722
	if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
				hdr->args.lock_context,
				hdr->rw_ops->rw_mode) == -EIO)
4723
		return -EIO;
4724
	if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags)))
4725 4726
		return -EIO;
	return 0;
L
Linus Torvalds 已提交
4727 4728
}

4729 4730
static int nfs4_write_done_cb(struct rpc_task *task,
			      struct nfs_pgio_header *hdr)
L
Linus Torvalds 已提交
4731
{
4732
	struct inode *inode = hdr->inode;
4733

4734
	trace_nfs4_write(hdr, task->tk_status);
4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747
	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 已提交
4748
	}
4749
	if (task->tk_status >= 0) {
4750
		renew_lease(NFS_SERVER(inode), hdr->timestamp);
4751
		nfs_writeback_update_inode(hdr);
4752
	}
4753
	return 0;
L
Linus Torvalds 已提交
4754 4755
}

4756
static bool nfs4_write_stateid_changed(struct rpc_task *task,
4757
		struct nfs_pgio_args *args)
4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769
{

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

4770
static int nfs4_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
4771
{
4772
	if (!nfs4_sequence_done(task, &hdr->res.seq_res))
4773
		return -EAGAIN;
4774
	if (nfs4_write_stateid_changed(task, &hdr->args))
4775
		return -EAGAIN;
4776 4777
	return hdr->pgio_done_cb ? hdr->pgio_done_cb(task, hdr) :
		nfs4_write_done_cb(task, hdr);
4778 4779
}

4780
static
4781
bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
4782
{
4783
	/* Don't request attributes for pNFS or O_DIRECT writes */
4784
	if (hdr->ds_clp != NULL || hdr->dreq != NULL)
4785 4786 4787 4788
		return false;
	/* Otherwise, request attributes if and only if we don't hold
	 * a delegation
	 */
4789
	return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
4790 4791
}

4792 4793
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
				  struct rpc_message *msg)
L
Linus Torvalds 已提交
4794
{
4795
	struct nfs_server *server = NFS_SERVER(hdr->inode);
4796

4797 4798 4799
	if (!nfs4_write_need_cache_consistency_data(hdr)) {
		hdr->args.bitmask = NULL;
		hdr->res.fattr = NULL;
4800
	} else
4801
		hdr->args.bitmask = server->cache_consistency_bitmask;
4802

4803 4804 4805 4806
	if (!hdr->pgio_done_cb)
		hdr->pgio_done_cb = nfs4_write_done_cb;
	hdr->res.server = server;
	hdr->timestamp   = jiffies;
L
Linus Torvalds 已提交
4807

4808
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
4809
	nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1);
L
Linus Torvalds 已提交
4810 4811
}

4812
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
4813
{
4814 4815 4816 4817
	nfs4_setup_sequence(NFS_SERVER(data->inode),
			&data->args.seq_args,
			&data->res.seq_res,
			task);
L
Linus Torvalds 已提交
4818 4819
}

4820
static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
L
Linus Torvalds 已提交
4821 4822
{
	struct inode *inode = data->inode;
4823

4824
	trace_nfs4_commit(data, task->tk_status);
4825 4826
	if (nfs4_async_handle_error(task, NFS_SERVER(inode),
				    NULL, NULL) == -EAGAIN) {
4827
		rpc_restart_call_prepare(task);
4828
		return -EAGAIN;
L
Linus Torvalds 已提交
4829
	}
4830
	return 0;
L
Linus Torvalds 已提交
4831 4832
}

4833
static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
4834 4835 4836
{
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return -EAGAIN;
4837
	return data->commit_done_cb(task, data);
4838 4839
}

4840
static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
L
Linus Torvalds 已提交
4841
{
4842
	struct nfs_server *server = NFS_SERVER(data->inode);
4843

4844 4845
	if (data->commit_done_cb == NULL)
		data->commit_done_cb = nfs4_commit_done_cb;
4846
	data->res.server = server;
4847
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
4848
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
L
Linus Torvalds 已提交
4849 4850
}

4851 4852 4853 4854 4855
struct nfs4_renewdata {
	struct nfs_client	*client;
	unsigned long		timestamp;
};

L
Linus Torvalds 已提交
4856 4857 4858 4859
/*
 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
 * standalone procedure for queueing an asynchronous RENEW.
 */
4860
static void nfs4_renew_release(void *calldata)
4861
{
4862 4863
	struct nfs4_renewdata *data = calldata;
	struct nfs_client *clp = data->client;
4864

4865 4866 4867
	if (atomic_read(&clp->cl_count) > 1)
		nfs4_schedule_state_renewal(clp);
	nfs_put_client(clp);
4868
	kfree(data);
4869 4870
}

4871
static void nfs4_renew_done(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
4872
{
4873 4874 4875
	struct nfs4_renewdata *data = calldata;
	struct nfs_client *clp = data->client;
	unsigned long timestamp = data->timestamp;
L
Linus Torvalds 已提交
4876

4877
	trace_nfs4_renew_async(clp, task->tk_status);
4878 4879 4880 4881 4882 4883 4884
	switch (task->tk_status) {
	case 0:
		break;
	case -NFS4ERR_LEASE_MOVED:
		nfs4_schedule_lease_moved_recovery(clp);
		break;
	default:
4885
		/* Unless we're shutting down, schedule state recovery! */
4886 4887 4888
		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
			return;
		if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
4889
			nfs4_schedule_lease_recovery(clp);
4890 4891 4892
			return;
		}
		nfs4_schedule_path_down_recovery(clp);
L
Linus Torvalds 已提交
4893
	}
4894
	do_renew_lease(clp, timestamp);
L
Linus Torvalds 已提交
4895 4896
}

4897 4898
static const struct rpc_call_ops nfs4_renew_ops = {
	.rpc_call_done = nfs4_renew_done,
4899
	.rpc_release = nfs4_renew_release,
4900 4901
};

4902
static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
L
Linus Torvalds 已提交
4903 4904 4905 4906
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
		.rpc_argp	= clp,
4907
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
4908
	};
4909
	struct nfs4_renewdata *data;
L
Linus Torvalds 已提交
4910

4911 4912
	if (renew_flags == 0)
		return 0;
4913 4914
	if (!atomic_inc_not_zero(&clp->cl_count))
		return -EIO;
4915
	data = kmalloc(sizeof(*data), GFP_NOFS);
4916 4917 4918 4919
	if (data == NULL)
		return -ENOMEM;
	data->client = clp;
	data->timestamp = jiffies;
4920
	return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
4921
			&nfs4_renew_ops, data);
L
Linus Torvalds 已提交
4922 4923
}

4924
static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
L
Linus Torvalds 已提交
4925 4926 4927 4928
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
		.rpc_argp	= clp,
4929
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
4930 4931 4932 4933
	};
	unsigned long now = jiffies;
	int status;

4934
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
L
Linus Torvalds 已提交
4935 4936
	if (status < 0)
		return status;
4937
	do_renew_lease(clp, now);
L
Linus Torvalds 已提交
4938 4939 4940
	return 0;
}

4941 4942
static inline int nfs4_server_supports_acls(struct nfs_server *server)
{
4943
	return server->caps & NFS_CAP_ACLS;
4944 4945
}

4946 4947
/* 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
4948 4949
 * the stack.
 */
4950
#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
4951

4952
static int buf_to_pages_noslab(const void *buf, size_t buflen,
4953
		struct page **pages)
4954 4955 4956 4957 4958 4959 4960
{
	struct page *newpage, **spages;
	int rc = 0;
	size_t len;
	spages = pages;

	do {
4961
		len = min_t(size_t, PAGE_SIZE, buflen);
4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980
		newpage = alloc_page(GFP_KERNEL);

		if (newpage == NULL)
			goto unwind;
		memcpy(page_address(newpage), buf, len);
                buf += len;
                buflen -= len;
		*pages++ = newpage;
		rc++;
	} while (buflen != 0);

	return rc;

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

4981 4982 4983
struct nfs4_cached_acl {
	int cached;
	size_t len;
A
Andrew Morton 已提交
4984
	char data[0];
4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026
};

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

5027
static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
5028 5029
{
	struct nfs4_cached_acl *acl;
5030
	size_t buflen = sizeof(*acl) + acl_len;
5031

5032
	if (buflen <= PAGE_SIZE) {
5033
		acl = kmalloc(buflen, GFP_KERNEL);
5034 5035 5036
		if (acl == NULL)
			goto out;
		acl->cached = 1;
5037
		_copy_from_pages(acl->data, pages, pgbase, acl_len);
5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048
	} 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);
}

5049 5050 5051 5052 5053 5054 5055 5056 5057 5058
/*
 * 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.
 */
5059
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
5060
{
5061
	struct page *pages[NFS4ACL_MAXPAGES] = {NULL, };
5062 5063 5064 5065 5066
	struct nfs_getaclargs args = {
		.fh = NFS_FH(inode),
		.acl_pages = pages,
		.acl_len = buflen,
	};
B
Benny Halevy 已提交
5067 5068 5069
	struct nfs_getaclres res = {
		.acl_len = buflen,
	};
5070 5071 5072
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
		.rpc_argp = &args,
B
Benny Halevy 已提交
5073
		.rpc_resp = &res,
5074
	};
5075 5076
	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
	int ret = -ENOMEM, i;
5077

5078 5079 5080 5081
	/* As long as we're doing a round trip to the server anyway,
	 * let's be prepared for a page of acl data. */
	if (npages == 0)
		npages = 1;
5082 5083
	if (npages > ARRAY_SIZE(pages))
		return -ERANGE;
5084

5085 5086 5087 5088
	for (i = 0; i < npages; i++) {
		pages[i] = alloc_page(GFP_KERNEL);
		if (!pages[i])
			goto out_free;
5089
	}
5090 5091 5092 5093 5094 5095

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

5096
	args.acl_len = npages * PAGE_SIZE;
5097

5098
	dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
5099 5100 5101
		__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);
5102 5103
	if (ret)
		goto out_free;
5104

5105 5106 5107 5108 5109
	/* 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;
5110
		ret = -ERANGE;
5111
		goto out_free;
5112
	}
5113
	nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
5114 5115 5116 5117 5118
	if (buf) {
		if (res.acl_len > buflen) {
			ret = -ERANGE;
			goto out_free;
		}
5119
		_copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
5120
	}
5121 5122
out_ok:
	ret = res.acl_len;
5123
out_free:
5124 5125 5126
	for (i = 0; i < npages; i++)
		if (pages[i])
			__free_page(pages[i]);
5127 5128
	if (res.acl_scratch)
		__free_page(res.acl_scratch);
5129 5130 5131
	return ret;
}

5132 5133 5134 5135 5136 5137
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);
5138
		trace_nfs4_get_acl(inode, ret);
5139 5140 5141 5142 5143 5144 5145
		if (ret >= 0)
			break;
		ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
	} while (exception.retry);
	return ret;
}

5146 5147 5148 5149 5150 5151 5152 5153 5154 5155
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;
5156 5157
	if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
		nfs_zap_acl_cache(inode);
5158 5159
	ret = nfs4_read_cached_acl(inode, buf, buflen);
	if (ret != -ENOENT)
5160 5161
		/* -ENOENT is returned if there is no ACL or if there is an ACL
		 * but no cached acl data, just the acl length */
5162 5163 5164 5165
		return ret;
	return nfs4_get_acl_uncached(inode, buf, buflen);
}

5166
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
5167 5168 5169 5170 5171 5172 5173 5174
{
	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 已提交
5175
	struct nfs_setaclres res;
5176 5177 5178
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETACL],
		.rpc_argp	= &arg,
B
Benny Halevy 已提交
5179
		.rpc_resp	= &res,
5180
	};
5181
	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
5182
	int ret, i;
5183 5184 5185

	if (!nfs4_server_supports_acls(server))
		return -EOPNOTSUPP;
5186 5187
	if (npages > ARRAY_SIZE(pages))
		return -ERANGE;
5188
	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages);
5189 5190
	if (i < 0)
		return i;
5191
	nfs4_inode_return_delegation(inode);
5192
	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
5193 5194 5195 5196 5197 5198 5199 5200

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

5201 5202 5203 5204 5205 5206 5207
	/*
	 * Acl update can result in inode attribute update.
	 * so mark the attribute cache invalid.
	 */
	spin_lock(&inode->i_lock);
	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
	spin_unlock(&inode->i_lock);
5208 5209
	nfs_access_zap_cache(inode);
	nfs_zap_acl_cache(inode);
5210 5211 5212
	return ret;
}

5213 5214 5215 5216 5217
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
{
	struct nfs4_exception exception = { };
	int err;
	do {
5218 5219 5220
		err = __nfs4_proc_set_acl(inode, buf, buflen);
		trace_nfs4_set_acl(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
5221 5222 5223 5224 5225
				&exception);
	} while (exception.retry);
	return err;
}

5226 5227 5228 5229 5230 5231 5232 5233 5234
#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 };
5235
	struct nfs4_getattr_arg arg = {
5236 5237 5238 5239 5240 5241 5242 5243 5244 5245
		.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],
5246
		.rpc_argp	= &arg,
5247 5248 5249 5250 5251 5252
		.rpc_resp	= &res,
	};
	int ret;

	nfs_fattr_init(&fattr);

5253
	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 0);
5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272
	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 {
5273 5274 5275
		err = _nfs4_get_security_label(inode, buf, buflen);
		trace_nfs4_get_security_label(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289
				&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 };
5290
	struct nfs_setattrargs arg = {
5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303
		.fh             = NFS_FH(inode),
		.iap            = &sattr,
		.server		= server,
		.bitmask	= bitmask,
		.label		= ilabel,
	};
	struct nfs_setattrres res = {
		.fattr		= fattr,
		.label		= olabel,
		.server		= server,
	};
	struct rpc_message msg = {
		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
5304
		.rpc_argp       = &arg,
5305 5306 5307 5308
		.rpc_resp       = &res,
	};
	int status;

5309
	nfs4_stateid_copy(&arg.stateid, &zero_stateid);
5310

5311
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326
	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 {
5327 5328 5329 5330
		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,
5331 5332 5333 5334 5335 5336
				&exception);
	} while (exception.retry);
	return err;
}

static int
5337
nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375
{
	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 */


5376 5377
static void nfs4_init_boot_verifier(const struct nfs_client *clp,
				    nfs4_verifier *bootverf)
5378 5379 5380
{
	__be32 verf[2];

5381 5382 5383
	if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
		/* An impossible timestamp guarantees this value
		 * will never match a generated boot time. */
5384 5385
		verf[0] = cpu_to_be32(U32_MAX);
		verf[1] = cpu_to_be32(U32_MAX);
5386
	} else {
5387
		struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
5388 5389 5390 5391
		u64 ns = ktime_to_ns(nn->boot_time);

		verf[0] = cpu_to_be32(ns >> 32);
		verf[1] = cpu_to_be32(ns);
5392
	}
5393 5394 5395
	memcpy(bootverf->data, verf, sizeof(bootverf->data));
}

5396 5397
static int
nfs4_init_nonuniform_client_string(struct nfs_client *clp)
5398
{
5399 5400
	size_t len;
	char *str;
5401

5402
	if (clp->cl_owner_id != NULL)
5403
		return 0;
5404

5405
	rcu_read_lock();
5406
	len = 14 + strlen(clp->cl_ipaddr) + 1 +
5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423
		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;
5424

5425
	rcu_read_lock();
5426
	scnprintf(str, len, "Linux NFSv4.0 %s/%s %s",
5427 5428 5429
			clp->cl_ipaddr,
			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO));
5430
	rcu_read_unlock();
5431 5432 5433

	clp->cl_owner_id = str;
	return 0;
5434 5435
}

5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457
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;

5458
	scnprintf(str, len, "Linux NFSv%u.%u %s/%s",
5459 5460 5461 5462 5463 5464 5465 5466 5467
			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)
5468
{
5469 5470
	size_t len;
	char *str;
5471 5472

	if (clp->cl_owner_id != NULL)
5473
		return 0;
5474 5475

	if (nfs4_client_id_uniquifier[0] != '\0')
5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492
		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;

5493
	scnprintf(str, len, "Linux NFSv%u.%u %s",
5494 5495 5496 5497
			clp->rpc_ops->version, clp->cl_minorversion,
			clp->cl_rpcclient->cl_nodename);
	clp->cl_owner_id = str;
	return 0;
5498 5499
}

5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513
/*
 * 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");
}

5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525
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,
};

5526 5527 5528 5529 5530 5531 5532 5533 5534 5535
/**
 * 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.
 */
5536 5537 5538
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 已提交
5539 5540 5541 5542 5543
{
	nfs4_verifier sc_verifier;
	struct nfs4_setclientid setclientid = {
		.sc_verifier = &sc_verifier,
		.sc_prog = program,
5544
		.sc_clnt = clp,
L
Linus Torvalds 已提交
5545 5546 5547 5548
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
		.rpc_argp = &setclientid,
5549
		.rpc_resp = res,
5550
		.rpc_cred = cred,
L
Linus Torvalds 已提交
5551
	};
5552 5553 5554 5555 5556 5557 5558 5559
	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,
	};
5560
	int status;
L
Linus Torvalds 已提交
5561

5562
	/* nfs_client_id4 */
5563
	nfs4_init_boot_verifier(clp, &sc_verifier);
5564 5565 5566 5567

	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags))
		status = nfs4_init_uniform_client_string(clp);
	else
5568
		status = nfs4_init_nonuniform_client_string(clp);
5569 5570 5571

	if (status)
		goto out;
5572

5573
	/* cb_client4 */
5574 5575 5576 5577
	setclientid.sc_netid_len =
				nfs4_init_callback_netid(clp,
						setclientid.sc_netid,
						sizeof(setclientid.sc_netid));
5578
	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
5579
				sizeof(setclientid.sc_uaddr), "%s.%u.%u",
L
Linus Torvalds 已提交
5580 5581
				clp->cl_ipaddr, port >> 8, port & 255);

5582
	dprintk("NFS call  setclientid auth=%s, '%s'\n",
5583
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
5584
		clp->cl_owner_id);
5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596
	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:
5597
	trace_nfs4_setclientid(clp, status);
5598 5599
	dprintk("NFS reply setclientid: %d\n", status);
	return status;
L
Linus Torvalds 已提交
5600 5601
}

5602 5603 5604 5605 5606 5607 5608 5609
/**
 * 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.
 */
5610
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
5611 5612
		struct nfs4_setclientid_res *arg,
		struct rpc_cred *cred)
L
Linus Torvalds 已提交
5613 5614 5615
{
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
5616
		.rpc_argp = arg,
5617
		.rpc_cred = cred,
L
Linus Torvalds 已提交
5618 5619 5620
	};
	int status;

5621 5622 5623
	dprintk("NFS call  setclientid_confirm auth=%s, (client ID %llx)\n",
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
		clp->cl_clientid);
5624
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
5625
	trace_nfs4_setclientid_confirm(clp, status);
5626
	dprintk("NFS reply setclientid_confirm: %d\n", status);
L
Linus Torvalds 已提交
5627 5628 5629
	return status;
}

5630 5631
struct nfs4_delegreturndata {
	struct nfs4_delegreturnargs args;
5632
	struct nfs4_delegreturnres res;
5633 5634
	struct nfs_fh fh;
	nfs4_stateid stateid;
5635
	unsigned long timestamp;
5636 5637 5638
	struct {
		struct nfs4_layoutreturn_args arg;
		struct nfs4_layoutreturn_res res;
5639
		struct nfs4_xdr_opaque_data ld_private;
5640 5641 5642
		u32 roc_barrier;
		bool roc;
	} lr;
5643
	struct nfs_fattr fattr;
5644
	int rpc_status;
5645
	struct inode *inode;
5646 5647 5648 5649 5650
};

static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_delegreturndata *data = calldata;
5651

5652 5653
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return;
5654

5655
	trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681

	/* 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;
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_EXPIRED:
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_OLD_STATEID:
		case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
		case -NFS4ERR_WRONG_CRED:
			data->args.lr_args = NULL;
			data->res.lr_res = NULL;
			data->res.lr_ret = 0;
			rpc_restart_call_prepare(task);
			return;
		}
	}

5682 5683
	switch (task->tk_status) {
	case 0:
5684
		renew_lease(data->res.server, data->timestamp);
5685
		break;
5686 5687
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_DELEG_REVOKED:
5688 5689 5690 5691
	case -NFS4ERR_EXPIRED:
		nfs4_free_revoked_stateid(data->res.server,
				data->args.stateid,
				task->tk_msg.rpc_cred);
5692 5693 5694 5695 5696
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_OLD_STATEID:
	case -NFS4ERR_STALE_STATEID:
		task->tk_status = 0;
		break;
5697 5698 5699 5700 5701 5702 5703 5704
	case -NFS4ERR_ACCESS:
		if (data->args.bitmask) {
			data->args.bitmask = NULL;
			data->res.fattr = NULL;
			task->tk_status = 0;
			rpc_restart_call_prepare(task);
			return;
		}
5705
	default:
5706 5707
		if (nfs4_async_handle_error(task, data->res.server,
					    NULL, NULL) == -EAGAIN) {
5708
			rpc_restart_call_prepare(task);
5709 5710 5711 5712
			return;
		}
	}
	data->rpc_status = task->tk_status;
5713 5714 5715 5716
}

static void nfs4_delegreturn_release(void *calldata)
{
5717
	struct nfs4_delegreturndata *data = calldata;
5718
	struct inode *inode = data->inode;
5719

5720
	if (inode) {
5721
		if (data->lr.roc)
5722 5723
			pnfs_roc_release(&data->lr.arg, &data->lr.res,
					data->res.lr_ret);
5724
		nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
5725 5726
		nfs_iput_and_deactive(inode);
	}
5727 5728 5729
	kfree(calldata);
}

5730 5731 5732 5733 5734 5735
static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
{
	struct nfs4_delegreturndata *d_data;

	d_data = (struct nfs4_delegreturndata *)data;

5736
	if (!d_data->lr.roc && nfs4_wait_on_layoutreturn(d_data->inode, task))
5737 5738
		return;

5739 5740 5741 5742
	nfs4_setup_sequence(d_data->res.server,
			&d_data->args.seq_args,
			&d_data->res.seq_res,
			task);
5743 5744
}

5745
static const struct rpc_call_ops nfs4_delegreturn_ops = {
5746
	.rpc_call_prepare = nfs4_delegreturn_prepare,
5747 5748 5749 5750
	.rpc_call_done = nfs4_delegreturn_done,
	.rpc_release = nfs4_delegreturn_release,
};

5751
static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
5752 5753
{
	struct nfs4_delegreturndata *data;
5754
	struct nfs_server *server = NFS_SERVER(inode);
5755
	struct rpc_task *task;
5756 5757 5758 5759
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
		.rpc_cred = cred,
	};
T
Trond Myklebust 已提交
5760 5761
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
5762
		.rpc_message = &msg,
T
Trond Myklebust 已提交
5763 5764 5765
		.callback_ops = &nfs4_delegreturn_ops,
		.flags = RPC_TASK_ASYNC,
	};
5766
	int status = 0;
5767

5768
	data = kzalloc(sizeof(*data), GFP_NOFS);
5769 5770
	if (data == NULL)
		return -ENOMEM;
5771
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
5772 5773 5774 5775 5776

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

5777 5778
	data->args.fhandle = &data->fh;
	data->args.stateid = &data->stateid;
5779
	data->args.bitmask = server->cache_consistency_bitmask;
5780
	nfs_copy_fh(&data->fh, NFS_FH(inode));
5781
	nfs4_stateid_copy(&data->stateid, stateid);
5782 5783
	data->res.fattr = &data->fattr;
	data->res.server = server;
5784
	data->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT;
5785
	data->lr.arg.ld_private = &data->lr.ld_private;
5786
	nfs_fattr_init(data->res.fattr);
5787
	data->timestamp = jiffies;
5788
	data->rpc_status = 0;
5789
	data->lr.roc = pnfs_roc(inode, &data->lr.arg, &data->lr.res, cred);
5790
	data->inode = nfs_igrab_and_active(inode);
5791 5792 5793 5794 5795
	if (data->inode) {
		if (data->lr.roc) {
			data->args.lr_args = &data->lr.arg;
			data->res.lr_res = &data->lr.res;
		}
5796 5797 5798
	} else if (data->lr.roc) {
		pnfs_roc_release(&data->lr.arg, &data->lr.res, 0);
		data->lr.roc = false;
5799
	}
5800

T
Trond Myklebust 已提交
5801
	task_setup_data.callback_data = data;
5802 5803
	msg.rpc_argp = &data->args;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
5804
	task = rpc_run_task(&task_setup_data);
5805
	if (IS_ERR(task))
5806
		return PTR_ERR(task);
5807 5808
	if (!issync)
		goto out;
5809
	status = nfs4_wait_for_completion_rpc_task(task);
5810 5811 5812 5813
	if (status != 0)
		goto out;
	status = data->rpc_status;
out:
5814
	rpc_put_task(task);
5815
	return status;
L
Linus Torvalds 已提交
5816 5817
}

5818
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
L
Linus Torvalds 已提交
5819 5820 5821 5822 5823
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs4_exception exception = { };
	int err;
	do {
5824
		err = _nfs4_proc_delegreturn(inode, cred, stateid, issync);
5825
		trace_nfs4_delegreturn(inode, stateid, err);
L
Linus Torvalds 已提交
5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840
		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);
5841
	struct nfs_client *clp = server->nfs_client;
T
Trond Myklebust 已提交
5842
	struct nfs_lockt_args arg = {
L
Linus Torvalds 已提交
5843
		.fh = NFS_FH(inode),
T
Trond Myklebust 已提交
5844
		.fl = request,
L
Linus Torvalds 已提交
5845
	};
T
Trond Myklebust 已提交
5846 5847
	struct nfs_lockt_res res = {
		.denied = request,
L
Linus Torvalds 已提交
5848 5849 5850 5851 5852 5853 5854 5855 5856 5857
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_LOCKT],
		.rpc_argp       = &arg,
		.rpc_resp       = &res,
		.rpc_cred	= state->owner->so_cred,
	};
	struct nfs4_lock_state *lsp;
	int status;

T
Trond Myklebust 已提交
5858
	arg.lock_owner.clientid = clp->cl_clientid;
5859 5860 5861 5862
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		goto out;
	lsp = request->fl_u.nfs4_fl.owner;
5863
	arg.lock_owner.id = lsp->ls_seqid.owner_id;
5864
	arg.lock_owner.s_dev = server->s_dev;
5865
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
T
Trond Myklebust 已提交
5866 5867 5868 5869 5870 5871
	switch (status) {
		case 0:
			request->fl_type = F_UNLCK;
			break;
		case -NFS4ERR_DENIED:
			status = 0;
L
Linus Torvalds 已提交
5872
	}
5873
	request->fl_ops->fl_release_private(request);
5874
	request->fl_ops = NULL;
5875
out:
L
Linus Torvalds 已提交
5876 5877 5878 5879 5880 5881 5882 5883 5884
	return status;
}

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

	do {
5885 5886 5887
		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 已提交
5888 5889 5890 5891 5892
				&exception);
	} while (exception.retry);
	return err;
}

5893
struct nfs4_unlockdata {
T
Trond Myklebust 已提交
5894 5895
	struct nfs_locku_args arg;
	struct nfs_locku_res res;
5896 5897
	struct nfs4_lock_state *lsp;
	struct nfs_open_context *ctx;
T
Trond Myklebust 已提交
5898
	struct file_lock fl;
5899
	struct nfs_server *server;
5900
	unsigned long timestamp;
5901 5902
};

T
Trond Myklebust 已提交
5903 5904 5905 5906 5907 5908 5909 5910
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;

5911
	p = kzalloc(sizeof(*p), GFP_NOFS);
T
Trond Myklebust 已提交
5912 5913 5914 5915 5916
	if (p == NULL)
		return NULL;
	p->arg.fh = NFS_FH(inode);
	p->arg.fl = &p->fl;
	p->arg.seqid = seqid;
5917
	p->res.seqid = seqid;
T
Trond Myklebust 已提交
5918 5919 5920 5921 5922 5923 5924 5925 5926
	p->lsp = lsp;
	atomic_inc(&lsp->ls_count);
	/* Ensure we don't close file until we're done freeing locks! */
	p->ctx = get_nfs_open_context(ctx);
	memcpy(&p->fl, fl, sizeof(p->fl));
	p->server = NFS_SERVER(inode);
	return p;
}

5927
static void nfs4_locku_release_calldata(void *data)
5928
{
5929
	struct nfs4_unlockdata *calldata = data;
T
Trond Myklebust 已提交
5930
	nfs_free_seqid(calldata->arg.seqid);
5931 5932 5933
	nfs4_put_lock_state(calldata->lsp);
	put_nfs_open_context(calldata->ctx);
	kfree(calldata);
5934 5935
}

5936
static void nfs4_locku_done(struct rpc_task *task, void *data)
5937
{
5938
	struct nfs4_unlockdata *calldata = data;
5939

5940 5941
	if (!nfs4_sequence_done(task, &calldata->res.seq_res))
		return;
5942 5943
	switch (task->tk_status) {
		case 0:
5944
			renew_lease(calldata->server, calldata->timestamp);
5945
			locks_lock_inode_wait(calldata->lsp->ls_state->inode, &calldata->fl);
5946 5947 5948
			if (nfs4_update_lock_stateid(calldata->lsp,
					&calldata->res.stateid))
				break;
5949 5950 5951 5952 5953
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_EXPIRED:
			nfs4_free_revoked_stateid(calldata->server,
					&calldata->arg.stateid,
					task->tk_msg.rpc_cred);
5954 5955
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_OLD_STATEID:
5956
		case -NFS4ERR_STALE_STATEID:
5957 5958 5959
			if (!nfs4_stateid_match(&calldata->arg.stateid,
						&calldata->lsp->ls_stateid))
				rpc_restart_call_prepare(task);
5960 5961
			break;
		default:
5962 5963
			if (nfs4_async_handle_error(task, calldata->server,
						    NULL, NULL) == -EAGAIN)
5964
				rpc_restart_call_prepare(task);
5965
	}
5966
	nfs_release_seqid(calldata->arg.seqid);
5967 5968
}

T
Trond Myklebust 已提交
5969
static void nfs4_locku_prepare(struct rpc_task *task, void *data)
5970
{
T
Trond Myklebust 已提交
5971
	struct nfs4_unlockdata *calldata = data;
5972

T
Trond Myklebust 已提交
5973
	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
5974
		goto out_wait;
5975
	nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid);
5976
	if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
5977
		/* Note: exit _without_ running nfs4_locku_done */
5978
		goto out_no_action;
5979
	}
5980
	calldata->timestamp = jiffies;
5981
	if (nfs4_setup_sequence(calldata->server,
5982
				&calldata->arg.seq_args,
5983 5984 5985
				&calldata->res.seq_res,
				task) != 0)
		nfs_release_seqid(calldata->arg.seqid);
5986 5987 5988 5989 5990
	return;
out_no_action:
	task->tk_action = NULL;
out_wait:
	nfs4_sequence_done(task, &calldata->res.seq_res);
5991 5992
}

5993
static const struct rpc_call_ops nfs4_locku_ops = {
T
Trond Myklebust 已提交
5994
	.rpc_call_prepare = nfs4_locku_prepare,
5995
	.rpc_call_done = nfs4_locku_done,
5996
	.rpc_release = nfs4_locku_release_calldata,
5997 5998
};

5999 6000 6001 6002 6003 6004
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;
6005 6006 6007 6008
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
		.rpc_cred = ctx->cred,
	};
T
Trond Myklebust 已提交
6009 6010
	struct rpc_task_setup task_setup_data = {
		.rpc_client = NFS_CLIENT(lsp->ls_state->inode),
6011
		.rpc_message = &msg,
T
Trond Myklebust 已提交
6012
		.callback_ops = &nfs4_locku_ops,
6013
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
6014 6015
		.flags = RPC_TASK_ASYNC,
	};
6016

6017 6018 6019
	nfs4_state_protect(NFS_SERVER(lsp->ls_state->inode)->nfs_client,
		NFS_SP4_MACH_CRED_CLEANUP, &task_setup_data.rpc_client, &msg);

6020 6021 6022 6023 6024
	/* 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;

6025 6026 6027 6028 6029 6030
	data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
	if (data == NULL) {
		nfs_free_seqid(seqid);
		return ERR_PTR(-ENOMEM);
	}

6031
	nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
6032 6033
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
6034 6035
	task_setup_data.callback_data = data;
	return rpc_run_task(&task_setup_data);
6036 6037
}

6038 6039
static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
6040 6041 6042
	struct inode *inode = state->inode;
	struct nfs4_state_owner *sp = state->owner;
	struct nfs_inode *nfsi = NFS_I(inode);
T
Trond Myklebust 已提交
6043
	struct nfs_seqid *seqid;
L
Linus Torvalds 已提交
6044
	struct nfs4_lock_state *lsp;
6045
	struct rpc_task *task;
6046
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
6047
	int status = 0;
6048
	unsigned char fl_flags = request->fl_flags;
6049

6050
	status = nfs4_set_lock_state(state, request);
6051 6052
	/* Unlock _before_ we do the RPC call */
	request->fl_flags |= FL_EXISTS;
6053 6054 6055
	/* Exclude nfs_delegation_claim_locks() */
	mutex_lock(&sp->so_delegreturn_mutex);
	/* Exclude nfs4_reclaim_open_stateid() - note nesting! */
6056
	down_read(&nfsi->rwsem);
6057
	if (locks_lock_inode_wait(inode, request) == -ENOENT) {
6058
		up_read(&nfsi->rwsem);
6059
		mutex_unlock(&sp->so_delegreturn_mutex);
6060
		goto out;
6061 6062
	}
	up_read(&nfsi->rwsem);
6063
	mutex_unlock(&sp->so_delegreturn_mutex);
6064
	if (status != 0)
6065 6066
		goto out;
	/* Is this a delegated lock? */
6067
	lsp = request->fl_u.nfs4_fl.owner;
6068 6069
	if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0)
		goto out;
6070 6071
	alloc_seqid = NFS_SERVER(inode)->nfs_client->cl_mvops->alloc_seqid;
	seqid = alloc_seqid(&lsp->ls_seqid, GFP_KERNEL);
6072
	status = -ENOMEM;
6073
	if (IS_ERR(seqid))
6074
		goto out;
6075
	task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid);
6076 6077
	status = PTR_ERR(task);
	if (IS_ERR(task))
6078
		goto out;
6079
	status = nfs4_wait_for_completion_rpc_task(task);
6080
	rpc_put_task(task);
6081
out:
6082
	request->fl_flags = fl_flags;
6083
	trace_nfs4_unlock(request, state, F_SETLK, status);
L
Linus Torvalds 已提交
6084 6085 6086
	return status;
}

6087 6088 6089 6090 6091 6092
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;
6093
	unsigned long timestamp;
6094 6095
	int rpc_status;
	int cancelled;
6096
	struct nfs_server *server;
6097 6098 6099
};

static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
6100 6101
		struct nfs_open_context *ctx, struct nfs4_lock_state *lsp,
		gfp_t gfp_mask)
L
Linus Torvalds 已提交
6102
{
6103 6104
	struct nfs4_lockdata *p;
	struct inode *inode = lsp->ls_state->inode;
L
Linus Torvalds 已提交
6105
	struct nfs_server *server = NFS_SERVER(inode);
6106
	struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
6107

6108
	p = kzalloc(sizeof(*p), gfp_mask);
6109 6110 6111 6112 6113
	if (p == NULL)
		return NULL;

	p->arg.fh = NFS_FH(inode);
	p->arg.fl = &p->fl;
6114
	p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask);
6115
	if (IS_ERR(p->arg.open_seqid))
6116
		goto out_free;
6117 6118
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	p->arg.lock_seqid = alloc_seqid(&lsp->ls_seqid, gfp_mask);
6119
	if (IS_ERR(p->arg.lock_seqid))
6120
		goto out_free_seqid;
6121
	p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
6122
	p->arg.lock_owner.id = lsp->ls_seqid.owner_id;
6123
	p->arg.lock_owner.s_dev = server->s_dev;
6124
	p->res.lock_seqid = p->arg.lock_seqid;
6125
	p->lsp = lsp;
6126
	p->server = server;
6127 6128 6129 6130
	atomic_inc(&lsp->ls_count);
	p->ctx = get_nfs_open_context(ctx);
	memcpy(&p->fl, fl, sizeof(p->fl));
	return p;
6131 6132
out_free_seqid:
	nfs_free_seqid(p->arg.open_seqid);
6133 6134 6135 6136 6137 6138 6139 6140 6141
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;
6142

6143
	dprintk("%s: begin!\n", __func__);
6144
	if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
6145
		goto out_wait;
6146
	/* Do we need to do an open_to_lock_owner? */
6147
	if (!test_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags)) {
6148
		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
6149
			goto out_release_lock_seqid;
6150
		}
6151 6152
		nfs4_stateid_copy(&data->arg.open_stateid,
				&state->open_stateid);
6153
		data->arg.new_lock_owner = 1;
6154
		data->res.open_seqid = data->arg.open_seqid;
6155
	} else {
6156
		data->arg.new_lock_owner = 0;
6157 6158 6159
		nfs4_stateid_copy(&data->arg.lock_stateid,
				&data->lsp->ls_stateid);
	}
6160 6161 6162 6163 6164
	if (!nfs4_valid_open_stateid(state)) {
		data->rpc_status = -EBADF;
		task->tk_action = NULL;
		goto out_release_open_seqid;
	}
6165
	data->timestamp = jiffies;
6166 6167
	if (nfs4_setup_sequence(data->server,
				&data->arg.seq_args,
6168
				&data->res.seq_res,
6169
				task) == 0)
6170
		return;
6171
out_release_open_seqid:
6172 6173 6174
	nfs_release_seqid(data->arg.open_seqid);
out_release_lock_seqid:
	nfs_release_seqid(data->arg.lock_seqid);
6175 6176
out_wait:
	nfs4_sequence_done(task, &data->res.seq_res);
6177
	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
6178 6179
}

6180 6181 6182
static void nfs4_lock_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_lockdata *data = calldata;
6183
	struct nfs4_lock_state *lsp = data->lsp;
6184

6185
	dprintk("%s: begin!\n", __func__);
6186

6187 6188
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return;
6189

6190
	data->rpc_status = task->tk_status;
6191 6192
	switch (task->tk_status) {
	case 0:
6193
		renew_lease(NFS_SERVER(d_inode(data->ctx->dentry)),
6194
				data->timestamp);
6195 6196
		if (data->arg.new_lock) {
			data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
6197
			if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0) {
6198 6199 6200 6201
				rpc_restart_call_prepare(task);
				break;
			}
		}
6202 6203 6204 6205 6206 6207
		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);
6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219
		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);
6220
	}
6221
	dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
6222 6223 6224 6225 6226 6227
}

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

6228
	dprintk("%s: begin!\n", __func__);
6229
	nfs_free_seqid(data->arg.open_seqid);
6230 6231 6232 6233 6234
	if (data->cancelled != 0) {
		struct rpc_task *task;
		task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
				data->arg.lock_seqid);
		if (!IS_ERR(task))
6235
			rpc_put_task_async(task);
6236
		dprintk("%s: cancelling lock!\n", __func__);
6237 6238 6239 6240 6241
	} else
		nfs_free_seqid(data->arg.lock_seqid);
	nfs4_put_lock_state(data->lsp);
	put_nfs_open_context(data->ctx);
	kfree(data);
6242
	dprintk("%s: done!\n", __func__);
6243 6244 6245 6246 6247 6248 6249 6250
}

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

6251 6252 6253 6254
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:
6255
	case -NFS4ERR_EXPIRED:
6256
	case -NFS4ERR_BAD_STATEID:
6257
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
6258
		if (new_lock_owner != 0 ||
6259
		   test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0)
6260
			nfs4_schedule_stateid_recovery(server, lsp->ls_state);
6261 6262 6263
		break;
	case -NFS4ERR_STALE_STATEID:
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
6264
		nfs4_schedule_lease_recovery(server->nfs_client);
6265 6266 6267
	};
}

6268
static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
6269 6270 6271
{
	struct nfs4_lockdata *data;
	struct rpc_task *task;
6272 6273 6274 6275
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
		.rpc_cred = state->owner->so_cred,
	};
T
Trond Myklebust 已提交
6276 6277
	struct rpc_task_setup task_setup_data = {
		.rpc_client = NFS_CLIENT(state->inode),
6278
		.rpc_message = &msg,
T
Trond Myklebust 已提交
6279
		.callback_ops = &nfs4_lock_ops,
6280
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
6281 6282
		.flags = RPC_TASK_ASYNC,
	};
6283 6284
	int ret;

6285
	dprintk("%s: begin!\n", __func__);
6286
	data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file),
6287 6288
			fl->fl_u.nfs4_fl.owner,
			recovery_type == NFS_LOCK_NEW ? GFP_KERNEL : GFP_NOFS);
6289 6290 6291 6292
	if (data == NULL)
		return -ENOMEM;
	if (IS_SETLKW(cmd))
		data->arg.block = 1;
6293
	nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
6294 6295
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
6296
	task_setup_data.callback_data = data;
6297 6298 6299 6300
	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);
6301 6302
	} else
		data->arg.new_lock = 1;
T
Trond Myklebust 已提交
6303
	task = rpc_run_task(&task_setup_data);
6304
	if (IS_ERR(task))
6305 6306 6307 6308
		return PTR_ERR(task);
	ret = nfs4_wait_for_completion_rpc_task(task);
	if (ret == 0) {
		ret = data->rpc_status;
6309 6310 6311
		if (ret)
			nfs4_handle_setlk_error(data->server, data->lsp,
					data->arg.new_lock_owner, ret);
6312 6313
	} else
		data->cancelled = 1;
6314
	rpc_put_task(task);
6315
	dprintk("%s: done, ret = %d!\n", __func__, ret);
6316
	trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret);
6317
	return ret;
L
Linus Torvalds 已提交
6318 6319 6320 6321
}

static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
6322
	struct nfs_server *server = NFS_SERVER(state->inode);
6323 6324 6325
	struct nfs4_exception exception = {
		.inode = state->inode,
	};
6326 6327 6328
	int err;

	do {
6329 6330 6331
		/* Cache the lock if possible... */
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
6332
		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
6333
		if (err != -NFS4ERR_DELAY)
6334 6335 6336 6337
			break;
		nfs4_handle_exception(server, err, &exception);
	} while (exception.retry);
	return err;
L
Linus Torvalds 已提交
6338 6339 6340 6341
}

static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
6342
	struct nfs_server *server = NFS_SERVER(state->inode);
6343 6344 6345
	struct nfs4_exception exception = {
		.inode = state->inode,
	};
6346 6347
	int err;

6348 6349 6350
	err = nfs4_set_lock_state(state, request);
	if (err != 0)
		return err;
6351
	if (!recover_lost_locks) {
6352 6353 6354
		set_bit(NFS_LOCK_LOST, &request->fl_u.nfs4_fl.owner->ls_flags);
		return 0;
	}
6355
	do {
6356 6357
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
6358
		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED);
6359 6360 6361 6362 6363 6364 6365 6366
		switch (err) {
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
6367
	} while (exception.retry);
6368
out:
6369
	return err;
L
Linus Torvalds 已提交
6370 6371
}

6372
#if defined(CONFIG_NFS_V4_1)
6373 6374
static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
6375 6376
	struct nfs4_lock_state *lsp;
	int status;
6377

6378 6379 6380 6381 6382 6383 6384 6385
	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;
	status = nfs4_lock_expired(state, request);
6386
	return status;
6387 6388 6389
}
#endif

L
Linus Torvalds 已提交
6390 6391
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
6392
	struct nfs_inode *nfsi = NFS_I(state->inode);
6393
	struct nfs4_state_owner *sp = state->owner;
6394
	unsigned char fl_flags = request->fl_flags;
6395
	int status;
L
Linus Torvalds 已提交
6396

6397
	request->fl_flags |= FL_ACCESS;
6398
	status = locks_lock_inode_wait(state->inode, request);
6399 6400
	if (status < 0)
		goto out;
6401
	mutex_lock(&sp->so_delegreturn_mutex);
6402
	down_read(&nfsi->rwsem);
6403 6404 6405
	if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
		/* Yes: cache locks! */
		/* ...but avoid races with delegation recall... */
6406
		request->fl_flags = fl_flags & ~FL_SLEEP;
6407
		status = locks_lock_inode_wait(state->inode, request);
6408
		up_read(&nfsi->rwsem);
6409
		mutex_unlock(&sp->so_delegreturn_mutex);
6410 6411
		goto out;
	}
6412
	up_read(&nfsi->rwsem);
6413
	mutex_unlock(&sp->so_delegreturn_mutex);
6414
	status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW);
6415 6416
out:
	request->fl_flags = fl_flags;
L
Linus Torvalds 已提交
6417 6418 6419 6420 6421
	return status;
}

static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
6422 6423
	struct nfs4_exception exception = {
		.state = state,
6424
		.inode = state->inode,
6425
	};
L
Linus Torvalds 已提交
6426 6427 6428
	int err;

	do {
6429 6430 6431
		err = _nfs4_proc_setlk(state, cmd, request);
		if (err == -NFS4ERR_DENIED)
			err = -EAGAIN;
L
Linus Torvalds 已提交
6432
		err = nfs4_handle_exception(NFS_SERVER(state->inode),
6433
				err, &exception);
L
Linus Torvalds 已提交
6434 6435 6436 6437
	} while (exception.retry);
	return err;
}

6438 6439 6440 6441
#define NFS4_LOCK_MINTIMEOUT (1 * HZ)
#define NFS4_LOCK_MAXTIMEOUT (30 * HZ)

static int
6442 6443
nfs4_retry_setlk_simple(struct nfs4_state *state, int cmd,
			struct file_lock *request)
6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459
{
	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;
}

6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550
#ifdef CONFIG_NFS_V4_1
struct nfs4_lock_waiter {
	struct task_struct	*task;
	struct inode		*inode;
	struct nfs_lowner	*owner;
	bool			notified;
};

static int
nfs4_wake_lock_waiter(wait_queue_t *wait, unsigned int mode, int flags, void *key)
{
	int ret;
	struct cb_notify_lock_args *cbnl = key;
	struct nfs4_lock_waiter	*waiter	= wait->private;
	struct nfs_lowner	*lowner = &cbnl->cbnl_owner,
				*wowner = waiter->owner;

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

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

	waiter->notified = true;

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

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

		freezable_schedule_timeout_interruptible(NFS4_LOCK_MAXTIMEOUT);
	}

	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 已提交
6551 6552 6553 6554 6555 6556 6557 6558
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 */
6559
	ctx = nfs_file_open_context(filp);
L
Linus Torvalds 已提交
6560 6561 6562 6563 6564
	state = ctx->state;

	if (request->fl_start < 0 || request->fl_end < 0)
		return -EINVAL;

6565 6566 6567 6568 6569
	if (IS_GETLK(cmd)) {
		if (state != NULL)
			return nfs4_proc_getlk(state, F_GETLK, request);
		return 0;
	}
L
Linus Torvalds 已提交
6570 6571 6572 6573

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

6574 6575 6576 6577 6578
	if (request->fl_type == F_UNLCK) {
		if (state != NULL)
			return nfs4_proc_unlck(state, cmd, request);
		return 0;
	}
L
Linus Torvalds 已提交
6579

6580 6581
	if (state == NULL)
		return -ENOLCK;
6582 6583 6584 6585 6586

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

6587 6588 6589 6590
	/*
	 * Don't rely on the VFS having checked the file open mode,
	 * since it won't do this for flock() locks.
	 */
6591
	switch (request->fl_type) {
6592 6593 6594 6595 6596 6597 6598 6599 6600
	case F_RDLCK:
		if (!(filp->f_mode & FMODE_READ))
			return -EBADF;
		break;
	case F_WRLCK:
		if (!(filp->f_mode & FMODE_WRITE))
			return -EBADF;
	}

6601 6602 6603 6604
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		return status;

6605
	return nfs4_retry_setlk(state, cmd, request);
L
Linus Torvalds 已提交
6606 6607
}

6608
int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid)
6609 6610 6611 6612 6613 6614
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	int err;

	err = nfs4_set_lock_state(state, fl);
	if (err != 0)
6615
		return err;
6616
	err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
6617
	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
6618
}
6619

6620 6621
struct nfs_release_lockowner_data {
	struct nfs4_lock_state *lsp;
6622
	struct nfs_server *server;
6623
	struct nfs_release_lockowner_args args;
6624
	struct nfs_release_lockowner_res res;
6625
	unsigned long timestamp;
6626 6627
};

6628 6629 6630
static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs_release_lockowner_data *data = calldata;
6631
	struct nfs_server *server = data->server;
6632 6633
	nfs40_setup_sequence(server->nfs_client->cl_slot_tbl,
			     &data->args.seq_args, &data->res.seq_res, task);
6634
	data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
6635
	data->timestamp = jiffies;
6636 6637 6638 6639 6640
}

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

6643
	nfs40_sequence_done(task, &data->res.seq_res);
6644 6645 6646 6647 6648 6649 6650

	switch (task->tk_status) {
	case 0:
		renew_lease(server, data->timestamp);
		break;
	case -NFS4ERR_STALE_CLIENTID:
	case -NFS4ERR_EXPIRED:
6651 6652
		nfs4_schedule_lease_recovery(server->nfs_client);
		break;
6653 6654
	case -NFS4ERR_LEASE_MOVED:
	case -NFS4ERR_DELAY:
6655 6656
		if (nfs4_async_handle_error(task, server,
					    NULL, NULL) == -EAGAIN)
6657 6658
			rpc_restart_call_prepare(task);
	}
6659 6660
}

6661 6662
static void nfs4_release_lockowner_release(void *calldata)
{
6663
	struct nfs_release_lockowner_data *data = calldata;
6664
	nfs4_free_lock_state(data->server, data->lsp);
6665 6666 6667
	kfree(calldata);
}

6668
static const struct rpc_call_ops nfs4_release_lockowner_ops = {
6669 6670
	.rpc_call_prepare = nfs4_release_lockowner_prepare,
	.rpc_call_done = nfs4_release_lockowner_done,
6671 6672 6673
	.rpc_release = nfs4_release_lockowner_release,
};

6674 6675
static void
nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
6676
{
6677
	struct nfs_release_lockowner_data *data;
6678 6679 6680 6681 6682
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
	};

	if (server->nfs_client->cl_mvops->minor_version != 0)
6683
		return;
6684

6685 6686
	data = kmalloc(sizeof(*data), GFP_NOFS);
	if (!data)
6687
		return;
6688
	data->lsp = lsp;
6689
	data->server = server;
6690 6691 6692
	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;
6693

6694
	msg.rpc_argp = &data->args;
6695 6696
	msg.rpc_resp = &data->res;
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
6697
	rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
6698 6699
}

6700 6701
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"

6702
static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
6703 6704 6705
				   struct dentry *unused, struct inode *inode,
				   const char *key, const void *buf,
				   size_t buflen, int flags)
6706
{
6707
	return nfs4_proc_set_acl(inode, buf, buflen);
6708 6709
}

6710
static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
6711 6712
				   struct dentry *unused, struct inode *inode,
				   const char *key, void *buf, size_t buflen)
6713
{
6714
	return nfs4_proc_get_acl(inode, buf, buflen);
6715 6716
}

6717
static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
6718
{
6719
	return nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry)));
6720 6721
}

6722 6723
#ifdef CONFIG_NFS_V4_SECURITY_LABEL

6724
static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
6725 6726 6727
				     struct dentry *unused, struct inode *inode,
				     const char *key, const void *buf,
				     size_t buflen, int flags)
6728 6729
{
	if (security_ismaclabel(key))
6730
		return nfs4_set_security_label(inode, buf, buflen);
6731 6732 6733 6734

	return -EOPNOTSUPP;
}

6735
static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler,
6736 6737
				     struct dentry *unused, struct inode *inode,
				     const char *key, void *buf, size_t buflen)
6738 6739
{
	if (security_ismaclabel(key))
6740
		return nfs4_get_security_label(inode, buf, buflen);
6741 6742 6743
	return -EOPNOTSUPP;
}

6744 6745
static ssize_t
nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
6746
{
6747
	int len = 0;
6748

6749 6750 6751 6752
	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;
6753 6754 6755 6756 6757 6758 6759 6760 6761 6762
	}
	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,
};

6763 6764 6765 6766 6767 6768 6769 6770 6771
#else

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

#endif
6772

6773 6774 6775
/*
 * nfs_fhget will use either the mounted_on_fileid or the fileid
 */
6776 6777
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
{
6778 6779 6780
	if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) ||
	       (fattr->valid & NFS_ATTR_FATTR_FILEID)) &&
	      (fattr->valid & NFS_ATTR_FATTR_FSID) &&
6781
	      (fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS)))
6782 6783 6784
		return;

	fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
6785
		NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_V4_REFERRAL;
6786 6787 6788 6789
	fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
	fattr->nlink = 2;
}

6790 6791 6792 6793
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)
6794 6795
{
	struct nfs_server *server = NFS_SERVER(dir);
6796
	u32 bitmask[3] = {
6797
		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
6798 6799 6800
	};
	struct nfs4_fs_locations_arg args = {
		.dir_fh = NFS_FH(dir),
6801
		.name = name,
6802 6803 6804
		.page = page,
		.bitmask = bitmask,
	};
B
Benny Halevy 已提交
6805 6806 6807
	struct nfs4_fs_locations_res res = {
		.fs_locations = fs_locations,
	};
6808 6809 6810
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
		.rpc_argp = &args,
B
Benny Halevy 已提交
6811
		.rpc_resp = &res,
6812 6813 6814
	};
	int status;

6815
	dprintk("%s: start\n", __func__);
6816 6817 6818 6819 6820 6821 6822 6823

	/* 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)
		bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
	else
		bitmask[0] |= FATTR4_WORD0_FILEID;

6824
	nfs_fattr_init(&fs_locations->fattr);
6825
	fs_locations->server = server;
6826
	fs_locations->nlocations = 0;
6827
	status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0);
6828
	dprintk("%s: returned status = %d\n", __func__, status);
6829 6830 6831
	return status;
}

6832 6833 6834 6835
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)
6836 6837 6838 6839
{
	struct nfs4_exception exception = { };
	int err;
	do {
6840 6841 6842 6843
		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,
6844 6845 6846 6847 6848
				&exception);
	} while (exception.retry);
	return err;
}

6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999
/*
 * 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;
}

7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 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
/*
 * 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;
}

7126
/**
7127 7128 7129 7130 7131
 * 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.
7132
 */
7133
static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors, bool use_integrity)
B
Bryan Schumaker 已提交
7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147
{
	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,
	};
7148
	struct rpc_clnt *clnt = NFS_SERVER(dir)->client;
7149
	struct rpc_cred *cred = NULL;
7150 7151 7152

	if (use_integrity) {
		clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient;
7153 7154
		cred = nfs4_get_clid_cred(NFS_SERVER(dir)->nfs_client);
		msg.rpc_cred = cred;
7155
	}
B
Bryan Schumaker 已提交
7156 7157

	dprintk("NFS call  secinfo %s\n", name->name);
7158 7159 7160 7161

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

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

7166 7167
	if (cred)
		put_rpccred(cred);
7168

B
Bryan Schumaker 已提交
7169 7170 7171
	return status;
}

7172 7173
int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
		      struct nfs4_secinfo_flavors *flavors)
B
Bryan Schumaker 已提交
7174 7175 7176 7177
{
	struct nfs4_exception exception = { };
	int err;
	do {
7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192
		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);

7193 7194
		trace_nfs4_secinfo(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
B
Bryan Schumaker 已提交
7195 7196 7197 7198 7199
				&exception);
	} while (exception.retry);
	return err;
}

7200
#ifdef CONFIG_NFS_V4_1
7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219
/*
 * 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;
}

7220
static bool
7221 7222
nfs41_same_server_scope(struct nfs41_server_scope *a,
			struct nfs41_server_scope *b)
7223 7224 7225 7226 7227 7228 7229 7230
{
	if (a->server_scope_sz == b->server_scope_sz &&
	    memcmp(a->server_scope, b->server_scope, a->server_scope_sz) == 0)
		return true;

	return false;
}

7231 7232 7233 7234 7235 7236 7237 7238 7239
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,
};

7240
/*
7241
 * nfs4_proc_bind_one_conn_to_session()
7242 7243 7244 7245
 *
 * The 4.1 client currently uses the same TCP connection for the
 * fore and backchannel.
 */
7246 7247 7248 7249 7250
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)
7251 7252
{
	int status;
7253 7254 7255 7256
	struct nfs41_bind_conn_to_session_args args = {
		.client = clp,
		.dir = NFS4_CDFC4_FORE_OR_BOTH,
	};
7257 7258 7259 7260
	struct nfs41_bind_conn_to_session_res res;
	struct rpc_message msg = {
		.rpc_proc =
			&nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
7261
		.rpc_argp = &args,
7262
		.rpc_resp = &res,
7263
		.rpc_cred = cred,
7264
	};
7265 7266 7267
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clnt,
		.rpc_xprt = xprt,
7268
		.callback_ops = &nfs4_bind_one_conn_to_session_ops,
7269 7270 7271 7272
		.rpc_message = &msg,
		.flags = RPC_TASK_TIMEOUT,
	};
	struct rpc_task *task;
7273 7274 7275

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

7276 7277 7278
	nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
	if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
		args.dir = NFS4_CDFC4_FORE;
7279

7280 7281 7282 7283 7284 7285 7286 7287 7288 7289
	/* 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);
7290
	trace_nfs4_bind_conn_to_session(clp, status);
7291
	if (status == 0) {
7292
		if (memcmp(res.sessionid.data,
7293 7294 7295
		    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
			dprintk("NFS: %s: Session ID mismatch\n", __func__);
			status = -EIO;
7296
			goto out;
7297
		}
7298
		if ((res.dir & args.dir) != res.dir || res.dir == 0) {
7299 7300 7301
			dprintk("NFS: %s: Unexpected direction from server\n",
				__func__);
			status = -EIO;
7302
			goto out;
7303
		}
7304
		if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
7305 7306 7307
			dprintk("NFS: %s: Server returned RDMA mode = true\n",
				__func__);
			status = -EIO;
7308
			goto out;
7309 7310 7311 7312 7313 7314 7315
		}
	}
out:
	dprintk("<-- %s status= %d\n", __func__, status);
	return status;
}

7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340
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 已提交
7341
/*
7342 7343
 * 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
7344 7345 7346 7347 7348 7349 7350 7351 7352
 */
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)
7353 7354 7355
	},
	.allow.u.words = {
		[0] = 1 << (OP_CLOSE) |
7356
		      1 << (OP_OPEN_DOWNGRADE) |
7357
		      1 << (OP_LOCKU) |
7358
		      1 << (OP_DELEGRETURN) |
7359
		      1 << (OP_COMMIT),
7360
		[1] = 1 << (OP_SECINFO - 32) |
7361
		      1 << (OP_SECINFO_NO_NAME - 32) |
7362
		      1 << (OP_LAYOUTRETURN - 32) |
7363
		      1 << (OP_TEST_STATEID - 32) |
7364 7365
		      1 << (OP_FREE_STATEID - 32) |
		      1 << (OP_WRITE - 32)
7366 7367 7368 7369 7370 7371
	}
};

/*
 * Select the state protection mode for client `clp' given the server results
 * from exchange_id in `sp'.
B
Benny Halevy 已提交
7372
 *
7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424
 * 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)
	};
	unsigned int i;

	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");
				return -EINVAL;
			}
		}

		/*
		 * 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");
			set_bit(NFS_SP4_MACH_CRED_MINIMAL, &clp->cl_sp4_flags);
		} else {
			dfprintk(MOUNT, "sp4_mach_cred: disabled\n");
			return -EINVAL;
		}
7425 7426

		if (test_bit(OP_CLOSE, sp->allow.u.longs) &&
7427 7428
		    test_bit(OP_OPEN_DOWNGRADE, sp->allow.u.longs) &&
		    test_bit(OP_DELEGRETURN, sp->allow.u.longs) &&
7429 7430 7431 7432
		    test_bit(OP_LOCKU, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  cleanup mode enabled\n");
			set_bit(NFS_SP4_MACH_CRED_CLEANUP, &clp->cl_sp4_flags);
		}
7433

7434 7435 7436 7437 7438 7439
		if (test_bit(OP_LAYOUTRETURN, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  pnfs cleanup mode enabled\n");
			set_bit(NFS_SP4_MACH_CRED_PNFS_CLEANUP,
				&clp->cl_sp4_flags);
		}

7440 7441 7442 7443 7444
		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");
			set_bit(NFS_SP4_MACH_CRED_SECINFO, &clp->cl_sp4_flags);
		}
7445 7446 7447 7448 7449 7450

		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");
			set_bit(NFS_SP4_MACH_CRED_STATEID, &clp->cl_sp4_flags);
		}
7451 7452 7453 7454 7455 7456 7457 7458 7459 7460

		if (test_bit(OP_WRITE, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  write mode enabled\n");
			set_bit(NFS_SP4_MACH_CRED_WRITE, &clp->cl_sp4_flags);
		}

		if (test_bit(OP_COMMIT, sp->allow.u.longs)) {
			dfprintk(MOUNT, "  commit mode enabled\n");
			set_bit(NFS_SP4_MACH_CRED_COMMIT, &clp->cl_sp4_flags);
		}
7461 7462 7463 7464 7465
	}

	return 0;
}

A
Andy Adamson 已提交
7466 7467 7468
struct nfs41_exchange_id_data {
	struct nfs41_exchange_id_res res;
	struct nfs41_exchange_id_args args;
7469
	struct rpc_xprt *xprt;
A
Andy Adamson 已提交
7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483
	int rpc_status;
};

static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
{
	struct nfs41_exchange_id_data *cdata =
					(struct nfs41_exchange_id_data *)data;
	struct nfs_client *clp = cdata->args.client;
	int status = task->tk_status;

	trace_nfs4_exchange_id(clp, status);

	if (status == 0)
		status = nfs4_check_cl_exchange_flags(cdata->res.flags);
7484 7485 7486 7487 7488 7489 7490

	if (cdata->xprt && status == 0) {
		status = nfs4_detect_session_trunking(clp, &cdata->res,
						      cdata->xprt);
		goto out;
	}

A
Andy Adamson 已提交
7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526
	if (status  == 0)
		status = nfs4_sp4_select_mode(clp, &cdata->res.state_protect);

	if (status == 0) {
		clp->cl_clientid = cdata->res.clientid;
		clp->cl_exchange_flags = cdata->res.flags;
		/* Client ID is not confirmed */
		if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) {
			clear_bit(NFS4_SESSION_ESTABLISHED,
			&clp->cl_session->session_state);
			clp->cl_seqid = cdata->res.seqid;
		}

		kfree(clp->cl_serverowner);
		clp->cl_serverowner = cdata->res.server_owner;
		cdata->res.server_owner = NULL;

		/* use the most recent implementation id */
		kfree(clp->cl_implid);
		clp->cl_implid = cdata->res.impl_id;
		cdata->res.impl_id = NULL;

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

		if (clp->cl_serverscope == NULL) {
			clp->cl_serverscope = cdata->res.server_scope;
			cdata->res.server_scope = NULL;
		}
7527 7528 7529
		/* Save the EXCHANGE_ID verifier session trunk tests */
		memcpy(clp->cl_confirm.data, cdata->args.verifier->data,
		       sizeof(clp->cl_confirm.data));
A
Andy Adamson 已提交
7530
	}
7531
out:
A
Andy Adamson 已提交
7532
	cdata->rpc_status = status;
7533
	return;
A
Andy Adamson 已提交
7534 7535 7536 7537 7538 7539 7540 7541
}

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

	nfs_put_client(cdata->args.client);
7542 7543 7544 7545
	if (cdata->xprt) {
		xprt_put(cdata->xprt);
		rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
	}
A
Andy Adamson 已提交
7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556
	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_call_done = nfs4_exchange_id_done,
	.rpc_release = nfs4_exchange_id_release,
};

7557 7558
/*
 * _nfs4_proc_exchange_id()
7559
 *
7560
 * Wrapper for EXCHANGE_ID operation.
B
Benny Halevy 已提交
7561
 */
7562
static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
7563
			u32 sp4_how, struct rpc_xprt *xprt)
B
Benny Halevy 已提交
7564 7565 7566 7567 7568 7569
{
	nfs4_verifier verifier;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID],
		.rpc_cred = cred,
	};
A
Andy Adamson 已提交
7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.callback_ops = &nfs4_exchange_id_call_ops,
		.rpc_message = &msg,
		.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
	};
	struct nfs41_exchange_id_data *calldata;
	struct rpc_task *task;
	int status = -EIO;

	if (!atomic_inc_not_zero(&clp->cl_count))
		goto out;

	status = -ENOMEM;
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
	if (!calldata)
		goto out;
B
Benny Halevy 已提交
7587

7588 7589
	if (!xprt)
		nfs4_init_boot_verifier(clp, &verifier);
7590 7591 7592

	status = nfs4_init_uniform_client_string(clp);
	if (status)
A
Andy Adamson 已提交
7593
		goto out_calldata;
7594 7595

	dprintk("NFS call  exchange_id auth=%s, '%s'\n",
7596
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
7597
		clp->cl_owner_id);
B
Benny Halevy 已提交
7598

A
Andy Adamson 已提交
7599 7600 7601 7602 7603
	calldata->res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
						GFP_NOFS);
	status = -ENOMEM;
	if (unlikely(calldata->res.server_owner == NULL))
		goto out_calldata;
7604

A
Andy Adamson 已提交
7605
	calldata->res.server_scope = kzalloc(sizeof(struct nfs41_server_scope),
7606
					GFP_NOFS);
A
Andy Adamson 已提交
7607
	if (unlikely(calldata->res.server_scope == NULL))
7608
		goto out_server_owner;
7609

A
Andy Adamson 已提交
7610 7611
	calldata->res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_NOFS);
	if (unlikely(calldata->res.impl_id == NULL))
7612 7613
		goto out_server_scope;

7614 7615
	switch (sp4_how) {
	case SP4_NONE:
A
Andy Adamson 已提交
7616
		calldata->args.state_protect.how = SP4_NONE;
7617 7618 7619
		break;

	case SP4_MACH_CRED:
A
Andy Adamson 已提交
7620
		calldata->args.state_protect = nfs4_sp4_mach_cred_request;
7621 7622 7623 7624 7625 7626
		break;

	default:
		/* unsupported! */
		WARN_ON_ONCE(1);
		status = -EINVAL;
7627
		goto out_impl_id;
7628
	}
7629 7630 7631 7632 7633 7634 7635 7636 7637
	if (xprt) {
		calldata->xprt = xprt;
		task_setup_data.rpc_xprt = xprt;
		task_setup_data.flags =
				RPC_TASK_SOFT|RPC_TASK_SOFTCONN|RPC_TASK_ASYNC;
		calldata->args.verifier = &clp->cl_confirm;
	} else {
		calldata->args.verifier = &verifier;
	}
A
Andy Adamson 已提交
7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649
	calldata->args.client = clp;
#ifdef CONFIG_NFS_V4_1_MIGRATION
	calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
	EXCHGID4_FLAG_BIND_PRINC_STATEID |
	EXCHGID4_FLAG_SUPP_MOVED_MIGR,
#else
	calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
	EXCHGID4_FLAG_BIND_PRINC_STATEID,
#endif
	msg.rpc_argp = &calldata->args;
	msg.rpc_resp = &calldata->res;
	task_setup_data.callback_data = calldata;
7650

A
Andy Adamson 已提交
7651 7652 7653 7654
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task)) {
	status = PTR_ERR(task);
		goto out_impl_id;
7655
	}
7656

7657 7658 7659 7660 7661
	if (!xprt) {
		status = rpc_wait_for_completion_task(task);
		if (!status)
			status = calldata->rpc_status;
	} else	/* session trunking test */
A
Andy Adamson 已提交
7662
		status = calldata->rpc_status;
7663

A
Andy Adamson 已提交
7664
	rpc_put_task(task);
7665
out:
7666
	if (clp->cl_implid != NULL)
7667
		dprintk("NFS reply exchange_id: Server Implementation ID: "
7668
			"domain: %s, name: %s, date: %llu,%u\n",
7669
			clp->cl_implid->domain, clp->cl_implid->name,
7670 7671
			clp->cl_implid->date.seconds,
			clp->cl_implid->date.nseconds);
7672
	dprintk("NFS reply exchange_id: %d\n", status);
B
Benny Halevy 已提交
7673
	return status;
A
Andy Adamson 已提交
7674 7675 7676 7677 7678 7679 7680 7681 7682 7683

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);
	goto out;
B
Benny Halevy 已提交
7684 7685
}

7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705
/*
 * 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) {
7706
		status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED, NULL);
7707 7708 7709 7710 7711
		if (!status)
			return 0;
	}

	/* try SP4_NONE */
7712
	return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL);
7713 7714
}

7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742
/**
 * 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;
	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 */
	return  _nfs4_proc_exchange_id(adata->clp, adata->cred, sp4_how, xprt);
7743
}
7744
EXPORT_SYMBOL_GPL(nfs4_test_session_trunk);
7745

T
Trond Myklebust 已提交
7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756
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);
7757
	trace_nfs4_destroy_clientid(clp, status);
T
Trond Myklebust 已提交
7758
	if (status)
7759
		dprintk("NFS: Got error %d from the server %s on "
T
Trond Myklebust 已提交
7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792
			"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;
7793 7794
	if (clp->cl_preserve_clid)
		goto out;
7795
	cred = nfs4_get_clid_cred(clp);
T
Trond Myklebust 已提交
7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807
	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 已提交
7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822
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 */
7823 7824 7825 7826
	nfs41_setup_sequence(data->clp->cl_session,
			&data->args->la_seq_args,
			&data->res->lr_seq_res,
			task);
A
Andy Adamson 已提交
7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839
	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__);
7840 7841
	if (!nfs41_sequence_done(task, &data->res->lr_seq_res))
		return;
A
Andy Adamson 已提交
7842 7843 7844 7845 7846 7847
	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;
7848 7849
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
7850
		rpc_restart_call_prepare(task);
A
Andy Adamson 已提交
7851 7852 7853 7854 7855
		return;
	}
	dprintk("<-- %s\n", __func__);
}

7856
static const struct rpc_call_ops nfs4_get_lease_time_ops = {
A
Andy Adamson 已提交
7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881
	.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,
7882 7883
		.callback_data = &data,
		.flags = RPC_TASK_TIMEOUT,
A
Andy Adamson 已提交
7884 7885 7886
	};
	int status;

7887
	nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
7888
	nfs4_set_sequence_privileged(&args.la_seq_args);
A
Andy Adamson 已提交
7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902
	dprintk("--> %s\n", __func__);
	task = rpc_run_task(&task_setup);

	if (IS_ERR(task))
		status = PTR_ERR(task);
	else {
		status = task->tk_status;
		rpc_put_task(task);
	}
	dprintk("<-- %s return %d\n", __func__, status);

	return status;
}

A
Andy Adamson 已提交
7903 7904 7905 7906 7907 7908 7909 7910 7911
/*
 * 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.
 */
7912 7913
static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args,
				    struct rpc_clnt *clnt)
A
Andy Adamson 已提交
7914
{
7915
	unsigned int max_rqst_sz, max_resp_sz;
7916
	unsigned int max_bc_payload = rpc_max_bc_payload(clnt);
7917 7918 7919

	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 已提交
7920 7921

	/* Fore channel attributes */
7922 7923
	args->fc_attrs.max_rqst_sz = max_rqst_sz;
	args->fc_attrs.max_resp_sz = max_resp_sz;
A
Andy Adamson 已提交
7924
	args->fc_attrs.max_ops = NFS4_MAX_OPS;
7925
	args->fc_attrs.max_reqs = max_session_slots;
A
Andy Adamson 已提交
7926 7927

	dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
7928
		"max_ops=%u max_reqs=%u\n",
A
Andy Adamson 已提交
7929 7930
		__func__,
		args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
7931
		args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
A
Andy Adamson 已提交
7932 7933

	/* Back channel attributes */
7934 7935
	args->bc_attrs.max_rqst_sz = max_bc_payload;
	args->bc_attrs.max_resp_sz = max_bc_payload;
A
Andy Adamson 已提交
7936 7937
	args->bc_attrs.max_resp_sz_cached = 0;
	args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
7938
	args->bc_attrs.max_reqs = min_t(unsigned short, max_session_cb_slots, 1);
A
Andy Adamson 已提交
7939 7940 7941 7942 7943 7944 7945 7946 7947

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

7948 7949
static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
		struct nfs41_create_session_res *res)
7950
{
7951
	struct nfs4_channel_attrs *sent = &args->fc_attrs;
7952
	struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965

	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;
7966 7967
	if (rcvd->max_reqs > NFS4_MAX_SLOT_TABLE)
		rcvd->max_reqs = NFS4_MAX_SLOT_TABLE;
7968
	return 0;
7969 7970
}

7971 7972
static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
		struct nfs41_create_session_res *res)
7973 7974
{
	struct nfs4_channel_attrs *sent = &args->bc_attrs;
7975
	struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
7976

7977 7978
	if (!(res->flags & SESSION4_BACK_CHAN))
		goto out;
7979 7980 7981 7982 7983 7984
	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;
7985
	if (rcvd->max_ops > sent->max_ops)
7986
		return -EINVAL;
7987
	if (rcvd->max_reqs > sent->max_reqs)
7988
		return -EINVAL;
7989
out:
7990 7991
	return 0;
}
7992 7993

static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
7994
				     struct nfs41_create_session_res *res)
7995
{
7996
	int ret;
7997

7998
	ret = nfs4_verify_fore_channel_attrs(args, res);
7999 8000
	if (ret)
		return ret;
8001 8002 8003 8004 8005 8006 8007
	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);
8008 8009 8010
	/* 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);
8011 8012
	session->flags = res->flags;
	memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
8013 8014 8015
	if (res->flags & SESSION4_BACK_CHAN)
		memcpy(&session->bc_attrs, &res->bc_attrs,
				sizeof(session->bc_attrs));
8016 8017
}

8018 8019
static int _nfs4_proc_create_session(struct nfs_client *clp,
		struct rpc_cred *cred)
A
Andy Adamson 已提交
8020 8021 8022 8023
{
	struct nfs4_session *session = clp->cl_session;
	struct nfs41_create_session_args args = {
		.client = clp,
8024 8025
		.clientid = clp->cl_clientid,
		.seqid = clp->cl_seqid,
A
Andy Adamson 已提交
8026 8027
		.cb_program = NFS4_CALLBACK,
	};
8028 8029
	struct nfs41_create_session_res res;

A
Andy Adamson 已提交
8030 8031 8032 8033
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
		.rpc_argp = &args,
		.rpc_resp = &res,
8034
		.rpc_cred = cred,
A
Andy Adamson 已提交
8035 8036 8037
	};
	int status;

8038
	nfs4_init_channel_attrs(&args, clp->cl_rpcclient);
8039
	args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
A
Andy Adamson 已提交
8040

8041
	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8042
	trace_nfs4_create_session(clp, status);
A
Andy Adamson 已提交
8043

8044 8045 8046 8047 8048 8049 8050 8051 8052 8053
	switch (status) {
	case -NFS4ERR_STALE_CLIENTID:
	case -NFS4ERR_DELAY:
	case -ETIMEDOUT:
	case -EACCES:
	case -EAGAIN:
		goto out;
	};

	clp->cl_seqid++;
8054
	if (!status) {
8055
		/* Verify the session's negotiated channel_attrs values */
8056
		status = nfs4_verify_channel_attrs(&args, &res);
A
Andy Adamson 已提交
8057
		/* Increment the clientid slot sequence id */
8058 8059 8060
		if (status)
			goto out;
		nfs4_update_session(session, &res);
A
Andy Adamson 已提交
8061
	}
8062
out:
A
Andy Adamson 已提交
8063 8064 8065 8066 8067 8068 8069 8070
	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.
 */
8071
int nfs4_proc_create_session(struct nfs_client *clp, struct rpc_cred *cred)
A
Andy Adamson 已提交
8072 8073 8074 8075 8076 8077 8078
{
	int status;
	unsigned *ptr;
	struct nfs4_session *session = clp->cl_session;

	dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);

8079
	status = _nfs4_proc_create_session(clp, cred);
A
Andy Adamson 已提交
8080 8081 8082
	if (status)
		goto out;

8083 8084 8085
	/* 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 已提交
8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096
	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 已提交
8097 8098 8099 8100
/*
 * Issue the over-the-wire RPC DESTROY_SESSION.
 * The caller must serialize access to this routine.
 */
8101 8102
int nfs4_proc_destroy_session(struct nfs4_session *session,
		struct rpc_cred *cred)
A
Andy Adamson 已提交
8103
{
8104 8105 8106 8107 8108
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION],
		.rpc_argp = session,
		.rpc_cred = cred,
	};
A
Andy Adamson 已提交
8109 8110 8111 8112 8113
	int status = 0;

	dprintk("--> nfs4_proc_destroy_session\n");

	/* session is still being setup */
8114 8115
	if (!test_and_clear_bit(NFS4_SESSION_ESTABLISHED, &session->session_state))
		return 0;
A
Andy Adamson 已提交
8116

8117
	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
8118
	trace_nfs4_destroy_session(session->clp, status);
A
Andy Adamson 已提交
8119 8120

	if (status)
8121
		dprintk("NFS: Got error %d from the server on DESTROY_SESSION. "
A
Andy Adamson 已提交
8122 8123 8124 8125 8126 8127
			"Session has been destroyed regardless...\n", status);

	dprintk("<-- nfs4_proc_destroy_session\n");
	return status;
}

A
Andy Adamson 已提交
8128 8129 8130
/*
 * Renew the cl_session lease.
 */
8131 8132 8133 8134 8135 8136
struct nfs4_sequence_data {
	struct nfs_client *clp;
	struct nfs4_sequence_args args;
	struct nfs4_sequence_res res;
};

8137 8138
static void nfs41_sequence_release(void *data)
{
8139 8140
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
8141

8142 8143 8144
	if (atomic_read(&clp->cl_count) > 1)
		nfs4_schedule_state_renewal(clp);
	nfs_put_client(clp);
8145
	kfree(calldata);
8146 8147
}

8148 8149 8150 8151 8152 8153 8154
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:
8155
		nfs4_schedule_lease_recovery(clp);
8156 8157 8158 8159
	}
	return 0;
}

8160
static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
A
Andy Adamson 已提交
8161
{
8162 8163
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
A
Andy Adamson 已提交
8164

8165 8166
	if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp))
		return;
A
Andy Adamson 已提交
8167

8168
	trace_nfs4_sequence(clp, task->tk_status);
A
Andy Adamson 已提交
8169 8170
	if (task->tk_status < 0) {
		dprintk("%s ERROR %d\n", __func__, task->tk_status);
8171 8172
		if (atomic_read(&clp->cl_count) == 1)
			goto out;
A
Andy Adamson 已提交
8173

8174 8175
		if (nfs41_sequence_handle_errors(task, clp) == -EAGAIN) {
			rpc_restart_call_prepare(task);
A
Andy Adamson 已提交
8176 8177 8178 8179
			return;
		}
	}
	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
8180
out:
A
Andy Adamson 已提交
8181 8182 8183 8184 8185
	dprintk("<-- %s\n", __func__);
}

static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
{
8186 8187
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
A
Andy Adamson 已提交
8188 8189 8190 8191 8192 8193
	struct nfs4_sequence_args *args;
	struct nfs4_sequence_res *res;

	args = task->tk_msg.rpc_argp;
	res = task->tk_msg.rpc_resp;

8194
	nfs41_setup_sequence(clp->cl_session, args, res, task);
A
Andy Adamson 已提交
8195 8196 8197 8198 8199
}

static const struct rpc_call_ops nfs41_sequence_ops = {
	.rpc_call_done = nfs41_sequence_call_done,
	.rpc_call_prepare = nfs41_sequence_prepare,
8200
	.rpc_release = nfs41_sequence_release,
A
Andy Adamson 已提交
8201 8202
};

8203 8204 8205
static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
		struct rpc_cred *cred,
		bool is_privileged)
A
Andy Adamson 已提交
8206
{
8207
	struct nfs4_sequence_data *calldata;
A
Andy Adamson 已提交
8208 8209 8210 8211
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
		.rpc_cred = cred,
	};
8212 8213 8214
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.rpc_message = &msg,
8215
		.callback_ops = &nfs41_sequence_ops,
8216
		.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
8217
	};
A
Andy Adamson 已提交
8218

8219
	if (!atomic_inc_not_zero(&clp->cl_count))
8220
		return ERR_PTR(-EIO);
8221
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
8222
	if (calldata == NULL) {
8223
		nfs_put_client(clp);
8224
		return ERR_PTR(-ENOMEM);
A
Andy Adamson 已提交
8225
	}
8226
	nfs4_init_sequence(&calldata->args, &calldata->res, 0);
8227 8228
	if (is_privileged)
		nfs4_set_sequence_privileged(&calldata->args);
8229 8230 8231
	msg.rpc_argp = &calldata->args;
	msg.rpc_resp = &calldata->res;
	calldata->clp = clp;
8232
	task_setup_data.callback_data = calldata;
A
Andy Adamson 已提交
8233

8234 8235 8236
	return rpc_run_task(&task_setup_data);
}

8237
static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
8238 8239 8240 8241
{
	struct rpc_task *task;
	int ret = 0;

8242
	if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
8243
		return -EAGAIN;
8244
	task = _nfs41_proc_sequence(clp, cred, false);
8245 8246 8247
	if (IS_ERR(task))
		ret = PTR_ERR(task);
	else
8248
		rpc_put_task_async(task);
8249 8250 8251 8252 8253 8254 8255 8256 8257
	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;

8258
	task = _nfs41_proc_sequence(clp, cred, true);
8259 8260 8261 8262 8263
	if (IS_ERR(task)) {
		ret = PTR_ERR(task);
		goto out;
	}
	ret = rpc_wait_for_completion_task(task);
8264
	if (!ret)
8265 8266 8267 8268 8269
		ret = task->tk_status;
	rpc_put_task(task);
out:
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
A
Andy Adamson 已提交
8270 8271
}

8272 8273 8274 8275 8276 8277 8278 8279 8280 8281
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;

8282 8283 8284 8285
	nfs41_setup_sequence(calldata->clp->cl_session,
			&calldata->arg.seq_args,
			&calldata->res.seq_res,
			task);
8286 8287
}

8288 8289 8290 8291 8292 8293 8294 8295 8296
static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp)
{
	switch(task->tk_status) {
	case 0:
	case -NFS4ERR_COMPLETE_ALREADY:
	case -NFS4ERR_WRONG_CRED: /* What to do here? */
		break;
	case -NFS4ERR_DELAY:
		rpc_delay(task, NFS4_POLL_RETRY_MAX);
8297 8298
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
8299 8300
		return -EAGAIN;
	default:
8301
		nfs4_schedule_lease_recovery(clp);
8302 8303 8304 8305
	}
	return 0;
}

8306 8307 8308 8309 8310 8311 8312
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__);
8313 8314
	if (!nfs41_sequence_done(task, res))
		return;
8315

8316
	trace_nfs4_reclaim_complete(clp, task->tk_status);
8317 8318 8319 8320
	if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) {
		rpc_restart_call_prepare(task);
		return;
	}
8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339
	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.
 */
8340 8341
static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
		struct rpc_cred *cred)
8342 8343 8344 8345 8346
{
	struct nfs4_reclaim_complete_data *calldata;
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE],
8347
		.rpc_cred = cred,
8348 8349 8350 8351 8352 8353 8354 8355 8356 8357
	};
	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__);
8358
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
8359 8360 8361 8362 8363
	if (calldata == NULL)
		goto out;
	calldata->clp = clp;
	calldata->arg.one_fs = 0;

8364
	nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
8365
	nfs4_set_sequence_privileged(&calldata->arg.seq_args);
8366 8367 8368 8369
	msg.rpc_argp = &calldata->arg;
	msg.rpc_resp = &calldata->res;
	task_setup_data.callback_data = calldata;
	task = rpc_run_task(&task_setup_data);
8370
	if (IS_ERR(task)) {
8371
		status = PTR_ERR(task);
8372 8373
		goto out;
	}
8374 8375 8376
	status = nfs4_wait_for_completion_rpc_task(task);
	if (status == 0)
		status = task->tk_status;
8377
	rpc_put_task(task);
8378
	return 0;
8379 8380 8381 8382
out:
	dprintk("<-- %s status=%d\n", __func__, status);
	return status;
}
8383 8384 8385 8386 8387

static void
nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
F
Fred Isaman 已提交
8388
	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
8389
	struct nfs4_session *session = nfs4_get_session(server);
8390 8391

	dprintk("--> %s\n", __func__);
8392 8393 8394
	nfs41_setup_sequence(session, &lgp->args.seq_args,
				&lgp->res.seq_res, task);
	dprintk("<-- %s\n", __func__);
8395 8396 8397 8398 8399
}

static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
8400 8401

	dprintk("--> %s\n", __func__);
8402
	nfs41_sequence_process(task, &lgp->res.seq_res);
8403 8404 8405 8406 8407 8408 8409
	dprintk("<-- %s\n", __func__);
}

static int
nfs4_layoutget_handle_exception(struct rpc_task *task,
		struct nfs4_layoutget *lgp, struct nfs4_exception *exception)
{
8410 8411 8412
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
	struct pnfs_layout_hdr *lo;
8413 8414
	int nfs4err = task->tk_status;
	int err, status = 0;
8415
	LIST_HEAD(head);
8416

8417
	dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
8418

8419
	switch (nfs4err) {
8420
	case 0:
8421
		goto out;
8422 8423 8424 8425 8426 8427 8428

	/*
	 * 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:
8429
		status = -ENODATA;
8430
		goto out;
8431 8432 8433 8434 8435
	/*
	 * NFS4ERR_BADLAYOUT means the MDS cannot return a layout of
	 * length lgp->args.minlength != 0 (see RFC5661 section 18.43.3).
	 */
	case -NFS4ERR_BADLAYOUT:
8436 8437
		status = -EOVERFLOW;
		goto out;
8438 8439
	/*
	 * NFS4ERR_LAYOUTTRYLATER is a conflict with another client
8440 8441
	 * (or clients) writing to the same RAID stripe except when
	 * the minlength argument is 0 (see RFC5661 section 18.43.3).
8442 8443 8444
	 *
	 * Treat it like we would RECALLCONFLICT -- we retry for a little
	 * while, and then eventually give up.
8445
	 */
8446
	case -NFS4ERR_LAYOUTTRYLATER:
8447 8448 8449
		if (lgp->args.minlength == 0) {
			status = -EOVERFLOW;
			goto out;
8450
		}
8451 8452
		status = -EBUSY;
		break;
8453 8454
	case -NFS4ERR_RECALLCONFLICT:
		status = -ERECALLCONFLICT;
8455
		break;
8456 8457
	case -NFS4ERR_DELEG_REVOKED:
	case -NFS4ERR_ADMIN_REVOKED:
8458 8459
	case -NFS4ERR_EXPIRED:
	case -NFS4ERR_BAD_STATEID:
8460
		exception->timeout = 0;
8461
		spin_lock(&inode->i_lock);
8462 8463 8464 8465
		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) ||
		    nfs4_stateid_match_other(&lgp->args.stateid,
8466
					&lgp->args.ctx->state->stateid)) {
8467
			spin_unlock(&inode->i_lock);
8468
			exception->state = lgp->args.ctx->state;
8469
			exception->stateid = &lgp->args.stateid;
8470 8471
			break;
		}
8472 8473 8474 8475

		/*
		 * Mark the bad layout state as invalid, then retry
		 */
T
Trond Myklebust 已提交
8476
		pnfs_mark_layout_stateid_invalid(lo, &head);
8477 8478 8479 8480
		spin_unlock(&inode->i_lock);
		pnfs_free_lseg_list(&head);
		status = -EAGAIN;
		goto out;
8481
	}
8482

8483 8484 8485 8486 8487 8488 8489
	err = nfs4_handle_exception(server, nfs4err, exception);
	if (!status) {
		if (exception->retry)
			status = -EAGAIN;
		else
			status = err;
	}
8490
out:
8491
	dprintk("<-- %s\n", __func__);
8492
	return status;
8493 8494
}

8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538
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;
}

8539 8540 8541
static void nfs4_layoutget_release(void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
8542 8543
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
8544
	size_t max_pages = max_response_pages(server);
8545 8546

	dprintk("--> %s\n", __func__);
8547
	nfs4_free_pages(lgp->args.layout.pages, max_pages);
8548
	pnfs_put_layout_hdr(NFS_I(inode)->layout);
8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559
	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,
};

8560
struct pnfs_layout_segment *
8561
nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
8562
{
8563 8564
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
8565
	size_t max_pages = max_response_pages(server);
8566 8567 8568 8569 8570
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
		.rpc_argp = &lgp->args,
		.rpc_resp = &lgp->res,
8571
		.rpc_cred = lgp->cred,
8572 8573 8574 8575 8576 8577 8578 8579
	};
	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,
	};
8580
	struct pnfs_layout_segment *lseg = NULL;
8581 8582 8583 8584
	struct nfs4_exception exception = {
		.inode = inode,
		.timeout = *timeout,
	};
8585 8586 8587 8588
	int status = 0;

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

8589 8590 8591
	/* nfs4_layoutget_release calls pnfs_put_layout_hdr */
	pnfs_get_layout_hdr(NFS_I(inode)->layout);

8592 8593 8594
	lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
	if (!lgp->args.layout.pages) {
		nfs4_layoutget_release(lgp);
8595
		return ERR_PTR(-ENOMEM);
8596 8597 8598
	}
	lgp->args.layout.pglen = max_pages * PAGE_SIZE;

8599
	lgp->res.layoutp = &lgp->args.layout;
8600
	lgp->res.seq_res.sr_slot = NULL;
8601
	nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
8602

8603 8604
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
8605
		return ERR_CAST(task);
8606
	status = nfs4_wait_for_completion_rpc_task(task);
8607 8608 8609 8610 8611
	if (status == 0) {
		status = nfs4_layoutget_handle_exception(task, lgp, &exception);
		*timeout = exception.timeout;
	}

8612 8613 8614
	trace_nfs4_layoutget(lgp->args.ctx,
			&lgp->args.range,
			&lgp->res.range,
8615
			&lgp->res.stateid,
8616
			status);
8617

8618 8619
	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
	if (status == 0 && lgp->res.layoutp->len)
8620
		lseg = pnfs_layout_process(lgp);
8621
	nfs4_sequence_free_slot(&lgp->res.seq_res);
8622 8623
	rpc_put_task(task);
	dprintk("<-- %s status=%d\n", __func__, status);
8624 8625 8626
	if (status)
		return ERR_PTR(status);
	return lseg;
8627 8628
}

B
Benny Halevy 已提交
8629 8630 8631 8632 8633 8634
static void
nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;

	dprintk("--> %s\n", __func__);
8635 8636 8637 8638
	nfs41_setup_sequence(lrp->clp->cl_session,
			&lrp->args.seq_args,
			&lrp->res.seq_res,
			task);
B
Benny Halevy 已提交
8639 8640 8641 8642 8643 8644 8645 8646 8647
}

static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;
	struct nfs_server *server;

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

8648
	if (!nfs41_sequence_process(task, &lrp->res.seq_res))
B
Benny Halevy 已提交
8649 8650 8651
		return;

	server = NFS_SERVER(lrp->args.inode);
8652 8653 8654 8655 8656 8657
	switch (task->tk_status) {
	default:
		task->tk_status = 0;
	case 0:
		break;
	case -NFS4ERR_DELAY:
8658
		if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
8659
			break;
8660
		nfs4_sequence_free_slot(&lrp->res.seq_res);
8661
		rpc_restart_call_prepare(task);
B
Benny Halevy 已提交
8662 8663 8664 8665 8666 8667 8668 8669
		return;
	}
	dprintk("<-- %s\n", __func__);
}

static void nfs4_layoutreturn_release(void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;
8670
	struct pnfs_layout_hdr *lo = lrp->args.layout;
B
Benny Halevy 已提交
8671 8672

	dprintk("--> %s\n", __func__);
8673
	pnfs_layoutreturn_free_lsegs(lo, &lrp->args.stateid, &lrp->args.range,
8674
			lrp->res.lrs_present ? &lrp->res.stateid : NULL);
8675
	nfs4_sequence_free_slot(&lrp->res.seq_res);
8676 8677
	if (lrp->ld_private.ops && lrp->ld_private.ops->free)
		lrp->ld_private.ops->free(&lrp->ld_private);
8678 8679
	pnfs_put_layout_hdr(lrp->args.layout);
	nfs_iput_and_deactive(lrp->inode);
B
Benny Halevy 已提交
8680 8681 8682 8683 8684 8685 8686 8687 8688 8689
	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,
};

8690
int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
B
Benny Halevy 已提交
8691 8692 8693 8694 8695 8696
{
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN],
		.rpc_argp = &lrp->args,
		.rpc_resp = &lrp->res,
8697
		.rpc_cred = lrp->cred,
B
Benny Halevy 已提交
8698 8699
	};
	struct rpc_task_setup task_setup_data = {
8700
		.rpc_client = NFS_SERVER(lrp->args.inode)->client,
B
Benny Halevy 已提交
8701 8702 8703 8704
		.rpc_message = &msg,
		.callback_ops = &nfs4_layoutreturn_call_ops,
		.callback_data = lrp,
	};
8705
	int status = 0;
B
Benny Halevy 已提交
8706

8707 8708 8709 8710
	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 已提交
8711
	dprintk("--> %s\n", __func__);
8712 8713 8714 8715 8716 8717 8718 8719
	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;
	}
8720
	nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1);
B
Benny Halevy 已提交
8721 8722 8723
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
		return PTR_ERR(task);
8724 8725
	if (sync)
		status = task->tk_status;
8726
	trace_nfs4_layoutreturn(lrp->args.inode, &lrp->args.stateid, status);
B
Benny Halevy 已提交
8727 8728 8729 8730 8731
	dprintk("<-- %s status=%d\n", __func__, status);
	rpc_put_task(task);
	return status;
}

8732
static int
8733 8734 8735
_nfs4_proc_getdeviceinfo(struct nfs_server *server,
		struct pnfs_device *pdev,
		struct rpc_cred *cred)
8736 8737 8738
{
	struct nfs4_getdeviceinfo_args args = {
		.pdev = pdev,
8739 8740
		.notify_types = NOTIFY_DEVICEID4_CHANGE |
			NOTIFY_DEVICEID4_DELETE,
8741 8742 8743 8744 8745 8746 8747 8748
	};
	struct nfs4_getdeviceinfo_res res = {
		.pdev = pdev,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO],
		.rpc_argp = &args,
		.rpc_resp = &res,
8749
		.rpc_cred = cred,
8750 8751 8752 8753
	};
	int status;

	dprintk("--> %s\n", __func__);
8754
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
8755 8756
	if (res.notification & ~args.notify_types)
		dprintk("%s: unsupported notification\n", __func__);
8757 8758
	if (res.notification != args.notify_types)
		pdev->nocache = 1;
8759

8760 8761 8762 8763 8764
	dprintk("<-- %s status=%d\n", __func__, status);

	return status;
}

8765 8766 8767
int nfs4_proc_getdeviceinfo(struct nfs_server *server,
		struct pnfs_device *pdev,
		struct rpc_cred *cred)
8768 8769 8770 8771 8772 8773
{
	struct nfs4_exception exception = { };
	int err;

	do {
		err = nfs4_handle_exception(server,
8774
					_nfs4_proc_getdeviceinfo(server, pdev, cred),
8775 8776 8777 8778 8779 8780
					&exception);
	} while (exception.retry);
	return err;
}
EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);

A
Andy Adamson 已提交
8781 8782 8783 8784
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);
8785
	struct nfs4_session *session = nfs4_get_session(server);
A
Andy Adamson 已提交
8786

8787 8788 8789 8790
	nfs41_setup_sequence(session,
			&data->args.seq_args,
			&data->res.seq_res,
			task);
A
Andy Adamson 已提交
8791 8792 8793 8794 8795 8796 8797 8798
}

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

8799
	if (!nfs41_sequence_done(task, &data->res.seq_res))
A
Andy Adamson 已提交
8800 8801 8802
		return;

	switch (task->tk_status) { /* Just ignore these failures */
8803 8804 8805 8806
	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 已提交
8807
		task->tk_status = 0;
8808 8809 8810
	case 0:
		break;
	default:
8811
		if (nfs4_async_handle_error(task, server, NULL, NULL) == -EAGAIN) {
8812 8813 8814 8815
			rpc_restart_call_prepare(task);
			return;
		}
	}
A
Andy Adamson 已提交
8816 8817 8818 8819 8820 8821
}

static void nfs4_layoutcommit_release(void *calldata)
{
	struct nfs4_layoutcommit_data *data = calldata;

A
Andy Adamson 已提交
8822
	pnfs_cleanup_layoutcommit(data);
8823 8824
	nfs_post_op_update_inode_force_wcc(data->args.inode,
					   data->res.fattr);
A
Andy Adamson 已提交
8825
	put_rpccred(data->cred);
8826
	nfs_iput_and_deactive(data->inode);
A
Andy Adamson 已提交
8827 8828 8829 8830 8831 8832 8833 8834 8835 8836
	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
8837
nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
A
Andy Adamson 已提交
8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854
{
	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;

8855 8856
	dprintk("NFS: initiating layoutcommit call. sync %d "
		"lbw: %llu inode %lu\n", sync,
A
Andy Adamson 已提交
8857 8858 8859
		data->args.lastbytewritten,
		data->args.inode->i_ino);

8860 8861 8862 8863 8864 8865 8866 8867
	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;
	}
8868
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
A
Andy Adamson 已提交
8869 8870 8871
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
		return PTR_ERR(task);
8872 8873
	if (sync)
		status = task->tk_status;
8874
	trace_nfs4_layoutcommit(data->args.inode, &data->args.stateid, status);
A
Andy Adamson 已提交
8875 8876 8877 8878
	dprintk("%s: status %d\n", __func__, status);
	rpc_put_task(task);
	return status;
}
8879

8880 8881 8882 8883
/**
 * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
 * possible) as per RFC3530bis and RFC5661 Security Considerations sections
 */
8884 8885
static int
_nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
8886 8887
		    struct nfs_fsinfo *info,
		    struct nfs4_secinfo_flavors *flavors, bool use_integrity)
8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899
{
	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,
	};
8900
	struct rpc_clnt *clnt = server->client;
8901
	struct rpc_cred *cred = NULL;
8902 8903 8904 8905
	int status;

	if (use_integrity) {
		clnt = server->nfs_client->cl_rpcclient;
8906 8907
		cred = nfs4_get_clid_cred(server->nfs_client);
		msg.rpc_cred = cred;
8908 8909 8910 8911 8912 8913 8914
	}

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

8915 8916
	if (cred)
		put_rpccred(cred);
8917 8918

	return status;
8919 8920 8921 8922 8923 8924 8925 8926 8927
}

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 {
8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945
		/* 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);

8946 8947 8948
		switch (err) {
		case 0:
		case -NFS4ERR_WRONGSEC:
8949
		case -ENOTSUPP:
8950
			goto out;
8951 8952 8953 8954
		default:
			err = nfs4_handle_exception(server, err, &exception);
		}
	} while (exception.retry);
8955
out:
8956 8957 8958 8959 8960 8961 8962 8963 8964
	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;
8965
	rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR;
8966
	struct nfs4_secinfo_flavors *flavors;
8967 8968
	struct nfs4_secinfo4 *secinfo;
	int i;
8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982

	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
	 */
8983
	if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) {
8984 8985 8986 8987 8988 8989
		err = nfs4_find_root_sec(server, fhandle, info);
		goto out_freepage;
	}
	if (err)
		goto out_freepage;

8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004
	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;
		}

9005 9006 9007
		if (!nfs_auth_info_match(&server->auth_info, flavor))
			flavor = RPC_AUTH_MAXFLAVOR;

9008 9009 9010 9011 9012 9013 9014 9015 9016 9017
		if (flavor != RPC_AUTH_MAXFLAVOR) {
			err = nfs4_lookup_root_sec(server, fhandle,
						   info, flavor);
			if (!err)
				break;
		}
	}

	if (flavor == RPC_AUTH_MAXFLAVOR)
		err = -EPERM;
9018 9019 9020 9021 9022 9023 9024 9025

out_freepage:
	put_page(page);
	if (err == -EACCES)
		return -EPERM;
out:
	return err;
}
9026

9027 9028 9029
static int _nfs41_test_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
9030 9031 9032
{
	int status;
	struct nfs41_test_stateid_args args = {
9033
		.stateid = stateid,
B
Bryan Schumaker 已提交
9034 9035 9036 9037 9038 9039
	};
	struct nfs41_test_stateid_res res;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID],
		.rpc_argp = &args,
		.rpc_resp = &res,
9040
		.rpc_cred = cred,
B
Bryan Schumaker 已提交
9041
	};
9042 9043 9044 9045
	struct rpc_clnt *rpc_client = server->client;

	nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
		&rpc_client, &msg);
9046

9047
	dprintk("NFS call  test_stateid %p\n", stateid);
9048
	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
9049
	nfs4_set_sequence_privileged(&args.seq_args);
9050
	status = nfs4_call_sync_sequence(rpc_client, server, &msg,
9051
			&args.seq_args, &res.seq_res);
9052 9053
	if (status != NFS_OK) {
		dprintk("NFS reply test_stateid: failed, %d\n", status);
9054
		return status;
9055 9056
	}
	dprintk("NFS reply test_stateid: succeeded, %d\n", -res.status);
9057
	return -res.status;
B
Bryan Schumaker 已提交
9058 9059
}

9060 9061 9062 9063 9064 9065
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:
9066
	case -NFS4ERR_RETRY_UNCACHED_REP:
9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077
		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);
	}
}

9078 9079 9080 9081 9082
/**
 * nfs41_test_stateid - perform a TEST_STATEID operation
 *
 * @server: server / transport on which to perform the operation
 * @stateid: state ID to test
9083
 * @cred: credential
9084 9085 9086 9087 9088
 *
 * 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.
 */
9089 9090 9091
static int nfs41_test_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
9092 9093 9094 9095
{
	struct nfs4_exception exception = { };
	int err;
	do {
9096
		err = _nfs41_test_stateid(server, stateid, cred);
9097
		nfs4_handle_delay_or_session_error(server, err, &exception);
B
Bryan Schumaker 已提交
9098 9099 9100
	} while (exception.retry);
	return err;
}
B
Bryan Schumaker 已提交
9101

9102 9103 9104
struct nfs_free_stateid_data {
	struct nfs_server *server;
	struct nfs41_free_stateid_args args;
B
Bryan Schumaker 已提交
9105
	struct nfs41_free_stateid_res res;
9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124
};

static void nfs41_free_stateid_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs_free_stateid_data *data = calldata;
	nfs41_setup_sequence(nfs4_get_session(data->server),
			&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:
9125
		if (nfs4_async_handle_error(task, data->server, NULL, NULL) == -EAGAIN)
9126 9127 9128 9129 9130 9131 9132 9133 9134
			rpc_restart_call_prepare(task);
	}
}

static void nfs41_free_stateid_release(void *calldata)
{
	kfree(calldata);
}

9135
static const struct rpc_call_ops nfs41_free_stateid_ops = {
9136 9137 9138 9139 9140 9141
	.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,
9142
		const nfs4_stateid *stateid,
9143
		struct rpc_cred *cred,
9144 9145
		bool privileged)
{
B
Bryan Schumaker 已提交
9146 9147
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID],
9148
		.rpc_cred = cred,
B
Bryan Schumaker 已提交
9149
	};
9150 9151 9152 9153 9154 9155 9156
	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 已提交
9157

9158 9159 9160
	nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
		&task_setup.rpc_client, &msg);

9161
	dprintk("NFS call  free_stateid %p\n", stateid);
9162 9163 9164 9165 9166 9167 9168 9169 9170 9171
	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;
9172
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
9173 9174 9175 9176
	if (privileged)
		nfs4_set_sequence_privileged(&data->args.seq_args);

	return rpc_run_task(&task_setup);
B
Bryan Schumaker 已提交
9177 9178
}

9179 9180 9181 9182 9183
/**
 * nfs41_free_stateid - perform a FREE_STATEID operation
 *
 * @server: server / transport on which to perform the operation
 * @stateid: state ID to release
9184
 * @cred: credential
9185
 * @is_recovery: set to true if this call needs to be privileged
9186
 *
9187
 * Note: this function is always asynchronous.
9188
 */
9189
static int nfs41_free_stateid(struct nfs_server *server,
9190 9191 9192
		const nfs4_stateid *stateid,
		struct rpc_cred *cred,
		bool is_recovery)
B
Bryan Schumaker 已提交
9193
{
9194 9195
	struct rpc_task *task;

9196
	task = _nfs41_free_stateid(server, stateid, cred, is_recovery);
9197 9198 9199
	if (IS_ERR(task))
		return PTR_ERR(task);
	rpc_put_task(task);
9200
	return 0;
B
Bryan Schumaker 已提交
9201
}
9202

9203 9204
static void
nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
9205
{
9206
	struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
9207

9208
	nfs41_free_stateid(server, &lsp->ls_stateid, cred, false);
9209 9210 9211
	nfs4_free_lock_state(server, lsp);
}

9212 9213 9214
static bool nfs41_match_stateid(const nfs4_stateid *s1,
		const nfs4_stateid *s2)
{
9215 9216 9217
	if (s1->type != s2->type)
		return false;

9218
	if (memcmp(s1->other, s2->other, sizeof(s1->other)) != 0)
9219 9220
		return false;

9221
	if (s1->seqid == s2->seqid)
9222
		return true;
9223
	if (s1->seqid == 0 || s2->seqid == 0)
9224 9225 9226 9227 9228
		return true;

	return false;
}

9229 9230
#endif /* CONFIG_NFS_V4_1 */

9231 9232 9233
static bool nfs4_match_stateid(const nfs4_stateid *s1,
		const nfs4_stateid *s2)
{
9234
	return nfs4_stateid_match(s1, s2);
9235 9236 9237
}


9238
static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
9239
	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
9240
	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
L
Linus Torvalds 已提交
9241 9242
	.recover_open	= nfs4_open_reclaim,
	.recover_lock	= nfs4_lock_reclaim,
9243
	.establish_clid = nfs4_init_clientid,
9244
	.detect_trunking = nfs40_discover_server_trunking,
L
Linus Torvalds 已提交
9245 9246
};

9247
#if defined(CONFIG_NFS_V4_1)
9248
static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
9249 9250 9251 9252
	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
	.recover_open	= nfs4_open_reclaim,
	.recover_lock	= nfs4_lock_reclaim,
9253
	.establish_clid = nfs41_init_clientid,
9254
	.reclaim_complete = nfs41_proc_reclaim_complete,
9255
	.detect_trunking = nfs41_discover_server_trunking,
9256 9257 9258
};
#endif /* CONFIG_NFS_V4_1 */

9259
static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
9260 9261
	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
9262
	.recover_open	= nfs40_open_expired,
9263 9264 9265 9266 9267
	.recover_lock	= nfs4_lock_expired,
	.establish_clid = nfs4_init_clientid,
};

#if defined(CONFIG_NFS_V4_1)
9268
static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
9269
	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
9270
	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
9271 9272
	.recover_open	= nfs41_open_expired,
	.recover_lock	= nfs41_lock_expired,
9273
	.establish_clid = nfs41_init_clientid,
L
Linus Torvalds 已提交
9274
};
9275
#endif /* CONFIG_NFS_V4_1 */
L
Linus Torvalds 已提交
9276

9277
static const struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
B
Benny Halevy 已提交
9278
	.sched_state_renewal = nfs4_proc_async_renew,
9279
	.get_state_renewal_cred_locked = nfs4_get_renew_cred_locked,
9280
	.renew_lease = nfs4_proc_renew,
B
Benny Halevy 已提交
9281 9282 9283
};

#if defined(CONFIG_NFS_V4_1)
9284
static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
B
Benny Halevy 已提交
9285
	.sched_state_renewal = nfs41_proc_async_sequence,
9286
	.get_state_renewal_cred_locked = nfs4_get_machine_cred_locked,
9287
	.renew_lease = nfs4_proc_sequence,
B
Benny Halevy 已提交
9288 9289 9290
};
#endif

9291
static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = {
9292
	.get_locations = _nfs40_proc_get_locations,
9293
	.fsid_present = _nfs40_proc_fsid_present,
9294 9295 9296 9297
};

#if defined(CONFIG_NFS_V4_1)
static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = {
9298
	.get_locations = _nfs41_proc_get_locations,
9299
	.fsid_present = _nfs41_proc_fsid_present,
9300 9301 9302
};
#endif	/* CONFIG_NFS_V4_1 */

9303 9304
static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
	.minor_version = 0,
9305 9306 9307
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_POSIX_LOCK,
9308 9309
	.init_client = nfs40_init_client,
	.shutdown_client = nfs40_shutdown_client,
9310
	.match_stateid = nfs4_match_stateid,
9311
	.find_root_sec = nfs4_find_root_sec,
9312
	.free_lock_state = nfs4_release_lockowner,
9313
	.test_and_free_expired = nfs40_test_and_free_expired_stateid,
9314
	.alloc_seqid = nfs_alloc_seqid,
9315
	.call_sync_ops = &nfs40_call_sync_ops,
9316 9317 9318
	.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
	.state_renewal_ops = &nfs40_state_renewal_ops,
9319
	.mig_recovery_ops = &nfs40_mig_recovery_ops,
9320 9321 9322
};

#if defined(CONFIG_NFS_V4_1)
9323 9324 9325 9326 9327 9328
static struct nfs_seqid *
nfs_alloc_no_seqid(struct nfs_seqid_counter *arg1, gfp_t arg2)
{
	return NULL;
}

9329 9330
static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
	.minor_version = 1,
9331 9332
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
9333
		| NFS_CAP_POSIX_LOCK
9334
		| NFS_CAP_STATEID_NFSV41
A
Anna Schumaker 已提交
9335
		| NFS_CAP_ATOMIC_OPEN_V1,
9336 9337
	.init_client = nfs41_init_client,
	.shutdown_client = nfs41_shutdown_client,
9338
	.match_stateid = nfs41_match_stateid,
9339
	.find_root_sec = nfs41_find_root_sec,
9340
	.free_lock_state = nfs41_free_lock_state,
9341
	.test_and_free_expired = nfs41_test_and_free_expired_stateid,
9342
	.alloc_seqid = nfs_alloc_no_seqid,
9343
	.session_trunk = nfs4_test_session_trunk,
9344
	.call_sync_ops = &nfs41_call_sync_ops,
9345 9346 9347
	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
	.state_renewal_ops = &nfs41_state_renewal_ops,
9348
	.mig_recovery_ops = &nfs41_mig_recovery_ops,
9349 9350 9351
};
#endif

9352 9353 9354
#if defined(CONFIG_NFS_V4_2)
static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
	.minor_version = 2,
9355 9356 9357 9358
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_POSIX_LOCK
		| NFS_CAP_STATEID_NFSV41
A
Anna Schumaker 已提交
9359
		| NFS_CAP_ATOMIC_OPEN_V1
A
Anna Schumaker 已提交
9360
		| NFS_CAP_ALLOCATE
A
Anna Schumaker 已提交
9361
		| NFS_CAP_COPY
A
Anna Schumaker 已提交
9362
		| NFS_CAP_DEALLOCATE
9363
		| NFS_CAP_SEEK
P
Peng Tao 已提交
9364 9365
		| NFS_CAP_LAYOUTSTATS
		| NFS_CAP_CLONE,
9366 9367
	.init_client = nfs41_init_client,
	.shutdown_client = nfs41_shutdown_client,
9368 9369
	.match_stateid = nfs41_match_stateid,
	.find_root_sec = nfs41_find_root_sec,
9370
	.free_lock_state = nfs41_free_lock_state,
9371
	.call_sync_ops = &nfs41_call_sync_ops,
9372
	.test_and_free_expired = nfs41_test_and_free_expired_stateid,
9373
	.alloc_seqid = nfs_alloc_no_seqid,
9374
	.session_trunk = nfs4_test_session_trunk,
9375 9376 9377
	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
	.state_renewal_ops = &nfs41_state_renewal_ops,
9378
	.mig_recovery_ops = &nfs41_mig_recovery_ops,
9379 9380 9381
};
#endif

9382 9383 9384 9385 9386
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
9387 9388 9389
#if defined(CONFIG_NFS_V4_2)
	[2] = &nfs_v4_2_minor_ops,
#endif
9390 9391
};

9392
static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409
{
	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;
}

9410
static const struct inode_operations nfs4_dir_inode_operations = {
9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423
	.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,
9424
	.listxattr	= nfs4_listxattr,
9425 9426
};

9427
static const struct inode_operations nfs4_file_inode_operations = {
9428 9429 9430
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
9431
	.listxattr	= nfs4_listxattr,
9432 9433
};

D
David Howells 已提交
9434
const struct nfs_rpc_ops nfs_v4_clientops = {
L
Linus Torvalds 已提交
9435 9436 9437
	.version	= 4,			/* protocol version */
	.dentry_ops	= &nfs4_dentry_operations,
	.dir_inode_ops	= &nfs4_dir_inode_operations,
9438
	.file_inode_ops	= &nfs4_file_inode_operations,
9439
	.file_ops	= &nfs4_file_operations,
L
Linus Torvalds 已提交
9440
	.getroot	= nfs4_proc_get_root,
B
Bryan Schumaker 已提交
9441
	.submount	= nfs4_submount,
B
Bryan Schumaker 已提交
9442
	.try_mount	= nfs4_try_mount,
L
Linus Torvalds 已提交
9443 9444 9445 9446 9447 9448 9449 9450
	.getattr	= nfs4_proc_getattr,
	.setattr	= nfs4_proc_setattr,
	.lookup		= nfs4_proc_lookup,
	.access		= nfs4_proc_access,
	.readlink	= nfs4_proc_readlink,
	.create		= nfs4_proc_create,
	.remove		= nfs4_proc_remove,
	.unlink_setup	= nfs4_proc_unlink_setup,
9451
	.unlink_rpc_prepare = nfs4_proc_unlink_rpc_prepare,
L
Linus Torvalds 已提交
9452
	.unlink_done	= nfs4_proc_unlink_done,
9453
	.rename_setup	= nfs4_proc_rename_setup,
9454
	.rename_rpc_prepare = nfs4_proc_rename_rpc_prepare,
9455
	.rename_done	= nfs4_proc_rename_done,
L
Linus Torvalds 已提交
9456 9457 9458 9459 9460 9461 9462 9463 9464
	.link		= nfs4_proc_link,
	.symlink	= nfs4_proc_symlink,
	.mkdir		= nfs4_proc_mkdir,
	.rmdir		= nfs4_proc_remove,
	.readdir	= nfs4_proc_readdir,
	.mknod		= nfs4_proc_mknod,
	.statfs		= nfs4_proc_statfs,
	.fsinfo		= nfs4_proc_fsinfo,
	.pathconf	= nfs4_proc_pathconf,
9465
	.set_capabilities = nfs4_server_capabilities,
L
Linus Torvalds 已提交
9466
	.decode_dirent	= nfs4_decode_dirent,
9467
	.pgio_rpc_prepare = nfs4_proc_pgio_rpc_prepare,
L
Linus Torvalds 已提交
9468
	.read_setup	= nfs4_proc_read_setup,
T
Trond Myklebust 已提交
9469
	.read_done	= nfs4_read_done,
L
Linus Torvalds 已提交
9470
	.write_setup	= nfs4_proc_write_setup,
9471
	.write_done	= nfs4_write_done,
L
Linus Torvalds 已提交
9472
	.commit_setup	= nfs4_proc_commit_setup,
9473
	.commit_rpc_prepare = nfs4_proc_commit_rpc_prepare,
9474
	.commit_done	= nfs4_commit_done,
L
Linus Torvalds 已提交
9475
	.lock		= nfs4_proc_lock,
9476
	.clear_acl_cache = nfs4_zap_acl_attr,
T
Trond Myklebust 已提交
9477
	.close_context  = nfs4_close_context,
9478
	.open_context	= nfs4_atomic_open,
9479
	.have_delegation = nfs4_have_delegation,
9480
	.return_delegation = nfs4_inode_return_delegation,
9481
	.alloc_client	= nfs4_alloc_client,
9482
	.init_client	= nfs4_init_client,
9483
	.free_client	= nfs4_free_client,
9484 9485
	.create_server	= nfs4_create_server,
	.clone_server	= nfs_clone_server,
L
Linus Torvalds 已提交
9486 9487
};

9488
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
9489
	.name	= XATTR_NAME_NFSV4_ACL,
9490 9491 9492 9493 9494 9495 9496
	.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,
9497 9498 9499
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	&nfs4_xattr_nfs4_label_handler,
#endif
9500 9501 9502
	NULL
};

L
Linus Torvalds 已提交
9503 9504 9505 9506 9507
/*
 * Local variables:
 *  c-basic-offset: 8
 * End:
 */