From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20617 invoked by alias); 13 Jan 2010 01:54:36 -0000 Received: (qmail 20596 invoked by uid 9805); 13 Jan 2010 01:54:36 -0000 Date: Wed, 13 Jan 2010 01:54:00 -0000 Message-ID: <20100113015436.20593.qmail@sourceware.org> From: snitzer@sourceware.org To: lvm-devel@redhat.com, lvm2-cvs@sourceware.org Subject: LVM2 lib/activate/dev_manager.c lib/report/rep ... Mailing-List: contact lvm2-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: lvm2-cvs-owner@sourceware.org X-SW-Source: 2010-01/txt/msg00075.txt.bz2 CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: snitzer@sourceware.org 2010-01-13 01:54:35 Modified files: lib/activate : dev_manager.c lib/report : report.c tools : lvconvert.c Log message: Merge on activate support. If either the origin or snapshot that is to be merged is open the merge will not start; only the merge metadata will be written. The merge will start on the next activation of the origin (or via lvchange --refresh) IFF both the origin and snapshot are closed. Merge on activate is particularly important if we want to merge over a mounted filesystem that cannot be unmounted (until next boot) --- for example root. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.170&r2=1.171 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/report/report.c.diff?cvsroot=lvm2&r1=1.109&r2=1.110 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.112&r2=1.113 --- LVM2/lib/activate/dev_manager.c 2010/01/13 01:44:37 1.170 +++ LVM2/lib/activate/dev_manager.c 2010/01/13 01:54:34 1.171 @@ -327,6 +327,52 @@ return 0; } +static int _lv_has_target_type(struct dev_manager *dm, + struct logical_volume *lv, + const char *layer, + const char *target_type) +{ + int r = 0; + char *dlid; + struct dm_task *dmt; + struct dm_info info; + void *next = NULL; + uint64_t start, length; + char *type = NULL; + char *params = NULL; + + if (!(dlid = build_dlid(dm, lv->lvid.s, layer))) + return_0; + + if (!(dmt = _setup_task(NULL, dlid, 0, + DM_DEVICE_STATUS, 0, 0))) + return_0; + + if (!dm_task_no_open_count(dmt)) + log_error("Failed to disable open_count"); + + if (!dm_task_run(dmt)) + goto_out; + + if (!dm_task_get_info(dmt, &info) || !info.exists) + goto_out; + + do { + next = dm_get_next_target(dmt, next, &start, &length, + &type, ¶ms); + if (type && strncmp(type, target_type, + strlen(target_type)) == 0) { + if (info.live_table && !info.inactive_table) + r = 1; + break; + } + } while (next); + + out: + dm_task_destroy(dmt); + return r; +} + static percent_range_t _combine_percent_ranges(percent_range_t a, percent_range_t b) { @@ -1062,12 +1108,33 @@ struct lv_segment *seg; struct lv_layer *lvlayer; struct dm_tree_node *dnode; + struct dm_info dinfo; char *name, *dlid, *lv_name; uint32_t max_stripe_size = UINT32_C(0); uint32_t read_ahead = lv->read_ahead; uint32_t read_ahead_flags = UINT32_C(0); uint16_t udev_flags = 0; + if (lv_is_origin(lv) && lv->merging_snapshot && !layer) { + /* + * Clear merge attributes if merge isn't currently possible: + * either origin or merging snapshot are open + * - must refresh info's open_count, so using the tree's + * existing nodes' info isn't an option + * - but use "snapshot-merge" if it is already being used + */ + if ((dev_manager_info(dm->mem, NULL, lv, + 0, 1, 0, &dinfo, NULL) && dinfo.open_count) || + (dev_manager_info(dm->mem, NULL, lv->merging_snapshot->cow, + 0, 1, 0, &dinfo, NULL) && dinfo.open_count)) { + if (!_lv_has_target_type(dm, lv, NULL, "snapshot-merge")) { + /* clear merge attributes */ + lv->merging_snapshot->status &= ~SNAPSHOT_MERGE; + lv->merging_snapshot = NULL; + } + } + } + lv_name = lv->name; if (lv_is_cow(lv) && find_cow(lv)->status & SNAPSHOT_MERGE) { if (layer) { --- LVM2/lib/report/report.c 2010/01/13 01:49:22 1.109 +++ LVM2/lib/report/report.c 2010/01/13 01:54:35 1.110 @@ -1032,8 +1032,16 @@ if (!lv_snapshot_percent(lv, &snap_percent, &percent_range) || (percent_range == PERCENT_INVALID)) { - *sortval = UINT64_C(100); - dm_report_field_set_value(field, "100.00", sortval); + if (!lv->merging_snapshot) { + *sortval = UINT64_C(100); + dm_report_field_set_value(field, "100.00", sortval); + } else { + /* onactivate merge that hasn't started yet would + * otherwise display incorrect snap% in origin + */ + *sortval = UINT64_C(0); + dm_report_field_set_value(field, "", sortval); + } return 1; } --- LVM2/tools/lvconvert.c 2010/01/13 01:49:52 1.112 +++ LVM2/tools/lvconvert.c 2010/01/13 01:54:35 1.113 @@ -1117,6 +1117,7 @@ struct lvconvert_params *lp) { int r = 0; + int merge_on_activate = 0; struct logical_volume *origin = origin_from_cow(lv); struct lv_segment *cow_seg = find_cow(lv); struct lvinfo info; @@ -1134,7 +1135,9 @@ /* * Prevent merge with open device(s) as it would likely lead - * to application/filesystem failure. + * to application/filesystem failure. Merge on origin's next + * activation if either the origin or snapshot LV are currently + * open. * * FIXME testing open_count is racey; snapshot-merge target's * constructor and DM should prevent appropriate devices from @@ -1143,13 +1146,13 @@ if (lv_info(cmd, origin, &info, 1, 0)) { if (info.open_count) { log_error("Can't merge over open origin volume"); - return 0; + merge_on_activate = 1; } } if (lv_info(cmd, lv, &info, 1, 0)) { if (info.open_count) { - log_error("Can't merge when snapshot is open"); - return 0; + log_print("Can't merge when snapshot is open"); + merge_on_activate = 1; } } @@ -1159,6 +1162,16 @@ if (!vg_write(lv->vg)) return_0; + if (merge_on_activate) { + /* commit vg but skip starting the merge */ + if (!vg_commit(lv->vg)) + return_0; + r = 1; + log_print("Merging of snapshot %s will start " + "next activation.", lv->name); + goto out; + } + /* Perform merge */ if (!suspend_lv(cmd, origin)) { log_error("Failed to suspend origin %s", origin->name);