super.c 36.2 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
D
David Howells 已提交
2 3 4 5 6 7 8
/*
 *  linux/fs/nfs/super.c
 *
 *  Copyright (C) 1992  Rick Sladkey
 *
 *  nfs superblock handling functions
 *
A
Alan Cox 已提交
9
 *  Modularised by Alan Cox <alan@lxorguk.ukuu.org.uk>, while hacking some
D
David Howells 已提交
10 11 12 13 14 15 16
 *  experimental NFS changes. Modularisation taken straight from SYS5 fs.
 *
 *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
 *  J.S.Peatfield@damtp.cam.ac.uk
 *
 *  Split from inode.c by David Howells <dhowells@redhat.com>
 *
17 18 19 20 21
 * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a
 *   particular server are held in the same superblock
 * - NFS superblocks can have several effective roots to the dentry tree
 * - directory type roots are spliced into the tree when a path from one root reaches the root
 *   of another (see nfs_lookup())
D
David Howells 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34
 */

#include <linux/module.h>
#include <linux/init.h>

#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/sunrpc/clnt.h>
35
#include <linux/sunrpc/addr.h>
D
David Howells 已提交
36 37
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/metrics.h>
38
#include <linux/sunrpc/xprtsock.h>
\
\"Talpey, Thomas\ 已提交
39
#include <linux/sunrpc/xprtrdma.h>
D
David Howells 已提交
40 41 42 43 44 45
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
#include <linux/nfs4_mount.h>
#include <linux/lockd/bind.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
46
#include <linux/namei.h>
D
David Howells 已提交
47 48
#include <linux/vfs.h>
#include <linux/inet.h>
49
#include <linux/in6.h>
50
#include <linux/slab.h>
51
#include <net/ipv6.h>
52
#include <linux/netdevice.h>
D
David Howells 已提交
53
#include <linux/nfs_xdr.h>
54
#include <linux/magic.h>
55
#include <linux/parser.h>
56
#include <linux/nsproxy.h>
57
#include <linux/rcupdate.h>
D
David Howells 已提交
58

59
#include <linux/uaccess.h>
D
David Howells 已提交
60 61 62 63 64 65

#include "nfs4_fs.h"
#include "callback.h"
#include "delegation.h"
#include "iostat.h"
#include "internal.h"
66
#include "fscache.h"
67
#include "nfs4session.h"
J
J. Bruce Fields 已提交
68
#include "pnfs.h"
69
#include "nfs.h"
D
David Howells 已提交
70 71

#define NFSDBG_FACILITY		NFSDBG_VFS
72

73
const struct super_operations nfs_sops = {
D
David Howells 已提交
74
	.alloc_inode	= nfs_alloc_inode,
A
Al Viro 已提交
75
	.free_inode	= nfs_free_inode,
D
David Howells 已提交
76
	.write_inode	= nfs_write_inode,
77
	.drop_inode	= nfs_drop_inode,
D
David Howells 已提交
78
	.statfs		= nfs_statfs,
79
	.evict_inode	= nfs_evict_inode,
D
David Howells 已提交
80 81
	.umount_begin	= nfs_umount_begin,
	.show_options	= nfs_show_options,
82 83
	.show_devname	= nfs_show_devname,
	.show_path	= nfs_show_path,
D
David Howells 已提交
84 85
	.show_stats	= nfs_show_stats,
};
B
Bryan Schumaker 已提交
86
EXPORT_SYMBOL_GPL(nfs_sops);
D
David Howells 已提交
87

B
Bryan Schumaker 已提交
88
#if IS_ENABLED(CONFIG_NFS_V4)
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
static int __init register_nfs4_fs(void)
{
	return register_filesystem(&nfs4_fs_type);
}

static void unregister_nfs4_fs(void)
{
	unregister_filesystem(&nfs4_fs_type);
}
#else
static int __init register_nfs4_fs(void)
{
	return 0;
}

static void unregister_nfs4_fs(void)
{
}
D
David Howells 已提交
107 108
#endif

109
static struct shrinker acl_shrinker = {
110 111
	.count_objects	= nfs_access_cache_count,
	.scan_objects	= nfs_access_cache_scan,
112 113
	.seeks		= DEFAULT_SEEKS,
};
114

D
David Howells 已提交
115 116 117 118 119 120 121 122 123 124 125
/*
 * Register the NFS filesystems
 */
int __init register_nfs_fs(void)
{
	int ret;

        ret = register_filesystem(&nfs_fs_type);
	if (ret < 0)
		goto error_0;

126
	ret = register_nfs4_fs();
D
David Howells 已提交
127 128
	if (ret < 0)
		goto error_1;
129 130 131 132

	ret = nfs_register_sysctl();
	if (ret < 0)
		goto error_2;
133 134 135
	ret = register_shrinker(&acl_shrinker);
	if (ret < 0)
		goto error_3;
D
David Howells 已提交
136
	return 0;
137 138
error_3:
	nfs_unregister_sysctl();
139 140
error_2:
	unregister_nfs4_fs();
D
David Howells 已提交
141 142 143 144 145 146 147 148 149 150 151
error_1:
	unregister_filesystem(&nfs_fs_type);
error_0:
	return ret;
}

/*
 * Unregister the NFS filesystems
 */
void __exit unregister_nfs_fs(void)
{
152
	unregister_shrinker(&acl_shrinker);
153
	nfs_unregister_sysctl();
154
	unregister_nfs4_fs();
D
David Howells 已提交
155 156 157
	unregister_filesystem(&nfs_fs_type);
}

158
bool nfs_sb_active(struct super_block *sb)
159
{
160
	struct nfs_server *server = NFS_SB(sb);
161

162 163 164 165 166
	if (!atomic_inc_not_zero(&sb->s_active))
		return false;
	if (atomic_inc_return(&server->active) != 1)
		atomic_dec(&sb->s_active);
	return true;
167
}
B
Bryan Schumaker 已提交
168
EXPORT_SYMBOL_GPL(nfs_sb_active);
169

170
void nfs_sb_deactive(struct super_block *sb)
171 172
{
	struct nfs_server *server = NFS_SB(sb);
173 174 175

	if (atomic_dec_and_test(&server->active))
		deactivate_super(sb);
176
}
B
Bryan Schumaker 已提交
177
EXPORT_SYMBOL_GPL(nfs_sb_deactive);
178

179 180 181 182 183 184 185 186 187
static int __nfs_list_for_each_server(struct list_head *head,
		int (*fn)(struct nfs_server *, void *),
		void *data)
{
	struct nfs_server *server, *last = NULL;
	int ret = 0;

	rcu_read_lock();
	list_for_each_entry_rcu(server, head, client_link) {
188
		if (!(server->super && nfs_sb_active(server->super)))
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
			continue;
		rcu_read_unlock();
		if (last)
			nfs_sb_deactive(last->super);
		last = server;
		ret = fn(server, data);
		if (ret)
			goto out;
		rcu_read_lock();
	}
	rcu_read_unlock();
out:
	if (last)
		nfs_sb_deactive(last->super);
	return ret;
}

int nfs_client_for_each_server(struct nfs_client *clp,
		int (*fn)(struct nfs_server *, void *),
		void *data)
{
	return __nfs_list_for_each_server(&clp->cl_superblocks, fn, data);
}
EXPORT_SYMBOL_GPL(nfs_client_for_each_server);

