All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/9] Add a tool for using the new sysfs files
@ 2021-08-30 15:56 schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 1/9] nfssysfs: Add a nfssysfs.py tool schumaker.anna
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

These patches implement a tool that can be used to read and write the
sysfs files, with subcommands! They do need my extra patches to add in
srcaddr and dst_port to the xprt_info file. Let me know if I need to
resend adding support for kernels both with and without these patches.

The following subcommands are implemented:
	nfssysfs.py rpc-client
 	nfssysfs.py xprt
 	nfssysfs.py xprt set
 	nfssysfs.py xprt-switch
 	nfssysfs.py xprt-switch set

So you can print out information about every xprt-switch with:
	anna@client ~ % nfssysfs xprt-switch
	switch 0: num_xprts 1, num_active 1, queue_len 0
		xprt 0: local, /var/run/gssproxy.sock [main]
	switch 1: num_xprts 1, num_active 1, queue_len 0
		xprt 1: local, /var/run/rpcbind.sock [main]
	switch 2: num_xprts 1, num_active 1, queue_len 0
		xprt 2: tcp, 192.168.111.1 [main]
	switch 3: num_xprts 4, num_active 4, queue_len 0
		xprt 3: tcp, 192.168.111.188 [main]
		xprt 4: tcp, 192.168.111.188
		xprt 5: tcp, 192.168.111.188
		xprt 6: tcp, 192.168.111.188

And information about each xprt:
	anna@client ~ % nfssysfs xprt       
	xprt 0: local, /var/run/gssproxy.sock, port 0, state <MAIN,CONNECTED,BOUND>
		Source: (einval), port 0, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	xprt 1: local, /var/run/rpcbind.sock, port 0, state <MAIN,CONNECTED,BOUND>
		Source: (einval), port 0, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	xprt 2: tcp, 192.168.111.1, port 2049, state <MAIN,CONNECTED,BOUND>
		Source: 192.168.111.222, port 959, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	xprt 3: tcp, 192.168.111.188, port 2049, state <MAIN,CONNECTED,BOUND>
		Source: 192.168.111.222, port 921, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	xprt 4: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
		Source: 192.168.111.222, port 726, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	xprt 5: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
		Source: 192.168.111.222, port 671, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	xprt 6: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
		Source: 192.168.111.222, port 934, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0

You can use the `set` subcommand to change the dstaddr of individual xprts:
	anna@client ~ % sudo nfssysfs xprt --id 4 
	xprt 4: tcp, 192.168.111.188, port 2049, state <CONNECTED,BOUND>
		Source: 192.168.111.222, port 726, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0
	anna@client ~ % sudo nfssysfs xprt set --id 4 --dstaddr server2.nowheycreamery.com
	xprt 4: tcp, 192.168.111.186, port 2049, state <CONNECTED,BOUND>
		Source: 192.168.111.222, port 726, Requests: 2
		Congestion: cur 0, win 256, Slots: min 2, max 65536
		Queues: binding 0, sending 0, pending 0, backlog 0, tasks 0

Or for changing the dstaddr of all xprts attached to a switch:
	anna@client % ./nfssysfs.py xprt-switch --id 3
	switch 3: num_xprts 4, num_active 4, queue_len 0
		xprt 3: tcp, 192.168.111.188 [main]
		xprt 4: tcp, 192.168.111.188
		xprt 5: tcp, 192.168.111.188
		xprt 6: tcp, 192.168.111.188
	anna@client % sudo ./nfssysfs.py xprt-switch set --id 4 --dstaddr server2.nowheycreamery.vm
	switch 3: num_xprts 4, num_active 4, queue_len 0
		xprt 2: tcp, 192.168.111.186 [main]
		xprt 3: tcp, 192.168.111.186
		xprt 5: tcp, 192.168.111.186
		xprt 6: tcp, 192.168.111.186


One question I have is about the name right now. Is naming it "nfssysfs"
okay, or would it be better to name it "nfs" with "sysfs" as a
subcommand? Going with just "nfs" as the command name would allow us to
add other non-sysfs tools as subcommands in the future (such as `nfs stat`
to call `nfsstat`, or for new commands that would otherwise be prefixed
with "nfs")

Thoughts?
Anna


