Bug#512601: multipath-tools: kpartx does not handle multi-Tb filesystems on i386

Vincent.McIntyre at csiro.au Vincent.McIntyre at csiro.au
Thu Jan 22 22:24:03 UTC 2009


On Thu, 22 Jan 2009, Guido Günther wrote:

> 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.

It is indeed a nicer patch.
I applied this to the pristine upstream source of 0.4.8 and redid
the test we did before. That worked fine as shown below.

starting state -
# parted /dev/sdd
# multipath -l
mpath0 (222a60001559596f8) dm-7 Promise,VTrak E610f
[size=9.5T][features=1 queue_if_no_path][hwhandler=0]
\_ round-robin 0 [prio=0][active]
   \_ 2:0:2:0 sdd 8:48  [active][undef]
   \_ 2:0:3:0 sde 8:64  [active][undef]
   \_ 2:0:4:0 sdf 8:80  [active][undef]
   \_ 2:0:5:0 sdg 8:96  [active][undef]
# parted /dev/mapper/mpath0 print

Disk /dev/mapper/mpath0: 10.5TB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system  Name     Flags
   1      17.4kB  10.5TB  10.5TB  xfs          primary

Information: Don't forget to update /etc/fstab, if necessary.

redo the kpartx -
# /etc/init.d/multipath-tools stop
Stopping multipath daemon.
# multipath -F
# ls /dev/mapper/mp*
ls: /dev/mapper/mp*: No such file or directory
# multipath -v2 -l
# ls /dev/mapper/mp*
ls: /dev/mapper/mp*: No such file or directory
# /etc/init.d/multipath-tools start
Starting multipath daemon.
# ls /dev/mapper/mp*
/dev/mapper/mpath0
# multipath -list
mpath0 (222a60001559596f8) dm-7 Promise,VTrak E610f
[size=9.5T][features=1 queue_if_no_path][hwhandler=0]
\_ round-robin 0 [prio=0][enabled]
   \_ 2:0:2:0 sdd 8:48  [active][undef]
   \_ 2:0:3:0 sde 8:64  [active][undef]
   \_ 2:0:4:0 sdf 8:80  [active][undef]
   \_ 2:0:5:0 sdg 8:96  [active][undef]
# strace -o /root/strace.kpartx.patched -f -s 2048 ./kpartx -a /dev/mapper/mpath0
# echo $?
0
# ls -l
/dev/mapper/mp*
brw-rw---- 1 root disk 254, 7 2009-01-23 08:30 /dev/mapper/mpath0
brw-rw---- 1 root disk 254, 8 2009-01-23 08:31 /dev/mapper/mpath0p1

# mkfs.xfs  -f -d agcount=16 /dev/mapper/mpath0p1
meta-data=/dev/mapper/mpath0p1   isize=256    agcount=16, agsize=160217232 
blks
           =                       sectsz=512   attr=0
data     =                       bsize=4096   blocks=2563475703, 
imaxpct=25
           =                       sunit=0      swidth=0 blks, unwritten=1
naming   =version 2              bsize=4096
log      =internal log           bsize=4096   blocks=32768, version=1
           =                       sectsz=512   sunit=0 blks
realtime =none                   extsz=65536  blocks=0, rtextents=0

# parted /dev/mapper/mpath0 print

Disk /dev/mapper/mpath0: 10.5TB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system  Name     Flags
   1      17.4kB  10.5TB  10.5TB  xfs          primary

Information: Don't forget to update /etc/fstab, if necessary.


# mount /dev/mapper/mpath0p1 /mnt
# df -k| grep mpath
/dev/mapper/mpath0p1 10253771740       544 10253771196   1% /mnt

whew.