D
David Howells 已提交
214 215 216
/*
 * Deliver file system statistics to userspace
 */
217
int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
D
David Howells 已提交
218
{
219
	struct nfs_server *server = NFS_SB(dentry->d_sb);
D
David Howells 已提交
220 221
	unsigned char blockbits;
	unsigned long blockres;
222
	struct nfs_fh *fh = NFS_FH(d_inode(dentry));
223 224 225 226 227 228
	struct nfs_fsstat res;
	int error = -ENOMEM;

	res.fattr = nfs_alloc_fattr();
	if (res.fattr == NULL)
		goto out_err;
D
David Howells 已提交
229

230
	error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
M
Menyhart Zoltan 已提交
231 232 233 234
	if (unlikely(error == -ESTALE)) {
		struct dentry *pd_dentry;

		pd_dentry = dget_parent(dentry);
A
Al Viro 已提交
235 236
		nfs_zap_caches(d_inode(pd_dentry));
		dput(pd_dentry);
M
Menyhart Zoltan 已提交
237
	}
238
	nfs_free_fattr(res.fattr);
D
David Howells 已提交
239 240
	if (error < 0)
		goto out_err;
241

A
Amnon Aaronsohn 已提交
242
	buf->f_type = NFS_SUPER_MAGIC;
D
David Howells 已提交
243 244 245 246 247 248

	/*
	 * Current versions of glibc do not correctly handle the
	 * case where f_frsize != f_bsize.  Eventually we want to
	 * report the value of wtmult in this field.
	 */
249
	buf->f_frsize = dentry->d_sb->s_blocksize;
D
David Howells 已提交
250 251 252 253 254 255 256 257

	/*
	 * On most *nix systems, f_blocks, f_bfree, and f_bavail
	 * are reported in units of f_frsize.  Linux hasn't had
	 * an f_frsize field in its statfs struct until recently,
	 * thus historically Linux's sys_statfs reports these
	 * fields in units of f_bsize.
	 */
258 259
	buf->f_bsize = dentry->d_sb->s_blocksize;
	blockbits = dentry->d_sb->s_blocksize_bits;
D
David Howells 已提交
260 261 262 263 264 265 266 267 268
	blockres = (1 << blockbits) - 1;
	buf->f_blocks = (res.tbytes + blockres) >> blockbits;
	buf->f_bfree = (res.fbytes + blockres) >> blockbits;
	buf->f_bavail = (res.abytes + blockres) >> blockbits;

	buf->f_files = res.tfiles;
	buf->f_ffree = res.afiles;

	buf->f_namelen = server->namelen;
A
Amnon Aaronsohn 已提交
269

D
David Howells 已提交
270 271 272
	return 0;

 out_err:
273
	dprintk("%s: statfs error = %d\n", __func__, -error);
A
Amnon Aaronsohn 已提交
274
	return error;
D
David Howells 已提交
275
}
B
Bryan Schumaker 已提交
276
EXPORT_SYMBOL_GPL(nfs_statfs);
D
David Howells 已提交
277

278 279 280
/*
 * Map the security flavour number to a name
 */
281 282
static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
{
283
	static const struct {
284 285
		rpc_authflavor_t flavour;
		const char *str;
286 287
	} sec_flavours[NFS_AUTH_INFO_MAX_FLAVORS] = {
		/* update NFS_AUTH_INFO_MAX_FLAVORS when this list changes! */
288 289 290 291 292 293 294 295 296 297 298
		{ RPC_AUTH_NULL, "null" },
		{ RPC_AUTH_UNIX, "sys" },
		{ RPC_AUTH_GSS_KRB5, "krb5" },
		{ RPC_AUTH_GSS_KRB5I, "krb5i" },
		{ RPC_AUTH_GSS_KRB5P, "krb5p" },
		{ RPC_AUTH_GSS_LKEY, "lkey" },
		{ RPC_AUTH_GSS_LKEYI, "lkeyi" },
		{ RPC_AUTH_GSS_LKEYP, "lkeyp" },
		{ RPC_AUTH_GSS_SPKM, "spkm" },
		{ RPC_AUTH_GSS_SPKMI, "spkmi" },
		{ RPC_AUTH_GSS_SPKMP, "spkmp" },
299
		{ UINT_MAX, "unknown" }
300 301 302
	};
	int i;

303
	for (i = 0; sec_flavours[i].flavour != UINT_MAX; i++) {
304 305 306 307 308 309
		if (sec_flavours[i].flavour == flavour)
			break;
	}
	return sec_flavours[i].str;
}

310 311 312 313
static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss,
				  int showdefaults)
{
	struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address;
N
NeilBrown 已提交
314
	char *proto = NULL;
315 316 317 318 319

	switch (sap->sa_family) {
	case AF_INET:
		switch (nfss->mountd_protocol) {
		case IPPROTO_UDP:
N
NeilBrown 已提交
320
			proto = RPCBIND_NETID_UDP;
321 322
			break;
		case IPPROTO_TCP:
N
NeilBrown 已提交
323
			proto = RPCBIND_NETID_TCP;
324 325 326 327 328 329
			break;
		}
		break;
	case AF_INET6:
		switch (nfss->mountd_protocol) {
		case IPPROTO_UDP:
N
NeilBrown 已提交
330
			proto = RPCBIND_NETID_UDP6;
331 332
			break;
		case IPPROTO_TCP:
N
NeilBrown 已提交
333
			proto = RPCBIND_NETID_TCP6;
334 335 336 337
			break;
		}
		break;
	}
N
NeilBrown 已提交
338 339
	if (proto || showdefaults)
		seq_printf(m, ",mountproto=%s", proto ?: "auto");
340 341
}

342 343 344 345 346
static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
				    int showdefaults)
{
	struct sockaddr *sap = (struct sockaddr *)&nfss->mountd_address;

347 348 349
	if (nfss->flags & NFS_MOUNT_LEGACY_INTERFACE)
		return;

350 351 352
	switch (sap->sa_family) {
	case AF_INET: {
		struct sockaddr_in *sin = (struct sockaddr_in *)sap;
H
Harvey Harrison 已提交
353
		seq_printf(m, ",mountaddr=%pI4", &sin->sin_addr.s_addr);
354 355 356 357
		break;
	}
	case AF_INET6: {
		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
358
		seq_printf(m, ",mountaddr=%pI6c", &sin6->sin6_addr);
359 360 361 362
		break;
	}
	default:
		if (showdefaults)
363
			seq_puts(m, ",mountaddr=unspecified");
364 365 366 367
	}

	if (nfss->mountd_version || showdefaults)
		seq_printf(m, ",mountvers=%u", nfss->mountd_version);
368 369 370
	if ((nfss->mountd_port &&
		nfss->mountd_port != (unsigned short)NFS_UNSPEC_PORT) ||
		showdefaults)
371 372
		seq_printf(m, ",mountport=%u", nfss->mountd_port);

373
	nfs_show_mountd_netid(m, nfss, showdefaults);
374 375
}

