Hi Vincent, On Thu, Jan 22, 2009 at 01:59:25PM +1100, Vincent McIntyre wrote: [..snip..] > We then cleared the multipath setup and redid it by hand, > running the new version of kpartx. Everything else used the programs > in multipath-tools_0.4.7-1. This created a partition of the correct size. Thanks a lot for you detailed report. Looking at upstream git this was fixed in commit 65d108fbe1bedbc2ef2da07049d174eb88896435 I've attached that commit to this mail (it applies to Debian's 0.4.8 as well). Could you try that one? It's very similar to the gentoo version but a bit cleaner.
[..snip..] > A patch against debian's 0.4.8-13 is attached. We haven't tested it yet, > we would like some advice on what is likely to explode if we just build > the patched 0.4.8 on an 'etch' system and install it. You'll need an updated dmsetup/libdevmapper to make it work on lenny. Packages are available here: http://debian.bzed.de/etch-backports/ > We could install a lenny machine and test on that. That would probably be easier. -- Guido
commit 65d108fbe1bedbc2ef2da07049d174eb88896435 Author: Christophe Varoqui <christophe.varo...@free.fr> Date: Wed Oct 10 23:13:31 2007 +0200 [kpartx] use uint64_t to account slices start/size And thus support >2TB partitioned devices. Redhat patch, pushed by Gerald Nowitzky. diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c index 3e973aa..893d6dd 100644 --- a/kpartx/devmapper.c +++ b/kpartx/devmapper.c @@ -4,10 +4,12 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdint.h> #include <libdevmapper.h> #include <ctype.h> #include <linux/kdev_t.h> #include <errno.h> +#include "devmapper.h" #define UUID_PREFIX "part%d-" #define MAX_PREFIX_LEN 8 @@ -72,7 +74,7 @@ dm_simplecmd (int task, const char *name) { extern int dm_addmap (int task, const char *name, const char *target, - const char *params, unsigned long size, const char *uuid, int part) { + const char *params, uint64_t size, const char *uuid, int part) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; diff --git a/kpartx/devmapper.h b/kpartx/devmapper.h index ccdbead..2bd27d2 100644 --- a/kpartx/devmapper.h +++ b/kpartx/devmapper.h @@ -1,7 +1,7 @@ int dm_prereq (char *, int, int, int); int dm_simplecmd (int, const char *); -int dm_addmap (int, const char *, const char *, const char *, unsigned long, - char *, int); +int dm_addmap (int, const char *, const char *, const char *, uint64_t, + const char *, int); int dm_map_present (char *); char * dm_mapname(int major, int minor); dev_t dm_get_first_dep(char *devname); diff --git a/kpartx/gpt.c b/kpartx/gpt.c index dc846ca..047a829 100644 --- a/kpartx/gpt.c +++ b/kpartx/gpt.c @@ -36,6 +36,7 @@ #include <errno.h> #include <endian.h> #include <byteswap.h> +#include <linux/fs.h> #include "crc32.h" #if BYTE_ORDER == LITTLE_ENDIAN @@ -50,10 +51,18 @@ # define __cpu_to_le32(x) bswap_32(x) #endif +#ifndef BLKGETLASTSECT #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */ +#endif +#ifndef BLKGETSIZE #define BLKGETSIZE _IO(0x12,96) /* return device size */ +#endif +#ifndef BLKSSZGET #define BLKSSZGET _IO(0x12,104) /* get block device sector size */ +#endif +#ifndef BLKGETSIZE64 #define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */ +#endif struct blkdev_ioctl_param { unsigned int block; @@ -143,20 +152,14 @@ get_sector_size(int filedes) static uint64_t _get_num_sectors(int filedes) { - unsigned long sectors=0; int rc; -#if 0 - uint64_t bytes=0; + uint64_t bytes=0; - rc = ioctl(filedes, BLKGETSIZE64, &bytes); + rc = ioctl(filedes, BLKGETSIZE64, &bytes); if (!rc) return bytes / get_sector_size(filedes); -#endif - rc = ioctl(filedes, BLKGETSIZE, §ors); - if (rc) - return 0; - - return sectors; + + return 0; } /************************************************************ @@ -193,7 +196,7 @@ last_lba(int filedes) sectors = 1; } - return sectors - 1; + return sectors ? sectors - 1 : 0; } @@ -220,17 +223,22 @@ read_lba(int fd, uint64_t lba, void *buffer, size_t bytes) { int sector_size = get_sector_size(fd); off_t offset = lba * sector_size; + uint64_t lastlba; ssize_t bytesread; lseek(fd, offset, SEEK_SET); bytesread = read(fd, buffer, bytes); + lastlba = last_lba(fd); + if (!lastlba) + return bytesread; + /* Kludge. This is necessary to read/write the last block of an odd-sized disk, until Linux 2.5.x kernel fixes. This is only used by gpt.c, and only to read one sector, so we don't have to be fancy. */ - if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd)) { + if (!bytesread && !(lastlba & 1) && lba == lastlba) { bytesread = read_lastoddsector(fd, lba, buffer, bytes); } return bytesread; @@ -505,7 +513,8 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes) if (!gpt || !ptes) return 0; - lastlba = last_lba(fd); + if (!(lastlba = last_lba(fd))) + return 0; good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, &pptes); if (good_pgpt) { diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c index dbe2ee2..72ca81d 100644 --- a/kpartx/kpartx.c +++ b/kpartx/kpartx.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <stdint.h> #include <sys/stat.h> #include <sys/types.h> #include <ctype.h> @@ -366,16 +367,16 @@ main(int argc, char **argv){ slices[j].minor = m++; - printf("%s%s%d : 0 %lu %s %lu\n", + printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n", mapname, delim, j+1, - (unsigned long) slices[j].size, device, - (unsigned long) slices[j].start); + slices[j].size, device, + slices[j].start); } /* Loop to resolve contained slices */ d = c; while (c) { for (j = 0; j < n; j++) { - unsigned long start; + uint64_t start; int k = slices[j].container - 1; if (slices[j].size == 0) @@ -387,9 +388,9 @@ main(int argc, char **argv){ slices[j].minor = m++; start = slices[j].start - slices[k].start; - printf("%s%s%d : 0 %lu /dev/dm-%d %lu\n", + printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n", mapname, delim, j+1, - (unsigned long) slices[j].size, + slices[j].size, slices[k].minor, start); c--; } @@ -448,8 +449,8 @@ main(int argc, char **argv){ } strip_slash(partname); - if (safe_sprintf(params, "%s %lu", device, - (unsigned long)slices[j].start)) { + if (safe_sprintf(params, "%s %" PRIu64 , + device, slices[j].start)) { fprintf(stderr, "params too small\n"); exit(1); } @@ -468,7 +469,7 @@ main(int argc, char **argv){ &slices[j].minor); if (verbose) - printf("add map %s (%d:%d): 0 %lu %s %s\n", + printf("add map %s (%d:%d): 0 %" PRIu64 " %s %s\n", partname, slices[j].major, slices[j].minor, slices[j].size, DM_TARGET, params); @@ -502,10 +503,10 @@ main(int argc, char **argv){ } strip_slash(partname); - if (safe_sprintf(params, "%d:%d %lu", + if (safe_sprintf(params, "%d:%d %" PRIu64, slices[k].major, slices[k].minor, - (unsigned long)slices[j].start)) { + slices[j].start)) { fprintf(stderr, "params too small\n"); exit(1); } @@ -524,7 +525,7 @@ main(int argc, char **argv){ &slices[j].minor); if (verbose) - printf("add map %s : 0 %lu %s %s\n", + printf("add map %s : 0 %" PRIu64 " %s %s\n", partname, slices[j].size, DM_TARGET, params); c--; diff --git a/kpartx/kpartx.h b/kpartx/kpartx.h index 9b3aeca..43ae3f8 100644 --- a/kpartx/kpartx.h +++ b/kpartx/kpartx.h @@ -1,6 +1,8 @@ #ifndef _KPARTX_H #define _KPARTX_H +#include <stdint.h> + /* * For each partition type there is a routine that takes * a block device and a range, and returns the list of @@ -20,8 +22,8 @@ * units: 512 byte sectors */ struct slice { - unsigned long start; - unsigned long size; + uint64_t start; + uint64_t size; int container; int major; int minor;