summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2019-07-31 17:31:33 +0530
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2019-07-31 17:49:43 +0530
commitb85561a4e8b6613a87a5f055a1365e2a97594de6 (patch)
tree22156b570af90cd7cacc67f0b7df7b2e649ad1df /scripts
parent85031ad48b011f5626cd0a287749abcaa145277b (diff)
downloadtargetcli-b85561a4e8b6613a87a5f055a1365e2a97594de6.tar.gz
targetcli: serialize multiple requests
Problem: ------- targetcli/rtslib cannot handle parallel requests at the moment. Read more about this at http://bit.ly/targetcli-parallel-requests-issue $ for i in {1..10}; do \ targetcli /backstores/fileio create ${i} /tmp/file${i} 10M& done Created fileio 1 with size 10485760 This _Backstore already exists in configFS This _Backstore already exists in configFS This _Backstore already exists in configFS This _Backstore already exists in configFS This _Backstore already exists in configFS Created fileio 6 with size 10485760 Created fileio 2 with size 10485760 This _Backstore already exists in configFS Created fileio 8 with size 10485760 Created fileio 9 with size 10485760 bails-out most of the time with above errors and sometimes even crashes. Solution: -------- Serialize/defend the parallel requests by simply taking a wait lock at targetcli level, so that only one request can be processed by targetcli at any given point in time. Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/targetcli42
1 files changed, 42 insertions, 0 deletions
diff --git a/scripts/targetcli b/scripts/targetcli
index 66cb5bb..9e03b0f 100755
--- a/scripts/targetcli
+++ b/scripts/targetcli
@@ -31,8 +31,11 @@ import socket
import struct
import readline
import six
+import fcntl
err = sys.stderr
+# lockfile for serializing multiple targetcli requests
+lock_file = '/var/run/targetcli.lock'
socket_path = '/var/run/targetclid.sock'
hints = ['/', 'backstores/', 'iscsi/', 'loopback/', 'vhost/', 'xen-pvscsi/',
'cd', 'pwd', 'ls', 'set', 'get', 'help', 'refresh', 'status',
@@ -85,6 +88,33 @@ def usage_version(cmd):
if cmd in ("version", "--version", "-v"):
version()
+def try_op_lock(shell, lkfd):
+ '''
+ acquire a blocking lock on lockfile, to serialize multiple requests
+ '''
+ try:
+ fcntl.flock(lkfd, fcntl.LOCK_EX) # wait here until ongoing request is finished
+ except Exception, e:
+ shell.con.display(
+ shell.con.render_text(
+ "taking lock on lockfile failed: %s" %str(e),
+ 'red'))
+ sys.exit(1)
+
+def release_op_lock(shell, lkfd):
+ '''
+ release blocking lock on lockfile, which can allow other requests process
+ '''
+ try:
+ fcntl.flock(lkfd, fcntl.LOCK_UN) # allow other requests now
+ except Exception, e:
+ shell.con.display(
+ shell.con.render_text(
+ "unlock on lockfile failed: %s" %str(e),
+ 'red'))
+ sys.exit(1)
+ lkfd.close()
+
def completer(text, state):
options = [x for x in hints if x.startswith(text)]
try:
@@ -168,6 +198,16 @@ def main():
if getuid() == 0:
is_root = True
+ try:
+ lkfd = open(lock_file, 'w+');
+ except IOError as e:
+ shell.con.display(
+ shell.con.render_text("opening lockfile failed: %s" %str(e),
+ 'red'))
+ sys.exit(1)
+
+ try_op_lock(shell, lkfd)
+
use_daemon = False
if shell.prefs['auto_use_daemon']:
use_daemon = True
@@ -214,6 +254,8 @@ def main():
shell.log.info("Global pref auto_save_on_exit=true")
root_node.ui_command_saveconfig()
+ release_op_lock(shell, lkfd)
+
if __name__ == "__main__":
main()