B
Bryan Schumaker 已提交
376
#if IS_ENABLED(CONFIG_NFS_V4)
377 378 379 380 381 382 383 384 385 386 387 388 389 390
static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
				    int showdefaults)
{
	struct nfs_client *clp = nfss->nfs_client;

	seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
}
#else
static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
				    int showdefaults)
{
}
#endif

391 392 393 394 395 396 397 398 399
static void nfs_show_nfs_version(struct seq_file *m,
		unsigned int version,
		unsigned int minorversion)
{
	seq_printf(m, ",vers=%u", version);
	if (version == 4)
		seq_printf(m, ".%u", minorversion);
}

D
David Howells 已提交
400 401 402
/*
 * Describe the mount options in force on this server representation
 */
403 404
static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
				   int showdefaults)
D
David Howells 已提交
405
{
D
David Howells 已提交
406
	static const struct proc_nfs_info {
D
David Howells 已提交
407
		int flag;
D
David Howells 已提交
408 409
		const char *str;
		const char *nostr;
D
David Howells 已提交
410
	} nfs_info[] = {
411 412
		{ NFS_MOUNT_SOFT, ",soft", "" },
		{ NFS_MOUNT_SOFTERR, ",softerr", "" },
413
		{ NFS_MOUNT_SOFTREVAL, ",softreval", "" },
414
		{ NFS_MOUNT_POSIX, ",posix", "" },
D
David Howells 已提交
415 416 417 418
		{ NFS_MOUNT_NOCTO, ",nocto", "" },
		{ NFS_MOUNT_NOAC, ",noac", "" },
		{ NFS_MOUNT_NONLM, ",nolock", "" },
		{ NFS_MOUNT_NOACL, ",noacl", "" },
419
		{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
C
Chuck Lever 已提交
420 421
		{ NFS_MOUNT_UNSHARED, ",nosharecache", "" },
		{ NFS_MOUNT_NORESVPORT, ",noresvport", "" },
D
David Howells 已提交
422 423
		{ 0, NULL, NULL }
	};
D
David Howells 已提交
424
	const struct proc_nfs_info *nfs_infop;
425
	struct nfs_client *clp = nfss->nfs_client;
426
	u32 version = clp->rpc_ops->version;
427
	int local_flock, local_fcntl;
D
David Howells 已提交
428

429
	nfs_show_nfs_version(m, version, clp->cl_minorversion);
430 431
	seq_printf(m, ",rsize=%u", nfss->rsize);
	seq_printf(m, ",wsize=%u", nfss->wsize);
432 433 434
	if (nfss->bsize != 0)
		seq_printf(m, ",bsize=%u", nfss->bsize);
	seq_printf(m, ",namlen=%u", nfss->namelen);
435
	if (nfss->acregmin != NFS_DEF_ACREGMIN*HZ || showdefaults)
436
		seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ);
437
	if (nfss->acregmax != NFS_DEF_ACREGMAX*HZ || showdefaults)
438
		seq_printf(m, ",acregmax=%u", nfss->acregmax/HZ);
439
	if (nfss->acdirmin != NFS_DEF_ACDIRMIN*HZ || showdefaults)
440
		seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ);
441
	if (nfss->acdirmax != NFS_DEF_ACDIRMAX*HZ || showdefaults)
442
		seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ);
443 444
	if (!(nfss->flags & (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR)))
			seq_puts(m, ",hard");
D
David Howells 已提交
445 446 447 448 449 450
	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
		if (nfss->flags & nfs_infop->flag)
			seq_puts(m, nfs_infop->str);
		else
			seq_puts(m, nfs_infop->nostr);
	}
451
	rcu_read_lock();
452
	seq_printf(m, ",proto=%s",
453
		   rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
454
	rcu_read_unlock();
455 456
	if (clp->cl_nconnect > 0)
		seq_printf(m, ",nconnect=%u", clp->cl_nconnect);
457 458 459 460 461 462 463
	if (version == 4) {
		if (nfss->port != NFS_PORT)
			seq_printf(m, ",port=%u", nfss->port);
	} else
		if (nfss->port)
			seq_printf(m, ",port=%u", nfss->port);

464 465
	seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ);
	seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries);
466
	seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
467 468 469

	if (version != 4)
		nfs_show_mountd_options(m, nfss, showdefaults);
470 471
	else
		nfs_show_nfsv4_options(m, nfss, showdefaults);
472

473
	if (nfss->options & NFS_OPTION_FSCACHE)
474
		seq_puts(m, ",fsc");
475

476
	if (nfss->options & NFS_OPTION_MIGRATION)
477
		seq_puts(m, ",migration");
478

479 480
	if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) {
		if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
481
			seq_puts(m, ",lookupcache=none");
482
		else
483
			seq_puts(m, ",lookupcache=pos");
484
	}
485 486 487 488 489

	local_flock = nfss->flags & NFS_MOUNT_LOCAL_FLOCK;
	local_fcntl = nfss->flags & NFS_MOUNT_LOCAL_FCNTL;

	if (!local_flock && !local_fcntl)
490
		seq_puts(m, ",local_lock=none");
491
	else if (local_flock && local_fcntl)
492
		seq_puts(m, ",local_lock=all");
493
	else if (local_flock)
494
		seq_puts(m, ",local_lock=flock");
495
	else
496
		seq_puts(m, ",local_lock=posix");
D
David Howells 已提交
497 498 499 500 501
}

/*
 * Describe the mount options on this VFS mountpoint
 */
502
int nfs_show_options(struct seq_file *m, struct dentry *root)
D
David Howells 已提交
503
{
504
	struct nfs_server *nfss = NFS_SB(root->d_sb);
D
David Howells 已提交
505 506 507

	nfs_show_mount_options(m, nfss, 0);

508
	rcu_read_lock();
509 510 511
	seq_printf(m, ",addr=%s",
			rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient,
							RPC_DISPLAY_ADDR));
512
	rcu_read_unlock();
D
David Howells 已提交
513 514 515

	return 0;
}
B
Bryan Schumaker 已提交
516
EXPORT_SYMBOL_GPL(nfs_show_options);
517

B
Bryan Schumaker 已提交
518
#if IS_ENABLED(CONFIG_NFS_V4)
519 520 521 522 523 524 525 526 527 528
static void show_lease(struct seq_file *m, struct nfs_server *server)
{
	struct nfs_client *clp = server->nfs_client;
	unsigned long expire;

	seq_printf(m, ",lease_time=%ld", clp->cl_lease_time / HZ);
	expire = clp->cl_last_renewal + clp->cl_lease_time;
	seq_printf(m, ",lease_expired=%ld",
		   time_after(expire, jiffies) ?  0 : (jiffies - expire) / HZ);
}
J
J. Bruce Fields 已提交
529
#ifdef CONFIG_NFS_V4_1
530
static void show_sessions(struct seq_file *m, struct nfs_server *server)
J
J. Bruce Fields 已提交
531 532
{
	if (nfs4_has_session(server->nfs_client))
533
		seq_puts(m, ",sessions");
J
J. Bruce Fields 已提交
534 535
}
#else
536 537
static void show_sessions(struct seq_file *m, struct nfs_server *server) {}
#endif
J
J. Bruce Fields 已提交
538 539 540
#endif