Anna Schumaker (9):
  nfssysfs: Add a nfssysfs.py tool
  nfssysfs.py: Add a command for printing xprt switch information
  nfssysfs.py: Add a command for printing individual xprts
  nfssysfs.py: Add a command for printing rpc-client information
  nfssysfs.py: Add a command for changing xprt dstaddr
  nfssysfs.py: Add a command for changing xprt-switch dstaddrs
  nfssysfs.py: Add a command for changing xprt state
  nfssysfs: Add a man page
  nfssysfs: Add installation to the Makefile

 .gitignore                  |   2 +
 configure.ac                |   1 +
 tools/Makefile.am           |   2 +-
 tools/nfssysfs/Makefile.am  |  20 +++++++
 tools/nfssysfs/client.py    |  27 ++++++++++
 tools/nfssysfs/nfssysfs     |   5 ++
 tools/nfssysfs/nfssysfs.man |  88 +++++++++++++++++++++++++++++++
 tools/nfssysfs/nfssysfs.py  |  23 ++++++++
 tools/nfssysfs/switch.py    |  51 ++++++++++++++++++
 tools/nfssysfs/sysfs.py     |  29 +++++++++++
 tools/nfssysfs/xprt.py      | 101 ++++++++++++++++++++++++++++++++++++
 11 files changed, 348 insertions(+), 1 deletion(-)
 create mode 100644 tools/nfssysfs/Makefile.am
 create mode 100644 tools/nfssysfs/client.py
 create mode 100644 tools/nfssysfs/nfssysfs
 create mode 100644 tools/nfssysfs/nfssysfs.man
 create mode 100755 tools/nfssysfs/nfssysfs.py
 create mode 100644 tools/nfssysfs/switch.py
 create mode 100644 tools/nfssysfs/sysfs.py
 create mode 100644 tools/nfssysfs/xprt.py

-- 
2.33.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v3 1/9] nfssysfs: Add a nfssysfs.py tool
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 2/9] nfssysfs.py: Add a command for printing xprt switch information schumaker.anna
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

This will be used to print and manipulate the sunrpc sysfs directory
files. Running without arguments prints both usage information and the
location of the sunrpc sysfs directory.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
v3: Check for type: "sysfs" as the third column in the /proc/mounts file
    Rename from nfs-sysfs.py to nfssysfs.py
---
 .gitignore                 |  2 ++
 tools/nfssysfs/nfssysfs.py | 13 +++++++++++++
 tools/nfssysfs/sysfs.py    | 19 +++++++++++++++++++
 3 files changed, 34 insertions(+)
 create mode 100755 tools/nfssysfs/nfssysfs.py
 create mode 100644 tools/nfssysfs/sysfs.py

diff --git a/.gitignore b/.gitignore
index c89d1cd2583d..a476bd20bc3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,5 @@ systemd/rpc-gssd.service
 cscope.*
 # generic editor backup et al
 *~
+# python bytecode
+__pycache__
diff --git a/tools/nfssysfs/nfssysfs.py b/tools/nfssysfs/nfssysfs.py
new file mode 100755
index 000000000000..8ff59ea9e81b
--- /dev/null
+++ b/tools/nfssysfs/nfssysfs.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import argparse
+import sysfs
+
+parser = argparse.ArgumentParser()
+
+def show_small_help(args):
+    parser.print_usage()
+    print("sunrpc dir:", sysfs.SUNRPC)
+parser.set_defaults(func=show_small_help)
+
+args = parser.parse_args()
+args.func(args)
diff --git a/tools/nfssysfs/sysfs.py b/tools/nfssysfs/sysfs.py
new file mode 100644
index 000000000000..c9d477063585
--- /dev/null
+++ b/tools/nfssysfs/sysfs.py
@@ -0,0 +1,19 @@
+import pathlib
+import re
+import sys
+
+MOUNT = None
+with open("/proc/mounts", 'r') as f:
+    for line in f:
+        if re.search("^sys ", line):
+            MOUNT = line.split()[1]
+            break
+
+if MOUNT == None:
+    print("ERROR: sysfs is not mounted")
+    sys.exit(1)
+
+SUNRPC = pathlib.Path(MOUNT) / "kernel" / "sunrpc"
+if not SUNRPC.is_dir():
+    print("ERROR: sysfs does not have sunrpc directory")
+    sys.exit(1)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 2/9] nfssysfs.py: Add a command for printing xprt switch information
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 1/9] nfssysfs: Add a nfssysfs.py tool schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 3/9] nfssysfs.py: Add a command for printing individual xprts schumaker.anna
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

This combines the information found in xprt_switch_info with a subset of
the information found in each xprt subdirectory

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 tools/nfssysfs/nfssysfs.py |  6 ++++++
 tools/nfssysfs/switch.py   | 35 +++++++++++++++++++++++++++++++++++
 tools/nfssysfs/sysfs.py    | 10 ++++++++++
 tools/nfssysfs/xprt.py     | 12 ++++++++++++
 4 files changed, 63 insertions(+)
 create mode 100644 tools/nfssysfs/switch.py
 create mode 100644 tools/nfssysfs/xprt.py

