summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WHATS_NEW1
-rw-r--r--doc/example.conf7
-rw-r--r--lib/config/defaults.h1
-rw-r--r--lib/locking/file_locking.c37
4 files changed, 45 insertions, 1 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 2576b0cc..dc378fb9 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.52 -
=================================
+ Implement write lock prioritisation for file locking and make it default.
Fix clogd build direcory.
Drop unrequired clogd Makefile.
Fix clvmd autodetection check and cleanup related configure messages.
diff --git a/doc/example.conf b/doc/example.conf
index 5bb20722..eaf922ba 100644
--- a/doc/example.conf
+++ b/doc/example.conf
@@ -288,6 +288,13 @@ global {
# in progress. A directory like /tmp that may get wiped on reboot is OK.
locking_dir = "/var/lock/lvm"
+ # Whenever a read-only and read-write access compete on a single volume
+ # group, ensure that the write lock gets priority over the read lock.
+ # Without this setting, write access may be stalled by high volume of
+ # read-only traffic on LVM metadata. NB. This option only affects
+ # locking_type = 1, i.e. local file-based locking.
+ prioritise_write_locks = 1
+
# Other entries can go here to allow you to load shared libraries
# e.g. if support for LVM1 metadata was compiled as a shared library use
# format_libraries = "liblvm2format1.so"
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 68dceb10..d483492b 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -42,6 +42,7 @@
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
#define DEFAULT_WAIT_FOR_LOCKS 1
+#define DEFAULT_PRIORITISE_WRITE_LOCKS 1
#define DEFAULT_MIRRORLOG "disk"
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
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;