#ifdef CONFIG_NFS_V4_1
541
static void show_pnfs(struct seq_file *m, struct nfs_server *server)
J
J. Bruce Fields 已提交
542 543 544 545 546 547 548
{
	seq_printf(m, ",pnfs=");
	if (server->pnfs_curr_ld)
		seq_printf(m, "%s", server->pnfs_curr_ld->name);
	else
		seq_printf(m, "not configured");
}
549 550 551

static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
{
552 553
	if (nfss->nfs_client && nfss->nfs_client->cl_implid) {
		struct nfs41_impl_id *impl_id = nfss->nfs_client->cl_implid;
554 555 556 557 558 559
		seq_printf(m, "\n\timpl_id:\tname='%s',domain='%s',"
			   "date='%llu,%u'",
			   impl_id->name, impl_id->domain,
			   impl_id->date.seconds, impl_id->date.nseconds);
	}
}
560
#else
B
Bryan Schumaker 已提交
561
#if IS_ENABLED(CONFIG_NFS_V4)
562 563 564
static void show_pnfs(struct seq_file *m, struct nfs_server *server)
{
}
565
#endif
566 567 568
static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss)
{
}
569
#endif
D
David Howells 已提交
570

571
int nfs_show_devname(struct seq_file *m, struct dentry *root)
572 573 574 575 576 577
{
	char *page = (char *) __get_free_page(GFP_KERNEL);
	char *devname, *dummy;
	int err = 0;
	if (!page)
		return -ENOMEM;
578
	devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
579 580 581 582 583 584 585
	if (IS_ERR(devname))
		err = PTR_ERR(devname);
	else
		seq_escape(m, devname, " \t\n\\");
	free_page((unsigned long)page);
	return err;
}
B
Bryan Schumaker 已提交
586
EXPORT_SYMBOL_GPL(nfs_show_devname);
587

588
int nfs_show_path(struct seq_file *m, struct dentry *dentry)
589 590 591 592
{
	seq_puts(m, "/");
	return 0;
}
B
Bryan Schumaker 已提交
593
EXPORT_SYMBOL_GPL(nfs_show_path);
594

D
David Howells 已提交
595 596 597
/*
 * Present statistical information for this VFS mountpoint
 */
598
int nfs_show_stats(struct seq_file *m, struct dentry *root)
D
David Howells 已提交
599 600
{
	int i, cpu;
601
	struct nfs_server *nfss = NFS_SB(root->d_sb);
D
David Howells 已提交
602 603 604 605 606 607 608 609
	struct rpc_auth *auth = nfss->client->cl_auth;
	struct nfs_iostats totals = { };

	seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);

	/*
	 * Display all mount option settings
	 */
610
	seq_puts(m, "\n\topts:\t");
611
	seq_puts(m, sb_rdonly(root->d_sb) ? "ro" : "rw");
612 613 614
	seq_puts(m, root->d_sb->s_flags & SB_SYNCHRONOUS ? ",sync" : "");
	seq_puts(m, root->d_sb->s_flags & SB_NOATIME ? ",noatime" : "");
	seq_puts(m, root->d_sb->s_flags & SB_NODIRATIME ? ",nodiratime" : "");
D
David Howells 已提交
615 616 617 618
	nfs_show_mount_options(m, nfss, 1);

	seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);

619
	show_implementation_id(m, nfss);
620

621
	seq_puts(m, "\n\tcaps:\t");
D
David Howells 已提交
622
	seq_printf(m, "caps=0x%x", nfss->caps);
623 624 625 626
	seq_printf(m, ",wtmult=%u", nfss->wtmult);
	seq_printf(m, ",dtsize=%u", nfss->dtsize);
	seq_printf(m, ",bsize=%u", nfss->bsize);
	seq_printf(m, ",namlen=%u", nfss->namelen);
D
David Howells 已提交
627

B
Bryan Schumaker 已提交
628
#if IS_ENABLED(CONFIG_NFS_V4)
629
	if (nfss->nfs_client->rpc_ops->version == 4) {
630
		seq_puts(m, "\n\tnfsv4:\t");
D
David Howells 已提交
631 632
		seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
		seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
633
		seq_printf(m, ",bm2=0x%x", nfss->attr_bitmask[2]);
D
David Howells 已提交
634
		seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
J
J. Bruce Fields 已提交
635 636
		show_sessions(m, nfss);
		show_pnfs(m, nfss);
637
		show_lease(m, nfss);
D
David Howells 已提交
638 639 640 641 642 643
	}
#endif

	/*
	 * Display security flavor in effect for this mount
	 */
644
	seq_printf(m, "\n\tsec:\tflavor=%u", auth->au_ops->au_flavor);
D
David Howells 已提交
645
	if (auth->au_flavor)
646
		seq_printf(m, ",pseudoflavor=%u", auth->au_flavor);
D
David Howells 已提交
647 648 649 650 651 652 653 654 655 656 657 658 659 660

	/*
	 * Display superblock I/O counters
	 */
	for_each_possible_cpu(cpu) {
		struct nfs_iostats *stats;

		preempt_disable();
		stats = per_cpu_ptr(nfss->io_stats, cpu);

		for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
			totals.events[i] += stats->events[i];
		for (i = 0; i < __NFSIOS_BYTESMAX; i++)
			totals.bytes[i] += stats->bytes[i];
661 662 663 664
#ifdef CONFIG_NFS_FSCACHE
		for (i = 0; i < __NFSIOS_FSCACHEMAX; i++)
			totals.fscache[i] += stats->fscache[i];
#endif
D
David Howells 已提交
665 666 667 668

		preempt_enable();
	}

669
	seq_puts(m, "\n\tevents:\t");
D
David Howells 已提交
670 671
	for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
		seq_printf(m, "%lu ", totals.events[i]);
672
	seq_puts(m, "\n\tbytes:\t");
D
David Howells 已提交
673 674
	for (i = 0; i < __NFSIOS_BYTESMAX; i++)
		seq_printf(m, "%Lu ", totals.bytes[i]);
675 676
#ifdef CONFIG_NFS_FSCACHE
	if (nfss->options & NFS_OPTION_FSCACHE) {
677
		seq_puts(m, "\n\tfsc:\t");
678
		for (i = 0; i < __NFSIOS_FSCACHEMAX; i++)
679
			seq_printf(m, "%Lu ", totals.fscache[i]);
680 681
	}
#endif
682
	seq_putc(m, '\n');
D
David Howells 已提交
683

684
	rpc_clnt_show_stats(m, nfss->client);
D
David Howells 已提交
685 686 687

	return 0;
}
B
Bryan Schumaker 已提交
688
EXPORT_SYMBOL_GPL(nfs_show_stats);
D
David Howells 已提交
689 690 691

/*
 * Begin unmount by attempting to remove all automounted mountpoints we added
692
 * in response to xdev traversals and referrals
D
David Howells 已提交
693
 */
694
void nfs_umount_begin(struct super_block *sb)
D
David Howells 已提交
695
{
696
	struct nfs_server *server;
T
Trond Myklebust 已提交
697 698
	struct rpc_clnt *rpc;

699
	server = NFS_SB(sb);
T
Trond Myklebust 已提交
700 701 702 703 704 705 706
	/* -EIO all pending I/O */
	rpc = server->client_acl;
	if (!IS_ERR(rpc))
		rpc_killall_tasks(rpc);
	rpc = server->client;
	if (!IS_ERR(rpc))
		rpc_killall_tasks(rpc);
D
David Howells 已提交
707
}
B
Bryan Schumaker 已提交
708
EXPORT_SYMBOL_GPL(nfs_umount_begin);
D
David Howells 已提交
709

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
/*
 * Return true if 'match' is in auth_info or auth_info is empty.
 * Return false otherwise.
 */