diff --git a/tools/nfssysfs/nfssysfs.py b/tools/nfssysfs/nfssysfs.py
index 8ff59ea9e81b..90efcbed7ac8 100755
--- a/tools/nfssysfs/nfssysfs.py
+++ b/tools/nfssysfs/nfssysfs.py
@@ -9,5 +9,11 @@ def show_small_help(args):
     print("sunrpc dir:", sysfs.SUNRPC)
 parser.set_defaults(func=show_small_help)
 
+
+import switch
+subparser = parser.add_subparsers(title="commands")
+switch.add_command(subparser)
+
+
 args = parser.parse_args()
 args.func(args)
diff --git a/tools/nfssysfs/switch.py b/tools/nfssysfs/switch.py
new file mode 100644
index 000000000000..afb6963a0a1f
--- /dev/null
+++ b/tools/nfssysfs/switch.py
@@ -0,0 +1,35 @@
+import sysfs
+import xprt
+
+class XprtSwitch:
+    def __init__(self, path):
+        self.path = path
+        self.id = int(str(path).rsplit("-", 1)[1])
+
+        self.xprts = [ xprt.Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
+        self.xprts.sort()
+
+        self.__dict__.update(sysfs.read_info_file(path / "xprt_switch_info"))
+
+    def __lt__(self, rhs):
+        return self.path < rhs.path
+
+    def __str__(self):
+        line = "switch %s: num_xprts %s, num_active %s, queue_len %s" % \
+                (self.id, self.num_xprts, self.num_active, self.queue_len)
+        for x in self.xprts:
+            line += "\n	%s" % x.small_str()
+        return line
+
+
+def list_xprt_switches(args):
+    switches = [ XprtSwitch(f) for f in (sysfs.SUNRPC / "xprt-switches").iterdir() ]
+    switches.sort()
+    for xs in switches:
+        if args.id == None or xs.id == args.id[0]:
+            print(xs)
+
+def add_command(subparser):
+    parser = subparser.add_parser("xprt-switch", help="Commands for xprt switches")
+    parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt-switch to show")
+    parser.set_defaults(func=list_xprt_switches)
diff --git a/tools/nfssysfs/sysfs.py b/tools/nfssysfs/sysfs.py
index c9d477063585..79f844af34a6 100644
--- a/tools/nfssysfs/sysfs.py
+++ b/tools/nfssysfs/sysfs.py
@@ -17,3 +17,13 @@ SUNRPC = pathlib.Path(MOUNT) / "kernel" / "sunrpc"
 if not SUNRPC.is_dir():
     print("ERROR: sysfs does not have sunrpc directory")
     sys.exit(1)
+
+
+def read_info_file(path):
+    res = dict()
+    with open(path) as info:
+        for line in info:
+            if "=" in line:
+                (key, val) = line.strip().split("=")
+                res[key] = int(val)
+    return res
diff --git a/tools/nfssysfs/xprt.py b/tools/nfssysfs/xprt.py
new file mode 100644
index 000000000000..d37537771c1d
--- /dev/null
+++ b/tools/nfssysfs/xprt.py
@@ -0,0 +1,12 @@
+class Xprt:
+    def __init__(self, path):
+        self.path = path
+        self.id = int(str(path).rsplit("-", 2)[1])
+        self.type = str(path).rsplit("-", 2)[2]
+        self.dstaddr = open(path / "dstaddr", 'r').readline().strip()
+
+    def __lt__(self, rhs):
+        return self.id < rhs.id
+
+    def small_str(self):
+        return "xprt %s: %s, %s" % (self.id, self.type, self.dstaddr)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 3/9] nfssysfs.py: Add a command for printing individual xprts
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 1/9] nfssysfs: Add a nfssysfs.py tool schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 2/9] nfssysfs.py: Add a command for printing xprt switch information schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 4/9] nfssysfs.py: Add a command for printing rpc-client information schumaker.anna
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

This shows more detailed information than what is presented with xprt
switches. I take the chance to add a main-export indicator to the
small_str() used when printing out xprt-switches.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 tools/nfssysfs/nfssysfs.py |  2 ++
 tools/nfssysfs/xprt.py     | 38 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/tools/nfssysfs/nfssysfs.py b/tools/nfssysfs/nfssysfs.py
index 90efcbed7ac8..dfad6ac08fa0 100755
--- a/tools/nfssysfs/nfssysfs.py
+++ b/tools/nfssysfs/nfssysfs.py
@@ -11,8 +11,10 @@ parser.set_defaults(func=show_small_help)
 
 
 import switch
+import xprt
 subparser = parser.add_subparsers(title="commands")
 switch.add_command(subparser)
+xprt.add_command(subparser)
 
 
 args = parser.parse_args()
