All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: viro@zeniv.linux.org.uk
Cc: dhowells@redhat.com, raven@themaw.net, linux-api@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	mszeredi@redhat.com
Subject: [PATCH 16/25] nfs: Support fsinfo() [ver #13]
Date: Tue, 28 May 2019 16:13:23 +0100	[thread overview]
Message-ID: <155905640395.1662.11340611657732220291.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <155905626142.1662.18430571708534506785.stgit@warthog.procyon.org.uk>

Allow fsinfo() to retrieve information about a superblock, including the
values configured by the parameters passed at superblock creation.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/nfs/fs_context.c |  163 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nfs/internal.h   |    6 ++
 fs/nfs/nfs4super.c  |    3 +
 fs/nfs/super.c      |   77 ++++++++++++++++++++++++
 4 files changed, 248 insertions(+), 1 deletion(-)

diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index d05271b91e38..f550b0e54833 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -17,6 +17,8 @@
 #include <linux/fs.h>
 #include <linux/fs_context.h>
 #include <linux/fs_parser.h>
+#include <linux/fsinfo.h>
+#include <linux/mount.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
 #include <linux/nfs4_mount.h>
@@ -1407,3 +1409,164 @@ MODULE_ALIAS_FS("nfs4");
 MODULE_ALIAS("nfs4");
 EXPORT_SYMBOL_GPL(nfs4_fs_type);
 #endif /* CONFIG_NFS_V4 */
+
+#ifdef CONFIG_FSINFO
+/*
+ * Allow the filesystem parameters to be queried.
+ */
+int nfs_fsinfo_parameters(struct fsinfo_kparams *params, struct path *path,
+			  const struct nfs_server *server)
+{
+	const struct nfs_client *client = server->nfs_client;
+	const struct sockaddr *sap = (const struct sockaddr *)&server->mountd_address;
+	unsigned int version = client->rpc_ops->version;
+	unsigned int sf = server->flags;
+	const char *b;
+	char *e;
+	int i;
+
+	static const struct proc_nfs_info {
+		int flag;
+		const char *str;
+		const char *nostr;
+	} nfs_info[] = {
+		{ NFS_MOUNT_SOFT, "soft", "hard" },
+		{ NFS_MOUNT_POSIX, "posix", "" },
+		{ NFS_MOUNT_NOCTO, "nocto", "" },
+		{ NFS_MOUNT_NOAC, "noac", "" },
+		{ NFS_MOUNT_NONLM, "nolock", "" },
+		{ NFS_MOUNT_NOACL, "noacl", "" },
+		{ NFS_MOUNT_NORDIRPLUS, "nordirplus", "" },
+		{ NFS_MOUNT_UNSHARED, "nosharecache", "" },
+		{ NFS_MOUNT_NORESVPORT, "noresvport", "" },
+	};
+
+	rcu_read_lock();
+
+	b = params->scratch_buffer;
+	b = nfs_path(&e, path->mnt->mnt_root, params->scratch_buffer, params->buf_size, 0);
+	if (b < e)
+		fsinfo_note_param(params, "source", b);
+
+	if (version == 4)
+		fsinfo_note_paramf(params, "vers", "4.%u", client->cl_minorversion);
+	else
+		fsinfo_note_paramf(params, "vers", "%u", version);
+
+	fsinfo_note_paramf(params, "rsize", "%u", server->rsize);
+	fsinfo_note_paramf(params, "wsize", "%u", server->wsize);
+	if (server->bsize)
+		fsinfo_note_paramf(params, "bsize", "%u", server->bsize);
+	fsinfo_note_paramf(params, "namlen", "%u", server->namelen);
+
+	if (server->acregmin != NFS_DEF_ACREGMIN*HZ)
+		fsinfo_note_paramf(params, "acregmin", "%u", server->acregmin/HZ);
+	if (server->acregmax != NFS_DEF_ACREGMAX*HZ)
+		fsinfo_note_paramf(params, "acregmin", "%u", server->acregmax/HZ);
+	if (server->acdirmin != NFS_DEF_ACDIRMIN*HZ)
+		fsinfo_note_paramf(params, "acdirmin", "%u", server->acdirmin/HZ);
+	if (server->acdirmax != NFS_DEF_ACDIRMAX*HZ)
+		fsinfo_note_paramf(params, "acdirmin", "%u", server->acdirmax/HZ);
+
+	for (i = 0; i < ARRAY_SIZE(nfs_info); i++) {
+		if (sf & nfs_info[i].flag)
+			b = nfs_info[i].str;
+		else
+			b = nfs_info[i].nostr;
+		if (b[0])
+			fsinfo_note_param(params, b, NULL);
+	}
+
+	fsinfo_note_param(params, "proto",
+			  rpc_peeraddr2str(server->client, RPC_DISPLAY_NETID));
+	if (version != 4 || server->port != NFS_PORT)
+		fsinfo_note_paramf(params, "port", "%u", server->port);
+
+	fsinfo_note_paramf(params, "timeo", "%lu",
+			   10U * server->client->cl_timeout->to_initval / HZ);
+	fsinfo_note_paramf(params, "retrans", "%u",
+			  server->client->cl_timeout->to_retries);
+	fsinfo_note_param(params, "sec",
+			  nfs_pseudoflavour_to_name(server->client->cl_auth->au_flavor));
+
+	if (server->options & NFS_OPTION_FSCACHE)
+		fsinfo_note_param(params, "fsc", NULL);
+	if (server->options & NFS_OPTION_MIGRATION)
+		fsinfo_note_param(params, "migration", NULL);
+
+	if (server->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) {
+		if (server->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
+			fsinfo_note_param(params, "lookupcache", "none");
+		else
+			fsinfo_note_param(params, "lookupcache", "pos");
+	}
+
+	switch (server->flags & (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL)) {
+	case 0:				b = "none";	break;
+	case NFS_MOUNT_LOCAL_FLOCK:	b = "flock";	break;
+	case NFS_MOUNT_LOCAL_FCNTL:	b = "posix";	break;
+	default:			b = "all";	break;
+	}
+	fsinfo_note_param(params, "local_lock", b);
+
+	if (version == 4)
+		fsinfo_note_param(params, "clientaddr", client->cl_ipaddr);
+
+	if (version != 4 && !(server->flags & NFS_MOUNT_LEGACY_INTERFACE)) {
+		switch (sap->sa_family) {
+		case AF_INET: {
+			struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+			fsinfo_note_paramf(params, "mountaddr", "%pI4",
+					   &sin->sin_addr.s_addr);
+			break;
+		}
+		case AF_INET6: {
+			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+			fsinfo_note_paramf(params, "mountaddr", "%pI6c",
+					   &sin6->sin6_addr);
+			break;
+		}
+		}
+
+		if (server->mountd_port &&
+		    server->mountd_port != (unsigned short)NFS_UNSPEC_PORT)
+			fsinfo_note_paramf(params, "mountport", "%u", server->mountd_port);
+
+		switch (sap->sa_family) {
+		case AF_INET:
+			switch (server->mountd_protocol) {
+			case IPPROTO_UDP:
+				b = RPCBIND_NETID_UDP;
+				break;
+			case IPPROTO_TCP:
+				b = RPCBIND_NETID_TCP;
+				break;
+			}
+			break;
+		case AF_INET6:
+			switch (server->mountd_protocol) {
+			case IPPROTO_UDP:
+				b = RPCBIND_NETID_UDP6;
+				break;
+			case IPPROTO_TCP:
+				b = RPCBIND_NETID_TCP6;
+				break;
+			}
+			break;
+		}
+
+		if (b)
+			fsinfo_note_param(params, "mountproto", b);
+
+		if (server->mountd_version)
+			fsinfo_note_paramf(params, "mountvers", "%u",
+					   server->mountd_version);
+	}
+
+	fsinfo_note_param(params, "addr",
+			  rpc_peeraddr2str(server->nfs_client->cl_rpcclient, RPC_DISPLAY_ADDR));
+
+	rcu_read_unlock();
+	return params->usage;
+}
+#endif /* CONFIG_FSINFO */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index da088f5611f0..c218e715881d 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -244,6 +244,10 @@ extern const struct svc_version nfs4_callback_version4;
 
 /* fs_context.c */
 extern struct file_system_type nfs_fs_type;
+#ifdef CONFIG_FSINFO
+extern int nfs_fsinfo_parameters(struct fsinfo_kparams *params, struct path *path,
+				 const struct nfs_server *server);
+#endif
 
 /* pagelist.c */
 extern int __init nfs_init_nfspagecache(void);
@@ -408,6 +412,7 @@ bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
 int nfs_try_get_tree(struct fs_context *);
 int nfs_get_tree_common(struct fs_context *);
 void nfs_kill_super(struct super_block *);
+const char *nfs_pseudoflavour_to_name(rpc_authflavor_t);
 
 extern struct rpc_stat nfs_rpcstat;
 
@@ -455,6 +460,7 @@ extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
 /* super.c */
 void nfs_umount_begin(struct super_block *);
 int  nfs_statfs(struct dentry *, struct kstatfs *);
+int  nfs_fsinfo(struct path *, struct fsinfo_kparams *);
 int  nfs_show_options(struct seq_file *, struct dentry *);
 int  nfs_show_devname(struct seq_file *, struct dentry *);
 int  nfs_show_path(struct seq_file *, struct dentry *);
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 0240429ec596..22d8f2842ac1 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -31,6 +31,9 @@ static const struct super_operations nfs4_sops = {
 	.show_devname	= nfs_show_devname,
 	.show_path	= nfs_show_path,
 	.show_stats	= nfs_show_stats,
+#ifdef CONFIG_FSINFO
+	.fsinfo		= nfs_fsinfo,
+#endif
 };
 
 struct nfs_subversion nfs_v4 = {
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index c455ebeeadc9..dde6c59d0210 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -54,6 +54,7 @@
 #include <linux/parser.h>
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
+#include <linux/fsinfo.h>
 
 #include <linux/uaccess.h>
 
@@ -81,6 +82,9 @@ const struct super_operations nfs_sops = {
 	.show_devname	= nfs_show_devname,
 	.show_path	= nfs_show_path,
 	.show_stats	= nfs_show_stats,
+#ifdef CONFIG_FSINFO
+	.fsinfo		= nfs_fsinfo,
+#endif
 };
 EXPORT_SYMBOL_GPL(nfs_sops);
 
@@ -241,10 +245,81 @@ int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 }
 EXPORT_SYMBOL_GPL(nfs_statfs);
 
+#ifdef CONFIG_FSINFO
+/*
+ * Get filesystem information.
+ */
+int nfs_fsinfo(struct path *path, struct fsinfo_kparams *params)
+{
+	struct fsinfo_server_address *addr;
+	struct fsinfo_capabilities *caps;
+	struct nfs_server *server = NFS_SB(path->dentry->d_sb);
+	struct nfs_client *client = server->nfs_client;
+	struct rpc_clnt *clnt;
+	struct rpc_xprt *xprt;
+	const char *str;
+	unsigned int version = client->rpc_ops->version;
+
+	switch (params->request) {
+	case FSINFO_ATTR_CAPABILITIES:
+		caps = params->buffer;
+		fsinfo_set_cap(caps, FSINFO_CAP_IS_NETWORK_FS);
+		fsinfo_set_cap(caps, FSINFO_CAP_AUTOMOUNTS);
+		fsinfo_set_cap(caps, FSINFO_CAP_ADV_LOCKS);
+		fsinfo_set_cap(caps, FSINFO_CAP_UIDS);
+		fsinfo_set_cap(caps, FSINFO_CAP_GIDS);
+		fsinfo_set_cap(caps, FSINFO_CAP_O_SYNC);
+		fsinfo_set_cap(caps, FSINFO_CAP_O_DIRECT);
+		fsinfo_set_cap(caps, FSINFO_CAP_SYMLINKS);
+		fsinfo_set_cap(caps, FSINFO_CAP_HARD_LINKS);
+		fsinfo_set_cap(caps, FSINFO_CAP_DEVICE_FILES);
+		fsinfo_set_cap(caps, FSINFO_CAP_UNIX_SPECIALS);
+		fsinfo_set_cap(caps, FSINFO_CAP_HAS_ATIME);
+		fsinfo_set_cap(caps, FSINFO_CAP_HAS_CTIME);
+		fsinfo_set_cap(caps, FSINFO_CAP_HAS_MTIME);
+		if (version == 4) {
+			fsinfo_set_cap(caps, FSINFO_CAP_LEASES);
+			fsinfo_set_cap(caps, FSINFO_CAP_IVER_ALL_CHANGE);
+		}
+		return sizeof(*caps);
+
+	case FSINFO_ATTR_SERVER_NAME:
+		if (params->Nth || params->Mth)
+			return -ENODATA;
+		str = client->cl_hostname;
+		goto string;
+
+	case FSINFO_ATTR_SERVER_ADDRESS:
+		if (params->Nth || params->Mth)
+			return -ENODATA;
+		addr = params->buffer;
+		clnt = client->cl_rpcclient;
+		rcu_read_lock();
+		xprt = rcu_dereference(clnt->cl_xprt);
+		memcpy(&addr->address, &xprt->addr, xprt->addrlen);
+		rcu_read_unlock();
+		return sizeof(*addr);
+
+	case FSINFO_ATTR_PARAMETERS:
+		return nfs_fsinfo_parameters(params, path, server);
+
+	default:
+		return generic_fsinfo(path, params);
+	}
+
+string:
+	if (!str)
+		return 0;
+	strcpy(params->buffer, str);
+	return strlen(params->buffer);
+}
+EXPORT_SYMBOL_GPL(nfs_fsinfo);
+#endif /* CONFIG_FSINFO */
+
 /*
  * Map the security flavour number to a name
  */
-static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
+const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
 {
 	static const struct {
 		rpc_authflavor_t flavour;


  parent reply	other threads:[~2019-05-28 15:13 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-28 15:11 [PATCH 00/25] VFS: Introduce filesystem information query syscall [ver #13] David Howells
2019-05-28 15:11 ` [PATCH 01/25] vfs: syscall: Add fsinfo() to query filesystem information " David Howells
2019-05-29  7:42   ` Miklos Szeredi
2019-06-18 22:24   ` David Howells
2019-05-28 15:11 ` [PATCH 02/25] vfs: Allow fsinfo() to query what's in an fs_context " David Howells
2019-06-21  9:47   ` Christian Brauner
2019-06-21 13:12   ` David Howells
2019-06-21 13:16     ` Christian Brauner
2019-06-21 13:16       ` Christian Brauner
2019-06-21 13:28       ` Christian Brauner
2019-06-21 14:50       ` David Howells
2019-05-28 15:11 ` [PATCH 03/25] vfs: Allow fsinfo() to be used to query an fs parameter description " David Howells
2019-05-28 15:11 ` [PATCH 04/25] vfs: Implement parameter value retrieval with fsinfo() " David Howells
2019-05-29  8:08   ` Miklos Szeredi
2019-06-18 22:34   ` David Howells
2019-06-19  6:33     ` Miklos Szeredi
2019-05-28 15:11 ` [PATCH 05/25] fsinfo: Implement retrieval of LSM parameters " David Howells
2019-05-28 15:11 ` [PATCH 06/25] vfs: Introduce a non-repeating system-unique superblock ID " David Howells
2019-05-28 15:12 ` [PATCH 07/25] vfs: Allow fsinfo() to look up a mount object by " David Howells
2019-05-28 15:12 ` [PATCH 08/25] vfs: Add mount notification count " David Howells
2019-05-28 15:12 ` [PATCH 09/25] vfs: Allow mount information to be queried by fsinfo() " David Howells
2019-06-01 16:08   ` Joel Fernandes
2019-06-05 12:21   ` Alan Jenkins
2019-06-18 14:00   ` David Howells
2019-05-28 15:12 ` [PATCH 10/25] vfs: fsinfo sample: Mount listing program " David Howells
2019-06-05 12:22   ` Alan Jenkins
2019-05-28 15:12 ` [PATCH 11/25] hugetlbfs: Add support for fsinfo() " David Howells
2019-05-28 15:12 ` [PATCH 12/25] kernfs, cgroup: Add fsinfo support " David Howells
2019-05-28 15:12 ` [PATCH 13/25] fsinfo: Support SELinux superblock parameter retrieval " David Howells
2019-05-28 15:13 ` [PATCH 14/25] fsinfo: Support Smack " David Howells
2019-05-28 15:13 ` [PATCH 15/25] afs: Support fsinfo() " David Howells
2019-05-28 15:13 ` David Howells [this message]
2019-05-28 15:13 ` [PATCH 17/25] fsinfo: autofs - add sb operation " David Howells
2019-05-28 15:13 ` [PATCH 18/25] fsinfo: shmem - add tmpfs " David Howells
2019-05-28 15:13 ` [PATCH 19/25] fsinfo: proc - add " David Howells
2019-05-28 15:13 ` [PATCH 20/25] fsinfo: devpts " David Howells
2019-05-28 15:14 ` [PATCH 21/25] fsinfo: pstore " David Howells
2019-05-28 15:14 ` [PATCH 22/25] fsinfo: debugfs " David Howells
2019-05-28 15:14 ` [PATCH 23/25] fsinfo: bpf " David Howells
2019-05-28 15:14 ` [PATCH 24/25] fsinfo: ufs " David Howells
2019-05-28 15:14 ` [PATCH 25/25] fsinfo: Add API documentation " David Howells
2019-06-05 12:21   ` Alan Jenkins
2019-06-18 14:01   ` David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=155905640395.1662.11340611657732220291.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mszeredi@redhat.com \
    --cc=raven@themaw.net \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.