bool nfs_auth_info_match(const struct nfs_auth_info *auth_info,
			 rpc_authflavor_t match)
{
	int i;

	if (!auth_info->flavor_len)
		return true;

	for (i = 0; i < auth_info->flavor_len; i++) {
		if (auth_info->flavors[i] == match)
			return true;
	}
	return false;
}
EXPORT_SYMBOL_GPL(nfs_auth_info_match);

730
/*
731 732
 * Ensure that a specified authtype in ctx->auth_info is supported by
 * the server. Returns 0 and sets ctx->selected_flavor if it's ok, and
733
 * -EACCES if not.
734
 */
735
static int nfs_verify_authflavors(struct nfs_fs_context *ctx,
736 737
				  rpc_authflavor_t *server_authlist,
				  unsigned int count)
738
{
739
	rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR;
C
Chuck Lever 已提交
740
	bool found_auth_null = false;
741
	unsigned int i;
742

743 744 745 746 747 748
	/*
	 * If the sec= mount option is used, the specified flavor or AUTH_NULL
	 * must be in the list returned by the server.
	 *
	 * AUTH_NULL has a special meaning when it's in the server list - it
	 * means that the server will ignore the rpc creds, so any flavor
749
	 * can be used but still use the sec= that was specified.
C
Chuck Lever 已提交
750 751 752 753
	 *
	 * Note also that the MNT procedure in MNTv1 does not return a list
	 * of supported security flavors. In this case, nfs_mount() fabricates
	 * a security flavor list containing just AUTH_NULL.
754
	 */
755
	for (i = 0; i < count; i++) {
756 757
		flavor = server_authlist[i];

758
		if (nfs_auth_info_match(&ctx->auth_info, flavor))
759
			goto out;
760 761

		if (flavor == RPC_AUTH_NULL)
C
Chuck Lever 已提交
762
			found_auth_null = true;
763 764
	}

C
Chuck Lever 已提交
765
	if (found_auth_null) {
766
		flavor = ctx->auth_info.flavors[0];
767
		goto out;
768
	}
769

770 771
	dfprintk(MOUNT,
		 "NFS: specified auth flavors not supported by server\n");
772
	return -EACCES;
773

774
out:
775 776
	ctx->selected_flavor = flavor;
	dfprintk(MOUNT, "NFS: using auth flavor %u\n", ctx->selected_flavor);
777
	return 0;
778 779
}

780 781 782 783
/*
 * Use the remote server's MOUNT service to request the NFS file handle
 * corresponding to the provided path.
 */
784
static int nfs_request_mount(struct fs_context *fc,
785 786 787
			     struct nfs_fh *root_fh,
			     rpc_authflavor_t *server_authlist,
			     unsigned int *server_authlist_len)
788
{
789
	struct nfs_fs_context *ctx = nfs_fc2context(fc);
790 791
	struct nfs_mount_request request = {
		.sap		= (struct sockaddr *)
792 793 794
						&ctx->mount_server.address,
		.dirpath	= ctx->nfs_server.export_path,
		.protocol	= ctx->mount_server.protocol,
795
		.fh		= root_fh,
796
		.noresvport	= ctx->flags & NFS_MOUNT_NORESVPORT,
797
		.auth_flav_len	= server_authlist_len,
798
		.auth_flavs	= server_authlist,
799
		.net		= fc->net_ns,
800
	};
801
	int status;
802

803 804
	if (ctx->mount_server.version == 0) {
		switch (ctx->version) {
805
			default:
806
				ctx->mount_server.version = NFS_MNT3_VERSION;
807 808
				break;
			case 2:
809
				ctx->mount_server.version = NFS_MNT_VERSION;
810
		}
811
	}
812
	request.version = ctx->mount_server.version;
813

814 815
	if (ctx->mount_server.hostname)
		request.hostname = ctx->mount_server.hostname;
816
	else
817
		request.hostname = ctx->nfs_server.hostname;
818

819 820 821
	/*
	 * Construct the mount server's address.
	 */
822 823 824 825
	if (ctx->mount_server.address.sa_family == AF_UNSPEC) {
		memcpy(request.sap, &ctx->nfs_server.address,
		       ctx->nfs_server.addrlen);
		ctx->mount_server.addrlen = ctx->nfs_server.addrlen;
826
	}
827 828
	request.salen = ctx->mount_server.addrlen;
	nfs_set_port(request.sap, &ctx->mount_server.port, 0);
829 830 831 832 833

	/*
	 * Now ask the mount server to map our export path
	 * to a file handle.
	 */
834
	status = nfs_mount(&request);
835 836 837 838 839
	if (status != 0) {
		dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
				request.hostname, status);
		return status;
	}
840

841
	return 0;
842 843
}

844
static struct nfs_server *nfs_try_mount_request(struct fs_context *fc)
845
{
846
	struct nfs_fs_context *ctx = nfs_fc2context(fc);
847
	int status;
848 849 850 851
	unsigned int i;
	bool tried_auth_unix = false;
	bool auth_null_in_list = false;
	struct nfs_server *server = ERR_PTR(-EACCES);
852 853
	rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS];
	unsigned int authlist_len = ARRAY_SIZE(authlist);
854

855
	status = nfs_request_mount(fc, ctx->mntfh, authlist, &authlist_len);
856 857 858
	if (status)
		return ERR_PTR(status);

859 860 861 862
	/*
	 * Was a sec= authflavor specified in the options? First, verify
	 * whether the server supports it, and then just try to use it if so.
	 */
863 864
	if (ctx->auth_info.flavor_len > 0) {
		status = nfs_verify_authflavors(ctx, authlist, authlist_len);
865
		dfprintk(MOUNT, "NFS: using auth flavor %u\n",
866
			 ctx->selected_flavor);
867 868
		if (status)
			return ERR_PTR(status);
869
		return ctx->nfs_mod->rpc_ops->create_server(fc);
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
	}

	/*
	 * No sec= option was provided. RFC 2623, section 2.7 suggests we
	 * SHOULD prefer the flavor listed first. However, some servers list
	 * AUTH_NULL first. Avoid ever choosing AUTH_NULL.
	 */
	for (i = 0; i < authlist_len; ++i) {
		rpc_authflavor_t flavor;
		struct rpcsec_gss_info info;

		flavor = authlist[i];
		switch (flavor) {
		case RPC_AUTH_UNIX:
			tried_auth_unix = true;
			break;
		case RPC_AUTH_NULL:
			auth_null_in_list = true;
			continue;
		default:
			if (rpcauth_get_gssinfo(flavor, &info) != 0)
				continue;
			/* Fallthrough */
		}
		dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor);
895
		ctx->selected_flavor = flavor;
896
		server = ctx->nfs_mod->rpc_ops->create_server(fc);
