4 * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
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.
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
20 #include "toolcontext.h"
23 int lv_is_origin(const struct logical_volume
*lv
)
25 return lv
->origin_count
? 1 : 0;
28 int lv_is_cow(const struct logical_volume
*lv
)
30 return lv
->snapshot
? 1 : 0;
33 int lv_is_visible(const struct logical_volume
*lv
)
35 if (lv
->status
& SNAPSHOT
)
39 if (lv_is_virtual_origin(origin_from_cow(lv
)))
42 return lv_is_visible(origin_from_cow(lv
));
45 return lv
->status
& VISIBLE_LV
? 1 : 0;
48 int lv_is_virtual_origin(const struct logical_volume
*lv
)
50 return (lv
->status
& VIRTUAL_ORIGIN
) ? 1 : 0;
54 /* Given a cow LV, return the snapshot lv_segment that uses it */
55 struct lv_segment
*find_cow(const struct logical_volume
*lv
)
60 /* Given a cow LV, return its origin */
61 struct logical_volume
*origin_from_cow(const struct logical_volume
*lv
)
63 return lv
->snapshot
->origin
;
66 void init_snapshot_seg(struct lv_segment
*seg
, struct logical_volume
*origin
,
67 struct logical_volume
*cow
, uint32_t chunk_size
)
69 seg
->chunk_size
= chunk_size
;
77 origin
->origin_count
++;
79 /* FIXME Assumes an invisible origin belongs to a sparse device */
80 if (!lv_is_visible(origin
))
81 origin
->status
|= VIRTUAL_ORIGIN
;
83 seg
->lv
->status
|= (SNAPSHOT
| VIRTUAL
);
85 dm_list_add(&origin
->snapshot_segs
, &seg
->origin_list
);
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
)
92 struct logical_volume
*snap
;
93 struct lv_segment
*seg
;
96 * Is the cow device already being used ?
99 log_error("'%s' is already in use as a snapshot.", cow
->name
);
104 log_error("Snapshot and origin LVs must differ.");
108 if (!(snap
= lv_create_empty("snapshot%d",
109 lvid
, LVM_READ
| LVM_WRITE
| VISIBLE_LV
,
110 ALLOC_INHERIT
, origin
->vg
)))
113 snap
->le_count
= extent_count
;
115 if (!(seg
= alloc_snapshot_seg(snap
, 0, 0)))
118 init_snapshot_seg(seg
, origin
, cow
, chunk_size
);
123 int vg_remove_snapshot(struct logical_volume
*cow
)
125 dm_list_del(&cow
->snapshot
->origin_list
);
126 cow
->snapshot
->origin
->origin_count
--;
128 if (!lv_remove(cow
->snapshot
->lv
)) {
129 log_error("Failed to remove internal snapshot LV %s",
130 cow
->snapshot
->lv
->name
);
134 cow
->snapshot
= NULL
;