nfs4proc.c 207.4 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/nfs_idmap.h>
55
#include <linux/xattr.h>
56
#include <linux/utsname.h>
57
#include <linux/freezer.h>
L
Linus Torvalds 已提交
58

59
#include "nfs4_fs.h"
L
Linus Torvalds 已提交
60
#include "delegation.h"
61
#include "internal.h"
62
#include "iostat.h"
A
Andy Adamson 已提交
63
#include "callback.h"
64
#include "pnfs.h"
65
#include "netns.h"
66
#include "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
struct nfs4_opendata;
77
static int _nfs4_proc_open(struct nfs4_opendata *data);
78
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
L
Linus Torvalds 已提交
79
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
80
static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
81
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
82 83
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);
84 85
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			    struct nfs_fattr *fattr, struct iattr *sattr,
86 87
			    struct nfs4_state *state, struct nfs4_label *ilabel,
			    struct nfs4_label *olabel);
88
#ifdef CONFIG_NFS_V4_1
89 90 91 92
static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
		struct rpc_cred *);
static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *,
		struct rpc_cred *);
93
#endif
94 95 96 97 98 99 100 101 102 103 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

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

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

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

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
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
};

216 217 218 219 220 221
static const u32 nfs4_open_noattr_bitmap[3] = {
	FATTR4_WORD0_TYPE
	| FATTR4_WORD0_CHANGE
	| FATTR4_WORD0_FILEID,
};

222
const u32 nfs4_statfs_bitmap[3] = {
L
Linus Torvalds 已提交
223 224 225 226 227 228 229 230
	FATTR4_WORD0_FILES_AVAIL
	| FATTR4_WORD0_FILES_FREE
	| FATTR4_WORD0_FILES_TOTAL,
	FATTR4_WORD1_SPACE_AVAIL
	| FATTR4_WORD1_SPACE_FREE
	| FATTR4_WORD1_SPACE_TOTAL
};

231
const u32 nfs4_pathconf_bitmap[3] = {
L
Linus Torvalds 已提交
232 233 234 235 236
	FATTR4_WORD0_MAXLINK
	| FATTR4_WORD0_MAXNAME,
	0
};

237
const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE
L
Linus Torvalds 已提交
238 239 240
			| FATTR4_WORD0_MAXREAD
			| FATTR4_WORD0_MAXWRITE
			| FATTR4_WORD0_LEASE_TIME,
241
			FATTR4_WORD1_TIME_DELTA
242 243
			| FATTR4_WORD1_FS_LAYOUT_TYPES,
			FATTR4_WORD2_LAYOUT_BLKSIZE
L
Linus Torvalds 已提交
244 245
};

246
const u32 nfs4_fs_locations_bitmap[3] = {
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
	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
262
	| FATTR4_WORD1_MOUNTED_ON_FILEID,
263 264
};

A
Al Viro 已提交
265
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
L
Linus Torvalds 已提交
266 267
		struct nfs4_readdir_arg *readdir)
{
268
	__be32 *start, *p;
L
Linus Torvalds 已提交
269 270

	if (cookie > 2) {
271
		readdir->cookie = cookie;
L
Linus Torvalds 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
		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.
	 */
288
	start = p = kmap_atomic(*readdir->pages);
L
Linus Torvalds 已提交
289 290 291 292 293 294 295 296 297 298 299
	
	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 */
P
Peter Staubach 已提交
300
		p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_inode));
L
Linus Torvalds 已提交
301 302 303 304 305 306 307 308 309 310 311
	}
	
	*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 */
P
Peter Staubach 已提交
312
	p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_parent->d_inode));
L
Linus Torvalds 已提交
313 314 315

	readdir->pgbase = (char *)p - (char *)start;
	readdir->count -= readdir->pgbase;
316
	kunmap_atomic(start);
L
Linus Torvalds 已提交
317 318
}

319 320 321 322 323 324 325 326 327 328
static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
{
	int res = 0;

	might_sleep();

	if (*timeout <= 0)
		*timeout = NFS4_POLL_RETRY_MIN;
	if (*timeout > NFS4_POLL_RETRY_MAX)
		*timeout = NFS4_POLL_RETRY_MAX;
329
	freezable_schedule_timeout_killable_unsafe(*timeout);
330 331 332 333 334 335 336 337 338
	if (fatal_signal_pending(current))
		res = -ERESTARTSYS;
	*timeout <<= 1;
	return res;
}

/* This is the error handling routine for processes that are allowed
 * to sleep.
 */
339
static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
340 341
{
	struct nfs_client *clp = server->nfs_client;
342
	struct nfs4_state *state = exception->state;
343
	struct inode *inode = exception->inode;
344 345 346 347 348 349
	int ret = errorcode;

	exception->retry = 0;
	switch(errorcode) {
		case 0:
			return 0;
350
		case -NFS4ERR_OPENMODE:
351
			if (inode && nfs4_have_delegation(inode, FMODE_READ)) {
352
				nfs4_inode_return_delegation(inode);
353 354 355 356 357
				exception->retry = 1;
				return 0;
			}
			if (state == NULL)
				break;
358 359 360
			ret = nfs4_schedule_stateid_recovery(server, state);
			if (ret < 0)
				break;
361
			goto wait_on_recovery;
362
		case -NFS4ERR_DELEG_REVOKED:
363 364
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_BAD_STATEID:
365 366 367 368 369
			if (inode != NULL && nfs4_have_delegation(inode, FMODE_READ)) {
				nfs_remove_bad_delegation(inode);
				exception->retry = 1;
				break;
			}
370 371
			if (state == NULL)
				break;
372 373 374
			ret = nfs4_schedule_stateid_recovery(server, state);
			if (ret < 0)
				break;
375
			goto wait_on_recovery;
376
		case -NFS4ERR_EXPIRED:
377 378 379 380 381
			if (state != NULL) {
				ret = nfs4_schedule_stateid_recovery(server, state);
				if (ret < 0)
					break;
			}
382
		case -NFS4ERR_STALE_STATEID:
383
		case -NFS4ERR_STALE_CLIENTID:
384 385
			nfs4_schedule_lease_recovery(clp);
			goto wait_on_recovery;
386
#if defined(CONFIG_NFS_V4_1)
387 388 389 390 391 392 393 394 395
		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);
396
			nfs4_schedule_session_recovery(clp->cl_session, errorcode);
397
			goto wait_on_recovery;
398
#endif /* defined(CONFIG_NFS_V4_1) */
399
		case -NFS4ERR_FILE_OPEN:
400 401 402 403 404 405 406
			if (exception->timeout > HZ) {
				/* We have retried a decent amount, time to
				 * fail
				 */
				ret = -EBUSY;
				break;
			}
407 408 409 410 411
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			ret = nfs4_delay(server->client, &exception->timeout);
			if (ret != 0)
				break;
412
		case -NFS4ERR_RETRY_UNCACHED_REP:
413 414
		case -NFS4ERR_OLD_STATEID:
			exception->retry = 1;
415 416 417 418 419 420 421 422 423 424 425 426 427
			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);
			}
428 429 430
	}
	/* We failed to handle the error */
	return nfs4_map_errors(ret);
431
wait_on_recovery:
432 433 434 435
	ret = nfs4_wait_clnt_recover(clp);
	if (ret == 0)
		exception->retry = 1;
	return ret;
436 437
}

438 439 440 441 442 443 444 445 446 447 448 449 450 451
/*
 * 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;
}
452

453
static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp)
L
Linus Torvalds 已提交
454 455 456 457 458 459 460
{
	spin_lock(&clp->cl_lock);
	if (time_before(clp->cl_last_renewal,timestamp))
		clp->cl_last_renewal = timestamp;
	spin_unlock(&clp->cl_lock);
}

461 462 463 464 465
static void renew_lease(const struct nfs_server *server, unsigned long timestamp)
{
	do_renew_lease(server->nfs_client, timestamp);
}

466 467 468 469 470 471
struct nfs4_call_sync_data {
	const struct nfs_server *seq_server;
	struct nfs4_sequence_args *seq_args;
	struct nfs4_sequence_res *seq_res;
};

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
static void nfs4_init_sequence(struct nfs4_sequence_args *args,
			       struct nfs4_sequence_res *res, int cache_reply)
{
	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;
}

C
Chuck Lever 已提交
487 488 489 490 491 492 493 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 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
static int nfs40_setup_sequence(const struct nfs_server *server,
				struct nfs4_sequence_args *args,
				struct nfs4_sequence_res *res,
				struct rpc_task *task)
{
	struct nfs4_slot_table *tbl = server->nfs_client->cl_slot_tbl;
	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);

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

static int nfs40_sequence_done(struct rpc_task *task,
			       struct nfs4_sequence_res *res)
{
	struct nfs4_slot *slot = res->sr_slot;
	struct nfs4_slot_table *tbl;

	if (!RPC_WAS_SENT(task))
		goto out;

	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;
out:
	return 1;
}

A
Andy Adamson 已提交
548 549
#if defined(CONFIG_NFS_V4_1)

550
static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
551
{
552
	struct nfs4_session *session;
A
Andy Adamson 已提交
553
	struct nfs4_slot_table *tbl;
554
	bool send_new_highest_used_slotid = false;
A
Andy Adamson 已提交
555

556
	if (!res->sr_slot) {
A
Andy Adamson 已提交
557 558
		/* just wake up the next guy waiting since
		 * we may have not consumed a slot after all */
A
Andy Adamson 已提交
559
		dprintk("%s: No slot\n", __func__);
560
		return;
A
Andy Adamson 已提交
561
	}
562 563
	tbl = res->sr_slot->table;
	session = tbl->session;
564

565
	spin_lock(&tbl->slot_tbl_lock);
566 567 568 569 570 571
	/* 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;

572 573 574 575
	if (nfs41_wake_and_assign_slot(tbl, res->sr_slot)) {
		send_new_highest_used_slotid = false;
		goto out_unlock;
	}
T
Trond Myklebust 已提交
576
	nfs4_free_slot(tbl, res->sr_slot);
577 578 579

	if (tbl->highest_used_slotid != NFS4_NO_SLOT)
		send_new_highest_used_slotid = false;
580
out_unlock:
581
	spin_unlock(&tbl->slot_tbl_lock);
582
	res->sr_slot = NULL;
583 584
	if (send_new_highest_used_slotid)
		nfs41_server_notify_highest_slotid_update(session->clp);
A
Andy Adamson 已提交
585 586
}

587
static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
588
{
589
	struct nfs4_session *session;
590
	struct nfs4_slot *slot;
591
	struct nfs_client *clp;
592
	bool interrupted = false;
593
	int ret = 1;
A
Andy Adamson 已提交
594

595 596
	/* don't increment the sequence number if the task wasn't sent */
	if (!RPC_WAS_SENT(task))
A
Andy Adamson 已提交
597 598
		goto out;

599
	slot = res->sr_slot;
600
	session = slot->table->session;
601

602 603 604 605 606
	if (slot->interrupted) {
		slot->interrupted = 0;
		interrupted = true;
	}

607
	trace_nfs4_sequence_done(session, res);
A
Andy Adamson 已提交
608
	/* Check the SEQUENCE operation status */
609 610
	switch (res->sr_status) {
	case 0:
A
Andy Adamson 已提交
611
		/* Update the slot's sequence and clientid lease timer */
612
		++slot->seq_nr;
613
		clp = session->clp;
614
		do_renew_lease(clp, res->sr_timestamp);
615
		/* Check sequence flags */
616 617
		if (res->sr_status_flags != 0)
			nfs4_schedule_lease_recovery(clp);
618
		nfs41_update_target_slotid(slot->table, slot, res);
619
		break;
620 621 622 623 624 625 626 627 628
	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;
629 630 631 632 633
	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.
		 */
634
		dprintk("%s: slot=%u seq=%u: Operation in progress\n",
635
			__func__,
636
			slot->slot_nr,
637
			slot->seq_nr);
638
		goto out_retry;
639 640 641 642 643
	case -NFS4ERR_BADSLOT:
		/*
		 * The slot id we used was probably retired. Try again
		 * using a different slot id.
		 */
644 645
		goto retry_nowait;
	case -NFS4ERR_SEQ_MISORDERED:
646 647 648 649 650 651 652 653
		/*
		 * Was the last operation on this sequence interrupted?
		 * If so, retry after bumping the sequence number.
		 */
		if (interrupted) {
			++slot->seq_nr;
			goto retry_nowait;
		}
654 655 656 657
		/*
		 * Could this slot have been previously retired?
		 * If so, then the server may be expecting seq_nr = 1!
		 */
658 659 660 661 662
		if (slot->seq_nr != 1) {
			slot->seq_nr = 1;
			goto retry_nowait;
		}
		break;
663 664 665
	case -NFS4ERR_SEQ_FALSE_RETRY:
		++slot->seq_nr;
		goto retry_nowait;
666 667
	default:
		/* Just update the slot sequence no. */
668
		++slot->seq_nr;
A
Andy Adamson 已提交
669 670 671 672
	}
out:
	/* The session may be reset by one of the error handlers. */
	dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
673
	nfs41_sequence_free_slot(res);
674
	return ret;
675 676 677 678 679 680
retry_nowait:
	if (rpc_restart_call_prepare(task)) {
		task->tk_status = 0;
		ret = 0;
	}
	goto out;
681
out_retry:
682
	if (!rpc_restart_call(task))
683 684 685
		goto out;
	rpc_delay(task, NFS4_POLL_RETRY_MAX);
	return 0;
A
Andy Adamson 已提交
686 687
}

688 689
static int nfs4_sequence_done(struct rpc_task *task,
			       struct nfs4_sequence_res *res)
690
{
691
	if (res->sr_slot == NULL)
692
		return 1;
C
Chuck Lever 已提交
693 694
	if (!res->sr_slot->table->session)
		return nfs40_sequence_done(task, res);
695
	return nfs41_sequence_done(task, res);
696 697
}

A
Andy Adamson 已提交
698
int nfs41_setup_sequence(struct nfs4_session *session,
A
Andy Adamson 已提交
699 700 701 702
				struct nfs4_sequence_args *args,
				struct nfs4_sequence_res *res,
				struct rpc_task *task)
{
A
Andy Adamson 已提交
703 704 705 706
	struct nfs4_slot *slot;
	struct nfs4_slot_table *tbl;

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

A
Andy Adamson 已提交
711 712
	tbl = &session->fc_slot_table;

713 714
	task->tk_timeout = 0;

A
Andy Adamson 已提交
715
	spin_lock(&tbl->slot_tbl_lock);
716
	if (test_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state) &&
717
	    !args->sa_privileged) {
718 719
		/* The state manager will wait until the slot table is empty */
		dprintk("%s session is draining\n", __func__);
720
		goto out_sleep;
721 722
	}

723
	slot = nfs4_alloc_slot(tbl);
724 725 726 727
	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 已提交
728
		dprintk("<-- %s: no free slots\n", __func__);
729
		goto out_sleep;
A
Andy Adamson 已提交
730 731 732
	}
	spin_unlock(&tbl->slot_tbl_lock);

733
	args->sa_slot = slot;
A
Andy Adamson 已提交
734

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

738
	res->sr_slot = slot;
739
	res->sr_timestamp = jiffies;
740
	res->sr_status_flags = 0;
A
Andy Adamson 已提交
741 742 743 744 745
	/*
	 * 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;
746
	trace_nfs4_setup_sequence(session, args);
747 748
out_success:
	rpc_call_start(task);
A
Andy Adamson 已提交
749
	return 0;
750
out_sleep:
751 752
	/* Privileged tasks are queued with top priority */
	if (args->sa_privileged)
753 754 755 756
		rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task,
				NULL, RPC_PRIORITY_PRIVILEGED);
	else
		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
757 758
	spin_unlock(&tbl->slot_tbl_lock);
	return -EAGAIN;
A
Andy Adamson 已提交
759
}
A
Andy Adamson 已提交
760
EXPORT_SYMBOL_GPL(nfs41_setup_sequence);
A
Andy Adamson 已提交
761

762 763 764 765
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 已提交
766
{
767
	struct nfs4_session *session = nfs4_get_session(server);
A
Andy Adamson 已提交
768 769
	int ret = 0;

C
Chuck Lever 已提交
770 771
	if (!session)
		return nfs40_setup_sequence(server, args, res, task);
772

773
	dprintk("--> %s clp %p session %p sr_slot %u\n",
774
		__func__, session->clp, session, res->sr_slot ?
775
			res->sr_slot->slot_nr : NFS4_NO_SLOT);
A
Andy Adamson 已提交
776

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

A
Andy Adamson 已提交
779 780 781 782 783 784
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
}

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

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

790
	nfs41_setup_sequence(session, data->seq_args, data->seq_res, task);
A
Andy Adamson 已提交
791 792
}

A
Andy Adamson 已提交
793 794
static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
{
795
	struct nfs4_call_sync_data *data = calldata;
A
Andy Adamson 已提交
796

797
	nfs41_sequence_done(task, data->seq_res);
A
Andy Adamson 已提交
798 799
}

800
static const struct rpc_call_ops nfs41_call_sync_ops = {
A
Andy Adamson 已提交
801
	.rpc_call_prepare = nfs41_call_sync_prepare,
A
Andy Adamson 已提交
802
	.rpc_call_done = nfs41_call_sync_done,
A
Andy Adamson 已提交
803 804
};

C
Chuck Lever 已提交
805 806
#else	/* !CONFIG_NFS_V4_1 */

807 808 809 810 811
static int nfs4_setup_sequence(const struct nfs_server *server,
			       struct nfs4_sequence_args *args,
			       struct nfs4_sequence_res *res,
			       struct rpc_task *task)
{
C
Chuck Lever 已提交
812
	return nfs40_setup_sequence(server, args, res, task);
813 814 815 816 817
}

static int nfs4_sequence_done(struct rpc_task *task,
			       struct nfs4_sequence_res *res)
{
C
Chuck Lever 已提交
818
	return nfs40_sequence_done(task, res);
819
}
C
Chuck Lever 已提交
820 821

#endif	/* !CONFIG_NFS_V4_1 */
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840

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

841 842
static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
				   struct nfs_server *server,
A
Andy Adamson 已提交
843 844
				   struct rpc_message *msg,
				   struct nfs4_sequence_args *args,
845
				   struct nfs4_sequence_res *res)
A
Andy Adamson 已提交
846 847 848
{
	int ret;
	struct rpc_task *task;
849
	struct nfs_client *clp = server->nfs_client;
850
	struct nfs4_call_sync_data data = {
851
		.seq_server = server,
A
Andy Adamson 已提交
852 853 854 855
		.seq_args = args,
		.seq_res = res,
	};
	struct rpc_task_setup task_setup = {
856
		.rpc_client = clnt,
A
Andy Adamson 已提交
857
		.rpc_message = msg,
858
		.callback_ops = clp->cl_mvops->call_sync_ops,
A
Andy Adamson 已提交
859 860 861 862 863 864 865 866 867 868 869 870 871
		.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;
}

872
static
873 874
int nfs4_call_sync(struct rpc_clnt *clnt,
		   struct nfs_server *server,
875 876 877 878 879
		   struct rpc_message *msg,
		   struct nfs4_sequence_args *args,
		   struct nfs4_sequence_res *res,
		   int cache_reply)
{
880
	nfs4_init_sequence(args, res, cache_reply);
881
	return nfs4_call_sync_sequence(clnt, server, msg, args, res);
882
}
A
Andy Adamson 已提交
883

884
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
L
Linus Torvalds 已提交
885
{
886
	struct nfs_inode *nfsi = NFS_I(dir);
L
Linus Torvalds 已提交
887

888
	spin_lock(&dir->i_lock);
889
	nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
890
	if (!cinfo->atomic || cinfo->before != dir->i_version)
891
		nfs_force_lookup_revalidate(dir);
892
	dir->i_version = cinfo->after;
D
David Howells 已提交
893
	nfs_fscache_invalidate(dir);
894
	spin_unlock(&dir->i_lock);
L
Linus Torvalds 已提交
895 896
}

897
struct nfs4_opendata {
898
	struct kref kref;
899 900
	struct nfs_openargs o_arg;
	struct nfs_openres o_res;
901 902
	struct nfs_open_confirmargs c_arg;
	struct nfs_open_confirmres c_res;
903 904
	struct nfs4_string owner_name;
	struct nfs4_string group_name;
905
	struct nfs_fattr f_attr;
906
	struct nfs4_label *f_label;
907
	struct dentry *dir;
908
	struct dentry *dentry;
909
	struct nfs4_state_owner *owner;
910
	struct nfs4_state *state;
911
	struct iattr attrs;
912
	unsigned long timestamp;
913
	unsigned int rpc_done : 1;
914
	unsigned int is_recover : 1;
915 916
	int rpc_status;
	int cancelled;
917 918
};

919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
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;
}

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;
	}
}
948 949 950 951

static void nfs4_init_opendata_res(struct nfs4_opendata *p)
{
	p->o_res.f_attr = &p->f_attr;
952
	p->o_res.f_label = p->f_label;
953 954
	p->o_res.seqid = p->o_arg.seqid;
	p->c_res.seqid = p->c_arg.seqid;
955
	p->o_res.server = p->o_arg.server;
956
	p->o_res.access_request = p->o_arg.access;
957
	nfs_fattr_init(&p->f_attr);
958
	nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name);
959 960
}

961
static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
962
		struct nfs4_state_owner *sp, fmode_t fmode, int flags,
963
		const struct iattr *attrs,
964
		struct nfs4_label *label,
965
		enum open_claim_type4 claim,
966
		gfp_t gfp_mask)
967
{
968
	struct dentry *parent = dget_parent(dentry);
969 970 971 972
	struct inode *dir = parent->d_inode;
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs4_opendata *p;

973
	p = kzalloc(sizeof(*p), gfp_mask);
974 975
	if (p == NULL)
		goto err;
976 977 978 979 980

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

981
	p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask);
982
	if (p->o_arg.seqid == NULL)
983
		goto err_free_label;
984 985
	nfs_sb_active(dentry->d_sb);
	p->dentry = dget(dentry);
986 987 988
	p->dir = parent;
	p->owner = sp;
	atomic_inc(&sp->so_count);
989 990
	p->o_arg.open_flags = flags;
	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
991 992 993 994 995 996 997 998
	/* 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 */
		p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY |
				  NFS4_ACCESS_EXTEND | NFS4_ACCESS_EXECUTE;
	}
999
	p->o_arg.clientid = server->nfs_client->cl_clientid;
1000 1001
	p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
	p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
1002
	p->o_arg.name = &dentry->d_name;
1003
	p->o_arg.server = server;
1004
	p->o_arg.bitmask = nfs4_bitmask(server, label);
1005
	p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
1006
	p->o_arg.label = label;
1007 1008
	p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
	switch (p->o_arg.claim) {
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
	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:
		p->o_arg.fh = NFS_FH(dentry->d_inode);
	}
1020
	if (attrs != NULL && attrs->ia_valid != 0) {
1021
		__u32 verf[2];
1022

1023 1024
		p->o_arg.u.attrs = &p->attrs;
		memcpy(&p->attrs, attrs, sizeof(p->attrs));
1025 1026 1027 1028 1029

		verf[0] = jiffies;
		verf[1] = current->pid;
		memcpy(p->o_arg.u.verifier.data, verf,
				sizeof(p->o_arg.u.verifier.data));
1030
	}
1031 1032 1033
	p->c_arg.fh = &p->o_res.fh;
	p->c_arg.stateid = &p->o_res.stateid;
	p->c_arg.seqid = p->o_arg.seqid;
1034
	nfs4_init_opendata_res(p);
1035
	kref_init(&p->kref);
1036
	return p;
1037 1038 1039 1040

err_free_label:
	nfs4_label_free(p->f_label);
err_free_p:
1041 1042 1043 1044 1045 1046
	kfree(p);
err:
	dput(parent);
	return NULL;
}

1047
static void nfs4_opendata_free(struct kref *kref)
1048
{
1049 1050
	struct nfs4_opendata *p = container_of(kref,
			struct nfs4_opendata, kref);
1051
	struct super_block *sb = p->dentry->d_sb;
1052 1053

	nfs_free_seqid(p->o_arg.seqid);
1054 1055
	if (p->state != NULL)
		nfs4_put_open_state(p->state);
1056
	nfs4_put_state_owner(p->owner);
1057 1058 1059

	nfs4_label_free(p->f_label);

1060
	dput(p->dir);
1061 1062
	dput(p->dentry);
	nfs_sb_deactive(sb);
1063
	nfs_fattr_free_names(&p->f_attr);
1064 1065 1066 1067 1068 1069 1070
	kfree(p);
}

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

1073 1074 1075 1076 1077 1078 1079 1080
static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
{
	int ret;

	ret = rpc_wait_for_completion_task(task);
	return ret;
}

1081
static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
1082 1083
{
	int ret = 0;
1084

1085
	if (open_mode & (O_EXCL|O_TRUNC))
1086 1087
		goto out;
	switch (mode & (FMODE_READ|FMODE_WRITE)) {
1088
		case FMODE_READ:
1089 1090
			ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0
				&& state->n_rdonly != 0;
1091 1092
			break;
		case FMODE_WRITE:
1093 1094
			ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0
				&& state->n_wronly != 0;
1095 1096
			break;
		case FMODE_READ|FMODE_WRITE:
1097 1098
			ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0
				&& state->n_rdwr != 0;
1099
	}
1100
out:
1101 1102 1103
	return ret;
}

1104
static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode)
1105
{
1106 1107
	if (delegation == NULL)
		return 0;
1108
	if ((delegation->type & fmode) != fmode)
1109
		return 0;
1110
	if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
1111
		return 0;
1112 1113
	if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
		return 0;
1114
	nfs_mark_delegation_referenced(delegation);
1115 1116 1117
	return 1;
}

1118
static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
1119
{
1120
	switch (fmode) {
1121 1122 1123 1124 1125 1126 1127 1128 1129
		case FMODE_WRITE:
			state->n_wronly++;
			break;
		case FMODE_READ:
			state->n_rdonly++;
			break;
		case FMODE_READ|FMODE_WRITE:
			state->n_rdwr++;
	}
1130
	nfs4_state_set_mode_locked(state, state->state | fmode);
1131 1132
}

