]> sourceware.org Git - lvm2.git/commitdiff
Move from 2-step to 3-step on-disk metadata commit.
authorAlasdair Kergon <agk@redhat.com>
Wed, 6 Apr 2005 18:59:55 +0000 (18:59 +0000)
committerAlasdair Kergon <agk@redhat.com>
Wed, 6 Apr 2005 18:59:55 +0000 (18:59 +0000)
WHATS_NEW
lib/format_text/format-text.c
lib/metadata/metadata.c
lib/metadata/metadata.h

index e2b7464d595da3b2d819ba7342511978339b97c7..c6facc32de9b70efb6e47d87492cbfb4d2c476c1 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.01.10 - 
 ================================
+  Move from 2-step to 3-step on-disk metadata commit.
   Scan ramdisks too.
   Annotate, tidy and extend list.h.
   Alignment tidying.
index 34eef5b4adb804ead9aee7923326773d4bd11549..7f630bad1db06cb03a707da0ac40844d0650d45d 100644 (file)
@@ -183,27 +183,30 @@ static int _raw_write_mda_header(const struct format_type *fmt,
 
 static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
                                       struct mda_header *mdah,
-                                      const char *vgname)
+                                      const char *vgname,
+                                      int precommit)
 {
        size_t len;
        char vgnamebuf[NAME_LEN + 2];
        struct raw_locn *rlocn;
        struct lvmcache_info *info;
 
-       rlocn = mdah->raw_locns;
+       rlocn = mdah->raw_locns;        /* Slot 0 */
+
+       if (precommit)
+               rlocn++;                /* Slot 1 */
 
+       /* FIXME Loop through rlocns two-at-a-time.  List null-terminated. */
        /* FIXME Ignore if checksum incorrect!!! */
-       while (rlocn->offset) {
-               if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
-                             sizeof(vgnamebuf), vgnamebuf)) {
-                       stack;
-                       goto error;
-               }
-               if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
-                   (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
-                       return rlocn;
-               }
-               rlocn++;
+       if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
+                     sizeof(vgnamebuf), vgnamebuf)) {
+               stack;
+               goto error;
+       }
+
+       if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
+           (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
+               return rlocn;
        }
 
       error:
@@ -247,7 +250,7 @@ static int _raw_holds_vgname(struct format_instance *fid,
                return 0;
        }
 
-       if (_find_vg_rlocn(dev_area, mdah, vgname))
+       if (_find_vg_rlocn(dev_area, mdah, vgname, 0))
                r = 1;
 
        if (!dev_close(dev_area->dev))
@@ -258,7 +261,8 @@ static int _raw_holds_vgname(struct format_instance *fid,
 
 static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
                                              const char *vgname,
-                                             struct device_area *area)
+                                             struct device_area *area,
+                                             int precommit)
 {
        struct volume_group *vg = NULL;
        struct raw_locn *rlocn;
@@ -277,7 +281,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
                goto out;
        }
 
-       if (!(rlocn = _find_vg_rlocn(area, mdah, vgname))) {
+       if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, precommit))) {
                log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
                goto out;
        }
@@ -301,8 +305,9 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
                stack;
                goto out;
        }
-       log_debug("Read %s metadata (%u) from %s at %" PRIu64 " size %" PRIu64,
-                 vg->name, vg->seqno, dev_name(area->dev),
+       log_debug("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
+                 PRIu64, vg->name, precommit ? "pre-commit " : "",
+                 vg->seqno, dev_name(area->dev),
                  area->start + rlocn->offset, rlocn->size);
 
       out:
@@ -318,7 +323,16 @@ static struct volume_group *_vg_read_raw(struct format_instance *fid,
 {
        struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
 
-       return _vg_read_raw_area(fid, vgname, &mdac->area);
+       return _vg_read_raw_area(fid, vgname, &mdac->area, 0);
+}
+
+static struct volume_group *_vg_read_precommit_raw(struct format_instance *fid,
+                                                  const char *vgname,
+                                                  struct metadata_area *mda)
+{
+       struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
+
+       return _vg_read_raw_area(fid, vgname, &mdac->area, 1);
 }
 
 static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
@@ -358,7 +372,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
                goto out;
        }
 
-       rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name);
+       rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0);
        mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
 
        if (!(mdac->rlocn.size = text_vg_export_raw(vg, "", buf, sizeof(buf)))) {
@@ -424,8 +438,10 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
        return r;
 }
 
