All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/9] Add a tool for using the new sysfs files
@ 2022-01-27 19:49 schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool schumaker.anna
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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!

The following subcommands are implemented:
	rpcctl client
 	rpcctl switch
 	rpcctl switch set
 	rpcctl xprt
 	rpcctl xprt set

So you can print out information about every switch with:
	anna@client ~ % rpcctl switch
	switch 0: xprts 1, active 1, queue 0
		xprt 0: local, /var/run/gssproxy.sock [main]
	switch 1: xprts 1, active 1, queue 0
		xprt 1: local, /var/run/rpcbind.sock [main]
	switch 2: xprts 1, active 1, queue 0
		xprt 2: tcp, 192.168.111.1 [main]
	switch 3: xprts 4, active 4, queue 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 ~ % rpcctl xprt
	xprt 0: local, /var/run/gssproxy.sock, port 0, state <CONNECTED,BOUND>, main
		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 <CONNECTED,BOUND>, main
		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 <CONNECTED,BOUND>, main
		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 <CONNECTED,BOUND>, main
		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 rpcctl 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 rpcctl 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 % rpcctl switch --id 3
	switch 3: xprts 4, active 4, queue 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 rpcctl switch set --id 4 --dstaddr server2.nowheycreamery.vm
	switch 3: xprts 4, active 4, queue 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

Changes in v7:
- Fix up detecting if sysfs is mounted

Thoughts?
Anna


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

 configure.ac             |   1 +
 tools/Makefile.am        |   2 +-
 tools/rpcctl/Makefile.am |  13 +++
 tools/rpcctl/rpcctl.man  |  88 +++++++++++++++
 tools/rpcctl/rpcctl.py   | 230 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 333 insertions(+), 1 deletion(-)
 create mode 100644 tools/rpcctl/Makefile.am
 create mode 100644 tools/rpcctl/rpcctl.man
 create mode 100755 tools/rpcctl/rpcctl.py

-- 
2.35.0


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

* [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-02-01 15:57   ` David Wysochanski
  2022-01-27 19:49 ` [PATCH v7 2/9] rpcctl: Add a command for printing xprt switch information schumaker.anna
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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>
--
v7: Check entire line for "sysfs" instead of just the start of the line
---
 tools/rpcctl/rpcctl.py | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100755 tools/rpcctl/rpcctl.py

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
new file mode 100755
index 000000000000..9737ac4a9740
--- /dev/null
+++ b/tools/rpcctl/rpcctl.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python3
+import argparse
+import pathlib
+import sys
+
+with open("/proc/mounts", 'r') as f:
+    mount = [ line.split()[1] for line in f if "sysfs" in line ]
+    if len(mount) == 0:
+        print("ERROR: sysfs is not mounted")
+        sys.exit(1)
+
+sunrpc = pathlib.Path(mount[0]) / "kernel" / "sunrpc"
+if not sunrpc.is_dir():
+    print("ERROR: sysfs does not have sunrpc directory")
+    sys.exit(1)
+
+parser = argparse.ArgumentParser()
+
+def show_small_help(args):
+    parser.print_usage()
+    print("sunrpc dir:", sunrpc)
+parser.set_defaults(func=show_small_help)
+
+args = parser.parse_args()
+args.func(args)
-- 
2.35.0


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

* [PATCH v7 2/9] rpcctl: Add a command for printing xprt switch information
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 3/9] rpcctl: Add a command for printing individual xprts schumaker.anna
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/rpcctl.py | 68 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index 9737ac4a9740..0d922f1acf21 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python3
 import argparse
+import collections
 import pathlib
 import sys
 
@@ -14,6 +15,70 @@ if not sunrpc.is_dir():
     print("ERROR: sysfs does not have sunrpc directory")
     sys.exit(1)
 