897 898 899 900 901 902 903 904 905 906 907 908 909 910
		if (!IS_ERR(server))
			return server;
	}

	/*
	 * Nothing we tried so far worked. At this point, give up if we've
	 * already tried AUTH_UNIX or if the server's list doesn't contain
	 * AUTH_NULL
	 */
	if (tried_auth_unix || !auth_null_in_list)
		return server;

	/* Last chance! Try AUTH_UNIX */
	dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX);
911
	ctx->selected_flavor = RPC_AUTH_UNIX;
912
	return ctx->nfs_mod->rpc_ops->create_server(fc);
913 914
}

D
David Howells 已提交
915
int nfs_try_get_tree(struct fs_context *fc)
916
{
D
David Howells 已提交
917 918 919
	struct nfs_fs_context *ctx = nfs_fc2context(fc);

	if (ctx->need_mount)
920
		ctx->server = nfs_try_mount_request(fc);
921
	else
922
		ctx->server = ctx->nfs_mod->rpc_ops->create_server(fc);
923

D
David Howells 已提交
924
	return nfs_get_tree_common(fc);
925
}
D
David Howells 已提交
926 927
EXPORT_SYMBOL_GPL(nfs_try_get_tree);

928

929
#define NFS_REMOUNT_CMP_FLAGMASK ~(NFS_MOUNT_INTR \
930 931 932 933 934 935 936 937 938
		| NFS_MOUNT_SECURE \
		| NFS_MOUNT_TCP \
		| NFS_MOUNT_VER3 \
		| NFS_MOUNT_KERBEROS \
		| NFS_MOUNT_NONLM \
		| NFS_MOUNT_BROKEN_SUID \
		| NFS_MOUNT_STRICTLOCK \
		| NFS_MOUNT_LEGACY_INTERFACE)

939 940 941
#define NFS_MOUNT_CMP_FLAGMASK (NFS_REMOUNT_CMP_FLAGMASK & \
		~(NFS_MOUNT_UNSHARED | NFS_MOUNT_NORESVPORT))

942 943
static int
nfs_compare_remount_data(struct nfs_server *nfss,
944
			 struct nfs_fs_context *ctx)
945
{
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
	if ((ctx->flags ^ nfss->flags) & NFS_REMOUNT_CMP_FLAGMASK ||
	    ctx->rsize != nfss->rsize ||
	    ctx->wsize != nfss->wsize ||
	    ctx->version != nfss->nfs_client->rpc_ops->version ||
	    ctx->minorversion != nfss->nfs_client->cl_minorversion ||
	    ctx->retrans != nfss->client->cl_timeout->to_retries ||
	    !nfs_auth_info_match(&ctx->auth_info, nfss->client->cl_auth->au_flavor) ||
	    ctx->acregmin != nfss->acregmin / HZ ||
	    ctx->acregmax != nfss->acregmax / HZ ||
	    ctx->acdirmin != nfss->acdirmin / HZ ||
	    ctx->acdirmax != nfss->acdirmax / HZ ||
	    ctx->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
	    (ctx->options & NFS_OPTION_FSCACHE) != (nfss->options & NFS_OPTION_FSCACHE) ||
	    ctx->nfs_server.port != nfss->port ||
	    ctx->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
	    !rpc_cmp_addr((struct sockaddr *)&ctx->nfs_server.address,
S
Stefan Richter 已提交
962
			  (struct sockaddr *)&nfss->nfs_client->cl_addr))
963 964 965 966 967
		return -EINVAL;

	return 0;
}

D
David Howells 已提交
968
int nfs_reconfigure(struct fs_context *fc)
969
{
D
David Howells 已提交
970 971
	struct nfs_fs_context *ctx = nfs_fc2context(fc);
	struct super_block *sb = fc->root->d_sb;
972 973
	struct nfs_server *nfss = sb->s_fs_info;

974 975
	sync_filesystem(sb);

976 977 978 979 980 981
	/*
	 * Userspace mount programs that send binary options generally send
	 * them populated with default values. We have no way to know which
	 * ones were explicitly specified. Fall back to legacy behavior and
	 * just return success.
	 */
D
David Howells 已提交
982
	if (ctx->skip_reconfig_option_check)
983 984
		return 0;

985 986
	/*
	 * noac is a special case. It implies -o sync, but that's not
D
David Howells 已提交
987
	 * necessarily reflected in the mtab options. reconfigure_super
988
	 * will clear SB_SYNCHRONOUS if -o sync wasn't specified in the
989 990
	 * remount options, so we have to explicitly reset it.
	 */
D
David Howells 已提交
991 992 993 994
	if (ctx->flags & NFS_MOUNT_NOAC) {
		fc->sb_flags |= SB_SYNCHRONOUS;
		fc->sb_flags_mask |= SB_SYNCHRONOUS;
	}
995

996
	/* compare new mount options with old ones */
D
David Howells 已提交
997
	return nfs_compare_remount_data(nfss, ctx);
998
}
D
David Howells 已提交
999
EXPORT_SYMBOL_GPL(nfs_reconfigure);
1000

D
David Howells 已提交
1001
/*
1002
 * Finish setting up an NFS superblock
D
David Howells 已提交
1003
 */
1004
static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
D
David Howells 已提交
1005 1006
{
	struct nfs_server *server = NFS_SB(sb);
1007

1008 1009
	sb->s_blocksize_bits = 0;
	sb->s_blocksize = 0;
1010 1011
	sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr;
	sb->s_op = server->nfs_client->cl_nfs_mod->sops;
1012 1013
	if (ctx && ctx->bsize)
		sb->s_blocksize = nfs_block_size(ctx->bsize, &sb->s_blocksize_bits);
D
David Howells 已提交
1014

1015
	if (server->nfs_client->rpc_ops->version != 2) {
1016 1017 1018
		/* The VFS shouldn't apply the umask to mode bits. We will do
		 * so ourselves when necessary.
		 */
1019
		sb->s_flags |= SB_POSIXACL;
1020
		sb->s_time_gran = 1;
P
Peng Tao 已提交
1021
		sb->s_export_op = &nfs_export_ops;
1022 1023 1024 1025 1026 1027 1028 1029 1030
	} else
		sb->s_time_gran = 1000;

	if (server->nfs_client->rpc_ops->version != 4) {
		sb->s_time_min = 0;
		sb->s_time_max = U32_MAX;
	} else {
		sb->s_time_min = S64_MIN;
		sb->s_time_max = S64_MAX;
1031
	}
1032

1033
	sb->s_magic = NFS_SUPER_MAGIC;
D
David Howells 已提交
1034

1035 1036 1037
	/* We probably want something more informative here */
	snprintf(sb->s_id, sizeof(sb->s_id),
		 "%u:%u", MAJOR(sb->s_dev), MINOR(sb->s_dev));
1038

1039 1040 1041
	if (sb->s_blocksize == 0)
		sb->s_blocksize = nfs_block_bits(server->wsize,
						 &sb->s_blocksize_bits);
D
David Howells 已提交
1042

1043
	nfs_super_set_maxbytes(sb, server->maxfilesize);
D
David Howells 已提交
1044 1045
}

1046 1047
static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b,
				     const struct fs_context *fc)
