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