+def read_addr_file(path):
+    try:
+        with open(path, 'r') as f:
+            return f.readline().strip()
+    except:
+        return "(enoent)"
+
+def read_info_file(path):
+    res = collections.defaultdict(int)
+    try:
+        with open(path) as info:
+            lines = [ l.split("=", 1) for l in info if "=" in l ]
+            res.update({ key:int(val.strip()) for (key, val) in lines })
+    finally:
+        return res
+
+
+class Xprt:
+    def __init__(self, path):
+        self.path = path
+        self.id = int(path.stem.split("-")[1])
+        self.type = path.stem.split("-")[2]
+        self.dstaddr = read_addr_file(path / "dstaddr")
+
+    def __lt__(self, rhs):
+        return self.id < rhs.id
+
+    def small_str(self):
+        return f"xprt {self.id}: {self.type}, {self.dstaddr}"
+
+
+class XprtSwitch:
+    def __init__(self, path):
+        self.path = path
+        self.id = int(path.stem.split("-")[1])
+        self.info = read_info_file(path / "xprt_switch_info")
+
+        self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
+        self.xprts.sort()
+
+    def __lt__(self, rhs):
+        return self.id < rhs.id
+
+    def __str__(self):
+        switch =  f"switch {self.id}: " \
+                  f"xprts {self.info['num_xprts']}, " \
+                  f"active {self.info['num_active']}, " \
+                  f"queue {self.info['queue_len']}"
+        xprts = [ f"	{x.small_str()}" for x in self.xprts ]
+        return "\n".join([ switch ] + xprts)
+
+    def add_command(subparser):
+        parser = subparser.add_parser("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=XprtSwitch.list_all)
+
+    def list_all(args):
+        switches = [ XprtSwitch(f) for f in (sunrpc / "xprt-switches").iterdir() ]
+        switches.sort()
+        for xs in switches:
+            if args.id == None or xs.id == args.id[0]:
+                print(xs)
+
+
 parser = argparse.ArgumentParser()
 
 def show_small_help(args):
@@ -21,5 +86,8 @@ def show_small_help(args):
     print("sunrpc dir:", sunrpc)
 parser.set_defaults(func=show_small_help)
 
+subparser = parser.add_subparsers(title="commands")
+XprtSwitch.add_command(subparser)
+
 args = parser.parse_args()
 args.func(args)
-- 
2.35.0


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

* [PATCH v7 3/9] rpcctl: Add a command for printing individual xprts
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 2/9] rpcctl: Add a command for printing xprt switch information schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 4/9] rpcctl: Add a command for printing rpc client information schumaker.anna
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/rpcctl.py | 43 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index 0d922f1acf21..b5092e39d336 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -37,13 +37,53 @@ class Xprt:
         self.path = path
         self.id = int(path.stem.split("-")[1])
         self.type = path.stem.split("-")[2]
+        self.info = read_info_file(path / "xprt_info")
         self.dstaddr = read_addr_file(path / "dstaddr")
+        self.srcaddr = read_addr_file(path / "srcaddr")
+
+        with open(path / "xprt_state") as f:
+            self.state = ','.join(f.readline().split()[1:])
 
     def __lt__(self, rhs):
         return self.id < rhs.id
 
+    def _xprt(self):
+        main = ", main" if self.info.get("main_xprt") else ""
+        return f"xprt {self.id}: {self.type}, {self.dstaddr}, " \
+               f"port {self.info['dst_port']}, state <{self.state}>{main}"
+
+    def _src_reqs(self):
+        return f"	Source: {self.srcaddr}, port {self.info['src_port']}, " \
+               f"Requests: {self.info['num_reqs']}"
+
+    def _cong_slots(self):
+        return f"	Congestion: cur {self.info['cur_cong']}, win {self.info['cong_win']}, " \
+               f"Slots: min {self.info['min_num_slots']}, max {self.info['max_num_slots']}"
+
+    def _queues(self):
+        return f"	Queues: binding {self.info['binding_q_len']}, " \
+               f"sending {self.info['sending_q_len']}, pending {self.info['pending_q_len']}, " \
+               f"backlog {self.info['backlog_q_len']}, tasks {self.info['tasks_queuelen']}"
+
+    def __str__(self):
+        return "\n".join([self._xprt(), self._src_reqs(),
+                          self._cong_slots(), self._queues() ])
+
     def small_str(self):
-        return f"xprt {self.id}: {self.type}, {self.dstaddr}"
+        main = " [main]" if self.info.get("main_xprt") else ""
+        return f"xprt {self.id}: {self.type}, {self.dstaddr}{main}"
+
+    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=Xprt.list_all)
+
+    def list_all(args):
+        xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
+        xprts.sort()
+        for xprt in xprts:
+            if args.id == None or xprt.id == args.id[0]:
+                print(xprt)
 
 
 class XprtSwitch:
@@ -88,6 +128,7 @@ parser.set_defaults(func=show_small_help)
 
 subparser = parser.add_subparsers(title="commands")
 XprtSwitch.add_command(subparser)
+Xprt.add_command(subparser)
 
 args = parser.parse_args()
 args.func(args)
-- 
2.35.0


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

