]> sourceware.org Git - lvm2.git/commitdiff
o First changes to add snapshot support.
authorJoe Thornber <thornber@redhat.com>
Tue, 12 Feb 2002 16:31:31 +0000 (16:31 +0000)
committerJoe Thornber <thornber@redhat.com>
Tue, 12 Feb 2002 16:31:31 +0000 (16:31 +0000)
I'm taking a different route from LVM1 here in that snapshots are a
seperate entity from the logical volumes, I think of them as an
application of an LV (or two lvs rather).  As such there is a list of
snapshots held against the vg, and there is *not* a SNAPSHOT, or
SHAPSHOT_ORG flag in lv->status.

lib/Makefile.in
lib/format1/disk-rep.h
lib/format1/format1.c
lib/format1/import-export.c
lib/metadata/metadata.h
lib/metadata/snapshot_manip.c [new file with mode: 0644]

index c35c2a72a535b79a861251c39521b7c6dba6e3ec..109d29b84d94b31051dadcbcb22e91b6f6520b35 100644 (file)
@@ -40,13 +40,14 @@ SOURCES=\
        format_text/import.c \
        label/label.c \
        label/uuid-map.c \
-       locking/locking.c \
        locking/file_locking.c \
+       locking/locking.c \
        log/log.c \
        metadata/lv_manip.c \
        metadata/merge.c \
        metadata/metadata.c \
        metadata/pv_map.c \
+       metadata/snapshot_manip.c \
        misc/lvm-file.c \
        mm/dbg_malloc.c \
        mm/pool.c \