1133
static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
1134 1135
{
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1136 1137
		nfs4_stateid_copy(&state->stateid, stateid);
	nfs4_stateid_copy(&state->open_stateid, stateid);
1138
	set_bit(NFS_OPEN_STATE, &state->flags);
1139
	switch (fmode) {
1140 1141 1142 1143 1144 1145 1146 1147 1148
		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);
	}
1149 1150
}

1151
static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
1152
{
1153
	write_seqlock(&state->seqlock);
1154
	nfs_set_open_stateid_locked(state, stateid, fmode);
1155
	write_sequnlock(&state->seqlock);
1156 1157
}

1158
static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, const nfs4_stateid *deleg_stateid, fmode_t fmode)
L
Linus Torvalds 已提交
1159
{
1160 1161 1162 1163 1164
	/*
	 * Protect the call to nfs4_state_set_mode_locked and
	 * serialise the stateid update
	 */
	write_seqlock(&state->seqlock);
1165
	if (deleg_stateid != NULL) {
1166
		nfs4_stateid_copy(&state->stateid, deleg_stateid);
1167 1168 1169
		set_bit(NFS_DELEGATED_STATE, &state->flags);
	}
	if (open_stateid != NULL)
1170
		nfs_set_open_stateid_locked(state, open_stateid, fmode);
1171 1172
	write_sequnlock(&state->seqlock);
	spin_lock(&state->owner->so_lock);
1173
	update_open_stateflags(state, fmode);
1174
	spin_unlock(&state->owner->so_lock);
L
Linus Torvalds 已提交
1175 1176
}

1177
static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *delegation, fmode_t fmode)
1178 1179 1180 1181 1182
{
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_delegation *deleg_cur;
	int ret = 0;

1183
	fmode &= (FMODE_READ|FMODE_WRITE);
1184 1185 1186 1187 1188 1189 1190

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

	spin_lock(&deleg_cur->lock);
1191
	if (rcu_dereference(nfsi->delegation) != deleg_cur ||
1192
	   test_bit(NFS_DELEGATION_RETURNING, &deleg_cur->flags) ||
1193
	    (deleg_cur->type & fmode) != fmode)
1194 1195 1196 1197
		goto no_delegation_unlock;

	if (delegation == NULL)
		delegation = &deleg_cur->stateid;
1198
	else if (!nfs4_stateid_match(&deleg_cur->stateid, delegation))
1199 1200
		goto no_delegation_unlock;

1201
	nfs_mark_delegation_referenced(deleg_cur);
1202
	__update_open_stateid(state, open_stateid, &deleg_cur->stateid, fmode);
1203 1204 1205 1206 1207 1208 1209
	ret = 1;
no_delegation_unlock:
	spin_unlock(&deleg_cur->lock);
no_delegation:
	rcu_read_unlock();

	if (!ret && open_stateid != NULL) {
1210
		__update_open_stateid(state, open_stateid, NULL, fmode);
1211 1212 1213 1214 1215 1216 1217
		ret = 1;
	}

	return ret;
}


1218
static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmode)
1219 1220 1221 1222 1223
{
	struct nfs_delegation *delegation;

	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(inode)->delegation);
1224
	if (delegation == NULL || (delegation->type & fmode) == fmode) {
1225 1226 1227 1228
		rcu_read_unlock();
		return;
	}
	rcu_read_unlock();
1229
	nfs4_inode_return_delegation(inode);
1230 1231
}

1232
static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
1233 1234 1235 1236
{
	struct nfs4_state *state = opendata->state;
	struct nfs_inode *nfsi = NFS_I(state->inode);
	struct nfs_delegation *delegation;
1237
	int open_mode = opendata->o_arg.open_flags;
1238
	fmode_t fmode = opendata->o_arg.fmode;
1239 1240 1241 1242
	nfs4_stateid stateid;
	int ret = -EAGAIN;

	for (;;) {
1243
		if (can_open_cached(state, fmode, open_mode)) {
1244
			spin_lock(&state->owner->so_lock);
1245 1246
			if (can_open_cached(state, fmode, open_mode)) {
				update_open_stateflags(state, fmode);
1247 1248 1249 1250 1251
				spin_unlock(&state->owner->so_lock);
				goto out_return_state;
			}
			spin_unlock(&state->owner->so_lock);
		}
1252 1253
		rcu_read_lock();
		delegation = rcu_dereference(nfsi->delegation);
1254
		if (!can_open_delegated(delegation, fmode)) {
1255
			rcu_read_unlock();
1256
			break;
1257
		}
1258
		/* Save the delegation */
1259
		nfs4_stateid_copy(&stateid, &delegation->stateid);
1260
		rcu_read_unlock();
1261
		nfs_release_seqid(opendata->o_arg.seqid);
1262 1263 1264 1265 1266
		if (!opendata->is_recover) {
			ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
			if (ret != 0)
				goto out;
		}
1267
		ret = -EAGAIN;
1268 1269

		/* Try to update the stateid using the delegation */
1270
		if (update_open_stateid(state, NULL, &stateid, fmode))
1271
			goto out_return_state;
1272 1273 1274 1275 1276 1277 1278 1279
	}
out:
	return ERR_PTR(ret);
out_return_state:
	atomic_inc(&state->count);
	return state;
}

1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337
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();
	if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
		pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
				   "returning a delegation for "
				   "OPEN(CLAIM_DELEGATE_CUR)\n",
				   clp->cl_hostname);
	} else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
		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;

	if (!data->rpc_done) {
		ret = data->rpc_status;
		goto err;
	}

	ret = -ESTALE;
	if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) ||
	    !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) ||
	    !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE))
		goto err;

	ret = -ENOMEM;
	state = nfs4_get_open_state(inode, data->owner);
	if (state == NULL)
		goto err;

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

1338 1339
	nfs_setsecurity(inode, &data->f_attr, data->f_label);

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
	if (data->o_res.delegation_type != 0)
		nfs4_opendata_check_deleg(data, state);
	update_open_stateid(state, &data->o_res.stateid, NULL,
			    data->o_arg.fmode);

	return state;
err:
	return ERR_PTR(ret);

}

static struct nfs4_state *
_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
1353 1354 1355
{
	struct inode *inode;
	struct nfs4_state *state = NULL;
1356
	int ret;
1357

1358
	if (!data->rpc_done) {
1359
		state = nfs4_try_open_cached(data);
1360 1361 1362
		goto out;
	}

1363
	ret = -EAGAIN;
1364
	if (!(data->f_attr.valid & NFS_ATTR_FATTR))
1365
		goto err;
1366
	inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr, data->f_label);
1367
	ret = PTR_ERR(inode);
1368
	if (IS_ERR(inode))
1369 1370
		goto err;
	ret = -ENOMEM;
1371 1372
	state = nfs4_get_open_state(inode, data->owner);
	if (state == NULL)
1373
		goto err_put_inode;
1374 1375
	if (data->o_res.delegation_type != 0)
		nfs4_opendata_check_deleg(data, state);
1376
	update_open_stateid(state, &data->o_res.stateid, NULL,
1377
			data->o_arg.fmode);
1378
	iput(inode);
1379
out:
1380
	nfs_release_seqid(data->o_arg.seqid);
1381
	return state;
1382 1383 1384 1385
err_put_inode:
	iput(inode);
err:
	return ERR_PTR(ret);
1386 1387
}

1388 1389 1390 1391 1392 1393 1394 1395
static struct nfs4_state *
nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
{
	if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
		return _nfs4_opendata_reclaim_to_nfs4_state(data);
	return _nfs4_opendata_to_nfs4_state(data);
}

1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
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);
}

1413 1414
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 已提交
1415 1416 1417
{
	struct nfs4_opendata *opendata;

1418
	opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0,
1419
			NULL, NULL, claim, GFP_NOFS);
T
Trond Myklebust 已提交
1420 1421 1422 1423 1424 1425 1426
	if (opendata == NULL)
		return ERR_PTR(-ENOMEM);
	opendata->state = state;
	atomic_inc(&state->count);
	return opendata;
}

1427
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmode, struct nfs4_state **res)
1428
{
1429
	struct nfs4_state *newstate;
1430 1431
	int ret;

1432 1433
	opendata->o_arg.open_flags = 0;
	opendata->o_arg.fmode = fmode;
1434 1435 1436
	memset(&opendata->o_res, 0, sizeof(opendata->o_res));
	memset(&opendata->c_res, 0, sizeof(opendata->c_res));
	nfs4_init_opendata_res(opendata);
1437
	ret = _nfs4_recover_proc_open(opendata);
1438 1439
	if (ret != 0)
		return ret; 
1440
	newstate = nfs4_opendata_to_nfs4_state(opendata);
1441 1442
	if (IS_ERR(newstate))
		return PTR_ERR(newstate);
1443
	nfs4_close_state(newstate, fmode);
1444
	*res = newstate;
1445 1446 1447 1448 1449 1450 1451 1452 1453
	return 0;
}

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

	/* memory barrier prior to reading state->n_* */
1454
	clear_bit(NFS_DELEGATED_STATE, &state->flags);
1455
	clear_bit(NFS_OPEN_STATE, &state->flags);
1456 1457
	smp_rmb();
	if (state->n_rdwr != 0) {
T
Trond Myklebust 已提交
1458
		clear_bit(NFS_O_RDWR_STATE, &state->flags);
1459
		ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
1460 1461
		if (ret != 0)
			return ret;
1462 1463
		if (newstate != state)
			return -ESTALE;
1464 1465
	}
	if (state->n_wronly != 0) {
T
Trond Myklebust 已提交
1466
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
1467
		ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
1468 1469
		if (ret != 0)
			return ret;
1470 1471
		if (newstate != state)
			return -ESTALE;
1472 1473
	}
	if (state->n_rdonly != 0) {
T
Trond Myklebust 已提交
1474
		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1475
		ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
1476 1477
		if (ret != 0)
			return ret;
1478 1479
		if (newstate != state)
			return -ESTALE;
1480
	}
1481 1482 1483 1484 1485
	/*
	 * 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 &&
1486
	    !nfs4_stateid_match(&state->stateid, &state->open_stateid)) {
1487
		write_seqlock(&state->seqlock);
1488
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1489
			nfs4_stateid_copy(&state->stateid, &state->open_stateid);
1490
		write_sequnlock(&state->seqlock);
1491
	}
1492 1493 1494
	return 0;
}

L
Linus Torvalds 已提交
1495 1496 1497 1498
/*
 * OPEN_RECLAIM:
 * 	reclaim state on the server after a reboot.
 */
1499
static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1500
{
1501
	struct nfs_delegation *delegation;
1502
	struct nfs4_opendata *opendata;
1503
	fmode_t delegation_type = 0;
L
Linus Torvalds 已提交
1504 1505
	int status;

1506 1507
	opendata = nfs4_open_recoverdata_alloc(ctx, state,
			NFS4_OPEN_CLAIM_PREVIOUS);
T
Trond Myklebust 已提交
1508 1509
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
1510 1511
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
1512
	if (delegation != NULL && test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) != 0)
1513
		delegation_type = delegation->type;
1514
	rcu_read_unlock();
1515 1516
	opendata->o_arg.u.delegation_type = delegation_type;
	status = nfs4_open_recover(opendata, state);
1517
	nfs4_opendata_put(opendata);
L
Linus Torvalds 已提交
1518 1519 1520
	return status;
}

1521
static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1522 1523 1524 1525 1526
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_exception exception = { };
	int err;
	do {
1527
		err = _nfs4_do_open_reclaim(ctx, state);
1528
		trace_nfs4_open_reclaim(ctx, 0, err);
1529 1530
		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
			continue;
1531
		if (err != -NFS4ERR_DELAY)
1532 1533
			break;
		nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
1534 1535 1536 1537
	} while (exception.retry);
	return err;
}

1538 1539 1540 1541 1542 1543 1544
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))
1545
		return -EAGAIN;
1546
	ret = nfs4_do_open_reclaim(ctx, state);
1547 1548 1549 1550
	put_nfs_open_context(ctx);
	return ret;
}

1551
static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, int err)
L
Linus Torvalds 已提交
1552
{
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
	switch (err) {
		default:
			printk(KERN_ERR "NFS: %s: unhandled error "
					"%d.\n", __func__, err);
		case 0:
		case -ENOENT:
		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);
		case -NFS4ERR_EXPIRED:
			/* Don't recall a delegation if it was lost */
			nfs4_schedule_lease_recovery(server->nfs_client);
			return -EAGAIN;
		case -NFS4ERR_DELEG_REVOKED:
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_BAD_STATEID:
1579
		case -NFS4ERR_OPENMODE:
1580 1581 1582 1583 1584 1585 1586 1587 1588
			nfs_inode_find_state_and_recover(state->inode,
					stateid);
			nfs4_schedule_stateid_recovery(server, state);
			return 0;
		case -NFS4ERR_DELAY:
		case -NFS4ERR_GRACE:
			set_bit(NFS_DELEGATED_STATE, &state->flags);
			ssleep(1);
			return -EAGAIN;
1589 1590 1591 1592
		case -ENOMEM:
		case -NFS4ERR_DENIED:
			/* kill_proc(fl->fl_pid, SIGLOST, 1); */
			return 0;
1593
	}
L
Linus Torvalds 已提交
1594 1595 1596
	return err;
}

1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	struct nfs4_opendata *opendata;
	int err;

	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);
	err = nfs4_open_recover(opendata, state);
	nfs4_opendata_put(opendata);
	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
}

1613 1614 1615 1616 1617
static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;

	data->rpc_status = task->tk_status;
1618
	if (data->rpc_status == 0) {
1619
		nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid);
1620
		nfs_confirm_seqid(&data->owner->so_seqid, 0);
1621
		renew_lease(data->o_res.server, data->timestamp);
1622
		data->rpc_done = 1;
1623
	}
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
}

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! */
1635
	if (!data->rpc_done)
1636 1637
		goto out_free;
	state = nfs4_opendata_to_nfs4_state(data);
1638
	if (!IS_ERR(state))
1639
		nfs4_close_state(state, data->o_arg.fmode);
1640
out_free:
1641
	nfs4_opendata_put(data);
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
}

static const struct rpc_call_ops nfs4_open_confirm_ops = {
	.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)
{
	struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
	struct rpc_task *task;
1656 1657 1658 1659 1660 1661
	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 已提交
1662 1663
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
1664
		.rpc_message = &msg,
T
Trond Myklebust 已提交
1665 1666
		.callback_ops = &nfs4_open_confirm_ops,
		.callback_data = data,
1667
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
1668 1669
		.flags = RPC_TASK_ASYNC,
	};
L
Linus Torvalds 已提交
1670 1671
	int status;

1672
	kref_get(&data->kref);
1673 1674
	data->rpc_done = 0;
	data->rpc_status = 0;
1675
	data->timestamp = jiffies;
T
Trond Myklebust 已提交
1676
	task = rpc_run_task(&task_setup_data);
1677
	if (IS_ERR(task))
1678 1679 1680 1681 1682 1683 1684
		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;
1685
	rpc_put_task(task);
L
Linus Torvalds 已提交
1686 1687 1688
	return status;
}

1689
static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
1690
{
1691 1692
	struct nfs4_opendata *data = calldata;
	struct nfs4_state_owner *sp = data->owner;
1693
	struct nfs_client *clp = sp->so_server->nfs_client;
1694

1695
	if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
1696
		goto out_wait;
1697 1698 1699 1700 1701 1702 1703
	/*
	 * 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;

1704
		if (can_open_cached(data->state, data->o_arg.fmode, data->o_arg.open_flags))
1705
			goto out_no_action;
1706 1707
		rcu_read_lock();
		delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
1708
		if (data->o_arg.claim != NFS4_OPEN_CLAIM_DELEGATE_CUR &&
1709
		    data->o_arg.claim != NFS4_OPEN_CLAIM_DELEG_CUR_FH &&
1710 1711
		    can_open_delegated(delegation, data->o_arg.fmode))
			goto unlock_no_action;
1712 1713
		rcu_read_unlock();
	}
1714
	/* Update client id. */
1715
	data->o_arg.clientid = clp->cl_clientid;
1716 1717 1718 1719
	switch (data->o_arg.claim) {
	case NFS4_OPEN_CLAIM_PREVIOUS:
	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
	case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
1720
		data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
1721 1722
	case NFS4_OPEN_CLAIM_FH:
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
T
Trond Myklebust 已提交
1723 1724
		nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
	}
1725
	data->timestamp = jiffies;
1726
	if (nfs4_setup_sequence(data->o_arg.server,
1727
				&data->o_arg.seq_args,
1728 1729 1730
				&data->o_res.seq_res,
				task) != 0)
		nfs_release_seqid(data->o_arg.seqid);
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740

	/* 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;
	}
1741
	return;
1742 1743
unlock_no_action:
	rcu_read_unlock();
1744 1745
out_no_action:
	task->tk_action = NULL;
1746
out_wait:
1747
	nfs4_sequence_done(task, &data->o_res.seq_res);
1748 1749
}

1750 1751 1752
static void nfs4_open_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_opendata *data = calldata;
L
Linus Torvalds 已提交
1753

1754
	data->rpc_status = task->tk_status;
1755

1756 1757
	if (!nfs4_sequence_done(task, &data->o_res.seq_res))
		return;
1758

1759
	if (task->tk_status == 0) {
1760 1761
		if (data->o_res.f_attr->valid & NFS_ATTR_FATTR_TYPE) {
			switch (data->o_res.f_attr->mode & S_IFMT) {
1762 1763 1764
			case S_IFREG:
				break;
			case S_IFLNK:
1765
				data->rpc_status = -ELOOP;
1766 1767
				break;
			case S_IFDIR:
1768
				data->rpc_status = -EISDIR;
1769 1770
				break;
			default:
1771
				data->rpc_status = -ENOTDIR;
1772
			}
1773
		}
1774
		renew_lease(data->o_res.server, data->timestamp);
1775 1776
		if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
			nfs_confirm_seqid(&data->owner->so_seqid, 0);
1777
	}
1778
	data->rpc_done = 1;
1779
}
1780

1781 1782 1783 1784 1785 1786 1787 1788 1789
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! */
1790
	if (data->rpc_status != 0 || !data->rpc_done)
1791 1792 1793 1794 1795
		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);
1796
	if (!IS_ERR(state))
1797
		nfs4_close_state(state, data->o_arg.fmode);
1798
out_free:
1799
	nfs4_opendata_put(data);
1800 1801 1802 1803 1804 1805 1806 1807
}

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

1808
static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
1809 1810 1811 1812 1813 1814
{
	struct inode *dir = data->dir->d_inode;
	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;
1815 1816 1817 1818 1819 1820
	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 已提交
1821 1822
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
1823
		.rpc_message = &msg,
T
Trond Myklebust 已提交
1824 1825
		.callback_ops = &nfs4_open_ops,
		.callback_data = data,
1826
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
1827 1828
		.flags = RPC_TASK_ASYNC,
	};
1829 1830
	int status;

1831
	nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
1832
	kref_get(&data->kref);
1833 1834
	data->rpc_done = 0;
	data->rpc_status = 0;
1835
	data->cancelled = 0;
1836 1837
	data->is_recover = 0;
	if (isrecover) {
1838
		nfs4_set_sequence_privileged(&o_arg->seq_args);
1839 1840
		data->is_recover = 1;
	}
T
Trond Myklebust 已提交
1841
	task = rpc_run_task(&task_setup_data);
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864
        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)
{
	struct inode *dir = data->dir->d_inode;
	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;

1865 1866
	nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr);

1867 1868 1869 1870 1871 1872 1873 1874 1875
	if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
		status = _nfs4_proc_open_confirm(data);
		if (status != 0)
			return status;
	}

	return status;
}

1876 1877
static int nfs4_opendata_access(struct rpc_cred *cred,
				struct nfs4_opendata *opendata,
1878 1879
				struct nfs4_state *state, fmode_t fmode,
				int openflags)
1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
{
	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;
1890
	/* don't check MAY_WRITE - a newly created file may not have
1891 1892 1893 1894 1895 1896 1897 1898
	 * write mode bits, but POSIX allows the creating process to write.
	 * use openflags to check for exec, because fmode won't
	 * always have FMODE_EXEC set when file open for exec. */
	if (openflags & __FMODE_EXEC) {
		/* ONLY check for exec rights */
		mask = MAY_EXEC;
	} else if (fmode & FMODE_READ)
		mask = MAY_READ;
1899 1900 1901 1902 1903 1904

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

1905
	if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
1906 1907 1908 1909
		return 0;

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

1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924
/*
 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
 */
static int _nfs4_proc_open(struct nfs4_opendata *data)
{
	struct inode *dir = data->dir->d_inode;
	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);
1925 1926 1927 1928 1929 1930
	if (!data->rpc_done)
		return status;
	if (status != 0) {
		if (status == -NFS4ERR_BADNAME &&
				!(o_arg->open_flags & O_CREAT))
			return -ENOENT;
1931
		return status;
1932
	}
1933

1934 1935
	nfs_fattr_map_and_free_names(server, &data->f_attr);

1936
	if (o_arg->open_flags & O_CREAT)
1937
		update_changeattr(dir, &o_res->cinfo);
T
Trond Myklebust 已提交
1938 1939
	if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
		server->caps &= ~NFS_CAP_POSIX_LOCK;
L
Linus Torvalds 已提交
1940
	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
1941
		status = _nfs4_proc_open_confirm(data);
L
Linus Torvalds 已提交
1942
		if (status != 0)
1943
			return status;
L
Linus Torvalds 已提交
1944 1945
	}
	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
1946
		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
1947
	return 0;
L
Linus Torvalds 已提交
1948 1949
}

A
Andy Adamson 已提交
1950 1951 1952 1953 1954
static int nfs4_recover_expired_lease(struct nfs_server *server)
{
	return nfs4_client_recover_expired_lease(server->nfs_client);
}

L
Linus Torvalds 已提交
1955 1956 1957 1958 1959
/*
 * OPEN_EXPIRED:
 * 	reclaim state on the server after a network partition.
 * 	Assumes caller holds the appropriate lock
 */
1960
static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
L
Linus Torvalds 已提交
1961
{
1962
	struct nfs4_opendata *opendata;
1963
	int ret;
L
Linus Torvalds 已提交
1964

1965
	opendata = nfs4_open_recoverdata_alloc(ctx, state,
1966
			NFS4_OPEN_CLAIM_FH);
T
Trond Myklebust 已提交
1967 1968
	if (IS_ERR(opendata))
		return PTR_ERR(opendata);
1969
	ret = nfs4_open_recover(opendata, state);
1970
	if (ret == -ESTALE)
1971
		d_drop(ctx->dentry);
1972
	nfs4_opendata_put(opendata);
1973
	return ret;
L
Linus Torvalds 已提交
1974 1975
}

1976
static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
1977
{
1978
	struct nfs_server *server = NFS_SERVER(state->inode);
1979 1980 1981 1982
	struct nfs4_exception exception = { };
	int err;

	do {
1983
		err = _nfs4_open_expired(ctx, state);
1984
		trace_nfs4_open_expired(ctx, 0, err);
1985 1986
		if (nfs4_clear_cap_atomic_open_v1(server, err, &exception))
			continue;
1987 1988 1989 1990 1991 1992 1993 1994
		switch (err) {
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
1995
	} while (exception.retry);
1996
out:
1997 1998 1999
	return err;
}

L
Linus Torvalds 已提交
2000 2001 2002
static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
	struct nfs_open_context *ctx;
2003
	int ret;
L
Linus Torvalds 已提交
2004

2005 2006
	ctx = nfs4_state_find_open_context(state);
	if (IS_ERR(ctx))
2007
		return -EAGAIN;
2008
	ret = nfs4_do_open_expired(ctx, state);
2009 2010
	put_nfs_open_context(ctx);
	return ret;
L
Linus Torvalds 已提交
2011 2012
}

2013
#if defined(CONFIG_NFS_V4_1)
2014
static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
2015 2016
{
	struct nfs_server *server = NFS_SERVER(state->inode);
2017
	nfs4_stateid *stateid = &state->stateid;
2018 2019 2020
	struct nfs_delegation *delegation;
	struct rpc_cred *cred = NULL;
	int status = -NFS4ERR_BAD_STATEID;
2021 2022 2023 2024 2025

	/* If a state reset has been done, test_stateid is unneeded */
	if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
		return;

2026 2027 2028 2029 2030 2031 2032 2033
	/* Get the delegation credential for use by test/free_stateid */
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(state->inode)->delegation);
	if (delegation != NULL &&
	    nfs4_stateid_match(&delegation->stateid, stateid)) {
		cred = get_rpccred(delegation->cred);
		rcu_read_unlock();
		status = nfs41_test_stateid(server, stateid, cred);
2034
		trace_nfs4_test_delegation_stateid(state, NULL, status);
2035 2036 2037
	} else
		rcu_read_unlock();

2038 2039 2040 2041
	if (status != NFS_OK) {
		/* Free the stateid unless the server explicitly
		 * informs us the stateid is unrecognized. */
		if (status != -NFS4ERR_BAD_STATEID)
2042
			nfs41_free_stateid(server, stateid, cred);
2043
		nfs_remove_bad_delegation(state->inode);
2044

2045 2046 2047
		write_seqlock(&state->seqlock);
		nfs4_stateid_copy(&state->stateid, &state->open_stateid);
		write_sequnlock(&state->seqlock);
2048 2049
		clear_bit(NFS_DELEGATED_STATE, &state->flags);
	}
2050 2051 2052

	if (cred != NULL)
		put_rpccred(cred);
2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
}

/**
 * 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);
2066
	nfs4_stateid *stateid = &state->open_stateid;
2067
	struct rpc_cred *cred = state->owner->so_cred;
2068 2069 2070 2071 2072 2073 2074 2075
	int status;

	/* If a state reset has been done, test_stateid is unneeded */
	if ((test_bit(NFS_O_RDONLY_STATE, &state->flags) == 0) &&
	    (test_bit(NFS_O_WRONLY_STATE, &state->flags) == 0) &&
	    (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0))
		return -NFS4ERR_BAD_STATEID;

2076
	status = nfs41_test_stateid(server, stateid, cred);
2077
	trace_nfs4_test_open_stateid(state, NULL, status);
2078 2079 2080 2081
	if (status != NFS_OK) {
		/* Free the stateid unless the server explicitly
		 * informs us the stateid is unrecognized. */
		if (status != -NFS4ERR_BAD_STATEID)
2082
			nfs41_free_stateid(server, stateid, cred);
2083 2084 2085 2086

		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
		clear_bit(NFS_O_RDWR_STATE, &state->flags);
2087
		clear_bit(NFS_OPEN_STATE, &state->flags);
2088 2089 2090 2091 2092 2093
	}
	return status;
}

