diff options
| author | Prasanna Kumar Kalever <prasanna.kalever@redhat.com> | 2019-07-31 17:31:33 +0530 |
|---|---|---|
| committer | Prasanna Kumar Kalever <prasanna.kalever@redhat.com> | 2019-07-31 17:49:43 +0530 |
| commit | b85561a4e8b6613a87a5f055a1365e2a97594de6 (patch) | |
| tree | 22156b570af90cd7cacc67f0b7df7b2e649ad1df /scripts | |
| parent | 85031ad48b011f5626cd0a287749abcaa145277b (diff) | |
| download | targetcli-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-x | scripts/targetcli | 42 |
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() |