diff --git a/tools/nfssysfs/xprt.py b/tools/nfssysfs/xprt.py
index d37537771c1d..fbdd9bfc9375 100644
--- a/tools/nfssysfs/xprt.py
+++ b/tools/nfssysfs/xprt.py
@@ -1,12 +1,48 @@
+import sysfs
+
 class Xprt:
     def __init__(self, path):
         self.path = path
         self.id = int(str(path).rsplit("-", 2)[1])
         self.type = str(path).rsplit("-", 2)[2]
         self.dstaddr = open(path / "dstaddr", 'r').readline().strip()
+        self.srcaddr = open(path / "srcaddr", 'r').readline().strip()
+
+        with open(path / "xprt_state") as f:
+            self.state = ','.join(f.readline().split()[1:])
+        self.__dict__.update(sysfs.read_info_file(path / "xprt_info"))
 
     def __lt__(self, rhs):
         return self.id < rhs.id
 
+    def __str__(self):
+        state = self.state
+        if self.main_xprt:
+            state = "MAIN," + self.state
+
+        line = "xprt %s: %s, %s, port %s, state <%s>" % \
+                (self.id, self.type, self.dstaddr, self.dst_port, state)
+        line += "\n	Source: %s, port %s, Requests: %s" % \
+                (self.srcaddr, self.src_port, self.num_reqs)
+        line += "\n	Congestion: cur %s, win %s, Slots: min %s, max %s" % \
+                (self.cur_cong, self.cong_win, self.min_num_slots, self.max_num_slots)
+        line += "\n	Queues: binding %s, sending %s, pending %s, backlog %s, tasks %s" % \
+                (self.binding_q_len, self.sending_q_len, self.pending_q_len, self.backlog_q_len, self.tasks_queuelen)
+        return line
+
     def small_str(self):
-        return "xprt %s: %s, %s" % (self.id, self.type, self.dstaddr)
+        return "xprt %s: %s, %s%s" % (self.id, self.type, self.dstaddr,
+                                     f" [main]" if self.main_xprt else "" )
+
+
+def list_xprts(args):
+    xprts = [ Xprt(f) for f in (sysfs.SUNRPC / "xprt-switches").glob("**/xprt-*") ]
+    xprts.sort()
+    for xprt in xprts:
+        if args.id == None or xprt.id == args.id[0]:
+            print(xprt)
+
+def add_command(subparser):
+    parser = subparser.add_parser("xprt", help="Commands for individual xprts")
+    parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt to show")
+    parser.set_defaults(func=list_xprts)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 4/9] nfssysfs.py: Add a command for printing rpc-client information
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (2 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 3/9] nfssysfs.py: Add a command for printing individual xprts schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 5/9] nfssysfs.py: Add a command for changing xprt dstaddr schumaker.anna
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

It's mostly the same information as with xprt-switches, except with
rpc-client id prepended to the first line.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 tools/nfssysfs/client.py   | 27 +++++++++++++++++++++++++++
 tools/nfssysfs/nfssysfs.py |  2 ++
 tools/nfssysfs/switch.py   |  7 ++++---
 3 files changed, 33 insertions(+), 3 deletions(-)
 create mode 100644 tools/nfssysfs/client.py

diff --git a/tools/nfssysfs/client.py b/tools/nfssysfs/client.py
new file mode 100644
index 000000000000..5192cc226aed
--- /dev/null
+++ b/tools/nfssysfs/client.py
@@ -0,0 +1,27 @@
+import sysfs
+import switch
+
+class RpcClient:
+    def __init__(self, path):
+        self.path = path
+        self.id = int(str(path).rsplit("-", 1)[1])
+        self.switch = switch.XprtSwitch(path / (path / "switch").readlink(), sep=",")
+
+    def __lt__(self, rhs):
+        return self.id < rhs.id
+
+    def __str__(self):
+        return "client %s: %s" % (self.id, self.switch)
+
+
+def list_rpc_clients(args):
+    clients = [ RpcClient(f) for f in (sysfs.SUNRPC / "rpc-clients").iterdir() ]
+    clients.sort()
+    for client in clients:
+        if args.id == None or client.id == args.id[0]:
+            print(client)
+
+def add_command(subparser):
+    parser = subparser.add_parser("rpc-client", help="Commands for rpc clients")
+    parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific client to show")
+    parser.set_defaults(func=list_rpc_clients)
diff --git a/tools/nfssysfs/nfssysfs.py b/tools/nfssysfs/nfssysfs.py
index dfad6ac08fa0..e2172cdfa4c1 100755
--- a/tools/nfssysfs/nfssysfs.py
+++ b/tools/nfssysfs/nfssysfs.py
@@ -10,9 +10,11 @@ def show_small_help(args):
 parser.set_defaults(func=show_small_help)
 
 
