From: Stephen Ayotte Date: Thu, 2 Jan 2014 19:30:26 +0000 (-0500) Subject: Support large bdevs on 32-bit; MB units by default. X-Git-Tag: lxc-1.0.0.beta2~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d659597e03725411c366c42dc02c64c0c35a167a;p=thirdparty%2Flxc.git Support large bdevs on 32-bit; MB units by default. Change all instances of "unsigned long" where referring to a bdev size to uint64_t; this fixes some overflows on 32-bit machines, where "unsigned long" is uint32_t. Support all unit-sizes supported by LVM except 's' and 'e' [bkmgt]. Print a warning and use default bdev-size if invalid unit-size specified. Signed-off-by: Stephen Ayotte Acked-by: Stéphane Graber --- diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h index 2fa24c0a3..4bbfc7167 100644 --- a/src/lxc/arguments.h +++ b/src/lxc/arguments.h @@ -25,6 +25,7 @@ #define __arguments_h #include +#include struct lxc_arguments; @@ -88,7 +89,7 @@ struct lxc_arguments { /* lxc-create */ char *bdevtype, *configfile, *template; char *fstype; - unsigned long fssize; + uint64_t fssize; char *lvname, *vgname, *thinpool; char *zfsroot, *lowerdir, *dir; diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c index 2e4281dc4..30b957469 100644 --- a/src/lxc/bdev.c +++ b/src/lxc/bdev.c @@ -29,6 +29,8 @@ */ #define _GNU_SOURCE #include +#include +#include #include #include #include @@ -58,6 +60,9 @@ #define LO_FLAGS_AUTOCLEAR 4 #endif +#define DEFAULT_FS_SIZE 1073741824 +#define DEFAULT_FSTYPE "ext3" + lxc_log_define(bdev, lxc); static int do_rsync(const char *src, const char *dest) @@ -86,9 +91,9 @@ static int do_rsync(const char *src, const char *dest) } /* - * return block size of dev->src + * return block size of dev->src in units of bytes */ -static int blk_getsize(struct bdev *bdev, unsigned long *size) +static int blk_getsize(struct bdev *bdev, uint64_t *size) { int fd, ret; char *path = bdev->src; @@ -99,7 +104,8 @@ static int blk_getsize(struct bdev *bdev, unsigned long *size) fd = open(path, O_RDONLY); if (fd < 0) return -1; - ret = ioctl(fd, BLKGETSIZE64, size); + + ret = ioctl(fd, BLKGETSIZE64, size); // size of device in bytes close(fd); return ret; } @@ -412,7 +418,7 @@ static char *dir_new_path(char *src, const char *oldname, const char *name, */ static int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, - unsigned long newsize) + uint64_t newsize) { int len, ret; @@ -625,7 +631,7 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname, static int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, - unsigned long newsize) + uint64_t newsize) { int len, ret; @@ -843,7 +849,7 @@ static int lvm_is_thin_pool(const char *path) * a valid thin pool, and if so, we'll create the requested lv from that thin * pool. */ -static int do_lvm_create(const char *path, unsigned long size, const char *thinpool) +static int do_lvm_create(const char *path, uint64_t size, const char *thinpool) { int ret, pid, len; char sz[24], *pathdup, *vg, *lv, *tp = NULL; @@ -855,8 +861,8 @@ static int do_lvm_create(const char *path, unsigned long size, const char *thinp if (pid > 0) return wait_for_pid(pid); - // lvcreate default size is in M, not bytes. - ret = snprintf(sz, 24, "%lu", size/1000000); + // specify bytes to lvcreate + ret = snprintf(sz, 24, "%"PRIu64"b", size); if (ret < 0 || ret >= 24) exit(1); @@ -902,7 +908,7 @@ static int do_lvm_create(const char *path, unsigned long size, const char *thinp exit(1); } -static int lvm_snapshot(const char *orig, const char *path, unsigned long size) +static int lvm_snapshot(const char *orig, const char *path, uint64_t size) { int ret, pid; char sz[24], *pathdup, *lv; @@ -914,8 +920,8 @@ static int lvm_snapshot(const char *orig, const char *path, unsigned long size) if (pid > 0) return wait_for_pid(pid); - // lvcreate default size is in M, not bytes. - ret = snprintf(sz, 24, "%lu", size/1000000); + // specify bytes to lvcreate + ret = snprintf(sz, 24, "%"PRIu64"b", size); if (ret < 0 || ret >= 24) exit(1); @@ -959,10 +965,10 @@ static int is_blktype(struct bdev *b) static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, - unsigned long newsize) + uint64_t newsize) { char fstype[100]; - unsigned long size = newsize; + uint64_t size = newsize; int len, ret; if (!orig->src || !orig->dest) @@ -1017,7 +1023,7 @@ static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldna } else { sprintf(fstype, "ext3"); if (!newsize) - size = 1000000000; // default to 1G + size = DEFAULT_FS_SIZE; } if (snap) { @@ -1053,13 +1059,11 @@ static int lvm_destroy(struct bdev *orig) return wait_for_pid(pid); } -#define DEFAULT_FS_SIZE 1024000000 -#define DEFAULT_FSTYPE "ext3" static int lvm_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { const char *vg, *thinpool, *fstype, *lv = n; - unsigned long sz; + uint64_t sz; int ret, len; if (!specs) @@ -1092,7 +1096,7 @@ static int lvm_create(struct bdev *bdev, const char *dest, const char *n, sz = DEFAULT_FS_SIZE; if (do_lvm_create(bdev->src, sz, thinpool) < 0) { - ERROR("Error creating new lvm blockdev %s size %lu", bdev->src, sz); + ERROR("Error creating new lvm blockdev %s size %"PRIu64" bytes", bdev->src, sz); return -1; } @@ -1322,7 +1326,7 @@ out: static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, - unsigned long newsize) + uint64_t newsize) { if (!orig->dest || !orig->src) return -1; @@ -1535,7 +1539,7 @@ static int loop_umount(struct bdev *bdev) return ret; } -static int do_loop_create(const char *path, unsigned long size, const char *fstype) +static int do_loop_create(const char *path, uint64_t size, const char *fstype) { int fd, ret; // create the new loopback file. @@ -1574,10 +1578,10 @@ static int do_loop_create(const char *path, unsigned long size, const char *fsty */ static int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, - unsigned long newsize) + uint64_t newsize) { char fstype[100]; - unsigned long size = newsize; + uint64_t size = newsize; int len, ret; char *srcdev; @@ -1626,7 +1630,7 @@ static int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn } else { sprintf(fstype, "%s", DEFAULT_FSTYPE); if (!newsize) - size = DEFAULT_FS_SIZE; // default to 1G + size = DEFAULT_FS_SIZE; } return do_loop_create(srcdev, size, fstype); } @@ -1635,7 +1639,7 @@ static int loop_create(struct bdev *bdev, const char *dest, const char *n, struct bdev_specs *specs) { const char *fstype; - unsigned long sz; + uint64_t sz; int ret, len; char *srcdev; @@ -1759,7 +1763,7 @@ static int overlayfs_umount(struct bdev *bdev) static int overlayfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, int snap, - unsigned long newsize) + uint64_t newsize) { if (!snap) { ERROR("overlayfs is only for snapshot clones"); @@ -2006,7 +2010,7 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data) */ struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, const char *bdevtype, - int flags, const char *bdevdata, unsigned long newsize, + int flags, const char *bdevdata, uint64_t newsize, int *needs_rdep) { struct bdev *orig, *new; diff --git a/src/lxc/bdev.h b/src/lxc/bdev.h index f4c0214dd..c45f08675 100644 --- a/src/lxc/bdev.h +++ b/src/lxc/bdev.h @@ -29,6 +29,7 @@ */ #include "config.h" +#include #include struct bdev; @@ -38,7 +39,7 @@ struct bdev; */ struct bdev_specs { char *fstype; - unsigned long fssize; // fs size in bytes + uint64_t fssize; // fs size in bytes struct { char *zfsroot; } zfs; @@ -61,7 +62,7 @@ struct bdev_ops { /* given original mount, rename the paths for cloned container */ int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, - int snap, unsigned long newsize); + int snap, uint64_t newsize); bool can_snapshot; }; @@ -100,7 +101,7 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data); struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname, const char *oldpath, const char *lxcpath, const char *bdevtype, - int flags, const char *bdevdata, unsigned long newsize, + int flags, const char *bdevdata, uint64_t newsize, int *needs_rdep); struct bdev *bdev_create(const char *dest, const char *type, const char *cname, struct bdev_specs *specs); diff --git a/src/lxc/lxc_clone.c b/src/lxc/lxc_clone.c index 8e8cd4640..ea2d16f0e 100644 --- a/src/lxc/lxc_clone.c +++ b/src/lxc/lxc_clone.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -37,37 +38,52 @@ lxc_log_define(lxc_clone, lxc); -static unsigned long get_fssize(char *s) +/* we pass fssize in bytes */ +static uint64_t get_fssize(char *s) { - unsigned long ret; - char *end; - - ret = strtoul(s, &end, 0); - if (end == s) - return 0; - while (isblank(*end)) - end++; - if (!(*end)) - return ret; - if (*end == 'g' || *end == 'G') - ret *= 1000000000; - else if (*end == 'm' || *end == 'M') - ret *= 1000000; - else if (*end == 'k' || *end == 'K') - ret *= 1000; - return ret; + uint64_t ret; + char *end; + + ret = strtoull(s, &end, 0); + if (end == s) + { + fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); + return 0; + } + while (isblank(*end)) + end++; + if (*end == '\0') + ret *= 1024ULL * 1024ULL; // MB by default + else if (*end == 'b' || *end == 'B') + ret *= 1ULL; + else if (*end == 'k' || *end == 'K') + ret *= 1024ULL; + else if (*end == 'm' || *end == 'M') + ret *= 1024ULL * 1024ULL; + else if (*end == 'g' || *end == 'G') + ret *= 1024ULL * 1024ULL * 1024ULL; + else if (*end == 't' || *end == 'T') + ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; + else + { + fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); + return 0; + } + return ret; } static void usage(const char *me) { - printf("Usage: %s [-s] [-B backingstore] [-L size] [-K] [-M] [-H]\n", me); + printf("Usage: %s [-s] [-B backingstore] [-L size[unit]] [-K] [-M] [-H]\n", me); printf(" [-p lxcpath] [-P newlxcpath] orig new\n"); printf("\n"); printf(" -s: snapshot rather than copy\n"); printf(" -B: use specified new backingstore. Default is the same as\n"); printf(" the original. Options include btrfs, lvm, overlayfs, \n"); printf(" dir and loop\n"); - printf(" -L: for blockdev-backed backingstore, use specified size\n"); + printf(" -L: for blockdev-backed backingstore, use specified size * specified\n"); + printf(" unit. Default size is the size of the source blockdev, default\n"); + printf(" unit is MB\n"); printf(" -K: Keep name - do not change the container name\n"); printf(" -M: Keep macaddr - do not choose a random new mac address\n"); printf(" -p: use container orig from custom lxcpath\n"); @@ -96,7 +112,7 @@ int main(int argc, char *argv[]) struct lxc_container *c1 = NULL, *c2 = NULL; int snapshot = 0, keepname = 0, keepmac = 0; int flags = 0, option_index; - long newsize = 0; + uint64_t newsize = 0; char *bdevtype = NULL, *lxcpath = NULL, *newpath = NULL, *fstype = NULL; char *orig = NULL, *new = NULL, *vgname = NULL; char **args = NULL; diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c index af10c59a0..42eb8d902 100644 --- a/src/lxc/lxc_create.c +++ b/src/lxc/lxc_create.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "lxc.h" #include "log.h" @@ -34,25 +35,36 @@ lxc_log_define(lxc_create, lxc); -/* we pass fssize in bytes */ -static unsigned long get_fssize(char *s) +static uint64_t get_fssize(char *s) { - unsigned long ret; + uint64_t ret; char *end; - ret = strtoul(s, &end, 0); + ret = strtoull(s, &end, 0); if (end == s) + { + fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); return 0; + } while (isblank(*end)) end++; - if (!(*end)) - return ret; - if (*end == 'g' || *end == 'G') - ret *= 1000000000; - else if (*end == 'm' || *end == 'M') - ret *= 1000000; + if (*end == '\0') + ret *= 1024ULL * 1024ULL; // MB by default + else if (*end == 'b' || *end == 'B') + ret *= 1ULL; else if (*end == 'k' || *end == 'K') - ret *= 1000; + ret *= 1024ULL; + else if (*end == 'm' || *end == 'M') + ret *= 1024ULL * 1024ULL; + else if (*end == 'g' || *end == 'G') + ret *= 1024ULL * 1024ULL * 1024ULL; + else if (*end == 't' || *end == 'T') + ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; + else + { + fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); + return 0; + } return ret; } @@ -130,16 +142,16 @@ Options :\n\ --lvname=LVNAME Use LVM lv name LVNAME\n\ (Default: container name)\n\ --vgname=VG Use LVM vg called VG\n\ - (Default: lxc))\n\ + (Default: lxc)\n\ --thinpool=TP Use LVM thin pool called TP\n\ - (Default: lxc))\n\ + (Default: lxc)\n\ --fstype=TYPE Create fstype TYPE\n\ - (Default: ext3))\n\ - --fssize=SIZE Create filesystem of size SIZE\n\ - (Default: 1G))\n\ + (Default: ext3)\n\ + --fssize=SIZE[U] Create filesystem of size SIZE * unit U (bBkKmMgGtT)\n\ + (Default: 1G, default unit: M)\n\ --dir=DIR Place rootfs directory under DIR\n\ --zfsroot=PATH Create zfs under given zfsroot\n\ - (Default: tank/lxc))\n", + (Default: tank/lxc)\n", .options = my_longopts, .parser = my_parser, .checker = NULL, diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 353b73391..f999cfc62 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -2276,7 +2277,7 @@ static bool add_rdepends(struct lxc_container *c, struct lxc_container *c0) } static int copy_storage(struct lxc_container *c0, struct lxc_container *c, - const char *newtype, int flags, const char *bdevdata, unsigned long newsize) + const char *newtype, int flags, const char *bdevdata, uint64_t newsize) { struct bdev *bdev; int need_rdep; @@ -2415,7 +2416,7 @@ static int create_file_dirname(char *path) static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *newname, const char *lxcpath, int flags, - const char *bdevtype, const char *bdevdata, unsigned long newsize, + const char *bdevtype, const char *bdevdata, uint64_t newsize, char **hookargs) { struct lxc_container *c2 = NULL; diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h index fe2dbc239..a62411b52 100644 --- a/src/lxc/lxccontainer.h +++ b/src/lxc/lxccontainer.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -543,7 +544,7 @@ struct lxc_container { */ struct lxc_container *(*clone)(struct lxc_container *c, const char *newname, const char *lxcpath, int flags, const char *bdevtype, - const char *bdevdata, unsigned long newsize, char **hookargs); + const char *bdevdata, uint64_t newsize, char **hookargs); /*! * \brief Allocate a console tty for the container.