From 5d1abab36be9375f46210dd19d5293cf73433681 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 7 Dec 2017 15:25:35 +0100 Subject: [PATCH 1/4] Auto-detect readonly state for iblock devices Configuring a read-only block device as read-write currently results in a backstore->enable configfs I/O error, as documented in: http://www.spinics.net/lists/target-devel/msg16310.html This change sees targetcli check the read-only status of the underlying block device via ioctl(BLKROGET). If a readonly= parameter isn't provided, then the backstore will use the ioctl(BLKROGET) value as the default. Signed-off-by: David Disseldorp (cherry picked from commit 1a0886ecbcba6d5b2d9756ecadb3e2eaab99d29e) --- targetcli/ui_backstore.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/targetcli/ui_backstore.py b/targetcli/ui_backstore.py index 83673a0..66a21c5 100644 --- a/targetcli/ui_backstore.py +++ b/targetcli/ui_backstore.py @@ -19,6 +19,9 @@ under the License. import glob import os +import fcntl +import array +import struct import re import stat import dbus @@ -516,6 +519,25 @@ class UIBlockBackstore(UIBackstore): self.so_cls = UIBlockStorageObject UIBackstore.__init__(self, 'block', parent) + def _ui_block_ro_check(self, dev): + BLKROGET=0x0000125E + try: + f = os.open(dev, os.O_RDONLY) + except (OSError, IOError): + raise ExecutionError("Could not open %s" % dev) + # ioctl returns an int. Provision a buffer for it + buf = array.array('c', [chr(0)] * 4) + try: + fcntl.ioctl(f, BLKROGET, buf) + except (OSError, IOError): + os.close(f) + return False + + os.close(f) + if struct.unpack('I', buf)[0] == 0: + return False + return True + def ui_command_create(self, name, dev, readonly=None, wwn=None): ''' Creates an Block Storage object. I{dev} is the path to the TYPE_DISK @@ -523,7 +545,13 @@ class UIBlockBackstore(UIBackstore): ''' self.assert_root() - readonly = self.ui_eval_param(readonly, 'bool', False) + ro_string = self.ui_eval_param(readonly, 'string', None) + if ro_string == None: + # attempt to detect block device readonly state via ioctl + readonly = self._ui_block_ro_check(dev) + else: + readonly = self.ui_eval_param(readonly, 'bool', False) + wwn = self.ui_eval_param(wwn, 'string', None) so = BlockStorageObject(name, dev, readonly=readonly, wwn=wwn) -- 2.13.6