Blame SOURCES/lvm2-2_02_183-io-use-sync-io-if-aio-fails.patch

3a5d46
 lib/commands/toolcontext.c   |  2 ++
3a5d46
 lib/config/config_settings.h |  3 +++
3a5d46
 lib/config/defaults.h        |  1 +
3a5d46
 lib/device/bcache.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
3a5d46
 lib/label/label.c            | 17 +++++++++++++----
3a5d46
 lib/misc/lvm-globals.c       | 11 +++++++++++
3a5d46
 lib/misc/lvm-globals.h       |  2 ++
3a5d46
 7 files changed, 74 insertions(+), 4 deletions(-)
3a5d46
3a5d46
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
3a5d46
index 2b72645..4d3f744 100644
3a5d46
--- a/lib/commands/toolcontext.c
3a5d46
+++ b/lib/commands/toolcontext.c
3a5d46
@@ -341,6 +341,8 @@ static void _init_logging(struct cmd_context *cmd)
3a5d46
 	    find_config_tree_bool(cmd, global_test_CFG, NULL);
3a5d46
 	init_test(cmd->default_settings.test);
3a5d46
 
3a5d46
+	init_use_aio(find_config_tree_bool(cmd, global_use_aio_CFG, NULL));
3a5d46
+
3a5d46
 	/* Settings for logging to file */
3a5d46
 	if (find_config_tree_bool(cmd, log_overwrite_CFG, NULL))
3a5d46
 		append = 0;
3a5d46
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
3a5d46
index 6d79087..2de3fd4 100644
3a5d46
--- a/lib/config/config_settings.h
3a5d46
+++ b/lib/config/config_settings.h
3a5d46
@@ -947,6 +947,9 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa
3a5d46
 	"Previously this was always shown as /dev/vgname/lvname even when that\n"
3a5d46
 	"was never a valid path in the /dev filesystem.\n")
3a5d46
 
3a5d46
+cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL,
3a5d46
+	"Use async I/O when reading and writing devices.\n")
3a5d46
+
3a5d46
 cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LVMETAD, vsn(2, 2, 93), "@DEFAULT_USE_LVMETAD@", 0, NULL,
3a5d46
 	"Use lvmetad to cache metadata and reduce disk scanning.\n"
3a5d46
 	"When enabled (and running), lvmetad provides LVM commands with VG\n"
3a5d46
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
3a5d46
index 1a11009..b3e6c34 100644
3a5d46
--- a/lib/config/defaults.h
3a5d46
+++ b/lib/config/defaults.h
3a5d46
@@ -59,6 +59,7 @@
3a5d46
 #define DEFAULT_METADATA_READ_ONLY 0
3a5d46
 #define DEFAULT_LVDISPLAY_SHOWS_FULL_DEVICE_PATH 0
3a5d46
 #define DEFAULT_UNKNOWN_DEVICE_NAME "[unknown]"
3a5d46
+#define DEFAULT_USE_AIO 1
3a5d46
 
3a5d46
 #define DEFAULT_SANLOCK_LV_EXTEND_MB 256
3a5d46
 
3a5d46
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
3a5d46
index 5ac2558..1cb1b2f 100644
3a5d46
--- a/lib/device/bcache.c
3a5d46
+++ b/lib/device/bcache.c
3a5d46
@@ -380,6 +380,48 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
3a5d46
         	return false;
3a5d46
 	}
3a5d46
 