static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
2094
	int status;
2095

2096 2097
	nfs41_clear_delegation_stateid(state);
	status = nfs41_check_open_stateid(state);
2098 2099 2100
	if (status != NFS_OK)
		status = nfs4_open_expired(sp, state);
	return status;
2101 2102 2103
}
#endif

2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119
/*
 * 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
 */
static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
{
	if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
	    !(sattr->ia_valid & ATTR_ATIME_SET))
		sattr->ia_valid |= ATTR_ATIME;

	if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
	    !(sattr->ia_valid & ATTR_MTIME_SET))
		sattr->ia_valid |= ATTR_MTIME;
}

2120 2121 2122
static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
		fmode_t fmode,
		int flags,
2123
		struct nfs_open_context *ctx)
2124 2125 2126
{
	struct nfs4_state_owner *sp = opendata->owner;
	struct nfs_server *server = sp->so_server;
2127
	struct dentry *dentry;
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
	struct nfs4_state *state;
	unsigned int seq;
	int ret;

	seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);

	ret = _nfs4_proc_open(opendata);
	if (ret != 0)
		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);

2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159
	dentry = opendata->dentry;
	if (dentry->d_inode == NULL) {
		/* FIXME: Is this d_drop() ever needed? */
		d_drop(dentry);
		dentry = d_add_unique(dentry, igrab(state->inode));
		if (dentry == NULL) {
			dentry = opendata->dentry;
		} else if (dentry != ctx->dentry) {
			dput(ctx->dentry);
			ctx->dentry = dget(dentry);
		}
		nfs_set_verifier(dentry,
				nfs_save_change_attribute(opendata->dir->d_inode));
	}

2160 2161 2162 2163
	ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags);
	if (ret != 0)
		goto out;

2164
	ctx->state = state;
2165 2166 2167 2168 2169
	if (dentry->d_inode == state->inode) {
		nfs_inode_attach_open_context(ctx);
		if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
			nfs4_schedule_stateid_recovery(server, state);
	}
2170 2171 2172 2173
out:
	return ret;
}

L
Linus Torvalds 已提交
2174
/*
2175
 * Returns a referenced nfs4_state
L
Linus Torvalds 已提交
2176
 */
2177
static int _nfs4_do_open(struct inode *dir,
2178
			struct nfs_open_context *ctx,
2179 2180
			int flags,
			struct iattr *sattr,
2181
			struct nfs4_label *label)
L
Linus Torvalds 已提交
2182 2183 2184 2185
{
	struct nfs4_state_owner  *sp;
	struct nfs4_state     *state = NULL;
	struct nfs_server       *server = NFS_SERVER(dir);
2186
	struct nfs4_opendata *opendata;
2187 2188 2189 2190
	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);
2191
	enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL;
2192
	struct nfs4_label *olabel = NULL;
2193
	int status;
L
Linus Torvalds 已提交
2194 2195 2196

	/* Protect against reboot recovery conflicts */
	status = -ENOMEM;
2197 2198
	sp = nfs4_get_state_owner(server, cred, GFP_KERNEL);
	if (sp == NULL) {
L
Linus Torvalds 已提交
2199 2200 2201
		dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
		goto out_err;
	}
2202 2203
	status = nfs4_recover_expired_lease(server);
	if (status != 0)
2204
		goto err_put_state_owner;
2205 2206
	if (dentry->d_inode != NULL)
		nfs4_return_incompatible_delegation(dentry->d_inode, fmode);
2207
	status = -ENOMEM;
2208 2209
	if (dentry->d_inode)
		claim = NFS4_OPEN_CLAIM_FH;
2210
	opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr,
2211
			label, claim, GFP_KERNEL);
2212
	if (opendata == NULL)
T
Trond Myklebust 已提交
2213
		goto err_put_state_owner;
L
Linus Torvalds 已提交
2214

2215 2216 2217 2218 2219 2220 2221 2222
	if (label) {
		olabel = nfs4_label_alloc(server, GFP_KERNEL);
		if (IS_ERR(olabel)) {
			status = PTR_ERR(olabel);
			goto err_opendata_put;
		}
	}

2223 2224 2225
	if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
		opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
		if (!opendata->f_attr.mdsthreshold)
2226
			goto err_free_label;
2227
		opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
2228
	}
2229 2230
	if (dentry->d_inode != NULL)
		opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
2231

2232
	status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx);
2233
	if (status != 0)
2234
		goto err_free_label;
2235
	state = ctx->state;
2236

2237 2238
	if ((opendata->o_arg.open_flags & O_EXCL) &&
	    (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) {
2239 2240 2241 2242 2243
		nfs4_exclusive_attrset(opendata, sattr);

		nfs_fattr_init(opendata->o_res.f_attr);
		status = nfs4_do_setattr(state->inode, cred,
				opendata->o_res.f_attr, sattr,
2244 2245
				state, label, olabel);
		if (status == 0) {
2246
			nfs_setattr_update_inode(state->inode, sattr);
2247
			nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr);
2248
			nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
2249
		}
2250
	}
2251 2252 2253 2254 2255 2256 2257

	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
		*ctx_th = opendata->f_attr.mdsthreshold;
	else
		kfree(opendata->f_attr.mdsthreshold);
	opendata->f_attr.mdsthreshold = NULL;

2258 2259
	nfs4_label_free(olabel);

2260
	nfs4_opendata_put(opendata);
L
Linus Torvalds 已提交
2261 2262
	nfs4_put_state_owner(sp);
	return 0;
2263 2264
err_free_label:
	nfs4_label_free(olabel);
2265
err_opendata_put:
2266
	kfree(opendata->f_attr.mdsthreshold);
2267
	nfs4_opendata_put(opendata);
2268 2269
err_put_state_owner:
	nfs4_put_state_owner(sp);
L
Linus Torvalds 已提交
2270 2271 2272 2273 2274
out_err:
	return status;
}


2275
static struct nfs4_state *nfs4_do_open(struct inode *dir,
2276
					struct nfs_open_context *ctx,
2277 2278
					int flags,
					struct iattr *sattr,
2279
					struct nfs4_label *label)
L
Linus Torvalds 已提交
2280
{
2281
	struct nfs_server *server = NFS_SERVER(dir);
L
Linus Torvalds 已提交
2282 2283 2284 2285 2286
	struct nfs4_exception exception = { };
	struct nfs4_state *res;
	int status;

	do {
2287
		status = _nfs4_do_open(dir, ctx, flags, sattr, label);
2288
		res = ctx->state;
2289
		trace_nfs4_open_file(ctx, flags, status);
L
Linus Torvalds 已提交
2290 2291 2292 2293 2294 2295 2296 2297
		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
2298
		 * doing an OPEN, we assume that nfs_increment_open_seqid() will
L
Linus Torvalds 已提交
2299 2300 2301 2302 2303
		 * 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) {
2304
			pr_warn_ratelimited("NFS: v4 server %s "
2305 2306
					" returned a bad sequence-id error!\n",
					NFS_SERVER(dir)->nfs_client->cl_hostname);
L
Linus Torvalds 已提交
2307 2308 2309
			exception.retry = 1;
			continue;
		}
2310 2311 2312 2313 2314 2315 2316 2317 2318 2319
		/*
		 * 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;
		}
2320 2321 2322 2323 2324
		if (status == -EAGAIN) {
			/* We must have found a delegation */
			exception.retry = 1;
			continue;
		}
2325 2326 2327
		if (nfs4_clear_cap_atomic_open_v1(server, status, &exception))
			continue;
		res = ERR_PTR(nfs4_handle_exception(server,
L
Linus Torvalds 已提交
2328 2329 2330 2331 2332
					status, &exception));
	} while (exception.retry);
	return res;
}

2333 2334
static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			    struct nfs_fattr *fattr, struct iattr *sattr,
2335 2336
			    struct nfs4_state *state, struct nfs4_label *ilabel,
			    struct nfs4_label *olabel)
L
Linus Torvalds 已提交
2337
{
2338
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
2339
        struct nfs_setattrargs  arg = {
2340
                .fh             = NFS_FH(inode),
L
Linus Torvalds 已提交
2341 2342 2343
                .iap            = sattr,
		.server		= server,
		.bitmask = server->attr_bitmask,
2344
		.label		= ilabel,
L
Linus Torvalds 已提交
2345 2346 2347
        };
        struct nfs_setattrres  res = {
		.fattr		= fattr,
2348
		.label		= olabel,
L
Linus Torvalds 已提交
2349 2350 2351
		.server		= server,
        };
        struct rpc_message msg = {
2352 2353 2354 2355
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
2356
        };
2357
	unsigned long timestamp = jiffies;
2358 2359
	fmode_t fmode;
	bool truncate;
2360
	int status;
L
Linus Torvalds 已提交
2361

2362 2363 2364 2365
	arg.bitmask = nfs4_bitmask(server, ilabel);
	if (ilabel)
		arg.bitmask = nfs4_bitmask(server, olabel);

2366
	nfs_fattr_init(fattr);
L
Linus Torvalds 已提交
2367

2368 2369 2370 2371 2372 2373 2374
	/* Servers should only apply open mode checks for file size changes */
	truncate = (sattr->ia_valid & ATTR_SIZE) ? true : false;
	fmode = truncate ? FMODE_WRITE : FMODE_READ;

	if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) {
		/* Use that stateid */
	} else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) {
2375 2376 2377 2378
		struct nfs_lockowner lockowner = {
			.l_owner = current->files,
			.l_pid = current->tgid,
		};
2379
		nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
2380
				&lockowner);
2381
	} else
2382
		nfs4_stateid_copy(&arg.stateid, &zero_stateid);
L
Linus Torvalds 已提交
2383

2384
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
2385 2386
	if (status == 0 && state != NULL)
		renew_lease(server, timestamp);
2387
	return status;
L
Linus Torvalds 已提交
2388 2389
}

2390 2391
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
			   struct nfs_fattr *fattr, struct iattr *sattr,
2392 2393
			   struct nfs4_state *state, struct nfs4_label *ilabel,
			   struct nfs4_label *olabel)
L
Linus Torvalds 已提交
2394
{
2395
	struct nfs_server *server = NFS_SERVER(inode);
2396 2397
	struct nfs4_exception exception = {
		.state = state,
2398
		.inode = inode,
2399
	};
L
Linus Torvalds 已提交
2400 2401
	int err;
	do {
2402
		err = _nfs4_do_setattr(inode, cred, fattr, sattr, state, ilabel, olabel);
2403
		trace_nfs4_setattr(inode, err);
2404 2405
		switch (err) {
		case -NFS4ERR_OPENMODE:
2406 2407 2408 2409 2410 2411 2412
			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);
			}
2413 2414 2415 2416 2417 2418 2419 2420
			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 已提交
2421
	} while (exception.retry);
2422
out:
L
Linus Torvalds 已提交
2423 2424 2425 2426 2427 2428 2429 2430
	return err;
}

struct nfs4_closedata {
	struct inode *inode;
	struct nfs4_state *state;
	struct nfs_closeargs arg;
	struct nfs_closeres res;
2431
	struct nfs_fattr fattr;
2432
	unsigned long timestamp;
F
Fred Isaman 已提交
2433 2434
	bool roc;
	u32 roc_barrier;
L
Linus Torvalds 已提交
2435 2436
};

2437
static void nfs4_free_closedata(void *data)
2438
{
2439 2440
	struct nfs4_closedata *calldata = data;
	struct nfs4_state_owner *sp = calldata->state->owner;
2441
	struct super_block *sb = calldata->state->inode->i_sb;
2442

F
Fred Isaman 已提交
2443 2444
	if (calldata->roc)
		pnfs_roc_release(calldata->state->inode);
2445 2446 2447
	nfs4_put_open_state(calldata->state);
	nfs_free_seqid(calldata->arg.seqid);
	nfs4_put_state_owner(sp);
2448
	nfs_sb_deactive(sb);
2449 2450 2451
	kfree(calldata);
}

2452 2453 2454 2455
static void nfs4_close_clear_stateid_flags(struct nfs4_state *state,
		fmode_t fmode)
{
	spin_lock(&state->owner->so_lock);
2456 2457 2458
	clear_bit(NFS_O_RDWR_STATE, &state->flags);
	switch (fmode & (FMODE_READ|FMODE_WRITE)) {
	case FMODE_WRITE:
2459
		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
2460 2461
		break;
	case FMODE_READ:
2462
		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
2463 2464 2465 2466 2467 2468
		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);
	}
2469 2470 2471
	spin_unlock(&state->owner->so_lock);
}

2472
static void nfs4_close_done(struct rpc_task *task, void *data)
L
Linus Torvalds 已提交
2473
{
2474
	struct nfs4_closedata *calldata = data;
L
Linus Torvalds 已提交
2475 2476 2477
	struct nfs4_state *state = calldata->state;
	struct nfs_server *server = NFS_SERVER(calldata->inode);

2478
	dprintk("%s: begin!\n", __func__);
2479 2480
	if (!nfs4_sequence_done(task, &calldata->res.seq_res))
		return;
2481
	trace_nfs4_close(state, &calldata->arg, &calldata->res, task->tk_status);
L
Linus Torvalds 已提交
2482 2483 2484 2485 2486
        /* 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:
F
Fred Isaman 已提交
2487 2488 2489
			if (calldata->roc)
				pnfs_roc_set_barrier(state->inode,
						     calldata->roc_barrier);
2490
			nfs_set_open_stateid(state, &calldata->res.stateid, 0);
2491
			renew_lease(server, calldata->timestamp);
2492 2493
			nfs4_close_clear_stateid_flags(state,
					calldata->arg.fmode);
L
Linus Torvalds 已提交
2494 2495
			break;
		case -NFS4ERR_STALE_STATEID:
2496 2497
		case -NFS4ERR_OLD_STATEID:
		case -NFS4ERR_BAD_STATEID:
L
Linus Torvalds 已提交
2498
		case -NFS4ERR_EXPIRED:
2499
			if (calldata->arg.fmode == 0)
2500
				break;
L
Linus Torvalds 已提交
2501
		default:
2502 2503
			if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
				rpc_restart_call_prepare(task);
L
Linus Torvalds 已提交
2504
	}
2505
	nfs_release_seqid(calldata->arg.seqid);
2506
	nfs_refresh_inode(calldata->inode, calldata->res.fattr);
2507
	dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
L
Linus Torvalds 已提交
2508 2509
}

T
Trond Myklebust 已提交
2510
static void nfs4_close_prepare(struct rpc_task *task, void *data)
L
Linus Torvalds 已提交
2511
{
T
Trond Myklebust 已提交
2512
	struct nfs4_closedata *calldata = data;
2513
	struct nfs4_state *state = calldata->state;
2514
	struct inode *inode = calldata->inode;
2515
	int call_close = 0;
2516

2517
	dprintk("%s: begin!\n", __func__);
2518
	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
2519
		goto out_wait;
2520

2521 2522
	task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
	calldata->arg.fmode = FMODE_READ|FMODE_WRITE;
2523
	spin_lock(&state->owner->so_lock);
2524
	/* Calculate the change in open mode */
2525
	if (state->n_rdwr == 0) {
2526
		if (state->n_rdonly == 0) {
2527 2528 2529
			call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
			call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
			calldata->arg.fmode &= ~FMODE_READ;
2530 2531
		}
		if (state->n_wronly == 0) {
2532 2533 2534
			call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
			call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
			calldata->arg.fmode &= ~FMODE_WRITE;
2535
		}
2536
	}
2537 2538
	if (!nfs4_valid_open_stateid(state))
		call_close = 0;
2539
	spin_unlock(&state->owner->so_lock);
2540 2541

	if (!call_close) {
2542
		/* Note: exit _without_ calling nfs4_close_done */
2543
		goto out_no_action;
2544
	}
2545

F
Fred Isaman 已提交
2546
	if (calldata->arg.fmode == 0) {
2547
		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
F
Fred Isaman 已提交
2548
		if (calldata->roc &&
2549 2550
		    pnfs_roc_drain(inode, &calldata->roc_barrier, task)) {
			nfs_release_seqid(calldata->arg.seqid);
2551
			goto out_wait;
2552
		    }
F
Fred Isaman 已提交
2553
	}
2554

2555
	nfs_fattr_init(calldata->res.fattr);
2556
	calldata->timestamp = jiffies;
2557
	if (nfs4_setup_sequence(NFS_SERVER(inode),
2558 2559
				&calldata->arg.seq_args,
				&calldata->res.seq_res,
2560 2561
				task) != 0)
		nfs_release_seqid(calldata->arg.seqid);
2562
	dprintk("%s: done!\n", __func__);
2563 2564 2565 2566 2567
	return;
out_no_action:
	task->tk_action = NULL;
out_wait:
	nfs4_sequence_done(task, &calldata->res.seq_res);
L
Linus Torvalds 已提交
2568 2569
}

2570
static const struct rpc_call_ops nfs4_close_ops = {
T
Trond Myklebust 已提交
2571
	.rpc_call_prepare = nfs4_close_prepare,
2572 2573 2574 2575
	.rpc_call_done = nfs4_close_done,
	.rpc_release = nfs4_free_closedata,
};

L
Linus Torvalds 已提交
2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586
/* 
 * 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!
 */
2587
int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
L
Linus Torvalds 已提交
2588
{
2589
	struct nfs_server *server = NFS_SERVER(state->inode);
L
Linus Torvalds 已提交
2590
	struct nfs4_closedata *calldata;
2591 2592
	struct nfs4_state_owner *sp = state->owner;
	struct rpc_task *task;
2593 2594 2595 2596
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
		.rpc_cred = state->owner->so_cred,
	};
T
Trond Myklebust 已提交
2597 2598
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
2599
		.rpc_message = &msg,
T
Trond Myklebust 已提交
2600
		.callback_ops = &nfs4_close_ops,
2601
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
2602 2603
		.flags = RPC_TASK_ASYNC,
	};
2604
	int status = -ENOMEM;
L
Linus Torvalds 已提交
2605

2606
	calldata = kzalloc(sizeof(*calldata), gfp_mask);
L
Linus Torvalds 已提交
2607
	if (calldata == NULL)
2608
		goto out;
2609
	nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1);
2610
	calldata->inode = state->inode;
L
Linus Torvalds 已提交
2611
	calldata->state = state;
2612
	calldata->arg.fh = NFS_FH(state->inode);
2613
	calldata->arg.stateid = &state->open_stateid;
L
Linus Torvalds 已提交
2614
	/* Serialization for the sequence id */
2615
	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid, gfp_mask);
2616 2617
	if (calldata->arg.seqid == NULL)
		goto out_free_calldata;
2618
	calldata->arg.fmode = 0;
2619
	calldata->arg.bitmask = server->cache_consistency_bitmask;
2620
	calldata->res.fattr = &calldata->fattr;
2621
	calldata->res.seqid = calldata->arg.seqid;
2622
	calldata->res.server = server;
2623
	calldata->roc = pnfs_roc(state->inode);
2624
	nfs_sb_active(calldata->inode->i_sb);
2625

2626 2627
	msg.rpc_argp = &calldata->arg;
	msg.rpc_resp = &calldata->res;
T
Trond Myklebust 已提交
2628 2629
	task_setup_data.callback_data = calldata;
	task = rpc_run_task(&task_setup_data);
2630 2631
	if (IS_ERR(task))
		return PTR_ERR(task);
2632 2633 2634
	status = 0;
	if (wait)
		status = rpc_wait_for_completion_task(task);
2635
	rpc_put_task(task);
2636
	return status;
2637 2638 2639
out_free_calldata:
	kfree(calldata);
out:
2640 2641
	nfs4_put_open_state(state);
	nfs4_put_state_owner(sp);
2642
	return status;
L
Linus Torvalds 已提交
2643 2644
}

2645
static struct inode *
2646
nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
L
Linus Torvalds 已提交
2647 2648
{
	struct nfs4_state *state;
2649 2650 2651
	struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;

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

T
Trond Myklebust 已提交
2653
	/* Protect against concurrent sillydeletes */
2654
	state = nfs4_do_open(dir, ctx, open_flags, attr, label);
2655 2656 2657

	nfs4_label_release_security(label);

2658 2659
	if (IS_ERR(state))
		return ERR_CAST(state);
2660
	return state->inode;
L
Linus Torvalds 已提交
2661 2662
}

2663
static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
T
Trond Myklebust 已提交
2664 2665 2666 2667
{
	if (ctx->state == NULL)
		return;
	if (is_sync)
2668
		nfs4_close_sync(ctx->state, ctx->mode);
T
Trond Myklebust 已提交
2669
	else
2670
		nfs4_close_state(ctx->state, ctx->mode);
T
Trond Myklebust 已提交
2671
}
L
Linus Torvalds 已提交
2672 2673 2674

static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
B
Benny Halevy 已提交
2675 2676 2677
	struct nfs4_server_caps_arg args = {
		.fhandle = fhandle,
	};
L
Linus Torvalds 已提交
2678 2679 2680
	struct nfs4_server_caps_res res = {};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
B
Benny Halevy 已提交
2681
		.rpc_argp = &args,
L
Linus Torvalds 已提交
2682 2683 2684 2685
		.rpc_resp = &res,
	};
	int status;

2686
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
2687 2688
	if (status == 0) {
		memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
2689 2690 2691 2692 2693
		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|
				NFS_CAP_CTIME|NFS_CAP_MTIME);
L
Linus Torvalds 已提交
2694 2695 2696 2697 2698 2699
		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
			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;
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715
		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;
2716 2717 2718 2719 2720 2721
#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));
2722

2723 2724 2725 2726
		if (server->caps & NFS_CAP_SECURITY_LABEL) {
			server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
			res.attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
		}
2727 2728 2729
		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;
L
Linus Torvalds 已提交
2730
		server->acl_bitmask = res.acl_bitmask;
2731
		server->fh_expire_type = res.fh_expire_type;
L
Linus Torvalds 已提交
2732
	}
A
Andy Adamson 已提交
2733

L
Linus Torvalds 已提交
2734 2735 2736
	return status;
}

2737
int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
L
Linus Torvalds 已提交
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751
{
	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)
{
2752
	u32 bitmask[3];
L
Linus Torvalds 已提交
2753
	struct nfs4_lookup_root_arg args = {
2754
		.bitmask = bitmask,
L
Linus Torvalds 已提交
2755 2756 2757
	};
	struct nfs4_lookup_res res = {
		.server = server,
2758
		.fattr = info->fattr,
L
Linus Torvalds 已提交
2759 2760 2761 2762 2763 2764 2765
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
2766

2767 2768 2769 2770 2771 2772 2773
	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;

2774
	nfs_fattr_init(info->fattr);
2775
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
2776 2777 2778 2779 2780 2781 2782 2783
}

static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
		struct nfs_fsinfo *info)
{
	struct nfs4_exception exception = { };
	int err;
	do {
2784
		err = _nfs4_lookup_root(server, fhandle, info);
2785
		trace_nfs4_lookup_root(server, fhandle, info->fattr, err);
2786 2787 2788
		switch (err) {
		case 0:
		case -NFS4ERR_WRONGSEC:
2789
			goto out;
2790 2791 2792
		default:
			err = nfs4_handle_exception(server, err, &exception);
		}
L
Linus Torvalds 已提交
2793
	} while (exception.retry);
2794
out:
L
Linus Torvalds 已提交
2795 2796 2797
	return err;
}

2798 2799 2800
static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fsinfo *info, rpc_authflavor_t flavor)
{
2801 2802 2803
	struct rpc_auth_create_args auth_args = {
		.pseudoflavor = flavor,
	};
2804 2805 2806
	struct rpc_auth *auth;
	int ret;

2807
	auth = rpcauth_create(&auth_args, server->client);
2808
	if (IS_ERR(auth)) {
2809
		ret = -EACCES;
2810 2811 2812 2813 2814 2815 2816
		goto out;
	}
	ret = nfs4_lookup_root(server, fhandle, info);
out:
	return ret;
}

2817 2818 2819 2820 2821 2822 2823 2824 2825
/*
 * 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.
 */
2826
static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
2827
			      struct nfs_fsinfo *info)
L
Linus Torvalds 已提交
2828
{
2829 2830 2831 2832 2833
	/* Per 3530bis 15.33.5 */
	static const rpc_authflavor_t flav_array[] = {
		RPC_AUTH_GSS_KRB5P,
		RPC_AUTH_GSS_KRB5I,
		RPC_AUTH_GSS_KRB5,
2834
		RPC_AUTH_UNIX,			/* courtesy */
2835 2836 2837 2838
		RPC_AUTH_NULL,
	};
	int status = -EPERM;
	size_t i;
C
Chuck Lever 已提交
2839

2840
	for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
2841
		status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
2842
		if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
2843 2844
			continue;
		break;
2845
	}
2846

2847 2848 2849 2850 2851 2852 2853 2854 2855
	/*
	 * -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;
2856 2857 2858
	return status;
}

C
Chuck Lever 已提交
2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872
static int nfs4_do_find_root_sec(struct nfs_server *server,
		struct nfs_fh *fhandle, struct nfs_fsinfo *info)
{
	int mv = server->nfs_client->cl_minorversion;
	return nfs_v4_minor_ops[mv]->find_root_sec(server, fhandle, info);
}

/**
 * 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
 *
 * Returns zero on success, or a negative errno.
2873
 */
2874 2875
int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
			 struct nfs_fsinfo *info)
2876
{
C
Chuck Lever 已提交
2877 2878 2879 2880 2881 2882 2883
	int status;

	status = nfs4_lookup_root(server, fhandle, info);
	if ((status == -NFS4ERR_WRONGSEC) &&
	    !(server->flags & NFS_MOUNT_SECFLAVOUR))
		status = nfs4_do_find_root_sec(server, fhandle, info);

L
Linus Torvalds 已提交
2884 2885 2886 2887
	if (status == 0)
		status = nfs4_server_capabilities(server, fhandle);
	if (status == 0)
		status = nfs4_do_fsinfo(server, fhandle, info);
C
Chuck Lever 已提交
2888

2889
	return nfs4_map_errors(status);
L
Linus Torvalds 已提交
2890 2891
}