1048 1049 1050 1051 1052
{
	const struct nfs_server *a = s->s_fs_info;
	const struct rpc_clnt *clnt_a = a->client;
	const struct rpc_clnt *clnt_b = b->client;

1053
	if ((s->s_flags & NFS_SB_MASK) != (fc->sb_flags & NFS_SB_MASK))
1054 1055 1056
		goto Ebusy;
	if (a->nfs_client != b->nfs_client)
		goto Ebusy;
1057
	if ((a->flags ^ b->flags) & NFS_MOUNT_CMP_FLAGMASK)
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
		goto Ebusy;
	if (a->wsize != b->wsize)
		goto Ebusy;
	if (a->rsize != b->rsize)
		goto Ebusy;
	if (a->acregmin != b->acregmin)
		goto Ebusy;
	if (a->acregmax != b->acregmax)
		goto Ebusy;
	if (a->acdirmin != b->acdirmin)
		goto Ebusy;
	if (a->acdirmax != b->acdirmax)
		goto Ebusy;
1071
	if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
1072
		goto Ebusy;
T
Trond Myklebust 已提交
1073
	return 1;
1074
Ebusy:
T
Trond Myklebust 已提交
1075 1076 1077
	return 0;
}

D
David Howells 已提交
1078
static int nfs_set_super(struct super_block *s, struct fs_context *fc)
T
Trond Myklebust 已提交
1079
{
D
David Howells 已提交
1080
	struct nfs_server *server = fc->s_fs_info;
T
Trond Myklebust 已提交
1081 1082
	int ret;

A
Al Viro 已提交
1083
	s->s_d_op = server->nfs_client->rpc_ops->dentry_ops;
T
Trond Myklebust 已提交
1084 1085 1086 1087 1088 1089
	ret = set_anon_super(s, server);
	if (ret == 0)
		server->s_dev = s->s_dev;
	return ret;
}

1090 1091 1092 1093
static int nfs_compare_super_address(struct nfs_server *server1,
				     struct nfs_server *server2)
{
	struct sockaddr *sap1, *sap2;
1094 1095 1096 1097 1098
	struct rpc_xprt *xprt1 = server1->client->cl_xprt;
	struct rpc_xprt *xprt2 = server2->client->cl_xprt;

	if (!net_eq(xprt1->xprt_net, xprt2->xprt_net))
		return 0;
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131

	sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr;
	sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr;

	if (sap1->sa_family != sap2->sa_family)
		return 0;

	switch (sap1->sa_family) {
	case AF_INET: {
		struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1;
		struct sockaddr_in *sin2 = (struct sockaddr_in *)sap2;
		if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
			return 0;
		if (sin1->sin_port != sin2->sin_port)
			return 0;
		break;
	}
	case AF_INET6: {
		struct sockaddr_in6 *sin1 = (struct sockaddr_in6 *)sap1;
		struct sockaddr_in6 *sin2 = (struct sockaddr_in6 *)sap2;
		if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
			return 0;
		if (sin1->sin6_port != sin2->sin6_port)
			return 0;
		break;
	}
	default:
		return 0;
	}

	return 1;
}

1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
static int nfs_compare_userns(const struct nfs_server *old,
		const struct nfs_server *new)
{
	const struct user_namespace *oldns = &init_user_ns;
	const struct user_namespace *newns = &init_user_ns;

	if (old->client && old->client->cl_cred)
		oldns = old->client->cl_cred->user_ns;
	if (new->client && new->client->cl_cred)
		newns = new->client->cl_cred->user_ns;
	if (oldns != newns)
		return 0;
	return 1;
}

D
David Howells 已提交
1147
static int nfs_compare_super(struct super_block *sb, struct fs_context *fc)
T
Trond Myklebust 已提交
1148
{
D
David Howells 已提交
1149
	struct nfs_server *server = fc->s_fs_info, *old = NFS_SB(sb);
T
Trond Myklebust 已提交
1150

1151
	if (!nfs_compare_super_address(old, server))
T
Trond Myklebust 已提交
1152 1153 1154 1155 1156 1157
		return 0;
	/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
	if (old->flags & NFS_MOUNT_UNSHARED)
		return 0;
	if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
		return 0;
1158 1159
	if (!nfs_compare_userns(old, server))
		return 0;
1160
	return nfs_compare_mount_options(sb, server, fc);
1161 1162
}

1163
#ifdef CONFIG_NFS_FSCACHE
1164
static void nfs_get_cache_cookie(struct super_block *sb,
D
David Howells 已提交
1165
				 struct nfs_fs_context *ctx)
1166
{
1167
	struct nfs_server *nfss = NFS_SB(sb);
1168 1169 1170
	char *uniq = NULL;
	int ulen = 0;

1171 1172 1173
	nfss->fscache_key = NULL;
	nfss->fscache = NULL;

D
David Howells 已提交
1174 1175 1176 1177 1178
	if (!ctx)
		return;

	if (ctx->clone_data.sb) {
		struct nfs_server *mnt_s = NFS_SB(ctx->clone_data.sb);
1179 1180
		if (!(mnt_s->options & NFS_OPTION_FSCACHE))
			return;
1181 1182 1183
		if (mnt_s->fscache_key) {
			uniq = mnt_s->fscache_key->key.uniquifier;
			ulen = mnt_s->fscache_key->key.uniq_len;
Y
YueHaibing 已提交
1184
		}
D
David Howells 已提交
1185 1186 1187 1188 1189 1190 1191
	} else {
		if (!(ctx->options & NFS_OPTION_FSCACHE))
			return;
		if (ctx->fscache_uniq) {
			uniq = ctx->fscache_uniq;
			ulen = strlen(ctx->fscache_uniq);
		}
1192
		return;
D
David Howells 已提交
1193
	}
1194 1195 1196

	nfs_fscache_get_super_cookie(sb, uniq, ulen);
}
1197 1198
#else
static void nfs_get_cache_cookie(struct super_block *sb,
D
David Howells 已提交
1199
				 struct nfs_fs_context *ctx)
1200 1201 1202
{
}
#endif
1203

1204 1205 1206 1207 1208 1209 1210
static void nfs_set_readahead(struct backing_dev_info *bdi,
			      unsigned long iomax_pages)
{
	bdi->ra_pages = VM_READAHEAD_PAGES;
	bdi->io_pages = iomax_pages;
}

D
David Howells 已提交
1211
int nfs_get_tree_common(struct fs_context *fc)
D
David Howells 已提交
1212
{
D
David Howells 已提交
1213
	struct nfs_fs_context *ctx = nfs_fc2context(fc);
D
David Howells 已提交
1214
	struct super_block *s;
D
David Howells 已提交
1215
	int (*compare_super)(struct super_block *, struct fs_context *) = nfs_compare_super;
1216
	struct nfs_server *server = ctx->server;
1217
	int error;
1218

1219
	ctx->server = NULL;
1220
	if (IS_ERR(server))
D
David Howells 已提交
1221
		return PTR_ERR(server);
1222

1223 1224 1225
	if (server->flags & NFS_MOUNT_UNSHARED)
		compare_super = NULL;

1226 1227
	/* -o noac implies -o sync */
	if (server->flags & NFS_MOUNT_NOAC)
D
David Howells 已提交
1228 1229 1230 1231 1232
		fc->sb_flags |= SB_SYNCHRONOUS;

	if (ctx->clone_data.sb)
		if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS)
			fc->sb_flags |= SB_SYNCHRONOUS;
1233

