]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Support large bdevs on 32-bit; MB units by default.
authorStephen Ayotte <stephen.ayotte@gmail.com>
Thu, 2 Jan 2014 19:30:26 +0000 (14:30 -0500)
committerStéphane Graber <stgraber@ubuntu.com>
Wed, 8 Jan 2014 17:31:50 +0000 (12:31 -0500)
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 <stephen.ayotte@gmail.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/arguments.h
src/lxc/bdev.c
src/lxc/bdev.h
src/lxc/lxc_clone.c
src/lxc/lxc_create.c
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h

index 2fa24c0a3f6cea3abbfe21ca88d34f2f942c1103..4bbfc716771d3441d72e19d16fbb8d3ee8b18ff8 100644 (file)
@@ -25,6 +25,7 @@
 #define __arguments_h
 
 #include <getopt.h>
+#include <stdint.h>
 
 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;
 
index 2e4281dc48d0359edacce7f8a2ba7e8e59175d94..30b957469537cccb1f8594a8b9ec7cf7514d447f 100644 (file)
@@ -29,6 +29,8 @@
  */
 #define _GNU_SOURCE
 #include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
 #include <unistd.h>
 #include <errno.h>
 #include <sched.h>
@@ -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;
index f4c0214dda4e70cfc3c433f452be73b00f86068c..c45f08675f05f9b6fefd038162652e6216400d39 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "config.h"
+#include <stdint.h>
 #include <lxc/lxccontainer.h>
 
 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);
index 8e8cd46407f35b5a65d61c14e7fa6af2b0ed5a40..ea2d16f0eabdf717f19e6a102932081ec47acf69 100644 (file)
@@ -22,6 +22,7 @@
 #include <signal.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <stdint.h>
 #include <sys/wait.h>
 #include <stdlib.h>
 #include <errno.h>
 
 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;
index af10c59a010b3693473ccd3081610574970ec447..42eb8d9023b3d444fcab7f331a6e21db6bc9d257 100644 (file)
@@ -25,6 +25,7 @@
 #include <ctype.h>
 #include <fcntl.h>
 #include <sys/types.h>
+#include <stdint.h>
 
 #include "lxc.h"
 #include "log.h"
 
 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,
index 353b733918d0ea35f259b070ac797b26ce78e87c..f999cfc625d189118807f9c92b93147ea5a28751 100644 (file)
@@ -33,6 +33,7 @@
 #include <sched.h>
 #include <arpa/inet.h>
 #include <libgen.h>
+#include <stdint.h>
 
 #include <lxc/lxccontainer.h>
 #include <lxc/version.h>
@@ -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;
index fe2dbc2395d5cfacf8a1234feaeb915700cf0b13..a62411b52646ef0a538234aa9906ef5813e15483 100644 (file)
@@ -26,6 +26,7 @@
 #include <semaphore.h>
 #include <stdbool.h>
 #include <stdlib.h>
+#include <stdint.h>
 
 #include <lxc/attach_options.h>
 
@@ -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.