Commit d659597e by Stephen Ayotte Committed by Stéphane Graber

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: 's avatarStephen Ayotte <stephen.ayotte@gmail.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent 6f639311
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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>
......@@ -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;
......
......@@ -25,6 +25,7 @@
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdint.h>
#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,
......
......@@ -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;
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment