diff options
author | Andy Grover <agrover@redhat.com> | 2013-11-05 14:31:42 -0800 |
---|---|---|
committer | Andy Grover <agrover@redhat.com> | 2013-11-05 14:31:42 -0800 |
commit | b1fe8abae6fd49f19942eb7992b7f790e8f77aac (patch) | |
tree | bdaede9209e6d2d7cc9059660bf3f3f529dbc15d /rtslib/utils.py | |
parent | 7cf029d04318b41be8dcc62b732f677cdb0c0b10 (diff) | |
download | rtslib-fb-locking.tar.gz |
Add locking around configfs save/restore/clear operationslocking
One concern raised on the list recently was that concurrent readers and
writers to configfs could result in things blowing up. This patch adds
a lock, which should serialize save, restore, and clear operations that
are used by targetctl, and potentially other clients via the rtslib API.
However, targetcli uses rtslib objects returned from other RTSRoot methods,
and could also potentially cause issues. We need to determine if we are OK
with that, or if more steps need to be taken to avoid this.
Signed-off-by: Andy Grover <agrover@redhat.com>
Diffstat (limited to 'rtslib/utils.py')
-rw-r--r-- | rtslib/utils.py | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/rtslib/utils.py b/rtslib/utils.py index 8f86d6d..1f36946 100644 --- a/rtslib/utils.py +++ b/rtslib/utils.py @@ -23,6 +23,8 @@ import stat import uuid import socket import subprocess +import fcntl +import time from contextlib import contextmanager class RTSLibError(Exception): @@ -391,6 +393,35 @@ def ignored(*exceptions): except exceptions: pass +@contextmanager +def file_lock(lock_file, timeout=10): + ''' + A context manager for locking a file, with timeout. + ''' + with open(lock_file, "w") as f: + for x in xrange(timeout): + try: + fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB) + except IOError: + time.sleep(1) + else: + try: + yield + finally: + fcntl.lockf(f, fcntl.LOCK_UN) + break + else: + raise IOError("Acquiring lock timed out after %d seconds" % timeout) + +def locked(func): + ''' + A decorator that enforces mutual exclusion between methods using it. + ''' + def inner(*args, **kwargs): + with file_lock("/var/run/target.lock"): + return func(*args, **kwargs) + return inner + # # These two functions are meant to be used with functools.partial and # properties. |