master - filter-mpath: detect partitions of mpath components
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=966d4f36d7fb29...
Commit: 966d4f36d7fb29734c6176e21a139375c431eeac
Parent: 65d0089c6477e6bc30ef64ce9fd79e8c855c4529
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 12 12:20:10 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 12 13:13:38 2013 +0200
filter-mpath: detect partitions of mpath components
We use mpath filtering (enabled by devices/multipath_component_detection=1
lvm.conf setting) to avoid a situation in which we could end up with
duplicate PVs found. We need to filter out the mpath components and
use only the top-level multipath mapping instead for PV scans.
However, if the there are partitions on multipath components, we need
to filter out these partitions. This patch fixes it so those
partitions found on multipath components are filtered as well.
For example, let's consider following configuration:
The sda and sdb are mpath components, sda1 and sdb1 the partitions
on these components, mpath-test the mpath mapping and mpath-test1
the partition mapping - created automatically by kpartx right
after mpath-test creation. The PV resides on top.
(LVM PV)
|
mpath-test1
|
mpath-test
|
sda1 ---------- sdb1
\ | |/
sda sdb
E.g. for sda1 and sdb1, the code will detect this and it skips
the partition that belongs to the multipath component:
<snippet from the log>
#filters/filter-mpath.c:156 /dev/sda1: Device is a partition, using primary device /dev/sda for mpath component detection
130 #ioctl/libdm-iface.c:1724 dm status (253:2) OF[16384](*1)
131 #filters/filter-mpath.c:196 /dev/sda1: Skipping mpath component device
</snippet from the log>
Othewise, we'd see the same PV label on sda1/sdb1 and mpath-test1
at the same time ending up with "Duplicate PV found...".
---
WHATS_NEW | 1 +
lib/filters/filter-mpath.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index aecf227..36ad365 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Also filter partitions on mpath components if multipath_component_detection=1.
Add lvresize support for online thin pool metadata volume resize.
Add helper functions find_pool_lv() and pool_can_resize_metadata().
Add detection for thin pool metadata resize kernel support.
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index 0e88e65..16e2105 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -123,11 +123,41 @@ static int dev_is_mpath(struct dev_filter *f, struct device *dev)
const char *sysfs_dir = dm_sysfs_dir();
int major = MAJOR(dev->dev);
int minor = MINOR(dev->dev);
+ dev_t primary_dev;
/* Limit this filter only to SCSI devices */
if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
return 0;
+ switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
+ case -1:
+ /* Error. */
+ log_error("Failed to get primary device for %d:%d.", major, minor);
+ return 0;
+ case 0:
+ /* The dev is already a primary dev. Just continue with the dev. */
+ break;
+ case 1:
+ /* The dev is partition. */
+ name = dev_name(dev); /* name of original dev for log_debug msg */
+
+ /* Get primary dev from cache. */
+ if (!(dev = dev_cache_get_by_devt(primary_dev, NULL))) {
+ log_error("dev_is_mpath: failed to get device for %d:%d",
+ major, minor);
+ return 0;
+ }
+
+ major = (int) MAJOR(primary_dev);
+ minor = (int) MINOR(primary_dev);
+
+ log_debug_devs("%s: Device is a partition, using primary "
+ "device %s for mpath component detection",
+ name, dev_name(dev));
+
+ break;
+ }
+
if (!(name = get_sysfs_name(dev)))
return_0;
10 years, 9 months
master - dev-type: dev_get_primary_dev fn: use dev_types and provide better return codes
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=65d0089c6477e6...
Commit: 65d0089c6477e6bc30ef64ce9fd79e8c855c4529
Parent: c6f48b7c1a0271255405346c50d6bee8cc8b9241
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 12 12:14:11 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 12 12:14:11 2013 +0200
dev-type: dev_get_primary_dev fn: use dev_types and provide better return codes
The dev_get_primary_dev fn now returns:
0 if the dev is already a primary dev
1 if the dev is a partition, primary dev is returned in "result" (output arg)
-1 on error
This way, we can better differentiate between the error state
and the state in which the dev supplied is not a partition
in the caller (this was same return value before).
Also, if we already have information about the device type,
we can check its major number against the list of known device
types (cmd->dev_types) directly, so we don't need to go through
the sysfs - we only check the major:minor pair which is a bit
more straightforward and faster. If the dev_types does not have
any info about this device type, the code just fallbacks to
the original sysfs interface to get the partition info.
---
lib/device/dev-md.c | 2 +-
lib/device/dev-type.c | 63 ++++++++++++++++++++++++++++++++++++------------
2 files changed, 48 insertions(+), 17 deletions(-)
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index a8bbe81..84d9ce3 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -141,7 +141,7 @@ static int _md_sysfs_attribute_snprintf(char *path, size_t size,
if (MAJOR(dev) == dt->blkext_major) {
/* lookup parent MD device from blkext partition */
- if (!dev_get_primary_dev(dt, blkdev, &dev))
+ if (dev_get_primary_dev(dt, blkdev, &dev) < 1)
return ret;
}
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 150daf4..92120e8 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -203,7 +203,7 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
return 1;
if ((MAJOR(dev->dev) == dt->blkext_major) &&
- (dev_get_primary_dev(dt, dev, &primary_dev)) &&
+ (dev_get_primary_dev(dt, dev, &primary_dev) > 0) &&
(MAJOR(primary_dev) == dt->md_major))
return 1;
@@ -318,28 +318,60 @@ int dev_is_partitioned(struct dev_types *dt, struct device *dev)
return _has_partition_table(dev);
}
+/*
+ * Get primary dev for the dev supplied.
+ * Returns:
+ * 0 if the dev is already a primary dev
+ * 1 if the dev is a partition, primary dev in result
+ * -1 on error
+ */
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
{
const char *sysfs_dir = dm_sysfs_dir();
+ int major = (int) MAJOR(dev->dev);
+ int minor = (int) MINOR(dev->dev);
char path[PATH_MAX+1];
char temp_path[PATH_MAX+1];
char buffer[64];
struct stat info;
- FILE *fp;
- uint32_t pri_maj, pri_min;
- int size, ret = 0;
+ FILE *fp = NULL;
+ int parts, residue, size, ret = -1;
+
+ /*
+ * Try to get the primary dev out of the
+ * list of known device types first.
+ */
+ if ((parts = dt->dev_type_array[major].max_partitions) > 1) {
+ if ((residue = minor % parts)) {
+ *result = MKDEV((dev_t)major, (minor - residue));
+ ret = 1;
+ } else {
+ *result = dev->dev;
+ ret = 0; /* dev is not a partition! */
+ }
+ goto out;
+ }
+
+ /*
+ * If we can't get the primary dev out of the list of known device
+ * types, try to look at sysfs directly then. This is more complex
+ * way and it also requires certain sysfs layout to be present
+ * which might not be there in old kernels!
+ */
/* check if dev is a partition */
if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
- sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
+ sysfs_dir, major, minor) < 0) {
log_error("dm_snprintf partition failed");
- return ret;
+ goto out;
}
if (stat(path, &info) == -1) {
if (errno != ENOENT)
log_sys_error("stat", path);
- return ret;
+ *result = dev->dev;
+ ret = 0; goto out; /* dev is not a partition! */
+
}
/*
@@ -351,7 +383,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
*/
if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
log_sys_error("readlink", path);
- return ret;
+ goto out;
}
temp_path[size] = '\0';
@@ -359,7 +391,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
sysfs_dir, basename(dirname(temp_path))) < 0) {
log_error("dm_snprintf dev failed");
- return ret;
+ goto out;
}
/* finally, parse 'dev' attribute and create corresponding dev_t */
@@ -368,13 +400,13 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
log_error("sysfs file %s does not exist", path);
else
log_sys_error("stat", path);
- return ret;
+ goto out;
}
fp = fopen(path, "r");
if (!fp) {
log_sys_error("fopen", path);
- return ret;
+ goto out;
}
if (!fgets(buffer, sizeof(buffer), fp)) {
@@ -382,16 +414,15 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
goto out;
}
- if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
+ if (sscanf(buffer, "%d:%d", &major, &minor) != 2) {
log_error("sysfs file %s not in expected MAJ:MIN format: %s",
path, buffer);
goto out;
}
- *result = MKDEV((dev_t)pri_maj, pri_min);
+ *result = MKDEV((dev_t)major, minor);
ret = 1;
-
out:
- if (fclose(fp))
+ if (fp && fclose(fp))
log_sys_error("fclose", path);
return ret;
@@ -615,7 +646,7 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
log_sys_error("stat", path);
return 0;
}
- if (!dev_get_primary_dev(dt, dev, &primary))
+ if (dev_get_primary_dev(dt, dev, &primary) < 0)
return 0;
/* get attribute from partition's primary device */
10 years, 9 months
master - refactor: make device type recognition code common for general use
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=c6f48b7c1a0271...
Commit: c6f48b7c1a0271255405346c50d6bee8cc8b9241
Parent: 1778d34cefdfe30055ac4a7e82438e4484004491
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 12 12:08:56 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 12 12:08:56 2013 +0200
refactor: make device type recognition code common for general use
Changes:
- move device type registration out of "type filter" (filter.c)
to a separate and new dev-type.[ch] for common use throughout the code
- the structure for keeping the major numbers detected for available
device types and available partitioning available is stored in
"dev_types" structure now
- move common partitioning detection code to dev-type.[ch] as well
together with other device-related functions bound to dev_types
(see dev-type.h for the interface)
The dev-type interface contains all common functions used to detect
subsystems/device types, signature/superblock recognition code,
type-specific device properties and other common device properties
(bound to dev_types), including partitioning support.
- add dev_types instance to cmd context as cmd->dev_types for common use
- use cmd->dev_types throughout as a central point for providing
information about device types
---
include/.symlinks.in | 1 +
lib/cache/lvmcache.c | 14 +-
lib/cache/lvmcache.h | 1 +
lib/commands/toolcontext.c | 28 ++-
lib/commands/toolcontext.h | 2 +
lib/device/dev-cache.c | 1 +
lib/device/dev-luks.c | 1 +
lib/device/dev-md.c | 39 ++--
lib/device/dev-swap.c | 1 +
lib/device/dev-type.c | 443 +++++++++++++++++++++++++++++----------
lib/device/dev-type.h | 76 +++++++
lib/device/device-types.h | 73 ++++----
lib/device/device.h | 16 --
lib/filters/filter-composite.c | 2 -
lib/filters/filter-md.c | 6 +-
lib/filters/filter-md.h | 3 +-
lib/filters/filter-mpath.c | 25 +--
lib/filters/filter-mpath.h | 3 +-
lib/filters/filter-persistent.c | 17 +-
lib/filters/filter-persistent.h | 4 +-
lib/filters/filter-regex.c | 1 -
lib/filters/filter-regex.h | 1 -
lib/filters/filter-sysfs.h | 1 -
lib/filters/filter.c | 274 +-----------------------
lib/filters/filter.h | 27 +--
lib/format1/disk-rep.c | 11 +-
lib/format_pool/disk_rep.c | 9 +-
lib/metadata/metadata.c | 8 +-
lib/metadata/pv_manip.c | 4 +-
29 files changed, 559 insertions(+), 533 deletions(-)
diff --git a/include/.symlinks.in b/include/.symlinks.in
index 1c883ae..facadbe 100644
--- a/include/.symlinks.in
+++ b/include/.symlinks.in
@@ -15,6 +15,7 @@
@top_srcdir(a)/lib/datastruct/lvm-types.h
@top_srcdir(a)/lib/datastruct/str_list.h
@top_srcdir(a)/lib/device/dev-cache.h
+@top_srcdir(a)/lib/device/dev-type.h
@top_srcdir(a)/lib/device/device.h
@top_srcdir(a)/lib/display/display.h
@top_srcdir(a)/lib/filters/filter-composite.h
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 6f935db..c0b3299 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1452,6 +1452,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
const char *vgname, const char *vgid,
uint32_t vgstatus)
{
+ const struct format_type *fmt = (const struct format_type *) labeller->private;
+ struct dev_types *dt = fmt->cmd->dev_types;
struct label *label;
struct lvmcache_info *existing, *info;
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
@@ -1485,12 +1487,12 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
} else {
if (existing->dev != dev) {
/* Is the existing entry a duplicate pvid e.g. md ? */
- if (dev_subsystem_part_major(existing->dev) &&
- !dev_subsystem_part_major(dev)) {
+ if (dev_subsystem_part_major(dt, existing->dev) &&
+ !dev_subsystem_part_major(dt, dev)) {
log_very_verbose("Ignoring duplicate PV %s on "
"%s - using %s %s",
pvid, dev_name(dev),
- dev_subsystem_name(existing->dev),
+ dev_subsystem_name(dt, existing->dev),
dev_name(existing->dev));
return NULL;
} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
@@ -1500,12 +1502,12 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
pvid, dev_name(dev),
dev_name(existing->dev));
return NULL;
- } else if (!dev_subsystem_part_major(existing->dev) &&
- dev_subsystem_part_major(dev))
+ } else if (!dev_subsystem_part_major(dt, existing->dev) &&
+ dev_subsystem_part_major(dt, dev))
log_very_verbose("Duplicate PV %s on %s - "
"using %s %s", pvid,
dev_name(existing->dev),
- dev_subsystem_name(existing->dev),
+ dev_subsystem_name(dt, existing->dev),
dev_name(dev));
else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
dm_is_dm_major(MAJOR(dev->dev)))
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 119b411..bf26664 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -17,6 +17,7 @@
#define _LVM_CACHE_H
#include "dev-cache.h"
+#include "dev-type.h"
#include "uuid.h"
#include "label.h"
#include "locking.h"
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index dca2329..79c25a5 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -820,8 +820,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
nr_filt++;
/* device type filter. Required. */
- cn = find_config_tree_node(cmd, devices_types_CFG);
- if (!(filters[nr_filt] = lvm_type_filter_create(cmd->proc_dir, cn))) {
+ if (!(filters[nr_filt] = lvm_type_filter_create(cmd->dev_types))) {
log_error("Failed to create lvm type filter");
goto bad;
}
@@ -830,13 +829,13 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
/* md component filter. Optional, non-critical. */
if (find_config_tree_bool(cmd, devices_md_component_detection_CFG)) {
init_md_filtering(1);
- if ((filters[nr_filt] = md_filter_create()))
+ if ((filters[nr_filt] = md_filter_create(cmd->dev_types)))
nr_filt++;
}
/* mpath component filter. Optional, non-critical. */
if (find_config_tree_bool(cmd, devices_multipath_component_detection_CFG)) {
- if ((filters[nr_filt] = mpath_filter_create()))
+ if ((filters[nr_filt] = mpath_filter_create(cmd->dev_types)))
nr_filt++;
}
@@ -898,7 +897,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
if (!dev_cache)
dev_cache = cache_file;
- if (!(f4 = persistent_filter_create(f3, dev_cache))) {
+ if (!(f4 = persistent_filter_create(cmd->dev_types, f3, dev_cache))) {
log_verbose("Failed to create persistent device filter.");
f3->destroy(f3);
return_0;
@@ -1451,6 +1450,10 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
if (!_process_config(cmd))
goto_out;
+ if (!(cmd->dev_types = create_dev_types(cmd->proc_dir,
+ find_config_tree_node(cmd, devices_types_CFG))))
+ goto_out;
+
if (!_init_dev_cache(cmd))
goto_out;
@@ -1541,6 +1544,15 @@ skip_dlclose:
}
}
+static void _destroy_dev_types(struct cmd_context *cmd)
+{
+ if (!cmd->dev_types)
+ return;
+
+ dm_free(cmd->dev_types);
+ cmd->dev_types = NULL;
+}
+
int refresh_filters(struct cmd_context *cmd)
{
int r, saved_ignore_suspended_devices = ignore_suspended_devices();
@@ -1584,6 +1596,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
cmd->filter = NULL;
}
dev_cache_exit();
+ _destroy_dev_types(cmd);
_destroy_tags(cmd);
cft_cmdline = _destroy_tag_configs(cmd);
@@ -1623,6 +1636,10 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_process_config(cmd))
return 0;
+ if (!(cmd->dev_types = create_dev_types(cmd->proc_dir,
+ find_config_tree_node(cmd, devices_types_CFG))))
+ return 0;
+
if (!_init_dev_cache(cmd))
return 0;
@@ -1667,6 +1684,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
if (cmd->mem)
dm_pool_destroy(cmd->mem);
dev_cache_exit();
+ _destroy_dev_types(cmd);
_destroy_tags(cmd);
if ((cft_cmdline = _destroy_tag_configs(cmd)))
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 307dc77..f6a09a7 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -17,6 +17,7 @@
#define _LVM_TOOLCONTEXT_H
#include "dev-cache.h"
+#include "dev-type.h"
#include <stdio.h>
#include <limits.h>
@@ -91,6 +92,7 @@ struct cmd_context {
unsigned independent_metadata_areas:1; /* Active formats have MDAs outside PVs */
+ struct dev_types *dev_types;
struct dev_filter *filter;
struct dev_filter *lvmetad_filter;
int dump_filter; /* Dump filter when exiting? */
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 0933549..9981967 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -18,6 +18,7 @@
#include "lvm-types.h"
#include "btree.h"
#include "filter.h"
+#include "config.h"
#include "toolcontext.h"
#include <unistd.h>
diff --git a/lib/device/dev-luks.c b/lib/device/dev-luks.c
index 10aae30..2c79a2b 100644
--- a/lib/device/dev-luks.c
+++ b/lib/device/dev-luks.c
@@ -13,6 +13,7 @@
*/
#include "lib.h"
+#include "dev-type.h"
#include "metadata.h"
#define LUKS_SIGNATURE "LUKS\xba\xbe"
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index c4e2316..a8bbe81 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -14,9 +14,9 @@
*/
#include "lib.h"
+#include "dev-type.h"
#include "metadata.h"
#include "xlate.h"
-#include "filter.h"
#ifdef linux
@@ -127,6 +127,7 @@ out:
}
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
+ struct dev_types *dt,
struct device *blkdev,
const char *attribute)
{
@@ -138,13 +139,13 @@ static int _md_sysfs_attribute_snprintf(char *path, size_t size,
if (!sysfs_dir || !*sysfs_dir)
return ret;
- if (MAJOR(dev) == blkext_major()) {
+ if (MAJOR(dev) == dt->blkext_major) {
/* lookup parent MD device from blkext partition */
- if (!get_primary_dev(blkdev, &dev))
+ if (!dev_get_primary_dev(dt, blkdev, &dev))
return ret;
}
- if (MAJOR(dev) != md_major())
+ if (MAJOR(dev) != dt->md_major)
return ret;
ret = dm_snprintf(path, size, "%s/dev/block/%d:%d/md/%s", sysfs_dir,
@@ -171,7 +172,7 @@ static int _md_sysfs_attribute_snprintf(char *path, size_t size,
return ret;
}
-static int _md_sysfs_attribute_scanf(const char *sysfs_dir,
+static int _md_sysfs_attribute_scanf(struct dev_types *dt,
struct device *dev,
const char *attribute_name,
const char *attribute_fmt,
@@ -181,8 +182,8 @@ static int _md_sysfs_attribute_scanf(const char *sysfs_dir,
FILE *fp;
int ret = 0;
- if (_md_sysfs_attribute_snprintf(path, PATH_MAX, dev,
- attribute_name) < 0)
+ if (_md_sysfs_attribute_snprintf(path, PATH_MAX, dt,
+ dev, attribute_name) < 0)
return ret;
if (!(fp = fopen(path, "r"))) {
@@ -211,13 +212,13 @@ out:
/*
* Retrieve chunk size from md device using sysfs.
*/
-static unsigned long dev_md_chunk_size(const char *sysfs_dir,
+static unsigned long dev_md_chunk_size(struct dev_types *dt,
struct device *dev)
{
const char *attribute = "chunk_size";
unsigned long chunk_size_bytes = 0UL;
- if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute,
+ if (_md_sysfs_attribute_scanf(dt, dev, attribute,
"%lu", &chunk_size_bytes) != 1)
return 0;
@@ -230,13 +231,13 @@ static unsigned long dev_md_chunk_size(const char *sysfs_dir,
/*
* Retrieve level from md device using sysfs.
*/
-static int dev_md_level(const char *sysfs_dir, struct device *dev)
+static int dev_md_level(struct dev_types *dt, struct device *dev)
{
char level_string[MD_MAX_SYSFS_SIZE];
const char *attribute = "level";
int level = -1;
- if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute,
+ if (_md_sysfs_attribute_scanf(dt, dev, attribute,
"%s", &level_string) != 1)
return -1;
@@ -253,12 +254,12 @@ static int dev_md_level(const char *sysfs_dir, struct device *dev)
/*
* Retrieve raid_disks from md device using sysfs.
*/
-static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
+static int dev_md_raid_disks(struct dev_types *dt, struct device *dev)
{
const char *attribute = "raid_disks";
int raid_disks = 0;
- if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute,
+ if (_md_sysfs_attribute_scanf(dt, dev, attribute,
"%d", &raid_disks) != 1)
return 0;
@@ -271,22 +272,21 @@ static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
/*
* Calculate stripe width of md device using its sysfs files.
*/
-unsigned long dev_md_stripe_width(struct device *dev)
+unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev)
{
- const char *sysfs_dir = dm_sysfs_dir();
unsigned long chunk_size_sectors = 0UL;
unsigned long stripe_width_sectors = 0UL;
int level, raid_disks, data_disks;
- chunk_size_sectors = dev_md_chunk_size(sysfs_dir, dev);
+ chunk_size_sectors = dev_md_chunk_size(dt, dev);
if (!chunk_size_sectors)
return 0;
- level = dev_md_level(sysfs_dir, dev);
+ level = dev_md_level(dt, dev);
if (level < 0)
return 0;
- raid_disks = dev_md_raid_disks(sysfs_dir, dev);
+ raid_disks = dev_md_raid_disks(dt, dev);
if (!raid_disks)
return 0;
@@ -333,7 +333,8 @@ int dev_is_md(struct device *dev __attribute__((unused)),
return 0;
}
-unsigned long dev_md_stripe_width(struct device *dev __attribute__((unused)))
+unsigned long dev_md_stripe_width(struct dev_types *dt __attribute__((unused)),
+ struct device *dev __attribute__((unused)))
{
return 0UL;
}
diff --git a/lib/device/dev-swap.c b/lib/device/dev-swap.c
index 346b60a..c3b121b 100644
--- a/lib/device/dev-swap.c
+++ b/lib/device/dev-swap.c
@@ -13,6 +13,7 @@
*/
#include "lib.h"
+#include "dev-type.h"
#include "metadata.h"
#ifdef linux
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
index 52eb4a6..150daf4 100644
--- a/lib/device/dev-type.c
+++ b/lib/device/dev-type.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -14,16 +13,240 @@
*/
#include "lib.h"
-#include "lvm-types.h"
-#include "device.h"
-#include "metadata.h"
-#include "filter.h"
+#include "dev-type.h"
#include "xlate.h"
+#include "config.h"
+#include "metadata.h"
-#include <libgen.h> /* dirname, basename */
+#include <libgen.h>
+#include <ctype.h>
-/* See linux/genhd.h and fs/partitions/msdos */
+#include "device-types.h"
+
+struct dev_types *create_dev_types(const char *proc_dir,
+ const struct dm_config_node *cn)
+{
+ struct dev_types *dt;
+ char line[80];
+ char proc_devices[PATH_MAX];
+ FILE *pd = NULL;
+ int i, j = 0;
+ int line_maj = 0;
+ int blocksection = 0;
+ size_t dev_len = 0;
+ const struct dm_config_value *cv;
+ const char *name;
+ char *nl;
+
+ if (!(dt = dm_zalloc(sizeof(struct dev_types)))) {
+ log_error("Failed to allocate device type register.");
+ return NULL;
+ }
+
+ if (!*proc_dir) {
+ log_verbose("No proc filesystem found: using all block device types");
+ for (i = 0; i < NUMBER_OF_MAJORS; i++)
+ dt->dev_type_array[i].max_partitions = 1;
+ return dt;
+ }
+
+ if (dm_snprintf(proc_devices, sizeof(proc_devices),
+ "%s/devices", proc_dir) < 0) {
+ log_error("Failed to create /proc/devices string");
+ goto bad;
+ }
+
+ if (!(pd = fopen(proc_devices, "r"))) {
+ log_sys_error("fopen", proc_devices);
+ goto bad;
+ }
+
+ while (fgets(line, sizeof(line), pd) != NULL) {
+ i = 0;
+ while (line[i] == ' ')
+ i++;
+
+ /* If it's not a number it may be name of section */
+ line_maj = atoi(((char *) (line + i)));
+
+ if (line_maj < 0 || line_maj >= NUMBER_OF_MAJORS) {
+ /*
+ * Device numbers shown in /proc/devices are actually direct
+ * numbers passed to registering function, however the kernel
+ * uses only 12 bits, so use just 12 bits for major.
+ */
+ if ((nl = strchr(line, '\n'))) *nl = '\0';
+ log_warn("WARNING: /proc/devices line: %s, replacing major with %d.",
+ line, line_maj & (NUMBER_OF_MAJORS - 1));
+ line_maj &= (NUMBER_OF_MAJORS - 1);
+ }
+
+ if (!line_maj) {
+ blocksection = (line[i] == 'B') ? 1 : 0;
+ continue;
+ }
+
+ /* We only want block devices ... */
+ if (!blocksection)
+ continue;
+
+ /* Find the start of the device major name */
+ while (line[i] != ' ' && line[i] != '\0')
+ i++;
+ while (line[i] == ' ')
+ i++;
+
+ /* Look for md device */
+ if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
+ dt->md_major = line_maj;
+
+ /* Look for blkext device */
+ if (!strncmp("blkext", line + i, 6) && isspace(*(line + i + 6)))
+ dt->blkext_major = line_maj;
+
+ /* Look for drbd device */
+ if (!strncmp("drbd", line + i, 4) && isspace(*(line + i + 4)))
+ dt->drbd_major = line_maj;
+
+ /* Look for EMC powerpath */
+ if (!strncmp("emcpower", line + i, 8) && isspace(*(line + i + 8)))
+ dt->emcpower_major = line_maj;
+
+ if (!strncmp("power2", line + i, 6) && isspace(*(line + i + 6)))
+ dt->power2_major = line_maj;
+
+ /* Look for device-mapper device */
+ /* FIXME Cope with multiple majors */
+ if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
+ dt->device_mapper_major = line_maj;
+
+ /* Major is SCSI device */
+ if (!strncmp("sd", line + i, 2) && isspace(*(line + i + 2)))
+ dt->dev_type_array[line_maj].flags |= PARTITION_SCSI_DEVICE;
+
+ /* Go through the valid device names and if there is a
+ match store max number of partitions */
+ for (j = 0; _dev_known_types[j].name[0]; j++) {
+ dev_len = strlen(_dev_known_types[j].name);
+ if (dev_len <= strlen(line + i) &&
+ !strncmp(_dev_known_types[j].name, line + i, dev_len) &&
+ (line_maj < NUMBER_OF_MAJORS)) {
+ dt->dev_type_array[line_maj].max_partitions =
+ _dev_known_types[j].max_partitions;
+ break;
+ }
+ }
+
+ if (!cn)
+ continue;
+
+ /* Check devices/types for local variations */
+ for (cv = cn->v; cv; cv = cv->next) {
+ if (cv->type != DM_CFG_STRING) {
+ log_error("Expecting string in devices/types "
+ "in config file");
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
+ goto bad;
+ }
+ dev_len = strlen(cv->v.str);
+ name = cv->v.str;
+ cv = cv->next;
+ if (!cv || cv->type != DM_CFG_INT) {
+ log_error("Max partition count missing for %s "
+ "in devices/types in config file",
+ name);
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
+ goto bad;
+ }
+ if (!cv->v.i) {
+ log_error("Zero partition count invalid for "
+ "%s in devices/types in config file",
+ name);
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
+ goto bad;
+ }
+ if (dev_len <= strlen(line + i) &&
+ !strncmp(name, line + i, dev_len) &&
+ (line_maj < NUMBER_OF_MAJORS)) {
+ dt->dev_type_array[line_maj].max_partitions = cv->v.i;
+ break;
+ }
+ }
+ }
+
+ if (fclose(pd))
+ log_sys_error("fclose", proc_devices);
+
+ return dt;
+bad:
+ dm_free(dt);
+ return NULL;
+}
+
+int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
+{
+ dev_t primary_dev;
+
+ if (MAJOR(dev->dev) == dt->device_mapper_major)
+ return 1;
+
+ if (MAJOR(dev->dev) == dt->drbd_major)
+ return 1;
+
+ if (MAJOR(dev->dev) == dt->emcpower_major)
+ return 1;
+
+ if (MAJOR(dev->dev) == dt->power2_major)
+ return 1;
+ if ((MAJOR(dev->dev) == dt->blkext_major) &&
+ (dev_get_primary_dev(dt, dev, &primary_dev)) &&
+ (MAJOR(primary_dev) == dt->md_major))
+ return 1;
+
+ return 0;
+}
+
+const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
+{
+ if (MAJOR(dev->dev) == dt->md_major)
+ return "MD";
+
+ if (MAJOR(dev->dev) == dt->drbd_major)
+ return "DRBD";
+
+ if (MAJOR(dev->dev) == dt->emcpower_major)
+ return "EMCPOWER";
+
+ if (MAJOR(dev->dev) == dt->power2_major)
+ return "POWER2";
+
+ if (MAJOR(dev->dev) == dt->blkext_major)
+ return "BLKEXT";
+
+ return "";
+}
+
+int major_max_partitions(struct dev_types *dt, int major)
+{
+ if (major >= NUMBER_OF_MAJORS)
+ return 0;
+
+ return dt->dev_type_array[major].max_partitions;
+}
+
+int major_is_scsi_device(struct dev_types *dt, int major)
+{
+ if (major >= NUMBER_OF_MAJORS)
+ return 0;
+
+ return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
+}
+
+/* See linux/genhd.h and fs/partitions/msdos */
#define PART_MAGIC 0xAA55
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
#define PART_OFFSET UINT64_C(0x1BE)
@@ -41,12 +264,12 @@ struct partition {
uint32_t nr_sects;
} __attribute__((packed));
-static int _is_partitionable(struct device *dev)
+static int _is_partitionable(struct dev_types *dt, struct device *dev)
{
- int parts = max_partitions(MAJOR(dev->dev));
+ int parts = major_max_partitions(dt, MAJOR(dev->dev));
/* All MD devices are partitionable via blkext (as of 2.6.28) */
- if (MAJOR(dev->dev) == md_major())
+ if (MAJOR(dev->dev) == dt->md_major)
return 1;
if ((parts <= 1) || (MINOR(dev->dev) % parts))
@@ -87,14 +310,93 @@ static int _has_partition_table(struct device *dev)
return ret;
}
-int is_partitioned_dev(struct device *dev)
+int dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
- if (!_is_partitionable(dev))
+ if (!_is_partitionable(dt, dev))
return 0;
return _has_partition_table(dev);
}
+int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
+{
+ const char *sysfs_dir = dm_sysfs_dir();
+ char path[PATH_MAX+1];
+ char temp_path[PATH_MAX+1];
+ char buffer[64];
+ struct stat info;
+ FILE *fp;
+ uint32_t pri_maj, pri_min;
+ int size, ret = 0;
+
+ /* check if dev is a partition */
+ if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
+ sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
+ log_error("dm_snprintf partition failed");
+ return ret;
+ }
+
+ if (stat(path, &info) == -1) {
+ if (errno != ENOENT)
+ log_sys_error("stat", path);
+ return ret;
+ }
+
+ /*
+ * extract parent's path from the partition's symlink, e.g.:
+ * - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
+ * - dirname ../../block/md0/md0p1 = ../../block/md0
+ * - basename ../../block/md0/md0 = md0
+ * Parent's 'dev' sysfs attribute = /sys/block/md0/dev
+ */
+ if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
+ log_sys_error("readlink", path);
+ return ret;
+ }
+
+ temp_path[size] = '\0';
+
+ if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
+ sysfs_dir, basename(dirname(temp_path))) < 0) {
+ log_error("dm_snprintf dev failed");
+ return ret;
+ }
+
+ /* finally, parse 'dev' attribute and create corresponding dev_t */
+ if (stat(path, &info) == -1) {
+ if (errno == ENOENT)
+ log_error("sysfs file %s does not exist", path);
+ else
+ log_sys_error("stat", path);
+ return ret;
+ }
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ log_sys_error("fopen", path);
+ return ret;
+ }
+
+ if (!fgets(buffer, sizeof(buffer), fp)) {
+ log_sys_error("fgets", path);
+ goto out;
+ }
+
+ if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
+ log_error("sysfs file %s not in expected MAJ:MIN format: %s",
+ path, buffer);
+ goto out;
+ }
+ *result = MKDEV((dev_t)pri_maj, pri_min);
+ ret = 1;
+
+out:
+ if (fclose(fp))
+ log_sys_error("fclose", path);
+
+ return ret;
+}
+
#if 0
#include <sys/stat.h>
#include <sys/mman.h>
@@ -278,86 +580,9 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
#ifdef linux
-int get_primary_dev(const struct device *dev, dev_t *result)
-{
- const char *sysfs_dir = dm_sysfs_dir();
- char path[PATH_MAX+1];
- char temp_path[PATH_MAX+1];
- char buffer[64];
- struct stat info;
- FILE *fp;
- uint32_t pri_maj, pri_min;
- int size, ret = 0;
-
- /* check if dev is a partition */
- if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
- sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
- log_error("dm_snprintf partition failed");
- return ret;
- }
-
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
- return ret;
- }
-
- /*
- * extract parent's path from the partition's symlink, e.g.:
- * - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
- * - dirname ../../block/md0/md0p1 = ../../block/md0
- * - basename ../../block/md0/md0 = md0
- * Parent's 'dev' sysfs attribute = /sys/block/md0/dev
- */
- if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
- log_sys_error("readlink", path);
- return ret;
- }
-
- temp_path[size] = '\0';
-
- if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
- sysfs_dir, basename(dirname(temp_path))) < 0) {
- log_error("dm_snprintf dev failed");
- return ret;
- }
-
- /* finally, parse 'dev' attribute and create corresponding dev_t */
- if (stat(path, &info) == -1) {
- if (errno == ENOENT)
- log_error("sysfs file %s does not exist", path);
- else
- log_sys_error("stat", path);
- return ret;
- }
-
- fp = fopen(path, "r");
- if (!fp) {
- log_sys_error("fopen", path);
- return ret;
- }
-
- if (!fgets(buffer, sizeof(buffer), fp)) {
- log_sys_error("fgets", path);
- goto out;
- }
-
- if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
- log_error("sysfs file %s not in expected MAJ:MIN format: %s",
- path, buffer);
- goto out;
- }
- *result = MKDEV((dev_t)pri_maj, pri_min);
- ret = 1;
-
-out:
- if (fclose(fp))
- log_sys_error("fclose", path);
-
- return ret;
-}
-
-static unsigned long _dev_topology_attribute(const char *attribute, struct device *dev)
+static unsigned long _dev_topology_attribute(struct dev_types *dt,
+ const char *attribute,
+ struct device *dev)
{
const char *sysfs_dir = dm_sysfs_dir();
static const char sysfs_fmt_str[] = "%s/dev/block/%d:%d/%s";
@@ -390,7 +615,7 @@ static unsigned long _dev_topology_attribute(const char *attribute, struct devic
log_sys_error("stat", path);
return 0;
}
- if (!get_primary_dev(dev, &primary))
+ if (!dev_get_primary_dev(dt, dev, &primary))
return 0;
/* get attribute from partition's primary device */
@@ -433,29 +658,29 @@ out:
return result >> SECTOR_SHIFT;
}
-unsigned long dev_alignment_offset(struct device *dev)
+unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev)
{
- return _dev_topology_attribute("alignment_offset", dev);
+ return _dev_topology_attribute(dt, "alignment_offset", dev);
}
-unsigned long dev_minimum_io_size(struct device *dev)
+unsigned long dev_minimum_io_size(struct dev_types *dt, struct device *dev)
{
- return _dev_topology_attribute("queue/minimum_io_size", dev);
+ return _dev_topology_attribute(dt, "queue/minimum_io_size", dev);
}
-unsigned long dev_optimal_io_size(struct device *dev)
+unsigned long dev_optimal_io_size(struct dev_types *dt, struct device *dev)
{
- return _dev_topology_attribute("queue/optimal_io_size", dev);
+ return _dev_topology_attribute(dt, "queue/optimal_io_size", dev);
}
-unsigned long dev_discard_max_bytes(struct device *dev)
+unsigned long dev_discard_max_bytes(struct dev_types *dt, struct device *dev)
{
- return _dev_topology_attribute("queue/discard_max_bytes", dev);
+ return _dev_topology_attribute(dt, "queue/discard_max_bytes", dev);
}
-unsigned long dev_discard_granularity(struct device *dev)
+unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev)
{
- return _dev_topology_attribute("queue/discard_granularity", dev);
+ return _dev_topology_attribute(dt, "queue/discard_granularity", dev);
}
#else
@@ -465,27 +690,27 @@ int get_primary_dev(struct device *dev, dev_t *result)
return 0;
}
-unsigned long dev_alignment_offset(struct device *dev)
+unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev)
{
return 0UL;
}
-unsigned long dev_minimum_io_size(struct device *dev)
+unsigned long dev_minimum_io_size(struct dev_types *dt, struct device *dev)
{
return 0UL;
}
-unsigned long dev_optimal_io_size(struct device *dev)
+unsigned long dev_optimal_io_size(struct dev_types *dt, struct device *dev)
{
return 0UL;
}
-unsigned long dev_discard_max_bytes(struct device *dev)
+unsigned long dev_discard_max_bytes(struct dev_types *dt, struct device *dev)
{
return 0UL;
}
-unsigned long dev_discard_granularity(struct device *dev)
+unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev)
{
return 0UL;
}
diff --git a/lib/device/dev-type.h b/lib/device/dev-type.h
new file mode 100644
index 0000000..1227ab0
--- /dev/null
+++ b/lib/device/dev-type.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_DEV_TYPE_H
+#define _LVM_DEV_TYPE_H
+
+#include "device.h"
+
+#define NUMBER_OF_MAJORS 4096
+
+#ifdef linux
+# define MAJOR(dev) ((dev & 0xfff00) >> 8)
+# define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
+# define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+#else
+# define MAJOR(x) major((x))
+# define MINOR(x) minor((x))
+# define MKDEV(x,y) makedev((x),(y))
+#endif
+
+#define PARTITION_SCSI_DEVICE (1 << 0)
+
+struct dev_type_def {
+ int max_partitions; /* 0 means LVM won't use this major number. */
+ int flags;
+};
+
+struct dev_types {
+ int md_major;
+ int blkext_major;
+ int drbd_major;
+ int device_mapper_major;
+ int emcpower_major;
+ int power2_major;
+ struct dev_type_def dev_type_array[NUMBER_OF_MAJORS];
+};
+
+struct dev_types *create_dev_types(const char *proc_dir, const struct dm_config_node *cn);
+
+/* Subsystems */
+int dev_subsystem_part_major(struct dev_types *dt, struct device *dev);
+const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
+int major_is_scsi_device(struct dev_types *dt, int major);
+
+/* Signature/superblock recognition with position returned where found. */
+int dev_is_md(struct device *dev, uint64_t *sb);
+int dev_is_swap(struct device *dev, uint64_t *signature);
+int dev_is_luks(struct device *dev, uint64_t *signature);
+
+/* Type-specific device properties */
+unsigned long dev_md_stripe_width(struct dev_types *dt, struct device *dev);
+
+/* Partitioning */
+int major_max_partitions(struct dev_types *dt, int major);
+int dev_is_partitioned(struct dev_types *dt, struct device *dev);
+int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result);
+
+/* Various device properties */
+unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev);
+unsigned long dev_minimum_io_size(struct dev_types *dt, struct device *dev);
+unsigned long dev_optimal_io_size(struct dev_types *dt, struct device *dev);
+unsigned long dev_discard_max_bytes(struct dev_types *dt, struct device *dev);
+unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev);
+
+#endif
diff --git a/lib/device/device-types.h b/lib/device/device-types.h
index 2e49f7f..48ae32a 100644
--- a/lib/device/device-types.h
+++ b/lib/device/device-types.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -16,7 +16,8 @@
typedef struct {
const char name[15];
const int8_t max_partitions;
-} device_info_t;
+ const char *desc;
+} dev_known_type_t;
/*
* Devices are only checked for partition tables if their minor number
@@ -26,38 +27,38 @@ typedef struct {
*
* The list can be supplemented with devices/types in the config file.
*/
-static const device_info_t _device_info[] = {
- {"ide", 64}, /* IDE disk */
- {"sd", 16}, /* SCSI disk */
- {"md", 1}, /* Multiple Disk driver (SoftRAID) */
- {"mdp", 1}, /* Partitionable MD */
- {"loop", 1}, /* Loop device */
- {"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
- {"dac960", 8}, /* DAC960 */
- {"nbd", 16}, /* Network Block Device */
- {"ida", 16}, /* Compaq SMART2 */
- {"cciss", 16}, /* Compaq CCISS array */
- {"ubd", 16}, /* User-mode virtual block device */
- {"ataraid", 16}, /* ATA Raid */
- {"drbd", 16}, /* Distributed Replicated Block Device */
- {"emcpower", 16}, /* EMC Powerpath */
- {"power2", 16}, /* EMC Powerpath */
- {"i2o_block", 16}, /* i2o Block Disk */
- {"iseries/vd", 8}, /* iSeries disks */
- {"gnbd", 1}, /* Network block device */
- {"ramdisk", 1}, /* RAM disk */
- {"aoe", 16}, /* ATA over Ethernet */
- {"device-mapper", 1}, /* Other mapped devices */
- {"xvd", 16}, /* Xen virtual block device */
- {"vdisk", 8}, /* SUN's LDOM virtual block device */
- {"ps3disk", 16}, /* PlayStation 3 internal disk */
- {"virtblk", 8}, /* VirtIO disk */
- {"mmc", 16}, /* MMC block device */
- {"blkext", 1}, /* Extended device partitions */
- {"fio", 16}, /* Fusion */
- {"mtip32xx", 16}, /* Micron PCIe SSDs */
- {"vtms", 16}, /* Violin Memory */
- {"skd", 16}, /* STEC */
- {"scm", 8}, /* Storage Class Memory (IBM S/390) */
- {"", 0}
+static const dev_known_type_t _dev_known_types[] = {
+ {"ide", 64, "IDE disk"},
+ {"sd", 16, "SCSI disk"},
+ {"md", 1, "Multiple Disk (MD/SoftRAID)"},
+ {"mdp", 1, "Partitionable MD"},
+ {"loop", 1, "Loop device"},
+ {"dasd", 4, "DASD disk (IBM S/390, zSeries)"},
+ {"dac960", 8, "DAC960"},
+ {"nbd", 16, "Network Block Device"},
+ {"ida", 16, "Compaq SMART2"},
+ {"cciss", 16, "Compaq CCISS array"},
+ {"ubd", 16, "User-mode virtual block device"},
+ {"ataraid", 16, "ATA Raid"},
+ {"drbd", 16, "Distributed Replicated Block Device (DRBD)"},
+ {"emcpower", 16, "EMC Powerpath"},
+ {"power2", 16, "EMC Powerpath"},
+ {"i2o_block", 16, "i2o Block Disk"},
+ {"iseries/vd", 8, "iSeries disks"},
+ {"gnbd", 1, "Network block device"},
+ {"ramdisk", 1, "RAM disk"},
+ {"aoe", 16, "ATA over Ethernet"},
+ {"device-mapper", 1, "Mapped device"},
+ {"xvd", 16, "Xen virtual block device"},
+ {"vdisk", 8, "SUN's LDOM virtual block device"},
+ {"ps3disk", 16, "PlayStation 3 internal disk"},
+ {"virtblk", 8, "VirtIO disk"},
+ {"mmc", 16, "MMC block device"},
+ {"blkext", 1, "Extended device partitions"},
+ {"fio", 16, "Fusion IO"},
+ {"mtip32xx", 16, "Micron PCIe SSD"},
+ {"vtms", 16, "Violin Memory"},
+ {"skd", 16, "STEC"},
+ {"scm", 8, "Storage Class Memory (IBM S/390)"},
+ {"", 0, ""}
};
diff --git a/lib/device/device.h b/lib/device/device.h
index 025d4ca..1d6304d 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -99,20 +99,4 @@ struct device *dev_create_file(const char *filename, struct device *dev,
/* Return a valid device name from the alias list; NULL otherwise */
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);
-int dev_is_swap(struct device *dev, uint64_t *signature);
-int dev_is_luks(struct device *dev, uint64_t *signature);
-unsigned long dev_md_stripe_width(struct device *dev);
-
-int is_partitioned_dev(struct device *dev);
-
-int get_primary_dev(const struct device *dev, dev_t *result);
-
-unsigned long dev_alignment_offset(struct device *dev);
-unsigned long dev_minimum_io_size(struct device *dev);
-unsigned long dev_optimal_io_size(struct device *dev);
-unsigned long dev_discard_max_bytes(struct device *dev);
-unsigned long dev_discard_granularity(struct device *dev);
-
#endif
diff --git a/lib/filters/filter-composite.c b/lib/filters/filter-composite.c
index c2b103d..47d147e 100644
--- a/lib/filters/filter-composite.c
+++ b/lib/filters/filter-composite.c
@@ -16,8 +16,6 @@
#include "lib.h"
#include "filter-composite.h"
-#include <stdarg.h>
-
static int _and_p(struct dev_filter *f, struct device *dev)
{
struct dev_filter **filters;
diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c
index 6f289b0..b18cd07 100644
--- a/lib/filters/filter-md.c
+++ b/lib/filters/filter-md.c
@@ -50,7 +50,7 @@ static void _destroy(struct dev_filter *f)
dm_free(f);
}
-struct dev_filter *md_filter_create(void)
+struct dev_filter *md_filter_create(struct dev_types *dt)
{
struct dev_filter *f;
@@ -62,14 +62,14 @@ struct dev_filter *md_filter_create(void)
f->passes_filter = _ignore_md;
f->destroy = _destroy;
f->use_count = 0;
- f->private = NULL;
+ f->private = dt;
return f;
}
#else
-struct dev_filter *md_filter_create(void)
+struct dev_filter *md_filter_create(struct dev_types *dt)
{
return NULL;
}
diff --git a/lib/filters/filter-md.h b/lib/filters/filter-md.h
index 6a98f0b..79e4f0e 100644
--- a/lib/filters/filter-md.h
+++ b/lib/filters/filter-md.h
@@ -16,8 +16,9 @@
#define _LVM_FILTER_MD_H
#include "dev-cache.h"
+#include "dev-type.h"
-struct dev_filter *md_filter_create(void);
+struct dev_filter *md_filter_create(struct dev_types *dt);
#endif
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index f3af268..0e88e65 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -13,11 +13,11 @@
*/
#include "lib.h"
-#include "filter.h"
#include "filter-mpath.h"
#include "activate.h"
#ifdef linux
+
#include <dirent.h>
#define MPATH_PREFIX "mpath-"
@@ -115,15 +115,17 @@ static int get_parent_mpath(const char *dir, char *name, int max_size)
static int dev_is_mpath(struct dev_filter *f, struct device *dev)
{
+ struct dev_types *dt = (struct dev_types *) f->private;
const char *name;
char path[PATH_MAX+1];
char parent_name[PATH_MAX+1];
struct stat info;
const char *sysfs_dir = dm_sysfs_dir();
- int major, minor;
+ int major = MAJOR(dev->dev);
+ int minor = MINOR(dev->dev);
/* Limit this filter only to SCSI devices */
- if (!major_is_scsi_device(MAJOR(dev->dev)))
+ if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
return 0;
if (!(name = get_sysfs_name(dev)))
@@ -149,8 +151,9 @@ static int dev_is_mpath(struct dev_filter *f, struct device *dev)
if (!get_sysfs_get_major_minor(sysfs_dir, parent_name, &major, &minor))
return_0;
- if (major != dm_major()) {
- log_error("mpath major %d is not dm major %d.", major, dm_major());
+ if (major != dt->device_mapper_major) {
+ log_error("mpath major %d is not dm major %d.", major,
+ dt->device_mapper_major);
return 0;
}
@@ -172,11 +175,10 @@ static void _destroy(struct dev_filter *f)
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying mpath filter while in use %u times.", f->use_count);
- dm_free(f->private);
dm_free(f);
}
-struct dev_filter *mpath_filter_create(void)
+struct dev_filter *mpath_filter_create(struct dev_types *dt)
{
const char *sysfs_dir = dm_sysfs_dir();
struct dev_filter *f;
@@ -194,19 +196,14 @@ struct dev_filter *mpath_filter_create(void)
f->passes_filter = _ignore_mpath;
f->destroy = _destroy;
f->use_count = 0;
-
- if (!(f->private = dm_strdup(sysfs_dir))) {
- log_error("Cannot duplicate sysfs dir.");
- dm_free(f);
- return NULL;
- }
+ f->private = dt;
return f;
}
#else
-struct dev_filter *mpath_filter_create(const char *sysfs_dir __attribute__((unused)))
+struct dev_filter *mpath_filter_create(struct device_types *dt)
{
return NULL;
}
diff --git a/lib/filters/filter-mpath.h b/lib/filters/filter-mpath.h
index 31585eb..5665f3b 100644
--- a/lib/filters/filter-mpath.h
+++ b/lib/filters/filter-mpath.h
@@ -16,8 +16,9 @@
#define _LVM_FILTER_MPATH_H
#include "dev-cache.h"
+#include "dev-type.h"
-struct dev_filter *mpath_filter_create(void);
+struct dev_filter *mpath_filter_create(struct dev_types *dt);
#endif
diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c
index 799e7d8..a59529d 100644
--- a/lib/filters/filter-persistent.c
+++ b/lib/filters/filter-persistent.c
@@ -14,23 +14,17 @@
*/
#include "lib.h"
-#include "config.h"
-#include "dev-cache.h"
-#include "filter.h"
#include "filter-persistent.h"
+#include "config.h"
#include "lvm-file.h"
-#include "lvm-string.h"
#include "activate.h"
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
struct pfilter {
char *file;
struct dm_hash_table *devices;
struct dev_filter *real;
time_t ctime;
+ struct dev_types *dt;
};
/*
@@ -287,7 +281,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
}
/* Test dm devices every time, so cache them as GOOD. */
- if (MAJOR(dev->dev) == dm_major()) {
+ if (MAJOR(dev->dev) == pf->dt->device_mapper_major) {
if (!l)
dm_list_iterate_items(sl, &dev->aliases)
if (!dm_hash_insert(pf->devices, sl->str, PF_GOOD_DEVICE)) {
@@ -329,7 +323,8 @@ static void _persistent_destroy(struct dev_filter *f)
dm_free(f);
}
-struct dev_filter *persistent_filter_create(struct dev_filter *real,
+struct dev_filter *persistent_filter_create(struct dev_types *dt,
+ struct dev_filter *real,
const char *file)
{
struct pfilter *pf;
@@ -341,6 +336,8 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
return NULL;
}
+ pf->dt = dt;
+
if (!(pf->file = dm_strdup(file))) {
log_error("Filename duplication for persistent filter failed.");
goto bad;
diff --git a/lib/filters/filter-persistent.h b/lib/filters/filter-persistent.h
index 58fbc10..bdbf887 100644
--- a/lib/filters/filter-persistent.h
+++ b/lib/filters/filter-persistent.h
@@ -17,8 +17,10 @@
#define _LVM_FILTER_PERSISTENT_H
#include "dev-cache.h"
+#include "dev-type.h"
-struct dev_filter *persistent_filter_create(struct dev_filter *f,
+struct dev_filter *persistent_filter_create(struct dev_types *dt,
+ struct dev_filter *f,
const char *file);
int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out);
diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c
index 7172c93..4fe9a7a 100644
--- a/lib/filters/filter-regex.c
+++ b/lib/filters/filter-regex.c
@@ -15,7 +15,6 @@
#include "lib.h"
#include "filter-regex.h"
-#include "device.h"
struct rfilter {
struct dm_pool *mem;
diff --git a/lib/filters/filter-regex.h b/lib/filters/filter-regex.h
index bb71f56..de05206 100644
--- a/lib/filters/filter-regex.h
+++ b/lib/filters/filter-regex.h
@@ -16,7 +16,6 @@
#ifndef _LVM_FILTER_REGEX_H
#define _LVM_FILTER_REGEX_H
-#include "config.h"
#include "dev-cache.h"
/*
diff --git a/lib/filters/filter-sysfs.h b/lib/filters/filter-sysfs.h
index 6fb5591..4b26ea6 100644
--- a/lib/filters/filter-sysfs.h
+++ b/lib/filters/filter-sysfs.h
@@ -15,7 +15,6 @@
#ifndef _LVM_FILTER_SYSFS_H
#define _LVM_FILTER_SYSFS_H
-#include "config.h"
#include "dev-cache.h"
struct dev_filter *sysfs_filter_create(void);
diff --git a/lib/filters/filter.c b/lib/filters/filter.c
index a86b398..cf06f88 100644
--- a/lib/filters/filter.c
+++ b/lib/filters/filter.c
@@ -14,104 +14,21 @@
*/
#include "lib.h"
-#include "dev-cache.h"
#include "filter.h"
#include "lvm-string.h"
#include "config.h"
#include "metadata.h"
#include "activate.h"
-#include <dirent.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <limits.h>
-
-#include "device/device-types.h"
-
-#define NUMBER_OF_MAJORS 4096
-
-#define PARTITION_SCSI_DEVICE (1 << 0)
-static struct {
- int max_partitions; /* 0 means LVM won't use this major number. */
- int flags;
-} _partitions[NUMBER_OF_MAJORS];
-
-static int _md_major = -1;
-static int _blkext_major = -1;
-static int _drbd_major = -1;
-static int _device_mapper_major = -1;
-static int _emcpower_major = -1;
-static int _power2_major = -1;
-
-int dm_major(void)
-{
- return _device_mapper_major;
-}
-
-int md_major(void)
-{
- return _md_major;
-}
-
-int blkext_major(void)
-{
- return _blkext_major;
-}
-
-int dev_subsystem_part_major(const struct device *dev)
-{
- dev_t primary_dev;
-
- if (MAJOR(dev->dev) == _md_major)
- return 1;
-
- if (MAJOR(dev->dev) == _drbd_major)
- return 1;
-
- if (MAJOR(dev->dev) == _emcpower_major)
- return 1;
-
- if (MAJOR(dev->dev) == _power2_major)
- return 1;
-
- if ((MAJOR(dev->dev) == _blkext_major) &&
- (get_primary_dev(dev, &primary_dev)) &&
- (MAJOR(primary_dev) == _md_major))
- return 1;
-
- return 0;
-}
-
-const char *dev_subsystem_name(const struct device *dev)
-{
- if (MAJOR(dev->dev) == _md_major)
- return "MD";
-
- if (MAJOR(dev->dev) == _drbd_major)
- return "DRBD";
-
- if (MAJOR(dev->dev) == _emcpower_major)
- return "EMCPOWER";
-
- if (MAJOR(dev->dev) == _power2_major)
- return "POWER2";
-
- if (MAJOR(dev->dev) == _blkext_major)
- return "BLKEXT";
-
- return "";
-}
-
-static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute__((unused)),
- struct device *dev)
+static int _passes_lvm_type_device_filter(struct dev_filter *f, struct device *dev)
{
+ struct dev_types *dt = (struct dev_types *) f->private;
const char *name = dev_name(dev);
int ret = 0;
uint64_t size;
/* Is this a recognised device type? */
- if (!_partitions[MAJOR(dev->dev)].max_partitions) {
+ if (!dt->dev_type_array[MAJOR(dev->dev)].max_partitions) {
log_debug_devs("%s: Skipping: Unrecognised LVM device type %"
PRIu64, name, (uint64_t) MAJOR(dev->dev));
return 0;
@@ -134,7 +51,7 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute__((un
goto out;
}
- if (is_partitioned_dev(dev)) {
+ if (dev_is_partitioned(dt, dev)) {
log_debug_devs("%s: Skipping: Partition table signature found",
name);
goto out;
@@ -149,179 +66,6 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f __attribute__((un
return ret;
}
-static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn)
-{
- char line[80];
- char proc_devices[PATH_MAX];
- FILE *pd = NULL;
- int i, j = 0;
- int line_maj = 0;
- int blocksection = 0;
- size_t dev_len = 0;
- const struct dm_config_value *cv;
- const char *name;
- char *nl;
-
- if (!*proc) {
- log_verbose("No proc filesystem found: using all block device "
- "types");
- for (i = 0; i < NUMBER_OF_MAJORS; i++)
- _partitions[i].max_partitions = 1;
- return 1;
- }
-
- /* All types unrecognised initially */
- memset(_partitions, 0, sizeof(_partitions));
-
- if (dm_snprintf(proc_devices, sizeof(proc_devices),
- "%s/devices", proc) < 0) {
- log_error("Failed to create /proc/devices string");
- return 0;
- }
-
- if (!(pd = fopen(proc_devices, "r"))) {
- log_sys_error("fopen", proc_devices);
- return 0;
- }
-
- while (fgets(line, sizeof(line), pd) != NULL) {
- i = 0;
- while (line[i] == ' ')
- i++;
-
- /* If it's not a number it may be name of section */
- line_maj = atoi(((char *) (line + i)));
-
- if (line_maj < 0 || line_maj >= NUMBER_OF_MAJORS) {
- /*
- * Device numbers shown in /proc/devices are actually direct
- * numbers passed to registering function, however the kernel
- * uses only 12 bits, so use just 12 bits for major.
- */
- if ((nl = strchr(line, '\n'))) *nl = '\0';
- log_warn("WARNING: /proc/devices line: %s, replacing major with %d.",
- line, line_maj & (NUMBER_OF_MAJORS - 1));
- line_maj &= (NUMBER_OF_MAJORS - 1);
- }
-
- if (!line_maj) {
- blocksection = (line[i] == 'B') ? 1 : 0;
- continue;
- }
-
- /* We only want block devices ... */
- if (!blocksection)
- continue;
-
- /* Find the start of the device major name */
- while (line[i] != ' ' && line[i] != '\0')
- i++;
- while (line[i] == ' ')
- i++;
-
- /* Look for md device */
- if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
- _md_major = line_maj;
-
- /* Look for blkext device */
- if (!strncmp("blkext", line + i, 6) && isspace(*(line + i + 6)))
- _blkext_major = line_maj;
-
- /* Look for drbd device */
- if (!strncmp("drbd", line + i, 4) && isspace(*(line + i + 4)))
- _drbd_major = line_maj;
-
- /* Look for EMC powerpath */
- if (!strncmp("emcpower", line + i, 8) && isspace(*(line + i + 8)))
- _emcpower_major = line_maj;
-
- if (!strncmp("power2", line + i, 6) && isspace(*(line + i + 6)))
- _power2_major = line_maj;
-
- /* Look for device-mapper device */
- /* FIXME Cope with multiple majors */
- if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
- _device_mapper_major = line_maj;
-
- /* Major is SCSI device */
- if (!strncmp("sd", line + i, 2) && isspace(*(line + i + 2)))
- _partitions[line_maj].flags |= PARTITION_SCSI_DEVICE;
-
- /* Go through the valid device names and if there is a
- match store max number of partitions */
- for (j = 0; _device_info[j].name[0]; j++) {
- dev_len = strlen(_device_info[j].name);
- if (dev_len <= strlen(line + i) &&
- !strncmp(_device_info[j].name, line + i, dev_len) &&
- (line_maj < NUMBER_OF_MAJORS)) {
- _partitions[line_maj].max_partitions =
- _device_info[j].max_partitions;
- break;
- }
- }
-
- if (!cn)
- continue;
-
- /* Check devices/types for local variations */
- for (cv = cn->v; cv; cv = cv->next) {
- if (cv->type != DM_CFG_STRING) {
- log_error("Expecting string in devices/types "
- "in config file");
- if (fclose(pd))
- log_sys_error("fclose", proc_devices);
- return 0;
- }
- dev_len = strlen(cv->v.str);
- name = cv->v.str;
- cv = cv->next;
- if (!cv || cv->type != DM_CFG_INT) {
- log_error("Max partition count missing for %s "
- "in devices/types in config file",
- name);
- if (fclose(pd))
- log_sys_error("fclose", proc_devices);
- return 0;
- }
- if (!cv->v.i) {
- log_error("Zero partition count invalid for "
- "%s in devices/types in config file",
- name);
- if (fclose(pd))
- log_sys_error("fclose", proc_devices);
- return 0;
- }
- if (dev_len <= strlen(line + i) &&
- !strncmp(name, line + i, dev_len) &&
- (line_maj < NUMBER_OF_MAJORS)) {
- _partitions[line_maj].max_partitions = cv->v.i;
- break;
- }
- }
- }
-
- if (fclose(pd))
- log_sys_error("fclose", proc_devices);
-
- return 1;
-}
-
-int max_partitions(int major)
-{
- if (major >= NUMBER_OF_MAJORS)
- return 0;
-
- return _partitions[major].max_partitions;
-}
-
-int major_is_scsi_device(int major)
-{
- if (major >= NUMBER_OF_MAJORS)
- return 0;
-
- return (_partitions[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
-}
-
static void _lvm_type_filter_destroy(struct dev_filter *f)
{
if (f->use_count)
@@ -330,8 +74,7 @@ static void _lvm_type_filter_destroy(struct dev_filter *f)
dm_free(f);
}
-struct dev_filter *lvm_type_filter_create(const char *proc,
- const struct dm_config_node *cn)
+struct dev_filter *lvm_type_filter_create(struct dev_types *dt)
{
struct dev_filter *f;
@@ -343,12 +86,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
f->passes_filter = _passes_lvm_type_device_filter;
f->destroy = _lvm_type_filter_destroy;
f->use_count = 0;
- f->private = NULL;
-
- if (!_scan_proc_dev(proc, cn)) {
- dm_free(f);
- return_NULL;
- }
+ f->private = dt;
return f;
}
diff --git a/lib/filters/filter.h b/lib/filters/filter.h
index cdbcfe8..e0a0c6a 100644
--- a/lib/filters/filter.h
+++ b/lib/filters/filter.h
@@ -16,30 +16,9 @@
#ifndef _LVM_FILTER_H
#define _LVM_FILTER_H
-#include "config.h"
+#include "dev-cache.h"
+#include "dev-type.h"
-#include <sys/stat.h>
-
-#ifdef linux
-# define MAJOR(dev) ((dev & 0xfff00) >> 8)
-# define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
-# define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
-#else
-# define MAJOR(x) major((x))
-# define MINOR(x) minor((x))
-# define MKDEV(x,y) makedev((x),(y))
-#endif
-
-struct dev_filter *lvm_type_filter_create(const char *proc,
- const struct dm_config_node *cn);
-
-int dm_major(void);
-int md_major(void);
-int blkext_major(void);
-int max_partitions(int major);
-int major_is_scsi_device(int major);
-
-int dev_subsystem_part_major(const struct device *dev);
-const char *dev_subsystem_name(const struct device *dev);
+struct dev_filter *lvm_type_filter_create(struct dev_types *dt);
#endif
diff --git a/lib/format1/disk-rep.c b/lib/format1/disk-rep.c
index 19776e0..bbce317 100644
--- a/lib/format1/disk-rep.c
+++ b/lib/format1/disk-rep.c
@@ -18,6 +18,7 @@
#include "xlate.h"
#include "filter.h"
#include "lvmcache.h"
+#include "metadata-exported.h"
#include <fcntl.h>
@@ -426,7 +427,7 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
return dl;
}
-static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
+static void _add_pv_to_list(struct cmd_context *cmd, struct dm_list *head, struct disk_list *data)
{
struct pv_disk *pvd;
struct disk_list *diskl;
@@ -435,14 +436,14 @@ static void _add_pv_to_list(struct dm_list *head, struct disk_list *data)
pvd = &diskl->pvd;
if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid,
sizeof(pvd->pv_uuid))) {
- if (!dev_subsystem_part_major(data->dev)) {
+ if (!dev_subsystem_part_major(cmd->dev_types, data->dev)) {
log_very_verbose("Ignoring duplicate PV %s on "
"%s", pvd->pv_uuid,
dev_name(data->dev));
return;
}
log_very_verbose("Duplicate PV %s - using %s %s",
- pvd->pv_uuid, dev_subsystem_name(data->dev),
+ pvd->pv_uuid, dev_subsystem_name(cmd->dev_types, data->dev),
dev_name(data->dev));
dm_list_del(&diskl->list);
break;
@@ -469,7 +470,7 @@ static int _read_pv_in_vg(struct lvmcache_info *info, void *baton)
!(b->data = read_disk(lvmcache_fmt(info), lvmcache_device(info), b->mem, b->vg_name)))
return 0; /* stop here */
- _add_pv_to_list(b->head, b->data);
+ _add_pv_to_list(lvmcache_fmt(info)->cmd, b->head, b->data);
return 1;
}
@@ -519,7 +520,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
/* Otherwise do a complete scan */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
if ((baton.data = read_disk(fmt, dev, mem, vg_name))) {
- _add_pv_to_list(head, baton.data);
+ _add_pv_to_list(fmt->cmd, head, baton.data);
}
}
dev_iter_destroy(iter);
diff --git a/lib/format_pool/disk_rep.c b/lib/format_pool/disk_rep.c
index 899a48d..f696463 100644
--- a/lib/format_pool/disk_rep.c
+++ b/lib/format_pool/disk_rep.c
@@ -20,6 +20,7 @@
#include "filter.h"
#include "xlate.h"
#include "disk_rep.h"
+#include "toolcontext.h"
#include <assert.h>
@@ -52,7 +53,7 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
return 1;
}
-static void _add_pl_to_list(struct dm_list *head, struct pool_list *data)
+static void _add_pl_to_list(struct cmd_context *cmd, struct dm_list *head, struct pool_list *data)
{
struct pool_list *pl;
@@ -62,14 +63,14 @@ static void _add_pl_to_list(struct dm_list *head, struct pool_list *data)
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
- if (!dev_subsystem_part_major(data->dev)) {
+ if (!dev_subsystem_part_major(cmd->dev_types, data->dev)) {
log_very_verbose("Ignoring duplicate PV %s on "
"%s", uuid,
dev_name(data->dev));
return;
}
log_very_verbose("Duplicate PV %s - using %s %s",
- uuid, dev_subsystem_name(data->dev),
+ uuid, dev_subsystem_name(cmd->dev_types, data->dev),
dev_name(data->dev));
dm_list_del(&pl->list);
break;
@@ -288,7 +289,7 @@ static int _read_pool_pv(struct lvmcache_info *info, void *baton)
if (b->sp_count != b->pl->pd.pl_subpools)
return 0;
- _add_pl_to_list(b->head, b->pl);
+ _add_pl_to_list(lvmcache_fmt(info)->cmd, b->head, b->pl);
if (b->sp_count > b->pl->pd.pl_sp_id && b->sp_devs[b->pl->pd.pl_sp_id] == 0)
b->sp_devs[b->pl->pd.pl_sp_id] = b->pl->pd.pl_sp_devs;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 4e52bd4..c65144c 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -84,7 +84,7 @@ unsigned long set_pe_align(struct physical_volume *pv, unsigned long data_alignm
* Align to stripe-width of underlying md device if present
*/
if (find_config_tree_bool(pv->fmt->cmd, devices_md_chunk_alignment_CFG)) {
- temp_pe_align = dev_md_stripe_width(pv->dev);
+ temp_pe_align = dev_md_stripe_width(pv->fmt->cmd->dev_types, pv->dev);
if (_alignment_overrides_default(temp_pe_align, default_pe_align))
pv->pe_align = temp_pe_align;
}
@@ -97,11 +97,11 @@ unsigned long set_pe_align(struct physical_volume *pv, unsigned long data_alignm
* (e.g. MD's stripe width)
*/
if (find_config_tree_bool(pv->fmt->cmd, devices_data_alignment_detection_CFG)) {
- temp_pe_align = dev_minimum_io_size(pv->dev);
+ temp_pe_align = dev_minimum_io_size(pv->fmt->cmd->dev_types, pv->dev);
if (_alignment_overrides_default(temp_pe_align, default_pe_align))
pv->pe_align = temp_pe_align;
- temp_pe_align = dev_optimal_io_size(pv->dev);
+ temp_pe_align = dev_optimal_io_size(pv->fmt->cmd->dev_types, pv->dev);
if (_alignment_overrides_default(temp_pe_align, default_pe_align))
pv->pe_align = temp_pe_align;
}
@@ -129,7 +129,7 @@ unsigned long set_pe_align_offset(struct physical_volume *pv,
goto out;
if (find_config_tree_bool(pv->fmt->cmd, devices_data_alignment_offset_detection_CFG)) {
- int align_offset = dev_alignment_offset(pv->dev);
+ int align_offset = dev_alignment_offset(pv->fmt->cmd->dev_types, pv->dev);
/* must handle a -1 alignment_offset; means dev is misaligned */
if (align_offset < 0)
align_offset = 0;
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index ae453ae..dea49f8 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -216,8 +216,8 @@ int discard_pv_segment(struct pv_segment *peg, uint32_t discard_area_reduction)
return 1;
}
- if (!dev_discard_max_bytes(peg->pv->dev) ||
- !dev_discard_granularity(peg->pv->dev))
+ if (!dev_discard_max_bytes(peg->pv->fmt->cmd->dev_types, peg->pv->dev) ||
+ !dev_discard_granularity(peg->pv->fmt->cmd->dev_types, peg->pv->dev))
return 1;
discard_offset_sectors = (peg->pe + peg->lvseg->area_len - discard_area_reduction) *
10 years, 9 months
master - refactor: move lib/device/device.c -> lib/device/dev-type.c
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1778d34cefdfe3...
Commit: 1778d34cefdfe30055ac4a7e82438e4484004491
Parent: 22b0f3573e222f7471c4e279e5703f2933cf6e9a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 12 11:53:55 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 12 11:54:37 2013 +0200
refactor: move lib/device/device.c -> lib/device/dev-type.c
---
lib/Makefile.in | 2 +-
lib/device/dev-type.c | 493 +++++++++++++++++++++++++++++++++++++++++++++++++
lib/device/device.c | 493 -------------------------------------------------
3 files changed, 494 insertions(+), 494 deletions(-)
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 82f700b..d789839 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -55,8 +55,8 @@ SOURCES =\
device/dev-io.c \
device/dev-md.c \
device/dev-swap.c \
+ device/dev-type.c \
device/dev-luks.c \
- device/device.c \
display/display.c \
error/errseg.c \
unknown/unknown.c \
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c
new file mode 100644
index 0000000..52eb4a6
--- /dev/null
+++ b/lib/device/dev-type.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lib.h"
+#include "lvm-types.h"
+#include "device.h"
+#include "metadata.h"
+#include "filter.h"
+#include "xlate.h"
+
+#include <libgen.h> /* dirname, basename */
+
+/* See linux/genhd.h and fs/partitions/msdos */
+
+#define PART_MAGIC 0xAA55
+#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
+#define PART_OFFSET UINT64_C(0x1BE)
+
+struct partition {
+ uint8_t boot_ind;
+ uint8_t head;
+ uint8_t sector;
+ uint8_t cyl;
+ uint8_t sys_ind; /* partition type */
+ uint8_t end_head;
+ uint8_t end_sector;
+ uint8_t end_cyl;
+ uint32_t start_sect;
+ uint32_t nr_sects;
+} __attribute__((packed));
+
+static int _is_partitionable(struct device *dev)
+{
+ int parts = max_partitions(MAJOR(dev->dev));
+
+ /* All MD devices are partitionable via blkext (as of 2.6.28) */
+ if (MAJOR(dev->dev) == md_major())
+ return 1;
+
+ if ((parts <= 1) || (MINOR(dev->dev) % parts))
+ return 0;
+
+ return 1;
+}
+
+static int _has_partition_table(struct device *dev)
+{
+ int ret = 0;
+ unsigned p;
+ struct {
+ uint8_t skip[PART_OFFSET];
+ struct partition part[4];
+ uint16_t magic;
+ } __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
+
+ if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
+ return_0;
+
+ /* FIXME Check for other types of partition table too */
+
+ /* Check for msdos partition table */
+ if (buf.magic == xlate16(PART_MAGIC)) {
+ for (p = 0; p < 4; ++p) {
+ /* Table is invalid if boot indicator not 0 or 0x80 */
+ if (buf.part[p].boot_ind & 0x7f) {
+ ret = 0;
+ break;
+ }
+ /* Must have at least one non-empty partition */
+ if (buf.part[p].nr_sects)
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+int is_partitioned_dev(struct device *dev)
+{
+ if (!_is_partitionable(dev))
+ return 0;
+
+ return _has_partition_table(dev);
+}
+
+#if 0
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/genhd.h>
+
+int _get_partition_type(struct dev_filter *filter, struct device *d);
+
+#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
+
+int is_extended_partition(struct device *d)
+{
+ return (MINOR_PART(d) > 4) ? 1 : 0;
+}
+
+struct device *dev_primary(struct dev_mgr *dm, struct device *d)
+{
+ struct device *ret;
+
+ ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
+ /* FIXME: Needs replacing with a 'refresh' */
+ if (!ret) {
+ init_dev_scan(dm);
+ ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
+ }
+
+ return ret;
+
+}
+
+int partition_type_is_lvm(struct dev_mgr *dm, struct device *d)
+{
+ int pt;
+
+ pt = _get_partition_type(dm, d);
+
+ if (!pt) {
+ if (is_whole_disk(dm, d))
+ /* FIXME: Overloaded pt=0 in error cases */
+ return 1;
+ else {
+ log_error
+ ("%s: missing partition table "
+ "on partitioned device", d->name);
+ return 0;
+ }
+ }
+
+ if (is_whole_disk(dm, d)) {
+ log_error("%s: looks to possess partition table", d->name);
+ return 0;
+ }
+
+ /* check part type */
+ if (pt != LVM_PARTITION && pt != LVM_NEW_PARTITION) {
+ log_error("%s: invalid partition type 0x%x "
+ "(must be 0x%x)", d->name, pt, LVM_NEW_PARTITION);
+ return 0;
+ }
+
+ if (pt == LVM_PARTITION) {
+ log_error
+ ("%s: old LVM partition type found - please change to 0x%x",
+ d->name, LVM_NEW_PARTITION);
+ return 0;
+ }
+
+ return 1;
+}
+
+int _get_partition_type(struct dev_mgr *dm, struct device *d)
+{
+ int pv_handle = -1;
+ struct device *primary;
+ ssize_t read_ret;
+ ssize_t bytes_read = 0;
+ char *buffer;
+ unsigned short *s_buffer;
+ struct partition *part;
+ loff_t offset = 0;
+ loff_t extended_offset = 0;
+ int part_sought;
+ int part_found = 0;
+ int first_partition = 1;
+ int extended_partition = 0;
+ int p;
+
+ if (!(primary = dev_primary(dm, d))) {
+ log_error
+ ("Failed to find main device containing partition %s",
+ d->name);
+ return 0;
+ }
+
+ if (!(buffer = dm_malloc(SECTOR_SIZE))) {
+ log_error("Failed to allocate partition table buffer");
+ return 0;
+ }
+
+ /* Get partition table */
+ if ((pv_handle = open(primary->name, O_RDONLY)) < 0) {
+ log_error("%s: open failed: %s", primary->name,
+ strerror(errno));
+ return 0;
+ }
+
+ s_buffer = (unsigned short *) buffer;
+ part = (struct partition *) (buffer + 0x1be);
+ part_sought = MINOR_PART(dm, d);
+
+ do {
+ bytes_read = 0;
+
+ if (llseek(pv_handle, offset * SECTOR_SIZE, SEEK_SET) == -1) {
+ log_error("%s: llseek failed: %s",
+ primary->name, strerror(errno));
+ return 0;
+ }
+
+ while ((bytes_read < SECTOR_SIZE) &&
+ (read_ret =
+ read(pv_handle, buffer + bytes_read,
+ SECTOR_SIZE - bytes_read)) != -1)
+ bytes_read += read_ret;
+
+ if (read_ret == -1) {
+ log_error("%s: read failed: %s", primary->name,
+ strerror(errno));
+ return 0;
+ }
+
+ if (s_buffer[255] == 0xAA55) {
+ if (is_whole_disk(dm, d))
+ return -1;
+ } else
+ return 0;
+
+ extended_partition = 0;
+
+ /* Loop through primary partitions */
+ for (p = 0; p < 4; p++) {
+ if (part[p].sys_ind == DOS_EXTENDED_PARTITION ||
+ part[p].sys_ind == LINUX_EXTENDED_PARTITION
+ || part[p].sys_ind == WIN98_EXTENDED_PARTITION) {
+ extended_partition = 1;
+ offset = extended_offset + part[p].start_sect;
+ if (extended_offset == 0)
+ extended_offset = part[p].start_sect;
+ if (first_partition == 1)
+ part_found++;
+ } else if (first_partition == 1) {
+ if (p == part_sought) {
+ if (part[p].sys_ind == 0) {
+ /* missing primary? */
+ return 0;
+ }
+ } else
+ part_found++;
+ } else if (!part[p].sys_ind)
+ part_found++;
+
+ if (part_sought == part_found)
+ return part[p].sys_ind;
+
+ }
+ first_partition = 0;
+ }
+ while (extended_partition == 1);
+
+ return 0;
+}
+#endif
+
+#ifdef linux
+
+int get_primary_dev(const struct device *dev, dev_t *result)
+{
+ const char *sysfs_dir = dm_sysfs_dir();
+ char path[PATH_MAX+1];
+ char temp_path[PATH_MAX+1];
+ char buffer[64];
+ struct stat info;
+ FILE *fp;
+ uint32_t pri_maj, pri_min;
+ int size, ret = 0;
+
+ /* check if dev is a partition */
+ if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
+ sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
+ log_error("dm_snprintf partition failed");
+ return ret;
+ }
+
+ if (stat(path, &info) == -1) {
+ if (errno != ENOENT)
+ log_sys_error("stat", path);
+ return ret;
+ }
+
+ /*
+ * extract parent's path from the partition's symlink, e.g.:
+ * - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
+ * - dirname ../../block/md0/md0p1 = ../../block/md0
+ * - basename ../../block/md0/md0 = md0
+ * Parent's 'dev' sysfs attribute = /sys/block/md0/dev
+ */
+ if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
+ log_sys_error("readlink", path);
+ return ret;
+ }
+
+ temp_path[size] = '\0';
+
+ if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
+ sysfs_dir, basename(dirname(temp_path))) < 0) {
+ log_error("dm_snprintf dev failed");
+ return ret;
+ }
+
+ /* finally, parse 'dev' attribute and create corresponding dev_t */
+ if (stat(path, &info) == -1) {
+ if (errno == ENOENT)
+ log_error("sysfs file %s does not exist", path);
+ else
+ log_sys_error("stat", path);
+ return ret;
+ }
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ log_sys_error("fopen", path);
+ return ret;
+ }
+
+ if (!fgets(buffer, sizeof(buffer), fp)) {
+ log_sys_error("fgets", path);
+ goto out;
+ }
+
+ if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
+ log_error("sysfs file %s not in expected MAJ:MIN format: %s",
+ path, buffer);
+ goto out;
+ }
+ *result = MKDEV((dev_t)pri_maj, pri_min);
+ ret = 1;
+
+out:
+ if (fclose(fp))
+ log_sys_error("fclose", path);
+
+ return ret;
+}
+
+static unsigned long _dev_topology_attribute(const char *attribute, struct device *dev)
+{
+ const char *sysfs_dir = dm_sysfs_dir();
+ static const char sysfs_fmt_str[] = "%s/dev/block/%d:%d/%s";
+ char path[PATH_MAX+1], buffer[64];
+ FILE *fp;
+ struct stat info;
+ dev_t uninitialized_var(primary);
+ unsigned long result = 0UL;
+
+ if (!attribute || !*attribute)
+ return_0;
+
+ if (!sysfs_dir || !*sysfs_dir)
+ return_0;
+
+ if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
+ (int)MAJOR(dev->dev), (int)MINOR(dev->dev),
+ attribute) < 0) {
+ log_error("dm_snprintf %s failed", attribute);
+ return 0;
+ }
+
+ /*
+ * check if the desired sysfs attribute exists
+ * - if not: either the kernel doesn't have topology support
+ * or the device could be a partition
+ */
+ if (stat(path, &info) == -1) {
+ if (errno != ENOENT) {
+ log_sys_error("stat", path);
+ return 0;
+ }
+ if (!get_primary_dev(dev, &primary))
+ return 0;
+
+ /* get attribute from partition's primary device */
+ if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
+ (int)MAJOR(primary), (int)MINOR(primary),
+ attribute) < 0) {
+ log_error("primary dm_snprintf %s failed", attribute);
+ return 0;
+ }
+ if (stat(path, &info) == -1) {
+ if (errno != ENOENT)
+ log_sys_error("stat", path);
+ 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", &result) != 1) {
+ log_error("sysfs file %s not in expected format: %s", path,
+ buffer);
+ goto out;
+ }
+
+ log_very_verbose("Device %s %s is %lu bytes.",
+ dev_name(dev), attribute, result);
+
+out:
+ if (fclose(fp))
+ log_sys_error("fclose", path);
+
+ return result >> SECTOR_SHIFT;
+}
+
+unsigned long dev_alignment_offset(struct device *dev)
+{
+ return _dev_topology_attribute("alignment_offset", dev);
+}
+
+unsigned long dev_minimum_io_size(struct device *dev)
+{
+ return _dev_topology_attribute("queue/minimum_io_size", dev);
+}
+
+unsigned long dev_optimal_io_size(struct device *dev)
+{
+ return _dev_topology_attribute("queue/optimal_io_size", dev);
+}
+
+unsigned long dev_discard_max_bytes(struct device *dev)
+{
+ return _dev_topology_attribute("queue/discard_max_bytes", dev);
+}
+
+unsigned long dev_discard_granularity(struct device *dev)
+{
+ return _dev_topology_attribute("queue/discard_granularity", dev);
+}
+
+#else
+
+int get_primary_dev(struct device *dev, dev_t *result)
+{
+ return 0;
+}
+
+unsigned long dev_alignment_offset(struct device *dev)
+{
+ return 0UL;
+}
+
+unsigned long dev_minimum_io_size(struct device *dev)
+{
+ return 0UL;
+}
+
+unsigned long dev_optimal_io_size(struct device *dev)
+{
+ return 0UL;
+}
+
+unsigned long dev_discard_max_bytes(struct device *dev)
+{
+ return 0UL;
+}
+
+unsigned long dev_discard_granularity(struct device *dev)
+{
+ return 0UL;
+}
+
+#endif
diff --git a/lib/device/device.c b/lib/device/device.c
deleted file mode 100644
index 52eb4a6..0000000
--- a/lib/device/device.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
- *
- * This file is part of LVM2.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License v.2.1.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "lib.h"
-#include "lvm-types.h"
-#include "device.h"
-#include "metadata.h"
-#include "filter.h"
-#include "xlate.h"
-
-#include <libgen.h> /* dirname, basename */
-
-/* See linux/genhd.h and fs/partitions/msdos */
-
-#define PART_MAGIC 0xAA55
-#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
-#define PART_OFFSET UINT64_C(0x1BE)
-
-struct partition {
- uint8_t boot_ind;
- uint8_t head;
- uint8_t sector;
- uint8_t cyl;
- uint8_t sys_ind; /* partition type */
- uint8_t end_head;
- uint8_t end_sector;
- uint8_t end_cyl;
- uint32_t start_sect;
- uint32_t nr_sects;
-} __attribute__((packed));
-
-static int _is_partitionable(struct device *dev)
-{
- int parts = max_partitions(MAJOR(dev->dev));
-
- /* All MD devices are partitionable via blkext (as of 2.6.28) */
- if (MAJOR(dev->dev) == md_major())
- return 1;
-
- if ((parts <= 1) || (MINOR(dev->dev) % parts))
- return 0;
-
- return 1;
-}
-
-static int _has_partition_table(struct device *dev)
-{
- int ret = 0;
- unsigned p;
- struct {
- uint8_t skip[PART_OFFSET];
- struct partition part[4];
- uint16_t magic;
- } __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
-
- if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
- return_0;
-
- /* FIXME Check for other types of partition table too */
-
- /* Check for msdos partition table */
- if (buf.magic == xlate16(PART_MAGIC)) {
- for (p = 0; p < 4; ++p) {
- /* Table is invalid if boot indicator not 0 or 0x80 */
- if (buf.part[p].boot_ind & 0x7f) {
- ret = 0;
- break;
- }
- /* Must have at least one non-empty partition */
- if (buf.part[p].nr_sects)
- ret = 1;
- }
- }
-
- return ret;
-}
-
-int is_partitioned_dev(struct device *dev)
-{
- if (!_is_partitionable(dev))
- return 0;
-
- return _has_partition_table(dev);
-}
-
-#if 0
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/genhd.h>
-
-int _get_partition_type(struct dev_filter *filter, struct device *d);
-
-#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
-
-int is_extended_partition(struct device *d)
-{
- return (MINOR_PART(d) > 4) ? 1 : 0;
-}
-
-struct device *dev_primary(struct dev_mgr *dm, struct device *d)
-{
- struct device *ret;
-
- ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
- /* FIXME: Needs replacing with a 'refresh' */
- if (!ret) {
- init_dev_scan(dm);
- ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
- }
-
- return ret;
-
-}
-
-int partition_type_is_lvm(struct dev_mgr *dm, struct device *d)
-{
- int pt;
-
- pt = _get_partition_type(dm, d);
-
- if (!pt) {
- if (is_whole_disk(dm, d))
- /* FIXME: Overloaded pt=0 in error cases */
- return 1;
- else {
- log_error
- ("%s: missing partition table "
- "on partitioned device", d->name);
- return 0;
- }
- }
-
- if (is_whole_disk(dm, d)) {
- log_error("%s: looks to possess partition table", d->name);
- return 0;
- }
-
- /* check part type */
- if (pt != LVM_PARTITION && pt != LVM_NEW_PARTITION) {
- log_error("%s: invalid partition type 0x%x "
- "(must be 0x%x)", d->name, pt, LVM_NEW_PARTITION);
- return 0;
- }
-
- if (pt == LVM_PARTITION) {
- log_error
- ("%s: old LVM partition type found - please change to 0x%x",
- d->name, LVM_NEW_PARTITION);
- return 0;
- }
-
- return 1;
-}
-
-int _get_partition_type(struct dev_mgr *dm, struct device *d)
-{
- int pv_handle = -1;
- struct device *primary;
- ssize_t read_ret;
- ssize_t bytes_read = 0;
- char *buffer;
- unsigned short *s_buffer;
- struct partition *part;
- loff_t offset = 0;
- loff_t extended_offset = 0;
- int part_sought;
- int part_found = 0;
- int first_partition = 1;
- int extended_partition = 0;
- int p;
-
- if (!(primary = dev_primary(dm, d))) {
- log_error
- ("Failed to find main device containing partition %s",
- d->name);
- return 0;
- }
-
- if (!(buffer = dm_malloc(SECTOR_SIZE))) {
- log_error("Failed to allocate partition table buffer");
- return 0;
- }
-
- /* Get partition table */
- if ((pv_handle = open(primary->name, O_RDONLY)) < 0) {
- log_error("%s: open failed: %s", primary->name,
- strerror(errno));
- return 0;
- }
-
- s_buffer = (unsigned short *) buffer;
- part = (struct partition *) (buffer + 0x1be);
- part_sought = MINOR_PART(dm, d);
-
- do {
- bytes_read = 0;
-
- if (llseek(pv_handle, offset * SECTOR_SIZE, SEEK_SET) == -1) {
- log_error("%s: llseek failed: %s",
- primary->name, strerror(errno));
- return 0;
- }
-
- while ((bytes_read < SECTOR_SIZE) &&
- (read_ret =
- read(pv_handle, buffer + bytes_read,
- SECTOR_SIZE - bytes_read)) != -1)
- bytes_read += read_ret;
-
- if (read_ret == -1) {
- log_error("%s: read failed: %s", primary->name,
- strerror(errno));
- return 0;
- }
-
- if (s_buffer[255] == 0xAA55) {
- if (is_whole_disk(dm, d))
- return -1;
- } else
- return 0;
-
- extended_partition = 0;
-
- /* Loop through primary partitions */
- for (p = 0; p < 4; p++) {
- if (part[p].sys_ind == DOS_EXTENDED_PARTITION ||
- part[p].sys_ind == LINUX_EXTENDED_PARTITION
- || part[p].sys_ind == WIN98_EXTENDED_PARTITION) {
- extended_partition = 1;
- offset = extended_offset + part[p].start_sect;
- if (extended_offset == 0)
- extended_offset = part[p].start_sect;
- if (first_partition == 1)
- part_found++;
- } else if (first_partition == 1) {
- if (p == part_sought) {
- if (part[p].sys_ind == 0) {
- /* missing primary? */
- return 0;
- }
- } else
- part_found++;
- } else if (!part[p].sys_ind)
- part_found++;
-
- if (part_sought == part_found)
- return part[p].sys_ind;
-
- }
- first_partition = 0;
- }
- while (extended_partition == 1);
-
- return 0;
-}
-#endif
-
-#ifdef linux
-
-int get_primary_dev(const struct device *dev, dev_t *result)
-{
- const char *sysfs_dir = dm_sysfs_dir();
- char path[PATH_MAX+1];
- char temp_path[PATH_MAX+1];
- char buffer[64];
- struct stat info;
- FILE *fp;
- uint32_t pri_maj, pri_min;
- int size, ret = 0;
-
- /* check if dev is a partition */
- if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
- sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
- log_error("dm_snprintf partition failed");
- return ret;
- }
-
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
- return ret;
- }
-
- /*
- * extract parent's path from the partition's symlink, e.g.:
- * - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
- * - dirname ../../block/md0/md0p1 = ../../block/md0
- * - basename ../../block/md0/md0 = md0
- * Parent's 'dev' sysfs attribute = /sys/block/md0/dev
- */
- if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
- log_sys_error("readlink", path);
- return ret;
- }
-
- temp_path[size] = '\0';
-
- if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
- sysfs_dir, basename(dirname(temp_path))) < 0) {
- log_error("dm_snprintf dev failed");
- return ret;
- }
-
- /* finally, parse 'dev' attribute and create corresponding dev_t */
- if (stat(path, &info) == -1) {
- if (errno == ENOENT)
- log_error("sysfs file %s does not exist", path);
- else
- log_sys_error("stat", path);
- return ret;
- }
-
- fp = fopen(path, "r");
- if (!fp) {
- log_sys_error("fopen", path);
- return ret;
- }
-
- if (!fgets(buffer, sizeof(buffer), fp)) {
- log_sys_error("fgets", path);
- goto out;
- }
-
- if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
- log_error("sysfs file %s not in expected MAJ:MIN format: %s",
- path, buffer);
- goto out;
- }
- *result = MKDEV((dev_t)pri_maj, pri_min);
- ret = 1;
-
-out:
- if (fclose(fp))
- log_sys_error("fclose", path);
-
- return ret;
-}
-
-static unsigned long _dev_topology_attribute(const char *attribute, struct device *dev)
-{
- const char *sysfs_dir = dm_sysfs_dir();
- static const char sysfs_fmt_str[] = "%s/dev/block/%d:%d/%s";
- char path[PATH_MAX+1], buffer[64];
- FILE *fp;
- struct stat info;
- dev_t uninitialized_var(primary);
- unsigned long result = 0UL;
-
- if (!attribute || !*attribute)
- return_0;
-
- if (!sysfs_dir || !*sysfs_dir)
- return_0;
-
- if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
- (int)MAJOR(dev->dev), (int)MINOR(dev->dev),
- attribute) < 0) {
- log_error("dm_snprintf %s failed", attribute);
- return 0;
- }
-
- /*
- * check if the desired sysfs attribute exists
- * - if not: either the kernel doesn't have topology support
- * or the device could be a partition
- */
- if (stat(path, &info) == -1) {
- if (errno != ENOENT) {
- log_sys_error("stat", path);
- return 0;
- }
- if (!get_primary_dev(dev, &primary))
- return 0;
-
- /* get attribute from partition's primary device */
- if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
- (int)MAJOR(primary), (int)MINOR(primary),
- attribute) < 0) {
- log_error("primary dm_snprintf %s failed", attribute);
- return 0;
- }
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
- 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", &result) != 1) {
- log_error("sysfs file %s not in expected format: %s", path,
- buffer);
- goto out;
- }
-
- log_very_verbose("Device %s %s is %lu bytes.",
- dev_name(dev), attribute, result);
-
-out:
- if (fclose(fp))
- log_sys_error("fclose", path);
-
- return result >> SECTOR_SHIFT;
-}
-
-unsigned long dev_alignment_offset(struct device *dev)
-{
- return _dev_topology_attribute("alignment_offset", dev);
-}
-
-unsigned long dev_minimum_io_size(struct device *dev)
-{
- return _dev_topology_attribute("queue/minimum_io_size", dev);
-}
-
-unsigned long dev_optimal_io_size(struct device *dev)
-{
- return _dev_topology_attribute("queue/optimal_io_size", dev);
-}
-
-unsigned long dev_discard_max_bytes(struct device *dev)
-{
- return _dev_topology_attribute("queue/discard_max_bytes", dev);
-}
-
-unsigned long dev_discard_granularity(struct device *dev)
-{
- return _dev_topology_attribute("queue/discard_granularity", dev);
-}
-
-#else
-
-int get_primary_dev(struct device *dev, dev_t *result)
-{
- return 0;
-}
-
-unsigned long dev_alignment_offset(struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_minimum_io_size(struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_optimal_io_size(struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_discard_max_bytes(struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_discard_granularity(struct device *dev)
-{
- return 0UL;
-}
-
-#endif
10 years, 9 months
master - refactor: move lib/filters/device-types.h -> lib/device/device-types.h
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=22b0f3573e222f...
Commit: 22b0f3573e222f7471c4e279e5703f2933cf6e9a
Parent: 657abb08e0e509e084d23d8b4dcf6248362cccd4
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 12 11:46:07 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 12 11:54:36 2013 +0200
refactor: move lib/filters/device-types.h -> lib/device/device-types.h
---
lib/device/device-types.h | 63 ++++++++++++++++++++++++++++++++++++++++++++
lib/filters/device-types.h | 63 --------------------------------------------
lib/filters/filter.c | 2 +-
3 files changed, 64 insertions(+), 64 deletions(-)
diff --git a/lib/device/device-types.h b/lib/device/device-types.h
new file mode 100644
index 0000000..2e49f7f
--- /dev/null
+++ b/lib/device/device-types.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+typedef struct {
+ const char name[15];
+ const int8_t max_partitions;
+} device_info_t;
+
+/*
+ * Devices are only checked for partition tables if their minor number
+ * is a multiple of the number corresponding to their type below
+ * i.e. this gives the granularity of whole-device minor numbers.
+ * Use 1 if the device is not partitionable.
+ *
+ * The list can be supplemented with devices/types in the config file.
+ */
+static const device_info_t _device_info[] = {
+ {"ide", 64}, /* IDE disk */
+ {"sd", 16}, /* SCSI disk */
+ {"md", 1}, /* Multiple Disk driver (SoftRAID) */
+ {"mdp", 1}, /* Partitionable MD */
+ {"loop", 1}, /* Loop device */
+ {"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
+ {"dac960", 8}, /* DAC960 */
+ {"nbd", 16}, /* Network Block Device */
+ {"ida", 16}, /* Compaq SMART2 */
+ {"cciss", 16}, /* Compaq CCISS array */
+ {"ubd", 16}, /* User-mode virtual block device */
+ {"ataraid", 16}, /* ATA Raid */
+ {"drbd", 16}, /* Distributed Replicated Block Device */
+ {"emcpower", 16}, /* EMC Powerpath */
+ {"power2", 16}, /* EMC Powerpath */
+ {"i2o_block", 16}, /* i2o Block Disk */
+ {"iseries/vd", 8}, /* iSeries disks */
+ {"gnbd", 1}, /* Network block device */
+ {"ramdisk", 1}, /* RAM disk */
+ {"aoe", 16}, /* ATA over Ethernet */
+ {"device-mapper", 1}, /* Other mapped devices */
+ {"xvd", 16}, /* Xen virtual block device */
+ {"vdisk", 8}, /* SUN's LDOM virtual block device */
+ {"ps3disk", 16}, /* PlayStation 3 internal disk */
+ {"virtblk", 8}, /* VirtIO disk */
+ {"mmc", 16}, /* MMC block device */
+ {"blkext", 1}, /* Extended device partitions */
+ {"fio", 16}, /* Fusion */
+ {"mtip32xx", 16}, /* Micron PCIe SSDs */
+ {"vtms", 16}, /* Violin Memory */
+ {"skd", 16}, /* STEC */
+ {"scm", 8}, /* Storage Class Memory (IBM S/390) */
+ {"", 0}
+};
diff --git a/lib/filters/device-types.h b/lib/filters/device-types.h
deleted file mode 100644
index 2e49f7f..0000000
--- a/lib/filters/device-types.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
- *
- * This file is part of LVM2.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License v.2.1.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-typedef struct {
- const char name[15];
- const int8_t max_partitions;
-} device_info_t;
-
-/*
- * Devices are only checked for partition tables if their minor number
- * is a multiple of the number corresponding to their type below
- * i.e. this gives the granularity of whole-device minor numbers.
- * Use 1 if the device is not partitionable.
- *
- * The list can be supplemented with devices/types in the config file.
- */
-static const device_info_t _device_info[] = {
- {"ide", 64}, /* IDE disk */
- {"sd", 16}, /* SCSI disk */
- {"md", 1}, /* Multiple Disk driver (SoftRAID) */
- {"mdp", 1}, /* Partitionable MD */
- {"loop", 1}, /* Loop device */
- {"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
- {"dac960", 8}, /* DAC960 */
- {"nbd", 16}, /* Network Block Device */
- {"ida", 16}, /* Compaq SMART2 */
- {"cciss", 16}, /* Compaq CCISS array */
- {"ubd", 16}, /* User-mode virtual block device */
- {"ataraid", 16}, /* ATA Raid */
- {"drbd", 16}, /* Distributed Replicated Block Device */
- {"emcpower", 16}, /* EMC Powerpath */
- {"power2", 16}, /* EMC Powerpath */
- {"i2o_block", 16}, /* i2o Block Disk */
- {"iseries/vd", 8}, /* iSeries disks */
- {"gnbd", 1}, /* Network block device */
- {"ramdisk", 1}, /* RAM disk */
- {"aoe", 16}, /* ATA over Ethernet */
- {"device-mapper", 1}, /* Other mapped devices */
- {"xvd", 16}, /* Xen virtual block device */
- {"vdisk", 8}, /* SUN's LDOM virtual block device */
- {"ps3disk", 16}, /* PlayStation 3 internal disk */
- {"virtblk", 8}, /* VirtIO disk */
- {"mmc", 16}, /* MMC block device */
- {"blkext", 1}, /* Extended device partitions */
- {"fio", 16}, /* Fusion */
- {"mtip32xx", 16}, /* Micron PCIe SSDs */
- {"vtms", 16}, /* Violin Memory */
- {"skd", 16}, /* STEC */
- {"scm", 8}, /* Storage Class Memory (IBM S/390) */
- {"", 0}
-};
diff --git a/lib/filters/filter.c b/lib/filters/filter.c
index d3fdd6e..a86b398 100644
--- a/lib/filters/filter.c
+++ b/lib/filters/filter.c
@@ -27,7 +27,7 @@
#include <fcntl.h>
#include <limits.h>
-#include "device-types.h"
+#include "device/device-types.h"
#define NUMBER_OF_MAJORS 4096
10 years, 9 months
master - cleanup: use libdm's dm_sysfs_dir() for sysfs directory throughout
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=657abb08e0e509...
Commit: 657abb08e0e509e084d23d8b4dcf6248362cccd4
Parent: bb70b38021992dd462a94d40527a315ce1e692fd
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Wed Jun 12 11:38:48 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Wed Jun 12 11:44:58 2013 +0200
cleanup: use libdm's dm_sysfs_dir() for sysfs directory throughout
And remove superfluous cmd->sysfs_dir and
set_sysfs_dir_path/sysfs_dir_path fn from lvm-globals.[ch].
---
lib/commands/toolcontext.c | 18 ++++++------
lib/commands/toolcontext.h | 1 -
lib/device/dev-md.c | 14 +++++-----
lib/device/device.c | 59 +++++++++++++++----------------------------
lib/device/device.h | 24 +++++------------
lib/filters/filter-mpath.c | 5 ++-
lib/filters/filter-mpath.h | 2 +-
lib/filters/filter-sysfs.c | 3 +-
lib/filters/filter-sysfs.h | 2 +-
lib/filters/filter.c | 2 +-
lib/metadata/metadata.c | 9 +++---
lib/metadata/pv_manip.c | 4 +-
12 files changed, 58 insertions(+), 85 deletions(-)
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index c409f2a..dca2329 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -79,14 +79,15 @@ static int _get_env_vars(struct cmd_context *cmd)
return 1;
}
-static void _get_sysfs_dir(struct cmd_context *cmd)
+static void _get_sysfs_dir(struct cmd_context *cmd, char *buf, size_t buf_size)
{
static char proc_mounts[PATH_MAX];
static char *split[4], buffer[PATH_MAX + 16];
FILE *fp;
char *sys_mnt = NULL;
- cmd->sysfs_dir[0] = '\0';
+ *buf = '\0';
+
if (!*cmd->proc_dir) {
log_debug("No proc filesystem found: skipping sysfs detection");
return;
@@ -119,7 +120,7 @@ static void _get_sysfs_dir(struct cmd_context *cmd)
return;
}
- strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir));
+ strncpy(buf, sys_mnt, buf_size);
}
static int _parse_debug_classes(struct cmd_context *cmd)
@@ -272,6 +273,7 @@ static int _process_config(struct cmd_context *cmd)
int64_t pv_min_kb;
const char *lvmetad_socket;
int udev_disabled = 0;
+ char sysfs_dir[PATH_MAX];
if (!config_def_check(cmd, 0, 0, 0) && find_config_tree_bool(cmd, config_abort_on_errors_CFG)) {
log_error("LVM configuration invalid.");
@@ -312,10 +314,8 @@ static int _process_config(struct cmd_context *cmd)
cmd->proc_dir[0] = '\0';
}
- /* FIXME Use global value of sysfs_dir everywhere instead cmd->sysfs_dir. */
- _get_sysfs_dir(cmd);
- set_sysfs_dir_path(cmd->sysfs_dir);
- dm_set_sysfs_dir(cmd->sysfs_dir);
+ _get_sysfs_dir(cmd, sysfs_dir, sizeof(sysfs_dir));
+ dm_set_sysfs_dir(sysfs_dir);
/* activation? */
cmd->default_settings.activation = find_config_tree_bool(cmd, global_activation_CFG);
@@ -804,7 +804,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
* unavailable devices.
*/
if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG)) {
- if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir)))
+ if ((filters[nr_filt] = sysfs_filter_create()))
nr_filt++;
}
@@ -836,7 +836,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
/* mpath component filter. Optional, non-critical. */
if (find_config_tree_bool(cmd, devices_multipath_component_detection_CFG)) {
- if ((filters[nr_filt] = mpath_filter_create(cmd->sysfs_dir)))
+ if ((filters[nr_filt] = mpath_filter_create()))
nr_filt++;
}
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index b79ebe2..307dc77 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -113,7 +113,6 @@ struct cmd_context {
char system_dir[PATH_MAX];
char dev_dir[PATH_MAX];
char proc_dir[PATH_MAX];
- char sysfs_dir[PATH_MAX]; /* FIXME Use global value instead. */
};
/*
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index 247a8ac..c4e2316 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -127,10 +127,10 @@ out:
}
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
- const char *sysfs_dir,
struct device *blkdev,
const char *attribute)
{
+ const char *sysfs_dir = dm_sysfs_dir();
struct stat info;
dev_t dev = blkdev->dev;
int ret = -1;
@@ -140,7 +140,7 @@ static int _md_sysfs_attribute_snprintf(char *path, size_t size,
if (MAJOR(dev) == blkext_major()) {
/* lookup parent MD device from blkext partition */
- if (!get_primary_dev(sysfs_dir, blkdev, &dev))
+ if (!get_primary_dev(blkdev, &dev))
return ret;
}
@@ -181,8 +181,8 @@ static int _md_sysfs_attribute_scanf(const char *sysfs_dir,
FILE *fp;
int ret = 0;
- if (_md_sysfs_attribute_snprintf(path, PATH_MAX, sysfs_dir,
- dev, attribute_name) < 0)
+ if (_md_sysfs_attribute_snprintf(path, PATH_MAX, dev,
+ attribute_name) < 0)
return ret;
if (!(fp = fopen(path, "r"))) {
@@ -271,8 +271,9 @@ static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
/*
* Calculate stripe width of md device using its sysfs files.
*/
-unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev)
+unsigned long dev_md_stripe_width(struct device *dev)
{
+ const char *sysfs_dir = dm_sysfs_dir();
unsigned long chunk_size_sectors = 0UL;
unsigned long stripe_width_sectors = 0UL;
int level, raid_disks, data_disks;
@@ -332,8 +333,7 @@ int dev_is_md(struct device *dev __attribute__((unused)),
return 0;
}
-unsigned long dev_md_stripe_width(const char *sysfs_dir __attribute__((unused)),
- struct device *dev __attribute__((unused)))
+unsigned long dev_md_stripe_width(struct device *dev __attribute__((unused)))
{
return 0UL;
}
diff --git a/lib/device/device.c b/lib/device/device.c
index a87ae7f..52eb4a6 100644
--- a/lib/device/device.c
+++ b/lib/device/device.c
@@ -278,9 +278,9 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
#ifdef linux
-int get_primary_dev(const char *sysfs_dir,
- const struct device *dev, dev_t *result)
+int get_primary_dev(const struct device *dev, dev_t *result)
{
+ const char *sysfs_dir = dm_sysfs_dir();
char path[PATH_MAX+1];
char temp_path[PATH_MAX+1];
char buffer[64];
@@ -357,10 +357,9 @@ out:
return ret;
}
-static unsigned long _dev_topology_attribute(const char *attribute,
- const char *sysfs_dir,
- struct device *dev)
+static unsigned long _dev_topology_attribute(const char *attribute, struct device *dev)
{
+ const char *sysfs_dir = dm_sysfs_dir();
static const char sysfs_fmt_str[] = "%s/dev/block/%d:%d/%s";
char path[PATH_MAX+1], buffer[64];
FILE *fp;
@@ -391,7 +390,7 @@ static unsigned long _dev_topology_attribute(const char *attribute,
log_sys_error("stat", path);
return 0;
}
- if (!get_primary_dev(sysfs_dir, dev, &primary))
+ if (!get_primary_dev(dev, &primary))
return 0;
/* get attribute from partition's primary device */
@@ -434,75 +433,59 @@ out:
return result >> SECTOR_SHIFT;
}
-unsigned long dev_alignment_offset(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_alignment_offset(struct device *dev)
{
- return _dev_topology_attribute("alignment_offset",
- sysfs_dir, dev);
+ return _dev_topology_attribute("alignment_offset", dev);
}
-unsigned long dev_minimum_io_size(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_minimum_io_size(struct device *dev)
{
- return _dev_topology_attribute("queue/minimum_io_size",
- sysfs_dir, dev);
+ return _dev_topology_attribute("queue/minimum_io_size", dev);
}
-unsigned long dev_optimal_io_size(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_optimal_io_size(struct device *dev)
{
- return _dev_topology_attribute("queue/optimal_io_size",
- sysfs_dir, dev);
+ return _dev_topology_attribute("queue/optimal_io_size", dev);
}
-unsigned long dev_discard_max_bytes(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_discard_max_bytes(struct device *dev)
{
- return _dev_topology_attribute("queue/discard_max_bytes",
- sysfs_dir, dev);
+ return _dev_topology_attribute("queue/discard_max_bytes", dev);
}
-unsigned long dev_discard_granularity(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_discard_granularity(struct device *dev)
{
- return _dev_topology_attribute("queue/discard_granularity",
- sysfs_dir, dev);
+ return _dev_topology_attribute("queue/discard_granularity", dev);
}
#else
-int get_primary_dev(const char *sysfs_dir,
- struct device *dev, dev_t *result)
+int get_primary_dev(struct device *dev, dev_t *result)
{
return 0;
}
-unsigned long dev_alignment_offset(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_alignment_offset(struct device *dev)
{
return 0UL;
}
-unsigned long dev_minimum_io_size(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_minimum_io_size(struct device *dev)
{
return 0UL;
}
-unsigned long dev_optimal_io_size(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_optimal_io_size(struct device *dev)
{
return 0UL;
}
-unsigned long dev_discard_max_bytes(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_discard_max_bytes(struct device *dev)
{
return 0UL;
}
-unsigned long dev_discard_granularity(const char *sysfs_dir,
- struct device *dev)
+unsigned long dev_discard_granularity(struct device *dev)
{
return 0UL;
}
diff --git a/lib/device/device.h b/lib/device/device.h
index 8c32a03..025d4ca 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -103,26 +103,16 @@ const char *dev_name_confirmed(struct device *dev, int quiet);
int dev_is_md(struct device *dev, uint64_t *sb);
int dev_is_swap(struct device *dev, uint64_t *signature);
int dev_is_luks(struct device *dev, uint64_t *signature);
-unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev);
+unsigned long dev_md_stripe_width(struct device *dev);
int is_partitioned_dev(struct device *dev);
-int get_primary_dev(const char *sysfs_dir,
- const struct device *dev, dev_t *result);
+int get_primary_dev(const struct device *dev, dev_t *result);
-unsigned long dev_alignment_offset(const char *sysfs_dir,
- struct device *dev);
-
-unsigned long dev_minimum_io_size(const char *sysfs_dir,
- struct device *dev);
-
-unsigned long dev_optimal_io_size(const char *sysfs_dir,
- struct device *dev);
-
-unsigned long dev_discard_max_bytes(const char *sysfs_dir,
- struct device *dev);
-
-unsigned long dev_discard_granularity(const char *sysfs_dir,
- struct device *dev);
+unsigned long dev_alignment_offset(struct device *dev);
+unsigned long dev_minimum_io_size(struct device *dev);
+unsigned long dev_optimal_io_size(struct device *dev);
+unsigned long dev_discard_max_bytes(struct device *dev);
+unsigned long dev_discard_granularity(struct device *dev);
#endif
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index 2d171e6..f3af268 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -119,7 +119,7 @@ static int dev_is_mpath(struct dev_filter *f, struct device *dev)
char path[PATH_MAX+1];
char parent_name[PATH_MAX+1];
struct stat info;
- const char *sysfs_dir = f->private;
+ const char *sysfs_dir = dm_sysfs_dir();
int major, minor;
/* Limit this filter only to SCSI devices */
@@ -176,8 +176,9 @@ static void _destroy(struct dev_filter *f)
dm_free(f);
}
-struct dev_filter *mpath_filter_create(const char *sysfs_dir)
+struct dev_filter *mpath_filter_create(void)
{
+ const char *sysfs_dir = dm_sysfs_dir();
struct dev_filter *f;
if (!*sysfs_dir) {
diff --git a/lib/filters/filter-mpath.h b/lib/filters/filter-mpath.h
index 0b5373f..31585eb 100644
--- a/lib/filters/filter-mpath.h
+++ b/lib/filters/filter-mpath.h
@@ -17,7 +17,7 @@
#include "dev-cache.h"
-struct dev_filter *mpath_filter_create(const char *sysfs_dir);
+struct dev_filter *mpath_filter_create(void);
#endif
diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c
index a075f36..cd039c0 100644
--- a/lib/filters/filter-sysfs.c
+++ b/lib/filters/filter-sysfs.c
@@ -290,8 +290,9 @@ static void _destroy(struct dev_filter *f)
dm_pool_destroy(ds->mem);
}
-struct dev_filter *sysfs_filter_create(const char *sysfs_dir)
+struct dev_filter *sysfs_filter_create(void)
{
+ const char *sysfs_dir = dm_sysfs_dir();
char sys_block[PATH_MAX];
unsigned sysfs_depth;
struct dm_pool *mem;
diff --git a/lib/filters/filter-sysfs.h b/lib/filters/filter-sysfs.h
index 9e4f503..6fb5591 100644
--- a/lib/filters/filter-sysfs.h
+++ b/lib/filters/filter-sysfs.h
@@ -18,6 +18,6 @@
#include "config.h"
#include "dev-cache.h"
-struct dev_filter *sysfs_filter_create(const char *sysfs_dir);
+struct dev_filter *sysfs_filter_create(void);
#endif
diff --git a/lib/filters/filter.c b/lib/filters/filter.c
index 7925440..d3fdd6e 100644
--- a/lib/filters/filter.c
+++ b/lib/filters/filter.c
@@ -76,7 +76,7 @@ int dev_subsystem_part_major(const struct device *dev)
return 1;
if ((MAJOR(dev->dev) == _blkext_major) &&
- (get_primary_dev(sysfs_dir_path(), dev, &primary_dev)) &&
+ (get_primary_dev(dev, &primary_dev)) &&
(MAJOR(primary_dev) == _md_major))
return 1;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index d25fe01..4e52bd4 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -84,7 +84,7 @@ unsigned long set_pe_align(struct physical_volume *pv, unsigned long data_alignm
* Align to stripe-width of underlying md device if present
*/
if (find_config_tree_bool(pv->fmt->cmd, devices_md_chunk_alignment_CFG)) {
- temp_pe_align = dev_md_stripe_width(pv->fmt->cmd->sysfs_dir, pv->dev);
+ temp_pe_align = dev_md_stripe_width(pv->dev);
if (_alignment_overrides_default(temp_pe_align, default_pe_align))
pv->pe_align = temp_pe_align;
}
@@ -97,11 +97,11 @@ unsigned long set_pe_align(struct physical_volume *pv, unsigned long data_alignm
* (e.g. MD's stripe width)
*/
if (find_config_tree_bool(pv->fmt->cmd, devices_data_alignment_detection_CFG)) {
- temp_pe_align = dev_minimum_io_size(pv->fmt->cmd->sysfs_dir, pv->dev);
+ temp_pe_align = dev_minimum_io_size(pv->dev);
if (_alignment_overrides_default(temp_pe_align, default_pe_align))
pv->pe_align = temp_pe_align;
- temp_pe_align = dev_optimal_io_size(pv->fmt->cmd->sysfs_dir, pv->dev);
+ temp_pe_align = dev_optimal_io_size(pv->dev);
if (_alignment_overrides_default(temp_pe_align, default_pe_align))
pv->pe_align = temp_pe_align;
}
@@ -129,8 +129,7 @@ unsigned long set_pe_align_offset(struct physical_volume *pv,
goto out;
if (find_config_tree_bool(pv->fmt->cmd, devices_data_alignment_offset_detection_CFG)) {
- int align_offset = dev_alignment_offset(pv->fmt->cmd->sysfs_dir,
- pv->dev);
+ int align_offset = dev_alignment_offset(pv->dev);
/* must handle a -1 alignment_offset; means dev is misaligned */
if (align_offset < 0)
align_offset = 0;
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index 4a65a3e..ae453ae 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -216,8 +216,8 @@ int discard_pv_segment(struct pv_segment *peg, uint32_t discard_area_reduction)
return 1;
}
- if (!dev_discard_max_bytes(peg->pv->fmt->cmd->sysfs_dir, peg->pv->dev) ||
- !dev_discard_granularity(peg->pv->fmt->cmd->sysfs_dir, peg->pv->dev))
+ if (!dev_discard_max_bytes(peg->pv->dev) ||
+ !dev_discard_granularity(peg->pv->dev))
return 1;
discard_offset_sectors = (peg->pe + peg->lvseg->area_len - discard_area_reduction) *
10 years, 9 months
master - lvresize: improve poolmetadatasize
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=bb70b38021992d...
Commit: bb70b38021992dd462a94d40527a315ce1e692fd
Parent: 6ff8b6d7548b218f678c45f768b8383038db1855
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Jun 11 19:46:42 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Jun 11 19:46:42 2013 +0200
lvresize: improve poolmetadatasize
Fix the usecase when only PV list is specified.
With --poolmetadatasize PV list is used for metadata extents.
Without --poolmetadatasize PV list is used for 100% extension of LV.
Handle the case, when nothing could be resized (i.e. in dmeventd)
---
tools/lvresize.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 3e2c281..9139228 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -214,12 +214,15 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
* Allow omission of extents and size if the user has given us
* one or more PVs. Most likely, the intent was "resize this
* LV the best you can with these PVs"
+ * If only --poolmetadatasize is specified with list of PVs,
+ * then metadata will be extended there.
*/
lp->sizeargs = arg_count(cmd, extents_ARG) + arg_count(cmd, size_ARG);
if ((lp->sizeargs == 0) && (argc >= 2)) {
lp->extents = 100;
lp->percent = PERCENT_PVS;
lp->sign = SIGN_PLUS;
+ lp->sizeargs = !lp->poolmetadatasize ? 1 : 0;
} else if ((lp->sizeargs != 1) &&
((lp->sizeargs == 2) ||
!arg_count(cmd, poolmetadatasize_ARG))) {
@@ -429,8 +432,11 @@ static int _lvresize_poolmetadata(struct cmd_context *cmd, struct volume_group *
return 2;
}
+ if (!lp->sizeargs && !archive(vg))
+ return_0;
+
log_print_unless_silent("Extending logical volume %s to %s.",
- lv->name,
+ lv->name,
display_size(cmd, (uint64_t) extents * vg->extent_size));
mseg = last_seg(lv);
seg_mirrors = lv_mirror_count(lv);
@@ -575,7 +581,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
return ECMD_FAILED;
}
- if (lp->sizeargs || (pvh != &vg->pvs)) { /* TODO: reindent or move to function */
+ if (lp->sizeargs) { /* TODO: reindent or move to function */
switch(lp->percent) {
case PERCENT_VG:
@@ -954,6 +960,9 @@ metadata_resize:
lock_lv = lv;
}
+ if (!lock_lv)
+ return ECMD_PROCESSED; /* Nothing to do */
+
/* store vg on disk(s) */
if (!vg_write(vg)) {
stack;
10 years, 9 months
master - lvresize: fix pvh handling
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6ff8b6d7548b21...
Commit: 6ff8b6d7548b218f678c45f768b8383038db1855
Parent: 861fd1108f4873f549c1e1b852243edcf03493d9
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Jun 11 14:55:32 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Jun 11 14:55:32 2013 +0200
lvresize: fix pvh handling
Fix bug in previous patch - if only PVs are specified -
it's like if user would have specified size.
---
tools/lvresize.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/lvresize.c b/tools/lvresize.c
index bb9a535..3e2c281 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -458,7 +458,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
uint32_t size_rest;
uint32_t pv_extent_count;
alloc_policy_t alloc;
- struct logical_volume *lock_lv;
+ struct logical_volume *lock_lv = NULL;
struct lv_list *lvl;
struct lv_segment *seg, *uninitialized_var(mirr_seg);
uint32_t seg_extents;
@@ -575,7 +575,7 @@ static int _lvresize(struct cmd_context *cmd, struct volume_group *vg,
return ECMD_FAILED;
}
- if (lp->sizeargs) { /* TODO: reindent or move to function */
+ if (lp->sizeargs || (pvh != &vg->pvs)) { /* TODO: reindent or move to function */
switch(lp->percent) {
case PERCENT_VG:
10 years, 9 months
master - libdm: move thin max size to header
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=861fd1108f4873...
Commit: 861fd1108f4873f549c1e1b852243edcf03493d9
Parent: 9ac0f58ea13dc068806ff1085e0ea06a7840d5fd
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed May 22 15:02:55 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Jun 11 14:21:00 2013 +0200
libdm: move thin max size to header
Move max size of thin metadata into define.
Increase a bit the size to match the kernel size.
(16978542592->17112760320)
---
libdm/libdevmapper.h | 7 +++++++
libdm/libdm-deptree.c | 15 ++++-----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index dba8548..bada775 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -749,6 +749,13 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
*/
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
+/*
+ * Max supported size for thin pool metadata device (17112760320 bytes)
+ * Limitation is hardcoded into the kernel and bigger device size
+ * is not accepted.
+ * drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
+ */
+#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t size,
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index f8c0d7a..50ed908 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -3232,13 +3232,6 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
{
struct load_segment *seg, *mseg;
uint64_t devsize = 0;
- /*
- * Max supported size for thin pool metadata device
- * Limitation is hardcoded into kernel and bigger
- * device size is not accepted. (16978542592)
- */
- const uint64_t max_metadata_size =
- 255ULL * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024;
if (data_block_size < DM_THIN_MIN_DATA_BLOCK_SIZE) {
log_error("Data block size %u is lower then %u sectors.",
@@ -3266,11 +3259,11 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
/* FIXME: more complex target may need more tweaks */
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
devsize += mseg->size;
- if (devsize > max_metadata_size) {
+ if (devsize > DM_THIN_MAX_METADATA_SIZE) {
log_debug_activation("Ignoring %" PRIu64 " of device.",
- devsize - max_metadata_size);
- mseg->size -= (devsize - max_metadata_size);
- devsize = max_metadata_size;
+ devsize - DM_THIN_MAX_METADATA_SIZE);
+ mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
+ devsize = DM_THIN_MAX_METADATA_SIZE;
/* FIXME: drop remaining segs */
}
}
10 years, 9 months
master - tests: lvresize thin
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9ac0f58ea13dc0...
Commit: 9ac0f58ea13dc068806ff1085e0ea06a7840d5fd
Parent: 4937df4aed699a5e3bc3c860e897fa0e448cfc6b
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Tue Jun 11 13:35:18 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Tue Jun 11 14:07:51 2013 +0200
tests: lvresize thin
---
test/shell/lvresize-thin-metadata.sh | 35 ++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/test/shell/lvresize-thin-metadata.sh b/test/shell/lvresize-thin-metadata.sh
new file mode 100644
index 0000000..10dbb4a
--- /dev/null
+++ b/test/shell/lvresize-thin-metadata.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. lib/test
+
+aux have_thin 1 8 0 || skip
+
+aux prepare_pvs 3
+
+vgcreate -s 1M $vg $(cat DEVICES)
+
+lvcreate -l1 -T $vg/pool
+
+# Confirm we have basic 2M metadata
+check lv_field $vg/pool_tmeta size "2.00m"
+
+lvresize --poolmetadata +2 $vg/pool
+
+# Test it's been resized to 4M
+check lv_field $vg/pool_tmeta size "4.00m"
+
+# TODO: Add more tests when kernel is fixed
+
+
+# TODO: Make a full metadata device and test dmeventd support
+
+vgremove -ff $vg
10 years, 9 months