2892 2893 2894 2895 2896
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;
2897
	struct nfs4_label *label = NULL;
2898 2899 2900 2901 2902 2903 2904

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

2905 2906 2907 2908
	label = nfs4_label_alloc(server, GFP_KERNEL);
	if (IS_ERR(label))
		return PTR_ERR(label);

2909
	error = nfs4_proc_getattr(server, mntfh, fattr, label);
2910 2911
	if (error < 0) {
		dprintk("nfs4_get_root: getattr error = %d\n", -error);
2912
		goto err_free_label;
2913 2914 2915 2916 2917 2918
	}

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

2919 2920 2921
err_free_label:
	nfs4_label_free(label);

2922 2923 2924
	return error;
}

M
Manoj Naik 已提交
2925 2926 2927 2928 2929
/*
 * 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
 */
2930 2931 2932
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 已提交
2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944
{
	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;

2945
	status = nfs4_proc_fs_locations(client, dir, name, locations, page);
M
Manoj Naik 已提交
2946 2947 2948 2949
	if (status != 0)
		goto out;
	/* Make sure server returned a different fsid for the referral */
	if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
2950 2951
		dprintk("%s: server did not return a different fsid for"
			" a referral at %s\n", __func__, name->name);
M
Manoj Naik 已提交
2952 2953 2954
		status = -EIO;
		goto out;
	}
2955 2956
	/* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
	nfs_fixup_referral_attributes(&locations->fattr);
M
Manoj Naik 已提交
2957

2958
	/* replace the lookup nfs_fattr with the locations nfs_fattr */
M
Manoj Naik 已提交
2959 2960 2961 2962 2963
	memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
	memset(fhandle, 0, sizeof(struct nfs_fh));
out:
	if (page)
		__free_page(page);
2964
	kfree(locations);
M
Manoj Naik 已提交
2965 2966 2967
	return status;
}

2968 2969
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
2970 2971 2972 2973 2974 2975 2976
{
	struct nfs4_getattr_arg args = {
		.fh = fhandle,
		.bitmask = server->attr_bitmask,
	};
	struct nfs4_getattr_res res = {
		.fattr = fattr,
2977
		.label = label,
L
Linus Torvalds 已提交
2978 2979 2980 2981 2982 2983 2984
		.server = server,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
2985 2986 2987

	args.bitmask = nfs4_bitmask(server, label);

2988
	nfs_fattr_init(fattr);
2989
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
2990 2991
}

2992 2993
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
				struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
2994 2995 2996 2997
{
	struct nfs4_exception exception = { };
	int err;
	do {
2998 2999 3000
		err = _nfs4_proc_getattr(server, fhandle, fattr, label);
		trace_nfs4_getattr(server, fhandle, fattr, err);
		err = nfs4_handle_exception(server, err,
L
Linus Torvalds 已提交
3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
				&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)
{
3027
	struct inode *inode = dentry->d_inode;
3028
	struct rpc_cred *cred = NULL;
3029
	struct nfs4_state *state = NULL;
3030
	struct nfs4_label *label = NULL;
L
Linus Torvalds 已提交
3031 3032
	int status;

B
Benny Halevy 已提交
3033
	if (pnfs_ld_layoutret_on_setattr(inode))
3034
		pnfs_commit_and_return_layout(inode);
B
Benny Halevy 已提交
3035

3036
	nfs_fattr_init(fattr);
L
Linus Torvalds 已提交
3037
	
3038 3039
	/* Deal with open(O_TRUNC) */
	if (sattr->ia_valid & ATTR_OPEN)
3040
		sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME);
3041 3042

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

3046
	/* Search for an existing open(O_WRITE) file */
3047 3048 3049 3050
	if (sattr->ia_valid & ATTR_FILE) {
		struct nfs_open_context *ctx;

		ctx = nfs_file_open_context(sattr->ia_file);
N
Neil Brown 已提交
3051 3052 3053 3054
		if (ctx) {
			cred = ctx->cred;
			state = ctx->state;
		}
3055
	}
3056

3057 3058 3059 3060 3061
	label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
	if (IS_ERR(label))
		return PTR_ERR(label);

	status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label);
3062
	if (status == 0) {
3063
		nfs_setattr_update_inode(inode, sattr);
3064 3065
		nfs_setsecurity(inode, fattr, label);
	}
3066
	nfs4_label_free(label);
L
Linus Torvalds 已提交
3067 3068 3069
	return status;
}

3070 3071
static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
		const struct qstr *name, struct nfs_fh *fhandle,
3072
		struct nfs_fattr *fattr, struct nfs4_label *label)
D
David Howells 已提交
3073
{
3074
	struct nfs_server *server = NFS_SERVER(dir);
D
David Howells 已提交
3075 3076 3077
	int		       status;
	struct nfs4_lookup_arg args = {
		.bitmask = server->attr_bitmask,
3078
		.dir_fh = NFS_FH(dir),
D
David Howells 已提交
3079 3080 3081 3082 3083
		.name = name,
	};
	struct nfs4_lookup_res res = {
		.server = server,
		.fattr = fattr,
3084
		.label = label,
D
David Howells 已提交
3085 3086 3087 3088 3089 3090 3091 3092
		.fh = fhandle,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};

3093 3094
	args.bitmask = nfs4_bitmask(server, label);

D
David Howells 已提交
3095 3096
	nfs_fattr_init(fattr);

L
Linus Torvalds 已提交
3097
	dprintk("NFS call  lookup %s\n", name->name);
3098
	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3099 3100 3101 3102
	dprintk("NFS reply lookup: %d\n", status);
	return status;
}

3103
static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
3104 3105
{
	fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
3106
		NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT;
3107 3108 3109 3110
	fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
	fattr->nlink = 2;
}

3111 3112
static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
				   struct qstr *name, struct nfs_fh *fhandle,
3113
				   struct nfs_fattr *fattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3114 3115
{
	struct nfs4_exception exception = { };
3116
	struct rpc_clnt *client = *clnt;
L
Linus Torvalds 已提交
3117 3118
	int err;
	do {
3119
		err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label);
3120
		trace_nfs4_lookup(dir, name, err);
3121
		switch (err) {
3122
		case -NFS4ERR_BADNAME:
3123 3124
			err = -ENOENT;
			goto out;
3125
		case -NFS4ERR_MOVED:
3126
			err = nfs4_get_referral(client, dir, name, fattr, fhandle);
3127
			goto out;
3128
		case -NFS4ERR_WRONGSEC:
3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140
			err = -EPERM;
			if (client != *clnt)
				goto out;

			client = nfs4_create_sec_client(client, dir, name);
			if (IS_ERR(client))
				return PTR_ERR(client);

			exception.retry = 1;
			break;
		default:
			err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
3141
		}
L
Linus Torvalds 已提交
3142
	} while (exception.retry);
3143 3144 3145 3146 3147 3148 3149

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

L
Linus Torvalds 已提交
3150 3151 3152
	return err;
}

3153
static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
3154 3155
			    struct nfs_fh *fhandle, struct nfs_fattr *fattr,
			    struct nfs4_label *label)
3156 3157 3158 3159
{
	int status;
	struct rpc_clnt *client = NFS_CLIENT(dir);

3160
	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label);
3161 3162 3163 3164 3165 3166 3167
	if (client != NFS_CLIENT(dir)) {
		rpc_shutdown_client(client);
		nfs_fixup_secinfo_attributes(fattr);
	}
	return status;
}

3168 3169 3170 3171 3172 3173 3174
struct rpc_clnt *
nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
			    struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
	int status;
	struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));

3175
	status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL);
3176 3177 3178 3179 3180 3181 3182
	if (status < 0) {
		rpc_shutdown_client(client);
		return ERR_PTR(status);
	}
	return client;
}

L
Linus Torvalds 已提交
3183 3184
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
3185
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
3186 3187
	struct nfs4_accessargs args = {
		.fh = NFS_FH(inode),
3188
		.bitmask = server->cache_consistency_bitmask,
3189 3190 3191
	};
	struct nfs4_accessres res = {
		.server = server,
L
Linus Torvalds 已提交
3192 3193 3194 3195 3196 3197 3198 3199
	};
	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;
3200
	int status = 0;
L
Linus Torvalds 已提交
3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217

	/*
	 * 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;
	}
3218 3219 3220 3221 3222

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

3223
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3224
	if (!status) {
3225
		nfs_access_set_mask(entry, res.access);
3226
		nfs_refresh_inode(inode, res.fattr);
L
Linus Torvalds 已提交
3227
	}
3228
	nfs_free_fattr(res.fattr);
L
Linus Torvalds 已提交
3229 3230 3231 3232 3233 3234 3235 3236
	return status;
}

static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3237 3238 3239
		err = _nfs4_proc_access(inode, entry);
		trace_nfs4_access(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
L
Linus Torvalds 已提交
3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261
				&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
3262
 * we get the post-operation mtime and size.
L
Linus Torvalds 已提交
3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275
 *
 * 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 已提交
3276
	struct nfs4_readlink_res res;
L
Linus Torvalds 已提交
3277 3278 3279
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
		.rpc_argp = &args,
B
Benny Halevy 已提交
3280
		.rpc_resp = &res,
L
Linus Torvalds 已提交
3281 3282
	};

3283
	return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3284 3285 3286 3287 3288 3289 3290 3291
}

static int nfs4_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3292 3293 3294
		err = _nfs4_proc_readlink(inode, page, pgbase, pglen);
		trace_nfs4_readlink(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
L
Linus Torvalds 已提交
3295 3296 3297 3298 3299 3300
				&exception);
	} while (exception.retry);
	return err;
}

/*
3301
 * This is just for mknod.  open(O_CREAT) will always do ->open_context().
L
Linus Torvalds 已提交
3302 3303 3304
 */
static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
3305
		 int flags)
L
Linus Torvalds 已提交
3306
{
3307
	struct nfs4_label l, *ilabel = NULL;
3308
	struct nfs_open_context *ctx;
L
Linus Torvalds 已提交
3309 3310 3311
	struct nfs4_state *state;
	int status = 0;

3312 3313 3314 3315
	ctx = alloc_nfs_open_context(dentry, FMODE_READ);
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

3316 3317
	ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);

A
Aneesh Kumar K.V 已提交
3318
	sattr->ia_mode &= ~current_umask();
3319
	state = nfs4_do_open(dir, ctx, flags, sattr, ilabel);
L
Linus Torvalds 已提交
3320 3321
	if (IS_ERR(state)) {
		status = PTR_ERR(state);
3322
		goto out;
L
Linus Torvalds 已提交
3323 3324
	}
out:
3325
	nfs4_label_release_security(ilabel);
3326
	put_nfs_open_context(ctx);
L
Linus Torvalds 已提交
3327 3328 3329 3330 3331
	return status;
}

static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
{
3332
	struct nfs_server *server = NFS_SERVER(dir);
3333
	struct nfs_removeargs args = {
L
Linus Torvalds 已提交
3334
		.fh = NFS_FH(dir),
3335
		.name = *name,
3336
	};
3337
	struct nfs_removeres res = {
3338
		.server = server,
L
Linus Torvalds 已提交
3339 3340
	};
	struct rpc_message msg = {
3341 3342 3343
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
		.rpc_argp = &args,
		.rpc_resp = &res,
L
Linus Torvalds 已提交
3344
	};
3345
	int status;
L
Linus Torvalds 已提交
3346

3347
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
3348
	if (status == 0)
3349
		update_changeattr(dir, &res.cinfo);
L
Linus Torvalds 已提交
3350 3351 3352 3353 3354 3355 3356 3357
	return status;
}

static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3358 3359 3360
		err = _nfs4_proc_remove(dir, name);
		trace_nfs4_remove(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
L
Linus Torvalds 已提交
3361 3362 3363 3364 3365
				&exception);
	} while (exception.retry);
	return err;
}

3366
static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
L
Linus Torvalds 已提交
3367
{
3368 3369 3370
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs_removeargs *args = msg->rpc_argp;
	struct nfs_removeres *res = msg->rpc_resp;
L
Linus Torvalds 已提交
3371

3372
	res->server = server;
L
Linus Torvalds 已提交
3373
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
3374
	nfs4_init_sequence(&args->seq_args, &res->seq_res, 1);
3375 3376

	nfs_fattr_init(res->dir_attr);
L
Linus Torvalds 已提交
3377 3378
}

3379 3380
static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
{
3381 3382 3383 3384
	nfs4_setup_sequence(NFS_SERVER(data->dir),
			&data->args.seq_args,
			&data->res.seq_res,
			task);
L
Linus Torvalds 已提交
3385 3386
}

3387
static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
L
Linus Torvalds 已提交
3388
{
3389 3390
	struct nfs_unlinkdata *data = task->tk_calldata;
	struct nfs_removeres *res = &data->res;
3391

3392 3393
	if (!nfs4_sequence_done(task, &res->seq_res))
		return 0;
3394
	if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
3395 3396 3397
		return 0;
	update_changeattr(dir, &res->cinfo);
	return 1;
L
Linus Torvalds 已提交
3398 3399
}

3400 3401 3402 3403 3404 3405 3406 3407
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;
3408
	nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1);
3409 3410
}

3411 3412
static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
{
3413 3414 3415 3416
	nfs4_setup_sequence(NFS_SERVER(data->old_dir),
			&data->args.seq_args,
			&data->res.seq_res,
			task);
3417 3418 3419 3420 3421
}

static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
				 struct inode *new_dir)
{
3422 3423
	struct nfs_renamedata *data = task->tk_calldata;
	struct nfs_renameres *res = &data->res;
3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434

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

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

L
Linus Torvalds 已提交
3435 3436 3437
static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
		struct inode *new_dir, struct qstr *new_name)
{
3438
	struct nfs_server *server = NFS_SERVER(old_dir);
3439
	struct nfs_renameargs arg = {
L
Linus Torvalds 已提交
3440 3441 3442 3443
		.old_dir = NFS_FH(old_dir),
		.new_dir = NFS_FH(new_dir),
		.old_name = old_name,
		.new_name = new_name,
3444
	};
3445
	struct nfs_renameres res = {
3446
		.server = server,
L
Linus Torvalds 已提交
3447 3448 3449 3450 3451 3452
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
		.rpc_argp = &arg,
		.rpc_resp = &res,
	};
3453
	int status = -ENOMEM;
3454

3455
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
L
Linus Torvalds 已提交
3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468
	if (!status) {
		update_changeattr(old_dir, &res.old_cinfo);
		update_changeattr(new_dir, &res.new_cinfo);
	}
	return status;
}

static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
		struct inode *new_dir, struct qstr *new_name)
{
	struct nfs4_exception exception = { };
	int err;
	do {
3469 3470 3471 3472
		err = _nfs4_proc_rename(old_dir, old_name,
					new_dir, new_name);
		trace_nfs4_rename(old_dir, old_name, new_dir, new_name, err);
		err = nfs4_handle_exception(NFS_SERVER(old_dir), err,
L
Linus Torvalds 已提交
3473 3474 3475 3476 3477 3478 3479
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
3480
	struct nfs_server *server = NFS_SERVER(inode);
L
Linus Torvalds 已提交
3481 3482 3483 3484
	struct nfs4_link_arg arg = {
		.fh     = NFS_FH(inode),
		.dir_fh = NFS_FH(dir),
		.name   = name,
3485 3486 3487 3488
		.bitmask = server->attr_bitmask,
	};
	struct nfs4_link_res res = {
		.server = server,
3489
		.label = NULL,
L
Linus Torvalds 已提交
3490 3491 3492 3493
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
		.rpc_argp = &arg,
3494
		.rpc_resp = &res,
L
Linus Torvalds 已提交
3495
	};
3496 3497 3498
	int status = -ENOMEM;

	res.fattr = nfs_alloc_fattr();
3499
	if (res.fattr == NULL)
3500
		goto out;
L
Linus Torvalds 已提交
3501

3502 3503 3504 3505 3506
	res.label = nfs4_label_alloc(server, GFP_KERNEL);
	if (IS_ERR(res.label)) {
		status = PTR_ERR(res.label);
		goto out;
	}
3507
	arg.bitmask = nfs4_bitmask(server, res.label);
3508

3509
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
3510 3511
	if (!status) {
		update_changeattr(dir, &res.cinfo);
3512 3513 3514
		status = nfs_post_op_update_inode(inode, res.fattr);
		if (!status)
			nfs_setsecurity(inode, res.fattr, res.label);
3515
	}
3516 3517 3518 3519


	nfs4_label_free(res.label);

3520 3521
out:
	nfs_free_fattr(res.fattr);
L
Linus Torvalds 已提交
3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536
	return status;
}

static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
	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;
}

3537 3538 3539 3540 3541 3542
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;
3543
	struct nfs4_label *label;
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554
};

static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
		struct qstr *name, struct iattr *sattr, u32 ftype)
{
	struct nfs4_createdata *data;

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

3555 3556 3557 3558
		data->label = nfs4_label_alloc(server, GFP_KERNEL);
		if (IS_ERR(data->label))
			goto out_free;

3559 3560 3561 3562 3563 3564 3565 3566
		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;
3567
		data->arg.bitmask = nfs4_bitmask(server, data->label);
3568 3569 3570
		data->res.server = server;
		data->res.fh = &data->fh;
		data->res.fattr = &data->fattr;
3571
		data->res.label = data->label;
3572 3573 3574
		nfs_fattr_init(data->res.fattr);
	}
	return data;
3575 3576 3577
out_free:
	kfree(data);
	return NULL;
3578 3579 3580 3581
}

static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
{
3582
	int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
3583
				    &data->arg.seq_args, &data->res.seq_res, 1);
3584 3585
	if (status == 0) {
		update_changeattr(dir, &data->res.dir_cinfo);
3586
		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
3587 3588 3589 3590 3591 3592
	}
	return status;
}

static void nfs4_free_createdata(struct nfs4_createdata *data)
{
3593
	nfs4_label_free(data->label);
3594 3595 3596
	kfree(data);
}

3597
static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
3598 3599
		struct page *page, unsigned int len, struct iattr *sattr,
		struct nfs4_label *label)
L
Linus Torvalds 已提交
3600
{
3601 3602
	struct nfs4_createdata *data;
	int status = -ENAMETOOLONG;
L
Linus Torvalds 已提交
3603

3604
	if (len > NFS4_MAXPATHLEN)
3605
		goto out;
3606

3607 3608 3609 3610 3611 3612 3613 3614
	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;
3615
	data->arg.label = label;
L
Linus Torvalds 已提交
3616
	
3617 3618 3619 3620
	status = nfs4_do_create(dir, dentry, data);

	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
3621 3622 3623
	return status;
}

3624
static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
3625
		struct page *page, unsigned int len, struct iattr *sattr)
L
Linus Torvalds 已提交
3626 3627
{
	struct nfs4_exception exception = { };
3628
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
3629
	int err;
3630 3631 3632

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

L
Linus Torvalds 已提交
3633
	do {
3634 3635 3636
		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 已提交
3637 3638
				&exception);
	} while (exception.retry);
3639 3640

	nfs4_label_release_security(label);
L
Linus Torvalds 已提交
3641 3642 3643 3644
	return err;
}

static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
3645
		struct iattr *sattr, struct nfs4_label *label)
L
Linus Torvalds 已提交
3646
{
3647 3648
	struct nfs4_createdata *data;
	int status = -ENOMEM;
L
Linus Torvalds 已提交
3649

3650 3651 3652 3653
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4DIR);
	if (data == NULL)
		goto out;

3654
	data->arg.label = label;
3655 3656 3657 3658
	status = nfs4_do_create(dir, dentry, data);

	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
3659 3660 3661 3662 3663 3664 3665
	return status;
}

static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr)
{
	struct nfs4_exception exception = { };
3666
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
3667
	int err;
A
Aneesh Kumar K.V 已提交
3668

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

A
Aneesh Kumar K.V 已提交
3671
	sattr->ia_mode &= ~current_umask();
L
Linus Torvalds 已提交
3672
	do {
3673 3674 3675
		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 已提交
3676 3677
				&exception);
	} while (exception.retry);
3678 3679
	nfs4_label_release_security(label);

L
Linus Torvalds 已提交
3680 3681 3682 3683
	return err;
}

static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
B
Bryan Schumaker 已提交
3684
		u64 cookie, struct page **pages, unsigned int count, int plus)
L
Linus Torvalds 已提交
3685 3686 3687 3688
{
	struct inode		*dir = dentry->d_inode;
	struct nfs4_readdir_arg args = {
		.fh = NFS_FH(dir),
B
Bryan Schumaker 已提交
3689
		.pages = pages,
L
Linus Torvalds 已提交
3690 3691
		.pgbase = 0,
		.count = count,
3692
		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
B
Bryan Schumaker 已提交
3693
		.plus = plus,
L
Linus Torvalds 已提交
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703
	};
	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;

3704
	dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __func__,
3705 3706 3707
			dentry->d_parent->d_name.name,
			dentry->d_name.name,
			(unsigned long long)cookie);
3708
	nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
L
Linus Torvalds 已提交
3709
	res.pgbase = args.pgbase;
3710
	status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
3711
	if (status >= 0) {
3712
		memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
3713 3714
		status += args.pgbase;
	}
3715 3716 3717

	nfs_invalidate_atime(dir);

3718
	dprintk("%s: returns %d\n", __func__, status);
L
Linus Torvalds 已提交
3719 3720 3721 3722
	return status;
}

static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
B
Bryan Schumaker 已提交
3723
		u64 cookie, struct page **pages, unsigned int count, int plus)
L
Linus Torvalds 已提交
3724 3725 3726 3727
{
	struct nfs4_exception exception = { };
	int err;
	do {
3728 3729 3730 3731
		err = _nfs4_proc_readdir(dentry, cred, cookie,
				pages, count, plus);
		trace_nfs4_readdir(dentry->d_inode, err);
		err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), err,
L
Linus Torvalds 已提交
3732 3733 3734 3735 3736 3737
				&exception);
	} while (exception.retry);
	return err;
}

static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
3738
		struct iattr *sattr, struct nfs4_label *label, dev_t rdev)
L
Linus Torvalds 已提交
3739
{
3740 3741 3742
	struct nfs4_createdata *data;
	int mode = sattr->ia_mode;
	int status = -ENOMEM;
L
Linus Torvalds 已提交
3743

3744 3745 3746 3747
	data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK);
	if (data == NULL)
		goto out;

L
Linus Torvalds 已提交
3748
	if (S_ISFIFO(mode))
3749
		data->arg.ftype = NF4FIFO;
L
Linus Torvalds 已提交
3750
	else if (S_ISBLK(mode)) {
3751 3752 3753
		data->arg.ftype = NF4BLK;
		data->arg.u.device.specdata1 = MAJOR(rdev);
		data->arg.u.device.specdata2 = MINOR(rdev);
L
Linus Torvalds 已提交
3754 3755
	}
	else if (S_ISCHR(mode)) {
3756 3757 3758
		data->arg.ftype = NF4CHR;
		data->arg.u.device.specdata1 = MAJOR(rdev);
		data->arg.u.device.specdata2 = MINOR(rdev);
3759 3760 3761
	} else if (!S_ISSOCK(mode)) {
		status = -EINVAL;
		goto out_free;
L
Linus Torvalds 已提交
3762
	}
3763

3764
	data->arg.label = label;
3765
	status = nfs4_do_create(dir, dentry, data);
3766
out_free:
3767 3768
	nfs4_free_createdata(data);
out:
L
Linus Torvalds 已提交
3769 3770 3771 3772 3773 3774 3775
	return status;
}

static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr, dev_t rdev)
{
	struct nfs4_exception exception = { };
3776
	struct nfs4_label l, *label = NULL;
L
Linus Torvalds 已提交
3777
	int err;
A
Aneesh Kumar K.V 已提交
3778

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

A
Aneesh Kumar K.V 已提交
3781
	sattr->ia_mode &= ~current_umask();
L
Linus Torvalds 已提交
3782
	do {
3783 3784 3785
		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 已提交
3786 3787
				&exception);
	} while (exception.retry);
3788 3789 3790

	nfs4_label_release_security(label);

L
Linus Torvalds 已提交
3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
	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 已提交
3801 3802 3803
	struct nfs4_statfs_res res = {
		.fsstat = fsstat,
	};
L
Linus Torvalds 已提交
3804 3805 3806
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
		.rpc_argp = &args,
B
Benny Halevy 已提交
3807
		.rpc_resp = &res,
L
Linus Torvalds 已提交
3808 3809
	};

3810
	nfs_fattr_init(fsstat->fattr);
3811
	return  nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832
}

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 已提交
3833 3834 3835
	struct nfs4_fsinfo_res res = {
		.fsinfo = fsinfo,
	};
L
Linus Torvalds 已提交
3836 3837 3838
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
		.rpc_argp = &args,
B
Benny Halevy 已提交
3839
		.rpc_resp = &res,
L
Linus Torvalds 已提交
3840 3841
	};

3842
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3843 3844 3845 3846 3847
}

static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
	struct nfs4_exception exception = { };
3848
	unsigned long now = jiffies;
L
Linus Torvalds 已提交
3849 3850 3851
	int err;

	do {
3852
		err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
3853
		trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err);
3854 3855 3856 3857 3858 3859 3860 3861 3862 3863
		if (err == 0) {
			struct nfs_client *clp = server->nfs_client;

			spin_lock(&clp->cl_lock);
			clp->cl_lease_time = fsinfo->lease_time * HZ;
			clp->cl_last_renewal = now;
			spin_unlock(&clp->cl_lock);
			break;
		}
		err = nfs4_handle_exception(server, err, &exception);
L
Linus Torvalds 已提交
3864 3865 3866 3867 3868 3869
	} while (exception.retry);
	return err;
}

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

3872
	nfs_fattr_init(fsinfo->fattr);
3873
	error = nfs4_do_fsinfo(server, fhandle, fsinfo);
3874 3875 3876
	if (error == 0) {
		/* block layout checks this! */
		server->pnfs_blksize = fsinfo->blksize;
3877
		set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype);
3878
	}
3879 3880

	return error;
L
Linus Torvalds 已提交
3881 3882 3883 3884 3885 3886 3887 3888 3889
}

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 已提交
3890 3891 3892
	struct nfs4_pathconf_res res = {
		.pathconf = pathconf,
	};
L
Linus Torvalds 已提交
3893 3894 3895
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
		.rpc_argp = &args,