D
David Howells 已提交
1234 1235
	if (server->caps & NFS_CAP_SECURITY_LABEL)
		fc->lsm_flags |= SECURITY_LSM_NATIVE_LABELS;
1236

1237
	/* Get a superblock - note that we may end up sharing one that already exists */
D
David Howells 已提交
1238 1239 1240
	fc->s_fs_info = server;
	s = sget_fc(fc, compare_super, nfs_set_super);
	fc->s_fs_info = NULL;
1241
	if (IS_ERR(s)) {
D
David Howells 已提交
1242
		error = PTR_ERR(s);
1243
		nfs_errorf(fc, "NFS: Couldn't get superblock");
1244
		goto out_err_nosb;
1245 1246
	}

1247 1248 1249
	if (s->s_fs_info != server) {
		nfs_free_server(server);
		server = NULL;
1250
	} else {
1251 1252
		error = super_setup_bdi_name(s, "%u:%u", MAJOR(server->s_dev),
					     MINOR(server->s_dev));
D
David Howells 已提交
1253
		if (error)
1254
			goto error_splat_super;
1255
		nfs_set_readahead(s->s_bdi, server->rpages);
1256
		server->super = s;
1257
	}
D
David Howells 已提交
1258

1259
	if (!s->s_root) {
1260
		unsigned bsize = ctx->clone_data.inherited_bsize;
1261
		/* initial superblock/root creation */
1262
		nfs_fill_super(s, ctx);
1263 1264 1265 1266
		if (bsize) {
			s->s_blocksize_bits = bsize;
			s->s_blocksize = 1U << bsize;
		}
D
David Howells 已提交
1267
		nfs_get_cache_cookie(s, ctx);
1268
	}
D
David Howells 已提交
1269

1270 1271
	error = nfs_get_root(s, fc);
	if (error < 0) {
1272
		nfs_errorf(fc, "NFS: Couldn't get root dentry");
1273
		goto error_splat_super;
D
David Howells 已提交
1274
	}
A
Al Viro 已提交
1275

1276
	s->s_flags |= SB_ACTIVE;
D
David Howells 已提交
1277
	error = 0;
1278 1279

out:
D
David Howells 已提交
1280
	return error;
1281

1282 1283
out_err_nosb:
	nfs_free_server(server);
1284
	goto out;
1285
error_splat_super:
1286
	deactivate_locked_super(s);
1287
	goto out;
D
David Howells 已提交
1288 1289
}

1290 1291 1292
/*
 * Destroy an NFS2/3 superblock
 */
1293
void nfs_kill_super(struct super_block *s)
D
David Howells 已提交
1294 1295
{
	struct nfs_server *server = NFS_SB(s);
1296 1297 1298
	dev_t dev = s->s_dev;

	generic_shutdown_super(s);
D
David Howells 已提交
1299

1300
	nfs_fscache_release_super_cookie(s);
1301

1302
	nfs_free_server(server);
1303
	free_anon_bdev(dev);
D
David Howells 已提交
1304
}
B
Bryan Schumaker 已提交
1305
EXPORT_SYMBOL_GPL(nfs_kill_super);
D
David Howells 已提交
1306

B
Bryan Schumaker 已提交
1307
#if IS_ENABLED(CONFIG_NFS_V4)
1308

1309 1310 1311 1312 1313
/*
 * NFS v4 module parameters need to stay in the
 * NFS client for backwards compatibility
 */
unsigned int nfs_callback_set_tcpport;
1314
unsigned short nfs_callback_nr_threads;
1315 1316 1317 1318 1319
/* Default cache timeout is 10 minutes */
unsigned int nfs_idmap_cache_timeout = 600;
/* Turn off NFSv4 uid/gid mapping when using AUTH_SYS */
bool nfs4_disable_idmapping = true;
unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE;
1320
unsigned short max_session_cb_slots = NFS4_DEF_CB_SLOT_TABLE_SIZE;
1321
unsigned short send_implementation_id = 1;
1322
char nfs4_client_id_uniquifier[NFS4_CLIENT_ID_UNIQ_LEN] = "";
1323
bool recover_lost_locks = false;
1324

1325
EXPORT_SYMBOL_GPL(nfs_callback_nr_threads);
B
Bryan Schumaker 已提交
1326 1327 1328 1329
EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport);
EXPORT_SYMBOL_GPL(nfs_idmap_cache_timeout);
EXPORT_SYMBOL_GPL(nfs4_disable_idmapping);
EXPORT_SYMBOL_GPL(max_session_slots);
1330
EXPORT_SYMBOL_GPL(max_session_cb_slots);
B
Bryan Schumaker 已提交
1331
EXPORT_SYMBOL_GPL(send_implementation_id);
1332
EXPORT_SYMBOL_GPL(nfs4_client_id_uniquifier);
1333
EXPORT_SYMBOL_GPL(recover_lost_locks);
B
Bryan Schumaker 已提交
1334

1335 1336 1337 1338 1339 1340 1341 1342 1343
#define NFS_CALLBACK_MAXPORTNR (65535U)

static int param_set_portnr(const char *val, const struct kernel_param *kp)
{
	unsigned long num;
	int ret;

	if (!val)
		return -EINVAL;
1344
	ret = kstrtoul(val, 0, &num);
1345
	if (ret || num > NFS_CALLBACK_MAXPORTNR)
1346 1347 1348 1349
		return -EINVAL;
	*((unsigned int *)kp->arg) = num;
	return 0;
}
1350
static const struct kernel_param_ops param_ops_portnr = {
1351 1352 1353 1354 1355 1356
	.set = param_set_portnr,
	.get = param_get_uint,
};
#define param_check_portnr(name, p) __param_check(name, p, unsigned int);

module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
1357 1358 1359
module_param_named(callback_nr_threads, nfs_callback_nr_threads, ushort, 0644);
MODULE_PARM_DESC(callback_nr_threads, "Number of threads that will be "
		"assigned to the NFSv4 callback channels.");
1360 1361
module_param(nfs_idmap_cache_timeout, int, 0644);
module_param(nfs4_disable_idmapping, bool, 0644);
1362 1363
module_param_string(nfs4_unique_id, nfs4_client_id_uniquifier,
			NFS4_CLIENT_ID_UNIQ_LEN, 0600);
1364 1365 1366 1367 1368
MODULE_PARM_DESC(nfs4_disable_idmapping,
		"Turn off NFSv4 idmapping when using 'sec=sys'");
module_param(max_session_slots, ushort, 0644);
MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 "
		"requests the client will negotiate");
1369
module_param(max_session_cb_slots, ushort, 0644);
1370
MODULE_PARM_DESC(max_session_cb_slots, "Maximum number of parallel NFSv4.1 "
1371
		"callbacks the client will process for a given server");
1372 1373 1374
module_param(send_implementation_id, ushort, 0644);
MODULE_PARM_DESC(send_implementation_id,
		"Send implementation ID with NFSv4.1 exchange_id");
1375
MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string");
1376

1377 1378 1379 1380 1381 1382
module_param(recover_lost_locks, bool, 0644);
MODULE_PARM_DESC(recover_lost_locks,
		 "If the server reports that a lock might be lost, "
		 "try to recover it risking data corruption.");


1383
#endif /* CONFIG_NFS_V4 */