[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [patch 4/4] Update pvck to include text metadata area and record detection.



--
Index: LVM2-working2/lib/format_text/format-text.c
===================================================================
--- LVM2-working2.orig/lib/format_text/format-text.c	2007-04-23 14:21:01.000000000 -0400
+++ LVM2-working2/lib/format_text/format-text.c	2007-04-24 21:50:23.000000000 -0400
@@ -39,6 +39,9 @@
 #define FMT_TEXT_NAME "lvm2"
 #define FMT_TEXT_ALIAS "text"
 
+static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
+					       struct device_area *dev_area);
+
 static struct format_instance *_text_create_text_instance(const struct format_type
 						     *fmt, const char *vgname,
 						     const char *vgid,
@@ -96,6 +99,145 @@ static int _mda_in_vg_raw(struct format_
 	return 0;
 }
 
+/*
+ * Get sector number preceeding cur_sector in circular region
+ * [start, start+size]
+ */
+static uint64_t _get_prev_sector_circular(uint64_t start, uint64_t size,
+					 uint64_t cur_sector)
+{
+	if (cur_sector >= start + SECTOR_SIZE)
+		return cur_sector - SECTOR_SIZE;
+	else
+		return (start + size - SECTOR_SIZE);
+}
+
+/*
+ * Analyze a metadata area for old metadata records in the circular buffer.
+ * This function just looks through and makes a first pass at the data in
+ * the sectors for particular things.
+ * FIXME: do something with each metadata area (try to extract vg, write
+ * raw data to file, etc)
+ */
+static int _pv_analyze_mda_raw (const struct format_type * fmt,
+				struct metadata_area *mda)
+{
+	struct mda_header *mdah;
+	struct raw_locn *rlocn;
+	uint64_t area_start;
+	uint64_t area_size;
+	uint64_t prev_sector;
+	uint64_t latest_mrec_offset;
+	int i;
+	uint64_t offset;
+	uint64_t offset2;
+	uint64_t size;
+	uint64_t size2;
+	char *buf=NULL;
+	struct device_area *area;
+	struct mda_context *mdac;
+
+	mdac = (struct mda_context *) mda->metadata_locn;
+
+	log_print("Found text metadata area, start=%lld, size=%lld",
+		  mdac->area.start,
+		  mdac->area.size);
+	area = &mdac->area;
+
+	if (!dev_open(area->dev)) {
+		stack;
+		return 0;
+	}
+
+	if (!(mdah = _raw_read_mda_header(fmt, area))) {
+		stack;
+		goto error;
+	}
+	rlocn = mdah->raw_locns;
+
+	/*
+	 * The device area includes the metadata header as well as the
+	 * records, so remove the metadata header from the start and size
+	 */
+	area_start = area->start + MDA_HEADER_SIZE;
+	area_size = area->size - MDA_HEADER_SIZE;
+	latest_mrec_offset = rlocn->offset + area->start;
+
+	/*
+	 * Start searching at rlocn (point of live metadata) and go
+	 * backwards.
+	 */
+	prev_sector = _get_prev_sector_circular(area_start, area_size,
+					       latest_mrec_offset);
+	offset = prev_sector;
+	size = SECTOR_SIZE;
+	offset2 = size2 = 0;
+	i = 0;
+	while (prev_sector != latest_mrec_offset) {
+		prev_sector = _get_prev_sector_circular(area_start, area_size,
+							prev_sector);
+		/*
+		 * FIXME: for some reason, the whole metadata region from
+		 * area->start to area->start+area->size is not used.
+		 * Only ~32KB seems to contain valid metadata records
+		 * (LVM2 format - format_text).  As a result, I end up with
+		 * "maybe_config_section" returning true when there's no valid
+		 * metadata in a sector (sectors with all nulls).
+		 */
+		if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2))) {
+			stack;
+			goto error;
+		}
+		if (!dev_read_circular(area->dev, offset, size,
+				       offset2, size2, buf)) {
+			stack;
+			goto error;
+		}
+		/*
+		 * FIXME: We could add more sophisticated metadata detection
+		 */
+		if (maybe_config_section(buf, size+size2)) {
+			/* FIXME: Validate region, pull out timestamp?, etc */
+			/* FIXME: Do something with this region */
+			log_verbose ("Found LVM2 metadata record at "
+				     "offset=%lld, size=%lld, "
+				     "offset2=%lld size2=%lld",
+				     offset, size, offset2, size2);
+			offset = prev_sector;
+			size = SECTOR_SIZE;
+			offset2 = size2 = 0;
+		} else {
+			/*
+			 * Not a complete metadata record, assume we have
+			 * metadata and just increase the size and offset.
+			 * Start the second region if the previous sector is
+			 * wrapping around towards the end of the disk.
+			 */
+			if (prev_sector > offset) {
+				offset2 = prev_sector;
+				size2 += SECTOR_SIZE;
+			} else {
+				offset = prev_sector;
+				size += SECTOR_SIZE;
+			}
+		}
+		dm_pool_free(fmt->cmd->mem, buf);
+		buf = NULL;
+	}
+
+	if (!dev_close(area->dev))
+		stack;
+	return 1;
+ error:
+	if (buf)
+		dm_pool_free(fmt->cmd->mem, buf);
+	if (!dev_close(area->dev))
+		stack;
+	return 0;
+}
+
+
+
 static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
 			  struct logical_volume *lv)
 {
@@ -1413,6 +1555,7 @@ static struct metadata_area_ops _metadat
 	.vg_commit = _vg_commit_raw,
 	.vg_revert = _vg_revert_raw,
 	.mda_in_vg = _mda_in_vg_raw,
+	.pv_analyze_mda = _pv_analyze_mda_raw,
 };
 
 /* pvmetadatasize in sectors */
Index: LVM2-working2/lib/metadata/metadata.h
===================================================================
--- LVM2-working2.orig/lib/metadata/metadata.h	2007-04-24 09:49:39.000000000 -0400
+++ LVM2-working2/lib/metadata/metadata.h	2007-04-24 12:48:06.000000000 -0400
@@ -183,6 +183,12 @@ struct metadata_area_ops {
 	 */
 	int (*mda_in_vg) (struct format_instance * fi,
 			    struct volume_group * vg, struct metadata_area *mda);
+	/*
+	 * Analyze a metadata area on a PV.
+	 */
+	int (*pv_analyze_mda) (const struct format_type * fmt,
+			       struct metadata_area *mda);
+
 };
 
 struct metadata_area {
Index: LVM2-working2/lib/metadata/metadata.c
===================================================================
--- LVM2-working2.orig/lib/metadata/metadata.c	2007-04-24 09:49:39.000000000 -0400
+++ LVM2-working2/lib/metadata/metadata.c	2007-04-24 13:14:46.000000000 -0400
@@ -1565,6 +1565,8 @@ int pv_analyze(struct cmd_context *cmd, 
 {
 	struct label *label;
 	struct device *dev;
+	struct metadata_area *mda;
+	struct lvmcache_info *info;
 
 	dev = dev_cache_get(pv_name, cmd->filter);
 	if (!dev) {
@@ -1585,5 +1587,12 @@ int pv_analyze(struct cmd_context *cmd, 
 	log_print("Found label on %s, sector %"PRIu64", type=%s",
 		  pv_name, label->sector, label->type);
 
+	/*
+	 * Next, loop through metadata areas
+	 */
+	info = label->info;
+	list_iterate_items(mda, &info->mdas) {
+		mda->ops->pv_analyze_mda(info->fmt, mda);
+	}
 	return 1;
 }

--


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]