master - [device/bcache] Initial code drop.
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=acb42ec4652450f7cd7...
Commit: acb42ec4652450f7cd73440929fd57f1487282bf
Parent: 00f1b208a1bf44665ec97a791355b1fcf525a3a7
Author: Joe Thornber <ejt(a)redhat.com>
AuthorDate: Tue Jan 30 10:46:08 2018 +0000
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:10:45 2018 -0500
[device/bcache] Initial code drop.
Compiles. Not written tests yet.
---
lib/device/bcache.c | 833 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/device/bcache.h | 83 +++++
2 files changed, 916 insertions(+), 0 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
new file mode 100644
index 0000000..1be626c
--- /dev/null
+++ b/lib/device/bcache.c
@@ -0,0 +1,833 @@
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <libaio.h>
+#include <unistd.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <sys/user.h>
+
+#include "bcache.h"
+#include "dm-logging.h"
+#include "log.h"
+
+#define SECTOR_SHIFT 9L
+
+//----------------------------------------------------------------
+
+// Assumes the list is not empty.
+static inline struct dm_list *_list_pop(struct dm_list *head)
+{
+ struct dm_list *l;
+
+ l = head->n;
+ dm_list_del(l);
+ return l;
+}
+
+//----------------------------------------------------------------
+
+struct control_block {
+ struct dm_list list;
+ void *context;
+ struct iocb cb;
+};
+
+struct cb_set {
+ struct dm_list free;
+ struct dm_list allocated;
+ struct control_block *vec;
+} control_block_set;
+
+static struct cb_set *_cb_set_create(unsigned nr)
+{
+ int i;
+ struct cb_set *cbs = malloc(sizeof(*cbs));
+
+ if (!cbs)
+ return NULL;
+
+ cbs->vec = malloc(nr * sizeof(*cbs->vec));
+ if (!cbs->vec) {
+ free(cbs);
+ return NULL;
+ }
+
+ dm_list_init(&cbs->free);
+ dm_list_init(&cbs->allocated);
+
+ for (i = 0; i < nr; i++)
+ dm_list_add(&cbs->free, &cbs->vec[i].list);
+
+ return cbs;
+}
+
+static bool _cb_set_destroy(struct cb_set *cbs)
+{
+ if (!dm_list_empty(&cbs->allocated)) {
+ // FIXME: I think we should propogate this up.
+ log_error("async io still in flight");
+ return false;
+ }
+
+ free(cbs->vec);
+ free(cbs);
+ return 0;
+}
+
+static struct control_block *_cb_alloc(struct cb_set *cbs, void *context)
+{
+ struct control_block *cb;
+
+ if (dm_list_empty(&cbs->free))
+ return NULL;
+
+ cb = dm_list_item(_list_pop(&cbs->free), struct control_block);
+ cb->context = context;
+ dm_list_add(&cbs->allocated, &cb->list);
+
+ return cb;
+}
+
+static void _cb_free(struct cb_set *cbs, struct control_block *cb)
+{
+ dm_list_del(&cb->list);
+ dm_list_add_h(&cbs->free, &cb->list);
+}
+
+static struct control_block *_iocb_to_cb(struct iocb *icb)
+{
+ return dm_list_struct_base(icb, struct control_block, cb);
+}
+
+//----------------------------------------------------------------
+
+// FIXME: write a sync engine too
+enum dir {
+ DIR_READ,
+ DIR_WRITE
+};
+
+struct io_engine {
+ io_context_t aio_context;
+ struct cb_set *cbs;
+};
+
+static struct io_engine *_engine_create(unsigned max_io)
+{
+ int r;
+ struct io_engine *e = malloc(sizeof(*e));
+
+ if (!e)
+ return NULL;
+
+ e->aio_context = 0;
+ r = io_setup(max_io, &e->aio_context);
+ if (r < 0) {
+ log_warn("io_setup failed");
+ return NULL;
+ }
+
+ e->cbs = _cb_set_create(max_io);
+ if (!e->cbs) {
+ log_warn("couldn't create control block set");
+ free(e);
+ return NULL;
+ }
+
+ return e;
+}
+
+static void _engine_destroy(struct io_engine *e)
+{
+ _cb_set_destroy(e->cbs);
+ io_destroy(e->aio_context);
+ free(e);
+}
+
+static bool _engine_issue(struct io_engine *e, int fd, enum dir d,
+ sector_t sb, sector_t se, void *data, void *context)
+{
+ int r;
+ struct iocb *cb_array[1];
+ struct control_block *cb;
+
+ if (((uint64_t) data) & (PAGE_SIZE - 1)) {
+ log_err("misaligned data buffer");
+ return false;
+ }
+
+ cb = _cb_alloc(e->cbs, context);
+ if (!cb) {
+ log_err("couldn't allocate control block");
+ return false;
+ }
+
+ memset(&cb->cb, 0, sizeof(cb->cb));
+
+ cb->cb.aio_fildes = (int) fd;
+ cb->cb.u.c.buf = data;
+ cb->cb.u.c.offset = sb << SECTOR_SHIFT;
+ cb->cb.u.c.nbytes = (se - sb) << SECTOR_SHIFT;
+ cb->cb.aio_lio_opcode = (d == DIR_READ) ? IO_CMD_PREAD : IO_CMD_PWRITE;
+
+ cb_array[0] = &cb->cb;
+ r = io_submit(e->aio_context, 1, cb_array);
+ if (r < 0) {
+ log_sys_error("io_submit", "");
+ _cb_free(e->cbs, cb);
+ return false;
+ }
+
+ return true;
+}
+
+#define MAX_IO 64
+typedef void complete_fn(void *context, int io_error);
+
+static bool _engine_wait(struct io_engine *e, complete_fn fn)
+{
+ int i, r;
+ struct io_event event[MAX_IO];
+ struct control_block *cb;
+
+ memset(&event, 0, sizeof(event));
+ r = io_getevents(e->aio_context, 1, MAX_IO, event, NULL);
+ if (r < 0) {
+ log_sys_error("io_getevents", "");
+ return false;
+ }
+
+ for (i = 0; i < r; i++) {
+ struct io_event *ev = event + i;
+
+ cb = _iocb_to_cb((struct iocb *) ev->obj);
+
+ if (ev->res == cb->cb.u.c.nbytes)
+ fn((void *) cb->context, 0);
+
+ else if ((int) ev->res < 0)
+ fn(cb->context, (int) ev->res);
+
+ else {
+ log_err("short io");
+ fn(cb->context, -ENODATA);
+ }
+
+ _cb_free(e->cbs, cb);
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------
+
+#define MIN_BLOCKS 16
+#define WRITEBACK_LOW_THRESHOLD_PERCENT 33
+#define WRITEBACK_HIGH_THRESHOLD_PERCENT 66
+
+//----------------------------------------------------------------
+
+static void *_alloc_aligned(size_t len, size_t alignment)
+{
+ void *result = NULL;
+ int r = posix_memalign(&result, alignment, len);
+ if (r)
+ return NULL;
+
+ return result;
+}
+
+//----------------------------------------------------------------
+
+static bool _test_flags(struct block *b, unsigned bits)
+{
+ return (b->flags & bits) != 0;
+}
+
+static void _set_flags(struct block *b, unsigned bits)
+{
+ b->flags |= bits;
+}
+
+static void _clear_flags(struct block *b, unsigned bits)
+{
+ b->flags &= ~bits;
+}
+
+//----------------------------------------------------------------
+
+enum block_flags {
+ BF_IO_PENDING = (1 << 0),
+ BF_DIRTY = (1 << 1),
+};
+
+struct bcache {
+ int fd;
+ sector_t block_sectors;
+ uint64_t nr_data_blocks;
+ uint64_t nr_cache_blocks;
+
+ struct io_engine *engine;
+
+ void *raw_data;
+ struct block *raw_blocks;
+
+ /*
+ * Lists that categorise the blocks.
+ */
+ unsigned nr_locked;
+ unsigned nr_dirty;
+ unsigned nr_io_pending;
+
+ struct dm_list free;
+ struct dm_list errored;
+ struct dm_list dirty;
+ struct dm_list clean;
+ struct dm_list io_pending;
+
+ /*
+ * Hash table.
+ */
+ unsigned nr_buckets;
+ unsigned hash_mask;
+ struct dm_list *buckets;
+
+ /*
+ * Statistics
+ */
+ unsigned read_hits;
+ unsigned read_misses;
+ unsigned write_zeroes;
+ unsigned write_hits;
+ unsigned write_misses;
+ unsigned prefetches;
+};
+
+//----------------------------------------------------------------
+
+/* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
+#define GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001UL
+
+static unsigned _hash(struct bcache *cache, int fd, uint64_t index)
+{
+ uint64_t h = (index << 10) & fd;
+ h *= GOLDEN_RATIO_PRIME_64;
+ return h & cache->hash_mask;
+}
+
+static struct block *_hash_lookup(struct bcache *cache, int fd, uint64_t index)
+{
+ struct block *b;
+ unsigned h = _hash(cache, fd, index);
+
+ dm_list_iterate_items_gen (b, cache->buckets + h, hash)
+ if (b->index == index)
+ return b;
+
+ return NULL;
+}
+
+static void _hash_insert(struct block *b)
+{
+ unsigned h = _hash(b->cache, b->fd, b->index);
+ dm_list_add_h(b->cache->buckets + h, &b->hash);
+}
+
+static void _hash_remove(struct block *b)
+{
+ dm_list_del(&b->hash);
+}
+
+/*
+ * Must return a power of 2.
+ */
+static unsigned _calc_nr_buckets(unsigned nr_blocks)
+{
+ unsigned r = 8;
+ unsigned n = nr_blocks / 4;
+
+ if (n < 8)
+ n = 8;
+
+ while (r < n)
+ r <<= 1;
+
+ return r;
+}
+
+static int _hash_table_init(struct bcache *cache, unsigned nr_entries)
+{
+ unsigned i;
+
+ cache->nr_buckets = _calc_nr_buckets(nr_entries);
+ cache->hash_mask = cache->nr_buckets - 1;
+ cache->buckets = malloc(cache->nr_buckets * sizeof(*cache->buckets));
+ if (!cache->buckets)
+ return -ENOMEM;
+
+ for (i = 0; i < cache->nr_buckets; i++)
+ dm_list_init(cache->buckets + i);
+
+ return 0;
+}
+
+static void _hash_table_exit(struct bcache *cache)
+{
+ free(cache->buckets);
+}
+
+//----------------------------------------------------------------
+
+static int _init_free_list(struct bcache *cache, unsigned count)
+{
+ unsigned i;
+ size_t block_size = cache->block_sectors << SECTOR_SHIFT;
+ unsigned char *data =
+ (unsigned char *) _alloc_aligned(count * block_size, PAGE_SIZE);
+
+ /* Allocate the data for each block. We page align the data. */
+ if (!data)
+ return -ENOMEM;
+
+ cache->raw_data = data;
+ cache->raw_blocks = malloc(count * sizeof(*cache->raw_blocks));
+
+ if (!cache->raw_blocks)
+ free(cache->raw_data);
+
+ for (i = 0; i < count; i++) {
+ struct block *b = cache->raw_blocks + i;
+ b->cache = cache;
+ b->data = data + (block_size * i);
+ dm_list_add(&cache->free, &b->list);
+ }
+
+ return 0;
+}
+
+static void _exit_free_list(struct bcache *cache)
+{
+ free(cache->raw_data);
+ free(cache->raw_blocks);
+}
+
+static struct block *_alloc_block(struct bcache *cache)
+{
+ struct block *b = dm_list_struct_base(_list_pop(&cache->free), struct block, list);
+ return b;
+}
+
+/*----------------------------------------------------------------
+ * Clean/dirty list management.
+ * Always use these methods to ensure nr_dirty_ is correct.
+ *--------------------------------------------------------------*/
+
+static void _unlink_block(struct block *b)
+{
+ if (_test_flags(b, BF_DIRTY))
+ b->cache->nr_dirty--;
+
+ dm_list_del(&b->list);
+}
+
+static void _link_block(struct block *b)
+{
+ struct bcache *cache = b->cache;
+
+ if (_test_flags(b, BF_DIRTY)) {
+ dm_list_add(&cache->dirty, &b->list);
+ cache->nr_dirty++;
+ } else
+ dm_list_add(&cache->clean, &b->list);
+}
+
+static void _relink(struct block *b)
+{
+ _unlink_block(b);
+ _link_block(b);
+}
+
+/*----------------------------------------------------------------
+ * Low level IO handling
+ *
+ * We cannot have two concurrent writes on the same block.
+ * eg, background writeback, put with dirty, flush?
+ *
+ * To avoid this we introduce some restrictions:
+ *
+ * i) A held block can never be written back.
+ * ii) You cannot get a block until writeback has completed.
+ *
+ *--------------------------------------------------------------*/
+
+/*
+ * |b->list| should be valid (either pointing to itself, on one of the other
+ * lists.
+ */
+static bool _issue_low_level(struct block *b, enum dir d)
+{
+ struct bcache *cache = b->cache;
+ sector_t sb = b->index * cache->block_sectors;
+ sector_t se = sb + cache->block_sectors;
+
+ if (_test_flags(b, BF_IO_PENDING))
+ return false;
+
+ _set_flags(b, BF_IO_PENDING);
+ return _engine_issue(cache->engine, cache->fd, d, sb, se, b->data, b);
+}
+
+static inline bool _issue_read(struct block *b)
+{
+ return _issue_low_level(b, DIR_READ);
+}
+
+static inline bool _issue_write(struct block *b)
+{
+ return _issue_low_level(b, DIR_WRITE);
+}
+
+static void _complete_io(void *context, int err)
+{
+ struct block *b = context;
+ struct bcache *cache = b->cache;
+
+ b->error = err;
+ _clear_flags(b, BF_IO_PENDING);
+ cache->nr_io_pending--;
+
+ /*
+ * b is on the io_pending list, so we don't want to use unlink_block.
+ * Which would incorrectly adjust nr_dirty.
+ */
+ dm_list_del(&b->list);
+
+ if (b->error)
+ dm_list_add(&cache->errored, &b->list);
+
+ else {
+ _clear_flags(b, BF_DIRTY);
+ _link_block(b);
+ }
+}
+
+static int _wait_io(struct bcache *cache)
+{
+ return _engine_wait(cache->engine, _complete_io);
+}
+
+/*----------------------------------------------------------------
+ * High level IO handling
+ *--------------------------------------------------------------*/
+
+static void _wait_all(struct bcache *cache)
+{
+ while (!dm_list_empty(&cache->io_pending))
+ _wait_io(cache);
+}
+
+static void _wait_specific(struct block *b)
+{
+ while (_test_flags(b, BF_IO_PENDING))
+ _wait_io(b->cache);
+}
+
+static unsigned _writeback(struct bcache *cache, unsigned count)
+{
+ unsigned actual = 0;
+ struct block *b, *tmp;
+
+ dm_list_iterate_items_gen_safe (b, tmp, &cache->dirty, list) {
+ if (actual == count)
+ break;
+
+ // We can't writeback anything that's still in use.
+ if (!b->ref_count) {
+ _issue_write(b);
+ actual++;
+ }
+ }
+
+ return actual;
+}
+
+/*----------------------------------------------------------------
+ * High level allocation
+ *--------------------------------------------------------------*/
+
+static struct block *_find_unused_clean_block(struct bcache *cache)
+{
+ struct block *b;
+
+ dm_list_iterate_items (b, &cache->clean) {
+ if (!b->ref_count) {
+ _unlink_block(b);
+ _hash_remove(b);
+ return b;
+ }
+ }
+
+ return NULL;
+}
+
+static struct block *_new_block(struct bcache *cache, block_address index)
+{
+ struct block *b;
+
+ b = _alloc_block(cache);
+ while (!b && cache->nr_locked < cache->nr_cache_blocks) {
+ b = _find_unused_clean_block(cache);
+ if (!b) {
+ if (dm_list_empty(&cache->io_pending))
+ _writeback(cache, 16);
+ _wait_io(cache);
+ }
+ }
+
+ if (b) {
+ dm_list_init(&b->list);
+ dm_list_init(&b->hash);
+ b->flags = 0;
+ b->index = index;
+ b->ref_count = 0;
+ b->error = 0;
+
+ _hash_insert(b);
+ }
+
+ return b;
+}
+
+/*----------------------------------------------------------------
+ * Block reference counting
+ *--------------------------------------------------------------*/
+static void _zero_block(struct block *b)
+{
+ b->cache->write_zeroes++;
+ memset(b->data, 0, b->cache->block_sectors << SECTOR_SHIFT);
+ _set_flags(b, BF_DIRTY);
+}
+
+static void _hit(struct block *b, unsigned flags)
+{
+ struct bcache *cache = b->cache;
+
+ if (flags & (GF_ZERO | GF_DIRTY))
+ cache->write_hits++;
+ else
+ cache->read_hits++;
+
+ _relink(b);
+}
+
+static void _miss(struct bcache *cache, unsigned flags)
+{
+ if (flags & (GF_ZERO | GF_DIRTY))
+ cache->write_misses++;
+ else
+ cache->read_misses++;
+}
+
+static struct block *_lookup_or_read_block(struct bcache *cache,
+ int fd, block_address index,
+ unsigned flags)
+{
+ struct block *b = _hash_lookup(cache, fd, index);
+
+ if (b) {
+ // FIXME: this is insufficient. We need to also catch a read
+ // lock of a write locked block. Ref count needs to distinguish.
+ if (b->ref_count && (flags & (GF_DIRTY | GF_ZERO))) {
+ log_err("concurrent write lock attempted");
+ return NULL;
+ }
+
+ if (_test_flags(b, BF_IO_PENDING)) {
+ _miss(cache, flags);
+ _wait_specific(b);
+
+ } else
+ _hit(b, flags);
+
+ _unlink_block(b);
+
+ if (flags & GF_ZERO)
+ _zero_block(b);
+
+ } else {
+ _miss(cache, flags);
+
+ b = _new_block(cache, index);
+ if (b) {
+ if (flags & GF_ZERO)
+ _zero_block(b);
+
+ else {
+ _issue_read(b);
+ _wait_specific(b);
+
+ // we know the block is clean and unerrored.
+ _unlink_block(b);
+ }
+ }
+ }
+
+ if (b && !b->error) {
+ if (flags & (GF_DIRTY | GF_ZERO))
+ _set_flags(b, BF_DIRTY);
+
+ _link_block(b);
+ return b;
+ }
+
+ return NULL;
+}
+
+static void _preemptive_writeback(struct bcache *cache)
+{
+ // FIXME: this ignores those blocks that are in the error state. Track
+ // nr_clean instead?
+ unsigned nr_available = cache->nr_cache_blocks - (cache->nr_dirty - cache->nr_io_pending);
+ if (nr_available < (WRITEBACK_LOW_THRESHOLD_PERCENT * cache->nr_cache_blocks / 100))
+ _writeback(cache, (WRITEBACK_HIGH_THRESHOLD_PERCENT * cache->nr_cache_blocks / 100) - nr_available);
+
+}
+
+/*----------------------------------------------------------------
+ * Public interface
+ *--------------------------------------------------------------*/
+struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks)
+{
+ int r;
+ struct bcache *cache;
+
+ cache = malloc(sizeof(*cache));
+ if (!cache)
+ return NULL;
+
+ cache->block_sectors = block_sectors;
+ cache->nr_cache_blocks = nr_cache_blocks;
+
+ cache->engine = _engine_create(nr_cache_blocks < 1024u ? nr_cache_blocks : 1024u);
+ if (!cache->engine) {
+ free(cache);
+ return NULL;
+ }
+
+ cache->nr_locked = 0;
+ cache->nr_dirty = 0;
+ cache->nr_io_pending = 0;
+
+ dm_list_init(&cache->free);
+ dm_list_init(&cache->errored);
+ dm_list_init(&cache->dirty);
+ dm_list_init(&cache->clean);
+ dm_list_init(&cache->io_pending);
+
+ if (_hash_table_init(cache, nr_cache_blocks)) {
+ _engine_destroy(cache->engine);
+ free(cache);
+ }
+
+ cache->read_hits = 0;
+ cache->read_misses = 0;
+ cache->write_zeroes = 0;
+ cache->write_hits = 0;
+ cache->write_misses = 0;
+ cache->prefetches = 0;
+
+ r = _init_free_list(cache, nr_cache_blocks);
+ if (r) {
+ _engine_destroy(cache->engine);
+ _hash_table_exit(cache);
+ free(cache);
+ }
+
+ return cache;
+}
+
+void bcache_destroy(struct bcache *cache)
+{
+ if (cache->nr_locked)
+ log_warn("some blocks are still locked\n");
+
+ bcache_flush(cache);
+ _wait_all(cache);
+ _exit_free_list(cache);
+ _hash_table_exit(cache);
+ _engine_destroy(cache->engine);
+ free(cache);
+}
+
+void bcache_prefetch(struct bcache *cache, int fd, block_address index)
+{
+ struct block *b = _hash_lookup(cache, fd, index);
+
+ if (!b) {
+ cache->prefetches++;
+
+ b = _new_block(cache, index);
+ if (b)
+ _issue_read(b);
+ }
+}
+
+bool bcache_get(struct bcache *cache, int fd, block_address index,
+ unsigned flags, struct block **result)
+{
+ struct block *b = _lookup_or_read_block(cache, fd, index, flags);
+ if (b) {
+ if (!b->ref_count)
+ cache->nr_locked++;
+ b->ref_count++;
+
+ *result = b;
+ return true;
+ }
+
+ *result = NULL;
+ log_err("couldn't get block");
+ return false;
+}
+
+void bcache_put(struct block *b)
+{
+ if (!b->ref_count) {
+ log_err("ref count on bcache block already zero");
+ return;
+ }
+
+ b->ref_count--;
+ if (!b->ref_count)
+ b->cache->nr_locked--;
+
+ if (_test_flags(b, BF_DIRTY))
+ _preemptive_writeback(b->cache);
+}
+
+int bcache_flush(struct bcache *cache)
+{
+ while (!dm_list_empty(&cache->dirty)) {
+ struct block *b = dm_list_item(_list_pop(&cache->dirty), struct block);
+ if (b->ref_count || _test_flags(b, BF_IO_PENDING))
+ // The superblock may well be still locked.
+ continue;
+
+ _issue_write(b);
+ }
+
+ _wait_all(cache);
+
+ return dm_list_empty(&cache->errored) ? 0 : -EIO;
+}
+
+//----------------------------------------------------------------
+
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
new file mode 100644
index 0000000..1f4262e
--- /dev/null
+++ b/lib/device/bcache.h
@@ -0,0 +1,83 @@
+#ifndef BCACHE_H
+#define BCACHE_H
+
+#include <stdint.h>
+
+#include "libdevmapper.h"
+
+/*----------------------------------------------------------------*/
+
+typedef uint64_t block_address;
+typedef uint64_t sector_t;
+
+struct bcache;
+struct block {
+ /* clients may only access these three fields */
+ int fd;
+ uint64_t index;
+ void *data;
+
+ struct bcache *cache;
+ struct dm_list list;
+ struct dm_list hash;
+
+ unsigned flags;
+ unsigned ref_count;
+ int error;
+};
+
+struct bcache *bcache_create(sector_t block_size, unsigned nr_cache_blocks);
+void bcache_destroy(struct bcache *cache);
+
+enum bcache_get_flags {
+ /*
+ * The block will be zeroed before get_block returns it. This
+ * potentially avoids a read if the block is not already in the cache.
+ * GF_DIRTY is implicit.
+ */
+ GF_ZERO = (1 << 0),
+
+ /*
+ * Indicates the caller is intending to change the data in the block, a
+ * writeback will occur after the block is released.
+ */
+ GF_DIRTY = (1 << 1)
+};
+
+typedef uint64_t block_address;
+
+unsigned bcache_get_max_prefetches(struct bcache *cache);
+
+/*
+ * Use the prefetch method to take advantage of asynchronous IO. For example,
+ * if you wanted to read a block from many devices concurrently you'd do
+ * something like this:
+ *
+ * dm_list_iterate_items (dev, &devices)
+ * bcache_prefetch(cache, dev->fd, block);
+ *
+ * dm_list_iterate_items (dev, &devices) {
+ * if (!bcache_get(cache, dev->fd, block, &b))
+ * fail();
+ *
+ * process_block(b);
+ * }
+ *
+ * It's slightly sub optimal, since you may not run the gets in the order that
+ * they complete. But we're talking a very small difference, and it's worth it
+ * to keep callbacks out of this interface.
+ */
+void bcache_prefetch(struct bcache *cache, int fd, block_address index);
+
+/*
+ * Returns true on success.
+ */
+bool bcache_get(struct bcache *cache, int fd, block_address index,
+ unsigned flags, struct block **result);
+void bcache_put(struct block *b);
+
+int bcache_flush(struct bcache *cache);
+
+/*----------------------------------------------------------------*/
+
+#endif
6 years
master - tests: improve mirror_images_redundant
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=d51429254f4e9b17083...
Commit: d51429254f4e9b17083af0c554aa7045e5ec08bb
Parent: ac18005de93de30db445e5fde6abdb801ee6e2a6
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Apr 20 10:15:14 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
tests: improve mirror_images_redundant
Use only passed VG for lvs and avoid 1 extra uneeded use of lvs.
---
test/lib/check.sh | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/test/lib/check.sh b/test/lib/check.sh
index ed4f8d7..c796104 100644
--- a/test/lib/check.sh
+++ b/test/lib/check.sh
@@ -41,7 +41,6 @@ lvdevices() {
mirror_images_redundant() {
local vg=$1
local lv="$vg/$2"
- lvs -a "$vg" -o+devices
for i in $(lvdevices "$lv"); do
echo "# $i:"
lvdevices "$vg/$i" | sort | uniq
@@ -158,7 +157,7 @@ mirror_nonredundant() {
attr=$(get lv_field "$lv" attr)
(echo "$attr" | grep "^......m...$" >/dev/null) || {
if (echo "$attr" | grep "^o.........$" >/dev/null) &&
- lvs -a | grep -F "[${2}_mimage" >/dev/null; then
+ lvs -a $1 | grep -F "[${2}_mimage" >/dev/null; then
echo "TEST WARNING: $lv is a snapshot origin and looks like a mirror,"
echo "assuming it is actually a mirror"
else
6 years
master - tests: update mirror test
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=ac18005de93de30db44...
Commit: ac18005de93de30db445e5fde6abdb801ee6e2a6
Parent: fa5ba7e42d409532ddeea97c5802f042e40935b2
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Fri Apr 20 10:13:21 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
tests: update mirror test
Since lvconvert again is able to wait on mirror synchronization,
drop 'should'.
Also add FIXME about 'lvreduce' and too big region size.
---
test/shell/lvconvert-mirror.sh | 43 +++++++++++++++++++++++----------------
1 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/test/shell/lvconvert-mirror.sh b/test/shell/lvconvert-mirror.sh
index 76ff166..4e18212 100644
--- a/test/shell/lvconvert-mirror.sh
+++ b/test/shell/lvconvert-mirror.sh
@@ -86,11 +86,15 @@ offset=$(get first_extent_sector "$dev2")
offset=$(( offset + 2 ))
# put 1 single slowing delayed sector
# update in case mirror ever gets faster and allows parallel read
-aux delay_dev "$dev2" 0 2000 ${offset}:1
-lvcreate -aey -l5 -Zn -Wn --type mirror --regionsize 16K -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev4" "$dev3:$DEVRANGE"
-should not lvconvert -m-1 $vg/$lv1 "$dev1"
+aux delay_dev "$dev2" 0 10 ${offset}:1
+
+lvcreate -aey -l10 -Zn -Wn --type mirror --regionsize 16k -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev4" "$dev3:$DEVRANGE"
+lvs -a -o+seg_pe_ranges $vg
+not lvconvert -m-1 $vg/$lv1 "$dev1"
+lvconvert $vg/$lv1 # wait
+lvs -a $vg
aux enable_dev "$dev2"
-should lvconvert $vg/$lv1 # wait
+lvconvert $vg/$lv1 # wait
lvconvert -m2 $vg/$lv1 "$dev1" "$dev2" "$dev4" "$dev3:0" # If the above "should" failed...
aux wait_for_sync $vg $lv1
@@ -114,9 +118,9 @@ aux delay_dev "$dev4" 0 2000 ${offset}:
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# Next convert should fail b/c we can't have 2 at once
-should not lvconvert -m+1 $vg/$lv1 "$dev5"
+not lvconvert -m+1 $vg/$lv1 "$dev5"
aux enable_dev "$dev4"
-should lvconvert $vg/$lv1 # wait
+lvconvert $vg/$lv1 # wait
lvconvert -m2 $vg/$lv1 # In case the above "should" actually failed
check mirror $vg $lv1 "$dev3"
@@ -159,7 +163,7 @@ lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE
lvchange -an $vg/$lv1
lvconvert -m+1 $vg/$lv1 "$dev4"
lvchange -aey $vg/$lv1
-should lvconvert $vg/$lv1 # wait
+lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
lvremove -ff $vg
@@ -171,7 +175,7 @@ lvremove -ff $vg
lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE"
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
lvconvert -m-1 $vg/$lv1 "$dev4"
-should lvconvert $vg/$lv1 # wait
+lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -182,7 +186,7 @@ lvremove -ff $vg
lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE"
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+2 -b $vg/$lv1 "$dev4" "$dev5"
lvconvert -m-1 $vg/$lv1 "$dev4"
-should lvconvert $vg/$lv1 # wait
+lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -195,9 +199,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
-should lvconvert $vg/$lv1
+lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
-should lvconvert $vg/$lv1
+lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -210,9 +214,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
-should lvconvert $vg/$lv1
+lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
-should lvconvert $vg/$lv1
+lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -225,9 +229,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
-should lvconvert --startpoll $vg/$lv1
+lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
-should lvconvert --startpoll $vg/$lv1
+lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -255,7 +259,8 @@ lvremove -ff $vg
lvcreate -aey -l 8 -n $lv1 $vg "$dev1:0-3" "$dev2:0-3"
lvconvert --type mirror -m1 $vg/$lv1
-should check mirror $vg $lv1
+# FIXME: lvm should be able to make legs redundant
+#should check mirror $vg $lv1
check mirror_legs $vg $lv1 2
lvremove -ff $vg
@@ -283,7 +288,9 @@ lvremove -ff $vg
# simple mirrored stripe
lvcreate -aey -i2 -l10 -n $lv1 $vg
-lvconvert --type mirror -m1 -i1 $vg/$lv1
+# FIXME: ATM reduce LV still must be bigger then region size!
+# LVM should do a better job here
+lvconvert --type mirror -m1 -i1 --regionsize 16k $vg/$lv1
lvreduce -f -l1 $vg/$lv1
lvextend -f -l10 $vg/$lv1
lvremove -ff $vg/$lv1
@@ -300,7 +307,7 @@ if test -e LOCAL_CLVMD; then
not lvconvert --type mirror -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2"
else
lvconvert --type mirror -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2"
-should check mirror $vg $lv1
+check mirror $vg $lv1
fi
lvremove -ff $vg
6 years
master - coverity: ensure 0 end string
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=fa5ba7e42d409532dde...
Commit: fa5ba7e42d409532ddeea97c5802f042e40935b2
Parent: 037c234eaaabd4989e769e1f9db47c8452fa4966
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Mar 29 19:07:31 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
coverity: ensure 0 end string
Use dm_strncpy() to enusure string ends with '\0'.
In case uuid does not fit, report error.
---
daemons/cmirrord/cluster.c | 2 +-
daemons/cmirrord/functions.c | 10 +++++++---
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/daemons/cmirrord/cluster.c b/daemons/cmirrord/cluster.c
index e56d8f3..180e34a 100644
--- a/daemons/cmirrord/cluster.c
+++ b/daemons/cmirrord/cluster.c
@@ -1631,7 +1631,7 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
size = ((strlen(uuid) + 1) > CPG_MAX_NAME_LENGTH) ?
CPG_MAX_NAME_LENGTH : (strlen(uuid) + 1);
- strncpy(new->name.value, uuid, size);
+ (void) dm_strncpy(new->name.value, uuid, size);
new->name.length = (uint32_t)size;
new->luid = luid;
diff --git a/daemons/cmirrord/functions.c b/daemons/cmirrord/functions.c
index 03f8626..5e43e1a 100644
--- a/daemons/cmirrord/functions.c
+++ b/daemons/cmirrord/functions.c
@@ -451,15 +451,19 @@ static int _clog_ctr(char *uuid, uint64_t luid,
lc->skip_bit_warning = region_count;
lc->disk_fd = -1;
lc->log_dev_failed = 0;
- strncpy(lc->uuid, uuid, DM_UUID_LEN);
+ if (!dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
+ LOG_ERROR("Cannot use too long UUID %s.", uuid);
+ r = -EINVAL;
+ goto fail;
+ }
lc->luid = luid;
if (get_log(lc->uuid, lc->luid) ||
get_pending_log(lc->uuid, lc->luid)) {
LOG_ERROR("[%s/%" PRIu64 "u] Log already exists, unable to create.",
SHORT_UUID(lc->uuid), lc->luid);
- dm_free(lc);
- return -EINVAL;
+ r = -EINVAL;
+ goto fail;
}
dm_list_init(&lc->mark_list);
6 years
master - cleanup: avoid compiler warn
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=037c234eaaabd4989e7...
Commit: 037c234eaaabd4989e769e1f9db47c8452fa4966
Parent: 73cda0437f8added751716c9bbae33fe321b4963
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Mar 29 18:49:42 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
cleanup: avoid compiler warn
When variable is unused...
---
daemons/cmirrord/cluster.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/daemons/cmirrord/cluster.c b/daemons/cmirrord/cluster.c
index 5b8b68d..e56d8f3 100644
--- a/daemons/cmirrord/cluster.c
+++ b/daemons/cmirrord/cluster.c
@@ -166,7 +166,9 @@ int cluster_send(struct clog_request *rq)
{
int r;
int found = 0;
+#if CMIRROR_HAS_CHECKPOINT
int count = 0;
+#endif
struct iovec iov;
struct clog_cpg *entry;
6 years
master - cleanup: correcting macro wrapping
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=73cda0437f8added751...
Commit: 73cda0437f8added751716c9bbae33fe321b4963
Parent: 9731d48691e85641e45a127ddf77fb603aa4900c
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Apr 19 17:35:48 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
cleanup: correcting macro wrapping
Use proper do {} while(0) so ';' after macros are correctly
interpretted..
---
lib/metadata/merge.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 90b40e2..7299620 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -71,12 +71,12 @@ int lv_merge_segments(struct logical_volume *lv)
if (error_count++ > ERROR_MAX) \
goto out
-#define seg_error(msg) { \
+#define seg_error(msg) do { \
log_error("LV %s, segment %u invalid: %s for %s segment.", \
seg->lv->name, seg_count, (msg), lvseg_name(seg)); \
if ((*error_count)++ > ERROR_MAX) \
return; \
- }
+ } while (0)
/*
* RAID segment property checks.
@@ -84,19 +84,19 @@ int lv_merge_segments(struct logical_volume *lv)
* Checks in here shall catch any
* bogus segment structure setup.
*/
-#define raid_seg_error(msg) { \
+#define raid_seg_error(msg) do { \
log_error("LV %s invalid: %s for %s segment", \
seg->lv->name, (msg), lvseg_name(seg)); \
if ((*error_count)++ > ERROR_MAX) \
return; \
-}
+} while (0)
-#define raid_seg_error_val(msg, val) { \
+#define raid_seg_error_val(msg, val) do { \
log_error("LV %s invalid: %s (is %u) for %s segment", \
seg->lv->name, (msg), (val), lvseg_name(seg)); \
if ((*error_count)++ > ERROR_MAX) \
return; \
-}
+} while(0)
/* Check segment LV for reshape flags. */
static int _check_raid_seg_reshape_flags(struct lv_segment *seg)
@@ -354,7 +354,7 @@ static void _check_lv_segment(struct logical_volume *lv, struct lv_segment *seg,
case CACHE_MODE_PASSTHROUGH:
break;
default:
- seg_error("has invalid cache's feature flag")
+ seg_error("has invalid cache's feature flag");
}
if (!seg->policy_name)
seg_error("is missing cache policy name");
6 years
master - cleanup: enhance debug message
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=9731d48691e85641e45...
Commit: 9731d48691e85641e45a127ddf77fb603aa4900c
Parent: d437bd86ffcb8dc589ddf941ec7c12d493c89b33
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Apr 19 12:32:01 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
cleanup: enhance debug message
---
lib/metadata/lv_manip.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 97a4e39..160943f 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3439,11 +3439,12 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
(existing_extents + new_extents) / ah->area_multiple);
}
- log_debug("Adjusted allocation request to %" PRIu32 " logical extents. Existing size %" PRIu32 ". New size %" PRIu32 ".",
- total_extents, existing_extents, total_extents + existing_extents);
+ if (total_extents || existing_extents)
+ log_debug("Adjusted allocation request to " FMTu32 " logical extents. Existing size " FMTu32 ". New size " FMTu32 ".",
+ total_extents, existing_extents, total_extents + existing_extents);
if (ah->log_len)
- log_debug("Mirror log of %" PRIu32 " extents of size %" PRIu32 " sectors needed for region size %" PRIu32 ".",
- ah->log_len, extent_size, ah->region_size);
+ log_debug("Mirror log of " FMTu32 " extents of size " FMTu32 " sectors needed for region size %s.",
+ ah->log_len, extent_size, display_size(cmd, (uint64_t)ah->region_size));
if (mirrors || stripes)
total_extents += existing_extents;
6 years
master - cleanup: display_lvname update message
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=d437bd86ffcb8dc589d...
Commit: d437bd86ffcb8dc589ddf941ec7c12d493c89b33
Parent: 7323557379d9dc40e68203a467e8ec541e512789
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Mar 27 21:08:20 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
cleanup: display_lvname update message
Add more display_lvname usage.
Update some error messages.
Indent.
---
lib/metadata/mirror.c | 39 ++++++++++++++++++++-------------------
tools/pvmove.c | 2 +-
2 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index 8fcf94e..13e1474 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -606,12 +606,12 @@ static int _mirrored_lv_in_sync(struct logical_volume *lv)
NULL)) {
if (lv_is_active_but_not_locally(lv))
log_error("Unable to determine mirror sync status of"
- " remotely active LV, %s/%s",
- lv->vg->name, lv->name);
+ " remotely active LV, %s",
+ display_lvname(lv));
else
log_error("Unable to determine mirror "
- "sync status of %s/%s.",
- lv->vg->name, lv->name);
+ "sync status of %s.",
+ display_lvname(lv));
return 0;
}
@@ -700,7 +700,7 @@ static int _split_mirror_images(struct logical_volume *lv,
new_lv->name = dm_pool_strdup(lv->vg->vgmem, split_name);
if (!new_lv->name) {
- log_error("Unable to rename newly split LV");
+ log_error("Unable to rename newly split LV.");
return 0;
}
@@ -1141,14 +1141,14 @@ int collapse_mirrored_lv(struct logical_volume *lv)
while ((tmp_lv = find_temporary_mirror(lv))) {
mirror_seg = find_mirror_seg(first_seg(tmp_lv));
if (!mirror_seg) {
- log_error("Failed to find mirrored LV for %s",
- tmp_lv->name);
+ log_error("Failed to find mirrored LV for %s.",
+ display_lvname(tmp_lv));
return 0;
}
if (!_mirrored_lv_in_sync(mirror_seg->lv)) {
- log_verbose("Not collapsing %s: out-of-sync",
- mirror_seg->lv->name);
+ log_verbose("Not collapsing %s: out-of-sync.",
+ display_lvname(mirror_seg->lv));
return 1;
}
@@ -1339,8 +1339,8 @@ static int _create_mimage_lvs(struct alloc_handle *ah,
for (m = 0; m < num_mirrors; m++) {
if (!(img_lvs[m] = lv_create_empty(img_name,
- NULL, LVM_READ | LVM_WRITE,
- ALLOC_INHERIT, lv->vg))) {
+ NULL, LVM_READ | LVM_WRITE,
+ ALLOC_INHERIT, lv->vg))) {
log_error("Aborting. Failed to create mirror image LV. "
"Remove new LV and retry.");
return 0;
@@ -1352,7 +1352,7 @@ static int _create_mimage_lvs(struct alloc_handle *ah,
if (!lv_add_log_segment(ah, first_area, img_lvs[m], 0)) {
log_error("Failed to add mirror image segment"
" to %s. Remove new LV and retry.",
- img_lvs[m]->name);
+ display_lvname(img_lvs[m]));
return 0;
}
} else {
@@ -1361,7 +1361,7 @@ static int _create_mimage_lvs(struct alloc_handle *ah,
stripe_size, 0, 0)) {
log_error("Aborting. Failed to add mirror image segment "
"to %s. Remove new LV and retry.",
- img_lvs[m]->name);
+ display_lvname(img_lvs[m]));
return 0;
}
}
@@ -1385,13 +1385,14 @@ int remove_mirrors_from_segments(struct logical_volume *lv,
/* Check the segment params are compatible */
dm_list_iterate_items(seg, &lv->segments) {
if (!seg_is_mirrored(seg)) {
- log_error("Segment is not mirrored: %s:%" PRIu32,
- lv->name, seg->le);
+ log_error("Segment is not mirrored: %s:" FMTu32,
+ display_lvname(lv), seg->le);
return 0;
}
if ((seg->status & status_mask) != status_mask) {
- log_error("Segment status does not match: %s:%" PRIu32
- " status:0x%" PRIx64 "/0x%" PRIx64, lv->name, seg->le,
+ log_error("Segment status does not match: %s:" FMTu32
+ " status:0x" FMTx64 "/0x" FMTx64,
+ display_lvname(lv), seg->le,
seg->status, status_mask);
return 0;
}
@@ -1523,7 +1524,7 @@ struct dm_list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
uint32_t s;
if (!(lvs = dm_pool_alloc(cmd->mem, sizeof(*lvs)))) {
- log_error("lvs list alloc failed");
+ log_error("lvs list alloc failed.");
return NULL;
}
@@ -1542,7 +1543,7 @@ struct dm_list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
seg_lv(seg, s) != lv)
continue;
if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl)))) {
- log_error("lv_list alloc failed");
+ log_error("lv_list alloc failed.");
return NULL;
}
lvl->lv = lv1;
diff --git a/tools/pvmove.c b/tools/pvmove.c
index 9ad17f6..754bd58 100644
--- a/tools/pvmove.c
+++ b/tools/pvmove.c
@@ -465,7 +465,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
/* With exclusive pvmove skip LV when:
* - is active remotely
* - is not active locally and cannot be activated exclusively locally
- *
+ *
* Note: lvm2 can proceed with exclusive pvmove for 'just' locally active LVs
* in the case it's NOT active anywhere else, since LOCKED LVs cannot be
* later activated by user.
6 years
master - cleanup: add _mb_ to regiosize option
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=7323557379d9dc40e68...
Commit: 7323557379d9dc40e68203a467e8ec541e512789
Parent: e878c3fc32161048e76c2b8e6a33d84f6852cdd4
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Apr 18 12:56:32 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
cleanup: add _mb_ to regiosize option
Just like with others mentions default unit in function name.
---
lib/metadata/metadata-exported.h | 2 +-
tools/args.h | 2 +-
tools/command.c | 4 ++--
tools/lvmcmdline.c | 2 +-
tools/tools.h | 2 +-
tools/vals.h | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index cd7ff8a..2bc7927 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -449,7 +449,7 @@ struct lv_segment {
struct logical_volume *merge_lv; /* thin, merge descendent lv into this ancestor */
struct logical_volume *cow;
struct dm_list origin_list;
- uint32_t region_size; /* For mirrors, replicators - in sectors */
+ uint32_t region_size; /* For raids/mirrors - in sectors */
uint32_t data_copies; /* For RAID: number of data copies (e.g. 3 for RAID 6 */
uint32_t extents_copied;/* Number of extents synced for raids/mirrors */
struct logical_volume *log_lv;
diff --git a/tools/args.h b/tools/args.h
index 89d84b4..b80b8da 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -1295,7 +1295,7 @@ arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0,
/* Not used */
arg(reset_ARG, 'R', "reset", 0, 0, 0, NULL)
-arg(regionsize_ARG, 'R', "regionsize", regionsize_VAL, 0, 0,
+arg(regionsize_ARG, 'R', "regionsize", regionsizemb_VAL, 0, 0,
"Size of each raid or mirror synchronization region.\n"
"lvm.conf activation/raid_region_size can be used to\n"
"configure a default.\n")
diff --git a/tools/command.c b/tools/command.c
index fafbaa9..a40b327 100644
--- a/tools/command.c
+++ b/tools/command.c
@@ -115,7 +115,7 @@ static inline int segtype_arg(struct cmd_context *cmd, struct arg_values *av) {
static inline int alloc_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
static inline int locktype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
static inline int readahead_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int regionsize_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int regionsize_mb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
static inline int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
static inline int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
static inline int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
@@ -2264,7 +2264,7 @@ static void _print_val_man(struct command_name *cname, int opt_enum, int val_enu
return;
}
- if (val_enum == regionsize_VAL) {
+ if (val_enum == regionsizemb_VAL) {
printf("\\fISize\\fP[m|UNIT]");
return;
}
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 6be4bcd..26510bc 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -929,7 +929,7 @@ int readahead_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_va
return 1;
}
-int regionsize_arg(struct cmd_context *cmd, struct arg_values *av)
+int regionsize_mb_arg(struct cmd_context *cmd, struct arg_values *av)
{
int pagesize = lvm_getpagesize();
uint32_t num;
diff --git a/tools/tools.h b/tools/tools.h
index dc29e4b..33cbf10 100644
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -174,7 +174,7 @@ int segtype_arg(struct cmd_context *cmd, struct arg_values *av);
int alloc_arg(struct cmd_context *cmd, struct arg_values *av);
int locktype_arg(struct cmd_context *cmd, struct arg_values *av);
int readahead_arg(struct cmd_context *cmd, struct arg_values *av);
-int regionsize_arg(struct cmd_context *cmd, struct arg_values *av);
+int regionsize_mb_arg(struct cmd_context *cmd, struct arg_values *av);
int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
diff --git a/tools/vals.h b/tools/vals.h
index 614a909..95dc8b2 100644
--- a/tools/vals.h
+++ b/tools/vals.h
@@ -120,7 +120,7 @@ val(sizemb_VAL, size_mb_arg, "SizeMB", "Size[m|UNIT]")
val(ssizemb_VAL, ssize_mb_arg, "SSizeMB", "[+|-]Size[m|UNIT]")
val(psizemb_VAL, psize_mb_arg, "PSizeMB", "[+]Size[m|UNIT]")
val(nsizemb_VAL, nsize_mb_arg, "NSizeMB", "[-]Size[m|UNIT]")
-val(regionsize_VAL, regionsize_arg, "RegionSize", "Size[m|UNIT]")
+val(regionsizemb_VAL, regionsize_mb_arg, "RegionSize", "Size[m|UNIT]")
val(extents_VAL, extents_arg, "Extents", "Number[PERCENT]")
val(sextents_VAL, sextents_arg, "SExtents", "[+|-]Number[PERCENT]")
val(pextents_VAL, pextents_arg, "PExtents", "[+]Number[PERCENT]")
6 years
master - cleanup: correct casting
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=e878c3fc32161048e76...
Commit: e878c3fc32161048e76c2b8e6a33d84f6852cdd4
Parent: 27a1a0e5c04806e217dbd9c197dc95c05341ed54
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Apr 16 12:57:02 2018 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Fri Apr 20 12:17:01 2018 +0200
cleanup: correct casting
---
lib/device/dev-io.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index 1d16a66..d631b86 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -242,7 +242,7 @@ int dev_async_getevents(void)
dev_name(devbuf->where.dev), _aio_events[event_nr].res,
(uint64_t) devbuf->where.size, (uint64_t) devbuf->where.start,
_reason_text(devbuf->reason),
- ((int64_t)_aio_events[event_nr].res < 0) ? strerror(-(int64_t)_aio_events[event_nr].res) : 0);
+ (((int64_t)_aio_events[event_nr].res) < 0) ? strerror(-(int64_t)_aio_events[event_nr].res) : 0);
_release_devbuf(devbuf);
if (dev_read_callback_fn)
dev_read_callback_fn(1, AIO_SUPPORTED_CODE_PATH, dev_read_callback_context, NULL);
6 years