From 6361cc5afd41ee36ce71bbc95722b52b71167d5e Mon Sep 17 00:00:00 2001 From: root Date: Wed, 29 Dec 2021 16:35:28 +0800 Subject: [PATCH] update version to 0.7 --- ...li-don-t-remove-ANA-Group-1-on-clear.patch | 33 ++++ ...README-Update-URL-for-configshell-fb.patch | 30 ++++ ...-Improve-IOError-handling-on-restore.patch | 61 ++++++++ ...-nvme-py-Explicit-close-is-redundant.patch | 29 ++++ ...vme-py-Sync-the-containing-directory.patch | 40 +++++ ...-Make-modprobe-work-for-kmod-lib-too.patch | 35 +++++ ...-py-test_invalid_input-fails-for-py3.patch | 48 ++++++ ...-nvmetcli-Report-save-name-correctly.patch | 50 ++++++ ...llow-different-devices-for-make-test.patch | 146 ++++++++++++++++++ ...vmetcli-Correct-xrange-usage-for-py3.patch | 57 +++++++ 0011-nvmetcli-add-a-tcp-example-json.patch | 99 ++++++++++++ 0012-Documentation-fix-typo.patch | 28 ++++ nvmetcli-0.4.tar.gz | Bin 21386 -> 0 bytes nvmetcli-0.7.tar.gz | Bin 0 -> 22691 bytes nvmetcli.spec | 27 +++- 15 files changed, 679 insertions(+), 4 deletions(-) create mode 100644 0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch create mode 100644 0002-README-Update-URL-for-configshell-fb.patch create mode 100644 0003-nvmetcli-Improve-IOError-handling-on-restore.patch create mode 100644 0004-nvme-py-Explicit-close-is-redundant.patch create mode 100644 0005-nvme-py-Sync-the-containing-directory.patch create mode 100644 0006-nvme-py-Make-modprobe-work-for-kmod-lib-too.patch create mode 100644 0007-test_nvmet-py-test_invalid_input-fails-for-py3.patch create mode 100644 0008-nvmetcli-Report-save-name-correctly.patch create mode 100644 0009-nvmetcli-Allow-different-devices-for-make-test.patch create mode 100644 0010-nvmetcli-Correct-xrange-usage-for-py3.patch create mode 100644 0011-nvmetcli-add-a-tcp-example-json.patch create mode 100644 0012-Documentation-fix-typo.patch delete mode 100644 nvmetcli-0.4.tar.gz create mode 100644 nvmetcli-0.7.tar.gz diff --git a/0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch b/0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch new file mode 100644 index 0000000..85e886f --- /dev/null +++ b/0001-nvmetcli-don-t-remove-ANA-Group-1-on-clear.patch @@ -0,0 +1,33 @@ +From 0827df8deb5304854d9efc58e9df5971aa66f490 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 27 Mar 2020 08:01:34 +0100 +Subject: [PATCH 01/12] nvmetcli: don't remove ANA Group 1 on clear + +The first ANA group is maintained by the kernel so it cannot +be deleted. + +Signed-off-by: Hannes Reinecke +Signed-off-by: Christoph Hellwig +--- + nvmet/nvme.py | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/nvmet/nvme.py b/nvmet/nvme.py +index 0647ddc..fdec4ff 100644 +--- a/nvmet/nvme.py ++++ b/nvmet/nvme.py +@@ -845,6 +845,11 @@ class ANAGroup(CFSNode): + + a._setup_attrs(n, err_func) + ++ def delete(self): ++ # ANA Group 1 is automatically created/deleted ++ if self.grpid != 1: ++ super(ANAGroup, self).delete() ++ + def dump(self): + d = super(ANAGroup, self).dump() + d['grpid'] = self.grpid +-- +2.29.2 + diff --git a/0002-README-Update-URL-for-configshell-fb.patch b/0002-README-Update-URL-for-configshell-fb.patch new file mode 100644 index 0000000..76b2ea8 --- /dev/null +++ b/0002-README-Update-URL-for-configshell-fb.patch @@ -0,0 +1,30 @@ +From a481736441b4c811f57fa84a8e3609b084f93835 Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:44 -0500 +Subject: [PATCH 02/12] README: Update URL for configshell-fb + +The github repository was moved. There is a github redirect, +so this change is not strictly required. + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + README | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/README b/README +index c8717e8..5a4ecd1 100644 +--- a/README ++++ b/README +@@ -7,7 +7,7 @@ to save, restore or clear the current NVMe target configuration. + Installation + ------------ + Please install the configshell-fb package from +-https://github.com/agrover/configshell-fb first. ++https://github.com/open-iscsi/configshell-fb first. + + nvmetcli can be run directly from the source directory or installed + using setup.py. +-- +2.29.2 + diff --git a/0003-nvmetcli-Improve-IOError-handling-on-restore.patch b/0003-nvmetcli-Improve-IOError-handling-on-restore.patch new file mode 100644 index 0000000..1c052c2 --- /dev/null +++ b/0003-nvmetcli-Improve-IOError-handling-on-restore.patch @@ -0,0 +1,61 @@ +From 48b8f318e0594d7adfec290ae47d9308eb0f65af Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:45 -0500 +Subject: [PATCH 03/12] nvmetcli: Improve IOError handling on restore + +Not all IOErrors are caused by specifying a missing configuration +file. When the file is present, dump the error exception text too, +so the user has a better idea what is wrong. + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + nvmetcli | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/nvmetcli b/nvmetcli +index 3d8c16e..a646232 100755 +--- a/nvmetcli ++++ b/nvmetcli +@@ -24,6 +24,7 @@ import os + import sys + import configshell_fb as configshell + import nvmet as nvme ++import errno + from string import hexdigits + import uuid + +@@ -674,16 +675,26 @@ def save(to_file): + + + def restore(from_file): ++ errors = None ++ + try: + errors = nvme.Root().restore_from_file(from_file) +- except IOError: +- # Not an error if the restore file is not present +- print("No saved config file at %s, ok, exiting" % from_file) +- sys.exit(0) ++ except IOError as e: ++ if e.errno == errno.ENOENT: ++ # Not an error if the restore file is not present ++ print("No saved config file at %s, ok, exiting" % from_file) ++ sys.exit(0) ++ else: ++ print("Error processing config file at %s, error %s, exiting" % ++ (from_file, str(e))) ++ sys.exit(1) + ++ # These errors are non-fatal + for error in errors: + print(error) + ++ sys.exit(0) ++ + + def clear(unused): + nvme.Root().clear_existing() +-- +2.29.2 + diff --git a/0004-nvme-py-Explicit-close-is-redundant.patch b/0004-nvme-py-Explicit-close-is-redundant.patch new file mode 100644 index 0000000..b329780 --- /dev/null +++ b/0004-nvme-py-Explicit-close-is-redundant.patch @@ -0,0 +1,29 @@ +From 226b73a4ae317c6aa3c7b00da2adbd1ec769ce34 Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:46 -0500 +Subject: [PATCH 04/12] nvme.py: Explicit close is redundant + +One of the benefits of using 'with' statement for open files is the +close is going to be called regardless of what happens. + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + nvmet/nvme.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/nvmet/nvme.py b/nvmet/nvme.py +index fdec4ff..687a45a 100644 +--- a/nvmet/nvme.py ++++ b/nvmet/nvme.py +@@ -302,7 +302,6 @@ class Root(CFSNode): + f.write("\n") + f.flush() + os.fsync(f.fileno()) +- f.close() + + os.rename(savefile + ".temp", savefile) + +-- +2.29.2 + diff --git a/0005-nvme-py-Sync-the-containing-directory.patch b/0005-nvme-py-Sync-the-containing-directory.patch new file mode 100644 index 0000000..c9f1adc --- /dev/null +++ b/0005-nvme-py-Sync-the-containing-directory.patch @@ -0,0 +1,40 @@ +From 12a8764c6113887c5691cab6a92bb1c13414395c Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:47 -0500 +Subject: [PATCH 05/12] nvme.py: Sync the containing directory + +It's apparent that some thought went into making sure the config +file makes it atomically to the fs. However, one thing is missing +which is doing a fsync on the containing directory of the config file. + +See: https://lwn.net/Articles/457667/ + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + nvmet/nvme.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/nvmet/nvme.py b/nvmet/nvme.py +index 687a45a..04659de 100644 +--- a/nvmet/nvme.py ++++ b/nvmet/nvme.py +@@ -305,6 +305,15 @@ class Root(CFSNode): + + os.rename(savefile + ".temp", savefile) + ++ # Sync the containing directory too ++ dir_fd = None ++ try: ++ dir_fd = os.open(savefile_dir, os.O_RDONLY) ++ os.fsync(dir_fd) ++ finally: ++ if dir_fd: ++ os.close(dir_fd) ++ + def clear_existing(self): + ''' + Remove entire current configuration. +-- +2.29.2 + diff --git a/0006-nvme-py-Make-modprobe-work-for-kmod-lib-too.patch b/0006-nvme-py-Make-modprobe-work-for-kmod-lib-too.patch new file mode 100644 index 0000000..7c52315 --- /dev/null +++ b/0006-nvme-py-Make-modprobe-work-for-kmod-lib-too.patch @@ -0,0 +1,35 @@ +From 75c178f6c2943490ef2c13df5863d6ac308f6ef1 Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:48 -0500 +Subject: [PATCH 06/12] nvme.py: Make modprobe work for kmod lib too + +The python library 'kmod' is included with libkmod, lets try to use that +if the user isn't utilizing kmodpy. + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + nvmet/nvme.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/nvmet/nvme.py b/nvmet/nvme.py +index 04659de..db8a03c 100644 +--- a/nvmet/nvme.py ++++ b/nvmet/nvme.py +@@ -253,7 +253,12 @@ class Root(CFSNode): + except kmod.KmodError: + pass + except ImportError: +- pass ++ # Try the ctypes library included with the libkmod itself. ++ try: ++ import kmod ++ kmod.Kmod().modprobe(modname) ++ except Exception as e: ++ pass + + def _list_subsystems(self): + self._check_self() +-- +2.29.2 + diff --git a/0007-test_nvmet-py-test_invalid_input-fails-for-py3.patch b/0007-test_nvmet-py-test_invalid_input-fails-for-py3.patch new file mode 100644 index 0000000..d9502c1 --- /dev/null +++ b/0007-test_nvmet-py-test_invalid_input-fails-for-py3.patch @@ -0,0 +1,48 @@ +From 477a04b18e8754dc3f75110f0e7e6cdac70217aa Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:49 -0500 +Subject: [PATCH 07/12] test_nvmet.py: test_invalid_input fails for py3 + +When you run 'make test' using python 3 the unit test +test_invalid_input fails with: + +Traceback (most recent call last): + File "/someuser/projects/nvmetcli/nvmet/test_nvmet.py", line 395, in +test_invalid_input + for i in range(l)) + File "/someuser/projects/nvmetcli/nvmet/test_nvmet.py", line 395, in + + for i in range(l)) +AttributeError: module 'string' has no attribute 'lowercase' + +Python 3 does not have 'string.lowercase' ref. +https://docs.python.org/3/library/string.html + +Python 2 does ref. +https://docs.python.org/2/library/string.html + +Both have "string.ascii_lowercase" so lets leverage that to +support both. + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + nvmet/test_nvmet.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nvmet/test_nvmet.py b/nvmet/test_nvmet.py +index 5caa546..aae4a86 100644 +--- a/nvmet/test_nvmet.py ++++ b/nvmet/test_nvmet.py +@@ -391,7 +391,7 @@ class TestNvmet(unittest.TestCase): + nqn='/', mode='create') + + for l in [ 257, 512, 1024, 2048 ]: +- toolong = ''.join(random.choice(string.lowercase) ++ toolong = ''.join(random.choice(string.ascii_lowercase) + for i in range(l)) + self.assertRaises(nvme.CFSError, nvme.Subsystem, + nqn=toolong, mode='create') +-- +2.29.2 + diff --git a/0008-nvmetcli-Report-save-name-correctly.patch b/0008-nvmetcli-Report-save-name-correctly.patch new file mode 100644 index 0000000..758a0b5 --- /dev/null +++ b/0008-nvmetcli-Report-save-name-correctly.patch @@ -0,0 +1,50 @@ +From fd09200bba73011b4b7086c96e394ce875fdd38f Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 26 Mar 2020 13:07:50 -0500 +Subject: [PATCH 08/12] nvmetcli: Report save name correctly + +When a user simply does 'nvmetcli restore' without +specifying a file name the default is used. However, if the +restore fails you end up with the error message: + +Error processing config file at None, error [Errno 1] Operation not +permitted: '/sys/kernel/config/nvmet/ports/0/ana_groups/1', exiting + +Correct file name if None in error path. + +Error processing config file at /etc/nvmet/config.json, error \ +[Errno 1] Operation not permitted: \ +'/sys/kernel/config/nvmet/ports/1/ana_groups/1', exiting + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + nvmet/__init__.py | 3 ++- + nvmetcli | 3 +++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/nvmet/__init__.py b/nvmet/__init__.py +index ca05de4..cf172bd 100644 +--- a/nvmet/__init__.py ++++ b/nvmet/__init__.py +@@ -1 +1,2 @@ +-from .nvme import Root, Subsystem, Namespace, Port, Host, Referral, ANAGroup ++from .nvme import Root, Subsystem, Namespace, Port, Host, Referral, ANAGroup,\ ++ DEFAULT_SAVE_FILE +diff --git a/nvmetcli b/nvmetcli +index a646232..8ee8590 100755 +--- a/nvmetcli ++++ b/nvmetcli +@@ -680,6 +680,9 @@ def restore(from_file): + try: + errors = nvme.Root().restore_from_file(from_file) + except IOError as e: ++ if not from_file: ++ from_file = nvme.DEFAULT_SAVE_FILE ++ + if e.errno == errno.ENOENT: + # Not an error if the restore file is not present + print("No saved config file at %s, ok, exiting" % from_file) +-- +2.29.2 + diff --git a/0009-nvmetcli-Allow-different-devices-for-make-test.patch b/0009-nvmetcli-Allow-different-devices-for-make-test.patch new file mode 100644 index 0000000..3f76ca7 --- /dev/null +++ b/0009-nvmetcli-Allow-different-devices-for-make-test.patch @@ -0,0 +1,146 @@ +From 35e92a1bfedf28868112165892b3eb2cd7f750ce Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Thu, 2 Apr 2020 10:54:43 -0500 +Subject: [PATCH 09/12] nvmetcli: Allow different devices for make test + +The test_nvmet.py by default uses /dev/ram0 and /dev/ram1 for 2 of the +unit tests. Add env. variable to allow user to specify different devices +or files. Additionally, skip these unit tests that require devices/files +if they are not present. Update README too. + +$ sudo make test +......s...s. +---------------------------------------------------------------------- +Ran 12 tests in 0.043s + +OK (skipped=2) +Name Stmts Miss Cover +----------------------------------------- +nvmet/__init__.py 1 0 100% +nvmet/nvme.py 517 237 54% +nvmet/test_nvmet.py 276 63 77% +----------------------------------------- +TOTAL 794 300 62% + +$ sudo NVMET_TEST_DEVICES="/dev/sdc,/dev/sdd" make test +............ +---------------------------------------------------------------------- +Ran 12 tests in 0.124s + +OK +Name Stmts Miss Cover +----------------------------------------- +nvmet/__init__.py 1 0 100% +nvmet/nvme.py 517 100 81% +nvmet/test_nvmet.py 276 4 99% +----------------------------------------- +TOTAL 794 104 87% + +Signed-off-by: Tony Asleson +Signed-off-by: Christoph Hellwig +--- + README | 5 ++++- + nvmet/test_nvmet.py | 26 ++++++++++++++++++++++---- + 2 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/README b/README +index 5a4ecd1..44f1c33 100644 +--- a/README ++++ b/README +@@ -47,7 +47,10 @@ Testing + ------- + nvmetcli comes with a testsuite that tests itself and the kernel configfs + interface for the NVMe target. To run it make sure you have nose2 and +-the coverage plugin for it installed and simple run 'make test'. ++the coverage plugin for it installed and simple run 'make test'. To run all ++the tests you also need some test block devices or files. Default is to ++use /dev/ram0 and /dev/ram1. You can override default with environmental ++variable eg. NVMET_TEST_DEVICES="/dev/sdk,/dev/sdj" make test . + + Development + ----------------- +diff --git a/nvmet/test_nvmet.py b/nvmet/test_nvmet.py +index aae4a86..f8ec232 100644 +--- a/nvmet/test_nvmet.py ++++ b/nvmet/test_nvmet.py +@@ -1,9 +1,22 @@ + ++import os + import random ++import stat + import string + import unittest + import nvmet.nvme as nvme + ++# Default test devices are ram disks, but allow user to specify different ++# block devices or files. ++NVMET_TEST_DEVICES = os.getenv("NVMET_TEST_DEVICES", ++ "/dev/ram0,/dev/ram1").split(',') ++ ++ ++def test_devices_present(): ++ return len([x for x in NVMET_TEST_DEVICES ++ if os.path.exists(x) and ++ (stat.S_ISBLK(os.stat(x).st_mode) or os.path.isfile(x))]) >= 2 ++ + + class TestNvmet(unittest.TestCase): + def test_subsystem(self): +@@ -101,6 +114,8 @@ class TestNvmet(unittest.TestCase): + n.delete() + self.assertEqual(len(list(s.namespaces)), 0) + ++ @unittest.skipUnless(test_devices_present(), ++ "Devices %s not available or suitable" % ','.join(NVMET_TEST_DEVICES)) + def test_namespace_attrs(self): + root = nvme.Root() + root.clear_existing() +@@ -116,7 +131,7 @@ class TestNvmet(unittest.TestCase): + self.assertRaises(nvme.CFSError, n.set_enable, 1) + + # now set a path and enable +- n.set_attr('device', 'path', '/dev/ram0') ++ n.set_attr('device', 'path', NVMET_TEST_DEVICES[0]) + n.set_enable(1) + self.assertTrue(n.get_enable()) + +@@ -125,7 +140,7 @@ class TestNvmet(unittest.TestCase): + + # test that we can't write to attrs while enabled + self.assertRaises(nvme.CFSError, n.set_attr, 'device', 'path', +- '/dev/ram1') ++ NVMET_TEST_DEVICES[1]) + self.assertRaises(nvme.CFSError, n.set_attr, 'device', 'nguid', + '15f7767b-50e7-4441-949c-75b99153dea7') + +@@ -403,6 +418,9 @@ class TestNvmet(unittest.TestCase): + self.assertRaises(nvme.CFSError, nvme.Port, + portid=1 << 17, mode='create') + ++ @unittest.skipUnless(test_devices_present(), ++ "Devices %s not available or suitable" % ','.join( ++ NVMET_TEST_DEVICES)) + def test_save_restore(self): + root = nvme.Root() + root.clear_existing() +@@ -416,7 +434,7 @@ class TestNvmet(unittest.TestCase): + s2.set_attr('attr', 'allow_any_host', 1) + + n = nvme.Namespace(s, nsid=42, mode='create') +- n.set_attr('device', 'path', '/dev/ram0') ++ n.set_attr('device', 'path', NVMET_TEST_DEVICES[0]) + n.set_enable(1) + + nguid = n.get_attr('device', 'nguid') +@@ -454,7 +472,7 @@ class TestNvmet(unittest.TestCase): + + # and check everything is still the same + self.assertTrue(n.get_enable()) +- self.assertEqual(n.get_attr('device', 'path'), '/dev/ram0') ++ self.assertEqual(n.get_attr('device', 'path'), NVMET_TEST_DEVICES[0]) + self.assertEqual(n.get_attr('device', 'nguid'), nguid) + + self.assertEqual(p.get_attr('addr', 'trtype'), 'loop') +-- +2.29.2 + diff --git a/0010-nvmetcli-Correct-xrange-usage-for-py3.patch b/0010-nvmetcli-Correct-xrange-usage-for-py3.patch new file mode 100644 index 0000000..7ba1e75 --- /dev/null +++ b/0010-nvmetcli-Correct-xrange-usage-for-py3.patch @@ -0,0 +1,57 @@ +From 9da40b0433b8338f82c2c910b1057e1e1061b9a0 Mon Sep 17 00:00:00 2001 +From: Tony Asleson +Date: Wed, 1 Apr 2020 14:13:16 -0500 +Subject: [PATCH 10/12] nvmetcli: Correct xrange usage for py3 + +If you are in a namespace and simply do a 'create' without specifying +a value you will get: + +/subsystems/n...f8/namespaces> create +name 'xrange' is not defined +subsystems/n...f8/namespaces> + +This is because xrange is not defined in python3 as python3 changed +it to range. As the code is already using six use six.move.xrange +which works for both python2 & python3. + +Signed-off-by: Tony Asleson +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +--- + nvmet/nvme.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/nvmet/nvme.py b/nvmet/nvme.py +index db8a03c..83fd75b 100644 +--- a/nvmet/nvme.py ++++ b/nvmet/nvme.py +@@ -23,7 +23,7 @@ import stat + import uuid + import json + from glob import iglob as glob +-from six import iteritems ++from six import iteritems, moves + + DEFAULT_SAVE_FILE = '/etc/nvmet/config.json' + +@@ -556,7 +556,7 @@ class Namespace(CFSNode): + raise CFSError("Need NSID for lookup") + + nsids = [n.nsid for n in subsystem.namespaces] +- for index in xrange(1, self.MAX_NSID + 1): ++ for index in moves.xrange(1, self.MAX_NSID + 1): + if index not in nsids: + nsid = index + break +@@ -816,7 +816,7 @@ class ANAGroup(CFSNode): + raise CFSError("Need grpid for lookup") + + grpids = [n.grpid for n in port.ana_groups] +- for index in xrange(2, self.MAX_GRPID + 1): ++ for index in moves.xrange(2, self.MAX_GRPID + 1): + if index not in grpids: + grpid = index + break +-- +2.29.2 + diff --git a/0011-nvmetcli-add-a-tcp-example-json.patch b/0011-nvmetcli-add-a-tcp-example-json.patch new file mode 100644 index 0000000..3bd70e7 --- /dev/null +++ b/0011-nvmetcli-add-a-tcp-example-json.patch @@ -0,0 +1,99 @@ +From 73dcf7ef6b6aa80c87c61f08583cba97ad1c626a Mon Sep 17 00:00:00 2001 +From: zhenwei pi +Date: Thu, 10 Dec 2020 17:06:56 +0800 +Subject: [PATCH 11/12] nvmetcli: add a tcp example json + +Run a tcp nvme target on linux-5.10-rc version, and save the config +as an example. + +Signed-off-by: zhenwei pi +Signed-off-by: Christoph Hellwig +--- + README | 5 +++++ + tcp.json | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + create mode 100644 tcp.json + +diff --git a/README b/README +index 44f1c33..6ebe666 100644 +--- a/README ++++ b/README +@@ -41,6 +41,11 @@ fc.json fits your setup: + + ./nvmetcli restore fc.json + ++Or to load the tcp + no host authentication version do the following ++after you've ensured that the IP address in tcp.json fits your setup: ++ ++ ./nvmetcli restore tcp.json ++ + These files can also be edited directly using your favorite editor. + + Testing +diff --git a/tcp.json b/tcp.json +new file mode 100644 +index 0000000..e6ff029 +--- /dev/null ++++ b/tcp.json +@@ -0,0 +1,58 @@ ++{ ++ "hosts": [], ++ "ports": [ ++ { ++ "addr": { ++ "adrfam": "ipv4", ++ "traddr": "192.168.122.33", ++ "treq": "not specified", ++ "trsvcid": "4420", ++ "trtype": "tcp" ++ }, ++ "ana_groups": [ ++ { ++ "ana": { ++ "state": "optimized" ++ }, ++ "grpid": 1 ++ } ++ ], ++ "param": { ++ "inline_data_size": "16384", ++ "pi_enable": "0" ++ }, ++ "portid": 1, ++ "referrals": [], ++ "subsystems": [ ++ "nvmet-always" ++ ] ++ } ++ ], ++ "subsystems": [ ++ { ++ "allowed_hosts": [], ++ "attr": { ++ "allow_any_host": "1", ++ "cntlid_max": "65519", ++ "cntlid_min": "1", ++ "model": "Linux", ++ "pi_enable": "0", ++ "serial": "123456789abcdef", ++ "version": "1.3" ++ }, ++ "namespaces": [ ++ { ++ "ana_grpid": 1, ++ "device": { ++ "nguid": "00000000-0000-0000-0000-000000000000", ++ "path": "/dev/nvme0n1", ++ "uuid": "d592cdf3-5d1c-44e0-8412-3fcf7d99df27" ++ }, ++ "enable": 1, ++ "nsid": 1 ++ } ++ ], ++ "nqn": "nvmet-always" ++ } ++ ] ++} +-- +2.29.2 + diff --git a/0012-Documentation-fix-typo.patch b/0012-Documentation-fix-typo.patch new file mode 100644 index 0000000..a77638e --- /dev/null +++ b/0012-Documentation-fix-typo.patch @@ -0,0 +1,28 @@ +From 297f40aef117875d98303b0535fb076626b91a19 Mon Sep 17 00:00:00 2001 +From: Maurizio Lombardi +Date: Mon, 1 Feb 2021 15:47:56 +0100 +Subject: [PATCH 12/12] Documentation: fix typo + +Signed-off-by: Maurizio Lombardi +Reviewed-by: Chaitanya Kulkarni +Signed-off-by: Christoph Hellwig +--- + Documentation/nvmetcli.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/nvmetcli.txt b/Documentation/nvmetcli.txt +index 05a0344..7d6ffda 100644 +--- a/Documentation/nvmetcli.txt ++++ b/Documentation/nvmetcli.txt +@@ -116,7 +116,7 @@ your devices and all dependent modules are loaded, + and configfs is mounted on /sys/kernel/config + using: + +- mount -t configs none /sys/kernel/config ++ mount -t configfs none /sys/kernel/config + + The following section walks through a configuration example. + +-- +2.29.2 + diff --git a/nvmetcli-0.4.tar.gz b/nvmetcli-0.4.tar.gz deleted file mode 100644 index 819d7fbb16b40bbc3dfc4ae89ec5a868a813ca96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21386 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 nvmetcli.8.gz %install %{__python3} setup.py install --skip-build --root %{buildroot} - +install -d %{buildroot}%{_unitdir} install -d %{buildroot}%{_sysconfdir}/nvmet install -m 644 -D nvmet.service %{buildroot}%{_unitdir}/nvmet.service install -m 644 -D Documentation/nvmetcli.8.gz %{buildroot}%{_mandir}/man8/nvmetcli.8.gz @@ -67,5 +80,11 @@ install -m 644 -D Documentation/nvmetcli.8.gz %{buildroot}%{_mandir}/man8/nvmetc %{_mandir}/man8/nvmetcli.8.gz %changelog +* Mon Dec 27 2021 Ge Wang - 0.7-1 +- update to version 0.7 + +* Fri Nov 6 2020 jialei - 0.4-7 +- add help for Requires + * Sat Nov 30 2019 Jiangping Hu - 0.4-6 - Package init -- Gitee