+import client
 import switch
 import xprt
 subparser = parser.add_subparsers(title="commands")
+client.add_command(subparser)
 switch.add_command(subparser)
 xprt.add_command(subparser)
 
diff --git a/tools/nfssysfs/switch.py b/tools/nfssysfs/switch.py
index afb6963a0a1f..5384f970235c 100644
--- a/tools/nfssysfs/switch.py
+++ b/tools/nfssysfs/switch.py
@@ -2,9 +2,10 @@ import sysfs
 import xprt
 
 class XprtSwitch:
-    def __init__(self, path):
+    def __init__(self, path, sep=":"):
         self.path = path
         self.id = int(str(path).rsplit("-", 1)[1])
+        self.sep = sep
 
         self.xprts = [ xprt.Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
         self.xprts.sort()
@@ -15,8 +16,8 @@ class XprtSwitch:
         return self.path < rhs.path
 
     def __str__(self):
-        line = "switch %s: num_xprts %s, num_active %s, queue_len %s" % \
-                (self.id, self.num_xprts, self.num_active, self.queue_len)
+        line = "switch %s%s num_xprts %s, num_active %s, queue_len %s" % \
+                (self.id, self.sep, self.num_xprts, self.num_active, self.queue_len)
         for x in self.xprts:
             line += "\n	%s" % x.small_str()
         return line
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 5/9] nfssysfs.py: Add a command for changing xprt dstaddr
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (3 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 4/9] nfssysfs.py: Add a command for printing rpc-client information schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 6/9] nfssysfs.py: Add a command for changing xprt-switch dstaddrs schumaker.anna
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

Using the socket module for dns resolution

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 tools/nfssysfs/xprt.py | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tools/nfssysfs/xprt.py b/tools/nfssysfs/xprt.py
index fbdd9bfc9375..2160cb0a9575 100644
--- a/tools/nfssysfs/xprt.py
+++ b/tools/nfssysfs/xprt.py
@@ -1,3 +1,4 @@
+import socket
 import sysfs
 
 class Xprt:
@@ -34,6 +35,12 @@ class Xprt:
         return "xprt %s: %s, %s%s" % (self.id, self.type, self.dstaddr,
                                      f" [main]" if self.main_xprt else "" )
 
+    def set_dstaddr(self, newaddr):
+        resolved = socket.gethostbyname(newaddr)
+        with open(self.path / "dstaddr", 'w') as f:
+            f.write(resolved)
+        self.dstaddr = open(self.path / "dstaddr", 'r').readline().strip()
+
 
 def list_xprts(args):
     xprts = [ Xprt(f) for f in (sysfs.SUNRPC / "xprt-switches").glob("**/xprt-*") ]
@@ -42,7 +49,28 @@ def list_xprts(args):
         if args.id == None or xprt.id == args.id[0]:
             print(xprt)
 
+def get_xprt(id):
+    xprts = [ Xprt(f) for f in (sysfs.SUNRPC / "xprt-switches").glob("**/xprt-*") ]
+    for xprt in xprts:
+        if xprt.id == id:
+            return xprt
+
+def set_xprt_property(args):
+    xprt = get_xprt(args.id[0])
+    try:
+        if args.dstaddr != None:
+            xprt.set_dstaddr(args.dstaddr[0])
+        print(xprt)
+    except Exception as e:
+        print(e)
+
 def add_command(subparser):
     parser = subparser.add_parser("xprt", help="Commands for individual xprts")
     parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt to show")
     parser.set_defaults(func=list_xprts)
+
+    subparser = parser.add_subparsers()
+    parser = subparser.add_parser("set", help="Set an xprt property")
+    parser.add_argument("--id", metavar="ID", nargs=1, type=int, required=True, help="Id of a specific xprt to modify")
+    parser.add_argument("--dstaddr", metavar="dstaddr", nargs=1, type=str, help="New dstaddr to set")
+    parser.set_defaults(func=set_xprt_property)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 6/9] nfssysfs.py: Add a command for changing xprt-switch dstaddrs
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (4 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 5/9] nfssysfs.py: Add a command for changing xprt dstaddr schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 7/9] nfssysfs.py: Add a command for changing xprt state schumaker.anna
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

This is basically the same as for xprts, but it iterates through all
xprts attached to the switch to apply the new address.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 tools/nfssysfs/switch.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tools/nfssysfs/switch.py b/tools/nfssysfs/switch.py
index 5384f970235c..859b82e07895 100644
--- a/tools/nfssysfs/switch.py
+++ b/tools/nfssysfs/switch.py
@@ -30,7 +30,22 @@ def list_xprt_switches(args):
         if args.id == None or xs.id == args.id[0]:
             print(xs)
 
