diff options
author | Patrick Caulfield <pcaulfie@redhat.com> | 2002-01-11 10:39:56 +0000 |
---|---|---|
committer | Patrick Caulfield <pcaulfie@redhat.com> | 2002-01-11 10:39:56 +0000 |
commit | 391f02b1b566ba90bec541bca6e199e8f119e76f (patch) | |
tree | 6ec2bd1dcfc5f03fd3df7f67b70cd3241c95588f /lib/label | |
parent | e3851db2160aa4fa9b9f891dbf27b216a025a1ff (diff) | |
download | lvm2-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.c | 220 | ||||
-rw-r--r-- | lib/label/lvm2_label.h | 10 |
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, §size)) 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, §size)) + 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); |