-static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
-                         struct metadata_area *mda)
+static int _vg_commit_raw_rlocn(struct format_instance *fid,
+                               struct volume_group *vg,
+                               struct metadata_area *mda,
+                               int precommit)
 {
        struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
        struct mda_header *mdah;
@@ -452,18 +468,23 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
                goto out;
        }
 
-       if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name))) {
-               rlocn = &mdah->raw_locns[0];
+       if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0))) {
+               mdah->raw_locns[0].offset = 0;
                mdah->raw_locns[1].offset = 0;
+               mdah->raw_locns[2].offset = 0;
+               rlocn = &mdah->raw_locns[0];
        }
 
+       if (precommit)
+               rlocn++;
+
        rlocn->offset = mdac->rlocn.offset;
        rlocn->size = mdac->rlocn.size;
        rlocn->checksum = mdac->rlocn.checksum;
 
-       log_debug("Committing %s metadata (%u) to %s header at %" PRIu64,
-                 vg->name, vg->seqno, dev_name(mdac->area.dev),
-                 mdac->area.start);
+       log_debug("%sCommitting %s metadata (%u) to %s header at %" PRIu64,
+                 precommit ? "Pre-" : "", vg->name, vg->seqno,
+                 dev_name(mdac->area.dev), mdac->area.start);
        if (!_raw_write_mda_header(fid->fmt, mdac->area.dev, mdac->area.start,
                                   mdah)) {
                log_error("Failed to write metadata area header");
@@ -473,12 +494,25 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
        r = 1;
 
       out:
-       if (!dev_close(mdac->area.dev))
+       if (!precommit && !dev_close(mdac->area.dev))
                stack;
 
        return r;
 }
 
+static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
+                         struct metadata_area *mda)
+{
+       return _vg_commit_raw_rlocn(fid, vg, mda, 0);
+}
+
+static int _vg_precommit_raw(struct format_instance *fid,
+                            struct volume_group *vg,
+                            struct metadata_area *mda)
+{
+       return _vg_commit_raw_rlocn(fid, vg, mda, 1);
+}
+
 /* Close metadata area devices */
 static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
                          struct metadata_area *mda)
@@ -524,7 +558,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
                goto out;
        }
 
-       if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name))) {
+       if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0))) {
                rlocn = &mdah->raw_locns[0];
                mdah->raw_locns[1].offset = 0;
        }
@@ -550,13 +584,13 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
 
 static struct volume_group *_vg_read_file_name(struct format_instance *fid,
                                               const char *vgname,
-                                              const char *path_live)
+                                              const char *read_path)
 {
        struct volume_group *vg;
        time_t when;
        char *desc;
 
-       if (!(vg = text_vg_import_file(fid, path_live, &when, &desc))) {
+       if (!(vg = text_vg_import_file(fid, read_path, &when, &desc))) {
                stack;
                return NULL;
        }
@@ -569,10 +603,10 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
        if (vgname && strcmp(vgname, vg->name)) {
                pool_free(fid->fmt->cmd->mem, vg);
                log_err("'%s' does not contain volume group '%s'.",
-                       path_live, vgname);
+                       read_path, vgname);
                return NULL;
        } else
-               log_debug("Read volume group %s from %s", vg->name, path_live);
+               log_debug("Read volume group %s from %s", vg->name, read_path);
 
        return vg;
 }
@@ -586,6 +620,15 @@ static struct volume_group *_vg_read_file(struct format_instance *fid,
        return _vg_read_file_name(fid, vgname, tc->path_live);
 }
 
+static struct volume_group *_vg_read_precommit_file(struct format_instance *fid,
+                                                   const char *vgname,
+                                                   struct metadata_area *mda)
+{
+       struct text_context *tc = (struct text_context *) mda->metadata_locn;
+
+       return _vg_read_file_name(fid, vgname, tc->path_edit);
+}
+
 static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
                          struct metadata_area *mda)
 {
@@ -857,7 +900,7 @@ static int _scan_raw(const struct format_type *fmt)
                if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
                                    sizeof(vgnamebuf))) {
                        if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
-                                                   &rl->dev_area)))
+                                                   &rl->dev_area, 0)))
                                lvmcache_update_vg(vg);
                }
        }