+def set_xprt_switch_property(args):
+    switch = XprtSwitch(sysfs.SUNRPC / "xprt-switches" / f"switch-{args.id[0]}")
+    try:
+        for xprt in switch.xprts:
+            xprt.set_dstaddr(args.dstaddr[0])
+        print(switch)
+    except Exception as e:
+        print(e)
+
 def add_command(subparser):
     parser = subparser.add_parser("xprt-switch", help="Commands for xprt switches")
     parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt-switch to show")
     parser.set_defaults(func=list_xprt_switches)
+
+    subparser = parser.add_subparsers()
+    parser = subparser.add_parser("set", help="Set an xprt switch property")
+    parser.add_argument("--id", metavar="ID", nargs=1, type=int, required=True, help="Id of an xprt-switch to modify")
+    parser.add_argument("--dstaddr", metavar="dstaddr", nargs=1, type=str, help="New dstaddr to set")
+    parser.set_defaults(func=set_xprt_switch_property)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 7/9] nfssysfs.py: Add a command for changing xprt state
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (5 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 6/9] nfssysfs.py: Add a command for changing xprt-switch dstaddrs schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 8/9] nfssysfs: Add a man page schumaker.anna
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

We can set it offline or online, or we can remove an xprt. The kernel
only supports removing offlined transports, so we make sure to set the
state to "offline" before sending the remove command.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
v3: Don't compare booleans against True / False
---
 tools/nfssysfs/xprt.py | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/tools/nfssysfs/xprt.py b/tools/nfssysfs/xprt.py
index 2160cb0a9575..9426c99dae2b 100644
--- a/tools/nfssysfs/xprt.py
+++ b/tools/nfssysfs/xprt.py
@@ -8,15 +8,18 @@ class Xprt:
         self.type = str(path).rsplit("-", 2)[2]
         self.dstaddr = open(path / "dstaddr", 'r').readline().strip()
         self.srcaddr = open(path / "srcaddr", 'r').readline().strip()
+        self.exists = True
 
-        with open(path / "xprt_state") as f:
-            self.state = ','.join(f.readline().split()[1:])
+        self.read_state()
         self.__dict__.update(sysfs.read_info_file(path / "xprt_info"))
 
     def __lt__(self, rhs):
         return self.id < rhs.id
 
     def __str__(self):
+        if not self.exists:
+            return "xprt %s: has been removed" % self.id
+
         state = self.state
         if self.main_xprt:
             state = "MAIN," + self.state
@@ -31,6 +34,13 @@ class Xprt:
                 (self.binding_q_len, self.sending_q_len, self.pending_q_len, self.backlog_q_len, self.tasks_queuelen)
         return line
 
+    def read_state(self):
+        if not self.path.exists():
+            self.exists = False
+            return
+        with open(self.path / "xprt_state") as f:
+            self.state = ','.join(f.readline().split()[1:])
+
     def small_str(self):
         return "xprt %s: %s, %s%s" % (self.id, self.type, self.dstaddr,
                                      f" [main]" if self.main_xprt else "" )
@@ -41,6 +51,11 @@ class Xprt:
             f.write(resolved)
         self.dstaddr = open(self.path / "dstaddr", 'r').readline().strip()
 
+    def set_state(self, state):
+        with open(self.path / "xprt_state", 'w') as f:
+            f.write(state)
+        self.read_state()
+
 
 def list_xprts(args):
     xprts = [ Xprt(f) for f in (sysfs.SUNRPC / "xprt-switches").glob("**/xprt-*") ]
@@ -60,6 +75,13 @@ def set_xprt_property(args):
     try:
         if args.dstaddr != None:
             xprt.set_dstaddr(args.dstaddr[0])
+        if args.offline:
+            xprt.set_state("offline")
+        elif args.online:
+            xprt.set_state("online")
+        elif args.remove:
+            xprt.set_state("offline")
+            xprt.set_state("remove")
         print(xprt)
     except Exception as e:
         print(e)
@@ -73,4 +95,7 @@ def add_command(subparser):
     parser = subparser.add_parser("set", help="Set an xprt property")
     parser.add_argument("--id", metavar="ID", nargs=1, type=int, required=True, help="Id of a specific xprt to modify")
     parser.add_argument("--dstaddr", metavar="dstaddr", nargs=1, type=str, help="New dstaddr to set")