3a5d46
+	/*
3a5d46
+	 * If bcache block goes past where lvm wants to write, then clamp it.
3a5d46
+	 */
3a5d46
+	if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) {
3a5d46
+		uint64_t offset = where;
3a5d46
+		uint64_t nbytes = len;
3a5d46
+		sector_t limit_nbytes = 0;
3a5d46
+		sector_t extra_nbytes = 0;
3a5d46
+
3a5d46
+		if (offset > _last_byte_offset) {
3a5d46
+			log_error("Limit write at %llu len %llu beyond last byte %llu",
3a5d46
+				  (unsigned long long)offset,
3a5d46
+				  (unsigned long long)nbytes,
3a5d46
+				  (unsigned long long)_last_byte_offset);
3a5d46
+			return false;
3a5d46
+		}
3a5d46
+
3a5d46
+		if (offset + nbytes > _last_byte_offset) {
3a5d46
+			limit_nbytes = _last_byte_offset - offset;
3a5d46
+			if (limit_nbytes % _last_byte_sector_size)
3a5d46
+				extra_nbytes = _last_byte_sector_size - (limit_nbytes % _last_byte_sector_size);
3a5d46
+
3a5d46
+			if (extra_nbytes) {
3a5d46
+				log_debug("Limit write at %llu len %llu to len %llu rounded to %llu",
3a5d46
+					  (unsigned long long)offset,
3a5d46
+					  (unsigned long long)nbytes,
3a5d46
+					  (unsigned long long)limit_nbytes,
3a5d46
+					  (unsigned long long)(limit_nbytes + extra_nbytes));
3a5d46
+				nbytes = limit_nbytes + extra_nbytes;
3a5d46
+			} else {
3a5d46
+				log_debug("Limit write at %llu len %llu to len %llu",
3a5d46
+					  (unsigned long long)offset,
3a5d46
+					  (unsigned long long)nbytes,
3a5d46
+					  (unsigned long long)limit_nbytes);
3a5d46
+				nbytes = limit_nbytes;
3a5d46
+			}
3a5d46
+		}
3a5d46
+
3a5d46
+		where = offset;
3a5d46
+		len = nbytes;
3a5d46
+	}
3a5d46
+
3a5d46
 	while (len) {
3a5d46
         	do {
3a5d46
                 	if (d == DIR_READ)
3a5d46
diff --git a/lib/label/label.c b/lib/label/label.c
3a5d46
index d2cfe62..e7e3997 100644
3a5d46
--- a/lib/label/label.c
3a5d46
+++ b/lib/label/label.c
3a5d46
@@ -797,7 +797,7 @@ out:
3a5d46
 
3a5d46
 static int _setup_bcache(int cache_blocks)
3a5d46
 {
3a5d46
-	struct io_engine *ioe;
3a5d46
+	struct io_engine *ioe = NULL;
3a5d46
 
3a5d46
 	if (cache_blocks < MIN_BCACHE_BLOCKS)
3a5d46
 		cache_blocks = MIN_BCACHE_BLOCKS;
3a5d46
@@ -805,9 +805,18 @@ static int _setup_bcache(int cache_blocks)
3a5d46
 	if (cache_blocks > MAX_BCACHE_BLOCKS)
3a5d46
 		cache_blocks = MAX_BCACHE_BLOCKS;
3a5d46
 
3a5d46
-	if (!(ioe = create_async_io_engine())) {
3a5d46
-		log_error("Failed to create bcache io engine.");
3a5d46
-		return 0;
3a5d46
+	if (use_aio()) {
3a5d46
+		if (!(ioe = create_async_io_engine())) {
3a5d46
+			log_warn("Failed to set up async io, using sync io.");
3a5d46
+			init_use_aio(0);
3a5d46
+		}
3a5d46
+	}
3a5d46
+
3a5d46
+	if (!ioe) {
3a5d46
+		if (!(ioe = create_sync_io_engine())) {
3a5d46
+			log_error("Failed to set up sync io.");
3a5d46
+			return 0;
3a5d46
+		}
3a5d46
 	}
3a5d46
 
3a5d46
 	if (!(scan_bcache = bcache_create(BCACHE_BLOCK_SIZE_IN_SECTORS, cache_blocks, ioe))) {
3a5d46
diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c
3a5d46
index 9941489..82c5706 100644
3a5d46
--- a/lib/misc/lvm-globals.c
3a5d46
+++ b/lib/misc/lvm-globals.c
3a5d46
@@ -24,6 +24,7 @@
3a5d46
 static int _verbose_level = VERBOSE_BASE_LEVEL;
3a5d46
 static int _silent = 0;
3a5d46
 static int _test = 0;
3a5d46
+static int _use_aio = 0;
3a5d46
 static int _md_filtering = 0;
3a5d46
 static int _internal_filtering = 0;
3a5d46
 static int _fwraid_filtering = 0;
3a5d46
@@ -71,6 +72,11 @@ void init_test(int level)
3a5d46
 	_test = level;
3a5d46
 }
3a5d46
 
3a5d46
+void init_use_aio(int use_aio)
3a5d46
+{
3a5d46
+	_use_aio = use_aio;
3a5d46
+}
3a5d46
+
3a5d46
 void init_md_filtering(int level)
3a5d46
 {
3a5d46
 	_md_filtering = level;
3a5d46
@@ -227,6 +233,11 @@ int test_mode(void)
3a5d46
 	return _test;
3a5d46
 }
3a5d46
 
3a5d46
+int use_aio(void)
3a5d46
+{
3a5d46
+	return _use_aio;
3a5d46
+}
3a5d46
+
3a5d46
 int md_filtering(void)
3a5d46
 {
3a5d46
 	return _md_filtering;
3a5d46
diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h
3a5d46
index b383891..f985cfa 100644
3a5d46
--- a/lib/misc/lvm-globals.h
3a5d46
+++ b/lib/misc/lvm-globals.h
3a5d46
@@ -25,6 +25,7 @@ enum dev_ext_e;
3a5d46
 void init_verbose(int level);
3a5d46
 void init_silent(int silent);
3a5d46
 void init_test(int level);
3a5d46
+void init_use_aio(int use_aio);
3a5d46
 void init_md_filtering(int level);
3a5d46
 void init_internal_filtering(int level);
3a5d46
 void init_fwraid_filtering(int level);
3a5d46
@@ -58,6 +59,7 @@ const char *get_cmd_name(void);
3a5d46
 void set_sysfs_dir_path(const char *path);
3a5d46
 
3a5d46
 int test_mode(void);
3a5d46
+int use_aio(void);
3a5d46
 int md_filtering(void);
3a5d46
 int internal_filtering(void);
3a5d46
 int fwraid_filtering(void);