From 3c2086efdd5be7e7d3356588c8c4c0e0f8c03c67 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 19 Sep 2008 05:19:09 +0000 Subject: [PATCH] adjust pe_align for md chunk size --- WHATS_NEW | 2 +- lib/device/dev-md.c | 65 ++++++++++++++++++++++++++++++++++++++++- lib/device/device.h | 1 + lib/metadata/metadata.c | 15 ++++++++-- 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 6223fd6b2..b0fcbca31 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,6 +1,6 @@ Version 2.02.40 - ================================ - Pass struct physical_volume to pe_align. + Pass struct physical_volume to pe_align and adjust for md chunk size. Store sysfs location in struct cmd_context. Avoid shuffling remaining mirror images when removing one, retaining primary. Add missing LV error target activation in _remove_mirror_images. diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c index 5fbf11980..37e398808 100644 --- a/lib/device/dev-md.c +++ b/lib/device/dev-md.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2004 Luca Berra - * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -16,6 +16,7 @@ #include "lib.h" #include "metadata.h" #include "xlate.h" +#include "filter.h" #ifdef linux @@ -124,6 +125,62 @@ out: return ret; } +/* + * Retrieve chunk size from md device using sysfs. + */ +unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev) +{ + char path[PATH_MAX+1], buffer[64]; + FILE *fp; + struct stat info; + unsigned long chunk_size = 0UL; + + if (MAJOR(dev->dev) != md_major()) + return 0; + + if (!sysfs_dir || !*sysfs_dir) + return_0; + + if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/md/chunk_size", + sysfs_dir, MAJOR(dev->dev), MINOR(dev->dev)) < 0) { + log_error("dm_snprintf md chunk_size failed"); + return 0; + } + + /* old sysfs structure */ + if (stat(path, &info) && + dm_snprintf(path, PATH_MAX, "%s/block/md%d/md/chunk_size", + sysfs_dir, MINOR(dev->dev)) < 0) { + log_error("dm_snprintf old md chunk size failed"); + return 0; + } + + if (!(fp = fopen(path, "r"))) { + log_sys_error("fopen", path); + return 0; + } + + if (!fgets(buffer, sizeof(buffer), fp)) { + log_sys_error("fgets", path); + goto out; + } + + if (sscanf(buffer, "%lu", &chunk_size) != 1) { + log_error("sysfs file %s not in expected format: %s", path, + buffer); + goto out; + } + + log_very_verbose("Found chunksize %u for md device %s.", chunk_size, + dev_name(dev)); + +out: + if (fclose(fp)) + log_sys_error("fclose", path); + + return chunk_size; +} + #else int dev_is_md(struct device *dev __attribute((unused)), @@ -132,4 +189,10 @@ int dev_is_md(struct device *dev __attribute((unused)), return 0; } +unsigned long dev_md_chunk_size(const char *sysfs_dir __attribute((unused)), + struct device *dev __attribute((unused))) +{ + return 0UL; +} + #endif diff --git a/lib/device/device.h b/lib/device/device.h index 73096547e..0831f9876 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -93,6 +93,7 @@ const char *dev_name_confirmed(struct device *dev, int quiet); /* Does device contain md superblock? If so, where? */ int dev_is_md(struct device *dev, uint64_t *sb); +unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev); int is_partitioned_dev(struct device *dev); diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 7171d2e07..3dd203632 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -66,9 +66,20 @@ static struct physical_volume *_find_pv_in_vg_by_uuid(const struct volume_group unsigned long pe_align(struct physical_volume *pv) { - if (!pv->pe_align) - pv->pe_align = MAX(65536UL, lvm_getpagesize()) >> SECTOR_SHIFT; + if (pv->pe_align) + goto out; + pv->pe_align = MAX(65536UL, lvm_getpagesize()) >> SECTOR_SHIFT; + + /* + * Align to chunk size of underlying md device if present + */ + if (pv->dev) + pv->pe_align = MAX(pv->pe_align, + dev_md_chunk_size(pv->fmt->cmd->sysfs_dir, + pv->dev)); + +out: return pv->pe_align; }