diff -Nru device-mapper.1.02.27/lib/.exported_symbols device-mapper.working//lib/.exported_symbols --- device-mapper.1.02.27/lib/.exported_symbols 2008-04-20 08:11:08.000000000 +0800 +++ device-mapper.working//lib/.exported_symbols 2009-10-19 15:24:48.000000000 +0800 @@ -49,6 +49,7 @@ dm_tree_node_get_uuid dm_tree_node_get_info dm_tree_node_get_context +dm_tree_node_size_changed dm_tree_node_num_children dm_tree_node_num_parents dm_tree_find_node diff -Nru device-mapper.1.02.27/lib/ioctl/libdm-iface.c device-mapper.working//lib/ioctl/libdm-iface.c --- device-mapper.1.02.27/lib/ioctl/libdm-iface.c 2009-10-19 15:25:24.000000000 +0800 +++ device-mapper.working//lib/ioctl/libdm-iface.c 2009-10-19 15:20:30.000000000 +0800 @@ -1568,6 +1568,11 @@ return r; } +uint64_t dm_task_get_existing_table_size(struct dm_task *dmt) +{ + return dmt->existing_table_size; +} + static int _reload_with_suppression_v4(struct dm_task *dmt) { struct dm_task *task; @@ -1601,6 +1606,12 @@ return r; } + /* Store existing table size */ + t2 = task->head; + while (t2 && t2->next) + t2 = t2->next; + dmt->existing_table_size = t2 ? t2->start + t2->length : 0; + if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only) goto no_match; diff -Nru device-mapper.1.02.27/lib/ioctl/libdm-targets.h device-mapper.working//lib/ioctl/libdm-targets.h --- device-mapper.1.02.27/lib/ioctl/libdm-targets.h 2007-11-28 04:57:05.000000000 +0800 +++ device-mapper.working//lib/ioctl/libdm-targets.h 2009-10-19 15:20:30.000000000 +0800 @@ -58,6 +58,7 @@ int no_open_count; int skip_lockfs; int suppress_identical_reload; + uint64_t existing_table_size; char *uuid; }; @@ -69,5 +70,6 @@ }; int dm_check_version(void); +uint64_t dm_task_get_existing_table_size(struct dm_task *dmt); #endif diff -Nru device-mapper.1.02.27/lib/libdevmapper.h device-mapper.working//lib/libdevmapper.h --- device-mapper.1.02.27/lib/libdevmapper.h 2008-06-25 06:53:48.000000000 +0800 +++ device-mapper.working//lib/libdevmapper.h 2009-10-19 15:24:32.000000000 +0800 @@ -287,6 +287,7 @@ const char *dm_tree_node_get_uuid(struct dm_tree_node *node); const struct dm_info *dm_tree_node_get_info(struct dm_tree_node *node); void *dm_tree_node_get_context(struct dm_tree_node *node); +int dm_tree_node_size_changed(struct dm_tree_node *dnode); /* * Returns the number of children of the given node (excluding the root node). diff -Nru device-mapper.1.02.27/lib/libdm-deptree.c device-mapper.working//lib/libdm-deptree.c --- device-mapper.1.02.27/lib/libdm-deptree.c 2008-06-25 22:24:17.000000000 +0800 +++ device-mapper.working//lib/libdm-deptree.c 2009-10-19 15:24:08.000000000 +0800 @@ -99,6 +99,7 @@ uint32_t read_ahead_flags; unsigned segment_count; + unsigned size_changed; struct list segs; const char *new_name; @@ -603,6 +604,7 @@ dnode->props.major = major; dnode->props.minor = minor; dnode->props.new_name = NULL; + dnode->props.size_changed = 0; } else if (strcmp(name, dnode->name)) { /* Do we need to rename node? */ if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) { @@ -656,6 +658,11 @@ return node->context; } +int dm_tree_node_size_changed(struct dm_tree_node *dnode) +{ + return dnode->props.size_changed; +} + int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted) { if (inverted) { @@ -1493,6 +1500,13 @@ if (r && !dnode->info.inactive_table) log_verbose("Suppressed %s identical table reload.", dnode->name); + + if ((dnode->props.size_changed = + (dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1)) + log_debug("Table size changed from %" PRIu64 " to %" + PRIu64 " for %s", + dm_task_get_existing_table_size(dmt), + seg_start, dnode->name); } dnode->props.segment_count = 0; @@ -1504,8 +1518,8 @@ } int dm_tree_preload_children(struct dm_tree_node *dnode, - const char *uuid_prefix, - size_t uuid_prefix_len) + const char *uuid_prefix, + size_t uuid_prefix_len) { void *handle = NULL; struct dm_tree_node *child; @@ -1540,8 +1554,12 @@ } } - /* Resume device immediately if it has parents */ - if (!dm_tree_node_num_children(child, 1)) + /* Propagate device size change change */ + if (child->props.size_changed) + dnode->props.size_changed = 1; + + /* Resume device immediately if it has parents and its size changed */ + if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed) continue; if (!child->info.inactive_table && !child->info.suspended)