Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
789edffe
Commit
789edffe
authored
Aug 15, 2017
by
Stéphane Graber
Committed by
GitHub
Aug 15, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1747 from brauner/2017-08-15/stable_2_0_cherry_picks
stable 2.0: revert a bunch of cherry picks
parents
93b8f59a
7d3391cb
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
567 additions
and
1291 deletions
+567
-1291
bdev.c
src/lxc/bdev/bdev.c
+75
-120
bdev.h
src/lxc/bdev/bdev.h
+0
-5
lxcbtrfs.c
src/lxc/bdev/lxcbtrfs.c
+77
-191
lxcbtrfs.h
src/lxc/bdev/lxcbtrfs.h
+0
-5
lxcdir.c
src/lxc/bdev/lxcdir.c
+29
-84
lxcloop.c
src/lxc/bdev/lxcloop.c
+58
-132
lxclvm.c
src/lxc/bdev/lxclvm.c
+168
-370
lxclvm.h
src/lxc/bdev/lxclvm.h
+0
-5
lxcnbd.c
src/lxc/bdev/lxcnbd.c
+5
-8
lxcoverlay.c
src/lxc/bdev/lxcoverlay.c
+46
-93
lxcoverlay.h
src/lxc/bdev/lxcoverlay.h
+1
-1
lxcrbd.c
src/lxc/bdev/lxcrbd.c
+50
-124
lxcrsync.c
src/lxc/bdev/lxcrsync.c
+0
-78
lxcrsync.h
src/lxc/bdev/lxcrsync.h
+0
-5
lxczfs.c
src/lxc/bdev/lxczfs.c
+23
-54
storage_utils.c
src/lxc/bdev/storage_utils.c
+10
-7
conf.c
src/lxc/conf.c
+18
-0
lxccontainer.c
src/lxc/lxccontainer.c
+5
-7
lxc_destroy.c
src/lxc/tools/lxc_destroy.c
+2
-2
No files found.
src/lxc/bdev/bdev.c
View file @
789edffe
...
...
@@ -82,8 +82,6 @@ static const struct bdev_ops aufs_ops = {
.
clone_paths
=
&
aufs_clonepaths
,
.
destroy
=
&
aufs_destroy
,
.
create
=
&
aufs_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
};
...
...
@@ -96,8 +94,6 @@ static const struct bdev_ops btrfs_ops = {
.
clone_paths
=
&
btrfs_clonepaths
,
.
destroy
=
&
btrfs_destroy
,
.
create
=
&
btrfs_create
,
.
create_clone
=
&
btrfs_create_clone
,
.
create_snapshot
=
&
btrfs_create_snapshot
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
};
...
...
@@ -110,8 +106,6 @@ static const struct bdev_ops dir_ops = {
.
clone_paths
=
&
dir_clonepaths
,
.
destroy
=
&
dir_destroy
,
.
create
=
&
dir_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
false
,
.
can_backup
=
true
,
};
...
...
@@ -124,8 +118,6 @@ static const struct bdev_ops loop_ops = {
.
clone_paths
=
&
loop_clonepaths
,
.
destroy
=
&
loop_destroy
,
.
create
=
&
loop_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
false
,
.
can_backup
=
true
,
};
...
...
@@ -138,8 +130,6 @@ static const struct bdev_ops lvm_ops = {
.
clone_paths
=
&
lvm_clonepaths
,
.
destroy
=
&
lvm_destroy
,
.
create
=
&
lvm_create
,
.
create_clone
=
&
lvm_create_clone
,
.
create_snapshot
=
&
lvm_create_snapshot
,
.
can_snapshot
=
true
,
.
can_backup
=
false
,
};
...
...
@@ -152,8 +142,6 @@ const struct bdev_ops nbd_ops = {
.
clone_paths
=
&
nbd_clonepaths
,
.
destroy
=
&
nbd_destroy
,
.
create
=
&
nbd_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
true
,
.
can_backup
=
false
,
};
...
...
@@ -166,8 +154,6 @@ static const struct bdev_ops ovl_ops = {
.
clone_paths
=
&
ovl_clonepaths
,
.
destroy
=
&
ovl_destroy
,
.
create
=
&
ovl_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
};
...
...
@@ -180,8 +166,6 @@ static const struct bdev_ops rbd_ops = {
.
clone_paths
=
&
rbd_clonepaths
,
.
destroy
=
&
rbd_destroy
,
.
create
=
&
rbd_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
false
,
.
can_backup
=
false
,
};
...
...
@@ -194,8 +178,6 @@ static const struct bdev_ops zfs_ops = {
.
clone_paths
=
&
zfs_clonepaths
,
.
destroy
=
&
zfs_destroy
,
.
create
=
&
zfs_create
,
.
create_clone
=
NULL
,
.
create_snapshot
=
NULL
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
};
...
...
@@ -212,7 +194,6 @@ static const struct bdev_type bdevs[] = {
{
.
name
=
"btrfs"
,
.
ops
=
&
btrfs_ops
,
},
{
.
name
=
"dir"
,
.
ops
=
&
dir_ops
,
},
{
.
name
=
"aufs"
,
.
ops
=
&
aufs_ops
,
},
{
.
name
=
"overlay"
,
.
ops
=
&
ovl_ops
,
},
{
.
name
=
"overlayfs"
,
.
ops
=
&
ovl_ops
,
},
{
.
name
=
"loop"
,
.
ops
=
&
loop_ops
,
},
{
.
name
=
"nbd"
,
.
ops
=
&
nbd_ops
,
},
...
...
@@ -326,8 +307,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
const
char
*
bdevdata
,
uint64_t
newsize
,
int
*
needs_rdep
)
{
struct
bdev
*
orig
,
*
new
;
pid_t
pid
;
int
ret
;
char
*
src_no_prefix
;
bool
snap
=
flags
&
LXC_CLONE_SNAPSHOT
;
bool
maybe_snap
=
flags
&
LXC_CLONE_MAYBE_SNAPSHOT
;
bool
keepbdevtype
=
flags
&
LXC_CLONE_KEEPBDEVTYPE
;
...
...
@@ -335,20 +316,20 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
const
char
*
oldname
=
c0
->
name
;
const
char
*
oldpath
=
c0
->
config_path
;
struct
rsync_data
data
;
char
cmd_output
[
MAXPATHLEN
];
/*
If the container name doesn't show up in the rootfs path, then we
*
don't know how to come up with a new name.
/*
if the container name doesn't show up in the rootfs path, then
*
we don't know how to come up with a new name
*/
if
(
!
strstr
(
src
,
oldname
))
{
ERROR
(
"Original rootfs path
\"
%s
\"
does not include container "
"name
\"
%s
\"
"
,
src
,
oldname
);
if
(
strstr
(
src
,
oldname
)
==
NULL
)
{
ERROR
(
"original rootfs path %s doesn't include container name %s"
,
src
,
oldname
);
return
NULL
;
}
orig
=
bdev_init
(
c0
->
lxc_conf
,
src
,
NULL
,
NULL
);
if
(
!
orig
)
{
ERROR
(
"
Failed to detect storage driver for
\"
%s
\"
"
,
src
);
ERROR
(
"
failed to detect blockdev type for %s
"
,
src
);
return
NULL
;
}
...
...
@@ -360,143 +341,128 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
len
=
strlen
(
oldpath
)
+
strlen
(
oldname
)
+
strlen
(
"/rootfs"
)
+
2
;
orig
->
dest
=
malloc
(
len
);
if
(
!
orig
->
dest
)
{
ERROR
(
"
Failed to allocate
memory"
);
ERROR
(
"
out of
memory"
);
bdev_put
(
orig
);
return
NULL
;
}
ret
=
snprintf
(
orig
->
dest
,
len
,
"%s/%s/rootfs"
,
oldpath
,
oldname
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
ERROR
(
"
Failed to create stri
ng"
);
ERROR
(
"
rootfs path too lo
ng"
);
bdev_put
(
orig
);
return
NULL
;
}
ret
=
stat
(
orig
->
dest
,
&
sb
);
if
(
ret
<
0
&&
errno
==
ENOENT
)
{
ret
=
mkdir_p
(
orig
->
dest
,
0755
);
if
(
ret
<
0
)
WARN
(
"
Failed to create directoy
\"
%s
\"
"
,
orig
->
dest
);
}
if
(
ret
<
0
&&
errno
==
ENOENT
)
if
(
mkdir_p
(
orig
->
dest
,
0755
)
<
0
)
WARN
(
"
Error creating '%s', continuing."
,
orig
->
dest
);
}
/* Special case for snapshot. If the caller requested maybe_snapshot and
* keepbdevtype and the backing store is directory, then proceed with a
* a copy clone rather than returning error.
/*
* special case for snapshot - if caller requested maybe_snapshot and
* keepbdevtype and backing store is directory, then proceed with a copy
* clone rather than returning error
*/
if
(
maybe_snap
&&
keepbdevtype
&&
!
bdevtype
&&
!
orig
->
ops
->
can_snapshot
)
snap
=
false
;
/* If newtype is NULL and snapshot is set, then use overlay. */
if
(
!
bdevtype
&&
!
keepbdevtype
&&
snap
&&
strcmp
(
orig
->
type
,
"dir"
)
==
0
)
bdevtype
=
"overlay"
;
/* If newtype is NULL and snapshot is set, then use overlay
fs
. */
if
(
!
bdevtype
&&
!
keepbdevtype
&&
snap
&&
(
!
strcmp
(
orig
->
type
,
"dir"
)
||
!
strcmp
(
orig
->
type
,
"overlayfs"
))
)
bdevtype
=
"overlay
fs
"
;
if
(
am_unpriv
()
&&
!
unpriv_snap_allowed
(
orig
,
bdevtype
,
snap
,
maybe_snap
))
{
ERROR
(
"Unsupported snapshot type
\"
%s
\"
for unprivileged users"
,
bdevtype
?
bdevtype
:
"(null)"
);
ERROR
(
"Unsupported snapshot type for unprivileged users"
);
bdev_put
(
orig
);
return
NULL
;
}
*
needs_rdep
=
0
;
if
(
bdevtype
&&
!
strcmp
(
orig
->
type
,
"dir"
)
&&
if
(
bdevtype
&&
strcmp
(
orig
->
type
,
"dir"
)
==
0
&&
(
strcmp
(
bdevtype
,
"aufs"
)
==
0
||
strcmp
(
bdevtype
,
"overlayfs"
)
==
0
||
strcmp
(
bdevtype
,
"overlay"
)
==
0
))
{
strcmp
(
bdevtype
,
"overlayfs"
)
==
0
))
{
*
needs_rdep
=
1
;
}
else
if
(
snap
&&
!
strcmp
(
orig
->
type
,
"lvm"
)
&&
}
else
if
(
snap
&&
strcmp
(
orig
->
type
,
"lvm"
)
==
0
&&
!
lvm_is_thin_volume
(
orig
->
src
))
{
*
needs_rdep
=
1
;
}
if
(
strcmp
(
oldpath
,
lxcpath
)
&&
!
bdevtype
&&
!
snap
)
if
(
strcmp
(
oldpath
,
lxcpath
)
&&
!
bdevtype
&&
strcmp
(
orig
->
type
,
"overlayfs"
)
)
bdevtype
=
"dir"
;
else
if
(
!
bdevtype
)
bdevtype
=
orig
->
type
;
/* get new bdev type */
new
=
bdev_get
(
bdevtype
);
if
(
!
new
)
{
ERROR
(
"
Failed to initialize
\"
%s
\"
storage driver
"
,
ERROR
(
"
no such block device type: %s
"
,
bdevtype
?
bdevtype
:
orig
->
type
);
bdev_put
(
orig
);
return
NULL
;
}
TRACE
(
"Initialized
\"
%s
\"
storage driver"
,
new
->
type
);
/* create new paths */
ret
=
new
->
ops
->
clone_paths
(
orig
,
new
,
oldname
,
cname
,
oldpath
,
lxcpath
,
snap
,
newsize
,
c0
->
lxc_conf
);
if
(
ret
<
0
)
{
ERROR
(
"Failed creating new paths for clone of
\"
%s
\"
"
,
src
);
if
(
new
->
ops
->
clone_paths
(
orig
,
new
,
oldname
,
cname
,
oldpath
,
lxcpath
,
snap
,
newsize
,
c0
->
lxc_conf
)
<
0
)
{
ERROR
(
"failed getting pathnames for cloned storage: %s"
,
src
);
goto
err
;
}
/* btrfs */
if
(
!
strcmp
(
orig
->
type
,
"btrfs"
)
&&
!
strcmp
(
new
->
type
,
"btrfs"
))
{
bool
bret
=
false
;
if
(
snap
||
btrfs_same_fs
(
orig
->
dest
,
new
->
dest
)
==
0
)
bret
=
new
->
ops
->
create_snapshot
(
c0
->
lxc_conf
,
orig
,
new
,
0
);
else
bret
=
new
->
ops
->
create_clone
(
c0
->
lxc_conf
,
orig
,
new
,
0
);
if
(
!
bret
)
return
NULL
;
if
(
am_unpriv
()
&&
chown_mapped_root
(
new
->
src
,
c0
->
lxc_conf
)
<
0
)
WARN
(
"Failed to update ownership of %s"
,
new
->
dest
);
if
(
snap
)
return
new
;
}
/* lvm */
if
(
!
strcmp
(
orig
->
type
,
"lvm"
)
&&
!
strcmp
(
new
->
type
,
"lvm"
))
{
bool
bret
=
false
;
if
(
snap
)
bret
=
new
->
ops
->
create_snapshot
(
c0
->
lxc_conf
,
orig
,
new
,
newsize
);
else
bret
=
new
->
ops
->
create_clone
(
c0
->
lxc_conf
,
orig
,
new
,
newsize
);
if
(
!
bret
)
return
NULL
;
/*
* https://github.com/lxc/lxc/issues/131
* Use btrfs snapshot feature instead of rsync to restore if both orig
* and new are btrfs
*/
if
(
bdevtype
&&
strcmp
(
orig
->
type
,
"btrfs"
)
==
0
&&
strcmp
(
new
->
type
,
"btrfs"
)
==
0
&&
btrfs_same_fs
(
orig
->
dest
,
new
->
dest
)
==
0
)
{
if
(
btrfs_destroy
(
new
)
<
0
)
{
ERROR
(
"Error destroying %s subvolume"
,
new
->
dest
);
goto
err
;
}
if
(
mkdir_p
(
new
->
dest
,
0755
)
<
0
)
{
ERROR
(
"Error creating %s directory"
,
new
->
dest
);
goto
err
;
}
if
(
btrfs_snapshot
(
orig
->
dest
,
new
->
dest
)
<
0
)
{
ERROR
(
"Error restoring %s to %s"
,
orig
->
dest
,
new
->
dest
);
goto
err
;
}
bdev_put
(
orig
);
return
new
;
}
if
(
strcmp
(
bdevtype
,
"btrfs"
))
{
if
(
!
strcmp
(
new
->
type
,
"overlay"
)
||
!
strcmp
(
new
->
type
,
"overlayfs"
))
src_no_prefix
=
ovl_get_lower
(
new
->
src
);
else
src_no_prefix
=
lxc_storage_get_path
(
new
->
src
,
new
->
type
);
if
(
am_unpriv
())
{
ret
=
chown_mapped_root
(
src_no_prefix
,
c0
->
lxc_conf
);
if
(
ret
<
0
)
WARN
(
"Failed to chown
\"
%s
\"
"
,
new
->
src
);
}
pid
=
fork
();
if
(
pid
<
0
)
{
SYSERROR
(
"fork"
);
goto
err
;
}
if
(
snap
)
if
(
pid
>
0
)
{
int
ret
=
wait_for_pid
(
pid
);
bdev_put
(
orig
);
if
(
ret
<
0
)
{
bdev_put
(
new
);
return
NULL
;
}
return
new
;
}
/* rsync the contents from source to target */
data
.
orig
=
orig
;
data
.
new
=
new
;
if
(
am_unpriv
())
{
ret
=
userns_exec_1
(
c0
->
lxc_conf
,
lxc_rsync_exec_wrapper
,
&
data
,
"lxc_rsync_exec_wrapper"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
"
,
orig
->
dest
,
new
->
dest
);
goto
err
;
}
}
else
{
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lxc_rsync_exec_wrapper
,
(
void
*
)
&
data
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
: %s"
,
orig
->
dest
,
new
->
dest
,
cmd_output
);
goto
err
;
}
}
if
(
am_unpriv
())
ret
=
userns_exec_1
(
c0
->
lxc_conf
,
rsync_rootfs_wrapper
,
&
data
,
"rsync_rootfs_wrapper"
);
else
ret
=
rsync_rootfs
(
&
data
);
bdev_put
(
orig
);
return
new
;
exit
(
ret
==
0
?
0
:
1
);
err:
bdev_put
(
orig
);
...
...
@@ -648,14 +614,3 @@ bool rootfs_is_blockdev(struct lxc_conf *conf)
return
false
;
}
char
*
lxc_storage_get_path
(
char
*
src
,
const
char
*
prefix
)
{
size_t
prefix_len
;
prefix_len
=
strlen
(
prefix
);
if
(
!
strncmp
(
src
,
prefix
,
prefix_len
)
&&
(
*
(
src
+
prefix_len
)
==
':'
))
return
(
src
+
prefix_len
+
1
);
return
src
;
}
src/lxc/bdev/bdev.h
View file @
789edffe
...
...
@@ -73,10 +73,6 @@ struct bdev_ops {
const
char
*
oldname
,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
);
bool
(
*
create_clone
)(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
);
bool
(
*
create_snapshot
)(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
);
bool
can_snapshot
;
bool
can_backup
;
};
...
...
@@ -129,6 +125,5 @@ bool bdev_destroy(struct lxc_conf *conf);
/* callback function to be used with userns_exec_1() */
int
bdev_destroy_wrapper
(
void
*
data
);
extern
bool
rootfs_is_blockdev
(
struct
lxc_conf
*
conf
);
extern
char
*
lxc_storage_get_path
(
char
*
src
,
const
char
*
prefix
);
#endif // __LXC_BDEV_H
src/lxc/bdev/lxcbtrfs.c
View file @
789edffe
...
...
@@ -32,7 +32,6 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/vfs.h>
...
...
@@ -40,10 +39,14 @@
#include "log.h"
#include "lxcbtrfs.h"
#include "lxcrsync.h"
#include "
../
utils.h"
#include "utils.h"
lxc_log_define
(
lxcbtrfs
,
lxc
);
/* defined in lxccontainer.c: needs to become common helper */
extern
char
*
dir_new_path
(
char
*
src
,
const
char
*
oldname
,
const
char
*
name
,
const
char
*
oldpath
,
const
char
*
lxcpath
);
/*
* Return the full path of objid under dirid. Let's say dirid is
* /lxc/c1/rootfs, and objid is /lxc/c1/rootfs/a/b/c. Then we will
...
...
@@ -188,12 +191,11 @@ int btrfs_detect(const char *path)
int
btrfs_mount
(
struct
bdev
*
bdev
)
{
unsigned
long
mntflags
;
char
*
mntdata
,
*
src
;
char
*
mntdata
;
int
ret
;
if
(
strcmp
(
bdev
->
type
,
"btrfs"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
...
...
@@ -202,9 +204,7 @@ int btrfs_mount(struct bdev *bdev)
return
-
22
;
}
src
=
lxc_storage_get_path
(
bdev
->
src
,
"btrfs"
);
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
|
mntflags
,
mntdata
);
ret
=
mount
(
bdev
->
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
|
mntflags
,
mntdata
);
free
(
mntdata
);
return
ret
;
}
...
...
@@ -213,50 +213,45 @@ int btrfs_umount(struct bdev *bdev)
{
if
(
strcmp
(
bdev
->
type
,
"btrfs"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
return
umount
(
bdev
->
dest
);
}
static
int
btrfs_subvolume_create
(
const
char
*
path
)
{
int
ret
,
saved_errno
;
struct
btrfs_ioctl_vol_args
args
;
char
*
p
,
*
newfull
;
int
fd
=
-
1
;
int
ret
,
fd
=
-
1
;
struct
btrfs_ioctl_vol_args
args
;
char
*
p
,
*
newfull
=
strdup
(
path
);
newfull
=
strdup
(
path
);
if
(
!
newfull
)
{
errno
=
ENOMEM
;
return
-
ENOMEM
;
ERROR
(
"Error: out of memory"
)
;
return
-
1
;
}
p
=
strrchr
(
newfull
,
'/'
);
if
(
!
p
)
{
ERROR
(
"bad path: %s"
,
path
);
free
(
newfull
);
errno
=
EINVAL
;
return
-
EINVAL
;
return
-
1
;
}
*
p
=
'\0'
;
fd
=
open
(
newfull
,
O_RDONLY
);
if
(
fd
<
0
)
{
ERROR
(
"Error opening %s"
,
newfull
);
free
(
newfull
);
return
-
errno
;
return
-
1
;
}
memset
(
&
args
,
0
,
sizeof
(
args
));
strncpy
(
args
.
name
,
p
+
1
,
BTRFS_SUBVOL_NAME_MAX
);
args
.
name
[
BTRFS_SUBVOL_NAME_MAX
-
1
]
=
0
;
strncpy
(
args
.
name
,
p
+
1
,
BTRFS_SUBVOL_NAME_MAX
);
args
.
name
[
BTRFS_SUBVOL_NAME_MAX
-
1
]
=
0
;
ret
=
ioctl
(
fd
,
BTRFS_IOC_SUBVOL_CREATE
,
&
args
);
saved_errno
=
errno
;
INFO
(
"btrfs: snapshot create ioctl returned %d"
,
ret
)
;
close
(
fd
);
free
(
newfull
);
errno
=
saved_errno
;
close
(
fd
)
;
return
ret
;
}
...
...
@@ -303,37 +298,39 @@ out:
int
btrfs_snapshot
(
const
char
*
orig
,
const
char
*
new
)
{
struct
btrfs_ioctl_vol_args_v2
args
;
char
*
newdir
,
*
newname
;
char
*
newfull
=
NULL
;
int
saved_errno
=
-
1
;
int
fd
=
-
1
,
fddst
=
-
1
,
ret
=
-
1
;
struct
btrfs_ioctl_vol_args_v2
args
;
char
*
newdir
,
*
newname
,
*
newfull
=
NULL
;
newfull
=
strdup
(
new
);
if
(
!
newfull
)
if
(
!
newfull
)
{
ERROR
(
"Error: out of memory"
);
goto
out
;
ret
=
rmdir
(
newfull
);
if
(
ret
<
0
&&
errno
!=
ENOENT
)
}
// make sure the directory doesn't already exist
if
(
rmdir
(
newfull
)
<
0
&&
errno
!=
ENOENT
)
{
SYSERROR
(
"Error removing empty new rootfs"
);
goto
out
;
}
newname
=
basename
(
newfull
);
newdir
=
dirname
(
newfull
);
fd
=
open
(
orig
,
O_RDONLY
);
if
(
fd
<
0
)
if
(
fd
<
0
)
{
SYSERROR
(
"Error opening original rootfs %s"
,
orig
);
goto
out
;
newdir
=
dirname
(
newfull
);
}
fddst
=
open
(
newdir
,
O_RDONLY
);
if
(
fddst
<
0
)
if
(
fddst
<
0
)
{
SYSERROR
(
"Error opening new container dir %s"
,
newdir
);
goto
out
;
}
memset
(
&
args
,
0
,
sizeof
(
args
));
args
.
fd
=
fd
;
strncpy
(
args
.
name
,
newname
,
BTRFS_SUBVOL_NAME_MAX
);
args
.
name
[
BTRFS_SUBVOL_NAME_MAX
-
1
]
=
0
;
args
.
name
[
BTRFS_SUBVOL_NAME_MAX
-
1
]
=
0
;
ret
=
ioctl
(
fddst
,
BTRFS_IOC_SNAP_CREATE_V2
,
&
args
);
saved_errno
=
errno
;
INFO
(
"btrfs: snapshot create ioctl returned %d"
,
ret
)
;
out:
if
(
fddst
!=
-
1
)
...
...
@@ -341,31 +338,23 @@ out:
if
(
fd
!=
-
1
)
close
(
fd
);
free
(
newfull
);
if
(
saved_errno
>=
0
)
errno
=
saved_errno
;
return
ret
;
}
int
btrfs_snapshot_wrapper
(
void
*
data
)
static
int
btrfs_snapshot_wrapper
(
void
*
data
)
{
char
*
src
;
struct
rsync_data_char
*
arg
=
data
;
if
(
setgid
(
0
)
<
0
)
{
ERROR
(
"Failed to setgid to 0"
);
return
-
1
;
}
if
(
setgroups
(
0
,
NULL
)
<
0
)
WARN
(
"Failed to clear groups"
);
if
(
setuid
(
0
)
<
0
)
{
ERROR
(
"Failed to setuid to 0"
);
return
-
1
;
}
src
=
lxc_storage_get_path
(
arg
->
src
,
"btrfs"
);
return
btrfs_snapshot
(
src
,
arg
->
dest
);
return
btrfs_snapshot
(
arg
->
src
,
arg
->
dest
);
}
int
btrfs_clonepaths
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
oldname
,
...
...
@@ -373,126 +362,52 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
char
*
src
;
if
(
!
orig
->
dest
||
!
orig
->
src
)
return
-
1
;
if
(
strcmp
(
orig
->
type
,
"btrfs"
)
&&
snap
)
{
ERROR
(
"btrfs snapshot from %s backing store is not supported"
,
orig
->
type
);
return
-
1
;
}
new
->
src
=
lxc_string_join
(
"/"
,
(
const
char
*
[]){
"btrfs:"
,
*
lxcpath
!=
'/'
?
lxcpath
:
++
lxcpath
,
cname
,
"rootfs"
,
NULL
},
false
);
if
(
!
new
->
src
)
{
ERROR
(
"Failed to create new rootfs path"
);
return
-
1
;
}
TRACE
(
"Constructed new rootfs path
\"
%s
\"
"
,
new
->
src
);
src
=
lxc_storage_get_path
(
new
->
src
,
"btrfs"
);
new
->
dest
=
strdup
(
src
);
if
(
!
new
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
src
);
return
-
1
;
}
if
(
orig
->
mntopts
)
{
new
->
mntopts
=
strdup
(
orig
->
mntopts
);
if
(
!
new
->
mntopts
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
orig
->
mntopts
);
if
(
strcmp
(
orig
->
type
,
"btrfs"
))
{
int
len
,
ret
;
if
(
snap
)
{
ERROR
(
"btrfs snapshot from %s backing store is not supported"
,
orig
->
type
);
return
-
1
;
}
}
return
0
;
}
bool
btrfs_create_clone
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
)
{
int
ret
;
struct
rsync_data
data
=
{
0
,
0
};
char
cmd_output
[
MAXPATHLEN
]
=
{
0
};
ret
=
rmdir
(
new
->
dest
);
if
(
ret
<
0
&&
errno
!=
ENOENT
)
return
false
;
ret
=
btrfs_subvolume_create
(
new
->
dest
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create btrfs subvolume
\"
%s
\"
"
,
new
->
dest
);
return
false
;
}
/* rsync the contents from source to target */
data
.
orig
=
orig
;
data
.
new
=
new
;
if
(
am_unpriv
())
{
ret
=
userns_exec_1
(
conf
,
lxc_rsync_exec_wrapper
,
&
data
,
"lxc_rsync_exec_wrapper"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
"
,
orig
->
dest
,
new
->
dest
);
return
false
;
}
return
true
;
}
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootfs"
)
+
3
;
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
return
-
1
;
ret
=
snprintf
(
new
->
src
,
len
,
"%s/%s/rootfs"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
else
{
// in case rootfs is in custom path, reuse it
if
((
new
->
src
=
dir_new_path
(
orig
->
src
,
oldname
,
cname
,
oldpath
,
lxcpath
))
==
NULL
)
return
-
1
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lxc_rsync_exec_wrapper
,
(
void
*
)
&
data
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
: %s"
,
orig
->
dest
,
new
->
dest
,
cmd_output
);
return
false
;
}
return
true
;
}
bool
btrfs_create_snapshot
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
)
{
int
ret
;
ret
=
rmdir
(
new
->
dest
);
if
(
ret
<
0
&&
errno
!=
ENOENT
)
return
false
;
if
(
am_unpriv
())
{
struct
rsync_data_char
args
;
args
.
src
=
orig
->
dest
;
args
.
dest
=
new
->
dest
;
if
((
new
->
dest
=
strdup
(
new
->
src
))
==
NULL
)
return
-
1
;
ret
=
userns_exec_1
(
conf
,
btrfs_snapshot_wrapper
,
&
args
,
"btrfs_snapshot_wrapper"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to run
\"
btrfs_snapshot_wrapper
\"
"
);
return
false
;
}
if
(
orig
->
mntopts
&&
(
new
->
mntopts
=
strdup
(
orig
->
mntopts
))
==
NULL
)
return
-
1
;
TRACE
(
"Created btrfs snapshot
\"
%s
\"
from
\"
%s
\"
"
,
new
->
dest
,
orig
->
dest
);
return
true
;
if
(
snap
)
{
struct
rsync_data_char
sdata
;
if
(
!
am_unpriv
())
return
btrfs_snapshot
(
orig
->
dest
,
new
->
dest
);
sdata
.
dest
=
new
->
dest
;
sdata
.
src
=
orig
->
dest
;
return
userns_exec_1
(
conf
,
btrfs_snapshot_wrapper
,
&
sdata
,
"btrfs_snapshot_wrapper"
);
}
ret
=
btrfs_snapshot
(
orig
->
dest
,
new
->
dest
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create btrfs snapshot
\"
%s
\"
from
\"
%s
\"
"
,
new
->
dest
,
orig
->
dest
);
return
false
;
if
(
rmdir
(
new
->
dest
)
<
0
&&
errno
!=
ENOENT
)
{
SYSERROR
(
"removing %s"
,
new
->
dest
);
return
-
1
;
}
TRACE
(
"Created btrfs snapshot
\"
%s
\"
from
\"
%s
\"
"
,
new
->
dest
,
orig
->
dest
);
return
true
;
return
btrfs_subvolume_create
(
new
->
dest
);
}
static
int
btrfs_do_destroy_subvol
(
const
char
*
path
)
...
...
@@ -816,50 +731,21 @@ bool btrfs_try_remove_subvol(const char *path)
{
if
(
!
btrfs_detect
(
path
))
return
false
;
return
btrfs_recursive_destroy
(
path
)
==
0
;
}
int
btrfs_destroy
(
struct
bdev
*
orig
)
{
char
*
src
;
src
=
lxc_storage_get_path
(
orig
->
src
,
"btrfs"
);
return
btrfs_recursive_destroy
(
src
);
return
btrfs_recursive_destroy
(
orig
->
src
);
}
int
btrfs_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
)
{
int
ret
;
size_t
len
;
len
=
strlen
(
dest
)
+
1
;
/* strlen("btrfs:") */
len
+=
6
;
bdev
->
src
=
malloc
(
len
);
if
(
!
bdev
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
}
ret
=
snprintf
(
bdev
->
src
,
len
,
"btrfs:%s"
,
dest
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
return
-
1
;
}
bdev
->
src
=
strdup
(
dest
);
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
dest
);
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
1
;
}
ret
=
btrfs_subvolume_create
(
bdev
->
dest
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create btrfs subvolume
\"
%s
\"
"
,
bdev
->
dest
);
}
return
ret
;
return
btrfs_subvolume_create
(
bdev
->
dest
);
}
src/lxc/bdev/lxcbtrfs.h
View file @
789edffe
...
...
@@ -412,10 +412,5 @@ int is_btrfs_subvol(const char *path);
bool
btrfs_try_remove_subvol
(
const
char
*
path
);
int
btrfs_same_fs
(
const
char
*
orig
,
const
char
*
new
);
int
btrfs_snapshot
(
const
char
*
orig
,
const
char
*
new
);
int
btrfs_snapshot_wrapper
(
void
*
data
);
bool
btrfs_create_clone
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
);
bool
btrfs_create_snapshot
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
);
#endif // __LXC_BTRFS_H
src/lxc/bdev/lxcdir.c
View file @
789edffe
...
...
@@ -36,101 +36,61 @@ lxc_log_define(lxcdir, lxc);
* name and paths for the new
*/
int
dir_clonepaths
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
oldname
,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
char
*
src_no_prefix
;
int
ret
;
size_t
len
;
int
len
,
ret
;
if
(
snap
)
{
ERROR
(
"
Directories cannot be snapshotted
"
);
ERROR
(
"
directories cannot be snapshotted. Try aufs or overlayfs.
"
);
return
-
1
;
}
if
(
!
orig
->
dest
||
!
orig
->
src
)
return
-
1
;
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootfs"
)
+
4
+
3
;
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootfs"
)
+
3
;
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
new
->
src
)
return
-
1
;
}
ret
=
snprintf
(
new
->
src
,
len
,
"dir:%s/%s/rootfs"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
ret
=
snprintf
(
new
->
src
,
len
,
"%s/%s/rootfs"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
src_no_prefix
=
lxc_storage_get_path
(
new
->
src
,
new
->
type
);
new
->
dest
=
strdup
(
src_no_prefix
);
if
(
!
new
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
new
->
src
);
if
((
new
->
dest
=
strdup
(
new
->
src
))
==
NULL
)
return
-
1
;
}
TRACE
(
"Created new path
\"
%s
\"
for dir storage driver"
,
new
->
dest
);
return
0
;
}
int
dir_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
)
struct
bdev_specs
*
specs
)
{
int
ret
;
const
char
*
src
;
size_t
len
;
/* strlen("dir:") */
len
=
4
;
if
(
specs
&&
specs
->
dir
)
src
=
specs
->
dir
;
bdev
->
src
=
strdup
(
specs
->
dir
)
;
else
src
=
dest
;
len
+=
strlen
(
src
)
+
1
;
bdev
->
src
=
malloc
(
len
);
if
(
!
bdev
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
}
ret
=
snprintf
(
bdev
->
src
,
len
,
"dir:%s"
,
src
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
bdev
->
src
=
strdup
(
dest
);
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
{
ERROR
(
"Out of memory"
);
return
-
1
;
}
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
dest
);
if
(
mkdir_p
(
bdev
->
src
,
0755
)
<
0
)
{
ERROR
(
"Error creating %s"
,
bdev
->
src
);
return
-
1
;
}
ret
=
mkdir_p
(
dest
,
0755
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create directory
\"
%s
\"
"
,
dest
);
if
(
mkdir_p
(
bdev
->
dest
,
0755
)
<
0
)
{
ERROR
(
"Error creating %s"
,
bdev
->
dest
);
return
-
1
;
}
TRACE
(
"Created directory
\"
%s
\"
"
,
dest
);
return
0
;
}
int
dir_destroy
(
struct
bdev
*
orig
)
{
int
ret
;
char
*
src
;
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
src
);
ret
=
lxc_rmdir_onedev
(
src
,
NULL
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to delete
\"
%s
\"
"
,
src
);
if
(
lxc_rmdir_onedev
(
orig
->
src
,
NULL
)
<
0
)
return
-
1
;
}
return
0
;
}
...
...
@@ -140,47 +100,34 @@ int dir_detect(const char *path)
return
1
;
// take their word for it
if
(
is_dir
(
path
))
return
1
;
return
0
;
}
int
dir_mount
(
struct
bdev
*
bdev
)
{
unsigned
long
mntflags
;
char
*
mntdata
;
int
ret
;
unsigned
long
mflags
,
mntflags
;
char
*
src
,
*
mntdata
;
unsigned
long
mflags
;
if
(
strcmp
(
bdev
->
type
,
"dir"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
ret
=
parse_mntopts
(
bdev
->
mntopts
,
&
mntflags
,
&
mntdata
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to parse mount options
\"
%s
\"
"
,
bdev
->
mntopts
);
if
(
parse_mntopts
(
bdev
->
mntopts
,
&
mntflags
,
&
mntdata
)
<
0
)
{
free
(
mntdata
);
return
-
22
;
}
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
|
mntflags
,
mntdata
);
ret
=
mount
(
bdev
->
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
|
mntflags
,
mntdata
);
if
((
0
==
ret
)
&&
(
mntflags
&
MS_RDONLY
))
{
DEBUG
(
"
Remounting
\"
%s
\"
on
\"
%s
\"
readonly
"
,
src
?
src
:
"(none)"
,
bdev
->
dest
?
bdev
->
dest
:
"(none)"
);
mflags
=
add_required_remount_flags
(
src
,
bdev
->
dest
,
MS_BIND
|
MS_REC
|
mntflags
|
MS_REMOUNT
);
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
mflags
,
mntdata
);
DEBUG
(
"
remounting %s on %s with readonly options
"
,
bdev
->
src
?
bdev
->
src
:
"(none)"
,
bdev
->
dest
?
bdev
->
dest
:
"(none)"
);
mflags
=
add_required_remount_flags
(
bdev
->
src
,
bdev
->
dest
,
MS_BIND
|
MS_REC
|
mntflags
|
MS_REMOUNT
);
ret
=
mount
(
bdev
->
src
,
bdev
->
dest
,
"bind"
,
mflags
,
mntdata
);
}
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to mount
\"
%s
\"
on
\"
%s
\"
"
,
src
,
bdev
->
dest
);
free
(
mntdata
);
return
-
1
;
}
TRACE
(
"Mounted
\"
%s
\"
on
\"
%s
\"
"
,
src
,
bdev
->
dest
);
free
(
mntdata
);
return
ret
;
}
...
...
@@ -189,9 +136,7 @@ int dir_umount(struct bdev *bdev)
{
if
(
strcmp
(
bdev
->
type
,
"dir"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
return
umount
(
bdev
->
dest
);
}
src/lxc/bdev/lxcloop.c
View file @
789edffe
...
...
@@ -22,15 +22,12 @@
*/
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS
#include <dirent.h>
#include <errno.h>
#include <inttypes.h>
#include <linux/loop.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/loop.h>
#include <sys/stat.h>
#include <sys/types.h>
...
...
@@ -49,16 +46,16 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype);
* called $lxcpath/$lxcname/rootdev
*/
int
loop_clonepaths
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
oldname
,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
char
fstype
[
100
];
uint64_t
size
=
newsize
;
int
len
,
ret
;
char
*
srcdev
;
char
fstype
[
100
]
=
"ext4"
;
if
(
snap
)
{
ERROR
(
"
The loop storage driver does not support snapshots
"
);
ERROR
(
"
loop devices cannot be snapshotted.
"
);
return
-
1
;
}
...
...
@@ -68,65 +65,43 @@ int loop_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootdev"
)
+
3
;
srcdev
=
alloca
(
len
);
ret
=
snprintf
(
srcdev
,
len
,
"%s/%s/rootdev"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
new
->
src
=
malloc
(
len
+
5
);
if
(
!
new
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
new
->
src
)
return
-
1
;
}
ret
=
snprintf
(
new
->
src
,
(
len
+
5
),
"loop:%s"
,
srcdev
);
if
(
ret
<
0
||
ret
>=
(
len
+
5
))
{
ERROR
(
"Failed to create string"
);
ret
=
snprintf
(
new
->
src
,
len
+
5
,
"loop:%s"
,
srcdev
);
if
(
ret
<
0
||
ret
>=
len
+
5
)
return
-
1
;
}
new
->
dest
=
malloc
(
len
);
if
(
!
new
->
dest
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
new
->
dest
)
return
-
1
;
}
ret
=
snprintf
(
new
->
dest
,
len
,
"%s/%s/rootfs"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
/
* I
t's tempting to say: if orig->src == loopback and !newsize, then
* copy the loopback file. However, we'd have to make sure to correctly
* keep holes!
So punt for now.
*/
/
/ i
t's tempting to say: if orig->src == loopback and !newsize, then
// copy the loopback file. However, we'd have to make sure to
// correctly keep holes!
So punt for now.
if
(
is_blktype
(
orig
))
{
/* detect size */
if
(
!
newsize
&&
blk_getsize
(
orig
,
&
size
)
<
0
)
{
ERROR
(
"Failed to detect size of loop file
\"
%s
\"
"
,
orig
->
src
);
ERROR
(
"Error getting size of %s"
,
orig
->
src
);
return
-
1
;
}
/* detect filesystem */
if
(
detect_fs
(
orig
,
fstype
,
100
)
<
0
)
{
INFO
(
"Failed to detect filesystem type for
\"
%s
\"
"
,
orig
->
src
);
INFO
(
"could not find fstype for %s, using %s"
,
orig
->
src
,
DEFAULT_FSTYPE
);
return
-
1
;
}
}
else
if
(
!
newsize
)
{
}
else
{
sprintf
(
fstype
,
"%s"
,
DEFAULT_FSTYPE
);
if
(
!
newsize
)
size
=
DEFAULT_FS_SIZE
;
}
ret
=
do_loop_create
(
srcdev
,
size
,
fstype
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create loop storage volume
\"
%s
\"
with "
"filesystem
\"
%s
\"
and size
\"
%"
PRIu64
"
\"
"
,
srcdev
,
fstype
,
size
);
return
-
1
;
}
return
0
;
return
do_loop_create
(
srcdev
,
size
,
fstype
);
}
int
loop_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
...
...
@@ -140,35 +115,23 @@ int loop_create(struct bdev *bdev, const char *dest, const char *n,
if
(
!
specs
)
return
-
1
;
/
* <dest> is passed in as <lxcpath>/<lxcname>/rootfs, <srcdev> will
* be <lxcpath>/<lxcname>/rootdev, and <src> will be "loop:<srcdev>".
*/
/
/ dest is passed in as $lxcpath / $lxcname / rootfs
// srcdev will be: $lxcpath / $lxcname / rootdev
// src will be 'loop:$srcdev'
len
=
strlen
(
dest
)
+
2
;
srcdev
=
alloca
(
len
);
ret
=
snprintf
(
srcdev
,
len
,
"%s"
,
dest
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
return
-
1
;
}
ret
=
sprintf
(
srcdev
+
len
-
4
,
"dev"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create string"
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
sprintf
(
srcdev
+
len
-
4
,
"dev"
);
bdev
->
src
=
malloc
(
len
+
5
);
if
(
!
bdev
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
bdev
->
src
)
return
-
1
;
}
ret
=
snprintf
(
bdev
->
src
,
len
+
5
,
"loop:%s"
,
srcdev
);
if
(
ret
<
0
||
ret
>=
len
+
5
)
{
ERROR
(
"Failed to create string"
);
if
(
ret
<
0
||
ret
>=
len
+
5
)
return
-
1
;
}
sz
=
specs
->
fssize
;
if
(
!
sz
)
...
...
@@ -178,31 +141,19 @@ int loop_create(struct bdev *bdev, const char *dest, const char *n,
if
(
!
fstype
)
fstype
=
DEFAULT_FSTYPE
;
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
dest
);
if
(
!
(
bdev
->
dest
=
strdup
(
dest
)))
return
-
1
;
}
ret
=
mkdir_p
(
bdev
->
dest
,
0755
);
if
(
ret
<
0
)
{
ERROR
(
"Failed creating directory
\"
%s
\"
"
,
bdev
->
dest
);
if
(
mkdir_p
(
bdev
->
dest
,
0755
)
<
0
)
{
ERROR
(
"Error creating %s"
,
bdev
->
dest
);
return
-
1
;
}
ret
=
do_loop_create
(
srcdev
,
sz
,
fstype
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create loop storage volume
\"
%s
\"
with "
"filesystem
\"
%s
\"
and size
\"
%"
PRIu64
"
\"
"
,
srcdev
,
fstype
,
sz
);
return
-
1
;
}
return
0
;
return
do_loop_create
(
srcdev
,
sz
,
fstype
);
}
int
loop_destroy
(
struct
bdev
*
orig
)
{
int
loop_destroy
(
struct
bdev
*
orig
)
{
return
unlink
(
orig
->
src
+
5
);
}
...
...
@@ -228,7 +179,7 @@ int loop_mount(struct bdev *bdev)
{
int
ret
,
loopfd
;
char
loname
[
MAXPATHLEN
];
char
*
src
;
char
*
src
=
bdev
->
src
;
if
(
strcmp
(
bdev
->
type
,
"loop"
))
return
-
22
;
...
...
@@ -237,98 +188,73 @@ int loop_mount(struct bdev *bdev)
return
-
22
;
/* skip prefix */
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
if
(
!
strncmp
(
bdev
->
src
,
"loop:"
,
5
))
src
+=
5
;
loopfd
=
lxc_prepare_loop_dev
(
src
,
loname
,
LO_FLAGS_AUTOCLEAR
);
if
(
loopfd
<
0
)
{
ERROR
(
"
F
ailed to prepare loop device for loop file
\"
%s
\"
"
,
src
);
ERROR
(
"
f
ailed to prepare loop device for loop file
\"
%s
\"
"
,
src
);
return
-
1
;
}
DEBUG
(
"
P
repared loop device
\"
%s
\"
"
,
loname
);
DEBUG
(
"
p
repared loop device
\"
%s
\"
"
,
loname
);
ret
=
mount_unknown_fs
(
loname
,
bdev
->
dest
,
bdev
->
mntopts
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to mount rootfs
\"
%s
\"
on
\"
%s
\"
via loop device
\"
%s
\"
"
,
bdev
->
src
,
bdev
->
dest
,
loname
);
close
(
loopfd
);
return
-
1
;
}
bdev
->
lofd
=
loopfd
;
DEBUG
(
"Mounted rootfs
\"
%s
\"
on
\"
%s
\"
via loop device
\"
%s
\"
"
,
bdev
->
src
,
bdev
->
dest
,
loname
);
if
(
ret
<
0
)
ERROR
(
"failed to mount rootfs
\"
%s
\"
onto
\"
%s
\"
via loop device
\"
%s
\"
"
,
bdev
->
src
,
bdev
->
dest
,
loname
);
else
bdev
->
lofd
=
loopfd
;
DEBUG
(
"mounted rootfs
\"
%s
\"
onto
\"
%s
\"
via loop device
\"
%s
\"
"
,
bdev
->
src
,
bdev
->
dest
,
loname
);
return
0
;
return
ret
;
}
int
loop_umount
(
struct
bdev
*
bdev
)
{
int
ret
,
saved_errno
;
int
ret
;
if
(
strcmp
(
bdev
->
type
,
"loop"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
ret
=
umount
(
bdev
->
dest
);
saved_errno
=
errno
;
if
(
bdev
->
lofd
>=
0
)
{
close
(
bdev
->
lofd
);
bdev
->
lofd
=
-
1
;
}
errno
=
saved_errno
;
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to umount
\"
%s
\"
"
,
bdev
->
dest
);
return
-
1
;
}
return
0
;
return
ret
;
}
static
int
do_loop_create
(
const
char
*
path
,
uint64_t
size
,
const
char
*
fstype
)
{
int
fd
,
ret
;
char
cmd_output
[
MAXPATHLEN
];
const
char
*
cmd_args
[
2
]
=
{
fstype
,
path
};
char
cmd_output
[
MAXPATHLEN
];
/* create the new loopback file */
fd
=
creat
(
path
,
S_IRUSR
|
S_IWUSR
);
if
(
fd
<
0
)
{
SYSERROR
(
"Failed to create new loop file
\"
%s
\"
"
,
path
);
// create the new loopback file.
fd
=
creat
(
path
,
S_IRUSR
|
S_IWUSR
);
if
(
fd
<
0
)
return
-
1
;
}
ret
=
lseek
(
fd
,
size
,
SEEK_SET
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to seek to set new loop file size for loop "
"file
\"
%s
\"
"
,
path
);
if
(
lseek
(
fd
,
size
,
SEEK_SET
)
<
0
)
{
SYSERROR
(
"Error seeking to set new loop file size"
);
close
(
fd
);
return
-
1
;
}
ret
=
write
(
fd
,
"1"
,
1
);
if
(
ret
!=
1
)
{
SYSERROR
(
"Failed creating new loop file
\"
%s
\"
"
,
path
);
if
(
write
(
fd
,
"1"
,
1
)
!=
1
)
{
SYSERROR
(
"Error creating new loop file"
);
close
(
fd
);
return
-
1
;
}
ret
=
close
(
fd
);
if
(
ret
<
0
)
{
SYSERROR
(
"
Failed to create new loop file
\"
%s
\"
"
,
path
);
SYSERROR
(
"
Error closing new loop file"
);
return
-
1
;
}
// create an fs in the loopback file
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
do_mkfs_exec_wrapper
,
(
void
*
)
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create new filesystem
\"
%s
\"
for loop file "
"
\"
%s
\"
: %s"
,
fstype
,
path
,
cmd_output
);
if
(
ret
<
0
)
return
-
1
;
}
return
0
;
}
src/lxc/bdev/lxclvm.c
View file @
789edffe
...
...
@@ -22,8 +22,8 @@
*/
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#define __STDC_FORMAT_MACROS
/* Required for PRIu64 to work. */
#include <inttypes.h>
/* Required for PRIu64 to work. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
...
...
@@ -36,238 +36,155 @@
#include "config.h"
#include "log.h"
#include "lxclvm.h"
#include "lxcrsync.h"
#include "storage_utils.h"
#include "utils.h"
/* major()/minor() */
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#
include <sys/mkdev.h>
#endif
lxc_log_define
(
lxclvm
,
lxc
);
struct
lvcreate_args
{
const
char
*
size
;
const
char
*
vg
;
const
char
*
lv
;
const
char
*
thinpool
;
/* snapshot specific arguments */
const
char
*
source_lv
;
};
static
int
lvm_destroy_exec_wrapper
(
void
*
data
)
{
struct
lvcreate_args
*
args
=
data
;
(
void
)
setenv
(
"LVM_SUPPRESS_FD_WARNINGS"
,
"1"
,
1
);
execlp
(
"lvremove"
,
"lvremove"
,
"-f"
,
args
->
lv
,
(
char
*
)
NULL
);
return
-
1
;
}
static
int
lvm_create_exec_wrapper
(
void
*
data
)
{
struct
lvcreate_args
*
args
=
data
;
(
void
)
setenv
(
"LVM_SUPPRESS_FD_WARNINGS"
,
"1"
,
1
);
if
(
args
->
thinpool
)
execlp
(
"lvcreate"
,
"lvcreate"
,
"--thinpool"
,
args
->
thinpool
,
"-V"
,
args
->
size
,
args
->
vg
,
"-n"
,
args
->
lv
,
(
char
*
)
NULL
);
else
execlp
(
"lvcreate"
,
"lvcreate"
,
"-L"
,
args
->
size
,
args
->
vg
,
"-n"
,
args
->
lv
,
(
char
*
)
NULL
);
return
-
1
;
}
static
int
lvm_snapshot_exec_wrapper
(
void
*
data
)
{
struct
lvcreate_args
*
args
=
data
;
(
void
)
setenv
(
"LVM_SUPPRESS_FD_WARNINGS"
,
"1"
,
1
);
if
(
args
->
thinpool
)
execlp
(
"lvcreate"
,
"lvcreate"
,
"-s"
,
"-n"
,
args
->
lv
,
args
->
source_lv
,
(
char
*
)
NULL
);
else
execlp
(
"lvcreate"
,
"lvcreate"
,
"-s"
,
"-L"
,
args
->
size
,
"-n"
,
args
->
lv
,
args
->
source_lv
,
(
char
*
)
NULL
);
return
-
1
;
}
/* The path must be "/dev/<vg>/<lv>". The volume group <vg> must be an existing
* volume group, and the logical volume <lv> must not yet exist.
* This function will attempt to create "/dev/<vg>/<lv> of size <size>. If
* thinpool is specified, we'll check for it's existence and if it's a valid
* thin pool, and if so, we'll create the requested logical volume from that
* thin pool.
*/
static
int
do_lvm_create
(
const
char
*
path
,
uint64_t
size
,
const
char
*
thinpool
)
extern
char
*
dir_new_path
(
char
*
src
,
const
char
*
oldname
,
const
char
*
name
,
const
char
*
oldpath
,
const
char
*
lxcpath
);
/*
* LVM ops
*/
/*
* path must be '/dev/$vg/$lv', $vg must be an existing VG, and $lv must not
* yet exist. This function will attempt to create /dev/$vg/$lv of size
* $size. If thinpool is specified, we'll check for it's existence and if
* it's
* 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
,
uint64_t
size
,
const
char
*
thinpool
)
{
int
len
,
ret
;
char
*
pathdup
,
*
vg
,
*
lv
;
char
cmd_output
[
MAXPATHLEN
];
char
sz
[
24
];
char
*
tp
=
NULL
;
struct
lvcreate_args
cmd_args
=
{
0
};
int
ret
,
pid
,
len
;
char
sz
[
24
],
*
pathdup
,
*
vg
,
*
lv
,
*
tp
=
NULL
;
ret
=
snprintf
(
sz
,
24
,
"%"
PRIu64
"b"
,
size
);
if
(
ret
<
0
||
ret
>=
24
)
{
ERROR
(
"Failed to create string: %d"
,
ret
);
if
((
pid
=
fork
())
<
0
)
{
SYSERROR
(
"failed fork"
);
return
-
1
;
}
if
(
pid
>
0
)
return
wait_for_pid
(
pid
);
// specify bytes to lvcreate
ret
=
snprintf
(
sz
,
24
,
"%"
PRIu64
"b"
,
size
);
if
(
ret
<
0
||
ret
>=
24
)
exit
(
EXIT_FAILURE
);
pathdup
=
strdup
(
path
);
if
(
!
pathdup
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
path
);
return
-
1
;
}
if
(
!
pathdup
)
exit
(
EXIT_FAILURE
);
lv
=
strrchr
(
pathdup
,
'/'
);
if
(
!
lv
)
{
ERROR
(
"Failed to detect
\"
/
\"
in string
\"
%s
\"
"
,
pathdup
);
free
(
pathdup
);
return
-
1
;
}
if
(
!
lv
)
exit
(
EXIT_FAILURE
);
*
lv
=
'\0'
;
lv
++
;
TRACE
(
"Parsed logical volume
\"
%s
\"
"
,
lv
);
vg
=
strrchr
(
pathdup
,
'/'
);
if
(
!
vg
)
{
ERROR
(
"Failed to detect
\"
/
\"
in string
\"
%s
\"
"
,
pathdup
);
free
(
pathdup
);
return
-
1
;
}
if
(
!
vg
)
exit
(
EXIT_FAILURE
);
vg
++
;
TRACE
(
"Parsed volume group
\"
%s
\"
"
,
vg
);
if
(
thinpool
)
{
len
=
strlen
(
pathdup
)
+
strlen
(
thinpool
)
+
2
;
tp
=
alloca
(
len
);
ret
=
snprintf
(
tp
,
len
,
"%s/%s"
,
pathdup
,
thinpool
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string: %d"
,
ret
);
free
(
pathdup
);
return
-
1
;
}
if
(
ret
<
0
||
ret
>=
len
)
exit
(
EXIT_FAILURE
);
ret
=
lvm_is_thin_pool
(
tp
);
TRACE
(
"got %d for thin pool at path: %s"
,
ret
,
tp
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to detect whether
\"
%s
\"
is a thinpool"
,
tp
);
free
(
pathdup
);
return
-
1
;
}
else
if
(
!
ret
)
{
TRACE
(
"Detected that
\"
%s
\"
is not a thinpool"
,
tp
);
INFO
(
"got %d for thin pool at path: %s"
,
ret
,
tp
);
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
if
(
!
ret
)
tp
=
NULL
;
}
else
{
TRACE
(
"Detected
\"
%s
\"
is a thinpool"
,
tp
);
}
}
cmd_args
.
thinpool
=
tp
;
cmd_args
.
vg
=
vg
;
cmd_args
.
lv
=
lv
;
cmd_args
.
size
=
sz
;
TRACE
(
"Creating new lvm storage volume
\"
%s
\"
on volume group
\"
%s
\"
"
"of size
\"
%s
\"
"
,
lv
,
vg
,
sz
);
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lvm_create_exec_wrapper
,
(
void
*
)
&
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create logical volume
\"
%s
\"
: %s"
,
lv
,
cmd_output
);
free
(
pathdup
);
return
-
1
;
}
TRACE
(
"Created new lvm storage volume
\"
%s
\"
on volume group
\"
%s
\"
"
"of size
\"
%s
\"
"
,
lv
,
vg
,
sz
);
(
void
)
setenv
(
"LVM_SUPPRESS_FD_WARNINGS"
,
"1"
,
1
);
if
(
!
tp
)
execlp
(
"lvcreate"
,
"lvcreate"
,
"-L"
,
sz
,
vg
,
"-n"
,
lv
,
(
char
*
)
NULL
);
else
execlp
(
"lvcreate"
,
"lvcreate"
,
"--thinpool"
,
tp
,
"-V"
,
sz
,
vg
,
"-n"
,
lv
,
(
char
*
)
NULL
);
free
(
pathdup
);
return
ret
;
SYSERROR
(
"execlp"
);
exit
(
EXIT_FAILURE
)
;
}
/* Look at "/sys/dev/block/maj:min/dm/uuid". If it contains the hardcoded LVM
* prefix "LVM-" then this is an lvm2 LV.
/*
* Look at /sys/dev/block/maj:min/dm/uuid. If it contains the hardcoded LVM
* prefix "LVM-", then this is an lvm2 LV
*/
int
lvm_detect
(
const
char
*
path
)
{
int
fd
;
ssize_t
ret
;
struct
stat
statbuf
;
char
devp
[
MAXPATHLEN
],
buf
[
4
];
FILE
*
fout
;
int
ret
;
struct
stat
statbuf
;
if
(
strncmp
(
path
,
"lvm:"
,
4
)
==
0
)
return
1
;
// take their word for it
ret
=
stat
(
path
,
&
statbuf
);
if
(
ret
<
0
)
if
(
ret
!=
0
)
return
0
;
if
(
!
S_ISBLK
(
statbuf
.
st_mode
))
return
0
;
ret
=
snprintf
(
devp
,
MAXPATHLEN
,
"/sys/dev/block/%d:%d/dm/uuid"
,
major
(
statbuf
.
st_rdev
),
minor
(
statbuf
.
st_rdev
));
major
(
statbuf
.
st_rdev
),
minor
(
statbuf
.
st_rdev
));
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
{
ERROR
(
"
Failed to create stri
ng"
);
ERROR
(
"
lvm uuid pathname too lo
ng"
);
return
0
;
}
fd
=
open
(
devp
,
O_RDONLY
);
if
(
fd
<
0
)
return
0
;
ret
=
read
(
fd
,
buf
,
sizeof
(
buf
));
close
(
fd
);
if
(
ret
!=
sizeof
(
buf
))
fout
=
fopen
(
devp
,
"r"
);
if
(
!
fout
)
return
0
;
if
(
strncmp
(
buf
,
"LVM-"
,
4
))
ret
=
fread
(
buf
,
1
,
4
,
fout
);
fclose
(
fout
);
if
(
ret
!=
4
||
strncmp
(
buf
,
"LVM-"
,
4
)
!=
0
)
return
0
;
return
1
;
}
int
lvm_mount
(
struct
bdev
*
bdev
)
{
char
*
src
;
if
(
strcmp
(
bdev
->
type
,
"lvm"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
/* If we might pass in data sometime, then we'll have to enrich
* mount_unknown_fs().
*/
return
mount_unknown_fs
(
src
,
bdev
->
dest
,
bdev
->
mntopts
);
/* if we might pass in data sometime, then we'll have to enrich
* mount_unknown_fs */
return
mount_unknown_fs
(
bdev
->
src
,
bdev
->
dest
,
bdev
->
mntopts
);
}
int
lvm_umount
(
struct
bdev
*
bdev
)
{
if
(
strcmp
(
bdev
->
type
,
"lvm"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
return
umount
(
bdev
->
dest
);
}
int
lvm_compare_lv_attr
(
const
char
*
path
,
int
pos
,
const
char
expected
)
{
struct
lxc_popen_FILE
*
f
;
int
ret
,
len
,
status
;
char
*
cmd
;
char
output
[
12
];
int
start
=
0
;
int
ret
,
len
,
status
,
start
=
0
;
char
*
cmd
,
output
[
12
];
const
char
*
lvscmd
=
"lvs --unbuffered --noheadings -o lv_attr %s 2>/dev/null"
;
len
=
strlen
(
lvscmd
)
+
strlen
(
path
)
-
1
;
...
...
@@ -278,22 +195,23 @@ int lvm_compare_lv_attr(const char *path, int pos, const char expected)
return
-
1
;
f
=
lxc_popen
(
cmd
);
if
(
!
f
)
{
if
(
f
==
NULL
)
{
SYSERROR
(
"popen failed"
);
return
-
1
;
}
if
(
!
fgets
(
output
,
12
,
f
->
f
))
ret
=
1
;
ret
=
fgets
(
output
,
12
,
f
->
f
)
==
NULL
;
status
=
lxc_pclose
(
f
);
/* Assume either vg or lvs do not exist, default comparison to false. */
if
(
ret
||
WEXITSTATUS
(
status
))
// Assume either vg or lvs do not exist, default
// comparison to false.
return
0
;
len
=
strlen
(
output
);
while
(
start
<
len
&&
output
[
start
]
==
' '
)
start
++
;
while
(
start
<
len
&&
output
[
start
]
==
' '
)
start
++
;
if
(
start
+
pos
<
len
&&
output
[
start
+
pos
]
==
expected
)
return
1
;
...
...
@@ -313,261 +231,155 @@ int lvm_is_thin_pool(const char *path)
int
lvm_snapshot
(
const
char
*
orig
,
const
char
*
path
,
uint64_t
size
)
{
int
ret
;
char
*
pathdup
,
*
lv
;
char
sz
[
24
];
char
cmd_output
[
MAXPATHLEN
];
struct
lvcreate_args
cmd_args
=
{
0
};
int
ret
,
pid
;
char
sz
[
24
],
*
pathdup
,
*
lv
;
ret
=
snprintf
(
sz
,
24
,
"%"
PRIu64
"b"
,
size
);
if
(
ret
<
0
||
ret
>=
24
)
{
ERROR
(
"Failed to create string"
);
if
((
pid
=
fork
())
<
0
)
{
SYSERROR
(
"failed fork"
);
return
-
1
;
}
if
(
pid
>
0
)
return
wait_for_pid
(
pid
);
pathdup
=
strdup
(
path
);
if
(
!
pathdup
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
path
);
return
-
1
;
}
// specify bytes to lvcreate
ret
=
snprintf
(
sz
,
24
,
"%"
PRIu64
"b"
,
size
);
if
(
ret
<
0
||
ret
>=
24
)
exit
(
EXIT_FAILURE
);
pathdup
=
strdup
(
path
);
if
(
!
pathdup
)
exit
(
EXIT_FAILURE
);
lv
=
strrchr
(
pathdup
,
'/'
);
if
(
!
lv
)
{
ERROR
(
"Failed to detect
\"
/
\"
in string
\"
%s
\"
"
,
pathdup
);
free
(
pathdup
);
return
-
1
;
exit
(
EXIT_FAILURE
)
;
}
*
lv
=
'\0'
;
lv
++
;
TRACE
(
"Parsed logical volume
\"
%s
\"
"
,
lv
);
/* Check if the original logical volume is backed by a thinpool, in
* which case we cannot specify a size that's different from the
* original size.
*/
// check if the original lv is backed by a thin pool, in which case we
// cannot specify a size that's different from the original size.
ret
=
lvm_is_thin_volume
(
orig
);
if
(
ret
<
0
)
{
if
(
ret
==
-
1
)
{
free
(
pathdup
);
return
-
1
;
}
else
if
(
ret
)
{
cmd_args
.
thinpool
=
orig
;
}
cmd_args
.
lv
=
lv
;
cmd_args
.
source_lv
=
orig
;
cmd_args
.
size
=
sz
;
TRACE
(
"Creating new lvm snapshot
\"
%s
\"
of
\"
%s
\"
with size
\"
%s
\"
"
,
lv
,
orig
,
sz
);
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lvm_snapshot_exec_wrapper
,
(
void
*
)
&
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create logical volume
\"
%s
\"
: %s"
,
orig
,
cmd_output
);
free
(
pathdup
);
return
-
1
;
(
void
)
setenv
(
"LVM_SUPPRESS_FD_WARNINGS"
,
"1"
,
1
);
if
(
!
ret
)
{
ret
=
execlp
(
"lvcreate"
,
"lvcreate"
,
"-s"
,
"-L"
,
sz
,
"-n"
,
lv
,
orig
,
(
char
*
)
NULL
);
}
else
{
ret
=
execlp
(
"lvcreate"
,
"lvcreate"
,
"-s"
,
"-n"
,
lv
,
orig
,
(
char
*
)
NULL
);
}
free
(
pathdup
);
return
0
;
exit
(
EXIT_FAILURE
)
;
}
int
lvm_clonepaths
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
oldname
,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
char
fstype
[
100
];
uint64_t
size
=
newsize
;
int
len
,
ret
;
const
char
*
vg
;
const
char
*
cmd_args
[
2
];
char
cmd_output
[
MAXPATHLEN
];
if
(
!
orig
->
src
||
!
orig
->
dest
)
return
-
1
;
if
(
strcmp
(
orig
->
type
,
"lvm"
)
&&
snap
)
{
ERROR
(
"LVM snapshot from
\"
%s
\"
storage driver is not supported"
,
orig
->
type
);
return
-
1
;
}
if
(
strcmp
(
orig
->
type
,
"lvm"
))
{
vg
=
lxc_global_config_value
(
"lxc.bdev.lvm.vg"
);
new
->
src
=
lxc_string_join
(
"/"
,
(
const
char
*
[]){
"lvm:"
,
"dev"
,
vg
,
cname
,
NULL
},
false
);
}
else
{
char
*
dup
,
*
slider
,
*
src
;
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
const
char
*
vg
;
dup
=
strdup
(
src
);
if
(
!
dup
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
src
);
if
(
snap
)
{
ERROR
(
"LVM snapshot from %s backing store is not supported"
,
orig
->
type
);
return
-
1
;
}
slider
=
strrchr
(
dup
,
'/'
);
if
(
!
slider
)
{
ERROR
(
"Failed to detect
\"
/
\"
in string
\"
%s
\"
"
,
dup
);
free
(
dup
);
vg
=
lxc_global_config_value
(
"lxc.bdev.lvm.vg"
);
len
=
strlen
(
"/dev/"
)
+
strlen
(
vg
)
+
strlen
(
cname
)
+
2
;
if
((
new
->
src
=
malloc
(
len
))
==
NULL
)
return
-
1
;
ret
=
snprintf
(
new
->
src
,
len
,
"/dev/%s/%s"
,
vg
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
else
{
new
->
src
=
dir_new_path
(
orig
->
src
,
oldname
,
cname
,
oldpath
,
lxcpath
);
if
(
!
new
->
src
)
return
-
1
;
}
*
slider
=
'\0'
;
slider
=
dup
;
new
->
src
=
lxc_string_join
(
"/"
,
(
const
char
*
[]){
"lvm:"
,
*
slider
==
'/'
?
++
slider
:
slider
,
cname
,
NULL
},
false
);
free
(
dup
);
}
if
(
!
new
->
src
)
{
ERROR
(
"Failed to create string"
);
return
-
1
;
}
if
(
orig
->
mntopts
)
{
new
->
mntopts
=
strdup
(
orig
->
mntopts
);
if
(
!
new
->
mntopts
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
orig
->
mntopts
);
if
(
!
new
->
mntopts
)
return
-
1
;
}
}
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootfs"
)
+
3
;
new
->
dest
=
malloc
(
len
);
if
(
!
new
->
dest
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
new
->
dest
)
return
-
1
;
}
ret
=
snprintf
(
new
->
dest
,
len
,
"%s/%s/rootfs"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
ret
=
mkdir_p
(
new
->
dest
,
0755
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
new
->
dest
);
if
(
mkdir_p
(
new
->
dest
,
0755
)
<
0
)
return
-
1
;
}
return
0
;
}
bool
lvm_create_clone
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
)
{
char
*
src
;
const
char
*
thinpool
;
int
ret
;
struct
rsync_data
data
;
char
*
cmd_args
[
2
];
char
cmd_output
[
MAXPATHLEN
];
char
fstype
[
100
]
=
"ext4"
;
uint64_t
size
=
newsize
;
if
(
is_blktype
(
orig
))
{
/* detect size */
if
(
!
newsize
&&
blk_getsize
(
orig
,
&
size
)
<
0
)
{
ERROR
(
"Failed to detect size of logical volume
\"
%s
\"
"
,
orig
->
src
);
ERROR
(
"Error getting size of %s"
,
orig
->
src
);
return
-
1
;
}
/* detect filesystem */
if
(
detect_fs
(
orig
,
fstype
,
100
)
<
0
)
{
INFO
(
"
Failed to detect filesystem type for
\"
%s
\"
"
,
orig
->
src
);
INFO
(
"
could not find fstype for %s, using ext3
"
,
orig
->
src
);
return
-
1
;
}
}
else
if
(
!
newsize
)
{
}
else
{
sprintf
(
fstype
,
"ext3"
);
if
(
!
newsize
)
size
=
DEFAULT_FS_SIZE
;
}
src
=
lxc_storage_get_path
(
new
->
src
,
"lvm"
);
thinpool
=
lxc_global_config_value
(
"lxc.bdev.lvm.thin_pool"
);
ret
=
do_lvm_create
(
src
,
size
,
thinpool
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create lvm storage volume
\"
%s
\"
"
,
src
);
return
-
1
;
}
cmd_args
[
0
]
=
fstype
;
cmd_args
[
1
]
=
src
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
do_mkfs_exec_wrapper
,
(
void
*
)
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create new filesystem
\"
%s
\"
for lvm storage "
"volume
\"
%s
\"
: %s"
,
fstype
,
src
,
cmd_output
);
return
-
1
;
}
data
.
orig
=
orig
;
data
.
new
=
new
;
ret
=
rsync_rootfs
(
&
data
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to rsync from
\"
%s
\"
to
\"
%s
\"
"
,
orig
->
dest
,
new
->
dest
);
return
false
;
}
TRACE
(
"Created lvm storage volume
\"
%s
\"
"
,
new
->
dest
);
return
true
;
}
bool
lvm_create_snapshot
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
)
{
int
ret
;
char
*
newsrc
,
*
origsrc
;
uint64_t
size
=
newsize
;
if
(
is_blktype
(
orig
))
{
if
(
!
newsize
&&
blk_getsize
(
orig
,
&
size
)
<
0
)
{
ERROR
(
"Failed to detect size of logical volume
\"
%s
\"
"
,
orig
->
src
);
if
(
snap
)
{
if
(
lvm_snapshot
(
orig
->
src
,
new
->
src
,
size
)
<
0
)
{
ERROR
(
"could not create %s snapshot of %s"
,
new
->
src
,
orig
->
src
);
return
-
1
;
}
}
else
{
if
(
do_lvm_create
(
new
->
src
,
size
,
lxc_global_config_value
(
"lxc.bdev.lvm.thin_pool"
))
<
0
)
{
ERROR
(
"Error creating new lvm blockdev"
);
return
-
1
;
}
}
else
if
(
!
newsize
)
{
size
=
DEFAULT_FS_SIZE
;
}
origsrc
=
lxc_storage_get_path
(
orig
->
src
,
"lvm"
);
newsrc
=
lxc_storage_get_path
(
new
->
src
,
"lvm"
);
ret
=
lvm_snapshot
(
origsrc
,
newsrc
,
size
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create lvm
\"
%s
\"
snapshot of
\"
%s
\"
"
,
new
->
src
,
orig
->
src
);
return
false
;
cmd_args
[
0
]
=
fstype
;
cmd_args
[
1
]
=
new
->
src
;
// create an fs in the loopback file
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
do_mkfs_exec_wrapper
,
(
void
*
)
cmd_args
);
if
(
ret
<
0
)
return
-
1
;
}
TRACE
(
"Created lvm snapshot
\"
%s
\"
from
\"
%s
\"
"
,
new
->
dest
,
orig
->
dest
);
return
true
;
return
0
;
}
int
lvm_destroy
(
struct
bdev
*
orig
)
{
int
ret
;
char
cmd_output
[
MAXPATHLEN
];
struct
lvcreate_args
cmd_args
=
{
0
};
cmd_args
.
lv
=
lxc_storage_get_path
(
orig
->
src
,
"lvm"
);
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lvm_destroy_exec_wrapper
,
(
void
*
)
&
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to destroy logical volume
\"
%s
\"
: %s"
,
orig
->
src
,
cmd_output
);
pid_t
pid
;
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
!
pid
)
{
(
void
)
setenv
(
"LVM_SUPPRESS_FD_WARNINGS"
,
"1"
,
1
);
execlp
(
"lvremove"
,
"lvremove"
,
"-f"
,
orig
->
src
,
(
char
*
)
NULL
);
exit
(
EXIT_FAILURE
);
}
TRACE
(
"Destroyed logical volume
\"
%s
\"
"
,
orig
->
src
);
return
0
;
return
wait_for_pid
(
pid
);
}
int
lvm_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
)
struct
bdev_specs
*
specs
)
{
const
char
*
vg
,
*
thinpool
,
*
fstype
,
*
lv
=
n
;
uint64_t
sz
;
...
...
@@ -590,28 +402,22 @@ int lvm_create(struct bdev *bdev, const char *dest, const char *n,
if
(
specs
->
lvm
.
lv
)
lv
=
specs
->
lvm
.
lv
;
len
=
strlen
(
vg
)
+
strlen
(
lv
)
+
4
+
7
;
len
=
strlen
(
vg
)
+
strlen
(
lv
)
+
7
;
bdev
->
src
=
malloc
(
len
);
if
(
!
bdev
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
bdev
->
src
)
return
-
1
;
}
ret
=
snprintf
(
bdev
->
src
,
len
,
"lvm:/dev/%s/%s"
,
vg
,
lv
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
ret
=
snprintf
(
bdev
->
src
,
len
,
"/dev/%s/%s"
,
vg
,
lv
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
/
* size is in bytes */
/
/ fssize is in bytes.
sz
=
specs
->
fssize
;
if
(
!
sz
)
sz
=
DEFAULT_FS_SIZE
;
ret
=
do_lvm_create
(
bdev
->
src
+
4
,
sz
,
thinpool
);
if
(
ret
<
0
)
{
ERROR
(
"Error creating new logical volume
\"
%s
\"
of size "
"
\"
%"
PRIu64
" bytes
\"
"
,
bdev
->
src
,
sz
);
if
(
do_lvm_create
(
bdev
->
src
,
sz
,
thinpool
)
<
0
)
{
ERROR
(
"Error creating new lvm blockdev %s size %"
PRIu64
" bytes"
,
bdev
->
src
,
sz
);
return
-
1
;
}
...
...
@@ -620,27 +426,19 @@ int lvm_create(struct bdev *bdev, const char *dest, const char *n,
fstype
=
DEFAULT_FSTYPE
;
cmd_args
[
0
]
=
fstype
;
cmd_args
[
1
]
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
)
;
cmd_args
[
1
]
=
bdev
->
src
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
do_mkfs_exec_wrapper
,
(
void
*
)
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create new logical volume
\"
%s
\"
: %s"
,
bdev
->
src
,
cmd_output
);
if
(
ret
<
0
)
return
-
1
;
}
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
dest
);
if
(
!
(
bdev
->
dest
=
strdup
(
dest
)))
return
-
1
;
}
ret
=
mkdir_p
(
bdev
->
dest
,
0755
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
bdev
->
dest
);
if
(
mkdir_p
(
bdev
->
dest
,
0755
)
<
0
)
{
ERROR
(
"Error creating %s"
,
bdev
->
dest
);
return
-
1
;
}
TRACE
(
"Created new logical volume
\"
%s
\"
"
,
bdev
->
dest
);
return
0
;
}
src/lxc/bdev/lxclvm.h
View file @
789edffe
...
...
@@ -25,7 +25,6 @@
#define __LXC_LVM_H
#define _GNU_SOURCE
#include <stdbool.h>
#include <stdint.h>
/* defined in bdev.h */
...
...
@@ -53,9 +52,5 @@ int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
int
lvm_destroy
(
struct
bdev
*
orig
);
int
lvm_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
);
bool
lvm_create_clone
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
);
bool
lvm_create_snapshot
(
struct
lxc_conf
*
conf
,
struct
bdev
*
orig
,
struct
bdev
*
new
,
uint64_t
newsize
);
#endif
/* __LXC_LVM_H */
src/lxc/bdev/lxcnbd.c
View file @
789edffe
...
...
@@ -116,21 +116,17 @@ int nbd_detect(const char *path)
int
nbd_mount
(
struct
bdev
*
bdev
)
{
int
ret
=
-
1
,
partition
;
char
*
src
;
char
path
[
50
];
if
(
strcmp
(
bdev
->
type
,
"nbd"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
/* nbd_idx should have been copied by bdev_init from the lxc_conf */
if
(
bdev
->
nbd_idx
<
0
)
return
-
22
;
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
partition
=
nbd_get_partition
(
src
);
partition
=
nbd_get_partition
(
bdev
->
src
);
if
(
partition
)
ret
=
snprintf
(
path
,
50
,
"/dev/nbd%dp%d"
,
bdev
->
nbd_idx
,
partition
);
...
...
@@ -155,13 +151,14 @@ int nbd_mount(struct bdev *bdev)
int
nbd_umount
(
struct
bdev
*
bdev
)
{
int
ret
;
if
(
strcmp
(
bdev
->
type
,
"nbd"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
return
umount
(
bdev
->
dest
)
;
ret
=
umount
(
bdev
->
dest
);
return
ret
;
}
bool
requires_nbd
(
const
char
*
path
)
...
...
src/lxc/bdev/lxcoverlay.c
View file @
789edffe
...
...
@@ -34,7 +34,6 @@
#include "lxccontainer.h"
#include "lxcoverlay.h"
#include "lxcrsync.h"
#include "storage_utils.h"
#include "utils.h"
lxc_log_define
(
lxcoverlay
,
lxc
);
...
...
@@ -42,6 +41,10 @@ lxc_log_define(lxcoverlay, lxc);
static
char
*
ovl_name
;
static
char
*
ovl_version
[]
=
{
"overlay"
,
"overlayfs"
};
/* defined in lxccontainer.c: needs to become common helper */
extern
char
*
dir_new_path
(
char
*
src
,
const
char
*
oldname
,
const
char
*
name
,
const
char
*
oldpath
,
const
char
*
lxcpath
);
static
char
*
ovl_detect_name
(
void
);
static
int
ovl_do_rsync
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
struct
lxc_conf
*
conf
);
...
...
@@ -55,21 +58,17 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
char
*
src
;
if
(
!
snap
)
{
ERROR
(
"overlay is only for snapshot clones"
);
ERROR
(
"overlay
fs
is only for snapshot clones"
);
return
-
22
;
}
if
(
!
orig
->
src
||
!
orig
->
dest
)
return
-
1
;
new
->
dest
=
lxc_string_join
(
"/"
,
(
const
char
*
[]){
lxcpath
,
cname
,
"rootfs"
,
NULL
},
false
);
new
->
dest
=
dir_new_path
(
orig
->
dest
,
oldname
,
cname
,
oldpath
,
lxcpath
);
if
(
!
new
->
dest
)
return
-
1
;
if
(
mkdir_p
(
new
->
dest
,
0755
)
<
0
)
return
-
1
;
...
...
@@ -134,19 +133,18 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
WARN
(
"Failed to update ownership of %s"
,
work
);
free
(
work
);
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
// the src will be 'overlayfs:lowerdir:upperdir'
len
=
strlen
(
delta
)
+
strlen
(
src
)
+
12
;
len
=
strlen
(
delta
)
+
strlen
(
orig
->
src
)
+
12
;
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
{
free
(
delta
);
return
-
ENOMEM
;
}
ret
=
snprintf
(
new
->
src
,
len
,
"overlay
:%s:%s"
,
src
,
delta
);
ret
=
snprintf
(
new
->
src
,
len
,
"overlay
fs:%s:%s"
,
orig
->
src
,
delta
);
free
(
delta
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
else
if
(
!
strcmp
(
orig
->
type
,
"overlayfs"
)
||
!
strcmp
(
orig
->
type
,
"overlay"
)
)
{
return
-
ENOMEM
;
}
else
if
(
strcmp
(
orig
->
type
,
"overlayfs"
)
==
0
)
{
/*
* What exactly do we want to do here? I think we want to use
* the original lowerdir, with a private delta which is
...
...
@@ -155,44 +153,26 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
char
*
osrc
,
*
odelta
,
*
nsrc
,
*
ndelta
,
*
work
;
char
*
lastslash
;
int
len
,
ret
,
lastslashidx
;
osrc
=
strdup
(
orig
->
src
);
if
(
!
osrc
)
{
SYSERROR
(
"Failed to duplicate
\"
%s
\"
"
,
orig
->
src
);
if
(
!
(
osrc
=
strdup
(
orig
->
src
)))
return
-
22
;
}
nsrc
=
strchr
(
osrc
,
':'
)
+
1
;
if
((
nsrc
!=
osrc
+
8
)
&&
(
nsrc
!=
osrc
+
10
))
{
free
(
osrc
);
ERROR
(
"Detected
\"
:
\"
in
\"
%s
\"
at wrong position"
,
osrc
);
return
-
22
;
}
odelta
=
strchr
(
nsrc
,
':'
);
if
(
!
odelta
)
{
if
(
nsrc
!=
osrc
+
10
||
(
odelta
=
strchr
(
nsrc
,
':'
))
==
NULL
)
{
free
(
osrc
);
ERROR
(
"Failed to find
\"
:
\"
in
\"
%s
\"
"
,
nsrc
);
return
-
22
;
}
*
odelta
=
'\0'
;
odelta
++
;
ndelta
=
lxc_string_join
(
"/"
,
(
const
char
*
[]){
lxcpath
,
cname
,
"rootfs"
,
NULL
},
false
);
if
(
!
ndelta
)
{
ndelta
=
dir_new_path
(
odelta
,
oldname
,
cname
,
oldpath
,
lxcpath
);
if
(
!
ndelta
)
{
free
(
osrc
);
ERROR
(
"Failed to create new path"
);
return
-
ENOMEM
;
}
ret
=
mkdir
(
ndelta
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
}
if
((
ret
=
mkdir
(
ndelta
,
0755
))
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"error: mkdir %s"
,
ndelta
);
free
(
osrc
);
free
(
ndelta
);
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
ndelta
);
return
-
1
;
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
ndelta
,
conf
)
<
0
)
WARN
(
"Failed to update ownership of %s"
,
ndelta
);
...
...
@@ -204,7 +184,6 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
if
(
!
lastslash
)
{
free
(
osrc
);
free
(
ndelta
);
ERROR
(
"Failed to detect
\"
/
\"
in
\"
%s
\"
"
,
ndelta
);
return
-
1
;
}
lastslash
++
;
...
...
@@ -214,43 +193,37 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
if
(
!
work
)
{
free
(
osrc
);
free
(
ndelta
);
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
}
strncpy
(
work
,
ndelta
,
lastslashidx
+
1
);
strcpy
(
work
+
lastslashidx
,
"olwork"
);
ret
=
mkdir
(
work
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
((
mkdir
(
work
,
0755
)
<
0
)
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"error: mkdir %s"
,
work
);
free
(
osrc
);
free
(
ndelta
);
free
(
work
);
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
ndelta
);
return
-
1
;
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
work
,
conf
)
<
0
)
WARN
(
"Failed to update ownership of %s"
,
work
);
free
(
work
);
len
=
strlen
(
nsrc
)
+
strlen
(
ndelta
)
+
1
0
;
len
=
strlen
(
nsrc
)
+
strlen
(
ndelta
)
+
1
2
;
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
{
free
(
osrc
);
free
(
ndelta
);
ERROR
(
"Failed to allocate memory"
);
return
-
ENOMEM
;
}
ret
=
snprintf
(
new
->
src
,
len
,
"overlay:%s:%s"
,
nsrc
,
ndelta
);
ret
=
snprintf
(
new
->
src
,
len
,
"overlay
fs
:%s:%s"
,
nsrc
,
ndelta
);
free
(
osrc
);
free
(
ndelta
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
return
-
1
;
}
if
(
ret
<
0
||
ret
>=
len
)
return
-
ENOMEM
;
return
ovl_do_rsync
(
orig
,
new
,
conf
);
}
else
{
ERROR
(
"overlay clone of %s container is not yet supported"
,
ERROR
(
"overlay
fs
clone of %s container is not yet supported"
,
orig
->
type
);
/*
* Note, supporting this will require ovl_mount supporting
...
...
@@ -263,7 +236,7 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
}
/*
* to say 'lxc-create -t ubuntu -n o1 -B overlay' means you want
* to say 'lxc-create -t ubuntu -n o1 -B overlay
fs
' means you want
* $lxcpath/$lxcname/rootfs to have the created container, while all
* changes after starting the container are written to
* $lxcpath/$lxcname/delta0
...
...
@@ -291,14 +264,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n,
return
-
1
;
}
// overlay:lower:upper
newlen
=
(
2
*
len
)
+
strlen
(
"overlay:"
)
+
2
;
// overlay
fs
:lower:upper
newlen
=
(
2
*
len
)
+
strlen
(
"overlay
fs
:"
)
+
2
;
bdev
->
src
=
malloc
(
newlen
);
if
(
!
bdev
->
src
)
{
ERROR
(
"Out of memory"
);
return
-
1
;
}
ret
=
snprintf
(
bdev
->
src
,
newlen
,
"overlay:%s:%s"
,
dest
,
delta
);
ret
=
snprintf
(
bdev
->
src
,
newlen
,
"overlay
fs
:%s:%s"
,
dest
,
delta
);
if
(
ret
<
0
||
ret
>=
newlen
)
return
-
1
;
...
...
@@ -312,23 +285,14 @@ int ovl_create(struct bdev *bdev, const char *dest, const char *n,
int
ovl_destroy
(
struct
bdev
*
orig
)
{
bool
ovl
;
char
*
upper
=
orig
->
src
;
char
*
upper
;
ovl
=
!
strncmp
(
upper
,
"overlay:"
,
8
);
if
(
!
ovl
&&
strncmp
(
upper
,
"overlayfs:"
,
10
))
if
(
strncmp
(
orig
->
src
,
"overlayfs:"
,
10
)
!=
0
)
return
-
22
;
if
(
ovl
)
upper
+=
8
;
else
upper
+=
10
;
upper
=
strchr
(
upper
,
':'
);
upper
=
strchr
(
orig
->
src
+
10
,
':'
);
if
(
!
upper
)
return
-
22
;
upper
++
;
return
lxc_rmdir_onedev
(
upper
,
NULL
);
}
...
...
@@ -339,6 +303,14 @@ int ovl_detect(const char *path)
return
0
;
}
char
*
ovl_getlower
(
char
*
p
)
{
char
*
p1
=
strchr
(
p
,
':'
);
if
(
p1
)
*
p1
=
'\0'
;
return
p
;
}
int
ovl_mount
(
struct
bdev
*
bdev
)
{
char
*
tmp
,
*
options
,
*
dup
,
*
lower
,
*
upper
;
...
...
@@ -349,9 +321,8 @@ int ovl_mount(struct bdev *bdev)
char
*
mntdata
;
int
ret
,
ret2
;
if
(
strcmp
(
bdev
->
type
,
"overlay
"
)
&&
strcmp
(
bdev
->
type
,
"overlay
fs"
))
if
(
strcmp
(
bdev
->
type
,
"overlayfs"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
...
...
@@ -445,7 +416,7 @@ int ovl_mount(struct bdev *bdev)
ret
=
ovl_remount_on_enodev
(
lower
,
bdev
->
dest
,
ovl_name
,
MS_MGC_VAL
|
mntflags
,
options_work
);
if
(
ret
<
0
)
{
INFO
(
"Overlay: Error mounting %s onto %s with options %s. "
INFO
(
"Overlay
fs
: Error mounting %s onto %s with options %s. "
"Retrying without workdir: %s."
,
lower
,
bdev
->
dest
,
options_work
,
strerror
(
errno
));
...
...
@@ -453,15 +424,15 @@ int ovl_mount(struct bdev *bdev)
ret
=
ovl_remount_on_enodev
(
lower
,
bdev
->
dest
,
ovl_name
,
MS_MGC_VAL
|
mntflags
,
options
);
if
(
ret
<
0
)
SYSERROR
(
"Overlay: Error mounting %s onto %s with "
SYSERROR
(
"Overlay
fs
: Error mounting %s onto %s with "
"options %s: %s."
,
lower
,
bdev
->
dest
,
options
,
strerror
(
errno
));
else
INFO
(
"Overlay: Mounted %s onto %s with options %s."
,
INFO
(
"Overlay
fs
: Mounted %s onto %s with options %s."
,
lower
,
bdev
->
dest
,
options
);
}
else
{
INFO
(
"Overlay: Mounted %s onto %s with options %s."
,
lower
,
INFO
(
"Overlay
fs
: Mounted %s onto %s with options %s."
,
lower
,
bdev
->
dest
,
options_work
);
}
return
ret
;
...
...
@@ -469,31 +440,13 @@ int ovl_mount(struct bdev *bdev)
int
ovl_umount
(
struct
bdev
*
bdev
)
{
if
(
strcmp
(
bdev
->
type
,
"overlay
"
)
&&
strcmp
(
bdev
->
type
,
"overlay
fs"
))
if
(
strcmp
(
bdev
->
type
,
"overlayfs"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
return
umount
(
bdev
->
dest
);
}
char
*
ovl_get_lower
(
const
char
*
rootfs_path
)
{
char
*
s1
;
s1
=
strstr
(
rootfs_path
,
":/"
);
if
(
!
s1
)
return
NULL
;
s1
++
;
s1
=
strstr
(
s1
,
":/"
);
if
(
!
s1
)
return
NULL
;
s1
++
;
return
s1
;
}
char
*
ovl_get_rootfs
(
const
char
*
rootfs_path
,
size_t
*
rootfslen
)
{
char
*
rootfsdir
=
NULL
;
...
...
@@ -802,7 +755,7 @@ static int ovl_do_rsync(struct bdev *orig, struct bdev *new, struct lxc_conf *co
else
ret
=
ovl_rsync
(
&
rdata
);
if
(
ret
)
ERROR
(
"copying overlay delta"
);
ERROR
(
"copying overlay
fs
delta"
);
return
ret
;
}
...
...
src/lxc/bdev/lxcoverlay.h
View file @
789edffe
...
...
@@ -76,7 +76,7 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
* To be called from functions in lxccontainer.c: Get lower directory for
* overlay rootfs.
*/
char
*
ovl_get
_lower
(
const
char
*
rootfs_path
);
char
*
ovl_get
lower
(
char
*
p
);
/*
* Get rootfs path for overlay backed containers. Allocated memory must be freed
...
...
src/lxc/bdev/lxcrbd.c
View file @
789edffe
...
...
@@ -23,7 +23,7 @@
#define _GNU_SOURCE
#define __STDC_FORMAT_MACROS
/* Required for PRIu64 to work. */
#include <inttypes.h>
/* Required for PRIu64 to work. */
#include <inttypes.h>
/* Required for PRIu64 to work. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
...
...
@@ -36,69 +36,24 @@
lxc_log_define
(
lxcrbd
,
lxc
);
struct
rbd_args
{
const
char
*
osd_pool_name
;
const
char
*
rbd_name
;
const
char
*
size
;
};
int
rbd_create_wrapper
(
void
*
data
)
{
struct
rbd_args
*
args
=
data
;
execlp
(
"rbd"
,
"rbd"
,
"create"
,
"--pool"
,
args
->
osd_pool_name
,
args
->
rbd_name
,
"--size"
,
args
->
size
,
(
char
*
)
NULL
);
return
-
1
;
}
int
rbd_map_wrapper
(
void
*
data
)
{
struct
rbd_args
*
args
=
data
;
execlp
(
"rbd"
,
"rbd"
,
"map"
,
"--pool"
,
args
->
osd_pool_name
,
args
->
rbd_name
,
(
char
*
)
NULL
);
return
-
1
;
}
int
rbd_unmap_wrapper
(
void
*
data
)
{
struct
rbd_args
*
args
=
data
;
execlp
(
"rbd"
,
"rbd"
,
"unmap"
,
args
->
rbd_name
,
(
char
*
)
NULL
);
return
-
1
;
}
int
rbd_delete_wrapper
(
void
*
data
)
{
struct
rbd_args
*
args
=
data
;
execlp
(
"rbd"
,
"rbd"
,
"rm"
,
args
->
rbd_name
,
(
char
*
)
NULL
);
return
-
1
;
}
int
rbd_clonepaths
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
oldname
,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
ERROR
(
"rbd clonepaths not implemented"
);
return
-
1
;
}
int
rbd_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
)
struct
bdev_specs
*
specs
)
{
const
char
*
rbdpool
,
*
fstype
;
const
char
*
rbdpool
,
*
rbdname
=
n
,
*
fstype
;
uint64_t
size
;
int
ret
,
len
;
char
sz
[
24
];
pid_t
pid
;
const
char
*
cmd_args
[
2
];
char
cmd_output
[
MAXPATHLEN
];
const
char
*
rbdname
=
n
;
struct
rbd_args
args
=
{
0
};
if
(
!
specs
)
return
-
1
;
...
...
@@ -111,112 +66,91 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
rbdname
=
specs
->
rbd
.
rbdname
;
/* source device /dev/rbd/lxc/ctn */
len
=
strlen
(
rbdpool
)
+
strlen
(
rbdname
)
+
4
+
11
;
len
=
strlen
(
rbdpool
)
+
strlen
(
rbdname
)
+
11
;
bdev
->
src
=
malloc
(
len
);
if
(
!
bdev
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
if
(
!
bdev
->
src
)
return
-
1
;
}
ret
=
snprintf
(
bdev
->
src
,
len
,
"rbd:/dev/rbd/%s/%s"
,
rbdpool
,
rbdname
);
if
(
ret
<
0
||
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
ret
=
snprintf
(
bdev
->
src
,
len
,
"/dev/rbd/%s/%s"
,
rbdpool
,
rbdname
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
}
/
* fssize is in bytes */
/
/ fssize is in bytes.
size
=
specs
->
fssize
;
if
(
!
size
)
size
=
DEFAULT_FS_SIZE
;
/* in megabytes for rbd tool */
ret
=
snprintf
(
sz
,
24
,
"%"
PRIu64
,
size
/
1024
/
1024
);
if
(
ret
<
0
||
ret
>=
24
)
{
ERROR
(
"Failed to create string"
);
return
-
1
;
}
// in megabytes for rbd tool
ret
=
snprintf
(
sz
,
24
,
"%"
PRIu64
,
size
/
1024
/
1024
);
if
(
ret
<
0
||
ret
>=
24
)
exit
(
1
);
args
.
osd_pool_name
=
rbdpool
;
args
.
rbd_name
=
rbdname
;
args
.
size
=
sz
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
rbd_create_wrapper
,
(
void
*
)
&
args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to create rbd storage volume
\"
%s
\"
: %s"
,
rbdname
,
cmd_output
);
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
!
pid
)
{
execlp
(
"rbd"
,
"rbd"
,
"create"
,
"--pool"
,
rbdpool
,
rbdname
,
"--size"
,
sz
,
(
char
*
)
NULL
);
exit
(
1
);
}
if
(
wait_for_pid
(
pid
)
<
0
)
return
-
1
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
rbd_map_wrapper
,
(
void
*
)
&
args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to map rbd storage volume
\"
%s
\"
: %s"
,
rbdname
,
cmd_output
);
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
!
pid
)
{
execlp
(
"rbd"
,
"rbd"
,
"map"
,
"--pool"
,
rbdpool
,
rbdname
,
(
char
*
)
NULL
);
exit
(
1
);
}
if
(
wait_for_pid
(
pid
)
<
0
)
return
-
1
;
fstype
=
specs
->
fstype
;
if
(
!
fstype
)
fstype
=
DEFAULT_FSTYPE
;
cmd_args
[
0
]
=
fstype
;
cmd_args
[
1
]
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
)
;
cmd_args
[
1
]
=
bdev
->
src
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
do_mkfs_exec_wrapper
,
(
void
*
)
cmd_args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to map rbd storage volume
\"
%s
\"
: %s"
,
rbdname
,
cmd_output
);
if
(
ret
<
0
)
return
-
1
;
}
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
dest
);
if
(
!
(
bdev
->
dest
=
strdup
(
dest
)))
return
-
1
;
}
ret
=
mkdir_p
(
bdev
->
dest
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
ERROR
(
"Failed to create directory
\"
%s
\"
"
,
bdev
->
dest
);
if
(
mkdir_p
(
bdev
->
dest
,
0755
)
<
0
&&
errno
!=
EEXIST
)
{
ERROR
(
"Error creating %s"
,
bdev
->
dest
);
return
-
1
;
}
TRACE
(
"Created rbd storage volume
\"
%s
\"
"
,
bdev
->
dest
);
return
0
;
}
int
rbd_destroy
(
struct
bdev
*
orig
)
{
int
ret
;
char
*
src
;
pid_t
pid
;
char
*
rbdfullname
;
char
cmd_output
[
MAXPATHLEN
];
struct
rbd_args
args
=
{
0
};
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
if
(
file_exists
(
src
))
{
args
.
rbd_name
=
src
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
rbd_unmap_wrapper
,
(
void
*
)
&
args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to map rbd storage volume
\"
%s
\"
: %s"
,
src
,
cmd_output
);
if
(
file_exists
(
orig
->
src
)
)
{
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
!
pid
)
{
execlp
(
"rbd"
,
"rbd"
,
"unmap"
,
orig
->
src
,
(
char
*
)
NULL
);
exit
(
1
);
}
if
(
wait_for_pid
(
pid
)
<
0
)
return
-
1
;
}
rbdfullname
=
alloca
(
strlen
(
src
)
-
8
);
strcpy
(
rbdfullname
,
&
src
[
9
]);
args
.
rbd_name
=
rbdfullname
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
rbd_delete_wrapper
,
(
void
*
)
&
args
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to delete rbd storage volume
\"
%s
\"
: %s"
,
rbdfullname
,
cmd_output
);
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
!
pid
)
{
rbdfullname
=
alloca
(
strlen
(
orig
->
src
)
-
8
);
strcpy
(
rbdfullname
,
&
orig
->
src
[
9
]
);
execlp
(
"rbd"
,
"rbd"
,
"rm"
,
rbdfullname
,
(
char
*
)
NULL
);
exit
(
1
);
}
return
wait_for_pid
(
pid
);
return
0
;
}
int
rbd_detect
(
const
char
*
path
)
...
...
@@ -228,33 +162,25 @@ int rbd_detect(const char *path)
int
rbd_mount
(
struct
bdev
*
bdev
)
{
char
*
src
;
if
(
strcmp
(
bdev
->
type
,
"rbd"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
if
(
!
file_exists
(
src
))
{
/* If blkdev does not exist it should be mapped, because it is
* not persistent on reboot.
*/
if
(
!
file_exists
(
bdev
->
src
)
)
{
// if blkdev does not exist it should be mapped, because it is not persistent on reboot
ERROR
(
"Block device %s is not mapped."
,
bdev
->
src
);
return
-
1
;
}
return
mount_unknown_fs
(
src
,
bdev
->
dest
,
bdev
->
mntopts
);
return
mount_unknown_fs
(
bdev
->
src
,
bdev
->
dest
,
bdev
->
mntopts
);
}
int
rbd_umount
(
struct
bdev
*
bdev
)
{
if
(
strcmp
(
bdev
->
type
,
"rbd"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
return
umount
(
bdev
->
dest
);
}
src/lxc/bdev/lxcrsync.c
View file @
789edffe
...
...
@@ -140,81 +140,3 @@ int rsync_rootfs_wrapper(void *data)
return
rsync_rootfs
(
arg
);
}
/* new helpers */
int
lxc_rsync_exec_wrapper
(
void
*
data
)
{
struct
rsync_data
*
arg
=
data
;
return
lxc_rsync
(
arg
);
}
int
lxc_rsync_exec
(
const
char
*
src
,
const
char
*
dest
)
{
int
ret
;
size_t
l
;
char
*
s
;
l
=
strlen
(
src
)
+
2
;
s
=
malloc
(
l
);
if
(
!
s
)
return
-
1
;
ret
=
snprintf
(
s
,
l
,
"%s"
,
src
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
l
)
return
-
1
;
s
[
l
-
2
]
=
'/'
;
s
[
l
-
1
]
=
'\0'
;
execlp
(
"rsync"
,
"rsync"
,
"-aHXS"
,
"--delete"
,
s
,
dest
,
(
char
*
)
NULL
);
return
-
1
;
}
int
lxc_rsync
(
struct
rsync_data
*
data
)
{
int
ret
;
struct
bdev
*
orig
=
data
->
orig
,
*
new
=
data
->
new
;
char
*
dest
,
*
src
;
ret
=
unshare
(
CLONE_NEWNS
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to unshare CLONE_NEWNS"
);
return
-
1
;
}
ret
=
detect_shared_rootfs
();
if
(
ret
)
{
ret
=
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
);
if
(
ret
<
0
)
SYSERROR
(
"Failed to make
\"
/
\"
a slave mount"
);
}
ret
=
orig
->
ops
->
mount
(
orig
);
if
(
ret
<
0
)
{
ERROR
(
"Failed mounting
\"
%s
\"
on
\"
%s
\"
"
,
orig
->
src
,
orig
->
dest
);
return
-
1
;
}
ret
=
new
->
ops
->
mount
(
new
);
if
(
ret
<
0
)
{
ERROR
(
"Failed mounting
\"
%s
\"
onto
\"
%s
\"
"
,
new
->
src
,
new
->
dest
);
return
-
1
;
}
ret
=
lxc_switch_uid_gid
(
0
,
0
);
if
(
ret
<
0
)
return
-
1
;
ret
=
lxc_setgroups
(
0
,
NULL
);
if
(
ret
<
0
)
return
-
1
;
src
=
lxc_storage_get_path
(
orig
->
dest
,
orig
->
type
);
dest
=
lxc_storage_get_path
(
new
->
dest
,
new
->
type
);
ret
=
lxc_rsync_exec
(
src
,
dest
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
"
,
src
,
dest
);
return
-
1
;
}
return
0
;
}
src/lxc/bdev/lxcrsync.h
View file @
789edffe
...
...
@@ -43,9 +43,4 @@ int rsync_delta(struct rsync_data_char *data);
int
rsync_rootfs
(
struct
rsync_data
*
data
);
int
rsync_rootfs_wrapper
(
void
*
data
);
/* new helpers */
extern
int
lxc_rsync_exec_wrapper
(
void
*
data
);
extern
int
lxc_rsync_exec
(
const
char
*
src
,
const
char
*
dest
);
extern
int
lxc_rsync
(
struct
rsync_data
*
data
);
#endif // __LXC_RSYNC_H
src/lxc/bdev/lxczfs.c
View file @
789edffe
...
...
@@ -85,23 +85,20 @@ int zfs_detect(const char *path)
int
zfs_mount
(
struct
bdev
*
bdev
)
{
int
ret
;
char
*
mntdata
,
*
src
;
unsigned
long
mntflags
;
if
(
strcmp
(
bdev
->
type
,
"zfs"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
char
*
mntdata
;
unsigned
long
mntflags
;
if
(
parse_mntopts
(
bdev
->
mntopts
,
&
mntflags
,
&
mntdata
)
<
0
)
{
free
(
mntdata
);
return
-
22
;
}
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
|
mntflags
,
mntdata
);
int
ret
=
mount
(
bdev
->
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
|
mntflags
,
mntdata
);
free
(
mntdata
);
return
ret
;
...
...
@@ -208,7 +205,6 @@ int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
)
{
char
*
origsrc
,
*
newsrc
;
int
len
,
ret
;
if
(
!
orig
->
src
||
!
orig
->
dest
)
...
...
@@ -219,22 +215,19 @@ int zfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
return
-
1
;
}
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootfs"
)
+
4
+
3
;
len
=
strlen
(
lxcpath
)
+
strlen
(
cname
)
+
strlen
(
"rootfs"
)
+
3
;
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
return
-
1
;
ret
=
snprintf
(
new
->
src
,
len
,
"
zfs:
%s/%s/rootfs"
,
lxcpath
,
cname
);
ret
=
snprintf
(
new
->
src
,
len
,
"%s/%s/rootfs"
,
lxcpath
,
cname
);
if
(
ret
<
0
||
ret
>=
len
)
return
-
1
;
newsrc
=
lxc_storage_get_path
(
new
->
src
,
new
->
type
);
new
->
dest
=
strdup
(
newsrc
);
if
(
!
new
->
dest
)
if
((
new
->
dest
=
strdup
(
new
->
src
))
==
NULL
)
return
-
1
;
origsrc
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
return
zfs_clone
(
origsrc
,
newsrc
,
oldname
,
cname
,
lxcpath
,
snap
);
return
zfs_clone
(
orig
->
src
,
new
->
src
,
oldname
,
cname
,
lxcpath
,
snap
);
}
/*
...
...
@@ -246,15 +239,14 @@ int zfs_destroy(struct bdev *orig)
{
pid_t
pid
;
char
output
[
MAXPATHLEN
];
char
*
p
,
*
src
;
char
*
p
;
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
pid
)
return
wait_for_pid
(
pid
);
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
if
(
!
zfs_list_entry
(
src
,
output
,
MAXPATHLEN
))
{
if
(
!
zfs_list_entry
(
orig
->
src
,
output
,
MAXPATHLEN
))
{
ERROR
(
"Error: zfs entry for %s not found"
,
orig
->
src
);
return
-
1
;
}
...
...
@@ -268,64 +260,41 @@ int zfs_destroy(struct bdev *orig)
exit
(
EXIT_FAILURE
);
}
struct
zfs_exec_args
{
char
*
dataset
;
char
*
options
;
};
int
zfs_create_exec_wrapper
(
void
*
args
)
{
struct
zfs_exec_args
*
zfs_args
=
args
;
execlp
(
"zfs"
,
"zfs"
,
"create"
,
zfs_args
->
options
,
zfs_args
->
dataset
,
(
char
*
)
NULL
);
return
-
1
;
}
int
zfs_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
)
{
const
char
*
zfsroot
;
char
cmd_output
[
MAXPATHLEN
],
dev
[
MAXPATHLEN
],
option
[
MAXPATHLEN
];
char
option
[
MAXPATHLEN
];
int
ret
;
size_t
len
;
struct
zfs_exec_args
cmd_args
;
pid_t
pid
;
if
(
!
specs
||
!
specs
->
zfs
.
zfsroot
)
zfsroot
=
lxc_global_config_value
(
"lxc.bdev.zfs.root"
);
else
zfsroot
=
specs
->
zfs
.
zfsroot
;
bdev
->
dest
=
strdup
(
dest
);
if
(
!
bdev
->
dest
)
{
if
(
!
(
bdev
->
dest
=
strdup
(
dest
)))
{
ERROR
(
"No mount target specified or out of memory"
);
return
-
1
;
}
len
=
strlen
(
bdev
->
dest
)
+
1
;
/* strlen("zfs:") */
len
+=
4
;
bdev
->
src
=
malloc
(
len
);
if
(
!
bdev
->
src
)
return
-
1
;
ret
=
snprintf
(
bdev
->
src
,
len
,
"zfs:%s"
,
bdev
->
dest
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
if
(
!
(
bdev
->
src
=
strdup
(
bdev
->
dest
)))
{
ERROR
(
"out of memory"
);
return
-
1
;
}
ret
=
snprintf
(
option
,
MAXPATHLEN
,
"-omountpoint=%s"
,
bdev
->
dest
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
-
1
;
if
((
pid
=
fork
())
<
0
)
return
-
1
;
if
(
pid
)
return
wait_for_pid
(
pid
);
char
dev
[
MAXPATHLEN
];
ret
=
snprintf
(
dev
,
MAXPATHLEN
,
"%s/%s"
,
zfsroot
,
n
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
-
1
;
exit
(
EXIT_FAILURE
)
;
cmd_args
.
options
=
option
;
cmd_args
.
dataset
=
dev
;
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
zfs_create_exec_wrapper
,
(
void
*
)
&
cmd_args
);
if
(
ret
<
0
)
ERROR
(
"Failed to create zfs dataset
\"
%s
\"
: %s"
,
dev
,
cmd_output
);
return
ret
;
execlp
(
"zfs"
,
"zfs"
,
"create"
,
option
,
dev
,
(
char
*
)
NULL
);
exit
(
EXIT_FAILURE
);
}
src/lxc/bdev/storage_utils.c
View file @
789edffe
...
...
@@ -129,10 +129,12 @@ bool attach_block_device(struct lxc_conf *conf)
int
blk_getsize
(
struct
bdev
*
bdev
,
uint64_t
*
size
)
{
int
fd
,
ret
;
char
*
src
;
char
*
path
=
bdev
->
src
;
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
fd
=
open
(
src
,
O_RDONLY
);
if
(
strcmp
(
bdev
->
type
,
"loop"
)
==
0
)
path
=
bdev
->
src
+
5
;
fd
=
open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
1
;
...
...
@@ -161,12 +163,15 @@ int detect_fs(struct bdev *bdev, char *type, int len)
size_t
linelen
;
pid_t
pid
;
FILE
*
f
;
char
*
sp1
,
*
sp2
,
*
sp3
,
*
srcdev
,
*
line
=
NULL
;
char
*
sp1
,
*
sp2
,
*
sp3
,
*
line
=
NULL
;
char
*
srcdev
;
if
(
!
bdev
||
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
1
;
srcdev
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
srcdev
=
bdev
->
src
;
if
(
strcmp
(
bdev
->
type
,
"loop"
)
==
0
)
srcdev
=
bdev
->
src
+
5
;
ret
=
pipe
(
p
);
if
(
ret
<
0
)
...
...
@@ -415,7 +420,6 @@ bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
// overlayfs -- which is also allowed)
if
(
strcmp
(
b
->
type
,
"dir"
)
==
0
||
strcmp
(
b
->
type
,
"aufs"
)
==
0
||
strcmp
(
b
->
type
,
"overlay"
)
==
0
||
strcmp
(
b
->
type
,
"overlayfs"
)
==
0
||
strcmp
(
b
->
type
,
"btrfs"
)
==
0
||
strcmp
(
b
->
type
,
"loop"
)
==
0
)
...
...
@@ -428,7 +432,6 @@ bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
// and loop. In particular, not zfs, btrfs, or lvm.
if
(
strcmp
(
t
,
"dir"
)
==
0
||
strcmp
(
t
,
"aufs"
)
==
0
||
strcmp
(
t
,
"overlay"
)
==
0
||
strcmp
(
t
,
"overlayfs"
)
==
0
||
strcmp
(
t
,
"btrfs"
)
==
0
||
strcmp
(
t
,
"loop"
)
==
0
)
...
...
src/lxc/conf.c
View file @
789edffe
...
...
@@ -3623,6 +3623,7 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
{
uid_t
rootuid
,
rootgid
;
unsigned
long
val
;
char
*
chownpath
=
path
;
int
hostuid
,
hostgid
,
ret
;
struct
stat
sb
;
char
map1
[
100
],
map2
[
100
],
map3
[
100
],
map4
[
100
],
map5
[
100
];
...
...
@@ -3658,6 +3659,23 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
}
rootgid
=
(
gid_t
)
val
;
/*
* In case of overlay, we want only the writeable layer to be chowned
*/
if
(
strncmp
(
path
,
"overlayfs:"
,
10
)
==
0
||
strncmp
(
path
,
"aufs:"
,
5
)
==
0
)
{
chownpath
=
strchr
(
path
,
':'
);
if
(
!
chownpath
)
{
ERROR
(
"Bad overlay path: %s"
,
path
);
return
-
1
;
}
chownpath
=
strchr
(
chownpath
+
1
,
':'
);
if
(
!
chownpath
)
{
ERROR
(
"Bad overlay path: %s"
,
path
);
return
-
1
;
}
chownpath
++
;
}
path
=
chownpath
;
if
(
hostuid
==
0
)
{
if
(
chown
(
path
,
rootuid
,
rootgid
)
<
0
)
{
ERROR
(
"Error chowning %s"
,
path
);
...
...
src/lxc/lxccontainer.c
View file @
789edffe
...
...
@@ -1265,10 +1265,8 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
exit
(
1
);
}
}
else
{
// TODO come up with a better way here!
char
*
src
;
free
(
bdev
->
dest
);
src
=
lxc_storage_get_path
(
bdev
->
src
,
bdev
->
type
);
bdev
->
dest
=
strdup
(
src
);
bdev
->
dest
=
strdup
(
bdev
->
src
);
}
/*
...
...
@@ -1433,7 +1431,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
}
/* execute */
execvp
(
tpath
,
newargv
);
SYSERROR
(
"
F
ailed to execute template %s"
,
tpath
);
SYSERROR
(
"
f
ailed to execute template %s"
,
tpath
);
exit
(
1
);
}
...
...
@@ -3225,8 +3223,8 @@ static int clone_update_rootfs_wrapper(void *data)
sudo lxc-clone -o o1 -n n1 -s -L|-fssize fssize -v|--vgname vgname \
-p|--lvprefix lvprefix -t|--fstype fstype -B backingstore
-s [ implies overlay]
-s -B overlay
-s [ implies overlay
fs
]
-s -B overlay
fs
-s -B aufs
only rootfs gets converted (copied/snapshotted) on clone.
...
...
@@ -3600,7 +3598,7 @@ static int do_lxcapi_snapshot(struct lxc_container *c, const char *commentfile)
if
(
bdev_is_dir
(
c
->
lxc_conf
,
c
->
lxc_conf
->
rootfs
.
path
))
{
ERROR
(
"Snapshot of directory-backed container requested."
);
ERROR
(
"Making a copy-clone. If you do want snapshots, then"
);
ERROR
(
"please create an aufs or overlay clone first, snapshot that"
);
ERROR
(
"please create an aufs or overlay
fs
clone first, snapshot that"
);
ERROR
(
"and keep the original container pristine."
);
flags
&=
~
LXC_CLONE_SNAPSHOT
|
LXC_CLONE_MAYBE_SNAPSHOT
;
}
...
...
src/lxc/tools/lxc_destroy.c
View file @
789edffe
...
...
@@ -171,7 +171,7 @@ static bool do_destroy(struct lxc_container *c)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
false
;
if
(
rmdir
(
path
)
<
0
&&
errno
!=
ENOENT
)
{
if
(
dir_exists
(
path
)
)
{
if
(
!
quiet
)
fprintf
(
stdout
,
"Destroying %s failed: %s has snapshots.
\n
"
,
c
->
name
,
c
->
name
);
return
false
;
...
...
@@ -271,7 +271,7 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
return
false
;
if
(
rmdir
(
path
)
<
0
&&
errno
!=
ENOENT
)
if
(
dir_exists
(
path
)
)
bret
=
c
->
destroy_with_snapshots
(
c
);
else
bret
=
do_destroy
(
c
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment