Home | History | Annotate | Line # | Download | only in metadata
snapshot_manip.c revision 1.1.1.2
      1      1.1  haad /*	$NetBSD: snapshot_manip.c,v 1.1.1.2 2009/02/18 11:17:11 haad Exp $	*/
      2      1.1  haad 
      3      1.1  haad /*
      4      1.1  haad  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
      5      1.1  haad  * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
      6      1.1  haad  *
      7      1.1  haad  * This file is part of LVM2.
      8      1.1  haad  *
      9      1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     10      1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     11      1.1  haad  * of the GNU Lesser General Public License v.2.1.
     12      1.1  haad  *
     13      1.1  haad  * You should have received a copy of the GNU Lesser General Public License
     14      1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     15      1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16      1.1  haad  */
     17      1.1  haad 
     18      1.1  haad #include "lib.h"
     19      1.1  haad #include "metadata.h"
     20      1.1  haad #include "toolcontext.h"
     21      1.1  haad #include "lv_alloc.h"
     22      1.1  haad 
     23      1.1  haad int lv_is_origin(const struct logical_volume *lv)
     24      1.1  haad {
     25      1.1  haad 	return lv->origin_count ? 1 : 0;
     26      1.1  haad }
     27      1.1  haad 
     28      1.1  haad int lv_is_cow(const struct logical_volume *lv)
     29      1.1  haad {
     30      1.1  haad 	return lv->snapshot ? 1 : 0;
     31      1.1  haad }
     32      1.1  haad 
     33      1.1  haad int lv_is_visible(const struct logical_volume *lv)
     34      1.1  haad {
     35      1.1  haad 	if (lv_is_cow(lv))
     36      1.1  haad 		return lv_is_visible(find_cow(lv)->lv);
     37      1.1  haad 
     38      1.1  haad 	return lv->status & VISIBLE_LV ? 1 : 0;
     39      1.1  haad }
     40      1.1  haad 
     41  1.1.1.2  haad int lv_is_displayable(const struct logical_volume *lv)
     42  1.1.1.2  haad {
     43  1.1.1.2  haad 	if (lv->status & SNAPSHOT)
     44  1.1.1.2  haad 		return 0;
     45  1.1.1.2  haad 
     46  1.1.1.2  haad 	return (lv->status & VISIBLE_LV) || lv_is_cow(lv) ? 1 : 0;
     47  1.1.1.2  haad }
     48  1.1.1.2  haad 
     49      1.1  haad /* Given a cow LV, return the snapshot lv_segment that uses it */
     50      1.1  haad struct lv_segment *find_cow(const struct logical_volume *lv)
     51      1.1  haad {
     52      1.1  haad 	return lv->snapshot;
     53      1.1  haad }
     54      1.1  haad 
     55      1.1  haad /* Given a cow LV, return its origin */
     56      1.1  haad struct logical_volume *origin_from_cow(const struct logical_volume *lv)
     57      1.1  haad {
     58      1.1  haad 	return lv->snapshot->origin;
     59      1.1  haad }
     60      1.1  haad 
     61      1.1  haad int vg_add_snapshot(const char *name, struct logical_volume *origin,
     62      1.1  haad 		    struct logical_volume *cow, union lvid *lvid,
     63      1.1  haad 		    uint32_t extent_count, uint32_t chunk_size)
     64      1.1  haad {
     65      1.1  haad 	struct logical_volume *snap;
     66      1.1  haad 	struct lv_segment *seg;
     67      1.1  haad 
     68      1.1  haad 	/*
     69      1.1  haad 	 * Is the cow device already being used ?
     70      1.1  haad 	 */
     71      1.1  haad 	if (lv_is_cow(cow)) {
     72      1.1  haad 		log_err("'%s' is already in use as a snapshot.", cow->name);
     73      1.1  haad 		return 0;
     74      1.1  haad 	}
     75      1.1  haad 
     76      1.1  haad 	if (cow == origin) {
     77      1.1  haad 		log_error("Snapshot and origin LVs must differ.");
     78      1.1  haad 		return 0;
     79      1.1  haad 	}
     80      1.1  haad 
     81      1.1  haad 	if (!(snap = lv_create_empty(name ? name : "snapshot%d",
     82      1.1  haad 				     lvid, LVM_READ | LVM_WRITE | VISIBLE_LV,
     83      1.1  haad 				     ALLOC_INHERIT, 1, origin->vg)))
     84      1.1  haad 		return_0;
     85      1.1  haad 
     86      1.1  haad 	snap->le_count = extent_count;
     87      1.1  haad 
     88      1.1  haad 	if (!(seg = alloc_snapshot_seg(snap, 0, 0)))
     89      1.1  haad 		return_0;
     90      1.1  haad 
     91      1.1  haad 	seg->chunk_size = chunk_size;
     92      1.1  haad 	seg->origin = origin;
     93      1.1  haad 	seg->cow = cow;
     94      1.1  haad 	seg->lv->status |= SNAPSHOT;
     95      1.1  haad 
     96      1.1  haad 	origin->origin_count++;
     97      1.1  haad 	origin->vg->snapshot_count++;
     98      1.1  haad 	origin->vg->lv_count--;
     99      1.1  haad 	cow->snapshot = seg;
    100      1.1  haad 
    101      1.1  haad 	cow->status &= ~VISIBLE_LV;
    102      1.1  haad 
    103      1.1  haad 	dm_list_add(&origin->snapshot_segs, &seg->origin_list);
    104      1.1  haad 
    105      1.1  haad 	return 1;
    106      1.1  haad }
    107      1.1  haad 
    108      1.1  haad int vg_remove_snapshot(struct logical_volume *cow)
    109      1.1  haad {
    110      1.1  haad 	dm_list_del(&cow->snapshot->origin_list);
    111      1.1  haad 	cow->snapshot->origin->origin_count--;
    112      1.1  haad 
    113      1.1  haad 	if (!lv_remove(cow->snapshot->lv)) {
    114      1.1  haad 		log_error("Failed to remove internal snapshot LV %s",
    115      1.1  haad 			  cow->snapshot->lv->name);
    116      1.1  haad 		return 0;
    117      1.1  haad 	}
    118      1.1  haad 
    119      1.1  haad 	cow->snapshot = NULL;
    120      1.1  haad 
    121      1.1  haad 	cow->vg->snapshot_count--;
    122      1.1  haad 	cow->vg->lv_count++;
    123      1.1  haad 	cow->status |= VISIBLE_LV;
    124      1.1  haad 
    125      1.1  haad 	return 1;
    126      1.1  haad }
    127