summaryrefslogtreecommitdiffstats
path: root/lib/locking/file_locking.c
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2009-09-02 14:47:39 +0000
committerPetr Rockai <prockai@redhat.com>2009-09-02 14:47:39 +0000
commit74aa6b56205ea8b40c5fceea94e0578f88f87d7e (patch)
treecc338c97f9ef6e386208664e9313ed746629091a /lib/locking/file_locking.c
parentc99b9fa9461561c1f40f040bd9ec146d093ce3c1 (diff)
downloadlvm2-74aa6b56205ea8b40c5fceea94e0578f88f87d7e.tar.gz
lvm2-74aa6b56205ea8b40c5fceea94e0578f88f87d7e.tar.xz
lvm2-74aa6b56205ea8b40c5fceea94e0578f88f87d7e.zip
Implement write lock prioritisation for file locking and make it default.
Diffstat (limited to 'lib/locking/file_locking.c')
-rw-r--r--lib/locking/file_locking.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c
index 0e1e8124..0ee8bbf8 100644
--- a/lib/locking/file_locking.c
+++ b/lib/locking/file_locking.c
@@ -38,6 +38,7 @@ struct lock_list {
static struct dm_list _lock_list;
static char _lock_dir[NAME_LEN];
+static int _prioritise_write_locks;
static sig_t _oldhandler;
static sigset_t _fullsigset, _intsigset;
@@ -47,6 +48,7 @@ static void _undo_flock(const char *file, int fd)
{
struct stat buf1, buf2;
+ log_debug("_undo_flock %s", file);
if (!flock(fd, LOCK_NB | LOCK_EX) &&
!stat(file, &buf1) &&
!fstat(fd, &buf2) &&
@@ -135,6 +137,8 @@ static int _do_flock(const char *file, int *fd, int operation, uint32_t nonblock
int old_errno;
struct stat buf1, buf2;
+ log_debug("_do_flock %s %c%c",
+ file, operation == LOCK_EX ? 'W' : 'R', nonblock ? ' ' : 'B');
do {
if ((*fd > -1) && close(*fd))
log_sys_error("close", file);
@@ -169,6 +173,29 @@ static int _do_flock(const char *file, int *fd, int operation, uint32_t nonblock
return_0;
}
+#define AUX_LOCK_SUFFIX ":aux"
+
+static int _do_write_priority_flock(const char *file, int *fd, int operation, uint32_t nonblock)
+{
+ int r, fd_aux = -1;
+ char *file_aux = alloca(strlen(file) + sizeof(AUX_LOCK_SUFFIX));
+
+ strcpy(file_aux, file);
+ strcat(file_aux, AUX_LOCK_SUFFIX);
+
+ if ((r = _do_flock(file_aux, &fd_aux, LOCK_EX, 0))) {
+ if (operation == LOCK_EX) {
+ r = _do_flock(file, fd, operation, nonblock);
+ _undo_flock(file_aux, fd_aux);
+ } else {
+ _undo_flock(file_aux, fd_aux);
+ r = _do_flock(file, fd, operation, nonblock);
+ }
+ }
+
+ return r;
+}
+
static int _lock_file(const char *file, uint32_t flags)
{
int operation;
@@ -207,7 +234,11 @@ static int _lock_file(const char *file, uint32_t flags)
log_very_verbose("Locking %s %c%c", ll->res, state,
nonblock ? ' ' : 'B');
- r = _do_flock(file, &ll->lf, operation, nonblock);
+ if (_prioritise_write_locks)
+ r = _do_write_priority_flock(file, &ll->lf, operation, nonblock);
+ else
+ r = _do_flock(file, &ll->lf, operation, nonblock);
+
if (r)
dm_list_add(&_lock_list, &ll->list);
else {
@@ -299,6 +330,10 @@ int init_file_locking(struct locking_type *locking, struct cmd_context *cmd)
DEFAULT_LOCK_DIR),
sizeof(_lock_dir));
+ _prioritise_write_locks =
+ find_config_tree_bool(cmd, "global/prioritise_write_locks",
+ DEFAULT_PRIORITISE_WRITE_LOCKS);
+
if (!dm_create_dir(_lock_dir))
return 0;