B
Benny Halevy 已提交
3896
		.rpc_resp = &res,
L
Linus Torvalds 已提交
3897 3898 3899 3900 3901 3902 3903 3904
	};

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

3905
	nfs_fattr_init(pathconf->fattr);
3906
	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
L
Linus Torvalds 已提交
3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922
}

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

3923
int nfs4_set_rw_stateid(nfs4_stateid *stateid,
3924 3925 3926 3927 3928 3929 3930 3931
		const struct nfs_open_context *ctx,
		const struct nfs_lock_context *l_ctx,
		fmode_t fmode)
{
	const struct nfs_lockowner *lockowner = NULL;

	if (l_ctx != NULL)
		lockowner = &l_ctx->lockowner;
3932
	return nfs4_select_rw_stateid(stateid, ctx->state, fmode, lockowner);
3933 3934 3935
}
EXPORT_SYMBOL_GPL(nfs4_set_rw_stateid);

3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962
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;

	if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode))
		return false;
	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;
}

3963 3964
void __nfs4_read_done_cb(struct nfs_read_data *data)
{
3965
	nfs_invalidate_atime(data->header->inode);
3966 3967
}

3968
static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)
L
Linus Torvalds 已提交
3969
{
3970
	struct nfs_server *server = NFS_SERVER(data->header->inode);
L
Linus Torvalds 已提交
3971

3972
	trace_nfs4_read(data, task->tk_status);
3973
	if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
3974
		rpc_restart_call_prepare(task);
T
Trond Myklebust 已提交
3975
		return -EAGAIN;
L
Linus Torvalds 已提交
3976
	}
3977

3978
	__nfs4_read_done_cb(data);
L
Linus Torvalds 已提交
3979
	if (task->tk_status > 0)
T
Trond Myklebust 已提交
3980 3981
		renew_lease(server, data->timestamp);
	return 0;
L
Linus Torvalds 已提交
3982 3983
}

3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997
static bool nfs4_read_stateid_changed(struct rpc_task *task,
		struct nfs_readargs *args)
{

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

3998 3999 4000 4001 4002 4003 4004
static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
{

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

	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return -EAGAIN;
4005 4006
	if (nfs4_read_stateid_changed(task, &data->args))
		return -EAGAIN;
4007 4008
	return data->read_done_cb ? data->read_done_cb(task, data) :
				    nfs4_read_done_cb(task, data);
4009 4010
}

4011
static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
L
Linus Torvalds 已提交
4012 4013
{
	data->timestamp   = jiffies;
4014
	data->read_done_cb = nfs4_read_done_cb;
4015
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
4016
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
L
Linus Torvalds 已提交
4017 4018
}

4019 4020
static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
{
4021
	if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
4022 4023
			&data->args.seq_args,
			&data->res.seq_res,
4024 4025 4026 4027
			task))
		return;
	nfs4_set_rw_stateid(&data->args.stateid, data->args.context,
			data->args.lock_context, FMODE_READ);
L
Linus Torvalds 已提交
4028 4029
}

4030
static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
L
Linus Torvalds 已提交
4031
{
4032
	struct inode *inode = data->header->inode;
L
Linus Torvalds 已提交
4033
	
4034
	trace_nfs4_write(data, task->tk_status);
4035
	if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
4036
		rpc_restart_call_prepare(task);
4037
		return -EAGAIN;
L
Linus Torvalds 已提交
4038
	}
4039
	if (task->tk_status >= 0) {
L
Linus Torvalds 已提交
4040
		renew_lease(NFS_SERVER(inode), data->timestamp);
4041
		nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
4042
	}
4043
	return 0;
L
Linus Torvalds 已提交
4044 4045
}

4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059
static bool nfs4_write_stateid_changed(struct rpc_task *task,
		struct nfs_writeargs *args)
{

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

4060 4061 4062 4063
static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return -EAGAIN;
4064 4065
	if (nfs4_write_stateid_changed(task, &data->args))
		return -EAGAIN;
4066 4067
	return data->write_done_cb ? data->write_done_cb(task, data) :
		nfs4_write_done_cb(task, data);
4068 4069
}

4070 4071
static
bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data)
4072
{
4073 4074 4075 4076 4077 4078 4079 4080
	const struct nfs_pgio_header *hdr = data->header;

	/* Don't request attributes for pNFS or O_DIRECT writes */
	if (data->ds_clp != NULL || hdr->dreq != NULL)
		return false;
	/* Otherwise, request attributes if and only if we don't hold
	 * a delegation
	 */
4081
	return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
4082 4083
}

4084
static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
L
Linus Torvalds 已提交
4085
{
4086
	struct nfs_server *server = NFS_SERVER(data->header->inode);
4087

4088
	if (!nfs4_write_need_cache_consistency_data(data)) {
4089 4090 4091 4092
		data->args.bitmask = NULL;
		data->res.fattr = NULL;
	} else
		data->args.bitmask = server->cache_consistency_bitmask;
4093

4094 4095
	if (!data->write_done_cb)
		data->write_done_cb = nfs4_write_done_cb;
4096
	data->res.server = server;
L
Linus Torvalds 已提交
4097 4098
	data->timestamp   = jiffies;

4099
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
4100
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
L
Linus Torvalds 已提交
4101 4102
}

4103 4104
static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data)
{
4105
	if (nfs4_setup_sequence(NFS_SERVER(data->header->inode),
4106 4107
			&data->args.seq_args,
			&data->res.seq_res,
4108 4109 4110 4111
			task))
		return;
	nfs4_set_rw_stateid(&data->args.stateid, data->args.context,
			data->args.lock_context, FMODE_WRITE);
L
Linus Torvalds 已提交
4112 4113
}

4114
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
4115
{
4116 4117 4118 4119
	nfs4_setup_sequence(NFS_SERVER(data->inode),
			&data->args.seq_args,
			&data->res.seq_res,
			task);
L
Linus Torvalds 已提交
4120 4121
}

4122
static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data)
L
Linus Torvalds 已提交
4123 4124
{
	struct inode *inode = data->inode;
4125

4126
	trace_nfs4_commit(data, task->tk_status);
4127
	if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
4128
		rpc_restart_call_prepare(task);
4129
		return -EAGAIN;
L
Linus Torvalds 已提交
4130
	}
4131
	return 0;
L
Linus Torvalds 已提交
4132 4133
}

4134
static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
4135 4136 4137
{
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return -EAGAIN;
4138
	return data->commit_done_cb(task, data);
4139 4140
}

4141
static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
L
Linus Torvalds 已提交
4142
{
4143
	struct nfs_server *server = NFS_SERVER(data->inode);
4144

4145 4146
	if (data->commit_done_cb == NULL)
		data->commit_done_cb = nfs4_commit_done_cb;
4147
	data->res.server = server;
4148
	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
4149
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
L
Linus Torvalds 已提交
4150 4151
}

4152 4153 4154 4155 4156
struct nfs4_renewdata {
	struct nfs_client	*client;
	unsigned long		timestamp;
};

L
Linus Torvalds 已提交
4157 4158 4159 4160
/*
 * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
 * standalone procedure for queueing an asynchronous RENEW.
 */
4161
static void nfs4_renew_release(void *calldata)
4162
{
4163 4164
	struct nfs4_renewdata *data = calldata;
	struct nfs_client *clp = data->client;
4165

4166 4167 4168
	if (atomic_read(&clp->cl_count) > 1)
		nfs4_schedule_state_renewal(clp);
	nfs_put_client(clp);
4169
	kfree(data);
4170 4171
}

4172
static void nfs4_renew_done(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
4173
{
4174 4175 4176
	struct nfs4_renewdata *data = calldata;
	struct nfs_client *clp = data->client;
	unsigned long timestamp = data->timestamp;
L
Linus Torvalds 已提交
4177

4178
	trace_nfs4_renew_async(clp, task->tk_status);
L
Linus Torvalds 已提交
4179
	if (task->tk_status < 0) {
4180
		/* Unless we're shutting down, schedule state recovery! */
4181 4182 4183
		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
			return;
		if (task->tk_status != NFS4ERR_CB_PATH_DOWN) {
4184
			nfs4_schedule_lease_recovery(clp);
4185 4186 4187
			return;
		}
		nfs4_schedule_path_down_recovery(clp);
L
Linus Torvalds 已提交
4188
	}
4189
	do_renew_lease(clp, timestamp);
L
Linus Torvalds 已提交
4190 4191
}

4192 4193
static const struct rpc_call_ops nfs4_renew_ops = {
	.rpc_call_done = nfs4_renew_done,
4194
	.rpc_release = nfs4_renew_release,
4195 4196
};

4197
static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
L
Linus Torvalds 已提交
4198 4199 4200 4201
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
		.rpc_argp	= clp,
4202
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
4203
	};
4204
	struct nfs4_renewdata *data;
L
Linus Torvalds 已提交
4205

4206 4207
	if (renew_flags == 0)
		return 0;
4208 4209
	if (!atomic_inc_not_zero(&clp->cl_count))
		return -EIO;
4210
	data = kmalloc(sizeof(*data), GFP_NOFS);
4211 4212 4213 4214
	if (data == NULL)
		return -ENOMEM;
	data->client = clp;
	data->timestamp = jiffies;
4215
	return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
4216
			&nfs4_renew_ops, data);
L
Linus Torvalds 已提交
4217 4218
}

4219
static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
L
Linus Torvalds 已提交
4220 4221 4222 4223
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_RENEW],
		.rpc_argp	= clp,
4224
		.rpc_cred	= cred,
L
Linus Torvalds 已提交
4225 4226 4227 4228
	};
	unsigned long now = jiffies;
	int status;

4229
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
L
Linus Torvalds 已提交
4230 4231
	if (status < 0)
		return status;
4232
	do_renew_lease(clp, now);
L
Linus Torvalds 已提交
4233 4234 4235
	return 0;
}

4236 4237 4238 4239 4240 4241 4242
static inline int nfs4_server_supports_acls(struct nfs_server *server)
{
	return (server->caps & NFS_CAP_ACLS)
		&& (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
		&& (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
}

4243 4244
/* 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
4245 4246
 * the stack.
 */
4247
#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
4248

4249 4250 4251 4252 4253 4254 4255 4256 4257
static int buf_to_pages_noslab(const void *buf, size_t buflen,
		struct page **pages, unsigned int *pgbase)
{
	struct page *newpage, **spages;
	int rc = 0;
	size_t len;
	spages = pages;

	do {
4258
		len = min_t(size_t, PAGE_SIZE, buflen);
4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277
		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;
}

4278 4279 4280
struct nfs4_cached_acl {
	int cached;
	size_t len;
A
Andrew Morton 已提交
4281
	char data[0];
4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323
};

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

4324
static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
4325 4326
{
	struct nfs4_cached_acl *acl;
4327
	size_t buflen = sizeof(*acl) + acl_len;
4328

4329
	if (buflen <= PAGE_SIZE) {
4330
		acl = kmalloc(buflen, GFP_KERNEL);
4331 4332 4333
		if (acl == NULL)
			goto out;
		acl->cached = 1;
4334
		_copy_from_pages(acl->data, pages, pgbase, acl_len);
4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345
	} 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);
}

4346 4347 4348 4349 4350 4351 4352 4353 4354 4355
/*
 * 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.
 */
4356
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
4357
{
4358
	struct page *pages[NFS4ACL_MAXPAGES] = {NULL, };
4359 4360 4361 4362 4363
	struct nfs_getaclargs args = {
		.fh = NFS_FH(inode),
		.acl_pages = pages,
		.acl_len = buflen,
	};
B
Benny Halevy 已提交
4364 4365 4366
	struct nfs_getaclres res = {
		.acl_len = buflen,
	};
4367 4368 4369
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
		.rpc_argp = &args,
B
Benny Halevy 已提交
4370
		.rpc_resp = &res,
4371
	};
4372 4373
	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
	int ret = -ENOMEM, i;
4374

4375 4376 4377 4378
	/* 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;
4379 4380
	if (npages > ARRAY_SIZE(pages))
		return -ERANGE;
4381

4382 4383 4384 4385
	for (i = 0; i < npages; i++) {
		pages[i] = alloc_page(GFP_KERNEL);
		if (!pages[i])
			goto out_free;
4386
	}
4387 4388 4389 4390 4391 4392

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

4393 4394
	args.acl_len = npages * PAGE_SIZE;
	args.acl_pgbase = 0;
4395

4396
	dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
4397 4398 4399
		__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);
4400 4401
	if (ret)
		goto out_free;
4402

4403 4404 4405 4406 4407
	/* 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;
4408
		ret = -ERANGE;
4409
		goto out_free;
4410
	}
4411
	nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
4412 4413 4414 4415 4416
	if (buf) {
		if (res.acl_len > buflen) {
			ret = -ERANGE;
			goto out_free;
		}
4417
		_copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
4418
	}
4419 4420
out_ok:
	ret = res.acl_len;
4421
out_free:
4422 4423 4424
	for (i = 0; i < npages; i++)
		if (pages[i])
			__free_page(pages[i]);
4425 4426
	if (res.acl_scratch)
		__free_page(res.acl_scratch);
4427 4428 4429
	return ret;
}

4430 4431 4432 4433 4434 4435
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);
4436
		trace_nfs4_get_acl(inode, ret);
4437 4438 4439 4440 4441 4442 4443
		if (ret >= 0)
			break;
		ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
	} while (exception.retry);
	return ret;
}

4444 4445 4446 4447 4448 4449 4450 4451 4452 4453
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;
4454 4455
	if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
		nfs_zap_acl_cache(inode);
4456 4457
	ret = nfs4_read_cached_acl(inode, buf, buflen);
	if (ret != -ENOENT)
4458 4459
		/* -ENOENT is returned if there is no ACL or if there is an ACL
		 * but no cached acl data, just the acl length */
4460 4461 4462 4463
		return ret;
	return nfs4_get_acl_uncached(inode, buf, buflen);
}

4464
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
4465 4466 4467 4468 4469 4470 4471 4472
{
	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 已提交
4473
	struct nfs_setaclres res;
4474 4475 4476
	struct rpc_message msg = {
		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETACL],
		.rpc_argp	= &arg,
B
Benny Halevy 已提交
4477
		.rpc_resp	= &res,
4478
	};
4479
	unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
4480
	int ret, i;
4481 4482 4483

	if (!nfs4_server_supports_acls(server))
		return -EOPNOTSUPP;
4484 4485
	if (npages > ARRAY_SIZE(pages))
		return -ERANGE;
4486 4487 4488
	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
	if (i < 0)
		return i;
4489
	nfs4_inode_return_delegation(inode);
4490
	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
4491 4492 4493 4494 4495 4496 4497 4498

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

4499 4500 4501 4502 4503 4504 4505
	/*
	 * 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);
4506 4507
	nfs_access_zap_cache(inode);
	nfs_zap_acl_cache(inode);
4508 4509 4510
	return ret;
}

4511 4512 4513 4514 4515
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
{
	struct nfs4_exception exception = { };
	int err;
	do {
4516 4517 4518
		err = __nfs4_proc_set_acl(inode, buf, buflen);
		trace_nfs4_set_acl(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
4519 4520 4521 4522 4523
				&exception);
	} while (exception.retry);
	return err;
}

4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570
#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 };
	struct nfs4_getattr_arg args = {
		.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],
		.rpc_argp	= &args,
		.rpc_resp	= &res,
	};
	int ret;

	nfs_fattr_init(&fattr);

	ret = rpc_call_sync(server->client, &msg, 0);
	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 {
4571 4572 4573
		err = _nfs4_get_security_label(inode, buf, buflen);
		trace_nfs4_get_security_label(inode, err);
		err = nfs4_handle_exception(NFS_SERVER(inode), err,
4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624
				&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 };
	struct nfs_setattrargs args = {
		.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],
		.rpc_argp       = &args,
		.rpc_resp       = &res,
	};
	int status;

	nfs4_stateid_copy(&args.stateid, &zero_stateid);

	status = rpc_call_sync(server->client, &msg, 0);
	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 {
4625 4626 4627 4628
		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,
4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674
				&exception);
	} while (exception.retry);
	return err;
}

static int
nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
{
	struct nfs4_label ilabel, *olabel = NULL;
	struct nfs_fattr fattr;
	struct rpc_cred *cred;
	struct inode *inode = dentry->d_inode;
	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 */


L
Linus Torvalds 已提交
4675
static int
4676
nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
L
Linus Torvalds 已提交
4677
{
4678 4679 4680
	struct nfs_client *clp = server->nfs_client;

	if (task->tk_status >= 0)
L
Linus Torvalds 已提交
4681 4682
		return 0;
	switch(task->tk_status) {
4683
		case -NFS4ERR_DELEG_REVOKED:
4684 4685
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_BAD_STATEID:
4686 4687 4688
			if (state == NULL)
				break;
			nfs_remove_bad_delegation(state->inode);
4689 4690 4691
		case -NFS4ERR_OPENMODE:
			if (state == NULL)
				break;
4692 4693
			if (nfs4_schedule_stateid_recovery(server, state) < 0)
				goto stateid_invalid;
4694
			goto wait_on_recovery;
4695
		case -NFS4ERR_EXPIRED:
4696 4697 4698 4699
			if (state != NULL) {
				if (nfs4_schedule_stateid_recovery(server, state) < 0)
					goto stateid_invalid;
			}
L
Linus Torvalds 已提交
4700
		case -NFS4ERR_STALE_STATEID:
4701
		case -NFS4ERR_STALE_CLIENTID:
4702 4703
			nfs4_schedule_lease_recovery(clp);
			goto wait_on_recovery;
4704 4705 4706 4707 4708 4709 4710 4711 4712 4713
#if defined(CONFIG_NFS_V4_1)
		case -NFS4ERR_BADSESSION:
		case -NFS4ERR_BADSLOT:
		case -NFS4ERR_BAD_HIGH_SLOT:
		case -NFS4ERR_DEADSESSION:
		case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
		case -NFS4ERR_SEQ_FALSE_RETRY:
		case -NFS4ERR_SEQ_MISORDERED:
			dprintk("%s ERROR %d, Reset session\n", __func__,
				task->tk_status);
4714
			nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
4715 4716 4717
			task->tk_status = 0;
			return -EAGAIN;
#endif /* CONFIG_NFS_V4_1 */
L
Linus Torvalds 已提交
4718
		case -NFS4ERR_DELAY:
4719
			nfs_inc_server_stats(server, NFSIOS_DELAY);
4720
		case -NFS4ERR_GRACE:
L
Linus Torvalds 已提交
4721 4722 4723
			rpc_delay(task, NFS4_POLL_RETRY_MAX);
			task->tk_status = 0;
			return -EAGAIN;
4724
		case -NFS4ERR_RETRY_UNCACHED_REP:
L
Linus Torvalds 已提交
4725 4726 4727 4728 4729 4730
		case -NFS4ERR_OLD_STATEID:
			task->tk_status = 0;
			return -EAGAIN;
	}
	task->tk_status = nfs4_map_errors(task->tk_status);
	return 0;
4731 4732 4733
stateid_invalid:
	task->tk_status = -EIO;
	return 0;
4734
wait_on_recovery:
4735 4736 4737 4738 4739
	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);
	task->tk_status = 0;
	return -EAGAIN;
L
Linus Torvalds 已提交
4740 4741
}

4742 4743
static void nfs4_init_boot_verifier(const struct nfs_client *clp,
				    nfs4_verifier *bootverf)
4744 4745 4746
{
	__be32 verf[2];

4747 4748 4749 4750
	if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
		/* An impossible timestamp guarantees this value
		 * will never match a generated boot time. */
		verf[0] = 0;
4751
		verf[1] = cpu_to_be32(NSEC_PER_SEC + 1);
4752
	} else {
4753
		struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
4754 4755
		verf[0] = cpu_to_be32(nn->boot_time.tv_sec);
		verf[1] = cpu_to_be32(nn->boot_time.tv_nsec);
4756
	}
4757 4758 4759
	memcpy(bootverf->data, verf, sizeof(bootverf->data));
}

4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780
static unsigned int
nfs4_init_nonuniform_client_string(const struct nfs_client *clp,
				   char *buf, size_t len)
{
	unsigned int result;

	rcu_read_lock();
	result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s",
				clp->cl_ipaddr,
				rpc_peeraddr2str(clp->cl_rpcclient,
							RPC_DISPLAY_ADDR),
				rpc_peeraddr2str(clp->cl_rpcclient,
							RPC_DISPLAY_PROTO));
	rcu_read_unlock();
	return result;
}

static unsigned int
nfs4_init_uniform_client_string(const struct nfs_client *clp,
				char *buf, size_t len)
{
4781
	const char *nodename = clp->cl_rpcclient->cl_nodename;
4782 4783

	if (nfs4_client_id_uniquifier[0] != '\0')
4784 4785 4786 4787 4788
		return scnprintf(buf, len, "Linux NFSv%u.%u %s/%s",
				clp->rpc_ops->version,
				clp->cl_minorversion,
				nfs4_client_id_uniquifier,
				nodename);
4789 4790
	return scnprintf(buf, len, "Linux NFSv%u.%u %s",
				clp->rpc_ops->version, clp->cl_minorversion,
4791
				nodename);
4792 4793
}

4794 4795 4796 4797 4798 4799 4800 4801 4802 4803
/**
 * 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.
 */
4804 4805 4806
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 已提交
4807 4808 4809 4810 4811
{
	nfs4_verifier sc_verifier;
	struct nfs4_setclientid setclientid = {
		.sc_verifier = &sc_verifier,
		.sc_prog = program,
A
Andy Adamson 已提交
4812
		.sc_cb_ident = clp->cl_cb_ident,
L
Linus Torvalds 已提交
4813 4814 4815 4816
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
		.rpc_argp = &setclientid,
4817
		.rpc_resp = res,
4818
		.rpc_cred = cred,
L
Linus Torvalds 已提交
4819
	};
4820
	int status;
L
Linus Torvalds 已提交
4821

4822
	/* nfs_client_id4 */
4823
	nfs4_init_boot_verifier(clp, &sc_verifier);
4824 4825 4826 4827 4828 4829 4830 4831 4832 4833
	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags))
		setclientid.sc_name_len =
				nfs4_init_uniform_client_string(clp,
						setclientid.sc_name,
						sizeof(setclientid.sc_name));
	else
		setclientid.sc_name_len =
				nfs4_init_nonuniform_client_string(clp,
						setclientid.sc_name,
						sizeof(setclientid.sc_name));
4834
	/* cb_client4 */
4835
	rcu_read_lock();
4836
	setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
4837
				sizeof(setclientid.sc_netid), "%s",
4838 4839
				rpc_peeraddr2str(clp->cl_rpcclient,
							RPC_DISPLAY_NETID));
4840 4841
	rcu_read_unlock();
	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
4842
				sizeof(setclientid.sc_uaddr), "%s.%u.%u",
L
Linus Torvalds 已提交
4843 4844
				clp->cl_ipaddr, port >> 8, port & 255);

4845 4846 4847 4848
	dprintk("NFS call  setclientid auth=%s, '%.*s'\n",
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
		setclientid.sc_name_len, setclientid.sc_name);
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
4849
	trace_nfs4_setclientid(clp, status);
4850 4851
	dprintk("NFS reply setclientid: %d\n", status);
	return status;
L
Linus Torvalds 已提交
4852 4853
}

4854 4855 4856 4857 4858 4859 4860 4861
/**
 * 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.
 */
4862
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
4863 4864
		struct nfs4_setclientid_res *arg,
		struct rpc_cred *cred)
L
Linus Torvalds 已提交
4865 4866 4867
{
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
4868
		.rpc_argp = arg,
4869
		.rpc_cred = cred,
L
Linus Torvalds 已提交
4870 4871 4872
	};
	int status;

4873 4874 4875
	dprintk("NFS call  setclientid_confirm auth=%s, (client ID %llx)\n",
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
		clp->cl_clientid);
4876
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
4877
	trace_nfs4_setclientid_confirm(clp, status);
4878
	dprintk("NFS reply setclientid_confirm: %d\n", status);
L
Linus Torvalds 已提交
4879 4880 4881
	return status;
}

4882 4883
struct nfs4_delegreturndata {
	struct nfs4_delegreturnargs args;
4884
	struct nfs4_delegreturnres res;
4885 4886
	struct nfs_fh fh;
	nfs4_stateid stateid;
4887
	unsigned long timestamp;
4888
	struct nfs_fattr fattr;
4889 4890 4891 4892 4893 4894
	int rpc_status;
};

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

4896 4897
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return;
4898

4899
	trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
4900 4901 4902 4903
	switch (task->tk_status) {
	case -NFS4ERR_STALE_STATEID:
	case -NFS4ERR_EXPIRED:
	case 0:
4904
		renew_lease(data->res.server, data->timestamp);
4905 4906 4907 4908
		break;
	default:
		if (nfs4_async_handle_error(task, data->res.server, NULL) ==
				-EAGAIN) {
4909
			rpc_restart_call_prepare(task);
4910 4911 4912 4913
			return;
		}
	}
	data->rpc_status = task->tk_status;
4914 4915 4916 4917 4918 4919 4920
}

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

4921 4922 4923 4924 4925 4926
static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
{
	struct nfs4_delegreturndata *d_data;

	d_data = (struct nfs4_delegreturndata *)data;

4927 4928 4929 4930
	nfs4_setup_sequence(d_data->res.server,
			&d_data->args.seq_args,
			&d_data->res.seq_res,
			task);
4931 4932
}

4933
static const struct rpc_call_ops nfs4_delegreturn_ops = {
4934
	.rpc_call_prepare = nfs4_delegreturn_prepare,
4935 4936 4937 4938
	.rpc_call_done = nfs4_delegreturn_done,
	.rpc_release = nfs4_delegreturn_release,
};

4939
static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
4940 4941
{
	struct nfs4_delegreturndata *data;
4942
	struct nfs_server *server = NFS_SERVER(inode);
4943
	struct rpc_task *task;
4944 4945 4946 4947
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
		.rpc_cred = cred,
	};
T
Trond Myklebust 已提交
4948 4949
	struct rpc_task_setup task_setup_data = {
		.rpc_client = server->client,
4950
		.rpc_message = &msg,
T
Trond Myklebust 已提交
4951 4952 4953
		.callback_ops = &nfs4_delegreturn_ops,
		.flags = RPC_TASK_ASYNC,
	};