index fa42d7716768dcce3849db1ddaaec1df2dad7176..7db71d7fe5b4ababd81688e38682d56124d69481 100644 (file)
@@ -216,7 +216,7 @@ int import_lv(struct pool *mem, struct logical_volume *lv,
 void export_lv(struct lv_disk *lvd, struct volume_group *vg,
               struct logical_volume *lv, const char *dev_dir);
 
-int import_extents(struct pool *mem, struct volume_group *vg, 
+int import_extents(struct pool *mem, struct volume_group *vg,
                   struct list *pvds);
 int export_extents(struct disk_list *dl, int lv_num,
                   struct logical_volume *lv,
index 1cfe297d35a5db47ff566648d5f50ecb93a00d5f..1b8de64414a32cbb038878bd03e8e8ea4c562c5c 100644 (file)
@@ -29,7 +29,7 @@ static int _check_vgs(struct list *pvs, int *partial)
         * If there are exported and unexported PVs, ignore exported ones.
         * This means an active VG won't be affected if disks are inserted
         * bearing an exported VG with the same name.
-        */ 
+        */
        list_iterate(pvh, pvs) {
                dl = list_item(pvh, struct disk_list);
 
index 8cec06fb12b95126998d5314bbdca4b07f76ab56..4e049cbce179b3d0dc41a4d298d45a7a07982ba0 100644 (file)
@@ -58,10 +58,10 @@ int import_pv(struct pool *mem, struct device *dev,
        if (vg &&
            strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id)))
                log_very_verbose("System ID %s on %s differs from %s for "
-                                "volume group", pvd->system_id, 
+                                "volume group", pvd->system_id,
                                 dev_name(pv->dev), vg->system_id);
-       
-       /* 
+
+       /*
         * If exported, we still need to flag in pv->status too because
         * we don't always have a struct volume_group when we need this.
         */
@@ -89,7 +89,7 @@ int _system_id(char *s, const char *prefix)
                return 0;
        }
 
-       if (lvm_snprintf(s, NAME_LEN, "%s%s%lu", 
+       if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
                         prefix, uts.nodename, time(NULL)) < 0) {
                log_error("Generated system_id too long");
                return 0;
@@ -120,14 +120,14 @@ int export_pv(struct pool *mem, struct volume_group *vg,
                strncpy(pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
 
        /* Preserve existing system_id if it exists */
-       if (vg && *vg->system_id) 
+       if (vg && *vg->system_id)
                strncpy(pvd->system_id, vg->system_id, sizeof(pvd->system_id));
 
        /* Is VG already exported or being exported? */
        if (vg && (vg->status & EXPORTED_VG)) {
                /* Does system_id need setting? */
-               if (!*vg->system_id || 
-                   strncmp(vg->system_id, EXPORTED_TAG, 
+               if (!*vg->system_id ||
+                   strncmp(vg->system_id, EXPORTED_TAG,
                            sizeof(EXPORTED_TAG) - 1)) {
                        if (!_system_id(pvd->system_id, EXPORTED_TAG)) {
                                stack;
@@ -160,7 +160,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
                }
 
        /* Update internal system_id if we changed it */
-       if (vg && 
+       if (vg &&
            (!*vg->system_id ||
             strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id))))
                strncpy(vg->system_id, pvd->system_id, NAME_LEN);
index e650863b86e6f94fa8811e1222dd1a20c9830e39..45f46ab8882468a715f32cc213e6ac4af841aebb 100644 (file)
@@ -94,6 +94,10 @@ struct volume_group {
         /* logical volumes */
         uint32_t lv_count;
        struct list lvs;
+
+       /* snapshots */
+       uint32_t snapshot_count;
+       struct list snapshots;
 };
 
 struct stripe_segment {
@@ -128,6 +132,14 @@ struct logical_volume {
        struct list segments;
 };
 
+struct snapshot {
+       int persistent;         /* boolean */
+       uint32_t chunk_size;    /* in 512 byte sectors */
+
+       struct logical_volume *origin;
+       struct logical_volume *cow;
+};
+
 struct name_list {
        struct list list;
        char *name;
@@ -143,6 +155,12 @@ struct lv_list {
        struct logical_volume *lv;
 };
 
+struct snapshot_list {
+       struct list list;
+
+       struct snapshot *snapshot;
+};
+
 struct format_instance {
        struct cmd_context *cmd;
        struct format_handler *ops;
@@ -315,4 +333,19 @@ int lv_check_segments(struct logical_volume *lv);
 int lv_merge_segments(struct logical_volume *lv);
 
 
+/*
+ * Useful functions for managing snapshots.
+ */
+int lv_is_origin(struct volume_group *vg, struct logical_volume *lv);
+int lv_is_cow(struct volume_group *vg, struct logical_volume *lv);
+
+int vg_add_snapshot(struct volume_group *vg,
+                   struct logical_volume *origin,
+                   struct logical_volume *cow,
+                   int persistent,
+                   uint32_t chunk_size);
+
+int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow);
+
+
 #endif
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
new file mode 100644 (file)
index 0000000..ab681c1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the LGPL.
+ */
+
+#include "log.h"
+#include "metadata.h"
+#include "toolcontext.h"
+
+int lv_is_origin(struct volume_group *vg, struct logical_volume *lv)
+{
+       struct list *slh;
+       struct snapshot *s;
+
+       list_iterate (slh, &vg->snapshots) {
+               s = list_item(slh, struct snapshot_list)->snapshot;
+               if (s->origin == lv)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int lv_is_cow(struct volume_group *vg, struct logical_volume *lv)
+{
+       struct list *slh;
+       struct snapshot *s;
+
+       list_iterate (slh, &vg->snapshots) {
+               s = list_item(slh, struct snapshot_list)->snapshot;
+               if (s->cow == lv)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int vg_add_snapshot(struct volume_group *vg,
+                   struct logical_volume *origin,
+                   struct logical_volume *cow,
+                   int persistent,
+                   uint32_t chunk_size)
+{
+       struct snapshot *s;
+       struct snapshot_list *sl;
+       struct pool *mem = vg->cmd->mem;
+
+       /*
+        * Is the cow device already being used ?
+        */
+       if (lv_is_cow(vg, cow)) {
+               log_err("'%s' is already in use as a snapshot.", cow->name);
+               return 0;
+       }
+
+       if (!(s = pool_alloc(mem, sizeof(*s)))) {
+               stack;
+               return 0;
+       }
+
+       s->persistent = persistent;
+       s->chunk_size = chunk_size;
+       s->origin = origin;
+       s->cow = cow;
+
+       if (!(sl = pool_alloc(mem, sizeof(*sl)))) {
+               stack;
+               pool_free(mem, s);
+               return 0;
+       }
+
+       sl->snapshot = s;
+       list_add(&vg->snapshots, &sl->list);
+
+       return 1;
+}
+
+int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow)
+{
+       struct list *slh;
+       struct snapshot_list *sl;
+
+       list_iterate (slh, &vg->snapshots) {
+               sl = list_item(slh, struct snapshot_list);
+
+               if (sl->snapshot->cow == cow) {
+                       list_del(slh);
+                       return 1;
+               }
+       }
+
+       /* fail */
+       log_err("Asked to remove an unknow snapshot.");
+       return 0;
+}
This page took 0.042223 seconds and 5 git commands to generate.