* [PATCH v7 4/9] rpcctl: Add a command for printing rpc client information
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (2 preceding siblings ...)
  2022-01-27 19:49 ` [PATCH v7 3/9] rpcctl: Add a command for printing individual xprts schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 5/9] rpcctl: Add a command for changing xprt dstaddr schumaker.anna
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/rpcctl.py | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index b5092e39d336..bdb56d1f5476 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -87,10 +87,11 @@ class Xprt:
 
 
 class XprtSwitch:
-    def __init__(self, path):
+    def __init__(self, path, sep=":"):
         self.path = path
         self.id = int(path.stem.split("-")[1])
         self.info = read_info_file(path / "xprt_switch_info")
+        self.sep = sep
 
         self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
         self.xprts.sort()
@@ -99,7 +100,7 @@ class XprtSwitch:
         return self.id < rhs.id
 
     def __str__(self):
-        switch =  f"switch {self.id}: " \
+        switch =  f"switch {self.id}{self.sep} " \
                   f"xprts {self.info['num_xprts']}, " \
                   f"active {self.info['num_active']}, " \
                   f"queue {self.info['queue_len']}"
@@ -119,6 +120,32 @@ class XprtSwitch:
                 print(xs)
 
 
+class RpcClient:
+    def __init__(self, path):
+        self.path = path
+        self.id = int(path.stem.split("-")[1])
+        self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
+
+    def __lt__(self, rhs):
+        return self.id < rhs.id
+
+    def __str__(self):
+        return f"client {self.id}: {self.switch}"
+
+    def add_command(subparser):
+        parser = subparser.add_parser("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=RpcClient.list_all)
+
+    def list_all(args):
+        clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
+        clients.sort()
+        for client in clients:
+            if args.id == None or client.id == args.id[0]:
+                print(client)
+
+
+
 parser = argparse.ArgumentParser()
 
 def show_small_help(args):
@@ -127,6 +154,7 @@ def show_small_help(args):
 parser.set_defaults(func=show_small_help)
 
 subparser = parser.add_subparsers(title="commands")
+RpcClient.add_command(subparser)
 XprtSwitch.add_command(subparser)
 Xprt.add_command(subparser)
 
-- 
2.35.0


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

* [PATCH v7 5/9] rpcctl: Add a command for changing xprt dstaddr
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (3 preceding siblings ...)
  2022-01-27 19:49 ` [PATCH v7 4/9] rpcctl: Add a command for printing rpc client information schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 6/9] rpcctl: Add a command for changing xprt switch dstaddrs schumaker.anna
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/rpcctl.py | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index bdb56d1f5476..c481f96333f9 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -2,6 +2,7 @@
 import argparse
 import collections
 import pathlib
+import socket
 import sys
 
 with open("/proc/mounts", 'r') as f:
@@ -22,6 +23,11 @@ def read_addr_file(path):
     except:
         return "(enoent)"
 
+def write_addr_file(path, newaddr):
+    with open(path, 'w') as f:
+        f.write(newaddr)
+    return read_addr_file(path)
+
 def read_info_file(path):
     res = collections.defaultdict(int)
     try:
@@ -73,11 +79,21 @@ class Xprt:
         main = " [main]" if self.info.get("main_xprt") else ""
         return f"xprt {self.id}: {self.type}, {self.dstaddr}{main}"
 
+    def set_dstaddr(self, newaddr):
+        resolved = socket.gethostbyname(newaddr)
+        self.dstaddr = write_addr_file(self.path / "dstaddr", resolved)
+
     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=Xprt.list_all)
 
+        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=Xprt.set_property)
+
     def list_all(args):
         xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
         xprts.sort()
@@ -85,6 +101,21 @@ class Xprt:
             if args.id == None or xprt.id == args.id[0]:
                 print(xprt)
 
+    def get_by_id(id):
+        xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
+        for xprt in xprts:
+            if xprt.id == id:
+                return xprt
+
+    def set_property(args):
+        xprt = Xprt.get_by_id(args.id[0])
+        try:
+            if args.dstaddr != None:
+                xprt.set_dstaddr(args.dstaddr[0])
+            print(xprt)
+        except Exception as e:
+            print(e)
+
 
 class XprtSwitch:
     def __init__(self, path, sep=":"):
-- 
2.35.0


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