+    parser.add_argument("--offline", action="store_true", help="Set an xprt offline")
+    parser.add_argument("--online", action="store_true", help="Set an offline xprt back online")
+    parser.add_argument("--remove", action="store_true", help="Remove an xprt")
     parser.set_defaults(func=set_xprt_property)
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 8/9] nfssysfs: Add a man page
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (6 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 7/9] nfssysfs.py: Add a command for changing xprt state schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-30 15:56 ` [PATCH v3 9/9] nfssysfs: Add installation to the Makefile schumaker.anna
  2021-08-31 12:26 ` [PATCH v3 0/9] Add a tool for using the new sysfs files Benjamin Coddington
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 tools/nfssysfs/nfssysfs.man | 88 +++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 tools/nfssysfs/nfssysfs.man

diff --git a/tools/nfssysfs/nfssysfs.man b/tools/nfssysfs/nfssysfs.man
new file mode 100644
index 000000000000..7b00c1a81106
--- /dev/null
+++ b/tools/nfssysfs/nfssysfs.man
@@ -0,0 +1,88 @@
+.\"
+.\" nfssysfs(8)
+.\"
+.TH nfssysfs 8 "05 Aug 2021"
+.SH NAME
+nfssysfs \- Displays NFS & SunRPC connection information
+.SH SYNOPSIS
+.B nfssysfs
+.RB [ \-h | \-\-help ]
+.P
+.B nfssysfs rpc-client
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.P
+.B nfssysfs xprt-switch
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.P
+.B nfssysfs xprt-switch set
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.RB [ \--dstaddr
+.IR dstaddr]
+.P
+.B nfssysfs xprt
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.P
+.B nfssysfs xprt set
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.RB [ \--dstaddr
+.IR dstaddr]
+.RB [ --offline ]
+.RB [ --online ]
+.RB [ --remove ]
+.P
+.SH DESCRIPTION
+.RB "The " nfssysfs " command displays information collected in the SunRPC sysfs files about the system's SunRPC objects.
+.P
+.SS Objects
+Valid
+.BR nfssysfs (8)
+objects are:
+.IP "\fBrpc-client\fP"
+Display information about this system's RPC clients.
+.IP "\fBxprt-switch\fP"
+Display information about groups of transports.
+.IP "\fBxprt\fP"
+Display detailed information about each transport that exists on the system.
+.SH OPTIONS
+.SS Options valid for all objects
+.TP
+.B \-h, \-\-help
+Show the help message and exit
+.TP
+.B \-\-id \fIID
+Set or display properties for the object with the given
+.IR ID.
+This option is mandatory for setting properties.
+.SS Options specific to the `xprt-switch set` sub-command
+.TP
+.B \-\-dstaddr \fIdstaddr
+Change the destination address of all transports in the xprt-switch to
+.IR dstaddr
+.SS Options specific to the `xprt set` sub-command
+.TP
+.B \-\-dstaddr \fIdstaddr
+Change the destination address of this specific transport to
+.TP
+.B \-\-offline
+Change the transport state from online to offline
+.TP
+.B \-\-online
+Change the transport state from offline to online
+.TP
+.B \-\-remove
+Removes the transport from the xprt-switch. Note that "main" transports cannot be removed.
+.SH DIRECTORY
+.TP
+.B /sys/kernel/sunrpc/
+.SH AUTHOR
+Anna Schumaker <Anna.Schumaker@Netapp.com>
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v3 9/9] nfssysfs: Add installation to the Makefile
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (7 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 8/9] nfssysfs: Add a man page schumaker.anna
@ 2021-08-30 15:56 ` schumaker.anna
  2021-08-31 12:26 ` [PATCH v3 0/9] Add a tool for using the new sysfs files Benjamin Coddington
  9 siblings, 0 replies; 11+ messages in thread
From: schumaker.anna @ 2021-08-30 15:56 UTC (permalink / raw)
  To: steved, linux-nfs; +Cc: Anna.Schumaker

From: Anna Schumaker <Anna.Schumaker@Netapp.com>

And create a shell script that launches the python program from the
$(libdir)

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
---
 configure.ac               |  1 +
 tools/Makefile.am          |  2 +-
 tools/nfssysfs/Makefile.am | 20 ++++++++++++++++++++
 tools/nfssysfs/nfssysfs    |  5 +++++
 4 files changed, 27 insertions(+), 1 deletion(-)
 create mode 100644 tools/nfssysfs/Makefile.am
 create mode 100644 tools/nfssysfs/nfssysfs

