Home | History | Annotate | Line # | Download | only in metadata
      1      1.1  haad /*	$NetBSD: snapshot_manip.c,v 1.1.1.3 2009/12/02 00:26:37 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.1.3  haad 	if (lv->status & SNAPSHOT)
     36  1.1.1.3  haad 		return 0;
     37  1.1.1.3  haad 
     38  1.1.1.3  haad 	if (lv_is_cow(lv)) {
     39  1.1.1.3  haad 		if (lv_is_virtual_origin(origin_from_cow(lv)))
     40  1.1.1.3  haad 			return 1;
     41  1.1.1.3  haad 
     42  1.1.1.3  haad 		return lv_is_visible(origin_from_cow(lv));
     43  1.1.1.3  haad 	}
     44      1.1  haad 
     45      1.1  haad 	return lv->status & VISIBLE_LV ? 1 : 0;
     46      1.1  haad }
     47      1.1  haad 
     48  1.1.1.3  haad int lv_is_virtual_origin(const struct logical_volume *lv)
     49  1.1.1.2  haad {
     50  1.1.1.3  haad 	return (lv->status & VIRTUAL_ORIGIN) ? 1 : 0;
     51  1.1.1.2  haad }
     52  1.1.1.2  haad 
     53  1.1.1.3  haad 
     54      1.1  haad /* Given a cow LV, return the snapshot lv_segment that uses it */
     55      1.1  haad struct lv_segment *find_cow(const struct logical_volume *lv)
     56      1.1  haad {
     57      1.1  haad 	return lv->snapshot;
     58      1.1  haad }
     59      1.1  haad 
     60      1.1  haad /* Given a cow LV, return its origin */
     61      1.1  haad struct logical_volume *origin_from_cow(const struct logical_volume *lv)
     62      1.1  haad {
     63      1.1  haad 	return lv->snapshot->origin;
     64      1.1  haad }
     65      1.1  haad 
     66  1.1.1.3  haad void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
     67  1.1.1.3  haad 		       struct logical_volume *cow, uint32_t chunk_size)
     68  1.1.1.3  haad {
     69  1.1.1.3  haad 	seg->chunk_size = chunk_size;
     70  1.1.1.3  haad 	seg->origin = origin;
     71  1.1.1.3  haad 	seg->cow = cow;
     72  1.1.1.3  haad 
     73  1.1.1.3  haad 	lv_set_hidden(cow);
     74  1.1.1.3  haad 
     75  1.1.1.3  haad 	cow->snapshot = seg;
     76  1.1.1.3  haad 
     77  1.1.1.3  haad 	origin->origin_count++;
     78  1.1.1.3  haad 
     79  1.1.1.3  haad 	/* FIXME Assumes an invisible origin belongs to a sparse device */
     80  1.1.1.3  haad 	if (!lv_is_visible(origin))
     81  1.1.1.3  haad 		origin->status |= VIRTUAL_ORIGIN;
     82  1.1.1.3  haad 
     83  1.1.1.3  haad 	seg->lv->status |= (SNAPSHOT | VIRTUAL);
     84  1.1.1.3  haad 
     85  1.1.1.3  haad 	dm_list_add(&origin->snapshot_segs, &seg->origin_list);
     86  1.1.1.3  haad }
     87  1.1.1.3  haad 
     88  1.1.1.3  haad int vg_add_snapshot(struct logical_volume *origin,
     89      1.1  haad 		    struct logical_volume *cow, union lvid *lvid,
     90      1.1  haad 		    uint32_t extent_count, uint32_t chunk_size)
     91      1.1  haad {
     92      1.1  haad 	struct logical_volume *snap;
     93      1.1  haad 	struct lv_segment *seg;
     94      1.1  haad 
     95      1.1  haad 	/*
     96      1.1  haad 	 * Is the cow device already being used ?
     97      1.1  haad 	 */
     98      1.1  haad 	if (lv_is_cow(cow)) {
     99  1.1.1.3  haad 		log_error("'%s' is already in use as a snapshot.", cow->name);
    100      1.1  haad 		return 0;
    101      1.1  haad 	}
    102      1.1  haad 
    103      1.1  haad 	if (cow == origin) {
    104      1.1  haad 		log_error("Snapshot and origin LVs must differ.");
    105      1.1  haad 		return 0;
    106      1.1  haad 	}
    107      1.1  haad 
    108  1.1.1.3  haad 	if (!(snap = lv_create_empty("snapshot%d",
    109      1.1  haad 				     lvid, LVM_READ | LVM_WRITE | VISIBLE_LV,
    110  1.1.1.3  haad 				     ALLOC_INHERIT, origin->vg)))
    111      1.1  haad 		return_0;
    112      1.1  haad 
    113      1.1  haad 	snap->le_count = extent_count;
    114      1.1  haad 
    115      1.1  haad 	if (!(seg = alloc_snapshot_seg(snap, 0, 0)))
    116      1.1  haad 		return_0;
    117      1.1  haad 
    118  1.1.1.3  haad 	init_snapshot_seg(seg, origin, cow, chunk_size);
    119      1.1  haad 
    120      1.1  haad 	return 1;
    121      1.1  haad }
    122      1.1  haad 
    123      1.1  haad int vg_remove_snapshot(struct logical_volume *cow)
    124      1.1  haad {
    125      1.1  haad 	dm_list_del(&cow->snapshot->origin_list);
    126      1.1  haad 	cow->snapshot->origin->origin_count--;
    127      1.1  haad 
    128      1.1  haad 	if (!lv_remove(cow->snapshot->lv)) {
    129      1.1  haad 		log_error("Failed to remove internal snapshot LV %s",
    130      1.1  haad 			  cow->snapshot->lv->name);
    131      1.1  haad 		return 0;
    132      1.1  haad 	}
    133      1.1  haad 
    134      1.1  haad 	cow->snapshot = NULL;
    135  1.1.1.3  haad 	lv_set_visible(cow);
    136      1.1  haad 
    137      1.1  haad 	return 1;
    138      1.1  haad }
    139