summaryrefslogtreecommitdiffstats
path: root/lib/label
diff options
context:
space:
mode:
authorPatrick Caulfield <pcaulfie@redhat.com>2002-01-11 10:39:56 +0000
committerPatrick Caulfield <pcaulfie@redhat.com>2002-01-11 10:39:56 +0000
commit391f02b1b566ba90bec541bca6e199e8f119e76f (patch)
tree6ec2bd1dcfc5f03fd3df7f67b70cd3241c95588f /lib/label
parente3851db2160aa4fa9b9f891dbf27b216a025a1ff (diff)
downloadlvm2-391f02b1b566ba90bec541bca6e199e8f119e76f.tar.gz
lvm2-391f02b1b566ba90bec541bca6e199e8f119e76f.tar.xz
lvm2-391f02b1b566ba90bec541bca6e199e8f119e76f.zip
Change lvm2_label to use Joe's new label switch system.
Diffstat (limited to 'lib/label')
-rw-r--r--lib/label/lvm2_label.c220
-rw-r--r--lib/label/lvm2_label.h10
2 files changed, 133 insertions, 97 deletions
diff --git a/lib/label/lvm2_label.c b/lib/label/lvm2_label.c
index 1ea94be0..dbb25b13 100644
--- a/lib/label/lvm2_label.c
+++ b/lib/label/lvm2_label.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001 Sistina Software
+ * Copyright (C) 2001-2002 Sistina Software
*
* This file is released under the LGPL.
*/
@@ -13,9 +13,11 @@
#include "device.h"
#include "dev-cache.h"
#include "log.h"
+#include "pool.h"
+#include "dbg_malloc.h"
#include "filter.h"
#include "label.h"
-#include "pool.h"
+#include "lvm2_label.h"
#include "xlate.h"
/* Label Magic is "LnXl" - error: imagination failure */
@@ -24,10 +26,7 @@
/* Size of blocks that dev_get_size() returns the number of */
#define BLOCK_SIZE 512
-/* Our memory pool */
-static void *label_pool = NULL;
-
-/* This is just the "struct label" with the data pointer removed */
+/* This is just the "struct lvm2_label" with the data pointer removed */
struct label_ondisk
{
uint32_t magic;
@@ -53,13 +52,13 @@ struct filter_private
/* Calculate CRC32 of a buffer */
static uint32_t crc32(uint32_t initial, const unsigned char *databuf, size_t datalen)
{
- uint32_t idx, crc = initial;
static const u_int crctab[] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
+ uint32_t idx, crc = initial;
for (idx = 0; idx < datalen; idx++) {
crc ^= *databuf++;
@@ -70,15 +69,17 @@ static uint32_t crc32(uint32_t initial, const unsigned char *databuf, size_t dat
}
/* Calculate crc */
-static uint32_t calc_crc(struct label *label)
+static uint32_t calc_crc(struct label_ondisk *label, char *data)
{
uint32_t crcval = 0xffffffff;
crcval = crc32(crcval, (char *)&label->magic, sizeof(label->magic));
+ crcval = crc32(crcval, (char *)&label->label1_loc, sizeof(label->label1_loc));
+ crcval = crc32(crcval, (char *)&label->label2_loc, sizeof(label->label2_loc));
crcval = crc32(crcval, (char *)&label->datalen, sizeof(label->datalen));
- crcval = crc32(crcval, (char *)label->disk_type, strlen(label->disk_type));
crcval = crc32(crcval, (char *)&label->version, sizeof(label->version));
- crcval = crc32(crcval, (char *)label->data, label->datalen);
+ crcval = crc32(crcval, (char *)label->disk_type, strlen(label->disk_type));
+ crcval = crc32(crcval, (char *)data, label->datalen);
return crcval;
}
@@ -90,10 +91,8 @@ static inline void get_label_locations(uint64_t size, uint32_t sectsize, long *f
*second = size*BLOCK_SIZE - sectsize;
}
-/* Read a label off disk - the data area is allocated
- from the pool in label->pool and should be freed by
- the caller */
-int label_read(struct device *dev, struct label *label)
+/* Read a label off disk */
+static int lvm2_label_read(struct labeller *l, struct device *dev, struct label **label)
{
uint64_t size;
uint32_t sectsize;
@@ -112,10 +111,7 @@ int label_read(struct device *dev, struct label *label)
if (!dev_open(dev, O_RDONLY))
return 0;
- if (label_pool == NULL)
- label_pool = pool_create(BLOCK_SIZE);
-
- block = pool_alloc(label_pool, sectsize);
+ block = dbg_malloc(sectsize);
if (!block)
{
stack;
@@ -130,7 +126,7 @@ int label_read(struct device *dev, struct label *label)
status = dev_read(dev, offset[iter], sectsize, block);
if (status)
{
- struct label incore;
+ struct label *incore;
int i;
int found_nul;
@@ -149,62 +145,64 @@ int label_read(struct device *dev, struct label *label)
if (!found_nul)
continue;
+ incore = dbg_malloc(sizeof(struct label));
+ if (incore == NULL)
+ {
+ return 0;
+ }
+
/* Copy and convert endianness */
- strncpy(incore.disk_type, ondisk->disk_type, sizeof(incore.disk_type));
- incore.magic = xlate32(ondisk->magic);
- incore.version[0] = xlate32(ondisk->version[0]);
- incore.version[1] = xlate32(ondisk->version[1]);
- incore.version[2] = xlate32(ondisk->version[2]);
- incore.label1_loc = xlate64(ondisk->label1_loc);
- incore.label2_loc = xlate64(ondisk->label2_loc);
- incore.datalen = xlate16(ondisk->datalen);
- incore.data = block + sizeof(struct label_ondisk);
- incore.crc = xlate32(ondisk->crc);
+ strncpy(incore->volume_type, ondisk->disk_type, sizeof(incore->volume_type));
+ incore->version[0] = xlate32(ondisk->version[0]);
+ incore->version[1] = xlate32(ondisk->version[1]);
+ incore->version[2] = xlate32(ondisk->version[2]);
+ incore->extra_len = xlate16(ondisk->datalen);
+ incore->extra_info = block + sizeof(struct label_ondisk);
/* Make sure datalen is a sensible size too */
- if (incore.datalen > sectsize)
+ if (incore->extra_len > sectsize)
continue;
/* Check Crc */
- if (incore.crc != calc_crc(&incore))
+ if (xlate32(ondisk->crc) != calc_crc(ondisk, incore->extra_info))
{
log_error("Crc %d on device %s does not match. got %x, expected %x",
- iter, dev_name(dev), incore.crc, calc_crc(&incore));
+ iter, dev_name(dev), xlate32(ondisk->crc), calc_crc(ondisk, incore->extra_info));
continue;
}
/* Check label locations match our view of the device */
- if (incore.label1_loc != offset[0])
+ if (xlate64(ondisk->label1_loc) != offset[0])
log_error("Label 1 location is wrong in label %d - check block size of the device\n",
iter);
- if (incore.label2_loc != offset[1])
+ if (xlate64(ondisk->label2_loc) != offset[1])
log_error("Label 2 location is wrong in label %d - the size of the device must have changed\n",
iter);
/* Copy to user's data area */
*label = incore;
- label->data = pool_alloc(label_pool, incore.datalen);
- if (!label->data)
+ incore->extra_info = dbg_malloc(incore->extra_len);
+ if (!incore->extra_info)
{
stack;
return 0;
}
- memcpy(label->data, incore.data, incore.datalen);
+ memcpy(incore->extra_info, block + sizeof(struct label_ondisk), incore->extra_len);
- pool_free(label_pool, block);
+ dbg_free(block);
dev_close(dev);
return 1;
}
}
- pool_free(label_pool, block);
+ dbg_free(block);
dev_close(dev);
return 0;
}
/* Write a label to a device */
-int label_write(struct device *dev, struct label *label)
+static int lvm2_label_write(struct labeller *l, struct device *dev, struct label *label)
{
uint64_t size;
uint32_t sectsize;
@@ -220,13 +218,10 @@ int label_write(struct device *dev, struct label *label)
return 0;
/* Can the metata fit in the remaining space ? */
- if (label->datalen > sectsize - sizeof(struct label_ondisk))
+ if (label->extra_len > sectsize - sizeof(struct label_ondisk))
return 0;
- if (label_pool == NULL)
- label_pool = pool_create(BLOCK_SIZE);
-
- block = pool_alloc(label_pool, sizeof(struct label_ondisk) + label->datalen);
+ block = dbg_malloc(sizeof(struct label_ondisk) + label->extra_len);
if (!block)
{
stack;
@@ -234,11 +229,6 @@ int label_write(struct device *dev, struct label *label)
}
ondisk = (struct label_ondisk *)block;
- /* Make sure the label has the right magic number in it */
- label->magic = LABEL_MAGIC;
- label->label1_loc = offset[0];
- label->label2_loc = offset[1];
-
get_label_locations(size, sectsize, &offset[0], &offset[1]);
/* Make into ondisk format */
@@ -248,24 +238,24 @@ int label_write(struct device *dev, struct label *label)
ondisk->version[2] = xlate32(label->version[2]);
ondisk->label1_loc = xlate64(offset[0]);
ondisk->label2_loc = xlate64(offset[1]);
- ondisk->datalen = xlate16(label->datalen);
- strncpy(ondisk->disk_type, label->disk_type, sizeof(ondisk->disk_type));
- memcpy(block+sizeof(struct label_ondisk), label->data, label->datalen);
- ondisk->crc = xlate32(calc_crc(label));
+ ondisk->datalen = xlate16(label->extra_len);
+ strncpy(ondisk->disk_type, label->volume_type, sizeof(ondisk->disk_type));
+ memcpy(block+sizeof(struct label_ondisk), label->extra_info, label->extra_len);
+ ondisk->crc = xlate32(calc_crc(ondisk, label->extra_info));
/* Write metadata to disk */
if (!dev_open(dev, O_RDWR))
{
- pool_free(label_pool, block);
+ dbg_free(block);
return 0;
}
- status1 = dev_write(dev, offset[0], sizeof(struct label_ondisk) + label->datalen, block);
+ status1 = dev_write(dev, offset[0], sizeof(struct label_ondisk) + label->extra_len, block);
if (!status1)
log_error("Error writing label 1\n");
/* Write another at the end of the device */
- status2 = dev_write(dev, offset[1], sizeof(struct label_ondisk) + label->datalen, block);
+ status2 = dev_write(dev, offset[1], sizeof(struct label_ondisk) + label->extra_len, block);
if (!status2)
{
char zerobuf[sizeof(struct label_ondisk)];
@@ -277,7 +267,7 @@ int label_write(struct device *dev, struct label *label)
log_error("Error erasing label 1\n");
}
- pool_free(label_pool, block);
+ dbg_free(block);
dev_close(dev);
return ((status1 != 0) && (status2 != 0));
@@ -286,13 +276,13 @@ int label_write(struct device *dev, struct label *label)
/* Return 1 for Yes, 0 for No */
-int is_labelled(struct device *dev)
+static int lvm2_is_labelled(struct labeller *l, struct device *dev)
{
- struct label l;
+ struct label *label;
int status;
- status = label_read(dev, &l);
- if (status) label_free(&l);
+ status = lvm2_label_read(l, dev, &label);
+ if (status) label_free(label);
return status;
}
@@ -300,35 +290,34 @@ int is_labelled(struct device *dev)
/* Check the device is labelled and has the right format_type */
static int _accept_format(struct dev_filter *f, struct device *dev)
{
- struct label l;
+ struct label *l;
int status;
struct filter_private *fp = (struct filter_private *) f->private;
- status = label_read(dev, &l);
- if (status) label_free(&l);
+ status = lvm2_label_read(NULL, dev, &l);
if (status)
{
- if (strcmp(l.disk_type, fp->disk_type) == 0)
+ if (strcmp(l->volume_type, fp->disk_type) == 0)
{
switch (fp->version_match)
{
case VERSION_MATCH_EQUAL:
- if (l.version[0] == fp->version[0] &&
- l.version[1] == fp->version[1] &&
- l.version[2] == fp->version[2])
+ if (l->version[0] == fp->version[0] &&
+ l->version[1] == fp->version[1] &&
+ l->version[2] == fp->version[2])
return 1;
break;
case VERSION_MATCH_LESSTHAN:
- if (l.version[0] == fp->version[0] &&
- l.version[1] < fp->version[1])
+ if (l->version[0] == fp->version[0] &&
+ l->version[1] < fp->version[1])
return 1;
break;
case VERSION_MATCH_LESSEQUAL:
- if (l.version[0] == fp->version[0] &&
- l.version[1] <= fp->version[1])
+ if (l->version[0] == fp->version[0] &&
+ l->version[1] <= fp->version[1])
return 1;
break;
@@ -336,6 +325,7 @@ static int _accept_format(struct dev_filter *f, struct device *dev)
return 1;
}
}
+ label_free(l);
}
return 0;
}
@@ -349,11 +339,10 @@ static int _accept_label(struct dev_filter *f, struct device *dev)
static void _destroy(struct dev_filter *f)
{
struct filter_private *fp = (struct filter_private *) f->private;
- pool_destroy(fp->mem);
}
/* A filter to find devices with a particular label type on them */
-struct dev_filter *label_format_filter_create(char *disk_type, uint32_t version[3], int match_type)
+struct dev_filter *lvm2_label_format_filter_create(char *disk_type, uint32_t version[3], int match_type)
{
struct pool *mem;
struct filter_private *fp;
@@ -400,7 +389,7 @@ struct dev_filter *label_format_filter_create(char *disk_type, uint32_t version[
}
/* A filter to find devices with any label on them */
-struct dev_filter *label_filter_create()
+struct dev_filter *lvm2_label_filter_create()
{
struct pool *mem = pool_create(10 * 1024);
struct filter_private *fp;
@@ -434,7 +423,7 @@ struct dev_filter *label_filter_create()
}
/* Return 1 if both labels are identical, 0 if not or there was an error */
-int labels_match(struct device *dev)
+static int lvm2_labels_match(struct labeller *l, struct device *dev)
{
uint64_t size;
uint32_t sectsize;
@@ -451,22 +440,19 @@ int labels_match(struct device *dev)
if (!dev_get_sectsize(dev, &sectsize))
return 0;
- if (label_pool == NULL)
- label_pool = pool_create(BLOCK_SIZE);
-
/* Allocate some space for the blocks we are going to read in */
- block1 = pool_alloc(label_pool, sectsize);
+ block1 = dbg_malloc(sectsize);
if (!block1)
{
stack;
return 0;
}
- block2 = pool_alloc(label_pool, sectsize);
+ block2 = dbg_malloc(sectsize);
if (!block2)
{
stack;
- pool_free(label_pool, block1);
+ dbg_free(block1);
return 0;
}
ondisk1 = (struct label_ondisk *)block1;
@@ -504,16 +490,72 @@ int labels_match(struct device *dev)
status = 1;
finish:
- pool_free(label_pool, block2);
- pool_free(label_pool, block1);
+ dbg_free(block2);
+ dbg_free(block1);
return status;
}
-/* Free data area allocated by label_read() */
-void label_free(struct label *label)
+static int lvm2_label_remove(struct labeller *l, struct device *dev)
+{
+ uint64_t size;
+ uint32_t sectsize;
+ char block[BLOCK_SIZE];
+ int status1, status2;
+ long offset[2];
+
+ if (!dev_get_size(dev, &size))
+ return 0;
+
+ if (!dev_get_sectsize(dev, &sectsize))
+ return 0;
+
+ if (!dev_open(dev, O_RDWR))
+ {
+ dbg_free(block);
+ return 0;
+ }
+
+ get_label_locations(size, sectsize, &offset[0], &offset[1]);
+ memset(block, 0, BLOCK_SIZE);
+
+ /* Blank out the first label */
+ status1 = dev_write(dev, offset[0], BLOCK_SIZE, block);
+ if (!status1)
+ log_error("Error erasing label 1\n");
+
+ /* ...and the other at the end of the device */
+ status2 = dev_write(dev, offset[1], BLOCK_SIZE, block);
+ if (!status2)
+ log_error("Error erasing label 2\n");
+
+ dev_close(dev);
+
+ return ((status1 != 0) && (status2 != 0));
+}
+
+static void lvm2_label_destroy(struct labeller *l)
{
- if (label->data)
- pool_free(label_pool, label->data);
}
+static struct label_ops handler_ops =
+{
+ can_handle: lvm2_is_labelled,
+ write: lvm2_label_write,
+ remove: lvm2_label_remove,
+ read: lvm2_label_read,
+ verify: lvm2_labels_match,
+ destroy: lvm2_label_destroy,
+};
+
+static struct labeller this_labeller =
+{
+ private : NULL,
+ ops : &handler_ops,
+};
+
+/* Don't know how this gets called... */
+void lvm2_init()
+{
+ label_register_handler("LVM2", &this_labeller);
+}
diff --git a/lib/label/lvm2_label.h b/lib/label/lvm2_label.h
index 8c64a46e..b901a889 100644
--- a/lib/label/lvm2_label.h
+++ b/lib/label/lvm2_label.h
@@ -4,7 +4,7 @@
* This file is released under the GPL.
*/
-struct label
+struct lvm2_label
{
uint32_t magic;
uint32_t crc;
@@ -15,7 +15,7 @@ struct label
char disk_type[32];
uint32_t version[3];
- char *data; /* Should be freed with label_free() */
+ char *data;
};
#define VERSION_MATCH_EQUAL 1
@@ -23,11 +23,5 @@ struct label
#define VERSION_MATCH_LESSEQUAL 3
#define VERSION_MATCH_ANY 4
-extern int label_write(struct device *dev, struct label *label);
-extern int label_read(struct device *dev, struct label *label);
-extern void label_free(struct label *label);
-extern int is_labelled(struct device *dev);
-extern int labels_match(struct device *dev);
-
extern struct dev_filter *label_filter_create();
extern struct dev_filter *label_format_filter_create(char *disk_type, uint32_t version[3], int match_type);