* [PATCH v7 6/9] rpcctl: Add a command for changing xprt switch dstaddrs
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (4 preceding siblings ...)
  2022-01-27 19:49 ` [PATCH v7 5/9] rpcctl: Add a command for changing xprt dstaddr schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 7/9] rpcctl: Add a command for changing xprt state schumaker.anna
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/rpcctl.py | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index c481f96333f9..9404b975e33d 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -143,6 +143,12 @@ class XprtSwitch:
         parser.add_argument("--id", metavar="ID", nargs=1, type=int, help="Id of a specific xprt-switch to show")
         parser.set_defaults(func=XprtSwitch.list_all)
 
+        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=XprtSwitch.set_property)
+
     def list_all(args):
         switches = [ XprtSwitch(f) for f in (sunrpc / "xprt-switches").iterdir() ]
         switches.sort()
@@ -150,6 +156,16 @@ class XprtSwitch:
             if args.id == None or xs.id == args.id[0]:
                 print(xs)
 
+    def set_property(args):
+        switch = XprtSwitch(sunrpc / "xprt-switches" / f"switch-{args.id[0]}")
+        try:
+            for xprt in switch.xprts:
+                if args.dstaddr != None:
+                    xprt.set_dstaddr(args.dstaddr[0])
+            print(switch)
+        except Exception as e:
+            print(e)
+
 
 class RpcClient:
     def __init__(self, path):
-- 
2.35.0


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

* [PATCH v7 7/9] rpcctl: Add a command for changing xprt state
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (5 preceding siblings ...)
  2022-01-27 19:49 ` [PATCH v7 6/9] rpcctl: Add a command for changing xprt switch dstaddrs schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 8/9] rpcctl: Add a man page schumaker.anna
  2022-01-27 19:49 ` [PATCH v7 9/9] rpcctl: Add installation to the Makefile schumaker.anna
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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>
---
 tools/rpcctl/rpcctl.py | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
index 9404b975e33d..0771c4e0d0b1 100755
--- a/tools/rpcctl/rpcctl.py
+++ b/tools/rpcctl/rpcctl.py
@@ -46,9 +46,7 @@ class Xprt:
         self.info = read_info_file(path / "xprt_info")
         self.dstaddr = read_addr_file(path / "dstaddr")
         self.srcaddr = read_addr_file(path / "srcaddr")
-
-        with open(path / "xprt_state") as f:
-            self.state = ','.join(f.readline().split()[1:])
+        self.read_state()
 
     def __lt__(self, rhs):
         return self.id < rhs.id
@@ -72,9 +70,16 @@ class Xprt:
                f"backlog {self.info['backlog_q_len']}, tasks {self.info['tasks_queuelen']}"
 
     def __str__(self):
+        if not self.path.exists():
+            return f"xprt {self.id}: has been removed"
         return "\n".join([self._xprt(), self._src_reqs(),
                           self._cong_slots(), self._queues() ])
 
+    def read_state(self):
+        if self.path.exists():
+            with open(self.path / "xprt_state") as f:
+                self.state = ','.join(f.readline().split()[1:])
+
     def small_str(self):
         main = " [main]" if self.info.get("main_xprt") else ""
         return f"xprt {self.id}: {self.type}, {self.dstaddr}{main}"
@@ -83,6 +88,11 @@ class Xprt:
         resolved = socket.gethostbyname(newaddr)
         self.dstaddr = write_addr_file(self.path / "dstaddr", resolved)
 
+    def set_state(self, state):
+        with open(self.path / "xprt_state", 'w') as f:
+            f.write(state)
+        self.read_state()
+
     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")
@@ -92,6 +102,10 @@ class Xprt:
         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=Xprt.set_property)
 
     def list_all(args):
@@ -112,6 +126,13 @@ class Xprt:
         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)
-- 
2.35.0


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

* [PATCH v7 8/9] rpcctl: Add a man page
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (6 preceding siblings ...)
  2022-01-27 19:49 ` [PATCH v7 7/9] rpcctl: Add a command for changing xprt state schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  2022-02-07 19:58   ` Steve Dickson
  2022-01-27 19:49 ` [PATCH v7 9/9] rpcctl: Add installation to the Makefile schumaker.anna
  8 siblings, 1 reply; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/rpcctl.man | 88 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 tools/rpcctl/rpcctl.man

diff --git a/tools/rpcctl/rpcctl.man b/tools/rpcctl/rpcctl.man
new file mode 100644
index 000000000000..e4dd53ac8531
--- /dev/null
+++ b/tools/rpcctl/rpcctl.man
@@ -0,0 +1,88 @@
+.\"
+.\" rpcctl(8)
+.\"
+.TH rpcctl 8 "25 Jan 2022"
+.SH NAME
+rpcctl \- Displays SunRPC connection information
+.SH SYNOPSIS
+.B rpcctl
+.RB [ \-h | \-\-help ]
+.P
+.B rpcctl client
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.P
+.B rpcctl switch
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.P
+.B rpcctl switch set
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.RB [ \--dstaddr
+.IR dstaddr]
+.P
+.B rpcctl xprt
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.P
+.B rpcctl xprt set
+.RB [ \-h | \-\-help ]
+.RB [ \--id
+.IR ID ]
+.RB [ \--dstaddr
+.IR dstaddr]
+.RB [ --offline ]
+.RB [ --online ]
+.RB [ --remove ]
+.P
+.SH DESCRIPTION
+.RB "The " rpcctl " command displays information collected in the SunRPC sysfs files about the system's SunRPC objects.
+.P
+.SS Objects
+Valid
+.BR rpcctl (8)
+objects are:
+.IP "\fBclient\fP"
+Display information about this system's RPC clients.
+.IP "\fBswitch\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 `switch set` sub-command
+.TP
+.B \-\-dstaddr \fIdstaddr
+Change the destination address of all transports in the 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 switch. Note that "main" transports cannot be removed.
+.SH DIRECTORY
+.TP
+.B /sys/kernel/sunrpc/
+.SH AUTHOR
+Anna Schumaker <Anna.Schumaker@Netapp.com>
-- 
2.35.0


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

* [PATCH v7 9/9] rpcctl: Add installation to the Makefile
  2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
                   ` (7 preceding siblings ...)
  2022-01-27 19:49 ` [PATCH v7 8/9] rpcctl: Add a man page schumaker.anna