4954
	int status = 0;
4955

4956
	data = kzalloc(sizeof(*data), GFP_NOFS);
4957 4958
	if (data == NULL)
		return -ENOMEM;
4959
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
4960 4961
	data->args.fhandle = &data->fh;
	data->args.stateid = &data->stateid;
4962
	data->args.bitmask = server->cache_consistency_bitmask;
4963
	nfs_copy_fh(&data->fh, NFS_FH(inode));
4964
	nfs4_stateid_copy(&data->stateid, stateid);
4965 4966
	data->res.fattr = &data->fattr;
	data->res.server = server;
4967
	nfs_fattr_init(data->res.fattr);
4968
	data->timestamp = jiffies;
4969 4970
	data->rpc_status = 0;

T
Trond Myklebust 已提交
4971
	task_setup_data.callback_data = data;
4972 4973
	msg.rpc_argp = &data->args;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
4974
	task = rpc_run_task(&task_setup_data);
4975
	if (IS_ERR(task))
4976
		return PTR_ERR(task);
4977 4978
	if (!issync)
		goto out;
4979
	status = nfs4_wait_for_completion_rpc_task(task);
4980 4981 4982
	if (status != 0)
		goto out;
	status = data->rpc_status;
4983 4984 4985 4986
	if (status == 0)
		nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
	else
		nfs_refresh_inode(inode, &data->fattr);
4987
out:
4988
	rpc_put_task(task);
4989
	return status;
L
Linus Torvalds 已提交
4990 4991
}

4992
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
L
Linus Torvalds 已提交
4993 4994 4995 4996 4997
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs4_exception exception = { };
	int err;
	do {
4998
		err = _nfs4_proc_delegreturn(inode, cred, stateid, issync);
4999
		trace_nfs4_delegreturn(inode, err);
L
Linus Torvalds 已提交
5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019
		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;
}

#define NFS4_LOCK_MINTIMEOUT (1 * HZ)
#define NFS4_LOCK_MAXTIMEOUT (30 * HZ)

/* 
 * sleep, with exponential backoff, and retry the LOCK operation. 
 */
static unsigned long
nfs4_set_lock_task_retry(unsigned long timeout)
{
5020
	freezable_schedule_timeout_killable_unsafe(timeout);
L
Linus Torvalds 已提交
5021 5022 5023 5024 5025 5026 5027 5028 5029 5030
	timeout <<= 1;
	if (timeout > NFS4_LOCK_MAXTIMEOUT)
		return NFS4_LOCK_MAXTIMEOUT;
	return timeout;
}

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);
5031
	struct nfs_client *clp = server->nfs_client;
T
Trond Myklebust 已提交
5032
	struct nfs_lockt_args arg = {
L
Linus Torvalds 已提交
5033
		.fh = NFS_FH(inode),
T
Trond Myklebust 已提交
5034
		.fl = request,
L
Linus Torvalds 已提交
5035
	};
T
Trond Myklebust 已提交
5036 5037
	struct nfs_lockt_res res = {
		.denied = request,
L
Linus Torvalds 已提交
5038 5039 5040 5041 5042 5043 5044 5045 5046 5047
	};
	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 已提交
5048
	arg.lock_owner.clientid = clp->cl_clientid;
5049 5050 5051 5052
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		goto out;
	lsp = request->fl_u.nfs4_fl.owner;
5053
	arg.lock_owner.id = lsp->ls_seqid.owner_id;
5054
	arg.lock_owner.s_dev = server->s_dev;
5055
	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
T
Trond Myklebust 已提交
5056 5057 5058 5059 5060 5061
	switch (status) {
		case 0:
			request->fl_type = F_UNLCK;
			break;
		case -NFS4ERR_DENIED:
			status = 0;
L
Linus Torvalds 已提交
5062
	}
5063
	request->fl_ops->fl_release_private(request);
5064
out:
L
Linus Torvalds 已提交
5065 5066 5067 5068 5069 5070 5071 5072 5073
	return status;
}

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

	do {
5074 5075 5076
		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 已提交
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097
				&exception);
	} while (exception.retry);
	return err;
}

static int do_vfs_lock(struct file *file, struct file_lock *fl)
{
	int res = 0;
	switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
		case FL_POSIX:
			res = posix_lock_file_wait(file, fl);
			break;
		case FL_FLOCK:
			res = flock_lock_file_wait(file, fl);
			break;
		default:
			BUG();
	}
	return res;
}

5098
struct nfs4_unlockdata {
T
Trond Myklebust 已提交
5099 5100
	struct nfs_locku_args arg;
	struct nfs_locku_res res;
5101 5102
	struct nfs4_lock_state *lsp;
	struct nfs_open_context *ctx;
T
Trond Myklebust 已提交
5103 5104
	struct file_lock fl;
	const struct nfs_server *server;
5105
	unsigned long timestamp;
5106 5107
};

T
Trond Myklebust 已提交
5108 5109 5110 5111 5112 5113 5114 5115
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;

5116
	p = kzalloc(sizeof(*p), GFP_NOFS);
T
Trond Myklebust 已提交
5117 5118 5119 5120 5121
	if (p == NULL)
		return NULL;
	p->arg.fh = NFS_FH(inode);
	p->arg.fl = &p->fl;
	p->arg.seqid = seqid;
5122
	p->res.seqid = seqid;
T
Trond Myklebust 已提交
5123 5124 5125 5126 5127 5128 5129 5130 5131 5132
	p->arg.stateid = &lsp->ls_stateid;
	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;
}

5133
static void nfs4_locku_release_calldata(void *data)
5134
{
5135
	struct nfs4_unlockdata *calldata = data;
T
Trond Myklebust 已提交
5136
	nfs_free_seqid(calldata->arg.seqid);
5137 5138 5139
	nfs4_put_lock_state(calldata->lsp);
	put_nfs_open_context(calldata->ctx);
	kfree(calldata);
5140 5141
}

5142
static void nfs4_locku_done(struct rpc_task *task, void *data)
5143
{
5144
	struct nfs4_unlockdata *calldata = data;
5145

5146 5147
	if (!nfs4_sequence_done(task, &calldata->res.seq_res))
		return;
5148 5149
	switch (task->tk_status) {
		case 0:
5150 5151
			nfs4_stateid_copy(&calldata->lsp->ls_stateid,
					&calldata->res.stateid);
5152
			renew_lease(calldata->server, calldata->timestamp);
5153
			break;
5154 5155
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_OLD_STATEID:
5156 5157 5158 5159
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_EXPIRED:
			break;
		default:
5160
			if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
5161
				rpc_restart_call_prepare(task);
5162
	}
5163
	nfs_release_seqid(calldata->arg.seqid);
5164 5165
}

T
Trond Myklebust 已提交
5166
static void nfs4_locku_prepare(struct rpc_task *task, void *data)
5167
{
T
Trond Myklebust 已提交
5168
	struct nfs4_unlockdata *calldata = data;
5169

T
Trond Myklebust 已提交
5170
	if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
5171
		goto out_wait;
5172
	if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
5173
		/* Note: exit _without_ running nfs4_locku_done */
5174
		goto out_no_action;
5175
	}
5176
	calldata->timestamp = jiffies;
5177
	if (nfs4_setup_sequence(calldata->server,
5178
				&calldata->arg.seq_args,
5179 5180 5181
				&calldata->res.seq_res,
				task) != 0)
		nfs_release_seqid(calldata->arg.seqid);
5182 5183 5184 5185 5186
	return;
out_no_action:
	task->tk_action = NULL;
out_wait:
	nfs4_sequence_done(task, &calldata->res.seq_res);
5187 5188
}

5189
static const struct rpc_call_ops nfs4_locku_ops = {
T
Trond Myklebust 已提交
5190
	.rpc_call_prepare = nfs4_locku_prepare,
5191
	.rpc_call_done = nfs4_locku_done,
5192
	.rpc_release = nfs4_locku_release_calldata,
5193 5194
};

5195 5196 5197 5198 5199 5200
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;
5201 5202 5203 5204
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
		.rpc_cred = ctx->cred,
	};
T
Trond Myklebust 已提交
5205 5206
	struct rpc_task_setup task_setup_data = {
		.rpc_client = NFS_CLIENT(lsp->ls_state->inode),
5207
		.rpc_message = &msg,
T
Trond Myklebust 已提交
5208
		.callback_ops = &nfs4_locku_ops,
5209
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
5210 5211
		.flags = RPC_TASK_ASYNC,
	};
5212

5213 5214 5215 5216 5217
	/* 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;

5218 5219 5220 5221 5222 5223
	data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
	if (data == NULL) {
		nfs_free_seqid(seqid);
		return ERR_PTR(-ENOMEM);
	}

5224
	nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
5225 5226
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
5227 5228
	task_setup_data.callback_data = data;
	return rpc_run_task(&task_setup_data);
5229 5230
}

5231 5232
static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
5233 5234 5235
	struct inode *inode = state->inode;
	struct nfs4_state_owner *sp = state->owner;
	struct nfs_inode *nfsi = NFS_I(inode);
T
Trond Myklebust 已提交
5236
	struct nfs_seqid *seqid;
L
Linus Torvalds 已提交
5237
	struct nfs4_lock_state *lsp;
5238 5239
	struct rpc_task *task;
	int status = 0;
5240
	unsigned char fl_flags = request->fl_flags;
5241

5242
	status = nfs4_set_lock_state(state, request);
5243 5244
	/* Unlock _before_ we do the RPC call */
	request->fl_flags |= FL_EXISTS;
5245 5246 5247
	/* Exclude nfs_delegation_claim_locks() */
	mutex_lock(&sp->so_delegreturn_mutex);
	/* Exclude nfs4_reclaim_open_stateid() - note nesting! */
5248 5249 5250
	down_read(&nfsi->rwsem);
	if (do_vfs_lock(request->fl_file, request) == -ENOENT) {
		up_read(&nfsi->rwsem);
5251
		mutex_unlock(&sp->so_delegreturn_mutex);
5252
		goto out;
5253 5254
	}
	up_read(&nfsi->rwsem);
5255
	mutex_unlock(&sp->so_delegreturn_mutex);
5256
	if (status != 0)
5257 5258
		goto out;
	/* Is this a delegated lock? */
5259
	lsp = request->fl_u.nfs4_fl.owner;
5260 5261
	if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) == 0)
		goto out;
5262
	seqid = nfs_alloc_seqid(&lsp->ls_seqid, GFP_KERNEL);
5263
	status = -ENOMEM;
T
Trond Myklebust 已提交
5264
	if (seqid == NULL)
5265
		goto out;
5266
	task = nfs4_do_unlck(request, nfs_file_open_context(request->fl_file), lsp, seqid);
5267 5268
	status = PTR_ERR(task);
	if (IS_ERR(task))
5269
		goto out;
5270
	status = nfs4_wait_for_completion_rpc_task(task);
5271
	rpc_put_task(task);
5272
out:
5273
	request->fl_flags = fl_flags;
5274
	trace_nfs4_unlock(request, state, F_SETLK, status);
L
Linus Torvalds 已提交
5275 5276 5277
	return status;
}

5278 5279 5280 5281 5282 5283
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;
5284
	unsigned long timestamp;
5285 5286
	int rpc_status;
	int cancelled;
5287
	struct nfs_server *server;
5288 5289 5290
};

static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
5291 5292
		struct nfs_open_context *ctx, struct nfs4_lock_state *lsp,
		gfp_t gfp_mask)
L
Linus Torvalds 已提交
5293
{
5294 5295
	struct nfs4_lockdata *p;
	struct inode *inode = lsp->ls_state->inode;
L
Linus Torvalds 已提交
5296
	struct nfs_server *server = NFS_SERVER(inode);
5297

5298
	p = kzalloc(sizeof(*p), gfp_mask);
5299 5300 5301 5302 5303
	if (p == NULL)
		return NULL;

	p->arg.fh = NFS_FH(inode);
	p->arg.fl = &p->fl;
5304
	p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid, gfp_mask);
5305 5306
	if (p->arg.open_seqid == NULL)
		goto out_free;
5307
	p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid, gfp_mask);
5308
	if (p->arg.lock_seqid == NULL)
5309
		goto out_free_seqid;
5310
	p->arg.lock_stateid = &lsp->ls_stateid;
5311
	p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
5312
	p->arg.lock_owner.id = lsp->ls_seqid.owner_id;
5313
	p->arg.lock_owner.s_dev = server->s_dev;
5314
	p->res.lock_seqid = p->arg.lock_seqid;
5315
	p->lsp = lsp;
5316
	p->server = server;
5317 5318 5319 5320
	atomic_inc(&lsp->ls_count);
	p->ctx = get_nfs_open_context(ctx);
	memcpy(&p->fl, fl, sizeof(p->fl));
	return p;
5321 5322
out_free_seqid:
	nfs_free_seqid(p->arg.open_seqid);
5323 5324 5325 5326 5327 5328 5329 5330 5331
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;
5332

5333
	dprintk("%s: begin!\n", __func__);
5334
	if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
5335
		goto out_wait;
5336 5337
	/* Do we need to do an open_to_lock_owner? */
	if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
5338
		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
5339
			goto out_release_lock_seqid;
5340
		}
5341
		data->arg.open_stateid = &state->open_stateid;
5342
		data->arg.new_lock_owner = 1;
5343
		data->res.open_seqid = data->arg.open_seqid;
5344 5345
	} else
		data->arg.new_lock_owner = 0;
5346 5347 5348 5349 5350
	if (!nfs4_valid_open_stateid(state)) {
		data->rpc_status = -EBADF;
		task->tk_action = NULL;
		goto out_release_open_seqid;
	}
5351
	data->timestamp = jiffies;
5352 5353
	if (nfs4_setup_sequence(data->server,
				&data->arg.seq_args,
5354
				&data->res.seq_res,
5355
				task) == 0)
5356
		return;
5357
out_release_open_seqid:
5358 5359 5360
	nfs_release_seqid(data->arg.open_seqid);
out_release_lock_seqid:
	nfs_release_seqid(data->arg.lock_seqid);
5361 5362
out_wait:
	nfs4_sequence_done(task, &data->res.seq_res);
5363
	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
5364 5365
}

5366 5367 5368 5369
static void nfs4_lock_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_lockdata *data = calldata;

5370
	dprintk("%s: begin!\n", __func__);
5371

5372 5373
	if (!nfs4_sequence_done(task, &data->res.seq_res))
		return;
5374

5375 5376 5377 5378 5379 5380 5381 5382
	data->rpc_status = task->tk_status;
	if (data->arg.new_lock_owner != 0) {
		if (data->rpc_status == 0)
			nfs_confirm_seqid(&data->lsp->ls_seqid, 0);
		else
			goto out;
	}
	if (data->rpc_status == 0) {
5383
		nfs4_stateid_copy(&data->lsp->ls_stateid, &data->res.stateid);
5384
		set_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags);
5385
		renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
5386 5387
	}
out:
5388
	dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
5389 5390 5391 5392 5393 5394
}

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

5395
	dprintk("%s: begin!\n", __func__);
5396
	nfs_free_seqid(data->arg.open_seqid);
5397 5398 5399 5400 5401
	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))
5402
			rpc_put_task_async(task);
5403
		dprintk("%s: cancelling lock!\n", __func__);
5404 5405 5406 5407 5408
	} else
		nfs_free_seqid(data->arg.lock_seqid);
	nfs4_put_lock_state(data->lsp);
	put_nfs_open_context(data->ctx);
	kfree(data);
5409
	dprintk("%s: done!\n", __func__);
5410 5411 5412 5413 5414 5415 5416 5417
}

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

5418 5419 5420 5421 5422
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:
	case -NFS4ERR_BAD_STATEID:
5423
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
5424
		if (new_lock_owner != 0 ||
5425
		   test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0)
5426
			nfs4_schedule_stateid_recovery(server, lsp->ls_state);
5427 5428 5429
		break;
	case -NFS4ERR_STALE_STATEID:
		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
5430 5431
	case -NFS4ERR_EXPIRED:
		nfs4_schedule_lease_recovery(server->nfs_client);
5432 5433 5434
	};
}

5435
static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
5436 5437 5438
{
	struct nfs4_lockdata *data;
	struct rpc_task *task;
5439 5440 5441 5442
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
		.rpc_cred = state->owner->so_cred,
	};
T
Trond Myklebust 已提交
5443 5444
	struct rpc_task_setup task_setup_data = {
		.rpc_client = NFS_CLIENT(state->inode),
5445
		.rpc_message = &msg,
T
Trond Myklebust 已提交
5446
		.callback_ops = &nfs4_lock_ops,
5447
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
5448 5449
		.flags = RPC_TASK_ASYNC,
	};
5450 5451
	int ret;

5452
	dprintk("%s: begin!\n", __func__);
5453
	data = nfs4_alloc_lockdata(fl, nfs_file_open_context(fl->fl_file),
5454 5455
			fl->fl_u.nfs4_fl.owner,
			recovery_type == NFS_LOCK_NEW ? GFP_KERNEL : GFP_NOFS);
5456 5457 5458 5459
	if (data == NULL)
		return -ENOMEM;
	if (IS_SETLKW(cmd))
		data->arg.block = 1;
5460
	nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
5461 5462
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;
T
Trond Myklebust 已提交
5463
	task_setup_data.callback_data = data;
5464 5465 5466 5467 5468
	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);
	}
T
Trond Myklebust 已提交
5469
	task = rpc_run_task(&task_setup_data);
5470
	if (IS_ERR(task))
5471 5472 5473 5474
		return PTR_ERR(task);
	ret = nfs4_wait_for_completion_rpc_task(task);
	if (ret == 0) {
		ret = data->rpc_status;
5475 5476 5477
		if (ret)
			nfs4_handle_setlk_error(data->server, data->lsp,
					data->arg.new_lock_owner, ret);
5478 5479
	} else
		data->cancelled = 1;
5480
	rpc_put_task(task);
5481
	dprintk("%s: done, ret = %d!\n", __func__, ret);
5482
	return ret;
L
Linus Torvalds 已提交
5483 5484 5485 5486
}

static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
5487
	struct nfs_server *server = NFS_SERVER(state->inode);
5488 5489 5490
	struct nfs4_exception exception = {
		.inode = state->inode,
	};
5491 5492 5493
	int err;

	do {
5494 5495 5496
		/* Cache the lock if possible... */
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
5497
		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
5498
		trace_nfs4_lock_reclaim(request, state, F_SETLK, err);
5499
		if (err != -NFS4ERR_DELAY)
5500 5501 5502 5503
			break;
		nfs4_handle_exception(server, err, &exception);
	} while (exception.retry);
	return err;
L
Linus Torvalds 已提交
5504 5505 5506 5507
}

static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
5508
	struct nfs_server *server = NFS_SERVER(state->inode);
5509 5510 5511
	struct nfs4_exception exception = {
		.inode = state->inode,
	};
5512 5513
	int err;

5514 5515 5516
	err = nfs4_set_lock_state(state, request);
	if (err != 0)
		return err;
5517
	do {
5518 5519
		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
			return 0;
5520
		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED);
5521
		trace_nfs4_lock_expired(request, state, F_SETLK, err);
5522 5523 5524 5525 5526 5527 5528 5529
		switch (err) {
		default:
			goto out;
		case -NFS4ERR_GRACE:
		case -NFS4ERR_DELAY:
			nfs4_handle_exception(server, err, &exception);
			err = 0;
		}
5530
	} while (exception.retry);
5531
out:
5532
	return err;
L
Linus Torvalds 已提交
5533 5534
}

5535
#if defined(CONFIG_NFS_V4_1)
5536 5537 5538 5539 5540 5541 5542 5543
/**
 * 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.
 */
5544
static int nfs41_check_expired_locks(struct nfs4_state *state)
5545
{
5546
	int status, ret = -NFS4ERR_BAD_STATEID;
5547
	struct nfs4_lock_state *lsp;
5548 5549
	struct nfs_server *server = NFS_SERVER(state->inode);

5550
	list_for_each_entry(lsp, &state->lock_states, ls_locks) {
5551
		if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
5552 5553 5554 5555 5556
			struct rpc_cred *cred = lsp->ls_state->owner->so_cred;

			status = nfs41_test_stateid(server,
					&lsp->ls_stateid,
					cred);
5557
			trace_nfs4_test_lock_stateid(state, lsp, status);
5558
			if (status != NFS_OK) {
5559 5560
				/* Free the stateid unless the server
				 * informs us the stateid is unrecognized. */
5561 5562
				if (status != -NFS4ERR_BAD_STATEID)
					nfs41_free_stateid(server,
5563 5564
							&lsp->ls_stateid,
							cred);
5565
				clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579
				ret = status;
			}
		}
	};

	return ret;
}

static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
	int status = NFS_OK;

	if (test_bit(LK_STATE_IN_USE, &state->flags))
		status = nfs41_check_expired_locks(state);
5580 5581 5582
	if (status != NFS_OK)
		status = nfs4_lock_expired(state, request);
	return status;
5583 5584 5585
}
#endif

L
Linus Torvalds 已提交
5586 5587
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
5588
	struct nfs4_state_owner *sp = state->owner;
5589
	struct nfs_inode *nfsi = NFS_I(state->inode);
5590
	unsigned char fl_flags = request->fl_flags;
5591
	unsigned int seq;
5592
	int status = -ENOLCK;
L
Linus Torvalds 已提交
5593

5594 5595 5596
	if ((fl_flags & FL_POSIX) &&
			!test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
		goto out;
5597 5598 5599 5600
	/* Is this a delegated open? */
	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		goto out;
5601 5602 5603 5604
	request->fl_flags |= FL_ACCESS;
	status = do_vfs_lock(request->fl_file, request);
	if (status < 0)
		goto out;
5605
	down_read(&nfsi->rwsem);
5606 5607 5608
	if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
		/* Yes: cache locks! */
		/* ...but avoid races with delegation recall... */
5609 5610 5611
		request->fl_flags = fl_flags & ~FL_SLEEP;
		status = do_vfs_lock(request->fl_file, request);
		goto out_unlock;
5612
	}
5613 5614
	seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
	up_read(&nfsi->rwsem);
5615
	status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW);
5616
	if (status != 0)
5617 5618 5619 5620
		goto out;
	down_read(&nfsi->rwsem);
	if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) {
		status = -NFS4ERR_DELAY;
5621
		goto out_unlock;
5622
	}
5623
	/* Note: we always want to sleep here! */
5624
	request->fl_flags = fl_flags | FL_SLEEP;
5625
	if (do_vfs_lock(request->fl_file, request) < 0)
5626 5627
		printk(KERN_WARNING "NFS: %s: VFS is out of sync with lock "
			"manager!\n", __func__);
5628
out_unlock:
5629
	up_read(&nfsi->rwsem);
5630 5631
out:
	request->fl_flags = fl_flags;
L
Linus Torvalds 已提交
5632 5633 5634 5635 5636
	return status;
}

static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
5637 5638
	struct nfs4_exception exception = {
		.state = state,
5639
		.inode = state->inode,
5640
	};
L
Linus Torvalds 已提交
5641 5642 5643
	int err;

	do {
5644
		err = _nfs4_proc_setlk(state, cmd, request);
5645
		trace_nfs4_set_lock(request, state, cmd, err);
5646 5647
		if (err == -NFS4ERR_DENIED)
			err = -EAGAIN;
L
Linus Torvalds 已提交
5648
		err = nfs4_handle_exception(NFS_SERVER(state->inode),
5649
				err, &exception);
L
Linus Torvalds 已提交
5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662
	} while (exception.retry);
	return err;
}

static int
nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
{
	struct nfs_open_context *ctx;
	struct nfs4_state *state;
	unsigned long timeout = NFS4_LOCK_MINTIMEOUT;
	int status;

	/* verify open state */
5663
	ctx = nfs_file_open_context(filp);
L
Linus Torvalds 已提交
5664 5665 5666 5667 5668
	state = ctx->state;

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

5669 5670 5671 5672 5673
	if (IS_GETLK(cmd)) {
		if (state != NULL)
			return nfs4_proc_getlk(state, F_GETLK, request);
		return 0;
	}
L
Linus Torvalds 已提交
5674 5675 5676 5677

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

5678 5679 5680 5681 5682
	if (request->fl_type == F_UNLCK) {
		if (state != NULL)
			return nfs4_proc_unlck(state, cmd, request);
		return 0;
	}
L
Linus Torvalds 已提交
5683

5684 5685
	if (state == NULL)
		return -ENOLCK;
5686 5687 5688 5689
	/*
	 * Don't rely on the VFS having checked the file open mode,
	 * since it won't do this for flock() locks.
	 */
5690
	switch (request->fl_type) {
5691 5692 5693 5694 5695 5696 5697 5698 5699
	case F_RDLCK:
		if (!(filp->f_mode & FMODE_READ))
			return -EBADF;
		break;
	case F_WRLCK:
		if (!(filp->f_mode & FMODE_WRITE))
			return -EBADF;
	}

L
Linus Torvalds 已提交
5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711
	do {
		status = nfs4_proc_setlk(state, cmd, request);
		if ((status != -EAGAIN) || IS_SETLK(cmd))
			break;
		timeout = nfs4_set_lock_task_retry(timeout);
		status = -ERESTARTSYS;
		if (signalled())
			break;
	} while(status < 0);
	return status;
}

5712
int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid)
5713 5714 5715 5716 5717 5718
{
	struct nfs_server *server = NFS_SERVER(state->inode);
	int err;

	err = nfs4_set_lock_state(state, fl);
	if (err != 0)
5719
		return err;
5720
	err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
5721
	return nfs4_handle_delegation_recall_error(server, state, stateid, err);
5722
}
5723

5724 5725
struct nfs_release_lockowner_data {
	struct nfs4_lock_state *lsp;
5726
	struct nfs_server *server;
5727 5728 5729
	struct nfs_release_lockowner_args args;
};

5730 5731
static void nfs4_release_lockowner_release(void *calldata)
{
5732
	struct nfs_release_lockowner_data *data = calldata;
5733
	nfs4_free_lock_state(data->server, data->lsp);
5734 5735 5736
	kfree(calldata);
}

5737
static const struct rpc_call_ops nfs4_release_lockowner_ops = {
5738 5739 5740
	.rpc_release = nfs4_release_lockowner_release,
};

