From: Trond Myklebust <Trond.Myklebust@netapp.com>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-fsdevel@vger.kernel.org
Subject: [PATCH 12/21] NFS: Add server and volume lists to /proc
Date: Thu, 06 Jul 2006 11:10:48 -0400 [thread overview]
Message-ID: <20060706151048.18779.55841.stgit@lade.trondhjem.org> (raw)
In-Reply-To: <20060706145424.18779.55583.stgit@lade.trondhjem.org>
From: David Howells <dhowells@redhat.com>
Make two new proc files available:
/proc/fs/nfsfs/servers
/proc/fs/nfsfs/volumes
The first lists the servers with which we are currently dealing (struct
nfs_client), and the second lists the volumes we have on those servers (struct
nfs_server).
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/client.c | 310 +++++++++++++++++++++++++++++++++++++++++++--
fs/nfs/inode.c | 7 +
fs/nfs/internal.h | 12 ++
include/linux/nfs_fs_sb.h | 4 +
4 files changed, 320 insertions(+), 13 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index fcbf2f3..8ae3f74 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -113,11 +113,15 @@ static struct nfs_client *nfs_alloc_clie
if (error < 0) {
dprintk("%s: couldn't start rpciod! Error = %d\n",
__FUNCTION__, error);
+ __set_bit(NFS_CS_RPCIOD, &clp->cl_svcs_state);
goto error_1;
}
- if (nfsversion == 4 && nfs_callback_up() < 0)
- goto error_2;
+ if (nfsversion == 4) {
+ if (nfs_callback_up() < 0)
+ goto error_2;
+ __set_bit(NFS_CS_CALLBACK, &clp->cl_svcs_state);
+ }
atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
@@ -150,8 +154,10 @@ #endif
error_3:
nfs_callback_down();
+ __clear_bit(NFS_CS_CALLBACK, &clp->cl_svcs_state);
error_2:
rpciod_down();
+ __clear_bit(NFS_CS_RPCIOD, &clp->cl_svcs_state);
error_1:
kfree(clp);
error_0:
@@ -163,10 +169,10 @@ error_0:
*/
static void nfs_free_client(struct nfs_client *clp)
{
- dprintk("--> nfs_free_client()\n");
+ dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion);
#ifdef CONFIG_NFS_V4
- if (clp->cl_nfsversion == 4) {
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_svcs_state)) {
while (!list_empty(&clp->cl_unused)) {
struct nfs4_state_owner *sp;
@@ -185,9 +191,10 @@ #endif
if (!IS_ERR(clp->cl_rpcclient))
rpc_shutdown_client(clp->cl_rpcclient);
- if (clp->cl_nfsversion == 4)
+ if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_svcs_state))
nfs_callback_down();
+ if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_svcs_state))
rpciod_down();
kfree(clp->cl_hostname);
@@ -867,18 +874,11 @@ static int nfs4_init_client(struct nfs_c
if (error < 0)
goto error;
- error = nfs_callback_up();
- if (error < 0) {
- dprintk("%s: failed to initialise callback channel. Error = %d\n",
- __FUNCTION__, error);
- goto error;
- }
-
error = nfs_idmap_new(clp);
if (error < 0) {
dprintk("%s: failed to create idmapper. Error = %d\n",
__FUNCTION__, error);
- nfs_callback_down();
+ __set_bit(NFS_CS_IDMAP, &clp->cl_svcs_state);
goto error;
}
@@ -1148,3 +1148,287 @@ out_free_server:
dprintk("<-- nfs_clone_server() = error %d\n", error);
return ERR_PTR(error);
}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_fs_nfs;
+
+static int nfs_server_list_open(struct inode *inode, struct file *file);
+static void *nfs_server_list_start(struct seq_file *p, loff_t *pos);
+static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos);
+static void nfs_server_list_stop(struct seq_file *p, void *v);
+static int nfs_server_list_show(struct seq_file *m, void *v);
+
+static struct seq_operations nfs_server_list_ops = {
+ .start = nfs_server_list_start,
+ .next = nfs_server_list_next,
+ .stop = nfs_server_list_stop,
+ .show = nfs_server_list_show,
+};
+
+static struct file_operations nfs_server_list_fops = {
+ .open = nfs_server_list_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int nfs_volume_list_open(struct inode *inode, struct file *file);
+static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos);
+static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos);
+static void nfs_volume_list_stop(struct seq_file *p, void *v);
+static int nfs_volume_list_show(struct seq_file *m, void *v);
+
+static struct seq_operations nfs_volume_list_ops = {
+ .start = nfs_volume_list_start,
+ .next = nfs_volume_list_next,
+ .stop = nfs_volume_list_stop,
+ .show = nfs_volume_list_show,
+};
+
+static struct file_operations nfs_volume_list_fops = {
+ .open = nfs_volume_list_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+/*
+ * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which
+ * we're dealing
+ */
+static int nfs_server_list_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *m;
+ int ret;
+
+ ret = seq_open(file, &nfs_server_list_ops);
+ if (ret < 0)
+ return ret;
+
+ m = file->private_data;
+ m->private = PDE(inode)->data;
+
+ return 0;
+}
+
+/*
+ * set up the iterator to start reading from the server list and return the first item
+ */
+static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
+{
+ struct list_head *_p;
+ loff_t pos = *_pos;
+
+ /* lock the list against modification */
+ spin_lock(&nfs_client_lock);
+
+ /* allow for the header line */
+ if (!pos)
+ return SEQ_START_TOKEN;
+ pos--;
+
+ /* find the n'th element in the list */
+ list_for_each(_p, &nfs_client_list)
+ if (!pos--)
+ break;
+
+ return _p != &nfs_client_list ? _p : NULL;
+}
+
+/*
+ * move to next server
+ */
+static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
+{
+ struct list_head *_p;
+
+ (*pos)++;
+
+ _p = v;
+ _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
+
+ return _p != &nfs_client_list ? _p : NULL;
+}
+
+/*
+ * clean up after reading from the transports list
+ */
+static void nfs_server_list_stop(struct seq_file *p, void *v)
+{
+ spin_unlock(&nfs_client_lock);
+}
+
+/*
+ * display a header line followed by a load of call lines
+ */
+static int nfs_server_list_show(struct seq_file *m, void *v)
+{
+ struct nfs_client *clp;
+
+ /* display header on line 1 */
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(m, "NV SERVER PORT USE HOSTNAME\n");
+ return 0;
+ }
+
+ /* display one transport per line on subsequent lines */
+ clp = list_entry(v, struct nfs_client, cl_share_link);
+
+ seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n",
+ clp->cl_nfsversion,
+ NIPQUAD(clp->cl_addr.sin_addr),
+ ntohs(clp->cl_addr.sin_port),
+ atomic_read(&clp->cl_count),
+ clp->cl_hostname);
+
+ return 0;
+}
+
+/*
+ * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes
+ */
+static int nfs_volume_list_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *m;
+ int ret;
+
+ ret = seq_open(file, &nfs_volume_list_ops);
+ if (ret < 0)
+ return ret;
+
+ m = file->private_data;
+ m->private = PDE(inode)->data;
+
+ return 0;
+}
+
+/*
+ * set up the iterator to start reading from the volume list and return the first item
+ */
+static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
+{
+ struct list_head *_p;
+ loff_t pos = *_pos;
+
+ /* lock the list against modification */
+ spin_lock(&nfs_client_lock);
+
+ /* allow for the header line */
+ if (!pos)
+ return SEQ_START_TOKEN;
+ pos--;
+
+ /* find the n'th element in the list */
+ list_for_each(_p, &nfs_volume_list)
+ if (!pos--)
+ break;
+
+ return _p != &nfs_volume_list ? _p : NULL;
+}
+
+/*
+ * move to next volume
+ */
+static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
+{
+ struct list_head *_p;
+
+ (*pos)++;
+
+ _p = v;
+ _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
+
+ return _p != &nfs_volume_list ? _p : NULL;
+}
+
+/*
+ * clean up after reading from the transports list
+ */
+static void nfs_volume_list_stop(struct seq_file *p, void *v)
+{
+ spin_unlock(&nfs_client_lock);
+}
+
+/*
+ * display a header line followed by a load of call lines
+ */
+static int nfs_volume_list_show(struct seq_file *m, void *v)
+{
+ struct nfs_server *server;
+ struct nfs_client *clp;
+ char dev[8], fsid[17];
+
+ /* display header on line 1 */
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(m, "NV SERVER PORT DEV FSID\n");
+ return 0;
+ }
+ /* display one transport per line on subsequent lines */
+ server = list_entry(v, struct nfs_server, master_link);
+ clp = server->nfs_client;
+
+ snprintf(dev, 8, "%u:%u",
+ MAJOR(server->s_dev), MINOR(server->s_dev));
+
+ snprintf(fsid, 17, "%llx:%llx",
+ server->fsid.major, server->fsid.minor);
+
+ seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n",
+ clp->cl_nfsversion,
+ NIPQUAD(clp->cl_addr.sin_addr),
+ ntohs(clp->cl_addr.sin_port),
+ dev,
+ fsid);
+
+ return 0;
+}
+
+/*
+ * initialise the /proc/fs/nfsfs/ directory
+ */
+int __init nfs_fs_proc_init(void)
+{
+ struct proc_dir_entry *p;
+
+ proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs);
+ if (!proc_fs_nfs)
+ goto error_0;
+
+ proc_fs_nfs->owner = THIS_MODULE;
+
+ /* a file of servers with which we're dealing */
+ p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs);
+ if (!p)
+ goto error_1;
+
+ p->proc_fops = &nfs_server_list_fops;
+ p->owner = THIS_MODULE;
+
+ /* a file of volumes that we have mounted */
+ p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs);
+ if (!p)
+ goto error_2;
+
+ p->proc_fops = &nfs_volume_list_fops;
+ p->owner = THIS_MODULE;
+ return 0;
+
+error_2:
+ remove_proc_entry("servers", proc_fs_nfs);
+error_1:
+ remove_proc_entry("nfsfs", proc_root_fs);
+error_0:
+ return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/nfsfs/ directory
+ */
+void nfs_fs_proc_exit(void)
+{
+ remove_proc_entry("volumes", proc_fs_nfs);
+ remove_proc_entry("servers", proc_fs_nfs);
+ remove_proc_entry("nfsfs", proc_root_fs);
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 261411a..7665b73 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1144,6 +1144,10 @@ static int __init init_nfs_fs(void)
{
int err;
+ err = nfs_fs_proc_init();
+ if (err)
+ goto out5;
+
err = nfs_init_nfspagecache();
if (err)
goto out4;
@@ -1184,6 +1188,8 @@ out2:
out3:
nfs_destroy_nfspagecache();
out4:
+ nfs_fs_proc_exit();
+out5:
return err;
}
@@ -1198,6 +1204,7 @@ #ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
#endif
unregister_nfs_fs();
+ nfs_fs_proc_exit();
}
/* Not quite true; I just maintain it */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 3d51eee..1a1312e 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -47,6 +47,18 @@ extern void nfs_free_server(struct nfs_s
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
struct nfs_fh *,
struct nfs_fattr *);
+#ifdef CONFIG_PROC_FS
+extern int __init nfs_fs_proc_init(void);
+extern void nfs_fs_proc_exit(void);
+#else
+static inline int nfs_fs_proc_init(void)
+{
+ return 0;
+}
+static inline void nfs_fs_proc_exit(void)
+{
+}
+#endif
/* nfs4namespace.c */
#ifdef CONFIG_NFS_V4
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 4e13a6c..62b7ca9 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -16,6 +16,10 @@ #define NFS_CS_READY 0 /* ready to be
#define NFS_CS_INITING 1 /* busy initialising */
int cl_nfsversion; /* NFS protocol version */
rpc_authflavor_t cl_authflavour;
+ unsigned long cl_svcs_state; /* NFS services state */
+#define NFS_CS_RPCIOD 0 /* - rpciod started */
+#define NFS_CS_CALLBACK 1 /* - callback started */
+#define NFS_CS_IDMAP 2 /* - idmap started */
struct sockaddr_in cl_addr; /* server identifier */
char * cl_hostname; /* hostname of server */
struct list_head cl_share_link; /* link in global client list */
next prev parent reply other threads:[~2006-07-06 15:11 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-07-06 14:54 [PATCH 00/21] FSCACHE support for AFS and NFS Trond Myklebust
2006-07-06 15:10 ` [PATCH 01/21] NFS: Add dentry materialisation op Trond Myklebust
2006-07-06 15:10 ` [PATCH 02/21] NFS: Fix up split of fs/nfs/inode.c Trond Myklebust
2006-07-06 15:10 ` [PATCH 03/21] NFS: Disambiguate nfs_stat_to_errno() Trond Myklebust
2006-07-06 15:10 ` [PATCH 04/21] NFS: Fix NFS4 callback up/down prototypes Trond Myklebust
2006-07-06 15:10 ` [PATCH 05/21] NFS: Rename struct nfs4_client to struct nfs_client Trond Myklebust
2006-07-06 15:10 ` [PATCH 06/21] NFS: Rename nfs_server::nfs4_state Trond Myklebust
2006-07-06 15:10 ` [PATCH 07/21] NFS: Return an error when starting the idmapping pipe Trond Myklebust
2006-07-06 15:10 ` [PATCH 08/21] NFS: Add a lookupfh NFS RPC op Trond Myklebust
2006-07-07 1:31 ` Andrew Morton
2006-07-06 15:10 ` [PATCH 09/21] " Trond Myklebust
2006-07-06 15:10 ` [PATCH 10/21] NFS: Generalise the nfs_client structure Trond Myklebust
2006-07-06 15:10 ` Trond Myklebust [this message]
2006-07-06 15:10 ` [PATCH 13/21] FS-Cache: Provide a filesystem-specific sync'able page bit Trond Myklebust
2006-07-06 15:10 ` [PATCH 14/21] FS-Cache: Avoid ENFILE checking for kernel-specific open files Trond Myklebust
2006-07-07 1:56 ` Andrew Morton
2006-07-07 9:54 ` Christoph Hellwig
2006-07-07 14:26 ` Trond Myklebust
2006-07-07 12:36 ` David Howells
2006-07-06 15:10 ` [PATCH 16/21] FS-Cache: Release page->private in failed readahead Trond Myklebust
2006-07-07 1:56 ` Andrew Morton
2006-07-07 9:18 ` David Howells
2006-07-06 15:11 ` [PATCH 17/21] FS-Cache: Make kAFS use FS-Cache Trond Myklebust
2006-07-06 15:11 ` [PATCH 19/21] NFS: Use local caching Trond Myklebust
2006-07-06 15:11 ` [PATCH 20/21] AUTOFS: Make sure all dentries refs are released before calling kill_anon_super() Trond Myklebust
2006-07-07 1:56 ` Andrew Morton
2006-07-07 3:15 ` Ian Kent
2006-07-07 3:23 ` Andrew Morton
2006-07-07 3:50 ` Ian Kent
2006-07-06 15:11 ` [PATCH 21/21] VFS: Destroy the dentries contributed by a superblock on unmounting Trond Myklebust
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=20060706151048.18779.55841.stgit@lade.trondhjem.org \
--to=trond.myklebust@netapp.com \
--cc=akpm@osdl.org \
--cc=linux-fsdevel@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).