linux-nvme.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] nvmetcli: add support for NVMe passthru target
@ 2025-06-11 10:39 Nilay Shroff
  2025-06-16  4:28 ` Chaitanya Kulkarni
  0 siblings, 1 reply; 3+ messages in thread
From: Nilay Shroff @ 2025-06-11 10:39 UTC (permalink / raw)
  To: linux-nvme; +Cc: hch, gjoyce

This change adds the support for configuring NVMe passthru target.

Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
---
 nvmet/__init__.py |   2 +-
 nvmet/nvme.py     | 102 ++++++++++++++++++++++++++++++++++++++++++++++
 nvmetcli          |  77 ++++++++++++++++++++++++++++++++++
 3 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/nvmet/__init__.py b/nvmet/__init__.py
index cf172bd..5e2f525 100644
--- a/nvmet/__init__.py
+++ b/nvmet/__init__.py
@@ -1,2 +1,2 @@
-from .nvme import Root, Subsystem, Namespace, Port, Host, Referral, ANAGroup,\
+from .nvme import Root, Subsystem, Namespace, Port, Host, Referral, ANAGroup, Passthru, \
     DEFAULT_SAVE_FILE
diff --git a/nvmet/nvme.py b/nvmet/nvme.py
index 59efdb5..d462ea2 100644
--- a/nvmet/nvme.py
+++ b/nvmet/nvme.py
@@ -462,6 +462,13 @@ class Subsystem(CFSNode):
     namespaces = property(_list_namespaces,
                           doc="Get the list of Namespaces for the Subsystem.")
 
+    def _get_passthru(self):
+        self._check_self()
+        return Passthru(self)
+
+    passthru = property(_get_passthru,
+                        doc="Get the passthru node for the subsystem")
+
     def _list_allowed_hosts(self):
         return [os.path.basename(name)
                 for name in os.listdir("%s/allowed_hosts/" % self._path)]
@@ -510,6 +517,8 @@ class Subsystem(CFSNode):
             Namespace.setup(s, ns, err_func)
         for h in t.get('allowed_hosts', []):
             s.add_allowed_host(h)
+        for pt in t.get('passthru', []):
+            Passthru.setup(s, pt, err_func)
 
         s._setup_attrs(t, err_func)
 
@@ -518,6 +527,7 @@ class Subsystem(CFSNode):
         d['nqn'] = self.nqn
         d['namespaces'] = [ns.dump() for ns in self.namespaces]
         d['allowed_hosts'] = self.allowed_hosts
+        d['passthru'] = [self.passthru.dump()]
         return d
 
 
@@ -629,6 +639,98 @@ class Namespace(CFSNode):
         d['ana_grpid'] = self.grpid
         return d
 
+class Passthru(CFSNode):
+    '''
+    This is an interface to a NVMe passthru in ConfigFS.
+    '''
+
+    def __init__(self, subsystem):
+        '''
+        @param subsystem: The parent Subsystem object.
+        @return: A Passthru object.
+        '''
+        super(Passthru, self).__init__()
+        self._path = "%s/passthru" % (subsystem.path)
+        self.attr_groups = ['device']
+
+    def _get_clear_ids(self):
+        self._check_self()
+        path = "%s/clear_ids" % self.path
+        _ids = 0
+        if os.path.isfile(path):
+            with open(path, 'r') as file_fd:
+                _ids = int(file_fd.read().strip())
+        return _ids
+
+    ids = property(_get_clear_ids,
+                   doc = "Get the passthru namespace clear_ids attribute.")
+
+    def set_clear_ids(self, clear):
+        self._check_self()
+        path = "%s/clear_ids" % self.path
+        if os.path.isfile(path):
+            with open(path, 'w') as file_fd:
+                file_fd.write(str(clear))
+
+    def _get_admin_timeout(self):
+        self._check_self()
+        path = "%s/admin_timeout" % self.path
+        _timeout = 0
+        if os.path.isfile(path):
+            with open(path, 'r') as file_fd:
+                _timeout = int(file_fd.read().strip())
+        return _timeout
+
+    admin_timeout = property(_get_admin_timeout,
+                   doc = "Get the passthru admin command timeout.")
+
+    def set_admin_timeout(self, timeout):
+        self._check_self()
+        path = "%s/admin_timeout" % self.path
+        if os.path.isfile(path):
+            with open(path, 'w') as file_fd:
+                file_fd.write(str(timeout))
+
+    def _get_io_timeout(self):
+        self._check_self()
+        path = "%s/io_timeout" % self.path
+        _timeout = 0
+        if os.path.isfile(path):
+            with open(path, 'r') as file_fd:
+                _timeout = int(file_fd.read().strip())
+        return _timeout
+
+    io_timeout = property(_get_io_timeout,
+                   doc = "Get the passthru IO command timeout.")
+
+    def set_io_timeout(self, timeout):
+        self._check_self()
+        path = "%s/io_timeout" % self.path
+        if os.path.isfile(path):
+            with open(path, 'w') as file_fd:
+                file_fd.write(str(timeout))
+
+    @classmethod
+    def setup(cls, subsys, p, err_func):
+        try:
+            pt = Passthru(subsys)
+        except CFSError as e:
+            err_func("Could not create Namespace object: %s" % e)
+            return
+        pt._setup_attrs(p, err_func)
+        if 'clear_ids' in p:
+            pt.set_clear_ids(int(p['clear_ids']))
+        if 'admin_timeout' in p:
+            pt.set_admin_timeout(int(p['admin_timeout']))
+        if 'io_timeout' in p:
+            pt.set_io_timeout(int(p['io_timeout']))
+
+    def dump(self):
+        d = super(Passthru, self).dump()
+        d['clear_ids'] = self.ids
+        d['admin_timeout'] = self.admin_timeout
+        d['io_timeout'] = self.io_timeout
+        return d
 
 class Port(CFSNode):
     '''
diff --git a/nvmetcli b/nvmetcli
index d949891..810a7cd 100755
--- a/nvmetcli
+++ b/nvmetcli
@@ -166,6 +166,7 @@ class UISubsystemNode(UINode):
         self._children = set([])
         UINamespacesNode(self)
         UIAllowedHostsNode(self)
+        UIPassthruNode(self)
 
     def summary(self):
         info = []
@@ -175,6 +176,82 @@ class UISubsystemNode(UINode):
         info.append("serial=" + self.cfnode.get_attr("attr", "serial"))
         return (", ".join(info), True)
 
+class UIPassthruNode(UINode):
+    ui_desc_device = {
+        'path' : ('string', 'Passthru device path')
+    }
+
+    def __init__(self, parent):
+        passthru = nvme.Passthru(parent.cfnode)
+        UINode.__init__(self, 'passthru', parent, passthru)
+
+    def refresh(self):
+        pass
+
+    def ui_command_enable(self):
+        if self.cfnode.get_enable():
+            self.shell.log.info("The passthru is already enabled.")
+        else:
+            try:
+                self.cfnode.set_enable(1)
+                self.shell.log.info("The passthru has been enabled.")
+            except Exception as e:
+                raise configshell.ExecutionError(
+                    "The passthru could not be enabled.")
+
+    def ui_command_disable(self):
+        if not self.cfnode.get_enable():
+            self.shell.log.info("The passthru is already disabled.")
+        else:
+            try:
+                self.cfnode.set_enable(0)
+                self.shell.log.info("The passthru has been disabled.")
+            except Exception as e:
+                raise configshell.ExecutionError(
+                    "The passthru could not be disabled.")
+
+    def ui_command_clear_ids(self, clear):
+        '''
+        If I{clear} is set to non-zero then clears the passthru namespace
+        unique identifiers EUI/GUID/UUID.
+        '''
+        try:
+            self.cfnode.set_clear_ids(clear)
+        except Exception as e:
+            raise configshell.ExecutionError(
+                "Failed to set clear_ids for this passthru target.")
+
+    def ui_command_admin_timeout(self, timeout):
+        '''
+        Sets the timeout of admin passthru command.
+        '''
+        try:
+            self.cfnode.set_admin_timeout(timeout)
+        except Exception as e:
+            raise configshell.ExecutionError(
+                "Failed to set the admin passthru command timeout.")
+
+    def ui_command_io_timeout(self, timeout):
+        '''
+        Sets the timeout of IO passthru command.
+        '''
+        try:
+            self.cfnode.set_io_timeout(timeout)
+        except Exception as e:
+            raise configshell.ExecutionError(
+                "Failed to set the IO passthru command timeout.")
+
+    def summary(self):
+        info = []
+        info.append("path=" + self.cfnode.get_attr("device", "path"))
+        if self.cfnode.ids != 0:
+            info.append("clear_ids=" + str(self.cfnode.ids))
+        if self.cfnode.admin_timeout != 0:
+            info.append("admin_tomeout=" + str(self.cfnode.admin_timeout))
+        if self.cfnode.io_timeout != 0:
+            info.append("io_tomeout=" + str(self.cfnode.io_timeout))
+        info.append("enabled" if self.cfnode.get_enable() else "disabled")
+        return (", ".join(info), True)
 
 class UINamespacesNode(UINode):
     def __init__(self, parent):
-- 
2.49.0



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

* Re: [PATCH] nvmetcli: add support for NVMe passthru target
  2025-06-11 10:39 [PATCH] nvmetcli: add support for NVMe passthru target Nilay Shroff
@ 2025-06-16  4:28 ` Chaitanya Kulkarni
  2025-07-22 13:49   ` Nilay Shroff
  0 siblings, 1 reply; 3+ messages in thread
From: Chaitanya Kulkarni @ 2025-06-16  4:28 UTC (permalink / raw)
  To: Nilay Shroff, linux-nvme@lists.infradead.org; +Cc: hch@lst.de, gjoyce@ibm.com

On 6/11/25 03:39, Nilay Shroff wrote:
> This change adds the support for configuring NVMe passthru target.
>
> Signed-off-by: Nilay Shroff<nilay@linux.ibm.com>
> ---
>   nvmet/__init__.py |   2 +-
>   nvmet/nvme.py     | 102 ++++++++++++++++++++++++++++++++++++++++++++++
>   nvmetcli          |  77 ++++++++++++++++++++++++++++++++++
>   3 files changed, 180 insertions(+), 1 deletion(-)

Thanks a lot for submitting this, we have been missing this support and
it is really useful addition.


Overall this change is useful and looks good, didn't get a chance to
test though.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



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

* Re: [PATCH] nvmetcli: add support for NVMe passthru target
  2025-06-16  4:28 ` Chaitanya Kulkarni