5741
static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
5742
{
5743
	struct nfs_release_lockowner_data *data;
5744 5745 5746 5747 5748
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
	};

	if (server->nfs_client->cl_mvops->minor_version != 0)
5749 5750 5751 5752 5753
		return -EINVAL;
	data = kmalloc(sizeof(*data), GFP_NOFS);
	if (!data)
		return -ENOMEM;
	data->lsp = lsp;
5754
	data->server = server;
5755 5756 5757 5758 5759 5760
	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;
	msg.rpc_argp = &data->args;
	rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
	return 0;
5761 5762
}

5763 5764
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"

5765 5766 5767
static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
				   const void *buf, size_t buflen,
				   int flags, int type)
5768
{
5769 5770
	if (strcmp(key, "") != 0)
		return -EINVAL;
5771

5772
	return nfs4_proc_set_acl(dentry->d_inode, buf, buflen);
5773 5774
}

5775 5776
static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
				   void *buf, size_t buflen, int type)
5777
{
5778 5779
	if (strcmp(key, "") != 0)
		return -EINVAL;
5780

5781
	return nfs4_proc_get_acl(dentry->d_inode, buf, buflen);
5782 5783
}

5784 5785 5786
static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
				       size_t list_len, const char *name,
				       size_t name_len, int type)
5787
{
5788
	size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
5789

5790 5791
	if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
		return 0;
5792 5793 5794

	if (list && len <= list_len)
		memcpy(list, XATTR_NAME_NFSV4_ACL, len);
5795
	return len;
5796 5797
}

5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
static inline int nfs4_server_supports_labels(struct nfs_server *server)
{
	return server->caps & NFS_CAP_SECURITY_LABEL;
}

static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
				   const void *buf, size_t buflen,
				   int flags, int type)
{
	if (security_ismaclabel(key))
		return nfs4_set_security_label(dentry, buf, buflen);

	return -EOPNOTSUPP;
}

static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
				   void *buf, size_t buflen, int type)
{
	if (security_ismaclabel(key))
		return nfs4_get_security_label(dentry->d_inode, buf, buflen);
	return -EOPNOTSUPP;
}

static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
				       size_t list_len, const char *name,
				       size_t name_len, int type)
{
	size_t len = 0;

	if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL)) {
		len = security_inode_listsecurity(dentry->d_inode, NULL, 0);
		if (list && len <= list_len)
			security_inode_listsecurity(dentry->d_inode, list, len);
	}
	return len;
}

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


5845 5846 5847
/*
 * nfs_fhget will use either the mounted_on_fileid or the fileid
 */
5848 5849
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
{
5850 5851 5852
	if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) ||
	       (fattr->valid & NFS_ATTR_FATTR_FILEID)) &&
	      (fattr->valid & NFS_ATTR_FATTR_FSID) &&
5853
	      (fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS)))
5854 5855 5856
		return;

	fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
5857
		NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_V4_REFERRAL;
5858 5859 5860 5861
	fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
	fattr->nlink = 2;
}

5862 5863 5864 5865
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)
5866 5867
{
	struct nfs_server *server = NFS_SERVER(dir);
5868
	u32 bitmask[3] = {
5869
		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
5870 5871 5872
	};
	struct nfs4_fs_locations_arg args = {
		.dir_fh = NFS_FH(dir),
5873
		.name = name,
5874 5875 5876
		.page = page,
		.bitmask = bitmask,
	};
B
Benny Halevy 已提交
5877 5878 5879
	struct nfs4_fs_locations_res res = {
		.fs_locations = fs_locations,
	};
5880 5881 5882
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
		.rpc_argp = &args,
B
Benny Halevy 已提交
5883
		.rpc_resp = &res,
5884 5885 5886
	};
	int status;

5887
	dprintk("%s: start\n", __func__);
5888 5889 5890 5891 5892 5893 5894 5895

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

5896
	nfs_fattr_init(&fs_locations->fattr);
5897
	fs_locations->server = server;
5898
	fs_locations->nlocations = 0;
5899
	status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0);
5900
	dprintk("%s: returned status = %d\n", __func__, status);
5901 5902 5903
	return status;
}

5904 5905 5906 5907
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)
5908 5909 5910 5911
{
	struct nfs4_exception exception = { };
	int err;
	do {
5912 5913 5914 5915
		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,
5916 5917 5918 5919 5920
				&exception);
	} while (exception.retry);
	return err;
}

5921
/**
5922 5923 5924 5925 5926
 * 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.
5927
 */
5928
static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors, bool use_integrity)
B
Bryan Schumaker 已提交
5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942
{
	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,
	};
5943 5944 5945 5946 5947 5948
	struct rpc_clnt *clnt = NFS_SERVER(dir)->client;

	if (use_integrity) {
		clnt = NFS_SERVER(dir)->nfs_client->cl_rpcclient;
		msg.rpc_cred = nfs4_get_clid_cred(NFS_SERVER(dir)->nfs_client);
	}
B
Bryan Schumaker 已提交
5949 5950

	dprintk("NFS call  secinfo %s\n", name->name);
5951 5952
	status = nfs4_call_sync(clnt, NFS_SERVER(dir), &msg, &args.seq_args,
				&res.seq_res, 0);
B
Bryan Schumaker 已提交
5953
	dprintk("NFS reply  secinfo: %d\n", status);
5954 5955 5956 5957

	if (msg.rpc_cred)
		put_rpccred(msg.rpc_cred);

B
Bryan Schumaker 已提交
5958 5959 5960
	return status;
}

5961 5962
int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
		      struct nfs4_secinfo_flavors *flavors)
B
Bryan Schumaker 已提交
5963 5964 5965 5966
{
	struct nfs4_exception exception = { };
	int err;
	do {
5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981
		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);

5982 5983
		trace_nfs4_secinfo(dir, name, err);
		err = nfs4_handle_exception(NFS_SERVER(dir), err,
B
Bryan Schumaker 已提交
5984 5985 5986 5987 5988
				&exception);
	} while (exception.retry);
	return err;
}

5989
#ifdef CONFIG_NFS_V4_1
5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008
/*
 * 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;
}

6009
static bool
6010 6011
nfs41_same_server_scope(struct nfs41_server_scope *a,
			struct nfs41_server_scope *b)
6012 6013 6014 6015 6016 6017 6018 6019
{
	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;
}

6020 6021 6022 6023 6024 6025
/*
 * nfs4_proc_bind_conn_to_session()
 *
 * The 4.1 client currently uses the same TCP connection for the
 * fore and backchannel.
 */
6026
int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
6027 6028 6029 6030 6031 6032 6033 6034
{
	int status;
	struct nfs41_bind_conn_to_session_res res;
	struct rpc_message msg = {
		.rpc_proc =
			&nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
		.rpc_argp = clp,
		.rpc_resp = &res,
6035
		.rpc_cred = cred,
6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046
	};

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

	res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS);
	if (unlikely(res.session == NULL)) {
		status = -ENOMEM;
		goto out;
	}

	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
6047
	trace_nfs4_bind_conn_to_session(clp, status);
6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074
	if (status == 0) {
		if (memcmp(res.session->sess_id.data,
		    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
			dprintk("NFS: %s: Session ID mismatch\n", __func__);
			status = -EIO;
			goto out_session;
		}
		if (res.dir != NFS4_CDFS4_BOTH) {
			dprintk("NFS: %s: Unexpected direction from server\n",
				__func__);
			status = -EIO;
			goto out_session;
		}
		if (res.use_conn_in_rdma_mode) {
			dprintk("NFS: %s: Server returned RDMA mode = true\n",
				__func__);
			status = -EIO;
			goto out_session;
		}
	}
out_session:
	kfree(res.session);
out:
	dprintk("<-- %s status= %d\n", __func__, status);
	return status;
}

B
Benny Halevy 已提交
6075 6076 6077
/*
 * nfs4_proc_exchange_id()
 *
6078 6079
 * Returns zero, a negative errno, or a negative NFS4ERR status code.
 *
B
Benny Halevy 已提交
6080 6081 6082 6083 6084
 * 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.
 */
6085
int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
B
Benny Halevy 已提交
6086 6087 6088
{
	nfs4_verifier verifier;
	struct nfs41_exchange_id_args args = {
6089
		.verifier = &verifier,
B
Benny Halevy 已提交
6090
		.client = clp,
6091 6092
		.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
			EXCHGID4_FLAG_BIND_PRINC_STATEID,
B
Benny Halevy 已提交
6093 6094
	};
	struct nfs41_exchange_id_res res = {
6095
		0
B
Benny Halevy 已提交
6096 6097 6098 6099 6100 6101 6102 6103 6104
	};
	int status;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID],
		.rpc_argp = &args,
		.rpc_resp = &res,
		.rpc_cred = cred,
	};

6105
	nfs4_init_boot_verifier(clp, &verifier);
6106 6107
	args.id_len = nfs4_init_uniform_client_string(clp, args.id,
							sizeof(args.id));
6108 6109 6110
	dprintk("NFS call  exchange_id auth=%s, '%.*s'\n",
		clp->cl_rpcclient->cl_auth->au_ops->au_name,
		args.id_len, args.id);
B
Benny Halevy 已提交
6111

6112
	res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
6113
					GFP_NOFS);
6114
	if (unlikely(res.server_owner == NULL)) {
6115 6116 6117
		status = -ENOMEM;
		goto out;
	}
6118

6119
	res.server_scope = kzalloc(sizeof(struct nfs41_server_scope),
6120
					GFP_NOFS);
6121
	if (unlikely(res.server_scope == NULL)) {
6122
		status = -ENOMEM;
6123
		goto out_server_owner;
6124
	}
6125

6126
	res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_NOFS);
6127
	if (unlikely(res.impl_id == NULL)) {
6128 6129 6130 6131
		status = -ENOMEM;
		goto out_server_scope;
	}

6132
	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
6133
	trace_nfs4_exchange_id(clp, status);
6134
	if (status == 0)
6135
		status = nfs4_check_cl_exchange_flags(res.flags);
6136

6137
	if (status == 0) {
6138 6139 6140 6141 6142
		clp->cl_clientid = res.clientid;
		clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R);
		if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R))
			clp->cl_seqid = res.seqid;

6143 6144 6145
		kfree(clp->cl_serverowner);
		clp->cl_serverowner = res.server_owner;
		res.server_owner = NULL;
6146

6147
		/* use the most recent implementation id */
6148 6149
		kfree(clp->cl_implid);
		clp->cl_implid = res.impl_id;
6150

6151
		if (clp->cl_serverscope != NULL &&
6152
		    !nfs41_same_server_scope(clp->cl_serverscope,
6153 6154 6155 6156
					     res.server_scope)) {
			dprintk("%s: server_scope mismatch detected\n",
				__func__);
			set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
6157 6158
			kfree(clp->cl_serverscope);
			clp->cl_serverscope = NULL;
6159 6160
		}

6161
		if (clp->cl_serverscope == NULL) {
6162
			clp->cl_serverscope = res.server_scope;
6163 6164
			goto out;
		}
6165 6166
	} else
		kfree(res.impl_id);
6167

6168 6169
out_server_owner:
	kfree(res.server_owner);
6170
out_server_scope:
6171 6172
	kfree(res.server_scope);
out:
6173
	if (clp->cl_implid != NULL)
6174
		dprintk("NFS reply exchange_id: Server Implementation ID: "
6175
			"domain: %s, name: %s, date: %llu,%u\n",
6176
			clp->cl_implid->domain, clp->cl_implid->name,
6177 6178
			clp->cl_implid->date.seconds,
			clp->cl_implid->date.nseconds);
6179
	dprintk("NFS reply exchange_id: %d\n", status);
B
Benny Halevy 已提交
6180 6181 6182
	return status;
}

T
Trond Myklebust 已提交
6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193
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);
6194
	trace_nfs4_destroy_clientid(clp, status);
T
Trond Myklebust 已提交
6195
	if (status)
6196
		dprintk("NFS: Got error %d from the server %s on "
T
Trond Myklebust 已提交
6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229
			"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;
6230 6231
	if (clp->cl_preserve_clid)
		goto out;
6232
	cred = nfs4_get_clid_cred(clp);
T
Trond Myklebust 已提交
6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244
	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 已提交
6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259
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 */
6260 6261 6262 6263
	nfs41_setup_sequence(data->clp->cl_session,
			&data->args->la_seq_args,
			&data->res->lr_seq_res,
			task);
A
Andy Adamson 已提交
6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276
	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__);
6277 6278
	if (!nfs41_sequence_done(task, &data->res->lr_seq_res))
		return;
A
Andy Adamson 已提交
6279 6280 6281 6282 6283 6284
	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;
6285 6286
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
6287
		rpc_restart_call_prepare(task);
A
Andy Adamson 已提交
6288 6289 6290 6291 6292
		return;
	}
	dprintk("<-- %s\n", __func__);
}

6293
static const struct rpc_call_ops nfs4_get_lease_time_ops = {
A
Andy Adamson 已提交
6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318
	.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,
6319 6320
		.callback_data = &data,
		.flags = RPC_TASK_TIMEOUT,
A
Andy Adamson 已提交
6321 6322 6323
	};
	int status;

6324
	nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
6325
	nfs4_set_sequence_privileged(&args.la_seq_args);
A
Andy Adamson 已提交
6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339
	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 已提交
6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350
/*
 * 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.
 */
static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
{
6351 6352 6353 6354
	unsigned int max_rqst_sz, max_resp_sz;

	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 已提交
6355 6356

	/* Fore channel attributes */
6357 6358
	args->fc_attrs.max_rqst_sz = max_rqst_sz;
	args->fc_attrs.max_resp_sz = max_resp_sz;
A
Andy Adamson 已提交
6359
	args->fc_attrs.max_ops = NFS4_MAX_OPS;
6360
	args->fc_attrs.max_reqs = max_session_slots;
A
Andy Adamson 已提交
6361 6362

	dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
6363
		"max_ops=%u max_reqs=%u\n",
A
Andy Adamson 已提交
6364 6365
		__func__,
		args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
6366
		args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
A
Andy Adamson 已提交
6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382

	/* Back channel attributes */
	args->bc_attrs.max_rqst_sz = PAGE_SIZE;
	args->bc_attrs.max_resp_sz = PAGE_SIZE;
	args->bc_attrs.max_resp_sz_cached = 0;
	args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
	args->bc_attrs.max_reqs = 1;

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

6383
static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
6384
{
6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399
	struct nfs4_channel_attrs *sent = &args->fc_attrs;
	struct nfs4_channel_attrs *rcvd = &session->fc_attrs;

	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;
6400 6401
	if (rcvd->max_reqs > NFS4_MAX_SLOT_TABLE)
		rcvd->max_reqs = NFS4_MAX_SLOT_TABLE;
6402
	return 0;
6403 6404
}

6405 6406 6407 6408
static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
{
	struct nfs4_channel_attrs *sent = &args->bc_attrs;
	struct nfs4_channel_attrs *rcvd = &session->bc_attrs;
6409

6410 6411 6412 6413 6414 6415 6416
	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;
	/* These would render the backchannel useless: */
6417
	if (rcvd->max_ops != sent->max_ops)
6418
		return -EINVAL;
6419
	if (rcvd->max_reqs != sent->max_reqs)
6420 6421 6422
		return -EINVAL;
	return 0;
}
6423 6424 6425 6426

static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
				     struct nfs4_session *session)
{
6427
	int ret;
6428

6429 6430 6431 6432
	ret = nfs4_verify_fore_channel_attrs(args, session);
	if (ret)
		return ret;
	return nfs4_verify_back_channel_attrs(args, session);
6433 6434
}

6435 6436
static int _nfs4_proc_create_session(struct nfs_client *clp,
		struct rpc_cred *cred)
A
Andy Adamson 已提交
6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449
{
	struct nfs4_session *session = clp->cl_session;
	struct nfs41_create_session_args args = {
		.client = clp,
		.cb_program = NFS4_CALLBACK,
	};
	struct nfs41_create_session_res res = {
		.client = clp,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
		.rpc_argp = &args,
		.rpc_resp = &res,
6450
		.rpc_cred = cred,
A
Andy Adamson 已提交
6451 6452 6453 6454
	};
	int status;

	nfs4_init_channel_attrs(&args);
6455
	args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
A
Andy Adamson 已提交
6456

6457
	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
6458
	trace_nfs4_create_session(clp, status);
A
Andy Adamson 已提交
6459

6460
	if (!status) {
6461 6462
		/* Verify the session's negotiated channel_attrs values */
		status = nfs4_verify_channel_attrs(&args, session);
A
Andy Adamson 已提交
6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474
		/* Increment the clientid slot sequence id */
		clp->cl_seqid++;
	}

	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.
 */
6475
int nfs4_proc_create_session(struct nfs_client *clp, struct rpc_cred *cred)
A
Andy Adamson 已提交
6476 6477 6478 6479 6480 6481 6482
{
	int status;
	unsigned *ptr;
	struct nfs4_session *session = clp->cl_session;

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

6483
	status = _nfs4_proc_create_session(clp, cred);
A
Andy Adamson 已提交
6484 6485 6486
	if (status)
		goto out;

6487 6488 6489
	/* 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 已提交
6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500
	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 已提交
6501 6502 6503 6504
/*
 * Issue the over-the-wire RPC DESTROY_SESSION.
 * The caller must serialize access to this routine.
 */
6505 6506
int nfs4_proc_destroy_session(struct nfs4_session *session,
		struct rpc_cred *cred)
A
Andy Adamson 已提交
6507
{
6508 6509 6510 6511 6512
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION],
		.rpc_argp = session,
		.rpc_cred = cred,
	};
A
Andy Adamson 已提交
6513 6514 6515 6516 6517 6518 6519 6520
	int status = 0;

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

	/* session is still being setup */
	if (session->clp->cl_cons_state != NFS_CS_READY)
		return status;

6521
	status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
6522
	trace_nfs4_destroy_session(session->clp, status);
A
Andy Adamson 已提交
6523 6524

	if (status)
6525
		dprintk("NFS: Got error %d from the server on DESTROY_SESSION. "
A
Andy Adamson 已提交
6526 6527 6528 6529 6530 6531
			"Session has been destroyed regardless...\n", status);

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

A
Andy Adamson 已提交
6532 6533 6534
/*
 * Renew the cl_session lease.
 */
6535 6536 6537 6538 6539 6540
struct nfs4_sequence_data {
	struct nfs_client *clp;
	struct nfs4_sequence_args args;
	struct nfs4_sequence_res res;
};

6541 6542
static void nfs41_sequence_release(void *data)
{
6543 6544
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
6545

6546 6547 6548
	if (atomic_read(&clp->cl_count) > 1)
		nfs4_schedule_state_renewal(clp);
	nfs_put_client(clp);
6549
	kfree(calldata);
6550 6551
}

6552 6553 6554 6555 6556 6557 6558
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:
6559
		nfs4_schedule_lease_recovery(clp);
6560 6561 6562 6563
	}
	return 0;
}

6564
static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
A
Andy Adamson 已提交
6565
{
6566 6567
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
A
Andy Adamson 已提交
6568

6569 6570
	if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp))
		return;
A
Andy Adamson 已提交
6571

6572
	trace_nfs4_sequence(clp, task->tk_status);
A
Andy Adamson 已提交
6573 6574
	if (task->tk_status < 0) {
		dprintk("%s ERROR %d\n", __func__, task->tk_status);
6575 6576
		if (atomic_read(&clp->cl_count) == 1)
			goto out;
A
Andy Adamson 已提交
6577

6578 6579
		if (nfs41_sequence_handle_errors(task, clp) == -EAGAIN) {
			rpc_restart_call_prepare(task);
A
Andy Adamson 已提交
6580 6581 6582 6583
			return;
		}
	}
	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
6584
out:
A
Andy Adamson 已提交
6585 6586 6587 6588 6589
	dprintk("<-- %s\n", __func__);
}

static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
{
6590 6591
	struct nfs4_sequence_data *calldata = data;
	struct nfs_client *clp = calldata->clp;
A
Andy Adamson 已提交
6592 6593 6594 6595 6596 6597
	struct nfs4_sequence_args *args;
	struct nfs4_sequence_res *res;

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

6598
	nfs41_setup_sequence(clp->cl_session, args, res, task);
A
Andy Adamson 已提交
6599 6600 6601 6602 6603
}

static const struct rpc_call_ops nfs41_sequence_ops = {
	.rpc_call_done = nfs41_sequence_call_done,
	.rpc_call_prepare = nfs41_sequence_prepare,
6604
	.rpc_release = nfs41_sequence_release,
A
Andy Adamson 已提交
6605 6606
};

6607 6608 6609
static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
		struct rpc_cred *cred,
		bool is_privileged)
A
Andy Adamson 已提交
6610
{
6611
	struct nfs4_sequence_data *calldata;
A
Andy Adamson 已提交
6612 6613 6614 6615
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE],
		.rpc_cred = cred,
	};
6616 6617 6618
	struct rpc_task_setup task_setup_data = {
		.rpc_client = clp->cl_rpcclient,
		.rpc_message = &msg,
6619
		.callback_ops = &nfs41_sequence_ops,
6620
		.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
6621
	};
A
Andy Adamson 已提交
6622

6623
	if (!atomic_inc_not_zero(&clp->cl_count))
6624
		return ERR_PTR(-EIO);
6625
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
6626
	if (calldata == NULL) {
6627
		nfs_put_client(clp);
6628
		return ERR_PTR(-ENOMEM);
A
Andy Adamson 已提交
6629
	}
6630
	nfs4_init_sequence(&calldata->args, &calldata->res, 0);
6631 6632
	if (is_privileged)
		nfs4_set_sequence_privileged(&calldata->args);
6633 6634 6635
	msg.rpc_argp = &calldata->args;
	msg.rpc_resp = &calldata->res;
	calldata->clp = clp;
6636
	task_setup_data.callback_data = calldata;
A
Andy Adamson 已提交
6637

6638 6639 6640
	return rpc_run_task(&task_setup_data);
}

6641
static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags)
6642 6643 6644 6645
{
	struct rpc_task *task;
	int ret = 0;

6646 6647
	if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
		return 0;
6648
	task = _nfs41_proc_sequence(clp, cred, false);
6649 6650 6651
	if (IS_ERR(task))
		ret = PTR_ERR(task);
	else
6652
		rpc_put_task_async(task);
6653 6654 6655 6656 6657 6658 6659 6660 6661
	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;

6662
	task = _nfs41_proc_sequence(clp, cred, true);
6663 6664 6665 6666 6667
	if (IS_ERR(task)) {
		ret = PTR_ERR(task);
		goto out;
	}
	ret = rpc_wait_for_completion_task(task);
6668 6669 6670 6671 6672
	if (!ret) {
		struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;

		if (task->tk_status == 0)
			nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
6673
		ret = task->tk_status;
6674
	}
6675 6676 6677 6678
	rpc_put_task(task);
out:
	dprintk("<-- %s status=%d\n", __func__, ret);
	return ret;
A
Andy Adamson 已提交
6679 6680
}

6681 6682 6683 6684 6685 6686 6687 6688 6689 6690
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;

6691 6692 6693 6694
	nfs41_setup_sequence(calldata->clp->cl_session,
			&calldata->arg.seq_args,
			&calldata->res.seq_res,
			task);
6695 6696
}

6697 6698 6699 6700 6701 6702 6703 6704 6705
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);
6706 6707
		/* fall through */
	case -NFS4ERR_RETRY_UNCACHED_REP:
6708 6709
		return -EAGAIN;
	default:
6710
		nfs4_schedule_lease_recovery(clp);
6711 6712 6713 6714
	}
	return 0;
}

6715 6716 6717 6718 6719 6720 6721
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__);
6722 6723
	if (!nfs41_sequence_done(task, res))
		return;
6724

6725
	trace_nfs4_reclaim_complete(clp, task->tk_status);
6726 6727 6728 6729
	if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) {
		rpc_restart_call_prepare(task);
		return;
	}
6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748
	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.
 */
6749 6750
static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
		struct rpc_cred *cred)
6751 6752 6753 6754 6755
{
	struct nfs4_reclaim_complete_data *calldata;
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE],
6756
		.rpc_cred = cred,
6757 6758 6759 6760 6761 6762 6763 6764 6765 6766
	};
	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__);
6767
	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
6768 6769 6770 6771 6772
	if (calldata == NULL)
		goto out;
	calldata->clp = clp;
	calldata->arg.one_fs = 0;

6773
	nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
6774
	nfs4_set_sequence_privileged(&calldata->arg.seq_args);
6775 6776 6777 6778
	msg.rpc_argp = &calldata->arg;
	msg.rpc_resp = &calldata->res;
	task_setup_data.callback_data = calldata;
	task = rpc_run_task(&task_setup_data);
6779
	if (IS_ERR(task)) {
6780
		status = PTR_ERR(task);
6781 6782
		goto out;
	}
6783 6784 6785
	status = nfs4_wait_for_completion_rpc_task(task);
	if (status == 0)
		status = task->tk_status;
6786
	rpc_put_task(task);
6787
	return 0;
6788 6789 6790 6791
out:
	dprintk("<-- %s status=%d\n", __func__, status);
	return status;
}
6792 6793 6794 6795 6796

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

	dprintk("--> %s\n", __func__);
F
Fred Isaman 已提交
6801 6802 6803 6804 6805
	/* Note the is a race here, where a CB_LAYOUTRECALL can come in
	 * right now covering the LAYOUTGET we are about to send.
	 * However, that is not so catastrophic, and there seems
	 * to be no way to prevent it completely.
	 */
6806
	if (nfs41_setup_sequence(session, &lgp->args.seq_args,
6807
				&lgp->res.seq_res, task))
6808
		return;
6809 6810 6811 6812 6813
	if (pnfs_choose_layoutget_stateid(&lgp->args.stateid,
					  NFS_I(lgp->args.inode)->layout,
					  lgp->args.ctx->state)) {
		rpc_exit(task, NFS4_OK);
	}
6814 6815 6816 6817 6818
}

static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
6819 6820 6821 6822
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
	struct pnfs_layout_hdr *lo;
	struct nfs4_state *state = NULL;
6823
	unsigned long timeo, giveup;
6824 6825 6826

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

6827
	if (!nfs41_sequence_done(task, &lgp->res.seq_res))
6828
		goto out;