diff --git a/configure.ac b/configure.ac
index bc2d0f02979c..57ad341948a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -731,6 +731,7 @@ AC_CONFIG_FILES([
 	tools/rpcgen/Makefile
 	tools/mountstats/Makefile
 	tools/nfs-iostat/Makefile
+	tools/nfssysfs/Makefile
 	tools/nfsdclnts/Makefile
 	tools/nfsconf/Makefile
 	tools/nfsdclddb/Makefile
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 9b4b0803db39..12c68b57b8ae 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
 OPTDIRS += nfsdclddb
 endif
 
-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts $(OPTDIRS)
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfssysfs nfsdclnts $(OPTDIRS)
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/tools/nfssysfs/Makefile.am b/tools/nfssysfs/Makefile.am
new file mode 100644
index 000000000000..983b128f5c98
--- /dev/null
+++ b/tools/nfssysfs/Makefile.am
@@ -0,0 +1,20 @@
+## Process this file with automake to produce Makefile.in
+PYTHON_FILES =  nfssysfs.py client.py switch.py sysfs.py xprt.py
+tooldir = $(DESTDIR)$(libdir)/nfssysfs
+
+man8_MANS = nfssysfs.man
+
+all-local: $(PYTHON_FILES)
+
+install-data-hook:
+	mkdir -p $(tooldir)
+	for f in $(PYTHON_FILES) ; do \
+		$(INSTALL) -m 644 $$f $(tooldir)/$$f ; \
+	done
+	chmod +x $(tooldir)/nfssysfs.py
+	$(INSTALL) -m 755 nfssysfs $(DESTDIR)$(sbindir)/nfssysfs
+	sed -i "s|LIBDIR=.|LIBDIR=$(tooldir)|" $(DESTDIR)$(sbindir)/nfssysfs
+
+
+
+MAINTAINERCLEANFILES=Makefile.in
diff --git a/tools/nfssysfs/nfssysfs b/tools/nfssysfs/nfssysfs
new file mode 100644
index 000000000000..82dd2da6f539
--- /dev/null
+++ b/tools/nfssysfs/nfssysfs
@@ -0,0 +1,5 @@
+#!/bin/bash
+LIBDIR=.
+PYTHON3=/usr/bin/python
+
+exec $PYTHON3 $LIBDIR/nfssysfs.py $*
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v3 0/9] Add a tool for using the new sysfs files
  2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (8 preceding siblings ...)
  2021-08-30 15:56 ` [PATCH v3 9/9] nfssysfs: Add installation to the Makefile schumaker.anna
@ 2021-08-31 12:26 ` Benjamin Coddington
  9 siblings, 0 replies; 11+ messages in thread
From: Benjamin Coddington @ 2021-08-31 12:26 UTC (permalink / raw)
  To: schumaker.anna; +Cc: steved, linux-nfs, Anna.Schumaker

On 30 Aug 2021, at 11:56, schumaker.anna@gmail.com wrote:

> From: Anna Schumaker <Anna.Schumaker@Netapp.com>
>
> okay, or would it be better to name it "nfs" with "sysfs" as a
> subcommand? Going with just "nfs" as the command name would allow us to
> add other non-sysfs tools as subcommands in the future (such as `nfs stat`
> to call `nfsstat`, or for new commands that would otherwise be prefixed
> with "nfs")
>
> Thoughts?

I'm in favor of having a top-level nfs command tree for tools and
administrators, and even dropping the intermediate "sysfs" bit for these
subcommands.  I'd like to use `nfs xprt` and `nfs rpc-client`..etc.  I think
that the intermediate 'sysfs' is unnecessary.

If I can ever get around to completing it, I have some work for displaying
mount to xprt relationships and forcibly unmounting for unavailable servers
where I would like to use `nfs shutdown` or some variation.

Ben


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-08-31 12:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-30 15:56 [PATCH v3 0/9] Add a tool for using the new sysfs files schumaker.anna
2021-08-30 15:56 ` [PATCH v3 1/9] nfssysfs: Add a nfssysfs.py tool schumaker.anna
2021-08-30 15:56 ` [PATCH v3 2/9] nfssysfs.py: Add a command for printing xprt switch information schumaker.anna
2021-08-30 15:56 ` [PATCH v3 3/9] nfssysfs.py: Add a command for printing individual xprts schumaker.anna
2021-08-30 15:56 ` [PATCH v3 4/9] nfssysfs.py: Add a command for printing rpc-client information schumaker.anna
2021-08-30 15:56 ` [PATCH v3 5/9] nfssysfs.py: Add a command for changing xprt dstaddr schumaker.anna
2021-08-30 15:56 ` [PATCH v3 6/9] nfssysfs.py: Add a command for changing xprt-switch dstaddrs schumaker.anna
2021-08-30 15:56 ` [PATCH v3 7/9] nfssysfs.py: Add a command for changing xprt state schumaker.anna
2021-08-30 15:56 ` [PATCH v3 8/9] nfssysfs: Add a man page schumaker.anna
2021-08-30 15:56 ` [PATCH v3 9/9] nfssysfs: Add installation to the Makefile schumaker.anna
2021-08-31 12:26 ` [PATCH v3 0/9] Add a tool for using the new sysfs files Benjamin Coddington

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.