@@ -1279,6 +1322,7 @@ static void _destroy(const struct format_type *fmt)
 
 static struct metadata_area_ops _metadata_text_file_ops = {
        vg_read:_vg_read_file,
+       vg_read_precommit:_vg_read_precommit_file,
        vg_write:_vg_write_file,
        vg_remove:_vg_remove_file,
        vg_commit:_vg_commit_file
@@ -1293,8 +1337,10 @@ static struct metadata_area_ops _metadata_text_file_backup_ops = {
 
 static struct metadata_area_ops _metadata_text_raw_ops = {
        vg_read:_vg_read_raw,
+       vg_read_precommit:_vg_read_precommit_raw,
        vg_write:_vg_write_raw,
        vg_remove:_vg_remove_raw,
+       vg_precommit:_vg_precommit_raw,
        vg_commit:_vg_commit_raw,
        vg_revert:_vg_revert_raw
 };
@@ -1650,7 +1696,8 @@ struct format_type *create_text_format(struct cmd_context *cmd)
        fmt->ops = &_text_handler;
        fmt->name = FMT_TEXT_NAME;
        fmt->alias = FMT_TEXT_ALIAS;
-       fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_UNLIMITED_VOLS;
+       fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
+                       FMT_UNLIMITED_VOLS;
 
        if (!(mda_lists = dbg_malloc(sizeof(struct mda_lists)))) {
                log_error("Failed to allocate dir_list");
index d7a3a8be266d2edd41fc3d841e7d6624ea87692b..2af54c07b248bbd600b0da217acb7bef8ff54f18 100644 (file)
@@ -507,6 +507,7 @@ int vg_write(struct volume_group *vg)
                        /* Revert */
                        list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
                                mda = list_item(mdah2, struct metadata_area);
+
                                if (mda->ops->vg_revert &&
                                    !mda->ops->vg_revert(vg->fid, vg, mda)) {
                                        stack;
@@ -528,6 +529,24 @@ int vg_write(struct volume_group *vg)
                }
        }
 
+       /* Now pre-commit each copy of the new metadata */
+       list_iterate(mdah, &vg->fid->metadata_areas) {
+               mda = list_item(mdah, struct metadata_area);
+               if (mda->ops->vg_precommit &&
+                   !mda->ops->vg_precommit(vg->fid, vg, mda)) {
+                       stack;
+                       /* Revert */
+                       list_iterate(mdah2, &vg->fid->metadata_areas) {
+                               mda = list_item(mdah2, struct metadata_area);
+                               if (mda->ops->vg_revert &&
+                                   !mda->ops->vg_revert(vg->fid, vg, mda)) {
+                                       stack;
+                               }
+                       }
+                       return 0;
+               }
+       }
+
        return 1;
 }
 
@@ -630,8 +649,9 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
  * and take appropriate action if it isn't (e.g. abort; get write lock 
  * and call vg_read again).
  */
-struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
-                            int *consistent)
+static struct volume_group *_vg_read(struct cmd_context *cmd,
+                                    const char *vgname,
+                                    int *consistent, int precommitted)
 {
        struct format_instance *fid;
        const struct format_type *fmt;
@@ -641,6 +661,11 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
        int inconsistent = 0;
 
        if (!*vgname) {
+               if (precommitted) {
+                       log_error("Internal error: vg_read requires vgname "
+                                 "with pre-commit.");
+                       return NULL;
+               }
                *consistent = 1;
                return _vg_read_orphans(cmd);
        }
@@ -662,6 +687,12 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
                }
        }
 
+       if (precommitted && !(fmt->features & FMT_PRECOMMIT)) {
+               log_error("Internal error: %s doesn't support "
+                         "pre-commit", fmt->name);
+               return NULL;
+       }
+
        /* create format instance with appropriate metadata area */
        if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
                log_error("Failed to create format instance");