6829 6830 6831

	switch (task->tk_status) {
	case 0:
6832
		goto out;
6833 6834
	case -NFS4ERR_LAYOUTTRYLATER:
	case -NFS4ERR_RECALLCONFLICT:
6835 6836 6837 6838
		timeo = rpc_get_timeout(task->tk_client);
		giveup = lgp->args.timestamp + timeo;
		if (time_after(giveup, jiffies))
			task->tk_status = -NFS4ERR_DELAY;
6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855
		break;
	case -NFS4ERR_EXPIRED:
	case -NFS4ERR_BAD_STATEID:
		spin_lock(&inode->i_lock);
		lo = NFS_I(inode)->layout;
		if (!lo || list_empty(&lo->plh_segs)) {
			spin_unlock(&inode->i_lock);
			/* If the open stateid was bad, then recover it. */
			state = lgp->args.ctx->state;
		} else {
			LIST_HEAD(head);

			pnfs_mark_matching_lsegs_invalid(lo, &head, NULL);
			spin_unlock(&inode->i_lock);
			/* Mark the bad layout state as invalid, then
			 * retry using the open stateid. */
			pnfs_free_lseg_list(&head);
6856 6857
		}
	}
6858 6859 6860
	if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
		rpc_restart_call_prepare(task);
out:
6861 6862 6863
	dprintk("<-- %s\n", __func__);
}

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

6908 6909 6910
static void nfs4_layoutget_release(void *calldata)
{
	struct nfs4_layoutget *lgp = calldata;
6911 6912
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
6913
	size_t max_pages = max_response_pages(server);
6914 6915

	dprintk("--> %s\n", __func__);
6916
	nfs4_free_pages(lgp->args.layout.pages, max_pages);
6917
	pnfs_put_layout_hdr(NFS_I(inode)->layout);
6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928
	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,
};

6929 6930
struct pnfs_layout_segment *
nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
6931
{
6932 6933
	struct inode *inode = lgp->args.inode;
	struct nfs_server *server = NFS_SERVER(inode);
6934
	size_t max_pages = max_response_pages(server);
6935 6936 6937 6938 6939
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
		.rpc_argp = &lgp->args,
		.rpc_resp = &lgp->res,
6940
		.rpc_cred = lgp->cred,
6941 6942 6943 6944 6945 6946 6947 6948
	};
	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,
	};
6949
	struct pnfs_layout_segment *lseg = NULL;
6950 6951 6952 6953
	int status = 0;

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

6954 6955 6956
	lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
	if (!lgp->args.layout.pages) {
		nfs4_layoutget_release(lgp);
6957
		return ERR_PTR(-ENOMEM);
6958 6959
	}
	lgp->args.layout.pglen = max_pages * PAGE_SIZE;
6960
	lgp->args.timestamp = jiffies;
6961

6962
	lgp->res.layoutp = &lgp->args.layout;
6963
	lgp->res.seq_res.sr_slot = NULL;
6964
	nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
6965 6966 6967 6968

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

6969 6970
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
6971
		return ERR_CAST(task);
6972
	status = nfs4_wait_for_completion_rpc_task(task);
F
Fred Isaman 已提交
6973 6974
	if (status == 0)
		status = task->tk_status;
6975 6976 6977 6978
	trace_nfs4_layoutget(lgp->args.ctx,
			&lgp->args.range,
			&lgp->res.range,
			status);
6979 6980
	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
	if (status == 0 && lgp->res.layoutp->len)
6981
		lseg = pnfs_layout_process(lgp);
6982 6983
	rpc_put_task(task);
	dprintk("<-- %s status=%d\n", __func__, status);
6984 6985 6986
	if (status)
		return ERR_PTR(status);
	return lseg;
6987 6988
}

B
Benny Halevy 已提交
6989 6990 6991 6992 6993 6994
static void
nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs4_layoutreturn *lrp = calldata;

	dprintk("--> %s\n", __func__);
6995 6996 6997 6998
	nfs41_setup_sequence(lrp->clp->cl_session,
			&lrp->args.seq_args,
			&lrp->res.seq_res,
			task);
B
Benny Halevy 已提交
6999 7000 7001 7002 7003 7004 7005 7006 7007
}

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

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

7008
	if (!nfs41_sequence_done(task, &lrp->res.seq_res))
B
Benny Halevy 已提交
7009 7010 7011 7012
		return;

	server = NFS_SERVER(lrp->args.inode);
	if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
7013
		rpc_restart_call_prepare(task);
B
Benny Halevy 已提交
7014 7015 7016 7017 7018 7019 7020 7021
		return;
	}
	dprintk("<-- %s\n", __func__);
}

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

	dprintk("--> %s\n", __func__);
7025 7026 7027 7028 7029
	spin_lock(&lo->plh_inode->i_lock);
	if (lrp->res.lrs_present)
		pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
	lo->plh_block_lgets--;
	spin_unlock(&lo->plh_inode->i_lock);
7030
	pnfs_put_layout_hdr(lrp->args.layout);
B
Benny Halevy 已提交
7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047
	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,
};

int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp)
{
	struct rpc_task *task;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTRETURN],
		.rpc_argp = &lrp->args,
		.rpc_resp = &lrp->res,
7048
		.rpc_cred = lrp->cred,
B
Benny Halevy 已提交
7049 7050
	};
	struct rpc_task_setup task_setup_data = {
7051
		.rpc_client = NFS_SERVER(lrp->args.inode)->client,
B
Benny Halevy 已提交
7052 7053 7054 7055 7056 7057 7058
		.rpc_message = &msg,
		.callback_ops = &nfs4_layoutreturn_call_ops,
		.callback_data = lrp,
	};
	int status;

	dprintk("--> %s\n", __func__);
7059
	nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1);
B
Benny Halevy 已提交
7060 7061 7062 7063
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
		return PTR_ERR(task);
	status = task->tk_status;
7064
	trace_nfs4_layoutreturn(lrp->args.inode, status);
B
Benny Halevy 已提交
7065 7066 7067 7068 7069
	dprintk("<-- %s status=%d\n", __func__, status);
	rpc_put_task(task);
	return status;
}

A
Andy Adamson 已提交
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
/*
 * Retrieve the list of Data Server devices from the MDS.
 */
static int _nfs4_getdevicelist(struct nfs_server *server,
				    const struct nfs_fh *fh,
				    struct pnfs_devicelist *devlist)
{
	struct nfs4_getdevicelist_args args = {
		.fh = fh,
		.layoutclass = server->pnfs_curr_ld->id,
	};
	struct nfs4_getdevicelist_res res = {
		.devlist = devlist,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICELIST],
		.rpc_argp = &args,
		.rpc_resp = &res,
	};
	int status;

	dprintk("--> %s\n", __func__);
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args,
				&res.seq_res, 0);
	dprintk("<-- %s status=%d\n", __func__, status);
	return status;
}

int nfs4_proc_getdevicelist(struct nfs_server *server,
			    const struct nfs_fh *fh,
			    struct pnfs_devicelist *devlist)
{
	struct nfs4_exception exception = { };
	int err;

	do {
		err = nfs4_handle_exception(server,
				_nfs4_getdevicelist(server, fh, devlist),
				&exception);
	} while (exception.retry);

	dprintk("%s: err=%d, num_devs=%u\n", __func__,
		err, devlist->num_devs);

	return err;
}
EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist);

7118
static int
7119 7120 7121
_nfs4_proc_getdeviceinfo(struct nfs_server *server,
		struct pnfs_device *pdev,
		struct rpc_cred *cred)
7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132
{
	struct nfs4_getdeviceinfo_args args = {
		.pdev = pdev,
	};
	struct nfs4_getdeviceinfo_res res = {
		.pdev = pdev,
	};
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO],
		.rpc_argp = &args,
		.rpc_resp = &res,
7133
		.rpc_cred = cred,
7134 7135 7136 7137
	};
	int status;

	dprintk("--> %s\n", __func__);
7138
	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
7139 7140 7141 7142 7143
	dprintk("<-- %s status=%d\n", __func__, status);

	return status;
}

7144 7145 7146
int nfs4_proc_getdeviceinfo(struct nfs_server *server,
		struct pnfs_device *pdev,
		struct rpc_cred *cred)
7147 7148 7149 7150 7151 7152
{
	struct nfs4_exception exception = { };
	int err;

	do {
		err = nfs4_handle_exception(server,
7153
					_nfs4_proc_getdeviceinfo(server, pdev, cred),
7154 7155 7156 7157 7158 7159
					&exception);
	} while (exception.retry);
	return err;
}
EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);

A
Andy Adamson 已提交
7160 7161 7162 7163
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);
7164
	struct nfs4_session *session = nfs4_get_session(server);
A
Andy Adamson 已提交
7165

7166 7167 7168 7169
	nfs41_setup_sequence(session,
			&data->args.seq_args,
			&data->res.seq_res,
			task);
A
Andy Adamson 已提交
7170 7171 7172 7173 7174 7175 7176 7177
}

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

7178
	if (!nfs41_sequence_done(task, &data->res.seq_res))
A
Andy Adamson 已提交
7179 7180 7181
		return;

	switch (task->tk_status) { /* Just ignore these failures */
7182 7183 7184 7185
	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 已提交
7186
		task->tk_status = 0;
7187 7188
		break;
	case 0:
A
Andy Adamson 已提交
7189 7190
		nfs_post_op_update_inode_force_wcc(data->args.inode,
						   data->res.fattr);
7191 7192 7193 7194 7195 7196 7197
		break;
	default:
		if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
			rpc_restart_call_prepare(task);
			return;
		}
	}
A
Andy Adamson 已提交
7198 7199 7200 7201 7202 7203
}

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

A
Andy Adamson 已提交
7204
	pnfs_cleanup_layoutcommit(data);
A
Andy Adamson 已提交
7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215
	put_rpccred(data->cred);
	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
7216
nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
A
Andy Adamson 已提交
7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240
{
	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,
		.flags = RPC_TASK_ASYNC,
	};
	struct rpc_task *task;
	int status = 0;

	dprintk("NFS: %4d initiating layoutcommit call. sync %d "
		"lbw: %llu inode %lu\n",
		data->task.tk_pid, sync,
		data->args.lastbytewritten,
		data->args.inode->i_ino);

7241
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
A
Andy Adamson 已提交
7242 7243 7244
	task = rpc_run_task(&task_setup_data);
	if (IS_ERR(task))
		return PTR_ERR(task);
7245
	if (sync == false)
A
Andy Adamson 已提交
7246 7247 7248 7249 7250
		goto out;
	status = nfs4_wait_for_completion_rpc_task(task);
	if (status != 0)
		goto out;
	status = task->tk_status;
7251
	trace_nfs4_layoutcommit(data->args.inode, status);
A
Andy Adamson 已提交
7252 7253 7254 7255 7256
out:
	dprintk("%s: status %d\n", __func__, status);
	rpc_put_task(task);
	return status;
}
7257

7258 7259 7260 7261
/**
 * Use the state managment nfs_client cl_rpcclient, which uses krb5i (if
 * possible) as per RFC3530bis and RFC5661 Security Considerations sections
 */
7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276
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 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,
	};
7277 7278
	return nfs4_call_sync(server->nfs_client->cl_rpcclient, server, &msg,
				&args.seq_args, &res.seq_res, 0);
7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292
}

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 {
		err = _nfs41_proc_secinfo_no_name(server, fhandle, info, flavors);
		switch (err) {
		case 0:
		case -NFS4ERR_WRONGSEC:
		case -NFS4ERR_NOTSUPP:
7293
			goto out;
7294 7295 7296 7297
		default:
			err = nfs4_handle_exception(server, err, &exception);
		}
	} while (exception.retry);
7298
out:
7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341
	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;
	rpc_authflavor_t flavor;
	struct nfs4_secinfo_flavors *flavors;

	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
	 */
	if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) {
		err = nfs4_find_root_sec(server, fhandle, info);
		goto out_freepage;
	}
	if (err)
		goto out_freepage;

	flavor = nfs_find_best_sec(flavors);
	if (err == 0)
		err = nfs4_lookup_root_sec(server, fhandle, info, flavor);

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

7343 7344 7345
static int _nfs41_test_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
7346 7347 7348
{
	int status;
	struct nfs41_test_stateid_args args = {
7349
		.stateid = stateid,
B
Bryan Schumaker 已提交
7350 7351 7352 7353 7354 7355
	};
	struct nfs41_test_stateid_res res;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID],
		.rpc_argp = &args,
		.rpc_resp = &res,
7356
		.rpc_cred = cred,
B
Bryan Schumaker 已提交
7357
	};
7358

7359
	dprintk("NFS call  test_stateid %p\n", stateid);
7360
	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
7361 7362 7363
	nfs4_set_sequence_privileged(&args.seq_args);
	status = nfs4_call_sync_sequence(server->client, server, &msg,
			&args.seq_args, &res.seq_res);
7364 7365
	if (status != NFS_OK) {
		dprintk("NFS reply test_stateid: failed, %d\n", status);
7366
		return status;
7367 7368
	}
	dprintk("NFS reply test_stateid: succeeded, %d\n", -res.status);
7369
	return -res.status;
B
Bryan Schumaker 已提交
7370 7371
}

7372 7373 7374 7375 7376
/**
 * nfs41_test_stateid - perform a TEST_STATEID operation
 *
 * @server: server / transport on which to perform the operation
 * @stateid: state ID to test
7377
 * @cred: credential
7378 7379 7380 7381 7382
 *
 * 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.
 */
7383 7384 7385
static int nfs41_test_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
7386 7387 7388 7389
{
	struct nfs4_exception exception = { };
	int err;
	do {
7390
		err = _nfs41_test_stateid(server, stateid, cred);
7391 7392 7393
		if (err != -NFS4ERR_DELAY)
			break;
		nfs4_handle_exception(server, err, &exception);
B
Bryan Schumaker 已提交
7394 7395 7396
	} while (exception.retry);
	return err;
}
B
Bryan Schumaker 已提交
7397

7398 7399 7400
struct nfs_free_stateid_data {
	struct nfs_server *server;
	struct nfs41_free_stateid_args args;
B
Bryan Schumaker 已提交
7401
	struct nfs41_free_stateid_res res;
7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430
};

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:
		if (nfs4_async_handle_error(task, data->server, NULL) == -EAGAIN)
			rpc_restart_call_prepare(task);
	}
}

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

7431
static const struct rpc_call_ops nfs41_free_stateid_ops = {
7432 7433 7434 7435 7436 7437 7438
	.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,
		nfs4_stateid *stateid,
7439
		struct rpc_cred *cred,
7440 7441
		bool privileged)
{
B
Bryan Schumaker 已提交
7442 7443
	struct rpc_message msg = {
		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID],
7444
		.rpc_cred = cred,
B
Bryan Schumaker 已提交
7445
	};
7446 7447 7448 7449 7450 7451 7452
	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 已提交
7453

7454
	dprintk("NFS call  free_stateid %p\n", stateid);
7455 7456 7457 7458 7459 7460 7461 7462 7463 7464
	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;
7465
	nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
7466 7467 7468 7469
	if (privileged)
		nfs4_set_sequence_privileged(&data->args.seq_args);

	return rpc_run_task(&task_setup);
B
Bryan Schumaker 已提交
7470 7471
}

7472 7473 7474 7475 7476
/**
 * nfs41_free_stateid - perform a FREE_STATEID operation
 *
 * @server: server / transport on which to perform the operation
 * @stateid: state ID to release
7477
 * @cred: credential
7478 7479 7480 7481
 *
 * Returns NFS_OK if the server freed "stateid".  Otherwise a
 * negative NFS4ERR value is returned.
 */
7482 7483 7484
static int nfs41_free_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
B
Bryan Schumaker 已提交
7485
{
7486 7487 7488
	struct rpc_task *task;
	int ret;

7489
	task = _nfs41_free_stateid(server, stateid, cred, true);
7490 7491 7492 7493 7494 7495 7496
	if (IS_ERR(task))
		return PTR_ERR(task);
	ret = rpc_wait_for_completion_task(task);
	if (!ret)
		ret = task->tk_status;
	rpc_put_task(task);
	return ret;
B
Bryan Schumaker 已提交
7497
}
7498

7499 7500 7501
static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
{
	struct rpc_task *task;
7502
	struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
7503

7504
	task = _nfs41_free_stateid(server, &lsp->ls_stateid, cred, false);
7505 7506 7507 7508 7509 7510 7511
	nfs4_free_lock_state(server, lsp);
	if (IS_ERR(task))
		return PTR_ERR(task);
	rpc_put_task(task);
	return 0;
}

7512 7513 7514
static bool nfs41_match_stateid(const nfs4_stateid *s1,
		const nfs4_stateid *s2)
{
7515
	if (memcmp(s1->other, s2->other, sizeof(s1->other)) != 0)
7516 7517
		return false;

7518
	if (s1->seqid == s2->seqid)
7519
		return true;
7520
	if (s1->seqid == 0 || s2->seqid == 0)
7521 7522 7523 7524 7525
		return true;

	return false;
}

7526 7527
#endif /* CONFIG_NFS_V4_1 */

7528 7529 7530
static bool nfs4_match_stateid(const nfs4_stateid *s1,
		const nfs4_stateid *s2)
{
7531
	return nfs4_stateid_match(s1, s2);
7532 7533 7534
}


7535
static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
7536
	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
7537
	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
L
Linus Torvalds 已提交
7538 7539
	.recover_open	= nfs4_open_reclaim,
	.recover_lock	= nfs4_lock_reclaim,
7540
	.establish_clid = nfs4_init_clientid,
7541
	.detect_trunking = nfs40_discover_server_trunking,
L
Linus Torvalds 已提交
7542 7543
};

7544
#if defined(CONFIG_NFS_V4_1)
7545
static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
7546 7547 7548 7549
	.owner_flag_bit = NFS_OWNER_RECLAIM_REBOOT,
	.state_flag_bit	= NFS_STATE_RECLAIM_REBOOT,
	.recover_open	= nfs4_open_reclaim,
	.recover_lock	= nfs4_lock_reclaim,
7550
	.establish_clid = nfs41_init_clientid,
7551
	.reclaim_complete = nfs41_proc_reclaim_complete,
7552
	.detect_trunking = nfs41_discover_server_trunking,
7553 7554 7555
};
#endif /* CONFIG_NFS_V4_1 */

7556
static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
7557 7558 7559 7560 7561 7562 7563 7564
	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
	.recover_open	= nfs4_open_expired,
	.recover_lock	= nfs4_lock_expired,
	.establish_clid = nfs4_init_clientid,
};

#if defined(CONFIG_NFS_V4_1)
7565
static const struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
7566
	.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
7567
	.state_flag_bit	= NFS_STATE_RECLAIM_NOGRACE,
7568 7569
	.recover_open	= nfs41_open_expired,
	.recover_lock	= nfs41_lock_expired,
7570
	.establish_clid = nfs41_init_clientid,
L
Linus Torvalds 已提交
7571
};
7572
#endif /* CONFIG_NFS_V4_1 */
L
Linus Torvalds 已提交
7573

7574
static const struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
B
Benny Halevy 已提交
7575
	.sched_state_renewal = nfs4_proc_async_renew,
7576
	.get_state_renewal_cred_locked = nfs4_get_renew_cred_locked,
7577
	.renew_lease = nfs4_proc_renew,
B
Benny Halevy 已提交
7578 7579 7580
};

#if defined(CONFIG_NFS_V4_1)
7581
static const struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
B
Benny Halevy 已提交
7582
	.sched_state_renewal = nfs41_proc_async_sequence,
7583
	.get_state_renewal_cred_locked = nfs4_get_machine_cred_locked,
7584
	.renew_lease = nfs4_proc_sequence,
B
Benny Halevy 已提交
7585 7586 7587
};
#endif

7588 7589
static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
	.minor_version = 0,
7590 7591 7592 7593
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_CHANGE_ATTR
		| NFS_CAP_POSIX_LOCK,
7594 7595
	.init_client = nfs40_init_client,
	.shutdown_client = nfs40_shutdown_client,
7596
	.match_stateid = nfs4_match_stateid,
7597
	.find_root_sec = nfs4_find_root_sec,
7598
	.free_lock_state = nfs4_release_lockowner,
7599
	.call_sync_ops = &nfs40_call_sync_ops,
7600 7601 7602
	.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
	.state_renewal_ops = &nfs40_state_renewal_ops,
7603 7604 7605 7606 7607
};

#if defined(CONFIG_NFS_V4_1)
static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
	.minor_version = 1,
7608 7609 7610
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_CHANGE_ATTR
7611
		| NFS_CAP_POSIX_LOCK
7612 7613
		| NFS_CAP_STATEID_NFSV41
		| NFS_CAP_ATOMIC_OPEN_V1,
7614 7615
	.init_client = nfs41_init_client,
	.shutdown_client = nfs41_shutdown_client,
7616
	.match_stateid = nfs41_match_stateid,
7617
	.find_root_sec = nfs41_find_root_sec,
7618
	.free_lock_state = nfs41_free_lock_state,
7619
	.call_sync_ops = &nfs41_call_sync_ops,
7620 7621 7622
	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
	.state_renewal_ops = &nfs41_state_renewal_ops,
7623 7624 7625
};
#endif

7626 7627 7628
#if defined(CONFIG_NFS_V4_2)
static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
	.minor_version = 2,
7629 7630 7631 7632 7633 7634
	.init_caps = NFS_CAP_READDIRPLUS
		| NFS_CAP_ATOMIC_OPEN
		| NFS_CAP_CHANGE_ATTR
		| NFS_CAP_POSIX_LOCK
		| NFS_CAP_STATEID_NFSV41
		| NFS_CAP_ATOMIC_OPEN_V1,
7635 7636
	.init_client = nfs41_init_client,
	.shutdown_client = nfs41_shutdown_client,
7637 7638
	.match_stateid = nfs41_match_stateid,
	.find_root_sec = nfs41_find_root_sec,
7639
	.free_lock_state = nfs41_free_lock_state,
7640
	.call_sync_ops = &nfs41_call_sync_ops,
7641 7642 7643 7644 7645 7646
	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
	.state_renewal_ops = &nfs41_state_renewal_ops,
};
#endif

7647 7648 7649 7650 7651
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
7652 7653 7654
#if defined(CONFIG_NFS_V4_2)
	[2] = &nfs_v4_2_minor_ops,
#endif
7655 7656
};

7657
static const struct inode_operations nfs4_dir_inode_operations = {
7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676
	.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,
	.getxattr	= generic_getxattr,
	.setxattr	= generic_setxattr,
	.listxattr	= generic_listxattr,
	.removexattr	= generic_removexattr,
};

7677
static const struct inode_operations nfs4_file_inode_operations = {
7678 7679 7680
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
7681 7682 7683 7684
	.getxattr	= generic_getxattr,
	.setxattr	= generic_setxattr,
	.listxattr	= generic_listxattr,
	.removexattr	= generic_removexattr,
7685 7686
};

D
David Howells 已提交
7687
const struct nfs_rpc_ops nfs_v4_clientops = {
L
Linus Torvalds 已提交
7688 7689 7690
	.version	= 4,			/* protocol version */
	.dentry_ops	= &nfs4_dentry_operations,
	.dir_inode_ops	= &nfs4_dir_inode_operations,
7691
	.file_inode_ops	= &nfs4_file_inode_operations,
7692
	.file_ops	= &nfs4_file_operations,
L
Linus Torvalds 已提交
7693
	.getroot	= nfs4_proc_get_root,
B
Bryan Schumaker 已提交
7694
	.submount	= nfs4_submount,
B
Bryan Schumaker 已提交
7695
	.try_mount	= nfs4_try_mount,
L
Linus Torvalds 已提交
7696 7697 7698 7699 7700 7701 7702 7703
	.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,
7704
	.unlink_rpc_prepare = nfs4_proc_unlink_rpc_prepare,
L
Linus Torvalds 已提交
7705 7706
	.unlink_done	= nfs4_proc_unlink_done,
	.rename		= nfs4_proc_rename,
7707
	.rename_setup	= nfs4_proc_rename_setup,
7708
	.rename_rpc_prepare = nfs4_proc_rename_rpc_prepare,
7709
	.rename_done	= nfs4_proc_rename_done,
L
Linus Torvalds 已提交
7710 7711 7712 7713 7714 7715 7716 7717 7718
	.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,
7719
	.set_capabilities = nfs4_server_capabilities,
L
Linus Torvalds 已提交
7720 7721
	.decode_dirent	= nfs4_decode_dirent,
	.read_setup	= nfs4_proc_read_setup,
7722
	.read_pageio_init = pnfs_pageio_init_read,
7723
	.read_rpc_prepare = nfs4_proc_read_rpc_prepare,
T
Trond Myklebust 已提交
7724
	.read_done	= nfs4_read_done,
L
Linus Torvalds 已提交
7725
	.write_setup	= nfs4_proc_write_setup,
7726
	.write_pageio_init = pnfs_pageio_init_write,
7727
	.write_rpc_prepare = nfs4_proc_write_rpc_prepare,
7728
	.write_done	= nfs4_write_done,
L
Linus Torvalds 已提交
7729
	.commit_setup	= nfs4_proc_commit_setup,
7730
	.commit_rpc_prepare = nfs4_proc_commit_rpc_prepare,
7731
	.commit_done	= nfs4_commit_done,
L
Linus Torvalds 已提交
7732
	.lock		= nfs4_proc_lock,
7733
	.clear_acl_cache = nfs4_zap_acl_attr,
T
Trond Myklebust 已提交
7734
	.close_context  = nfs4_close_context,
7735
	.open_context	= nfs4_atomic_open,
7736
	.have_delegation = nfs4_have_delegation,
7737
	.return_delegation = nfs4_inode_return_delegation,
7738
	.alloc_client	= nfs4_alloc_client,
7739
	.init_client	= nfs4_init_client,
7740
	.free_client	= nfs4_free_client,
7741 7742
	.create_server	= nfs4_create_server,
	.clone_server	= nfs_clone_server,
L
Linus Torvalds 已提交
7743 7744
};

7745 7746 7747 7748 7749 7750 7751 7752 7753
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
	.prefix	= XATTR_NAME_NFSV4_ACL,
	.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,
7754 7755 7756
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
	&nfs4_xattr_nfs4_label_handler,
#endif
7757 7758 7759
	NULL
};

L
Linus Torvalds 已提交
7760 7761 7762 7763 7764
/*
 * Local variables:
 *  c-basic-offset: 8
 * End:
 */