> [..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.

I need to get it to work on 'etch', was your saying 'lenny' a typo?

> Packages are available here:
> http://debian.bzed.de/etch-backports/

I looked here. devmapper_1.02.24.orig.tar.gz seems to be missing.
Also the backport of multipath-tools is 0.4.8-7.

I assume I should just get devmapper_1.02.27-4 from the official
'testing' suite and use that with 0.4.8-13 from testing?

I tried to apply the git patch and build. That failed.
# tar zxf multipath-tools_0.4.8.orig.tar.gz
# zcat  multipath-tools_0.4.8-13.diff.gz |patch -p0
patching file multipath-tools-0.4.8/debian/changelog
patching file multipath-tools-0.4.8/debian/control
patching file multipath-tools-0.4.8/debian/multipath-tools.postinst
patching file multipath-tools-0.4.8/debian/compat
patching file multipath-tools-0.4.8/debian/copyright
patching file multipath-tools-0.4.8/debian/multipath-tools.examples
patching file multipath-tools-0.4.8/debian/multipath-tools.preinst
patching file multipath-tools-0.4.8/debian/multipath-tools.init
patching file multipath-tools-0.4.8/debian/rules
patching file multipath-tools-0.4.8/debian/multipath-tools.prerm
patching file multipath-tools-0.4.8/debian/NEWS
patching file multipath-tools-0.4.8/debian/dmsetup_env
patching file multipath-tools-0.4.8/debian/multipath-tools.install
patching file multipath-tools-0.4.8/debian/multipath-tools.docs
patching file multipath-tools-0.4.8/debian/multipath-tools.multipath-tools-boot.init
patching file multipath-tools-0.4.8/debian/multipath-udeb.install
patching file multipath-tools-0.4.8/debian/multipath.udev
patching file multipath-tools-0.4.8/debian/kpartx.install
patching file multipath-tools-0.4.8/debian/kpartx.manpages
patching file multipath-tools-0.4.8/debian/kpartx.postinst
patching file multipath-tools-0.4.8/debian/kpartx.udev
patching file multipath-tools-0.4.8/debian/watch
patching file multipath-tools-0.4.8/debian/multipath-tools.README.Debian
patching file multipath-tools-0.4.8/debian/multipath-tools-boot.postinst
patching file multipath-tools-0.4.8/debian/multipath-tools-boot.postrm
patching file multipath-tools-0.4.8/debian/README.source
patching file multipath-tools-0.4.8/debian/multipath-tools-boot.templates
patching file multipath-tools-0.4.8/debian/multipath-tools-boot.config
patching file multipath-tools-0.4.8/debian/patches/series
patching file multipath-tools-0.4.8/debian/patches/0001-get-rid-of-arch-specific-ifdef-spaghettis.patch
patching file multipath-tools-0.4.8/debian/patches/0002--libmultipath-filter_wwid-is-called-with-the-wron.patch
patching file multipath-tools-0.4.8/debian/patches/0003--kpartx-Fix-udev-rules-for-dmraid.patch
patching file multipath-tools-0.4.8/debian/patches/0004--kpartx-fix-extended-partition-handling.patch
patching file multipath-tools-0.4.8/debian/patches/0005--kpartx-remove-partitions-in-reverse-order.patch
patching file multipath-tools-0.4.8/debian/patches/0006--kpartx-documentation-fixes.patch
patching file multipath-tools-0.4.8/debian/patches/0007--kpartx-remove-dead-code.patch
patching file multipath-tools-0.4.8/debian/patches/0008-udev-as-of-0.124-doesn-t-support-scsi_id-s-anymor.patch
patching file multipath-tools-0.4.8/debian/patches/0009-blacklist-cciss-devices.patch
patching file multipath-tools-0.4.8/debian/initramfs/hooks
patching file multipath-tools-0.4.8/debian/initramfs/local-top
patching file multipath-tools-0.4.8/debian/reportbug/script
patching file multipath-tools-0.4.8/debian/po/POTFILES.in
patching file multipath-tools-0.4.8/debian/po/templates.pot
patching file multipath-tools-0.4.8/debian/po/pt.po
patching file multipath-tools-0.4.8/debian/po/de.po
patching file multipath-tools-0.4.8/debian/po/fr.po
patching file multipath-tools-0.4.8/debian/po/sv.po
patching file multipath-tools-0.4.8/debian/po/ru.po

here goes the git patch...

# cd multipath-tools-0.4.8/
# patch -p1 < /tmp/65d108f.diff.edited
patching file kpartx/devmapper.c
Hunk #2 succeeded at 74 with fuzz 1.
patching file kpartx/devmapper.h
patching file kpartx/gpt.c
patching file kpartx/kpartx.c
patching file kpartx/kpartx.h

try to build ...

# chmod +x debian/rules
# debian/rules binary
# quilt exits with 2 as return when there was nothing to do.
# That's not an error here (but it's usefull to break loops in crude scripts)
QUILT_PATCHES=debian/patches quilt --quiltrc /dev/null push -a || test $? = 2
Applying patch 0001-get-rid-of-arch-specific-ifdef-spaghettis.patch
patching file kpartx/lopart.c

Applying patch 
0002--libmultipath-filter_wwid-is-called-with-the-wron.patch
patching file libmultipath/blacklist.c

Applying patch 0003--kpartx-Fix-udev-rules-for-dmraid.patch
patching file kpartx/kpartx.rules

Applying patch 0004--kpartx-fix-extended-partition-handling.patch
patching file kpartx/kpartx.c
Hunk #1 succeeded at 266 (offset 1 line).
Hunk #2 FAILED at 388.
Hunk #3 succeeded at 432 (offset 1 line).
Hunk #4 succeeded at 478 (offset 1 line).
Hunk #5 succeeded at 489 (offset 1 line).
Hunk #6 FAILED at 504.
Hunk #7 FAILED at 527.
3 out of 7 hunks FAILED -- rejects in file kpartx/kpartx.c
Patch 0004--kpartx-fix-extended-partition-handling.patch does not apply 
(enforce with -f)
make: *** [debian/stamp-patched] Error 1

I slightly edited the diff file, it would not apply with the
'--git' option to diff included  and I had to remove the 'index' lines.
I've attached that and the kpartx.c I have ended up with.

Am I applying the git patch too early?

>> We could install a lenny machine and test on that.
> That would probably be easier.

I will try this but it will take a few days to arrange.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: kpartx.c
Type: text/x-csrc
Size: 12483 bytes
Desc: 
Url : http://lists.alioth.debian.org/pipermail/pkg-lvm-maintainers/attachments/20090123/e012d728/attachment-0001.c 
-------------- next part --------------
diff a/kpartx/devmapper.c b/kpartx/devmapper.c
--- 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 a/kpartx/devmapper.h b/kpartx/devmapper.h
--- 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 a/kpartx/gpt.c b/kpartx/gpt.c
--- 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, &sectors);
-        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 a/kpartx/kpartx.c b/kpartx/kpartx.c
--- 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  a/kpartx/kpartx.h b/kpartx/kpartx.h
--- 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;


More information about the pkg-lvm-maintainers mailing list