@ 2025-07-22 13:49   ` Nilay Shroff
  0 siblings, 0 replies; 3+ messages in thread
From: Nilay Shroff @ 2025-07-22 13:49 UTC (permalink / raw)
  To: hch@lst.de
  Cc: gjoyce@ibm.com, linux-nvme@lists.infradead.org,
	Chaitanya Kulkarni

Hi Christoph,

A gentle ping about this patch.  Did you get a chance to review it? 

Thanks,
--Nilay

On 6/16/25 9:58 AM, Chaitanya Kulkarni wrote:
> On 6/11/25 03:39, Nilay Shroff wrote:
>> This change adds the support for configuring NVMe passthru target.
>>
>> Signed-off-by: Nilay Shroff<nilay@linux.ibm.com>
>> ---
>>   nvmet/__init__.py |   2 +-
>>   nvmet/nvme.py     | 102 ++++++++++++++++++++++++++++++++++++++++++++++
>>   nvmetcli          |  77 ++++++++++++++++++++++++++++++++++
>>   3 files changed, 180 insertions(+), 1 deletion(-)
> 
> Thanks a lot for submitting this, we have been missing this support and
> it is really useful addition.
> 
> 
> Overall this change is useful and looks good, didn't get a chance to
> test though.
> 
> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
> 
> -ck
> 
> 



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

end of thread, other threads:[~2025-07-22 14:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-11 10:39 [PATCH] nvmetcli: add support for NVMe passthru target Nilay Shroff
2025-06-16  4:28 ` Chaitanya Kulkarni
2025-07-22 13:49   ` Nilay Shroff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).