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
241978fa
Unverified
Commit
241978fa
authored
Jul 28, 2017
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
overlay: rework overlay storage driver
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
3ef1df7c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
368 additions
and
248 deletions
+368
-248
lxcoverlay.c
src/lxc/bdev/lxcoverlay.c
+330
-244
lxccontainer.c
src/lxc/lxccontainer.c
+38
-4
No files found.
src/lxc/bdev/lxcoverlay.c
View file @
241978fa
...
@@ -45,8 +45,6 @@ static char *ovl_version[] = {"overlay", "overlayfs"};
...
@@ -45,8 +45,6 @@ static char *ovl_version[] = {"overlay", "overlayfs"};
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
);
static
int
ovl_rsync
(
struct
rsync_data
*
data
);
static
int
ovl_rsync_wrapper
(
void
*
data
);
static
int
ovl_remount_on_enodev
(
const
char
*
lower
,
const
char
*
target
,
static
int
ovl_remount_on_enodev
(
const
char
*
lower
,
const
char
*
target
,
const
char
*
name
,
unsigned
long
mountflags
,
const
char
*
name
,
unsigned
long
mountflags
,
const
void
*
options
);
const
void
*
options
);
...
@@ -55,61 +53,80 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
...
@@ -55,61 +53,80 @@ 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
;
int
ret
;
char
*
src
;
if
(
!
snap
)
{
if
(
!
snap
)
{
ERROR
(
"overlay is only for snapshot clones"
);
ERROR
(
"The overlay storage driver can only be used for "
"snapshots"
);
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
=
must_make_path
(
lxcpath
,
cname
,
"rootfs"
,
NULL
);
"/"
,
(
const
char
*
[]){
lxcpath
,
cname
,
"rootfs"
,
NULL
},
false
);
if
(
!
new
->
dest
)
return
-
1
;
if
(
mkdir_p
(
new
->
dest
,
0755
)
<
0
)
ret
=
mkdir_p
(
new
->
dest
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
new
->
dest
);
return
-
1
;
return
-
1
;
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
new
->
dest
,
conf
)
<
0
)
if
(
am_unpriv
())
{
WARN
(
"Failed to update ownership of %s"
,
new
->
dest
);
ret
=
chown_mapped_root
(
new
->
dest
,
conf
);
if
(
ret
<
0
)
WARN
(
"Failed to update ownership of %s"
,
new
->
dest
);
}
if
(
strcmp
(
orig
->
type
,
"dir"
)
==
0
)
{
if
(
strcmp
(
orig
->
type
,
"dir"
)
==
0
)
{
char
*
delta
,
*
lastslash
;
char
*
delta
,
*
lastslash
;
char
*
work
;
char
*
work
;
int
ret
,
len
,
lastslashidx
;
int
ret
,
len
,
lastslashidx
;
/*
/* If we have "/var/lib/lxc/c2/rootfs" then delta will be
* if we have
* "/var/lib/lxc/c2/delta0".
* /var/lib/lxc/c2/rootfs
* then delta will be
* /var/lib/lxc/c2/delta0
*/
*/
lastslash
=
strrchr
(
new
->
dest
,
'/'
);
lastslash
=
strrchr
(
new
->
dest
,
'/'
);
if
(
!
lastslash
)
if
(
!
lastslash
)
{
ERROR
(
"Failed to detect
\"
/
\"
in string
\"
%s
\"
"
,
new
->
dest
);
return
-
22
;
return
-
22
;
if
(
strlen
(
lastslash
)
<
7
)
}
if
(
strlen
(
lastslash
)
<
(
sizeof
(
"/rootfs"
)
-
1
))
{
ERROR
(
"Failed to detect
\"
/rootfs
\"
in string
\"
%s
\"
"
,
new
->
dest
);
return
-
22
;
return
-
22
;
}
lastslash
++
;
lastslash
++
;
lastslashidx
=
lastslash
-
new
->
dest
;
lastslashidx
=
lastslash
-
new
->
dest
;
delta
=
malloc
(
lastslashidx
+
7
);
delta
=
malloc
(
lastslashidx
+
7
);
if
(
!
delta
)
if
(
!
delta
)
{
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
return
-
1
;
}
strncpy
(
delta
,
new
->
dest
,
lastslashidx
+
1
);
strncpy
(
delta
,
new
->
dest
,
lastslashidx
+
1
);
strcpy
(
delta
+
lastslashidx
,
"delta0"
);
strncpy
(
delta
+
lastslashidx
,
"delta0"
,
sizeof
(
"delta0"
)
-
1
);
if
((
ret
=
mkdir
(
delta
,
0755
))
<
0
)
{
delta
[
lastslashidx
+
sizeof
(
"delta0"
)]
=
'\0'
;
SYSERROR
(
"error: mkdir %s"
,
delta
);
ret
=
mkdir
(
delta
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
delta
);
free
(
delta
);
free
(
delta
);
return
-
1
;
return
-
1
;
}
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
delta
,
conf
)
<
0
)
WARN
(
"Failed to update ownership of %s"
,
delta
);
/*
if
(
am_unpriv
())
{
* Make workdir for overlayfs.v22 or higher:
ret
=
chown_mapped_root
(
delta
,
conf
);
if
(
ret
<
0
)
WARN
(
"Failed to update ownership of %s"
,
delta
);
}
/* Make workdir for overlayfs.v22 or higher:
* The workdir will be
* The workdir will be
* /var/lib/lxc/c2/olwork
* /var/lib/lxc/c2/olwork
* and is used to prepare files before they are atomically
* and is used to prepare files before they are atomically
...
@@ -119,86 +136,103 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
...
@@ -119,86 +136,103 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
*/
*/
work
=
malloc
(
lastslashidx
+
7
);
work
=
malloc
(
lastslashidx
+
7
);
if
(
!
work
)
{
if
(
!
work
)
{
ERROR
(
"Failed to allocate memory"
);
free
(
delta
);
free
(
delta
);
return
-
1
;
return
-
1
;
}
}
strncpy
(
work
,
new
->
dest
,
lastslashidx
+
1
);
strncpy
(
work
,
new
->
dest
,
lastslashidx
+
1
);
strcpy
(
work
+
lastslashidx
,
"olwork"
);
strncpy
(
work
+
lastslashidx
,
"olwork"
,
sizeof
(
"olwork"
)
-
1
);
work
[
lastslashidx
+
sizeof
(
"olwork"
)]
=
'\0'
;
if
(
mkdir
(
work
,
0755
)
<
0
)
{
if
(
mkdir
(
work
,
0755
)
<
0
)
{
SYSERROR
(
"error: mkdir %s"
,
work
);
SYSERROR
(
"error: mkdir %s"
,
work
);
free
(
delta
);
free
(
delta
);
free
(
work
);
free
(
work
);
return
-
1
;
return
-
1
;
}
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
work
,
conf
)
<
0
)
WARN
(
"Failed to update ownership of %s"
,
work
);
if
(
am_unpriv
())
{
ret
=
chown_mapped_root
(
work
,
conf
);
if
(
ret
<
0
)
WARN
(
"Failed to update ownership of %s"
,
work
);
}
free
(
work
);
free
(
work
);
/* strlen("overlay:") = 8
* +
* strlen(delta)
* +
* :
* +
* strlen(src)
* +
* \0
*/
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
src
=
lxc_storage_get_path
(
orig
->
src
,
orig
->
type
);
// the src will be 'overlayfs:lowerdir:upperdir'
len
=
8
+
strlen
(
delta
)
+
1
+
strlen
(
src
)
+
1
;
len
=
strlen
(
delta
)
+
strlen
(
src
)
+
12
;
new
->
src
=
malloc
(
len
);
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
{
if
(
!
new
->
src
)
{
ERROR
(
"Failed to allocate memory"
);
free
(
delta
);
free
(
delta
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
ret
=
snprintf
(
new
->
src
,
len
,
"overlay:%s:%s"
,
src
,
delta
);
ret
=
snprintf
(
new
->
src
,
len
,
"overlay:%s:%s"
,
src
,
delta
);
free
(
delta
);
free
(
delta
);
if
(
ret
<
0
||
ret
>=
len
)
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
return
-
1
;
return
-
1
;
}
else
if
(
!
strcmp
(
orig
->
type
,
"overlayfs"
)
||
!
strcmp
(
orig
->
type
,
"overlay"
))
{
}
/*
}
else
if
(
!
strcmp
(
orig
->
type
,
"overlayfs"
)
||
* What exactly do we want to do here? I think we want to use
!
strcmp
(
orig
->
type
,
"overlay"
))
{
* the original lowerdir, with a private delta which is
* originally rsynced from the original delta
*/
char
*
osrc
,
*
odelta
,
*
nsrc
,
*
ndelta
,
*
work
;
char
*
osrc
,
*
odelta
,
*
nsrc
,
*
ndelta
,
*
work
;
char
*
lastslash
;
char
*
lastslash
;
int
len
,
ret
,
lastslashidx
;
int
ret
,
lastslashidx
;
size_t
len
;
osrc
=
strdup
(
orig
->
src
);
osrc
=
strdup
(
orig
->
src
);
if
(
!
osrc
)
{
if
(
!
osrc
)
{
SYSERROR
(
"Failed to duplicate
\"
%s
\"
"
,
orig
->
src
);
ERROR
(
"Failed to duplicate string
\"
%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
+
8
)
&&
(
nsrc
!=
osrc
+
10
))
{
free
(
osrc
);
free
(
osrc
);
ERROR
(
"Detected
\"
:
\"
in
\"
%s
\"
at wrong position"
,
osrc
);
ERROR
(
"Detected
\"
:
\"
in
\"
%s
\"
at wrong position"
,
osrc
);
return
-
22
;
return
-
22
;
}
}
odelta
=
strchr
(
nsrc
,
':'
);
odelta
=
strchr
(
nsrc
,
':'
);
if
(
!
odelta
)
{
if
(
!
odelta
)
{
free
(
osrc
);
free
(
osrc
);
ERROR
(
"Failed to find
\"
:
\"
in
\"
%s
\"
"
,
nsrc
);
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
=
must_make_path
(
lxcpath
,
cname
,
"delta0"
,
NULL
);
if
(
!
ndelta
)
{
free
(
osrc
);
ERROR
(
"Failed to create new path"
);
return
-
ENOMEM
;
}
ret
=
mkdir
(
ndelta
,
0755
);
ret
=
mkdir
(
ndelta
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
free
(
osrc
);
free
(
osrc
);
free
(
ndelta
);
free
(
ndelta
);
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
ndelta
);
SYSERROR
(
"Failed to create
directory
\"
%s
\"
"
,
ndelta
);
return
-
1
;
return
-
1
;
}
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
ndelta
,
conf
)
<
0
)
if
(
am_unpriv
())
{
WARN
(
"Failed to update ownership of %s"
,
ndelta
);
ret
=
chown_mapped_root
(
ndelta
,
conf
);
if
(
ret
<
0
)
WARN
(
"Failed to update ownership of %s"
,
ndelta
);
}
/*
/* Make workdir for overlayfs.v22 or higher (See the comment
* make workdir for overlayfs.v22 or higher (see comment further
* further up.).
* up)
*/
*/
lastslash
=
strrchr
(
ndelta
,
'/'
);
lastslash
=
strrchr
(
ndelta
,
'/'
);
if
(
!
lastslash
)
{
if
(
!
lastslash
)
{
...
@@ -217,22 +251,38 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
...
@@ -217,22 +251,38 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
ERROR
(
"Failed to allocate memory"
);
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
return
-
1
;
}
}
strncpy
(
work
,
ndelta
,
lastslashidx
+
1
);
strncpy
(
work
,
ndelta
,
lastslashidx
+
1
);
strcpy
(
work
+
lastslashidx
,
"olwork"
);
strncpy
(
work
+
lastslashidx
,
"olwork"
,
sizeof
(
"olwork"
)
-
1
);
work
[
lastslashidx
+
sizeof
(
"olwork"
)]
=
'\0'
;
ret
=
mkdir
(
work
,
0755
);
ret
=
mkdir
(
work
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
free
(
osrc
);
free
(
osrc
);
free
(
ndelta
);
free
(
ndelta
);
free
(
work
);
free
(
work
);
SYSERROR
(
"Failed to create
\"
%s
\"
"
,
ndelta
);
SYSERROR
(
"Failed to create
directory
\"
%s
\"
"
,
ndelta
);
return
-
1
;
return
-
1
;
}
}
if
(
am_unpriv
()
&&
chown_mapped_root
(
work
,
conf
)
<
0
)
if
(
am_unpriv
())
{
WARN
(
"Failed to update ownership of %s"
,
work
);
ret
=
chown_mapped_root
(
work
,
conf
);
if
(
ret
<
0
)
WARN
(
"Failed to update ownership of %s"
,
work
);
}
free
(
work
);
free
(
work
);
len
=
strlen
(
nsrc
)
+
strlen
(
ndelta
)
+
10
;
/* strlen("overlay:") = 8
* +
* strlen(delta)
* +
* :
* +
* strlen(src)
* +
* \0
*/
len
=
8
+
strlen
(
ndelta
)
+
1
+
strlen
(
nsrc
)
+
1
;
new
->
src
=
malloc
(
len
);
new
->
src
=
malloc
(
len
);
if
(
!
new
->
src
)
{
if
(
!
new
->
src
)
{
free
(
osrc
);
free
(
osrc
);
...
@@ -243,17 +293,16 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
...
@@ -243,17 +293,16 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
ret
=
snprintf
(
new
->
src
,
len
,
"overlay:%s:%s"
,
nsrc
,
ndelta
);
ret
=
snprintf
(
new
->
src
,
len
,
"overlay:%s:%s"
,
nsrc
,
ndelta
);
free
(
osrc
);
free
(
osrc
);
free
(
ndelta
);
free
(
ndelta
);
if
(
ret
<
0
||
ret
>=
len
)
{
if
(
ret
<
0
||
(
size_t
)
ret
>=
len
)
{
ERROR
(
"Failed to create string"
);
ERROR
(
"Failed to create string"
);
return
-
1
;
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 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
* mounting of the underlay. No big deal, just needs to be done.
* mounting of the underlay. No big deal, just needs to be done.
*/
*/
return
-
1
;
return
-
1
;
...
@@ -262,67 +311,86 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
...
@@ -262,67 +311,86 @@ int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
return
0
;
return
0
;
}
}
/*
/* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
* to say 'lxc-create -t ubuntu -n o1 -B overlay' means you want
* "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
* $lxcpath/$lxcname/rootfs to have the created container, while all
* after starting the container are written to "<lxcpath>/<lxcname>/delta0".
* changes after starting the container are written to
* $lxcpath/$lxcname/delta0
*/
*/
int
ovl_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
int
ovl_create
(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
)
struct
bdev_specs
*
specs
)
{
{
char
*
delta
;
char
*
delta
;
int
ret
,
len
=
strlen
(
dest
),
newlen
;
int
ret
;
size_t
len
,
newlen
;
if
(
len
<
8
||
strcmp
(
dest
+
len
-
7
,
"/rootfs"
)
!=
0
)
len
=
strlen
(
dest
);
if
(
len
<
8
||
strcmp
(
dest
+
len
-
7
,
"/rootfs"
))
{
ERROR
(
"Failed to detect
\"
/rootfs
\"
in
\"
%s
\"
"
,
dest
);
return
-
1
;
return
-
1
;
}
if
(
!
(
bdev
->
dest
=
strdup
(
dest
)))
{
bdev
->
dest
=
strdup
(
dest
);
ERROR
(
"Out of memory"
);
if
(
!
bdev
->
dest
)
{
ERROR
(
"Failed to duplicate string
\"
%s
\"
"
,
dest
);
return
-
1
;
return
-
1
;
}
}
delta
=
alloca
(
strlen
(
dest
)
+
1
);
delta
=
malloc
(
len
+
1
);
strcpy
(
delta
,
dest
);
if
(
!
delta
)
{
strcpy
(
delta
+
len
-
6
,
"delta0"
);
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
}
strncpy
(
delta
,
dest
,
len
);
strncpy
(
delta
+
len
-
6
,
"delta0"
,
sizeof
(
"delta0"
)
-
1
);
delta
[
len
+
sizeof
(
"delta0"
)]
=
'\0'
;
if
(
mkdir_p
(
delta
,
0755
)
<
0
)
{
ret
=
mkdir_p
(
delta
,
0755
);
ERROR
(
"Error creating %s"
,
delta
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
delta
);
free
(
delta
);
return
-
1
;
return
-
1
;
}
}
/
/ overlay:lower:upper
/
* overlay:lower:upper */
newlen
=
(
2
*
len
)
+
strlen
(
"overlay:"
)
+
2
;
newlen
=
(
2
*
len
)
+
strlen
(
"overlay:"
)
+
2
;
bdev
->
src
=
malloc
(
newlen
);
bdev
->
src
=
malloc
(
newlen
);
if
(
!
bdev
->
src
)
{
if
(
!
bdev
->
src
)
{
ERROR
(
"Out of memory"
);
ERROR
(
"Failed to allocate memory"
);
free
(
delta
);
return
-
1
;
return
-
1
;
}
}
ret
=
snprintf
(
bdev
->
src
,
newlen
,
"overlay:%s:%s"
,
dest
,
delta
);
ret
=
snprintf
(
bdev
->
src
,
newlen
,
"overlay:%s:%s"
,
dest
,
delta
);
if
(
ret
<
0
||
ret
>=
newlen
)
if
(
ret
<
0
||
(
size_t
)
ret
>=
newlen
)
{
ERROR
(
"Failed to create string"
);
free
(
delta
);
return
-
1
;
return
-
1
;
}
if
(
mkdir_p
(
bdev
->
dest
,
0755
)
<
0
)
{
ret
=
mkdir_p
(
bdev
->
dest
,
0755
);
ERROR
(
"Error creating %s"
,
bdev
->
dest
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
bdev
->
dest
);
free
(
delta
);
return
-
1
;
return
-
1
;
}
}
free
(
delta
);
return
0
;
return
0
;
}
}
int
ovl_destroy
(
struct
bdev
*
orig
)
int
ovl_destroy
(
struct
bdev
*
orig
)
{
{
bool
ovl
;
bool
ovl
;
char
*
upper
=
orig
->
src
;
char
*
upper
=
orig
->
src
;
ovl
=
!
strncmp
(
upper
,
"overlay:"
,
8
);
ovl
=
!
strncmp
(
upper
,
"overlay:"
,
8
);
if
(
!
ovl
&&
strncmp
(
upper
,
"overlayfs:"
,
10
))
if
(
!
ovl
&&
strncmp
(
upper
,
"overlayfs:"
,
10
))
return
-
22
;
return
-
22
;
if
(
ovl
)
if
(
ovl
)
upper
+=
8
;
upper
+=
8
;
else
else
upper
+=
10
;
upper
+=
10
;
upper
=
strchr
(
upper
,
':'
);
upper
=
strchr
(
upper
,
':'
);
if
(
!
upper
)
if
(
!
upper
)
...
@@ -348,7 +416,7 @@ int ovl_mount(struct bdev *bdev)
...
@@ -348,7 +416,7 @@ int ovl_mount(struct bdev *bdev)
char
*
tmp
,
*
options
,
*
dup
,
*
lower
,
*
upper
;
char
*
tmp
,
*
options
,
*
dup
,
*
lower
,
*
upper
;
char
*
options_work
,
*
work
,
*
lastslash
;
char
*
options_work
,
*
work
,
*
lastslash
;
int
lastslashidx
;
int
lastslashidx
;
in
t
len
,
len2
;
size_
t
len
,
len2
;
unsigned
long
mntflags
;
unsigned
long
mntflags
;
char
*
mntdata
;
char
*
mntdata
;
int
ret
,
ret2
;
int
ret
,
ret2
;
...
@@ -362,53 +430,87 @@ int ovl_mount(struct bdev *bdev)
...
@@ -362,53 +430,87 @@ int ovl_mount(struct bdev *bdev)
if
(
!
ovl_name
)
if
(
!
ovl_name
)
ovl_name
=
ovl_detect_name
();
ovl_name
=
ovl_detect_name
();
/*
/* Separately mount it first:
* separately mount it first:
* mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
* mount -t overlayfs * -oupperdir=${upper},lowerdir=${lower} lower dest
*/
*/
dup
=
alloca
(
strlen
(
bdev
->
src
)
+
1
);
dup
=
strdup
(
bdev
->
src
);
strcpy
(
dup
,
bdev
->
src
);
if
(
!
dup
)
{
ERROR
(
"Failed to allocate memory"
);
return
-
1
;
}
/* support multiple lower layers */
/* support multiple lower layers */
if
(
!
(
lower
=
strstr
(
dup
,
":/"
)))
lower
=
strstr
(
dup
,
":/"
);
return
-
22
;
if
(
!
lower
)
{
ERROR
(
"Failed to detect
\"
:/
\"
in string
\"
%s
\"
"
,
dup
);
free
(
dup
);
return
-
22
;
}
lower
++
;
lower
++
;
upper
=
lower
;
upper
=
lower
;
while
((
tmp
=
strstr
(
++
upper
,
":/"
)))
{
while
((
tmp
=
strstr
(
++
upper
,
":/"
)))
{
upper
=
tmp
;
upper
=
tmp
;
}
}
if
(
--
upper
==
lower
)
upper
--
;
if
(
upper
==
lower
)
{
free
(
dup
);
return
-
22
;
return
-
22
;
}
*
upper
=
'\0'
;
*
upper
=
'\0'
;
upper
++
;
upper
++
;
// if delta doesn't yet exist, create it
/* if delta doesn't yet exist, create it */
if
(
mkdir_p
(
upper
,
0755
)
<
0
&&
errno
!=
EEXIST
)
ret
=
mkdir_p
(
upper
,
0755
)
<
0
;
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
upper
);
free
(
dup
);
return
-
22
;
return
-
22
;
}
/*
/* overlayfs.v22 or higher needs workdir option:
* overlayfs.v22 or higher needs workdir option:
* if upper is
* if upper is
* /var/lib/lxc/c2/delta0
* /var/lib/lxc/c2/delta0
* then workdir is
* then workdir is
* /var/lib/lxc/c2/olwork
* /var/lib/lxc/c2/olwork
*/
*/
lastslash
=
strrchr
(
upper
,
'/'
);
lastslash
=
strrchr
(
upper
,
'/'
);
if
(
!
lastslash
)
if
(
!
lastslash
)
{
ERROR
(
"Failed to detect
\"
/
\"
in string
\"
%s
\"
"
,
upper
);
free
(
dup
);
return
-
22
;
return
-
22
;
}
lastslash
++
;
lastslash
++
;
lastslashidx
=
lastslash
-
upper
;
lastslashidx
=
lastslash
-
upper
;
work
=
alloca
(
lastslashidx
+
7
);
work
=
malloc
(
lastslashidx
+
7
);
strncpy
(
work
,
upper
,
lastslashidx
+
7
);
if
(
!
work
)
{
strcpy
(
work
+
lastslashidx
,
"olwork"
);
ERROR
(
"Failed to allocate memory"
);
free
(
dup
);
return
-
22
;
}
if
(
parse_mntopts
(
bdev
->
mntopts
,
&
mntflags
,
&
mntdata
)
<
0
)
{
strncpy
(
work
,
upper
,
lastslashidx
+
1
);
strncpy
(
work
+
lastslashidx
,
"olwork"
,
sizeof
(
"olwork"
)
-
1
);
work
[
lastslashidx
+
sizeof
(
"olwork"
)]
=
'\0'
;
ret
=
parse_mntopts
(
bdev
->
mntopts
,
&
mntflags
,
&
mntdata
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to parse mount options"
);
free
(
mntdata
);
free
(
mntdata
);
free
(
dup
);
free
(
work
);
return
-
22
;
return
-
22
;
}
}
if
(
mkdir_p
(
work
,
0755
)
<
0
&&
errno
!=
EEXIST
)
{
ret
=
mkdir_p
(
work
,
0755
);
if
(
ret
<
0
&&
errno
!=
EEXIST
)
{
SYSERROR
(
"Failed to create directory
\"
%s
\"
"
,
work
);
free
(
mntdata
);
free
(
mntdata
);
free
(
dup
);
free
(
work
);
return
-
22
;
return
-
22
;
}
}
...
@@ -419,72 +521,94 @@ int ovl_mount(struct bdev *bdev)
...
@@ -419,72 +521,94 @@ int ovl_mount(struct bdev *bdev)
*/
*/
if
(
mntdata
)
{
if
(
mntdata
)
{
len
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
"upperdir=,lowerdir=,"
)
+
strlen
(
mntdata
)
+
1
;
len
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
"upperdir=,lowerdir=,"
)
+
strlen
(
mntdata
)
+
1
;
options
=
alloca
(
len
);
options
=
alloca
(
len
);
ret
=
snprintf
(
options
,
len
,
"upperdir=%s,lowerdir=%s,%s"
,
upper
,
lower
,
mntdata
);
ret
=
snprintf
(
options
,
len
,
"upperdir=%s,lowerdir=%s,%s"
,
upper
,
lower
,
mntdata
);
len2
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
work
)
len2
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
work
)
+
+
strlen
(
"upperdir=,lowerdir=,workdir="
)
+
strlen
(
mntdata
)
+
1
;
strlen
(
"upperdir=,lowerdir=,workdir="
)
+
strlen
(
mntdata
)
+
1
;
options_work
=
alloca
(
len2
);
options_work
=
alloca
(
len2
);
ret2
=
snprintf
(
options
,
len2
,
"upperdir=%s,lowerdir=%s,workdir=%s,%s"
,
ret2
=
snprintf
(
options
,
len2
,
upper
,
lower
,
work
,
mntdata
);
"upperdir=%s,lowerdir=%s,workdir=%s,%s"
,
upper
,
lower
,
work
,
mntdata
);
}
else
{
}
else
{
len
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
"upperdir=,lowerdir="
)
+
1
;
len
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
"upperdir=,lowerdir="
)
+
1
;
options
=
alloca
(
len
);
options
=
alloca
(
len
);
ret
=
snprintf
(
options
,
len
,
"upperdir=%s,lowerdir=%s"
,
upper
,
lower
);
ret
=
snprintf
(
options
,
len
,
"upperdir=%s,lowerdir=%s"
,
upper
,
lower
);
len2
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
work
)
len2
=
strlen
(
lower
)
+
strlen
(
upper
)
+
strlen
(
work
)
+
+
strlen
(
"upperdir=,lowerdir=,workdir="
)
+
1
;
strlen
(
"upperdir=,lowerdir=,workdir="
)
+
1
;
options_work
=
alloca
(
len2
);
options_work
=
alloca
(
len2
);
ret2
=
snprintf
(
options_work
,
len2
,
"upperdir=%s,lowerdir=%s,workdir=%s"
,
ret2
=
snprintf
(
options_work
,
len2
,
upper
,
lower
,
work
);
"upperdir=%s,lowerdir=%s,workdir=%s"
,
upper
,
lower
,
work
);
}
}
if
(
ret
<
0
||
ret
>=
len
||
ret2
<
0
||
ret2
>=
len2
)
{
if
(
ret
<
0
||
ret
>=
len
||
ret2
<
0
||
ret2
>=
len2
)
{
ERROR
(
"Failed to create string"
);
free
(
mntdata
);
free
(
mntdata
);
free
(
dup
);
free
(
work
);
return
-
1
;
return
-
1
;
}
}
/* Assume we need a workdir as we are on a overlay version >= v22. */
/* Assume we need a workdir as we are on a overlay version >= v22. */
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
(
"
Failed to mount
\"
%s
\"
on
\"
%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
));
/* Assume we cannot use a workdir as we are on a version <= v21. */
/* Assume we cannot use a workdir as we are on a version <= v21.
*/
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
(
"Failed to mount
\"
%s
\"
on
\"
%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
(
"
Mounted
\"
%s
\"
on
\"
%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
(
"
Mounted
\"
%s
\"
on
\"
%s
\"
with options
\"
%s
\"
"
,
lower
,
bdev
->
dest
,
options_work
);
bdev
->
dest
,
options_work
);
}
}
free
(
dup
);
free
(
work
);
return
ret
;
return
ret
;
}
}
int
ovl_umount
(
struct
bdev
*
bdev
)
int
ovl_umount
(
struct
bdev
*
bdev
)
{
{
int
ret
;
if
(
strcmp
(
bdev
->
type
,
"overlay"
)
&&
strcmp
(
bdev
->
type
,
"overlayfs"
))
if
(
strcmp
(
bdev
->
type
,
"overlay"
)
&&
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
);
ret
=
umount
(
bdev
->
dest
);
if
(
ret
<
0
)
SYSERROR
(
"Failed to unmount
\"
%s
\"
"
,
bdev
->
dest
);
else
TRACE
(
"Unmounted
\"
%s
\"
"
,
bdev
->
dest
);
return
ret
;
}
}
char
*
ovl_get_lower
(
const
char
*
rootfs_path
)
char
*
ovl_get_lower
(
const
char
*
rootfs_path
)
{
{
char
*
s1
;
char
*
s1
;
s1
=
strstr
(
rootfs_path
,
":/"
);
s1
=
strstr
(
rootfs_path
,
":/"
);
if
(
!
s1
)
if
(
!
s1
)
return
NULL
;
return
NULL
;
...
@@ -512,7 +636,8 @@ char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
...
@@ -512,7 +636,8 @@ char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
if
(
!
s1
)
if
(
!
s1
)
return
NULL
;
return
NULL
;
if
((
s2
=
strstr
(
s1
,
":/"
)))
{
s2
=
strstr
(
s1
,
":/"
);
if
(
s2
)
{
s2
=
s2
+
1
;
s2
=
s2
+
1
;
if
((
s3
=
strstr
(
s2
,
":/"
)))
if
((
s3
=
strstr
(
s2
,
":/"
)))
*
s3
=
'\0'
;
*
s3
=
'\0'
;
...
@@ -537,18 +662,12 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
...
@@ -537,18 +662,12 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
const
char
*
lxc_name
,
const
char
*
lxc_path
)
const
char
*
lxc_name
,
const
char
*
lxc_path
)
{
{
char
lxcpath
[
MAXPATHLEN
];
char
lxcpath
[
MAXPATHLEN
];
char
*
rootfs_path
=
NULL
;
char
**
opts
;
char
*
rootfsdir
=
NULL
;
int
ret
;
char
*
upperdir
=
NULL
;
size_t
arrlen
,
dirlen
,
i
,
len
,
rootfslen
;
char
*
workdir
=
NULL
;
char
**
opts
=
NULL
;
int
fret
=
-
1
;
int
fret
=
-
1
;
int
ret
=
0
;
char
*
rootfs_dir
=
NULL
,
*
rootfs_path
=
NULL
,
*
upperdir
=
NULL
,
size_t
arrlen
=
0
;
*
workdir
=
NULL
;
size_t
dirlen
=
0
;
size_t
i
;
size_t
len
=
0
;
size_t
rootfslen
=
0
;
/* When rootfs == NULL we have a container without a rootfs. */
/* When rootfs == NULL we have a container without a rootfs. */
if
(
rootfs
&&
rootfs
->
path
)
if
(
rootfs
&&
rootfs
->
path
)
...
@@ -561,19 +680,22 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
...
@@ -561,19 +680,22 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
goto
err
;
goto
err
;
for
(
i
=
0
;
i
<
arrlen
;
i
++
)
{
for
(
i
=
0
;
i
<
arrlen
;
i
++
)
{
if
(
strstr
(
opts
[
i
],
"upperdir="
)
&&
(
strlen
(
opts
[
i
])
>
(
len
=
strlen
(
"upperdir="
))))
if
(
strstr
(
opts
[
i
],
"upperdir="
)
&&
(
strlen
(
opts
[
i
])
>
(
len
=
strlen
(
"upperdir="
))))
upperdir
=
opts
[
i
]
+
len
;
upperdir
=
opts
[
i
]
+
len
;
else
if
(
strstr
(
opts
[
i
],
"workdir="
)
&&
(
strlen
(
opts
[
i
])
>
(
len
=
strlen
(
"workdir="
))))
else
if
(
strstr
(
opts
[
i
],
"workdir="
)
&&
(
strlen
(
opts
[
i
])
>
(
len
=
strlen
(
"workdir="
))))
workdir
=
opts
[
i
]
+
len
;
workdir
=
opts
[
i
]
+
len
;
}
}
if
(
rootfs_path
)
{
if
(
rootfs_path
)
{
ret
=
snprintf
(
lxcpath
,
MAXPATHLEN
,
"%s/%s"
,
lxc_path
,
lxc_name
);
ret
=
snprintf
(
lxcpath
,
MAXPATHLEN
,
"%s/%s"
,
lxc_path
,
lxc_name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
goto
err
;
goto
err
;
rootfsdir
=
ovl_get_rootfs
(
rootfs_path
,
&
rootfslen
);
rootfs
_
dir
=
ovl_get_rootfs
(
rootfs_path
,
&
rootfslen
);
if
(
!
rootfsdir
)
if
(
!
rootfs
_
dir
)
goto
err
;
goto
err
;
dirlen
=
strlen
(
lxcpath
);
dirlen
=
strlen
(
lxcpath
);
...
@@ -588,51 +710,52 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
...
@@ -588,51 +710,52 @@ int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
if
(
upperdir
)
{
if
(
upperdir
)
{
if
(
!
rootfs_path
)
if
(
!
rootfs_path
)
ret
=
mkdir_p
(
upperdir
,
0755
);
ret
=
mkdir_p
(
upperdir
,
0755
);
else
if
((
strncmp
(
upperdir
,
lxcpath
,
dirlen
)
==
0
)
&&
(
strncmp
(
upperdir
,
rootfsdir
,
rootfslen
)
!=
0
))
else
if
(
!
strncmp
(
upperdir
,
lxcpath
,
dirlen
)
&&
strncmp
(
upperdir
,
rootfs_dir
,
rootfslen
))
ret
=
mkdir_p
(
upperdir
,
0755
);
ret
=
mkdir_p
(
upperdir
,
0755
);
if
(
ret
<
0
)
if
(
ret
<
0
)
WARN
(
"Failed to create upperdir"
);
WARN
(
"Failed to create directory
\"
%s
\"
: %s"
,
upperdir
,
strerror
(
errno
));
}
}
ret
=
0
;
ret
=
0
;
if
(
workdir
)
{
if
(
workdir
)
{
if
(
!
rootfs_path
)
if
(
!
rootfs_path
)
ret
=
mkdir_p
(
workdir
,
0755
);
ret
=
mkdir_p
(
workdir
,
0755
);
else
if
((
strncmp
(
workdir
,
lxcpath
,
dirlen
)
==
0
)
&&
(
strncmp
(
workdir
,
rootfsdir
,
rootfslen
)
!=
0
))
else
if
(
!
strncmp
(
workdir
,
lxcpath
,
dirlen
)
&&
strncmp
(
workdir
,
rootfs_dir
,
rootfslen
))
ret
=
mkdir_p
(
workdir
,
0755
);
ret
=
mkdir_p
(
workdir
,
0755
);
if
(
ret
<
0
)
if
(
ret
<
0
)
WARN
(
"Failed to create workdir"
);
WARN
(
"Failed to create directory
\"
%s
\"
: %s"
,
workdir
,
strerror
(
errno
));
}
}
fret
=
0
;
fret
=
0
;
err:
err:
free
(
rootfsdir
);
free
(
rootfs
_
dir
);
lxc_free_array
((
void
**
)
opts
,
free
);
lxc_free_array
((
void
**
)
opts
,
free
);
return
fret
;
return
fret
;
}
}
/*
/* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
* with overlay lxc.mount.entry entries we need to update absolute paths for
* with overlay lxc.mount.entry entries we need to update absolute paths for
* upper- and workdir. This update is done in two locations:
* upper- and workdir. This update is done in two locations:
* lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
* lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
* independent of each other since lxc_conf->mountlist may contain
er
more mount
* independent of each other since lxc_conf->mountlist may contain more mount
* entries (e.g. from other included files) than lxc_conf->unexpanded_config
.
* entries (e.g. from other included files) than lxc_conf->unexpanded_config.
*/
*/
int
ovl_update_abs_paths
(
struct
lxc_conf
*
lxc_conf
,
const
char
*
lxc_path
,
int
ovl_update_abs_paths
(
struct
lxc_conf
*
lxc_conf
,
const
char
*
lxc_path
,
const
char
*
lxc_name
,
const
char
*
newpath
,
const
char
*
lxc_name
,
const
char
*
newpath
,
const
char
*
newname
)
const
char
*
newname
)
{
{
char
new_upper
[
MAXPATHLEN
];
char
new_upper
[
MAXPATHLEN
],
new_work
[
MAXPATHLEN
],
old_upper
[
MAXPATHLEN
],
char
new_work
[
MAXPATHLEN
];
old_work
[
MAXPATHLEN
];
char
old_upper
[
MAXPATHLEN
];
char
old_work
[
MAXPATHLEN
];
char
*
cleanpath
=
NULL
;
size_t
i
;
size_t
i
;
struct
lxc_list
*
iterator
;
char
*
cleanpath
=
NULL
;
int
fret
=
-
1
;
int
fret
=
-
1
;
int
ret
=
0
;
int
ret
=
0
;
struct
lxc_list
*
iterator
;
const
char
*
ovl_dirs
[]
=
{
"br"
,
"upperdir"
,
"workdir"
};
const
char
*
ovl_dirs
[]
=
{
"br"
,
"upperdir"
,
"workdir"
};
cleanpath
=
strdup
(
newpath
);
cleanpath
=
strdup
(
newpath
);
...
@@ -652,19 +775,20 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
...
@@ -652,19 +775,20 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
goto
err
;
goto
err
;
}
}
ret
=
snprintf
(
old_work
,
MAXPATHLEN
,
"workdir=%s/%s"
,
lxc_path
,
lxc_name
);
ret
=
snprintf
(
old_work
,
MAXPATHLEN
,
"workdir=%s/%s"
,
lxc_path
,
lxc_name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
goto
err
;
goto
err
;
ret
=
snprintf
(
new_work
,
MAXPATHLEN
,
"workdir=%s/%s"
,
cleanpath
,
newname
);
ret
=
snprintf
(
new_work
,
MAXPATHLEN
,
"workdir=%s/%s"
,
cleanpath
,
newname
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
goto
err
;
goto
err
;
lxc_list_for_each
(
iterator
,
&
lxc_conf
->
mount_list
)
{
lxc_list_for_each
(
iterator
,
&
lxc_conf
->
mount_list
)
{
char
*
mnt_entry
=
NULL
;
char
*
mnt_entry
=
NULL
,
*
new_mnt_entry
=
NULL
,
*
tmp
=
NULL
,
char
*
new_mnt_entry
=
NULL
;
*
tmp_mnt_entry
=
NULL
;
char
*
tmp
=
NULL
;
char
*
tmp_mnt_entry
=
NULL
;
mnt_entry
=
iterator
->
elem
;
mnt_entry
=
iterator
->
elem
;
if
(
strstr
(
mnt_entry
,
"overlay"
))
if
(
strstr
(
mnt_entry
,
"overlay"
))
...
@@ -675,23 +799,28 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
...
@@ -675,23 +799,28 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
if
(
!
tmp
)
if
(
!
tmp
)
continue
;
continue
;
ret
=
snprintf
(
old_upper
,
MAXPATHLEN
,
"%s=%s/%s"
,
tmp
,
lxc_path
,
lxc_name
);
ret
=
snprintf
(
old_upper
,
MAXPATHLEN
,
"%s=%s/%s"
,
tmp
,
lxc_path
,
lxc_name
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
goto
err
;
goto
err
;
ret
=
snprintf
(
new_upper
,
MAXPATHLEN
,
"%s=%s/%s"
,
tmp
,
cleanpath
,
newname
);
ret
=
snprintf
(
new_upper
,
MAXPATHLEN
,
"%s=%s/%s"
,
tmp
,
cleanpath
,
newname
);
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
if
(
ret
<
0
||
ret
>=
MAXPATHLEN
)
goto
err
;
goto
err
;
if
(
strstr
(
mnt_entry
,
old_upper
))
{
if
(
strstr
(
mnt_entry
,
old_upper
))
{
tmp_mnt_entry
=
lxc_string_replace
(
old_upper
,
new_upper
,
mnt_entry
);
tmp_mnt_entry
=
lxc_string_replace
(
old_upper
,
new_upper
,
mnt_entry
);
}
}
if
(
strstr
(
mnt_entry
,
old_work
))
{
if
(
strstr
(
mnt_entry
,
old_work
))
{
if
(
tmp_mnt_entry
)
if
(
tmp_mnt_entry
)
new_mnt_entry
=
lxc_string_replace
(
old_work
,
new_work
,
tmp_mnt_entry
);
new_mnt_entry
=
lxc_string_replace
(
old_work
,
new_work
,
tmp_mnt_entry
);
else
else
new_mnt_entry
=
lxc_string_replace
(
old_work
,
new_work
,
mnt_entry
);
new_mnt_entry
=
lxc_string_replace
(
old_work
,
new_work
,
mnt_entry
);
}
}
if
(
new_mnt_entry
)
{
if
(
new_mnt_entry
)
{
...
@@ -716,68 +845,24 @@ static int ovl_remount_on_enodev(const char *lower, const char *target,
...
@@ -716,68 +845,24 @@ static int ovl_remount_on_enodev(const char *lower, const char *target,
const
char
*
name
,
unsigned
long
mountflags
,
const
char
*
name
,
unsigned
long
mountflags
,
const
void
*
options
)
const
void
*
options
)
{
{
int
ret
;
int
ret
;
ret
=
mount
(
lower
,
target
,
ovl_name
,
MS_MGC_VAL
|
mountflags
,
options
);
ret
=
mount
(
lower
,
target
,
ovl_name
,
MS_MGC_VAL
|
mountflags
,
options
);
if
(
ret
<
0
&&
errno
==
ENODEV
)
/* Try other module name. */
if
(
ret
<
0
&&
errno
==
ENODEV
)
/* Try other module name. */
ret
=
mount
(
lower
,
target
,
ret
=
mount
(
lower
,
target
,
ovl_name
==
ovl_version
[
0
]
?
ovl_version
[
1
]
ovl_name
==
ovl_version
[
0
]
?
ovl_version
[
1
]
:
ovl_version
[
0
],
:
ovl_version
[
0
],
MS_MGC_VAL
|
mountflags
,
options
);
MS_MGC_VAL
|
mountflags
,
options
);
return
ret
;
return
ret
;
}
static
int
ovl_rsync
(
struct
rsync_data
*
data
)
{
int
ret
;
if
(
setgid
(
0
)
<
0
)
{
ERROR
(
"Failed to setgid to 0"
);
return
-
1
;
}
if
(
setgroups
(
0
,
NULL
)
<
0
)
WARN
(
"Failed to clear groups"
);
if
(
setuid
(
0
)
<
0
)
{
ERROR
(
"Failed to setuid to 0"
);
return
-
1
;
}
if
(
unshare
(
CLONE_NEWNS
)
<
0
)
{
SYSERROR
(
"Unable to unshare mounts ns"
);
return
-
1
;
}
if
(
detect_shared_rootfs
())
{
if
(
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
))
{
SYSERROR
(
"Failed to make / rslave"
);
ERROR
(
"Continuing..."
);
}
}
if
(
ovl_mount
(
data
->
orig
)
<
0
)
{
ERROR
(
"Failed mounting original container fs"
);
return
-
1
;
}
if
(
ovl_mount
(
data
->
new
)
<
0
)
{
ERROR
(
"Failed mounting new container fs"
);
return
-
1
;
}
ret
=
do_rsync
(
data
->
orig
->
dest
,
data
->
new
->
dest
);
ovl_umount
(
data
->
new
);
ovl_umount
(
data
->
orig
);
if
(
ret
<
0
)
{
ERROR
(
"rsyncing %s to %s"
,
data
->
orig
->
dest
,
data
->
new
->
dest
);
return
-
1
;
}
return
0
;
}
}
static
char
*
ovl_detect_name
(
void
)
static
char
*
ovl_detect_name
(
void
)
{
{
FILE
*
f
;
char
*
v
=
ovl_version
[
0
];
char
*
v
=
ovl_version
[
0
];
char
*
line
=
NULL
;
char
*
line
=
NULL
;
size_t
len
=
0
;
size_t
len
=
0
;
FILE
*
f
=
fopen
(
"/proc/filesystems"
,
"r"
);
f
=
fopen
(
"/proc/filesystems"
,
"r"
);
if
(
!
f
)
if
(
!
f
)
return
v
;
return
v
;
...
@@ -793,27 +878,28 @@ static char *ovl_detect_name(void)
...
@@ -793,27 +878,28 @@ static char *ovl_detect_name(void)
return
v
;
return
v
;
}
}
static
int
ovl_do_rsync
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
struct
lxc_conf
*
conf
)
static
int
ovl_do_rsync
(
struct
bdev
*
orig
,
struct
bdev
*
new
,
struct
lxc_conf
*
conf
)
{
{
int
ret
=
-
1
;
int
ret
=
-
1
;
struct
rsync_data
rdata
;
struct
rsync_data
rdata
=
{
0
,
0
};
char
cmd_output
[
MAXPATHLEN
]
=
{
0
};
rdata
.
orig
=
orig
;
rdata
.
orig
=
orig
;
rdata
.
new
=
new
;
rdata
.
new
=
new
;
if
(
am_unpriv
())
if
(
am_unpriv
())
{
ret
=
userns_exec_1
(
conf
,
ovl_rsync_wrapper
,
&
rdata
,
ret
=
userns_exec_1
(
conf
,
lxc_rsync_exec_wrapper
,
&
rdata
,
"ovl_rsync_wrapper"
);
"lxc_rsync_exec_wrapper"
);
else
if
(
ret
<
0
)
ret
=
ovl_rsync
(
&
rdata
);
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
"
,
if
(
ret
)
orig
->
dest
,
new
->
dest
);
ERROR
(
"copying overlay delta"
);
}
else
{
ret
=
run_command
(
cmd_output
,
sizeof
(
cmd_output
),
lxc_rsync_exec_wrapper
,
(
void
*
)
&
rdata
);
if
(
ret
<
0
)
ERROR
(
"Failed to rsync from
\"
%s
\"
into
\"
%s
\"
: %s"
,
orig
->
dest
,
new
->
dest
,
cmd_output
);
}
return
ret
;
return
ret
;
}
}
static
int
ovl_rsync_wrapper
(
void
*
data
)
{
struct
rsync_data
*
arg
=
data
;
return
ovl_rsync
(
arg
);
}
src/lxc/lxccontainer.c
View file @
241978fa
...
@@ -1263,11 +1263,45 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
...
@@ -1263,11 +1263,45 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool need_
if
(
strcmp
(
bdev
->
type
,
"dir"
)
&&
strcmp
(
bdev
->
type
,
"btrfs"
))
{
if
(
strcmp
(
bdev
->
type
,
"dir"
)
&&
strcmp
(
bdev
->
type
,
"btrfs"
))
{
if
(
geteuid
()
!=
0
)
{
if
(
geteuid
()
!=
0
)
{
ERROR
(
"non-root users can only create btrfs and directory-backed containers"
);
ERROR
(
"non-root users can only create btrfs and directory-backed containers"
);
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
}
if
(
bdev
->
ops
->
mount
(
bdev
)
<
0
)
{
ERROR
(
"Error mounting rootfs"
);
if
(
!
strcmp
(
bdev
->
type
,
"overlay"
)
||
!
strcmp
(
bdev
->
type
,
"overlayfs"
))
{
exit
(
1
);
/* If we create an overlay container we need to
* rsync the contents into
* <container-path>/<container-name>/rootfs.
* However, the overlay mount function will
* mount will mount
* <container-path>/<container-name>/delta0
* over
* <container-path>/<container-name>/rootfs
* which means we would rsync the rootfs into
* the delta directory. That doesn't make sense
* since the delta directory only exists to
* record the differences to
* <container-path>/<container-name>/rootfs. So
* let's simply bind-mount here and then rsync
* directly into
* <container-path>/<container-name>/rootfs.
*/
char
*
src
;
src
=
ovl_get_rootfs
(
bdev
->
src
,
&
(
size_t
){
0
});
if
(
!
src
)
{
ERROR
(
"Failed to get rootfs"
);
exit
(
EXIT_FAILURE
);
}
ret
=
mount
(
src
,
bdev
->
dest
,
"bind"
,
MS_BIND
|
MS_REC
,
NULL
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to mount rootfs"
);
return
-
1
;
}
}
else
{
if
(
bdev
->
ops
->
mount
(
bdev
)
<
0
)
{
ERROR
(
"Failed to mount rootfs"
);
exit
(
EXIT_FAILURE
);
}
}
}
}
else
{
// TODO come up with a better way here!
}
else
{
// TODO come up with a better way here!
char
*
src
;
char
*
src
;
...
...
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