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