@ 2022-01-27 19:49 ` schumaker.anna
  8 siblings, 0 replies; 14+ messages in thread
From: schumaker.anna @ 2022-01-27 19:49 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/rpcctl/Makefile.am | 13 +++++++++++++
 3 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 tools/rpcctl/Makefile.am

diff --git a/configure.ac b/configure.ac
index 93626d62be40..dcd3be0c8a8b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -737,6 +737,7 @@ AC_CONFIG_FILES([
 	tools/rpcgen/Makefile
 	tools/mountstats/Makefile
 	tools/nfs-iostat/Makefile
+	tools/rpcctl/Makefile
 	tools/nfsdclnts/Makefile
 	tools/nfsconf/Makefile
 	tools/nfsdclddb/Makefile
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 9b4b0803db39..c3feabbec681 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 rpcctl nfsdclnts $(OPTDIRS)
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/tools/rpcctl/Makefile.am b/tools/rpcctl/Makefile.am
new file mode 100644
index 000000000000..33fb431fe7d4
--- /dev/null
+++ b/tools/rpcctl/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to produce Makefile.in
+PYTHON_FILES =  rpcctl.py
+
+man8_MANS = rpcctl.man
+
+EXTRA_DIST = $(man8_MANS) $(PYTHON_FILES)
+
+all-local: $(PYTHON_FILES)
+
+install-data-hook:
+	$(INSTALL) -m 755 rpcctl.py $(DESTDIR)$(sbindir)/rpcctl
+
+MAINTAINERCLEANFILES=Makefile.in
-- 
2.35.0


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

* Re: [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool
  2022-01-27 19:49 ` [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool schumaker.anna
@ 2022-02-01 15:57   ` David Wysochanski
  2022-02-02 15:33     ` Steve Dickson
  0 siblings, 1 reply; 14+ messages in thread
From: David Wysochanski @ 2022-02-01 15:57 UTC (permalink / raw)
  To: schumaker.anna; +Cc: Dickson, Steve, linux-nfs, Anna Schumaker

On Thu, Jan 27, 2022 at 2:50 PM <schumaker.anna@gmail.com> wrote:
>
> 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>
> --
> v7: Check entire line for "sysfs" instead of just the start of the line
> ---
>  tools/rpcctl/rpcctl.py | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>  create mode 100755 tools/rpcctl/rpcctl.py
>
> diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
> new file mode 100755
> index 000000000000..9737ac4a9740
> --- /dev/null
> +++ b/tools/rpcctl/rpcctl.py
> @@ -0,0 +1,25 @@
> +#!/usr/bin/python3
> +import argparse
> +import pathlib
> +import sys
> +
> +with open("/proc/mounts", 'r') as f:
> +    mount = [ line.split()[1] for line in f if "sysfs" in line ]
> +    if len(mount) == 0:
> +        print("ERROR: sysfs is not mounted")
> +        sys.exit(1)
> +
> +sunrpc = pathlib.Path(mount[0]) / "kernel" / "sunrpc"
> +if not sunrpc.is_dir():
> +    print("ERROR: sysfs does not have sunrpc directory")
> +    sys.exit(1)
> +
> +parser = argparse.ArgumentParser()
> +
> +def show_small_help(args):
> +    parser.print_usage()
> +    print("sunrpc dir:", sunrpc)
> +parser.set_defaults(func=show_small_help)
> +
> +args = parser.parse_args()
> +args.func(args)
> --
> 2.35.0
>

Might want to rework some of the directory related code to ensure you
handle disappearing entries.  Got Tracebacks (see below) while running
a series of tests that would:
- mount
- run some IO
- umount


[root@dwysocha-fedora-node1 nfs-utils]# while true; do
./tools/rpcctl/rpcctl.py xprt; done | grep -B 5 -A 5 Traceback
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in list_all
    xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in <listcomp>
    xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
  File "/usr/lib64/python3.10/pathlib.py", line 1032, in glob
    for p in selector.select_from(self):
  File "/usr/lib64/python3.10/pathlib.py", line 492, in _select_from
    for starting_point in self._iterate_directories(parent_path,
is_dir, scandir):
  File "/usr/lib64/python3.10/pathlib.py", line 482, in _iterate_directories
    for p in self._iterate_directories(path, is_dir, scandir):
  File "/usr/lib64/python3.10/pathlib.py", line 471, in _iterate_directories
    with scandir(parent_path) as scandir_it:
FileNotFoundError: [Errno 2] No such file or directory:
'/sys/kernel/sunrpc/xprt-switches/switch-4'
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in list_all
    xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in <listcomp>
    xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
  File "/usr/lib64/python3.10/pathlib.py", line 1032, in glob
    for p in selector.select_from(self):
  File "/usr/lib64/python3.10/pathlib.py", line 492, in _select_from
    for starting_point in self._iterate_directories(parent_path,
is_dir, scandir):
  File "/usr/lib64/python3.10/pathlib.py", line 482, in _iterate_directories
    for p in self._iterate_directories(path, is_dir, scandir):
  File "/usr/lib64/python3.10/pathlib.py", line 471, in _iterate_directories
    with scandir(parent_path) as scandir_it:
FileNotFoundError: [Errno 2] No such file or directory:
'/sys/kernel/sunrpc/xprt-switches/switch-2'




[root@dwysocha-fedora-node1 nfs-utils]# while true; do
./tools/rpcctl/rpcctl.py client; done | grep -B 10 -A 10 Traceback
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
    self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
  File "/usr/lib64/python3.10/pathlib.py", line 1159, in readlink
    path = self._accessor.readlink(self)
FileNotFoundError: [Errno 2] No such file or directory:
'/sys/kernel/sunrpc/rpc-clients/clnt-3/switch'
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
    self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
  File "/usr/lib64/python3.10/pathlib.py", line 1159, in readlink
    path = self._accessor.readlink(self)
FileNotFoundError: [Errno 2] No such file or directory:
'/sys/kernel/sunrpc/rpc-clients/clnt-7/switch'
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
    self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in __init__
    self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in <listcomp>
    self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 49, in __init__
    self.read_state()
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 81, in read_state
    self.state = ','.join(f.readline().split()[1:])
OSError: [Errno 19] No such device
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
    self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in __init__
    self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in <listcomp>
    self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
  File "/usr/lib64/python3.10/pathlib.py", line 1015, in iterdir
    for name in self._accessor.listdir(self):
FileNotFoundError: [Errno 2] No such file or directory:
'/sys/kernel/sunrpc/rpc-clients/clnt-9/../../xprt-switches/switch-2'
Traceback (most recent call last):
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
    args.func(args)
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
    clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
  File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
    self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
  File "/usr/lib64/python3.10/pathlib.py", line 1159, in readlink
    path = self._accessor.readlink(self)
FileNotFoundError: [Errno 2] No such file or directory:
'/sys/kernel/sunrpc/rpc-clients/clnt-5/switch'
^C


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

* Re: [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool
  2022-02-01 15:57   ` David Wysochanski
@ 2022-02-02 15:33     ` Steve Dickson
  0 siblings, 0 replies; 14+ messages in thread
From: Steve Dickson @ 2022-02-02 15:33 UTC (permalink / raw)
  To: David Wysochanski, schumaker.anna; +Cc: linux-nfs, Anna Schumaker

Hey Dave!

On 2/1/22 10:57, David Wysochanski wrote:
> On Thu, Jan 27, 2022 at 2:50 PM <schumaker.anna@gmail.com> wrote:
> 
> Might want to rework some of the directory related code to ensure you
> handle disappearing entries.  Got Tracebacks (see below) while running
> a series of tests that would:
> - mount
> - run some IO
> - umount
I guess I'm curious what your exception is...

Shouldn't rpcctl fail after a umount or is your
concern about how the command is failing?

steved.
> 
> 
> [root@dwysocha-fedora-node1 nfs-utils]# while true; do
> ./tools/rpcctl/rpcctl.py xprt; done | grep -B 5 -A 5 Traceback
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in list_all
>      xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in <listcomp>
>      xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
>    File "/usr/lib64/python3.10/pathlib.py", line 1032, in glob
>      for p in selector.select_from(self):
>    File "/usr/lib64/python3.10/pathlib.py", line 492, in _select_from
>      for starting_point in self._iterate_directories(parent_path,
> is_dir, scandir):
>    File "/usr/lib64/python3.10/pathlib.py", line 482, in _iterate_directories
>      for p in self._iterate_directories(path, is_dir, scandir):
>    File "/usr/lib64/python3.10/pathlib.py", line 471, in _iterate_directories
>      with scandir(parent_path) as scandir_it:
> FileNotFoundError: [Errno 2] No such file or directory:
> '/sys/kernel/sunrpc/xprt-switches/switch-4'
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in list_all
>      xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 112, in <listcomp>
>      xprts = [ Xprt(f) for f in (sunrpc / "xprt-switches").glob("**/xprt-*") ]
>    File "/usr/lib64/python3.10/pathlib.py", line 1032, in glob
>      for p in selector.select_from(self):
>    File "/usr/lib64/python3.10/pathlib.py", line 492, in _select_from
>      for starting_point in self._iterate_directories(parent_path,
> is_dir, scandir):
>    File "/usr/lib64/python3.10/pathlib.py", line 482, in _iterate_directories
>      for p in self._iterate_directories(path, is_dir, scandir):
>    File "/usr/lib64/python3.10/pathlib.py", line 471, in _iterate_directories
>      with scandir(parent_path) as scandir_it:
> FileNotFoundError: [Errno 2] No such file or directory:
> '/sys/kernel/sunrpc/xprt-switches/switch-2'
> 
> 
> 
> 
> [root@dwysocha-fedora-node1 nfs-utils]# while true; do
> ./tools/rpcctl/rpcctl.py client; done | grep -B 10 -A 10 Traceback
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
>      self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
>    File "/usr/lib64/python3.10/pathlib.py", line 1159, in readlink
>      path = self._accessor.readlink(self)
> FileNotFoundError: [Errno 2] No such file or directory:
> '/sys/kernel/sunrpc/rpc-clients/clnt-3/switch'
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
>      self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
>    File "/usr/lib64/python3.10/pathlib.py", line 1159, in readlink
>      path = self._accessor.readlink(self)
> FileNotFoundError: [Errno 2] No such file or directory:
> '/sys/kernel/sunrpc/rpc-clients/clnt-7/switch'
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
>      self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in __init__
>      self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in <listcomp>
>      self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 49, in __init__
>      self.read_state()
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 81, in read_state
>      self.state = ','.join(f.readline().split()[1:])
> OSError: [Errno 19] No such device
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
>      self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in __init__
>      self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 148, in <listcomp>
>      self.xprts = [ Xprt(p) for p in self.path.iterdir() if p.is_dir() ]
>    File "/usr/lib64/python3.10/pathlib.py", line 1015, in iterdir
>      for name in self._accessor.listdir(self):
> FileNotFoundError: [Errno 2] No such file or directory:
> '/sys/kernel/sunrpc/rpc-clients/clnt-9/../../xprt-switches/switch-2'
> Traceback (most recent call last):
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 230, in <module>
>      args.func(args)
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in list_all
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 209, in <listcomp>
>      clients = [ RpcClient(f) for f in (sunrpc / "rpc-clients").iterdir() ]
>    File "/mnt/build/nfs-utils/./tools/rpcctl/rpcctl.py", line 195, in __init__
>      self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
>    File "/usr/lib64/python3.10/pathlib.py", line 1159, in readlink
>      path = self._accessor.readlink(self)
> FileNotFoundError: [Errno 2] No such file or directory:
> '/sys/kernel/sunrpc/rpc-clients/clnt-5/switch'
> ^C
> 


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

* Re: [PATCH v7 8/9] rpcctl: Add a man page
  2022-01-27 19:49 ` [PATCH v7 8/9] rpcctl: Add a man page schumaker.anna
@ 2022-02-07 19:58   ` Steve Dickson
  2022-02-07 20:32     ` Anna Schumaker
  0 siblings, 1 reply; 14+ messages in thread
From: Steve Dickson @ 2022-02-07 19:58 UTC (permalink / raw)
  To: schumaker.anna, linux-nfs; +Cc: Anna.Schumaker

Hey Anna!

On 1/27/22 2:49 PM, schumaker.anna@gmail.com wrote:
> From: Anna Schumaker <Anna.Schumaker@Netapp.com>
> 
> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
> ---
>   tools/rpcctl/rpcctl.man | 88 +++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 88 insertions(+)
>   create mode 100644 tools/rpcctl/rpcctl.man
> 
> diff --git a/tools/rpcctl/rpcctl.man b/tools/rpcctl/rpcctl.man
> new file mode 100644
> index 000000000000..e4dd53ac8531
> --- /dev/null
> +++ b/tools/rpcctl/rpcctl.man
> @@ -0,0 +1,88 @@
> +.\"
> +.\" rpcctl(8)
> +.\"
> +.TH rpcctl 8 "25 Jan 2022"
> +.SH NAME
> +rpcctl \- Displays SunRPC connection information
> +.SH SYNOPSIS
> +.B rpcctl
> +.RB [ \-h | \-\-help ]
> +.P
> +.B rpcctl client
> +.RB [ \-h | \-\-help ]
> +.RB [ \--id
> +.IR ID ]
> +.P
> +.B rpcctl switch
> +.RB [ \-h | \-\-help ]
> +.RB [ \--id
> +.IR ID ]
> +.P
> +.B rpcctl switch set
> +.RB [ \-h | \-\-help ]
> +.RB [ \--id
> +.IR ID ]
> +.RB [ \--dstaddr
> +.IR dstaddr]
> +.P
> +.B rpcctl xprt
> +.RB [ \-h | \-\-help ]
> +.RB [ \--id
> +.IR ID ]
> +.P
> +.B rpcctl xprt set
> +.RB [ \-h | \-\-help ]
> +.RB [ \--id
> +.IR ID ]
> +.RB [ \--dstaddr
> +.IR dstaddr]
> +.RB [ --offline ]
> +.RB [ --online ]
> +.RB [ --remove ]
> +.P
> +.SH DESCRIPTION
> +.RB "The " rpcctl " command displays information collected in the SunRPC sysfs files about the system's SunRPC objects.
> +.P
> +.SS Objects
> +Valid
> +.BR rpcctl (8)
> +objects are:
> +.IP "\fBclient\fP"
> +Display information about this system's RPC clients.
> +.IP "\fBswitch\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 `switch set` sub-command
> +.TP
> +.B \-\-dstaddr \fIdstaddr
> +Change the destination address of all transports in the 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 switch. Note that "main" transports cannot be removed.
I got some feed back on this manpage....

They said would be useful to have examples on how to use
the objects... esp the switch set and xprt set ones.
I kinda agree...

steved.
> +.SH DIRECTORY
> +.TP
> +.B /sys/kernel/sunrpc/
> +.SH AUTHOR
> +Anna Schumaker <Anna.Schumaker@Netapp.com>


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

* Re: [PATCH v7 8/9] rpcctl: Add a man page
  2022-02-07 19:58   ` Steve Dickson
@ 2022-02-07 20:32     ` Anna Schumaker
  0 siblings, 0 replies; 14+ messages in thread
From: Anna Schumaker @ 2022-02-07 20:32 UTC (permalink / raw)
  To: Steve Dickson; +Cc: Linux NFS Mailing List, Schumaker Anna

On Mon, Feb 7, 2022 at 2:58 PM Steve Dickson <steved@redhat.com> wrote:
>
> Hey Anna!
>
> On 1/27/22 2:49 PM, schumaker.anna@gmail.com wrote:
> > From: Anna Schumaker <Anna.Schumaker@Netapp.com>
> >
> > Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
> > ---
> >   tools/rpcctl/rpcctl.man | 88 +++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 88 insertions(+)
> >   create mode 100644 tools/rpcctl/rpcctl.man
> >
> > diff --git a/tools/rpcctl/rpcctl.man b/tools/rpcctl/rpcctl.man
> > new file mode 100644
> > index 000000000000..e4dd53ac8531
> > --- /dev/null
> > +++ b/tools/rpcctl/rpcctl.man
> > @@ -0,0 +1,88 @@
> > +.\"
> > +.\" rpcctl(8)
> > +.\"
> > +.TH rpcctl 8 "25 Jan 2022"
> > +.SH NAME
> > +rpcctl \- Displays SunRPC connection information
> > +.SH SYNOPSIS
> > +.B rpcctl
> > +.RB [ \-h | \-\-help ]
> > +.P
> > +.B rpcctl client
> > +.RB [ \-h | \-\-help ]
> > +.RB [ \--id
> > +.IR ID ]
> > +.P
> > +.B rpcctl switch
> > +.RB [ \-h | \-\-help ]
> > +.RB [ \--id
> > +.IR ID ]
> > +.P
> > +.B rpcctl switch set
> > +.RB [ \-h | \-\-help ]
> > +.RB [ \--id
> > +.IR ID ]
> > +.RB [ \--dstaddr
> > +.IR dstaddr]
> > +.P
> > +.B rpcctl xprt
> > +.RB [ \-h | \-\-help ]
> > +.RB [ \--id
> > +.IR ID ]
> > +.P
> > +.B rpcctl xprt set
> > +.RB [ \-h | \-\-help ]
> > +.RB [ \--id
> > +.IR ID ]
> > +.RB [ \--dstaddr
> > +.IR dstaddr]
> > +.RB [ --offline ]
> > +.RB [ --online ]
> > +.RB [ --remove ]
> > +.P
> > +.SH DESCRIPTION
> > +.RB "The " rpcctl " command displays information collected in the SunRPC sysfs files about the system's SunRPC objects.
> > +.P
> > +.SS Objects
> > +Valid
> > +.BR rpcctl (8)
> > +objects are:
> > +.IP "\fBclient\fP"
> > +Display information about this system's RPC clients.
> > +.IP "\fBswitch\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 `switch set` sub-command
> > +.TP
> > +.B \-\-dstaddr \fIdstaddr
> > +Change the destination address of all transports in the 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 switch. Note that "main" transports cannot be removed.
> I got some feed back on this manpage....
>
> They said would be useful to have examples on how to use
> the objects... esp the switch set and xprt set ones.
> I kinda agree...

Okay, I can add that. I'll send out a new version with that and
anything Rahul finds once he checks back in after trying the tool with
the sysfs kernel fixes.

Anna

>
> steved.
> > +.SH DIRECTORY
> > +.TP
> > +.B /sys/kernel/sunrpc/
> > +.SH AUTHOR
> > +Anna Schumaker <Anna.Schumaker@Netapp.com>
>

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

end of thread, other threads:[~2022-02-07 20:48 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-27 19:49 [PATCH v7 0/9] Add a tool for using the new sysfs files schumaker.anna
2022-01-27 19:49 ` [PATCH v7 1/9] rpcctl: Add a rpcctl.py tool schumaker.anna
2022-02-01 15:57   ` David Wysochanski
2022-02-02 15:33     ` Steve Dickson
2022-01-27 19:49 ` [PATCH v7 2/9] rpcctl: Add a command for printing xprt switch information schumaker.anna
2022-01-27 19:49 ` [PATCH v7 3/9] rpcctl: Add a command for printing individual xprts schumaker.anna
2022-01-27 19:49 ` [PATCH v7 4/9] rpcctl: Add a command for printing rpc client information schumaker.anna
2022-01-27 19:49 ` [PATCH v7 5/9] rpcctl: Add a command for changing xprt dstaddr schumaker.anna
2022-01-27 19:49 ` [PATCH v7 6/9] rpcctl: Add a command for changing xprt switch dstaddrs schumaker.anna
2022-01-27 19:49 ` [PATCH v7 7/9] rpcctl: Add a command for changing xprt state schumaker.anna
2022-01-27 19:49 ` [PATCH v7 8/9] rpcctl: Add a man page schumaker.anna
2022-02-07 19:58   ` Steve Dickson
2022-02-07 20:32     ` Anna Schumaker
2022-01-27 19:49 ` [PATCH v7 9/9] rpcctl: Add installation to the Makefile schumaker.anna

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.