@@ -671,7 +702,10 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
        /* Ensure contents of all metadata areas match - else do recovery */
        list_iterate(mdah, &fid->metadata_areas) {
                mda = list_item(mdah, struct metadata_area);
-               if (!(vg = mda->ops->vg_read(fid, vgname, mda))) {
+               if ((precommitted &&
+                    !(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
+                   (!precommitted &&
+                    !(vg = mda->ops->vg_read(fid, vgname, mda)))) {
                        inconsistent = 1;
                        continue;
                }
@@ -697,6 +731,12 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
                        return NULL;
                }
 
+               if (precommitted && !(fmt->features & FMT_PRECOMMIT)) {
+                       log_error("Internal error: %s doesn't support "
+                                 "pre-commit", fmt->name);
+                       return NULL;
+               }
+
                /* create format instance with appropriate metadata area */
                if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
                        log_error("Failed to create format instance");
@@ -706,7 +746,11 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
                /* Ensure contents of all metadata areas match - else recover */
                list_iterate(mdah, &fid->metadata_areas) {
                        mda = list_item(mdah, struct metadata_area);
-                       if (!(vg = mda->ops->vg_read(fid, vgname, mda))) {
+                       if ((precommitted &&
+                            !(vg = mda->ops->vg_read_precommit(fid, vgname,
+                                                               mda))) ||
+                           (!precommitted &&
+                            !(vg = mda->ops->vg_read(fid, vgname, mda)))) {
                                inconsistent = 1;
                                continue;
                        }
@@ -732,6 +776,12 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
        lvmcache_update_vg(correct_vg);
 
        if (inconsistent) {
+               if (precommitted) {
+                       log_error("Inconsistent pre-commit metadata copies "
+                                 "for volume group %s", vgname);
+                       return NULL;
+               }
+
                if (!*consistent)
                        return correct_vg;
 
@@ -769,6 +819,19 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
        return correct_vg;
 }
 
+struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
+                            int *consistent)
+{
+       return _vg_read(cmd, vgname, consistent, 0);
+}
+
+struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
+                                         const char *vgname,
+                                         int *consistent)
+{
+       return _vg_read(cmd, vgname, consistent, 1);
+}
+
 /* This is only called by lv_from_lvid, which is only called from 
  * activate.c so we know the appropriate VG lock is already held and 
  * the vg_read is therefore safe.
index 17c6d3e5ba5b531f8e5160f3b535e5052ffd79b8..437c45ec5b548f0d78bd1921327b83e21249a4e5 100644 (file)
@@ -68,6 +68,7 @@
 #define FMT_UNLIMITED_VOLS     0x00000008      /* Unlimited PVs/LVs? */
 #define FMT_RESTRICTED_LVIDS   0x00000010      /* LVID <= 255 */
 #define FMT_ORPHAN_ALLOCATABLE 0x00000020      /* Orphan PV allocatable? */
+#define FMT_PRECOMMIT          0x00000040      /* Supports pre-commit? */
 
 typedef enum {
        ALLOC_INVALID,
@@ -124,6 +125,9 @@ struct metadata_area_ops {
        struct volume_group *(*vg_read) (struct format_instance * fi,
                                         const char *vg_name,
                                         struct metadata_area * mda);
+       struct volume_group *(*vg_read_precommit) (struct format_instance * fi,
+                                        const char *vg_name,
+                                        struct metadata_area * mda);
        /*
         * Write out complete VG metadata.  You must ensure internal
         * consistency before calling. eg. PEs can't refer to PVs not
@@ -140,6 +144,9 @@ struct metadata_area_ops {
         */
        int (*vg_write) (struct format_instance * fid, struct volume_group * vg,
                         struct metadata_area * mda);
+       int (*vg_precommit) (struct format_instance * fid,
+                            struct volume_group * vg,
+                            struct metadata_area * mda);
        int (*vg_commit) (struct format_instance * fid,
                          struct volume_group * vg, struct metadata_area * mda);
        int (*vg_revert) (struct format_instance * fid,
@@ -374,6 +381,9 @@ int vg_commit(struct volume_group *vg);
 int vg_revert(struct volume_group *vg);
 struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
                             int *consistent);
+struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
+                                         const char *vg_name,
+                                         int *consistent);
 struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid);
 struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
                                struct list *mdas, uint64_t *label_sector,
This page took 0.053183 seconds and 5 git commands to generate.