master - scan: invalidate bcache for dev after errors
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=da2b155a9da4c4c9caf...
Commit: da2b155a9da4c4c9caf502b87ad263de6e678b30
Parent: 4331182964e37ad75690007f5f874f2606944a34
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Feb 27 15:03:56 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
scan: invalidate bcache for dev after errors
If there are errors reading or writing dev,
invalidate bcache for it.
---
lib/label/label.c | 25 +++++++++++++++++++------
1 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index 88001a9..0514ddf 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -871,11 +871,16 @@ bool dev_read_bytes(struct device *dev, off_t start, size_t len, void *data)
}
if (dev->bcache_fd <= 0) {
- log_error("dev_read_bytes %s with invalid bcache_fd", dev_name(dev));
+ log_error("dev_read_bytes %s with invalid fd %d", dev_name(dev), dev->bcache_fd);
return false;
}
- return bcache_read_bytes(scan_bcache, dev->bcache_fd, start, len, data);
+ if (!bcache_read_bytes(scan_bcache, dev->bcache_fd, start, len, data)) {
+ label_scan_invalidate(dev);
+ return false;
+ }
+ return true;
+
}
bool dev_write_bytes(struct device *dev, off_t start, size_t len, void *data)
@@ -895,11 +900,15 @@ bool dev_write_bytes(struct device *dev, off_t start, size_t len, void *data)
}
if (dev->bcache_fd <= 0) {
- log_error("dev_write_bytes %s with invalid bcache_fd", dev_name(dev));
+ log_error("dev_write_bytes %s with invalid fd %d", dev_name(dev), dev->bcache_fd);
return false;
}
- return bcache_write_bytes(scan_bcache, dev->bcache_fd, start, len, data);
+ if (!bcache_write_bytes(scan_bcache, dev->bcache_fd, start, len, data)) {
+ label_scan_invalidate(dev);
+ return false;
+ }
+ return true;
}
bool dev_write_zeros(struct device *dev, off_t start, size_t len)
@@ -919,10 +928,14 @@ bool dev_write_zeros(struct device *dev, off_t start, size_t len)
}
if (dev->bcache_fd <= 0) {
- log_error("dev_write_bytes %s with invalid bcache_fd", dev_name(dev));
+ log_error("dev_write_bytes %s with invalid fd %d", dev_name(dev), dev->bcache_fd);
return false;
}
- return bcache_write_zeros(scan_bcache, dev->bcache_fd, start, len);
+ if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, start, len)) {
+ label_scan_invalidate(dev);
+ return false;
+ }
+ return true;
}
6 years
master - bcache: add some error messages for debugging
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=4331182964e37ad7569...
Commit: 4331182964e37ad75690007f5f874f2606944a34
Parent: 21057676a1f01c6b1f19b2e879d8385d76adb517
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Feb 27 12:37:25 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
bcache: add some error messages for debugging
---
lib/device/bcache.c | 21 +++++++++++++++++++--
1 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 272de60..94623a8 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -659,8 +659,11 @@ static struct block *_new_block(struct bcache *cache, int fd, block_address inde
if (dm_list_empty(&cache->io_pending))
_writeback(cache, 16); // FIXME: magic number
_wait_io(cache);
- } else
+ } else {
+ log_error("bcache no new blocks for fd %d index %u",
+ fd, (uint32_t)index);
return NULL;
+ }
}
}
@@ -676,6 +679,18 @@ static struct block *_new_block(struct bcache *cache, int fd, block_address inde
_hash_insert(b);
}
+ if (!b) {
+ log_error("bcache no new blocks for fd %d index %u "
+ "clean %u free %u dirty %u pending %u nr_data_blocks %u nr_cache_blocks %u",
+ fd, (uint32_t)index,
+ dm_list_size(&cache->clean),
+ dm_list_size(&cache->free),
+ dm_list_size(&cache->dirty),
+ dm_list_size(&cache->io_pending),
+ (uint32_t)cache->nr_data_blocks,
+ (uint32_t)cache->nr_cache_blocks);
+ }
+
return b;
}
@@ -893,7 +908,7 @@ bool bcache_get(struct bcache *cache, int fd, block_address index,
}
*result = NULL;
- log_warn("couldn't get block");
+ log_error("bcache failed to get block %u fd %d", (uint32_t)index, fd);
return false;
}
@@ -1077,6 +1092,8 @@ bool bcache_write_bytes(struct bcache *cache, int fd, off_t start, size_t len, v
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, 0, &b)) {
+ log_error("bcache_write failed to get block %u fd %d bb %u be %u",
+ (uint32_t)i, fd, (uint32_t)bb, (uint32_t)be);
errors++;
break;
}
6 years
master - scan: create bcache with minimum number of blocks
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=21057676a1f01c6b1f1...
Commit: 21057676a1f01c6b1f19b2e879d8385d76adb517
Parent: e49b114f7e437666caefa04aada31f32820e286e
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Feb 27 12:35:45 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
scan: create bcache with minimum number of blocks
In some odd cases (e.g. tests) there are very few devices
which results in creating too few blocks in bcache, so
create bcache with a minimum number of blocks.
---
lib/label/label.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index 45a3ecf..88001a9 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -560,13 +560,15 @@ static int _scan_list(struct dm_list *devs, int *failed)
return 1;
}
+#define MIN_BCACHE_BLOCKS 32
+
static int _setup_bcache(int cache_blocks)
{
struct io_engine *ioe;
/* No devices can happen, just create bcache with any small number. */
- if (!cache_blocks)
- cache_blocks = 8;
+ if (cache_blocks < MIN_BCACHE_BLOCKS)
+ cache_blocks = MIN_BCACHE_BLOCKS;
/*
* 100 is arbitrary, it's the max number of concurrent aio's
@@ -831,7 +833,7 @@ int label_read_sector(struct device *dev, struct label **labelp, uint64_t scan_s
int label_scan_setup_bcache(void)
{
if (!scan_bcache) {
- if (!_setup_bcache(32))
+ if (!_setup_bcache(0))
return 0;
}
6 years
master - bcache: use wrappers for bcache read write in lvm
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=e49b114f7e437666cae...
Commit: e49b114f7e437666caefa04aada31f32820e286e
Parent: 80654920468841251a7f940e410ca61de8383b41
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Feb 27 11:26:04 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
bcache: use wrappers for bcache read write in lvm
Using a wrapper makes it easier to disable bcache if needed.
---
lib/config/config.c | 4 +-
lib/device/dev-type.c | 4 +-
lib/format_text/archiver.c | 2 +-
lib/format_text/format-text.c | 19 ++++-----
lib/label/label.c | 82 +++++++++++++++++++++++++++++++++++++---
lib/label/label.h | 8 ++++
lib/metadata/metadata.c | 2 +-
tools/toollib.c | 2 +-
8 files changed, 99 insertions(+), 24 deletions(-)
diff --git a/lib/config/config.c b/lib/config/config.c
index 0711b8c..d07c173 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -534,11 +534,11 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
return 0;
}
- if (!bcache_read_bytes(scan_bcache, dev->bcache_fd, offset, size, buf))
+ if (!dev_read_bytes(dev, offset, size, buf))
goto out;
if (size2) {
- if (!bcache_read_bytes(scan_bcache, dev->bcache_fd, offset2, size2, buf + size))
+ if (!dev_read_bytes(dev, offset2, size2, buf + size))
goto out;
}
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index e69f7ca..9923943 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -677,7 +677,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
} else
log_verbose(_msg_wiping, type, name);
- if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, offset_value, len)) {
+ if (!dev_write_zeros(dev, offset_value, len)) {
log_error("Failed to wipe %s signature on %s.", type, name);
return 0;
}
@@ -774,7 +774,7 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam
}
log_print_unless_silent("Wiping %s on %s.", type, name);
- if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, offset_found, wipe_len)) {
+ if (!dev_write_zeros(dev, offset_found, wipe_len)) {
log_error("Failed to wipe %s on %s.", type, name);
return 0;
}
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index 43ae4eb..c8aeb47 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -489,7 +489,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
log_verbose("Zeroing start of device %s", pv_name);
- if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, 0, 2048)) {
+ if (!dev_write_zeros(dev, 0, 2048)) {
log_error("%s not wiped: aborting", pv_name);
return 0;
}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index 4eef72e..4a9c303 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -227,7 +227,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
if (!(buf = dm_malloc(size + size2)))
goto_out;
- if (!bcache_read_bytes(scan_bcache, area->dev->bcache_fd, offset, size, buf)) {
+ if (!dev_read_bytes(area->dev, offset, size, buf)) {
log_error("Failed to read dev %s offset %llu size %llu",
dev_name(area->dev),
(unsigned long long)offset,
@@ -236,7 +236,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
}
if (size2) {
- if (!bcache_read_bytes(scan_bcache, area->dev->bcache_fd, offset2, size2, buf + size)) {
+ if (!dev_read_bytes(area->dev, offset2, size2, buf + size)) {
log_error("Failed to read dev %s offset %llu size %llu",
dev_name(area->dev),
(unsigned long long)offset2,
@@ -330,7 +330,7 @@ static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev
log_debug_metadata("Reading mda header sector from %s at %llu",
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
- if (!bcache_read_bytes(scan_bcache, dev_area->dev->bcache_fd, dev_area->start, MDA_HEADER_SIZE, mdah)) {
+ if (!dev_read_bytes(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
log_error("Failed to read metadata area header on %s at %llu",
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
return 0;
@@ -400,7 +400,7 @@ static int _raw_write_mda_header(const struct format_type *fmt,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)));
- if (!bcache_write_bytes(scan_bcache, dev->bcache_fd, start_byte, MDA_HEADER_SIZE, mdah)) {
+ if (!dev_write_bytes(dev, start_byte, MDA_HEADER_SIZE, mdah)) {
log_error("Failed to write mda header to %s fd %d", dev_name(dev), dev->bcache_fd);
return 0;
}
@@ -464,7 +464,7 @@ static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area,
*/
memset(vgnamebuf, 0, sizeof(vgnamebuf));
- bcache_read_bytes(scan_bcache, dev_area->dev->bcache_fd, dev_area->start + rlocn->offset, NAME_LEN, vgnamebuf);
+ dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, vgnamebuf);
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{'))
@@ -675,7 +675,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
(unsigned long long)(mdac->rlocn.size - new_wrap),
(unsigned long long)new_wrap);
- if (!bcache_write_bytes(scan_bcache, mdac->area.dev->bcache_fd, mdac->area.start + mdac->rlocn.offset,
+ if (!dev_write_bytes(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
(size_t) (mdac->rlocn.size - new_wrap),
fidtc->raw_metadata_buf)) {
log_error("Failed to write metadata to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd);
@@ -688,8 +688,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
(unsigned long long)(mdac->area.start + MDA_HEADER_SIZE),
(unsigned long long)new_wrap);
- if (!bcache_write_bytes(scan_bcache, mdac->area.dev->bcache_fd,
- mdac->area.start + MDA_HEADER_SIZE,
+ if (!dev_write_bytes(mdac->area.dev, mdac->area.start + MDA_HEADER_SIZE,
(size_t) new_wrap,
fidtc->raw_metadata_buf + mdac->rlocn.size - new_wrap)) {
log_error("Failed to write metadata wrap to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd);
@@ -1217,7 +1216,7 @@ int read_metadata_location_summary(const struct format_type *fmt,
return 0;
}
- bcache_read_bytes(scan_bcache, dev_area->dev->bcache_fd, dev_area->start + rlocn->offset, NAME_LEN, buf);
+ dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, buf);
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
len < (NAME_LEN - 1))
@@ -2308,7 +2307,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
zero_len = (mda_size > wipe_size) ? wipe_size : mda_size;
- if (!bcache_write_zeros(scan_bcache, pv->dev->bcache_fd, mda_start, zero_len)) {
+ if (!dev_write_zeros(pv->dev, mda_start, zero_len)) {
log_error("Failed to wipe new metadata area on %s at %llu len %llu",
pv_dev_name(pv),
(unsigned long long)mda_start,
diff --git a/lib/label/label.c b/lib/label/label.c
index 67d441b..45a3ecf 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -125,8 +125,7 @@ int label_remove(struct device *dev)
memset(readbuf, 0, sizeof(readbuf));
- if (!bcache_read_bytes(scan_bcache, dev->bcache_fd,
- sector << SECTOR_SHIFT, LABEL_SIZE, readbuf)) {
+ if (!dev_read_bytes(dev, sector << SECTOR_SHIFT, LABEL_SIZE, readbuf)) {
log_error("Failed to read label from %s sector %llu",
dev_name(dev), (unsigned long long)sector);
continue;
@@ -152,8 +151,7 @@ int label_remove(struct device *dev)
log_very_verbose("%s: Wiping label at sector %llu",
dev_name(dev), (unsigned long long)sector);
- if (!bcache_write_zeros(scan_bcache, dev->bcache_fd,
- sector << SECTOR_SHIFT, LABEL_SIZE)) {
+ if (!dev_write_zeros(dev, sector << SECTOR_SHIFT, LABEL_SIZE)) {
log_error("Failed to remove label from %s at sector %llu",
dev_name(dev), (unsigned long long)sector);
r = 0;
@@ -166,7 +164,6 @@ int label_remove(struct device *dev)
}
}
- out:
return r;
}
@@ -209,8 +206,7 @@ int label_write(struct device *dev, struct label *label)
return 0;
}
- if (!bcache_write_bytes(scan_bcache, dev->bcache_fd,
- label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
+ if (!dev_write_bytes(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
log_debug_devs("Failed to write label to %s", dev_name(dev));
r = 0;
}
@@ -856,3 +852,75 @@ int label_scan_open(struct device *dev)
return 1;
}
+bool dev_read_bytes(struct device *dev, off_t start, size_t len, void *data)
+{
+ int ret;
+
+ if (!scan_bcache) {
+ if (!dev_open_readonly(dev))
+ return false;
+
+ ret = dev_read(dev, start, len, 0, data);
+
+ if (!dev_close(dev))
+ stack;
+
+ return ret ? true : false;
+ }
+
+ if (dev->bcache_fd <= 0) {
+ log_error("dev_read_bytes %s with invalid bcache_fd", dev_name(dev));
+ return false;
+ }
+
+ return bcache_read_bytes(scan_bcache, dev->bcache_fd, start, len, data);
+}
+
+bool dev_write_bytes(struct device *dev, off_t start, size_t len, void *data)
+{
+ int ret;
+
+ if (!scan_bcache) {
+ if (!dev_open(dev))
+ return false;
+
+ ret = dev_write(dev, start, len, 0, data);
+
+ if (!dev_close(dev))
+ stack;
+
+ return ret ? true : false;
+ }
+
+ if (dev->bcache_fd <= 0) {
+ log_error("dev_write_bytes %s with invalid bcache_fd", dev_name(dev));
+ return false;
+ }
+
+ return bcache_write_bytes(scan_bcache, dev->bcache_fd, start, len, data);
+}
+
+bool dev_write_zeros(struct device *dev, off_t start, size_t len)
+{
+ int ret;
+
+ if (!scan_bcache) {
+ if (!dev_open(dev))
+ return false;
+
+ ret = dev_set(dev, start, len, 0, 0);
+
+ if (!dev_close(dev))
+ stack;
+
+ return ret ? true : false;
+ }
+
+ if (dev->bcache_fd <= 0) {
+ log_error("dev_write_bytes %s with invalid bcache_fd", dev_name(dev));
+ return false;
+ }
+
+ return bcache_write_zeros(scan_bcache, dev->bcache_fd, start, len);
+}
+
diff --git a/lib/label/label.h b/lib/label/label.h
index 92f3e7b..8ef687b 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -114,4 +114,12 @@ void label_scan_confirm(struct device *dev);
int label_scan_setup_bcache(void);
int label_scan_open(struct device *dev);
+/*
+ * Wrappers around bcache equivalents.
+ * (these make it easier to disable bcache and revert to direct rw if needed)
+ */
+bool dev_read_bytes(struct device *dev, off_t start, size_t len, void *data);
+bool dev_write_bytes(struct device *dev, off_t start, size_t len, void *data);
+bool dev_write_zeros(struct device *dev, off_t start, size_t len);
+
#endif
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 4cad2a1..b442451 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -1429,7 +1429,7 @@ static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_write *pvw)
if (pvw->pp->zero) {
log_verbose("Zeroing start of device %s", pv_name);
- if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, 0, 2048)) {
+ if (!dev_write_zeros(dev, 0, 2048)) {
log_error("%s not wiped: aborting", pv_name);
return 0;
}
diff --git a/tools/toollib.c b/tools/toollib.c
index b0c0e8e..b029a0d 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -5830,7 +5830,7 @@ do_command:
if (pp->zero) {
log_verbose("Zeroing start of device %s.", pv_name);
- if (!bcache_write_zeros(scan_bcache, pv->dev->bcache_fd, 0, 2048)) {
+ if (!dev_write_zeros(pv->dev, 0, 2048)) {
log_error("%s not wiped: aborting.", pv_name);
dm_list_move(&pp->arg_fail, &pd->list);
continue;
6 years
master - bcache: do all writes through bcache
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=80654920468841251a7...
Commit: 80654920468841251a7f940e410ca61de8383b41
Parent: 8b26a007b1b545333b40675b1c425b1ef5e0b653
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Mon Feb 19 15:40:44 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
bcache: do all writes through bcache
---
lib/device/bcache.c | 86 ++++++++++++++++++++++++++++++-
lib/device/bcache.h | 4 +-
lib/device/dev-type.c | 6 ++-
lib/format_text/archiver.c | 10 +---
lib/format_text/format-text.c | 94 +++++++++++++---------------------
lib/label/label.c | 112 +++++++++++++++++++----------------------
lib/label/label.h | 1 +
lib/metadata/metadata.c | 19 +++----
tools/toollib.c | 17 ++----
9 files changed, 193 insertions(+), 156 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 499c6af..272de60 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -897,7 +897,7 @@ bool bcache_get(struct bcache *cache, int fd, block_address index,
return false;
}
-void bcache_put(struct block *b)
+static void _put_ref(struct block *b)
{
if (!b->ref_count) {
log_warn("ref count on bcache block already zero");
@@ -907,6 +907,11 @@ void bcache_put(struct block *b)
b->ref_count--;
if (!b->ref_count)
b->cache->nr_locked--;
+}
+
+void bcache_put(struct block *b)
+{
+ _put_ref(b);
if (_test_flags(b, BF_DIRTY))
_preemptive_writeback(b->cache);
@@ -925,7 +930,7 @@ bool bcache_flush(struct bcache *cache)
// The superblock may well be still locked.
continue;
}
-
+
_issue_write(b);
}
@@ -1058,5 +1063,82 @@ bool bcache_read_bytes(struct bcache *cache, int fd, off_t start, size_t len, vo
return errors ? false : true;
}
+bool bcache_write_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data)
+{
+ struct block *b;
+ block_address bb, be, i;
+ unsigned char *udata = data;
+ off_t block_size = cache->block_sectors << SECTOR_SHIFT;
+ int errors = 0;
+
+ byte_range_to_block_range(cache, start, len, &bb, &be);
+ for (i = bb; i < be; i++)
+ bcache_prefetch(cache, fd, i);
+
+ for (i = bb; i < be; i++) {
+ if (!bcache_get(cache, fd, i, 0, &b)) {
+ errors++;
+ break;
+ }
+
+ if (i == bb) {
+ off_t block_offset = start % block_size;
+ size_t blen = _min(block_size - block_offset, len);
+ memcpy(((unsigned char *) b->data) + block_offset, udata, blen);
+ len -= blen;
+ udata += blen;
+ } else {
+ size_t blen = _min(block_size, len);
+ memcpy(b->data, udata, blen);
+ len -= blen;
+ udata += blen;
+ }
+
+ _set_flags(b, BF_DIRTY);
+ _unlink_block(b);
+ _link_block(b);
+ _put_ref(b);
+ }
+
+ if (!bcache_flush(cache))
+ errors++;
+
+ return errors ? false : true;
+}
+
+#define ZERO_BUF_LEN 4096
+
+bool bcache_write_zeros(struct bcache *cache, int fd, off_t start, size_t len)
+{
+ char zerobuf[ZERO_BUF_LEN];
+ size_t plen;
+ size_t poff;
+
+ memset(zerobuf, 0, sizeof(zerobuf));
+
+ if (len <= ZERO_BUF_LEN)
+ return bcache_write_bytes(cache, fd, start, len, &zerobuf);
+
+ poff = 0;
+ plen = ZERO_BUF_LEN;
+
+ while (1) {
+ if (!bcache_write_bytes(cache, fd, start + poff, plen, &zerobuf))
+ return false;
+
+ poff += plen;
+ len -= plen;
+
+ if (!len)
+ break;
+
+ if (len < ZERO_BUF_LEN)
+ plen = len;
+ }
+
+ return true;
+}
+
+
//----------------------------------------------------------------
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
index e5d98e8..d5f6d0a 100644
--- a/lib/device/bcache.h
+++ b/lib/device/bcache.h
@@ -148,9 +148,11 @@ void bcache_invalidate_fd(struct bcache *cache, int fd);
void bcache_prefetch_bytes(struct bcache *cache, int fd, off_t start, size_t len);
/*
- * Reads the bytes.
+ * Reads and writes the bytes. Returns false if errors occur.
*/
bool bcache_read_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data);
+bool bcache_write_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data);
+bool bcache_write_zeros(struct bcache *cache, int fd, off_t start, size_t len);
/*----------------------------------------------------------------*/
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 9608146..e69f7ca 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -17,6 +17,8 @@
#include "xlate.h"
#include "config.h"
#include "metadata.h"
+#include "bcache.h"
+#include "label.h"
#include <libgen.h>
#include <ctype.h>
@@ -675,7 +677,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
} else
log_verbose(_msg_wiping, type, name);
- if (!dev_set(dev, offset_value, len, DEV_IO_SIGNATURES, 0)) {
+ if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, offset_value, len)) {
log_error("Failed to wipe %s signature on %s.", type, name);
return 0;
}
@@ -772,7 +774,7 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam
}
log_print_unless_silent("Wiping %s on %s.", type, name);
- if (!dev_set(dev, offset_found, wipe_len, DEV_IO_SIGNATURES, 0)) {
+ if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, offset_found, wipe_len)) {
log_error("Failed to wipe %s on %s.", type, name);
return 0;
}
diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c
index 81b5da9..43ae4eb 100644
--- a/lib/format_text/archiver.c
+++ b/lib/format_text/archiver.c
@@ -488,19 +488,11 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
}
log_verbose("Zeroing start of device %s", pv_name);
- if (!dev_open_quiet(dev)) {
- log_error("%s not opened: device not zeroed", pv_name);
- return 0;
- }
- if (!dev_set(dev, UINT64_C(0), (size_t) 2048, DEV_IO_LABEL, 0)) {
+ if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, 0, 2048)) {
log_error("%s not wiped: aborting", pv_name);
- if (!dev_close(dev))
- stack;
return 0;
}
- if (!dev_close(dev))
- stack;
}
}
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
index ef59f07..4eef72e 100644
--- a/lib/format_text/format-text.c
+++ b/lib/format_text/format-text.c
@@ -330,8 +330,6 @@ static int _raw_read_mda_header(struct mda_header *mdah, struct device_area *dev
log_debug_metadata("Reading mda header sector from %s at %llu",
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
- label_scan_confirm(dev_area->dev); /* FIXME: remove this, ensures dev is in bcache */
-
if (!bcache_read_bytes(scan_bcache, dev_area->dev->bcache_fd, dev_area->start, MDA_HEADER_SIZE, mdah)) {
log_error("Failed to read metadata area header on %s at %llu",
dev_name(dev_area->dev), (unsigned long long)dev_area->start);
@@ -397,24 +395,16 @@ static int _raw_write_mda_header(const struct format_type *fmt,
mdah->version = FMTT_VERSION;
mdah->start = start_byte;
- label_scan_invalidate(dev);
-
- if (!dev_open(dev))
- return_0;
-
_xlate_mdah(mdah);
mdah->checksum_xl = xlate32(calc_crc(INITIAL_CRC, (uint8_t *)mdah->magic,
MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl)));
- if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, MDA_HEADER_REASON(primary_mda), mdah)) {
- dev_close(dev);
- return_0;
+ if (!bcache_write_bytes(scan_bcache, dev->bcache_fd, start_byte, MDA_HEADER_SIZE, mdah)) {
+ log_error("Failed to write mda header to %s fd %d", dev_name(dev), dev->bcache_fd);
+ return 0;
}
- if (dev_close(dev))
- stack;
-
return 1;
}
@@ -474,8 +464,6 @@ static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area,
*/
memset(vgnamebuf, 0, sizeof(vgnamebuf));
- label_scan_confirm(dev_area->dev); /* FIXME: remove this, ensures dev is in bcache */
-
bcache_read_bytes(scan_bcache, dev_area->dev->bcache_fd, dev_area->start + rlocn->offset, NAME_LEN, vgnamebuf);
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
@@ -681,30 +669,32 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
goto out;
}
- log_debug_metadata("Writing %s metadata to %s at " FMTu64 " len " FMTu64 " of " FMTu64,
- vg->name, dev_name(mdac->area.dev), mdac->area.start +
- mdac->rlocn.offset, mdac->rlocn.size - new_wrap, mdac->rlocn.size);
-
- label_scan_invalidate(mdac->area.dev);
-
- if (!dev_open(mdac->area.dev))
- return_0;
+ log_debug_metadata("Writing metadata for VG %s to %s at %llu len %llu (wrap %llu)",
+ vg->name, dev_name(mdac->area.dev),
+ (unsigned long long)(mdac->area.start + mdac->rlocn.offset),
+ (unsigned long long)(mdac->rlocn.size - new_wrap),
+ (unsigned long long)new_wrap);
- /* Write text out, circularly */
- if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
- (size_t) (mdac->rlocn.size - new_wrap), MDA_CONTENT_REASON(mda_is_primary(mda)),
- fidtc->raw_metadata_buf))
- goto_out;
+ if (!bcache_write_bytes(scan_bcache, mdac->area.dev->bcache_fd, mdac->area.start + mdac->rlocn.offset,
+ (size_t) (mdac->rlocn.size - new_wrap),
+ fidtc->raw_metadata_buf)) {
+ log_error("Failed to write metadata to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd);
+ goto out;
+ }
if (new_wrap) {
- log_debug_metadata("Writing wrapped metadata to %s at " FMTu64 " len " FMTu64 " of " FMTu64,
- dev_name(mdac->area.dev), mdac->area.start +
- MDA_HEADER_SIZE, new_wrap, mdac->rlocn.size);
-
- if (!dev_write(mdac->area.dev, mdac->area.start + MDA_HEADER_SIZE,
- (size_t) new_wrap, MDA_CONTENT_REASON(mda_is_primary(mda)),
- fidtc->raw_metadata_buf + mdac->rlocn.size - new_wrap))
- goto_out;
+ log_debug_metadata("Writing metadata for VG %s to %s at %llu len %llu (wrapped)",
+ vg->name, dev_name(mdac->area.dev),
+ (unsigned long long)(mdac->area.start + MDA_HEADER_SIZE),
+ (unsigned long long)new_wrap);
+
+ if (!bcache_write_bytes(scan_bcache, mdac->area.dev->bcache_fd,
+ mdac->area.start + MDA_HEADER_SIZE,
+ (size_t) new_wrap,
+ fidtc->raw_metadata_buf + mdac->rlocn.size - new_wrap)) {
+ log_error("Failed to write metadata wrap to %s fd %d", dev_name(mdac->area.dev), mdac->area.dev->bcache_fd);
+ goto out;
+ }
}
mdac->rlocn.checksum = calc_crc(INITIAL_CRC, (uint8_t *)fidtc->raw_metadata_buf,
@@ -720,9 +710,6 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
out:
if (!r) {
- if (!dev_close(mdac->area.dev))
- stack;
-
dm_free(fidtc->raw_metadata_buf);
fidtc->raw_metadata_buf = NULL;
}
@@ -819,9 +806,6 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
out:
if (!precommit) {
- if (!dev_close(mdac->area.dev))
- stack;
-
dm_free(fidtc->raw_metadata_buf);
fidtc->raw_metadata_buf = NULL;
}
@@ -904,9 +888,6 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
rlocn->checksum = 0;
rlocn_set_ignored(mdah->raw_locns, mda_is_ignored(mda));
- if (!dev_open(mdac->area.dev))
- return_0;
-
if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mda_is_primary(mda), mdac->area.start,
mdah)) {
dm_pool_free(fid->fmt->cmd->mem, mdah);
@@ -917,9 +898,6 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
r = 1;
out:
- if (!dev_close(mdac->area.dev))
- stack;
-
return r;
}
@@ -1239,8 +1217,6 @@ int read_metadata_location_summary(const struct format_type *fmt,
return 0;
}
- label_scan_confirm(dev_area->dev); /* FIXME: remove this, ensures dev is in bcache */
-
bcache_read_bytes(scan_bcache, dev_area->dev->bcache_fd, dev_area->start + rlocn->offset, NAME_LEN, buf);
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
@@ -1397,8 +1373,6 @@ static int _write_single_mda(struct metadata_area *mda, void *baton)
if (!_raw_write_mda_header(p->fmt, mdac->area.dev, mda_is_primary(mda),
mdac->area.start, mdah)) {
- if (!dev_close(p->pv->dev))
- stack;
return_0;
}
return 1;
@@ -2123,6 +2097,7 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
uint64_t mda_start;
uint64_t adjustment, limit, tmp_mda_size;
uint64_t wipe_size = 8 << SECTOR_SHIFT;
+ uint64_t zero_len;
size_t page_size = lvm_getpagesize();
struct metadata_area *mda;
struct mda_context *mdac;
@@ -2330,13 +2305,14 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
}
/* Wipe metadata area with zeroes. */
- if (!dev_set(pv->dev, mda_start,
- (size_t) ((mda_size > wipe_size) ? wipe_size : mda_size),
- MDA_HEADER_REASON(!mda_index), 0)) {
- log_error("Failed to wipe new metadata area "
- "at the %s of the %s",
- mda_index ? "end" : "start",
- pv_dev_name(pv));
+
+ zero_len = (mda_size > wipe_size) ? wipe_size : mda_size;
+
+ if (!bcache_write_zeros(scan_bcache, pv->dev->bcache_fd, mda_start, zero_len)) {
+ log_error("Failed to wipe new metadata area on %s at %llu len %llu",
+ pv_dev_name(pv),
+ (unsigned long long)mda_start,
+ (unsigned long long)zero_len);
return 0;
}
diff --git a/lib/label/label.c b/lib/label/label.c
index 278f26a..67d441b 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -104,8 +104,7 @@ struct labeller *label_get_handler(const char *name)
/* FIXME Also wipe associated metadata area headers? */
int label_remove(struct device *dev)
{
- char buf[LABEL_SIZE] __attribute__((aligned(8)));
- char readbuf[LABEL_SCAN_SIZE] __attribute__((aligned(8)));
+ char readbuf[LABEL_SIZE] __attribute__((aligned(8)));
int r = 1;
uint64_t sector;
int wipe;
@@ -113,31 +112,27 @@ int label_remove(struct device *dev)
struct label_header *lh;
struct lvmcache_info *info;
- memset(buf, 0, LABEL_SIZE);
-
log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
- label_scan_invalidate(dev);
-
- if (!dev_open(dev))
- return_0;
-
- /*
- * We flush the device just in case someone is stupid
- * enough to be trying to import an open pv into lvm.
- */
- dev_flush(dev);
-
- if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, DEV_IO_LABEL, readbuf)) {
- log_debug_devs("%s: Failed to read label area", dev_name(dev));
- goto out;
+ if (!label_scan_open(dev)) {
+ log_error("Failed to open device %s", dev_name(dev));
+ return 0;
}
/* Scan first few sectors for anything looking like a label */
for (sector = 0; sector < LABEL_SCAN_SECTORS;
sector += LABEL_SIZE >> SECTOR_SHIFT) {
- lh = (struct label_header *) (readbuf +
- (sector << SECTOR_SHIFT));
+
+ memset(readbuf, 0, sizeof(readbuf));
+
+ if (!bcache_read_bytes(scan_bcache, dev->bcache_fd,
+ sector << SECTOR_SHIFT, LABEL_SIZE, readbuf)) {
+ log_error("Failed to read label from %s sector %llu",
+ dev_name(dev), (unsigned long long)sector);
+ continue;
+ }
+
+ lh = (struct label_header *)readbuf;
wipe = 0;
@@ -146,8 +141,7 @@ int label_remove(struct device *dev)
wipe = 1;
} else {
dm_list_iterate_items(li, &_labellers) {
- if (li->l->ops->can_handle(li->l, (char *) lh,
- sector)) {
+ if (li->l->ops->can_handle(li->l, (char *)lh, sector)) {
wipe = 1;
break;
}
@@ -155,27 +149,24 @@ int label_remove(struct device *dev)
}
if (wipe) {
- log_very_verbose("%s: Wiping label at sector %" PRIu64,
- dev_name(dev), sector);
- if (dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE, DEV_IO_LABEL,
- buf)) {
+ log_very_verbose("%s: Wiping label at sector %llu",
+ dev_name(dev), (unsigned long long)sector);
+
+ if (!bcache_write_zeros(scan_bcache, dev->bcache_fd,
+ sector << SECTOR_SHIFT, LABEL_SIZE)) {
+ log_error("Failed to remove label from %s at sector %llu",
+ dev_name(dev), (unsigned long long)sector);
+ r = 0;
+ } else {
/* Also remove the PV record from cache. */
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
if (info)
lvmcache_del(info);
- } else {
- log_error("Failed to remove label from %s at "
- "sector %" PRIu64, dev_name(dev),
- sector);
- r = 0;
}
}
}
out:
- if (!dev_close(dev))
- stack;
-
return r;
}
@@ -197,8 +188,6 @@ int label_write(struct device *dev, struct label *label)
return 0;
}
- label_scan_invalidate(dev);
-
memset(buf, 0, LABEL_SIZE);
strncpy((char *)lh->id, LABEL_ID, sizeof(lh->id));
@@ -211,20 +200,21 @@ int label_write(struct device *dev, struct label *label)
lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, (uint8_t *)&lh->offset_xl, LABEL_SIZE -
((uint8_t *) &lh->offset_xl - (uint8_t *) lh)));
- if (!dev_open(dev))
- return_0;
-
log_very_verbose("%s: Writing label to sector %" PRIu64 " with stored offset %"
PRIu32 ".", dev_name(dev), label->sector,
xlate32(lh->offset_xl));
- if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, DEV_IO_LABEL, buf)) {
+
+ if (!label_scan_open(dev)) {
+ log_error("Failed to open device %s", dev_name(dev));
+ return 0;
+ }
+
+ if (!bcache_write_bytes(scan_bcache, dev->bcache_fd,
+ label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
log_debug_devs("Failed to write label to %s", dev_name(dev));
r = 0;
}
- if (!dev_close(dev))
- stack;
-
return r;
}
@@ -763,8 +753,10 @@ void label_scan_destroy(struct cmd_context *cmd)
return;
}
- while ((dev = dev_iter_get(iter)))
- label_scan_invalidate(dev);
+ while ((dev = dev_iter_get(iter))) {
+ if (_in_bcache(dev))
+ _scan_dev_close(dev);
+ }
dev_iter_destroy(iter);
bcache_destroy(scan_bcache);
@@ -834,22 +826,6 @@ int label_read_sector(struct device *dev, struct label **labelp, uint64_t scan_s
}
/*
- * FIXME: remove this. It should not be needed once writes are going through
- * bcache. As it is now, the write path involves multiple writes to a device,
- * and later writes want to read previous writes from disk. They do these
- * reads using the standard read paths which require the devs to be in bcache,
- * but the bcache reads do not find the dev because the writes have gone around
- * bcache. To work around this for now, check if each dev is in bcache before
- * reading it, and if not add it first.
- */
-
-void label_scan_confirm(struct device *dev)
-{
- if (!_in_bcache(dev))
- label_read(dev, NULL, 0);
-}
-
-/*
* This is only needed when commands are using lvmetad, in which case they
* don't do an initial label_scan, but may later need to rescan certain devs
* from disk and call this function. FIXME: is there some better number to
@@ -866,3 +842,17 @@ int label_scan_setup_bcache(void)
return 1;
}
+/*
+ * This is needed to write to a new non-lvm device.
+ * Scanning that dev would not keep it open or in
+ * bcache, but to use bcache_write we need the dev
+ * to be open so we can use dev->bcache_fd to write.
+ */
+
+int label_scan_open(struct device *dev)
+{
+ if (!_in_bcache(dev))
+ return _scan_dev_open(dev);
+ return 1;
+}
+
diff --git a/lib/label/label.h b/lib/label/label.h
index bf6e926..92f3e7b 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -112,5 +112,6 @@ int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector
int label_read_sector(struct device *dev, struct label **labelp, uint64_t scan_sector);
void label_scan_confirm(struct device *dev);
int label_scan_setup_bcache(void);
+int label_scan_open(struct device *dev);
#endif
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index b588a04..4cad2a1 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -692,6 +692,7 @@ int check_pv_dev_sizes(struct volume_group *vg)
* . lvmcache_get_vgids()
* . lvmcache_get_vgnames()
* . the vg->pvs_to_write list and pv_to_write struct
+ * . _pvcreate_write()
*/
int vg_extend_each_pv(struct volume_group *vg, struct pvcreate_params *pp)
@@ -1414,28 +1415,24 @@ static int _pvcreate_write(struct cmd_context *cmd, struct pv_to_write *pvw)
struct device *dev = pv->dev;
const char *pv_name = dev_name(dev);
+ if (!label_scan_open(dev)) {
+ log_error("%s not opened: device not written", pv_name);
+ return 0;
+ }
+
if (pvw->new_pv) {
/* Wipe existing label first */
- if (!label_remove(pv_dev(pv))) {
+ if (!label_remove(dev)) {
log_error("Failed to wipe existing label on %s", pv_name);
return 0;
}
if (pvw->pp->zero) {
log_verbose("Zeroing start of device %s", pv_name);
- if (!dev_open_quiet(dev)) {
- log_error("%s not opened: device not zeroed", pv_name);
- return 0;
- }
-
- if (!dev_set(dev, UINT64_C(0), (size_t) 2048, DEV_IO_LABEL, 0)) {
+ if (!bcache_write_zeros(scan_bcache, dev->bcache_fd, 0, 2048)) {
log_error("%s not wiped: aborting", pv_name);
- if (!dev_close(dev))
- stack;
return 0;
}
- if (!dev_close(dev))
- stack;
}
}
diff --git a/tools/toollib.c b/tools/toollib.c
index 623bfbb..b0c0e8e 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -5728,6 +5728,8 @@ do_command:
* Wipe signatures on devices being created.
*/
dm_list_iterate_items_safe(pd, pd2, &pp->arg_create) {
+ label_scan_open(pd->dev);
+
log_verbose("Wiping signatures on new PV %s.", pd->name);
if (!wipe_known_signatures(cmd, pd->dev, pd->name, TYPE_LVM1_MEMBER | TYPE_LVM2_MEMBER,
@@ -5805,6 +5807,8 @@ do_command:
pv_name = pd->name;
+ label_scan_open(pd->dev);
+
log_debug("Creating a new PV on %s.", pv_name);
if (!(pv = pv_create(cmd, pd->dev, &pp->pva))) {
@@ -5816,6 +5820,7 @@ do_command:
log_verbose("Set up physical volume for \"%s\" with %" PRIu64
" available sectors.", pv_name, pv_size(pv));
+
if (!label_remove(pv->dev)) {
log_error("Failed to wipe existing label on %s.", pv_name);
dm_list_move(&pp->arg_fail, &pd->list);
@@ -5825,21 +5830,11 @@ do_command:
if (pp->zero) {
log_verbose("Zeroing start of device %s.", pv_name);
- if (!dev_open_quiet(pv->dev)) {
- log_error("%s not opened: device not zeroed.", pv_name);
- dm_list_move(&pp->arg_fail, &pd->list);
- continue;
- }
-
- if (!dev_set(pv->dev, UINT64_C(0), (size_t) 2048, DEV_IO_LABEL, 0)) {
+ if (!bcache_write_zeros(scan_bcache, pv->dev->bcache_fd, 0, 2048)) {
log_error("%s not wiped: aborting.", pv_name);
- if (!dev_close(pv->dev))
- stack;
dm_list_move(&pp->arg_fail, &pd->list);
continue;
}
- if (!dev_close(pv->dev))
- stack;
}
log_verbose("Writing physical volume data to disk \"%s\".", pv_name);
6 years
master - misc bcache fixes from ejt
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=8b26a007b1b545333b4...
Commit: 8b26a007b1b545333b40675b1c425b1ef5e0b653
Parent: 0da296003d3af3f505213a25783dda534af2d9d6
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Tue Feb 20 09:33:27 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
misc bcache fixes from ejt
---
lib/device/bcache.c | 64 +++++++++++++++++++++++++++++++--------------------
lib/device/bcache.h | 9 +++++-
lib/label/label.c | 2 +-
3 files changed, 47 insertions(+), 28 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 38c909c..499c6af 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -134,7 +134,6 @@ struct async_engine {
struct io_engine e;
io_context_t aio_context;
struct cb_set *cbs;
- unsigned max_io;
};
static struct async_engine *_to_async(struct io_engine *e)
@@ -185,7 +184,10 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
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);
+ do {
+ r = io_submit(e->aio_context, 1, cb_array);
+ } while (r == -EAGAIN);
+
if (r < 0) {
log_sys_warn("io_submit");
_cb_free(e->cbs, cb);
@@ -206,7 +208,10 @@ static bool _async_wait(struct io_engine *ioe, io_complete_fn fn)
struct async_engine *e = _to_async(ioe);
memset(&event, 0, sizeof(event));
- r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL);
+ do {
+ r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL);
+ } while (r == -EINTR);
+
if (r < 0) {
log_sys_warn("io_getevents");
return false;
@@ -223,6 +228,7 @@ static bool _async_wait(struct io_engine *ioe, io_complete_fn fn)
else if ((int) ev->res < 0)
fn(cb->context, (int) ev->res);
+ // FIXME: dct added this. a short read is ok?!
else if (ev->res >= (1 << SECTOR_SHIFT)) {
/* minimum acceptable read is 1 sector */
fn((void *) cb->context, 0);
@@ -238,13 +244,12 @@ static bool _async_wait(struct io_engine *ioe, io_complete_fn fn)
return true;
}
-static unsigned _async_max_io(struct io_engine *ioe)
+static unsigned _async_max_io(struct io_engine *e)
{
- struct async_engine *e = _to_async(ioe);
- return e->max_io;
+ return MAX_IO;
}
-struct io_engine *create_async_io_engine(unsigned max_io)
+struct io_engine *create_async_io_engine(void)
{
int r;
struct async_engine *e = dm_malloc(sizeof(*e));
@@ -252,22 +257,20 @@ struct io_engine *create_async_io_engine(unsigned max_io)
if (!e)
return NULL;
- e->max_io = max_io;
-
e->e.destroy = _async_destroy;
e->e.issue = _async_issue;
e->e.wait = _async_wait;
e->e.max_io = _async_max_io;
e->aio_context = 0;
- r = io_setup(max_io, &e->aio_context);
+ r = io_setup(MAX_IO, &e->aio_context);
if (r < 0) {
log_warn("io_setup failed");
dm_free(e);
return NULL;
}
- e->cbs = _cb_set_create(max_io);
+ e->cbs = _cb_set_create(MAX_IO);
if (!e->cbs) {
log_warn("couldn't create control block set");
dm_free(e);
@@ -535,10 +538,17 @@ static void _complete_io(void *context, int err)
*/
dm_list_del(&b->list);
- if (b->error)
- dm_list_add(&cache->errored, &b->list);
+ if (b->error) {
+ if (b->io_dir == DIR_READ) {
+ // We can just forget about this block, since there's
+ // no dirty data to be written back.
+ _hash_remove(b);
+ dm_list_add(&cache->free, &b->list);
- else {
+ } else
+ dm_list_add(&cache->errored, &b->list);
+
+ } else {
_clear_flags(b, BF_DIRTY);
_link_block(b);
}
@@ -548,35 +558,34 @@ static void _complete_io(void *context, int err)
* |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)
+static void _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;
+ return;
+ b->io_dir = d;
_set_flags(b, BF_IO_PENDING);
dm_list_add(&cache->io_pending, &b->list);
if (!cache->engine->issue(cache->engine, d, b->fd, sb, se, b->data, b)) {
_complete_io(b, -EIO);
- return false;
+ return;
}
- return true;
-
}
-static inline bool _issue_read(struct block *b)
+static inline void _issue_read(struct block *b)
{
- return _issue_low_level(b, DIR_READ);
+ _issue_low_level(b, DIR_READ);
}
-static inline bool _issue_write(struct block *b)
+static inline void _issue_write(struct block *b)
{
- return _issue_low_level(b, DIR_WRITE);
+ _issue_low_level(b, DIR_WRITE);
}
static bool _wait_io(struct bcache *cache)
@@ -903,8 +912,13 @@ void bcache_put(struct block *b)
_preemptive_writeback(b->cache);
}
-int bcache_flush(struct bcache *cache)
+bool bcache_flush(struct bcache *cache)
{
+ // Only dirty data is on the errored list, since bad read blocks get
+ // recycled straight away. So we put these back on the dirty list, and
+ // try and rewrite everything.
+ dm_list_splice(&cache->dirty, &cache->errored);
+
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)) {
@@ -917,7 +931,7 @@ int bcache_flush(struct bcache *cache)
_wait_all(cache);
- return dm_list_empty(&cache->errored) ? 0 : -EIO;
+ return dm_list_empty(&cache->errored);
}
static void _recycle_block(struct bcache *cache, struct block *b)
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
index 7d38d33..e5d98e8 100644
--- a/lib/device/bcache.h
+++ b/lib/device/bcache.h
@@ -47,7 +47,7 @@ struct io_engine {
unsigned (*max_io)(struct io_engine *e);
};
-struct io_engine *create_async_io_engine(unsigned max_io);
+struct io_engine *create_async_io_engine(void);
/*----------------------------------------------------------------*/
@@ -65,6 +65,7 @@ struct block {
unsigned flags;
unsigned ref_count;
int error;
+ enum dir io_dir;
};
/*
@@ -122,7 +123,11 @@ 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);
+/*
+ * flush() does not attempt to writeback locked blocks. flush will fail
+ * (return false), if any unlocked dirty data cannot be written back.
+ */
+bool bcache_flush(struct bcache *cache);
/*
* Removes a block from the cache. If the block is dirty it will be written
diff --git a/lib/label/label.c b/lib/label/label.c
index dfd3e37..278f26a 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -587,7 +587,7 @@ static int _setup_bcache(int cache_blocks)
* possible, i.e, the number of devices that can be read at
* once. Should this be configurable?
*/
- if (!(ioe = create_async_io_engine(100))) {
+ if (!(ioe = create_async_io_engine())) {
log_error("Failed to create bcache io engine.");
return 0;
}
6 years
master - vgchange: invalidate bcache for stacked LVs when deactivating
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=0da296003d3af3f5052...
Commit: 0da296003d3af3f505213a25783dda534af2d9d6
Parent: 34fd818caf89f39dab58ef2ce7c60c193db02cf0
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Feb 16 14:18:55 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
vgchange: invalidate bcache for stacked LVs when deactivating
An LV with a stacked PV will be open in bcache and needs to be
invalidated to close the fd before attempting to deactivate.
---
lib/label/label.c | 19 +++++++++++++++++++
lib/label/label.h | 1 +
tools/toollib.c | 11 ++---------
tools/vgchange.c | 17 +++++++++++------
4 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index c35818a..dfd3e37 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -20,6 +20,7 @@
#include "lvmcache.h"
#include "bcache.h"
#include "toolcontext.h"
+#include "activate.h"
#include <sys/stat.h>
#include <fcntl.h>
@@ -726,6 +727,24 @@ void label_scan_invalidate(struct device *dev)
}
/*
+ * If a PV is stacked on an LV, then the LV is kept open
+ * in bcache, and needs to be closed so the open fd doesn't
+ * interfere with processing the LV.
+ */
+
+void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv)
+{
+ struct lvinfo lvinfo;
+ struct device *dev;
+ dev_t devt;
+
+ lv_info(cmd, lv, 0, &lvinfo, 0, 0);
+ devt = MKDEV(lvinfo.major, lvinfo.minor);
+ if ((dev = dev_cache_get_by_devt(devt, cmd->filter)))
+ label_scan_invalidate(dev);
+}
+
+/*
* Undo label_scan()
*
* Close devices that are open because bcache is holding blocks for them.
diff --git a/lib/label/label.h b/lib/label/label.h
index 107bd30..bf6e926 100644
--- a/lib/label/label.h
+++ b/lib/label/label.h
@@ -106,6 +106,7 @@ int label_scan(struct cmd_context *cmd);
int label_scan_devs(struct cmd_context *cmd, struct dm_list *devs);
int label_scan_devs_excl(struct dm_list *devs);
void label_scan_invalidate(struct device *dev);
+void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
void label_scan_destroy(struct cmd_context *cmd);
int label_read(struct device *dev, struct label **labelp, uint64_t unused_sector);
int label_read_sector(struct device *dev, struct label **labelp, uint64_t scan_sector);
diff --git a/tools/toollib.c b/tools/toollib.c
index 0b8823b..623bfbb 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -3009,7 +3009,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
log_report_t saved_log_report_state = log_get_report_state();
char lv_uuid[64] __attribute__((aligned(8)));
char vg_uuid[64] __attribute__((aligned(8)));
- struct lvinfo lvinfo;
int ret_max = ECMD_PROCESSED;
int ret = 0;
int whole_selected = 0;
@@ -3026,8 +3025,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct lv_list *final_lvl;
struct dm_list found_arg_lvnames;
struct glv_list *glvl, *tglvl;
- struct device *dev;
- dev_t devt;
int do_report_ret_code = 1;
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LV);
@@ -3170,12 +3167,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
* in bcache, and needs to be closed so the open fd doesn't
* interfere with processing the LV.
*/
- dm_list_iterate_items(lvl, &final_lvs) {
- lv_info(cmd, lvl->lv, 0, &lvinfo, 0, 0);
- devt = MKDEV(lvinfo.major, lvinfo.minor);
- if ((dev = dev_cache_get_by_devt(devt, cmd->filter)))
- label_scan_invalidate(dev);
- }
+ dm_list_iterate_items(lvl, &final_lvs)
+ label_scan_invalidate_lv(cmd, lvl->lv);
dm_list_iterate_items(lvl, &final_lvs) {
lv_uuid[0] = '\0';
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 7cfaab6..61b78df 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -209,14 +209,19 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
cmd->handles_missing_pvs = 1;
/* FIXME: Force argument to deactivate them? */
- if (!do_activate && (lv_open = lvs_in_vg_opened(vg))) {
+ if (!do_activate) {
dm_list_iterate_items(lvl, &vg->lvs)
- if (lv_is_visible(lvl->lv) &&
- !lv_check_not_in_use(lvl->lv, 1)) {
- log_error("Can't deactivate volume group \"%s\" with %d open "
- "logical volume(s)", vg->name, lv_open);
- return 0;
+ label_scan_invalidate_lv(cmd, lvl->lv);
+
+ if ((lv_open = lvs_in_vg_opened(vg))) {
+ dm_list_iterate_items(lvl, &vg->lvs) {
+ if (lv_is_visible(lvl->lv) && !lv_check_not_in_use(lvl->lv, 1)) {
+ log_error("Can't deactivate volume group \"%s\" with %d open logical volume(s)",
+ vg->name, lv_open);
+ return 0;
+ }
}
+ }
}
/* FIXME Move into library where clvmd can use it */
6 years
master - scan: drop bcache and close fd for LV with stacked PV
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=34fd818caf89f39dab5...
Commit: 34fd818caf89f39dab58ef2ce7c60c193db02cf0
Parent: c2b10daf694bea490044b752209a416f886373ea
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Fri Feb 16 10:37:09 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
scan: drop bcache and close fd for LV with stacked PV
When a PV is stacked on an LV, the LV will be kept in
bcache, and the open fd on the LV may interfere with
processing the LV. So, drop/close a bcache fd for
an LV before processing the LV.
---
tools/toollib.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/tools/toollib.c b/tools/toollib.c
index 807e34c..0b8823b 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -3009,6 +3009,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
log_report_t saved_log_report_state = log_get_report_state();
char lv_uuid[64] __attribute__((aligned(8)));
char vg_uuid[64] __attribute__((aligned(8)));
+ struct lvinfo lvinfo;
int ret_max = ECMD_PROCESSED;
int ret = 0;
int whole_selected = 0;
@@ -3025,6 +3026,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct lv_list *final_lvl;
struct dm_list found_arg_lvnames;
struct glv_list *glvl, *tglvl;
+ struct device *dev;
+ dev_t devt;
int do_report_ret_code = 1;
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LV);
@@ -3162,6 +3165,18 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
}
log_set_report_object_name_and_id(NULL, NULL);
+ /*
+ * If a PV is stacked on an LV, then the LV is kept open
+ * in bcache, and needs to be closed so the open fd doesn't
+ * interfere with processing the LV.
+ */
+ dm_list_iterate_items(lvl, &final_lvs) {
+ lv_info(cmd, lvl->lv, 0, &lvinfo, 0, 0);
+ devt = MKDEV(lvinfo.major, lvinfo.minor);
+ if ((dev = dev_cache_get_by_devt(devt, cmd->filter)))
+ label_scan_invalidate(dev);
+ }
+
dm_list_iterate_items(lvl, &final_lvs) {
lv_uuid[0] = '\0';
if (!id_write_format(&lvl->lv->lvid.id[1], lv_uuid, sizeof(lv_uuid)))
6 years
master - scan: put dev back on caller's list
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=c2b10daf694bea49004...
Commit: c2b10daf694bea490044b752209a416f886373ea
Parent: e7670d333855ecccb21b30bc6b4525d6bafaa940
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Feb 15 14:17:51 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:47 2018 -0500
scan: put dev back on caller's list
Commit 6e442875613915e506440e59a290b56756df2521 missed
adding devs back to caller's list.
---
lib/label/label.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index 38db733..c35818a 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -513,6 +513,7 @@ static int _scan_list(struct dm_list *devs, int *failed)
if (!_scan_dev_open(devl->dev)) {
log_debug_devs("%s: Failed to open device.", dev_name(devl->dev));
dm_list_del(&devl->list);
+ dm_list_add(&done_devs, &devl->list);
scan_failed_count++;
continue;
}
@@ -561,8 +562,8 @@ static int _scan_list(struct dm_list *devs, int *failed)
if (!dm_list_empty(devs))
goto scan_more;
- log_debug_devs("Scanned %d devices: %d for lvm, %d failed.",
- dm_list_size(&done_devs), scan_lvm_count, scan_failed_count);
+ log_debug_devs("Scanned devices: %d lvm, %d failed.",
+ scan_lvm_count, scan_failed_count);
if (failed)
*failed = scan_failed_count;
6 years
master - scan: use 128K bcache block size
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=b504bb809efa8a3a4db...
Commit: b504bb809efa8a3a4db0e494bb80d3720d82e6ff
Parent: ae093df3f15f6d125bf85ed921e5a971b170dc23
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Feb 15 10:27:43 2018 -0600
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Apr 20 11:22:46 2018 -0500
scan: use 128K bcache block size
---
lib/label/label.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/label/label.c b/lib/label/label.c
index dc14beb..38db733 100644
--- a/lib/label/label.c
+++ b/lib/label/label.c
@@ -253,7 +253,7 @@ struct label *label_create(struct labeller *labeller)
/* global variable for accessing the bcache populated by label scan */
struct bcache *scan_bcache;
-#define BCACHE_BLOCK_SIZE_IN_SECTORS 2048 /* 1MB */
+#define BCACHE_BLOCK_SIZE_IN_SECTORS 256 /* 256*512 = 128K */
static bool _in_bcache(struct device *dev)
{
6 years