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
493de765
Unverified
Commit
493de765
authored
Jun 04, 2017
by
Christian Brauner
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bdev: non-functional changes
Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
b9986e43
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
228 additions
and
186 deletions
+228
-186
bdev.c
src/lxc/bdev/bdev.c
+203
-159
bdev.h
src/lxc/bdev/bdev.h
+25
-27
No files found.
src/lxc/bdev/bdev.c
View file @
493de765
...
@@ -75,110 +75,110 @@ lxc_log_define(bdev, lxc);
...
@@ -75,110 +75,110 @@ lxc_log_define(bdev, lxc);
/* aufs */
/* aufs */
static
const
struct
bdev_ops
aufs_ops
=
{
static
const
struct
bdev_ops
aufs_ops
=
{
.
detect
=
&
aufs_detect
,
.
detect
=
&
aufs_detect
,
.
mount
=
&
aufs_mount
,
.
mount
=
&
aufs_mount
,
.
umount
=
&
aufs_umount
,
.
umount
=
&
aufs_umount
,
.
clone_paths
=
&
aufs_clonepaths
,
.
clone_paths
=
&
aufs_clonepaths
,
.
destroy
=
&
aufs_destroy
,
.
destroy
=
&
aufs_destroy
,
.
create
=
&
aufs_create
,
.
create
=
&
aufs_create
,
.
can_snapshot
=
true
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
.
can_backup
=
true
,
};
};
/* btrfs */
/* btrfs */
static
const
struct
bdev_ops
btrfs_ops
=
{
static
const
struct
bdev_ops
btrfs_ops
=
{
.
detect
=
&
btrfs_detect
,
.
detect
=
&
btrfs_detect
,
.
mount
=
&
btrfs_mount
,
.
mount
=
&
btrfs_mount
,
.
umount
=
&
btrfs_umount
,
.
umount
=
&
btrfs_umount
,
.
clone_paths
=
&
btrfs_clonepaths
,
.
clone_paths
=
&
btrfs_clonepaths
,
.
destroy
=
&
btrfs_destroy
,
.
destroy
=
&
btrfs_destroy
,
.
create
=
&
btrfs_create
,
.
create
=
&
btrfs_create
,
.
can_snapshot
=
true
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
.
can_backup
=
true
,
};
};
/* dir */
/* dir */
static
const
struct
bdev_ops
dir_ops
=
{
static
const
struct
bdev_ops
dir_ops
=
{
.
detect
=
&
dir_detect
,
.
detect
=
&
dir_detect
,
.
mount
=
&
dir_mount
,
.
mount
=
&
dir_mount
,
.
umount
=
&
dir_umount
,
.
umount
=
&
dir_umount
,
.
clone_paths
=
&
dir_clonepaths
,
.
clone_paths
=
&
dir_clonepaths
,
.
destroy
=
&
dir_destroy
,
.
destroy
=
&
dir_destroy
,
.
create
=
&
dir_create
,
.
create
=
&
dir_create
,
.
can_snapshot
=
false
,
.
can_snapshot
=
false
,
.
can_backup
=
true
,
.
can_backup
=
true
,
};
};
/* loop */
/* loop */
static
const
struct
bdev_ops
loop_ops
=
{
static
const
struct
bdev_ops
loop_ops
=
{
.
detect
=
&
loop_detect
,
.
detect
=
&
loop_detect
,
.
mount
=
&
loop_mount
,
.
mount
=
&
loop_mount
,
.
umount
=
&
loop_umount
,
.
umount
=
&
loop_umount
,
.
clone_paths
=
&
loop_clonepaths
,
.
clone_paths
=
&
loop_clonepaths
,
.
destroy
=
&
loop_destroy
,
.
destroy
=
&
loop_destroy
,
.
create
=
&
loop_create
,
.
create
=
&
loop_create
,
.
can_snapshot
=
false
,
.
can_snapshot
=
false
,
.
can_backup
=
true
,
.
can_backup
=
true
,
};
};
/* lvm */
/* lvm */
static
const
struct
bdev_ops
lvm_ops
=
{
static
const
struct
bdev_ops
lvm_ops
=
{
.
detect
=
&
lvm_detect
,
.
detect
=
&
lvm_detect
,
.
mount
=
&
lvm_mount
,
.
mount
=
&
lvm_mount
,
.
umount
=
&
lvm_umount
,
.
umount
=
&
lvm_umount
,
.
clone_paths
=
&
lvm_clonepaths
,
.
clone_paths
=
&
lvm_clonepaths
,
.
destroy
=
&
lvm_destroy
,
.
destroy
=
&
lvm_destroy
,
.
create
=
&
lvm_create
,
.
create
=
&
lvm_create
,
.
can_snapshot
=
true
,
.
can_snapshot
=
true
,
.
can_backup
=
false
,
.
can_backup
=
false
,
};
};
/* nbd */
/* nbd */
const
struct
bdev_ops
nbd_ops
=
{
const
struct
bdev_ops
nbd_ops
=
{
.
detect
=
&
nbd_detect
,
.
detect
=
&
nbd_detect
,
.
mount
=
&
nbd_mount
,
.
mount
=
&
nbd_mount
,
.
umount
=
&
nbd_umount
,
.
umount
=
&
nbd_umount
,
.
clone_paths
=
&
nbd_clonepaths
,
.
clone_paths
=
&
nbd_clonepaths
,
.
destroy
=
&
nbd_destroy
,
.
destroy
=
&
nbd_destroy
,
.
create
=
&
nbd_create
,
.
create
=
&
nbd_create
,
.
can_snapshot
=
true
,
.
can_snapshot
=
true
,
.
can_backup
=
false
,
.
can_backup
=
false
,
};
};
/* overlay */
/* overlay */
static
const
struct
bdev_ops
ovl_ops
=
{
static
const
struct
bdev_ops
ovl_ops
=
{
.
detect
=
&
ovl_detect
,
.
detect
=
&
ovl_detect
,
.
mount
=
&
ovl_mount
,
.
mount
=
&
ovl_mount
,
.
umount
=
&
ovl_umount
,
.
umount
=
&
ovl_umount
,
.
clone_paths
=
&
ovl_clonepaths
,
.
clone_paths
=
&
ovl_clonepaths
,
.
destroy
=
&
ovl_destroy
,
.
destroy
=
&
ovl_destroy
,
.
create
=
&
ovl_create
,
.
create
=
&
ovl_create
,
.
can_snapshot
=
true
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
.
can_backup
=
true
,
};
};
/* rbd */
/* rbd */
static
const
struct
bdev_ops
rbd_ops
=
{
static
const
struct
bdev_ops
rbd_ops
=
{
.
detect
=
&
rbd_detect
,
.
detect
=
&
rbd_detect
,
.
mount
=
&
rbd_mount
,
.
mount
=
&
rbd_mount
,
.
umount
=
&
rbd_umount
,
.
umount
=
&
rbd_umount
,
.
clone_paths
=
&
rbd_clonepaths
,
.
clone_paths
=
&
rbd_clonepaths
,
.
destroy
=
&
rbd_destroy
,
.
destroy
=
&
rbd_destroy
,
.
create
=
&
rbd_create
,
.
create
=
&
rbd_create
,
.
can_snapshot
=
false
,
.
can_snapshot
=
false
,
.
can_backup
=
false
,
.
can_backup
=
false
,
};
};
/* zfs */
/* zfs */
static
const
struct
bdev_ops
zfs_ops
=
{
static
const
struct
bdev_ops
zfs_ops
=
{
.
detect
=
&
zfs_detect
,
.
detect
=
&
zfs_detect
,
.
mount
=
&
zfs_mount
,
.
mount
=
&
zfs_mount
,
.
umount
=
&
zfs_umount
,
.
umount
=
&
zfs_umount
,
.
clone_paths
=
&
zfs_clonepaths
,
.
clone_paths
=
&
zfs_clonepaths
,
.
destroy
=
&
zfs_destroy
,
.
destroy
=
&
zfs_destroy
,
.
create
=
&
zfs_create
,
.
create
=
&
zfs_create
,
.
can_snapshot
=
true
,
.
can_snapshot
=
true
,
.
can_backup
=
true
,
.
can_backup
=
true
,
};
};
struct
bdev_type
{
struct
bdev_type
{
...
@@ -187,32 +187,33 @@ struct bdev_type {
...
@@ -187,32 +187,33 @@ struct bdev_type {
};
};
static
const
struct
bdev_type
bdevs
[]
=
{
static
const
struct
bdev_type
bdevs
[]
=
{
{
.
name
=
"zfs"
,
.
ops
=
&
zfs_ops
,
},
{
.
name
=
"zfs"
,
.
ops
=
&
zfs_ops
,
},
{
.
name
=
"lvm"
,
.
ops
=
&
lvm_ops
,
},
{
.
name
=
"lvm"
,
.
ops
=
&
lvm_ops
,
},
{
.
name
=
"rbd"
,
.
ops
=
&
rbd_ops
,
},
{
.
name
=
"rbd"
,
.
ops
=
&
rbd_ops
,
},
{
.
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
=
"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
,
},
};
};
static
const
size_t
numbdevs
=
sizeof
(
bdevs
)
/
sizeof
(
struct
bdev_type
);
static
const
size_t
numbdevs
=
sizeof
(
bdevs
)
/
sizeof
(
struct
bdev_type
);
/* helpers */
/* helpers */
static
const
struct
bdev_type
*
bdev_query
(
struct
lxc_conf
*
conf
,
const
char
*
src
);
static
const
struct
bdev_type
*
bdev_query
(
struct
lxc_conf
*
conf
,
const
char
*
src
);
static
struct
bdev
*
bdev_get
(
const
char
*
type
);
static
struct
bdev
*
bdev_get
(
const
char
*
type
);
static
struct
bdev
*
do_bdev_create
(
const
char
*
dest
,
const
char
*
type
,
static
struct
bdev
*
do_bdev_create
(
const
char
*
dest
,
const
char
*
type
,
const
char
*
cname
,
struct
bdev_specs
*
specs
);
const
char
*
cname
,
struct
bdev_specs
*
specs
);
static
int
find_fstype_cb
(
char
*
buffer
,
void
*
data
);
static
int
find_fstype_cb
(
char
*
buffer
,
void
*
data
);
static
char
*
linkderef
(
char
*
path
,
char
*
dest
);
static
char
*
linkderef
(
char
*
path
,
char
*
dest
);
static
bool
unpriv_snap_allowed
(
struct
bdev
*
b
,
const
char
*
t
,
bool
snap
,
static
bool
unpriv_snap_allowed
(
struct
bdev
*
b
,
const
char
*
t
,
bool
snap
,
bool
maybesnap
);
bool
maybesnap
);
/* the bulk of this needs to become a common helper */
/* the bulk of this needs to become a common helper */
char
*
dir_new_path
(
char
*
src
,
const
char
*
oldname
,
const
char
*
name
,
char
*
dir_new_path
(
char
*
src
,
const
char
*
oldname
,
const
char
*
name
,
const
char
*
oldpath
,
const
char
*
lxcpath
)
const
char
*
oldpath
,
const
char
*
lxcpath
)
{
{
char
*
ret
,
*
p
,
*
p2
;
char
*
ret
,
*
p
,
*
p2
;
int
l1
,
l2
,
nlen
;
int
l1
,
l2
,
nlen
;
...
@@ -244,11 +245,12 @@ char *dir_new_path(char *src, const char *oldname, const char *name,
...
@@ -244,11 +245,12 @@ char *dir_new_path(char *src, const char *oldname, const char *name,
while
((
p2
=
strstr
(
src
,
oldname
))
!=
NULL
)
{
while
((
p2
=
strstr
(
src
,
oldname
))
!=
NULL
)
{
strncpy
(
p
,
src
,
p2
-
src
);
// copy text up to oldname
strncpy
(
p
,
src
,
p2
-
src
);
// copy text up to oldname
p
+=
p2
-
src
;
// move target pointer (p)
p
+=
p2
-
src
;
// move target pointer (p)
p
+=
sprintf
(
p
,
"%s"
,
name
);
// print new name in place of oldname
p
+=
sprintf
(
p
,
"%s"
,
src
=
p2
+
l2
;
// move src to end of oldname
name
);
// print new name in place of oldname
src
=
p2
+
l2
;
// move src to end of oldname
}
}
sprintf
(
p
,
"%s"
,
src
);
// copy the rest of src
sprintf
(
p
,
"%s"
,
src
);
// copy the rest of src
return
ret
;
return
ret
;
}
}
...
@@ -264,15 +266,19 @@ bool attach_block_device(struct lxc_conf *conf)
...
@@ -264,15 +266,19 @@ bool attach_block_device(struct lxc_conf *conf)
if
(
!
conf
->
rootfs
.
path
)
if
(
!
conf
->
rootfs
.
path
)
return
true
;
return
true
;
path
=
conf
->
rootfs
.
path
;
path
=
conf
->
rootfs
.
path
;
if
(
!
requires_nbd
(
path
))
if
(
!
requires_nbd
(
path
))
return
true
;
return
true
;
path
=
strchr
(
path
,
':'
);
path
=
strchr
(
path
,
':'
);
if
(
!
path
)
if
(
!
path
)
return
false
;
return
false
;
path
++
;
path
++
;
if
(
!
attach_nbd
(
path
,
conf
))
if
(
!
attach_nbd
(
path
,
conf
))
return
false
;
return
false
;
return
true
;
return
true
;
}
}
...
@@ -283,6 +289,7 @@ bool bdev_can_backup(struct lxc_conf *conf)
...
@@ -283,6 +289,7 @@ bool bdev_can_backup(struct lxc_conf *conf)
if
(
!
bdev
)
if
(
!
bdev
)
return
false
;
return
false
;
ret
=
bdev
->
ops
->
can_backup
;
ret
=
bdev
->
ops
->
can_backup
;
bdev_put
(
bdev
);
bdev_put
(
bdev
);
return
ret
;
return
ret
;
...
@@ -293,8 +300,8 @@ bool bdev_can_backup(struct lxc_conf *conf)
...
@@ -293,8 +300,8 @@ bool bdev_can_backup(struct lxc_conf *conf)
* the original, mount the new, and rsync the contents.
* the original, mount the new, and rsync the contents.
*/
*/
struct
bdev
*
bdev_copy
(
struct
lxc_container
*
c0
,
const
char
*
cname
,
struct
bdev
*
bdev_copy
(
struct
lxc_container
*
c0
,
const
char
*
cname
,
const
char
*
lxcpath
,
const
char
*
bdevtype
,
int
flags
,
const
char
*
lxcpath
,
const
char
*
bdevtype
,
int
flags
,
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
;
pid_t
pid
;
...
@@ -311,8 +318,9 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -311,8 +318,9 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
* we 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
)
==
NULL
)
{
if
(
strstr
(
src
,
oldname
)
==
NULL
)
{
ERROR
(
"original rootfs path %s doesn't include container name %s"
,
ERROR
(
src
,
oldname
);
"original rootfs path %s doesn't include container name %s"
,
src
,
oldname
);
return
NULL
;
return
NULL
;
}
}
...
@@ -334,6 +342,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -334,6 +342,7 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
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
(
"rootfs path too long"
);
ERROR
(
"rootfs path too long"
);
...
@@ -341,9 +350,11 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -341,9 +350,11 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
return
NULL
;
return
NULL
;
}
}
ret
=
stat
(
orig
->
dest
,
&
sb
);
ret
=
stat
(
orig
->
dest
,
&
sb
);
if
(
ret
<
0
&&
errno
==
ENOENT
)
if
(
ret
<
0
&&
errno
==
ENOENT
)
if
(
mkdir_p
(
orig
->
dest
,
0755
)
<
0
)
if
(
mkdir_p
(
orig
->
dest
,
0755
)
<
0
)
WARN
(
"Error creating '%s', continuing."
,
orig
->
dest
);
WARN
(
"Error creating '%s', continuing."
,
orig
->
dest
);
}
}
/*
/*
...
@@ -357,7 +368,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -357,7 +368,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
/*
/*
* If newtype is NULL and snapshot is set, then use overlayfs
* If newtype is NULL and snapshot is set, then use overlayfs
*/
*/
if
(
!
bdevtype
&&
!
keepbdevtype
&&
snap
&&
strcmp
(
orig
->
type
,
"dir"
)
==
0
)
if
(
!
bdevtype
&&
!
keepbdevtype
&&
snap
&&
strcmp
(
orig
->
type
,
"dir"
)
==
0
)
bdevtype
=
"overlayfs"
;
bdevtype
=
"overlayfs"
;
if
(
am_unpriv
()
&&
!
unpriv_snap_allowed
(
orig
,
bdevtype
,
snap
,
maybe_snap
))
{
if
(
am_unpriv
()
&&
!
unpriv_snap_allowed
(
orig
,
bdevtype
,
snap
,
maybe_snap
))
{
...
@@ -368,23 +380,24 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -368,23 +380,24 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
*
needs_rdep
=
0
;
*
needs_rdep
=
0
;
if
(
bdevtype
&&
strcmp
(
orig
->
type
,
"dir"
)
==
0
&&
if
(
bdevtype
&&
strcmp
(
orig
->
type
,
"dir"
)
==
0
&&
(
strcmp
(
bdevtype
,
"aufs"
)
==
0
||
(
strcmp
(
bdevtype
,
"aufs"
)
==
0
||
strcmp
(
bdevtype
,
"overlayfs"
)
==
0
))
{
strcmp
(
bdevtype
,
"overlayfs"
)
==
0
))
{
*
needs_rdep
=
1
;
*
needs_rdep
=
1
;
}
else
if
(
snap
&&
strcmp
(
orig
->
type
,
"lvm"
)
==
0
&&
}
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
;
}
}
new
=
bdev_get
(
bdevtype
?
bdevtype
:
orig
->
type
);
new
=
bdev_get
(
bdevtype
?
bdevtype
:
orig
->
type
);
if
(
!
new
)
{
if
(
!
new
)
{
ERROR
(
"no such block device type: %s"
,
bdevtype
?
bdevtype
:
orig
->
type
);
ERROR
(
"no such block device type: %s"
,
bdevtype
?
bdevtype
:
orig
->
type
);
bdev_put
(
orig
);
bdev_put
(
orig
);
return
NULL
;
return
NULL
;
}
}
if
(
new
->
ops
->
clone_paths
(
orig
,
new
,
oldname
,
cname
,
oldpath
,
lxcpath
,
if
(
new
->
ops
->
clone_paths
(
orig
,
new
,
oldname
,
cname
,
oldpath
,
lxcpath
,
snap
,
newsize
,
c0
->
lxc_conf
)
<
0
)
{
snap
,
newsize
,
c0
->
lxc_conf
)
<
0
)
{
ERROR
(
"failed getting pathnames for cloned storage: %s"
,
src
);
ERROR
(
"failed getting pathnames for cloned storage: %s"
,
src
);
goto
err
;
goto
err
;
}
}
...
@@ -397,11 +410,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -397,11 +410,12 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
/*
/*
* https://github.com/lxc/lxc/issues/131
* https://github.com/lxc/lxc/issues/131
* Use btrfs snapshot feature instead of rsync to restore if both orig and new are btrfs
* Use btrfs snapshot feature instead of rsync to restore if both orig
* and new are btrfs
*/
*/
if
(
bdevtype
&&
if
(
bdevtype
&&
strcmp
(
orig
->
type
,
"btrfs"
)
==
0
&&
strcmp
(
orig
->
type
,
"btrfs"
)
==
0
&&
strcmp
(
new
->
type
,
"btrfs"
)
==
0
&&
strcmp
(
new
->
type
,
"btrfs"
)
==
0
&&
btrfs_same_fs
(
orig
->
dest
,
new
->
dest
)
==
0
)
{
btrfs_same_fs
(
orig
->
dest
,
new
->
dest
)
==
0
)
{
if
(
btrfs_destroy
(
new
)
<
0
)
{
if
(
btrfs_destroy
(
new
)
<
0
)
{
ERROR
(
"Error destroying %s subvolume"
,
new
->
dest
);
ERROR
(
"Error destroying %s subvolume"
,
new
->
dest
);
goto
err
;
goto
err
;
...
@@ -411,7 +425,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -411,7 +425,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
goto
err
;
goto
err
;
}
}
if
(
btrfs_snapshot
(
orig
->
dest
,
new
->
dest
)
<
0
)
{
if
(
btrfs_snapshot
(
orig
->
dest
,
new
->
dest
)
<
0
)
{
ERROR
(
"Error restoring %s to %s"
,
orig
->
dest
,
new
->
dest
);
ERROR
(
"Error restoring %s to %s"
,
orig
->
dest
,
new
->
dest
);
goto
err
;
goto
err
;
}
}
bdev_put
(
orig
);
bdev_put
(
orig
);
...
@@ -437,7 +452,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
...
@@ -437,7 +452,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
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
,
rsync_rootfs_wrapper
,
&
data
,
"rsync_rootfs_wrapper"
);
ret
=
userns_exec_1
(
c0
->
lxc_conf
,
rsync_rootfs_wrapper
,
&
data
,
"rsync_rootfs_wrapper"
);
else
else
ret
=
rsync_rootfs
(
&
data
);
ret
=
rsync_rootfs
(
&
data
);
...
@@ -461,7 +477,7 @@ err:
...
@@ -461,7 +477,7 @@ err:
* @specs: details about the backing store to create, like fstype
* @specs: details about the backing store to create, like fstype
*/
*/
struct
bdev
*
bdev_create
(
const
char
*
dest
,
const
char
*
type
,
const
char
*
cname
,
struct
bdev
*
bdev_create
(
const
char
*
dest
,
const
char
*
type
,
const
char
*
cname
,
struct
bdev_specs
*
specs
)
struct
bdev_specs
*
specs
)
{
{
struct
bdev
*
bdev
;
struct
bdev
*
bdev
;
char
*
best_options
[]
=
{
"btrfs"
,
"zfs"
,
"lvm"
,
"dir"
,
"rbd"
,
NULL
};
char
*
best_options
[]
=
{
"btrfs"
,
"zfs"
,
"lvm"
,
"dir"
,
"rbd"
,
NULL
};
...
@@ -474,10 +490,13 @@ struct bdev *bdev_create(const char *dest, const char *type, const char *cname,
...
@@ -474,10 +490,13 @@ struct bdev *bdev_create(const char *dest, const char *type, const char *cname,
// try for the best backing store type, according to our
// try for the best backing store type, according to our
// opinionated preferences
// opinionated preferences
for
(
i
=
0
;
best_options
[
i
];
i
++
)
{
for
(
i
=
0
;
best_options
[
i
];
i
++
)
{
if
((
bdev
=
do_bdev_create
(
dest
,
best_options
[
i
],
cname
,
specs
)))
if
((
bdev
=
do_bdev_create
(
dest
,
best_options
[
i
],
cname
,
specs
)))
return
bdev
;
return
bdev
;
}
}
return
NULL
;
// 'dir' should never fail, so this shouldn't happen
return
NULL
;
// 'dir' should never fail, so this shouldn't
// happen
}
}
// -B lvm,dir
// -B lvm,dir
...
@@ -485,7 +504,7 @@ struct bdev *bdev_create(const char *dest, const char *type, const char *cname,
...
@@ -485,7 +504,7 @@ struct bdev *bdev_create(const char *dest, const char *type, const char *cname,
char
*
dup
=
alloca
(
strlen
(
type
)
+
1
),
*
saveptr
=
NULL
,
*
token
;
char
*
dup
=
alloca
(
strlen
(
type
)
+
1
),
*
saveptr
=
NULL
,
*
token
;
strcpy
(
dup
,
type
);
strcpy
(
dup
,
type
);
for
(
token
=
strtok_r
(
dup
,
","
,
&
saveptr
);
token
;
for
(
token
=
strtok_r
(
dup
,
","
,
&
saveptr
);
token
;
token
=
strtok_r
(
NULL
,
","
,
&
saveptr
))
{
token
=
strtok_r
(
NULL
,
","
,
&
saveptr
))
{
if
((
bdev
=
do_bdev_create
(
dest
,
token
,
cname
,
specs
)))
if
((
bdev
=
do_bdev_create
(
dest
,
token
,
cname
,
specs
)))
return
bdev
;
return
bdev
;
}
}
...
@@ -518,20 +537,23 @@ int bdev_destroy_wrapper(void *data)
...
@@ -518,20 +537,23 @@ int bdev_destroy_wrapper(void *data)
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
;
}
}
if
(
!
bdev_destroy
(
conf
))
if
(
!
bdev_destroy
(
conf
))
return
-
1
;
return
-
1
;
else
return
0
;
return
0
;
}
}
struct
bdev
*
bdev_init
(
struct
lxc_conf
*
conf
,
const
char
*
src
,
const
char
*
dst
,
struct
bdev
*
bdev_init
(
struct
lxc_conf
*
conf
,
const
char
*
src
,
const
char
*
dst
,
const
char
*
mntopts
)
const
char
*
mntopts
)
{
{
struct
bdev
*
bdev
;
struct
bdev
*
bdev
;
const
struct
bdev_type
*
q
;
const
struct
bdev_type
*
q
;
...
@@ -549,6 +571,7 @@ struct bdev *bdev_init(struct lxc_conf *conf, const char *src, const char *dst,
...
@@ -549,6 +571,7 @@ struct bdev *bdev_init(struct lxc_conf *conf, const char *src, const char *dst,
bdev
=
malloc
(
sizeof
(
struct
bdev
));
bdev
=
malloc
(
sizeof
(
struct
bdev
));
if
(
!
bdev
)
if
(
!
bdev
)
return
NULL
;
return
NULL
;
memset
(
bdev
,
0
,
sizeof
(
struct
bdev
));
memset
(
bdev
,
0
,
sizeof
(
struct
bdev
));
bdev
->
ops
=
q
->
ops
;
bdev
->
ops
=
q
->
ops
;
bdev
->
type
=
q
->
name
;
bdev
->
type
=
q
->
name
;
...
@@ -620,7 +643,7 @@ void detach_block_device(struct lxc_conf *conf)
...
@@ -620,7 +643,7 @@ void detach_block_device(struct lxc_conf *conf)
*/
*/
int
detect_fs
(
struct
bdev
*
bdev
,
char
*
type
,
int
len
)
int
detect_fs
(
struct
bdev
*
bdev
,
char
*
type
,
int
len
)
{
{
int
p
[
2
],
ret
;
int
p
[
2
],
ret
;
size_t
linelen
;
size_t
linelen
;
pid_t
pid
;
pid_t
pid
;
FILE
*
f
;
FILE
*
f
;
...
@@ -637,8 +660,10 @@ int detect_fs(struct bdev *bdev, char *type, int len)
...
@@ -637,8 +660,10 @@ int detect_fs(struct bdev *bdev, char *type, int len)
ret
=
pipe
(
p
);
ret
=
pipe
(
p
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
-
1
;
return
-
1
;
if
((
pid
=
fork
())
<
0
)
if
((
pid
=
fork
())
<
0
)
return
-
1
;
return
-
1
;
if
(
pid
>
0
)
{
if
(
pid
>
0
)
{
int
status
;
int
status
;
close
(
p
[
1
]);
close
(
p
[
1
]);
...
@@ -664,7 +689,7 @@ int detect_fs(struct bdev *bdev, char *type, int len)
...
@@ -664,7 +689,7 @@ int detect_fs(struct bdev *bdev, char *type, int len)
exit
(
1
);
exit
(
1
);
if
(
detect_shared_rootfs
())
{
if
(
detect_shared_rootfs
())
{
if
(
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
))
{
if
(
mount
(
NULL
,
"/"
,
NULL
,
MS_SLAVE
|
MS_REC
,
NULL
))
{
SYSERROR
(
"Failed to make / rslave"
);
SYSERROR
(
"Failed to make / rslave"
);
ERROR
(
"Continuing..."
);
ERROR
(
"Continuing..."
);
}
}
...
@@ -672,9 +697,11 @@ int detect_fs(struct bdev *bdev, char *type, int len)
...
@@ -672,9 +697,11 @@ int detect_fs(struct bdev *bdev, char *type, int len)
ret
=
mount_unknown_fs
(
srcdev
,
bdev
->
dest
,
bdev
->
mntopts
);
ret
=
mount_unknown_fs
(
srcdev
,
bdev
->
dest
,
bdev
->
mntopts
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"failed mounting %s onto %s to detect fstype"
,
srcdev
,
bdev
->
dest
);
ERROR
(
"failed mounting %s onto %s to detect fstype"
,
srcdev
,
bdev
->
dest
);
exit
(
1
);
exit
(
1
);
}
}
// if symlink, get the real dev name
// if symlink, get the real dev name
char
devpath
[
MAXPATHLEN
];
char
devpath
[
MAXPATHLEN
];
char
*
l
=
linkderef
(
srcdev
,
devpath
);
char
*
l
=
linkderef
(
srcdev
,
devpath
);
...
@@ -683,6 +710,7 @@ int detect_fs(struct bdev *bdev, char *type, int len)
...
@@ -683,6 +710,7 @@ int detect_fs(struct bdev *bdev, char *type, int len)
f
=
fopen
(
"/proc/self/mounts"
,
"r"
);
f
=
fopen
(
"/proc/self/mounts"
,
"r"
);
if
(
!
f
)
if
(
!
f
)
exit
(
1
);
exit
(
1
);
while
(
getline
(
&
line
,
&
linelen
,
f
)
!=
-
1
)
{
while
(
getline
(
&
line
,
&
linelen
,
f
)
!=
-
1
)
{
sp1
=
strchr
(
line
,
' '
);
sp1
=
strchr
(
line
,
' '
);
if
(
!
sp1
)
if
(
!
sp1
)
...
@@ -701,8 +729,10 @@ int detect_fs(struct bdev *bdev, char *type, int len)
...
@@ -701,8 +729,10 @@ int detect_fs(struct bdev *bdev, char *type, int len)
sp2
++
;
sp2
++
;
if
(
write
(
p
[
1
],
sp2
,
strlen
(
sp2
))
!=
strlen
(
sp2
))
if
(
write
(
p
[
1
],
sp2
,
strlen
(
sp2
))
!=
strlen
(
sp2
))
exit
(
1
);
exit
(
1
);
exit
(
0
);
exit
(
0
);
}
}
exit
(
1
);
exit
(
1
);
}
}
...
@@ -720,9 +750,10 @@ int do_mkfs(const char *path, const char *fstype)
...
@@ -720,9 +750,10 @@ int do_mkfs(const char *path, const char *fstype)
// If the file is not a block device, we don't want mkfs to ask
// If the file is not a block device, we don't want mkfs to ask
// us about whether to proceed.
// us about whether to proceed.
if
(
null_stdfds
()
<
0
)
if
(
null_stdfds
()
<
0
)
exit
(
1
);
exit
(
EXIT_FAILURE
);
execlp
(
"mkfs"
,
"mkfs"
,
"-t"
,
fstype
,
path
,
(
char
*
)
NULL
);
execlp
(
"mkfs"
,
"mkfs"
,
"-t"
,
fstype
,
path
,
(
char
*
)
NULL
);
exit
(
1
);
exit
(
EXIT_FAILURE
);
}
}
/*
/*
...
@@ -733,20 +764,23 @@ int is_blktype(struct bdev *b)
...
@@ -733,20 +764,23 @@ int is_blktype(struct bdev *b)
{
{
if
(
strcmp
(
b
->
type
,
"lvm"
)
==
0
)
if
(
strcmp
(
b
->
type
,
"lvm"
)
==
0
)
return
1
;
return
1
;
return
0
;
return
0
;
}
}
int
mount_unknown_fs
(
const
char
*
rootfs
,
const
char
*
target
,
int
mount_unknown_fs
(
const
char
*
rootfs
,
const
char
*
target
,
const
char
*
options
)
const
char
*
options
)
{
{
size_t
i
;
int
ret
;
struct
cbarg
{
struct
cbarg
{
const
char
*
rootfs
;
const
char
*
rootfs
;
const
char
*
target
;
const
char
*
target
;
const
char
*
options
;
const
char
*
options
;
}
cbarg
=
{
}
cbarg
=
{
.
rootfs
=
rootfs
,
.
rootfs
=
rootfs
,
.
target
=
target
,
.
target
=
target
,
.
options
=
options
,
.
options
=
options
,
};
};
/*
/*
...
@@ -755,15 +789,11 @@ int mount_unknown_fs(const char *rootfs, const char *target,
...
@@ -755,15 +789,11 @@ int mount_unknown_fs(const char *rootfs, const char *target,
* are auto-loaded and fall back to the supported kernel fs
* are auto-loaded and fall back to the supported kernel fs
*/
*/
char
*
fsfile
[]
=
{
char
*
fsfile
[]
=
{
"/etc/filesystems"
,
"/etc/filesystems"
,
"/proc/filesystems"
,
"/proc/filesystems"
,
};
};
size_t
i
;
for
(
i
=
0
;
i
<
sizeof
(
fsfile
)
/
sizeof
(
fsfile
[
0
]);
i
++
)
{
for
(
i
=
0
;
i
<
sizeof
(
fsfile
)
/
sizeof
(
fsfile
[
0
]);
i
++
)
{
int
ret
;
if
(
access
(
fsfile
[
i
],
F_OK
))
if
(
access
(
fsfile
[
i
],
F_OK
))
continue
;
continue
;
...
@@ -788,34 +818,38 @@ bool rootfs_is_blockdev(struct lxc_conf *conf)
...
@@ -788,34 +818,38 @@ bool rootfs_is_blockdev(struct lxc_conf *conf)
int
ret
;
int
ret
;
if
(
!
conf
->
rootfs
.
path
||
strcmp
(
conf
->
rootfs
.
path
,
"/"
)
==
0
||
if
(
!
conf
->
rootfs
.
path
||
strcmp
(
conf
->
rootfs
.
path
,
"/"
)
==
0
||
strlen
(
conf
->
rootfs
.
path
)
==
0
)
strlen
(
conf
->
rootfs
.
path
)
==
0
)
return
false
;
return
false
;
ret
=
stat
(
conf
->
rootfs
.
path
,
&
st
);
ret
=
stat
(
conf
->
rootfs
.
path
,
&
st
);
if
(
ret
==
0
&&
S_ISBLK
(
st
.
st_mode
))
if
(
ret
==
0
&&
S_ISBLK
(
st
.
st_mode
))
return
true
;
return
true
;
q
=
bdev_query
(
conf
,
conf
->
rootfs
.
path
);
q
=
bdev_query
(
conf
,
conf
->
rootfs
.
path
);
if
(
!
q
)
if
(
!
q
)
return
false
;
return
false
;
if
(
strcmp
(
q
->
name
,
"lvm"
)
==
0
||
if
(
strcmp
(
q
->
name
,
"lvm"
)
==
0
||
strcmp
(
q
->
name
,
"loop"
)
==
0
||
strcmp
(
q
->
name
,
"loop"
)
==
0
||
strcmp
(
q
->
name
,
"nbd"
)
==
0
)
strcmp
(
q
->
name
,
"nbd"
)
==
0
)
return
true
;
return
true
;
return
false
;
return
false
;
}
}
static
struct
bdev
*
do_bdev_create
(
const
char
*
dest
,
const
char
*
type
,
static
struct
bdev
*
do_bdev_create
(
const
char
*
dest
,
const
char
*
type
,
const
char
*
cname
,
struct
bdev_specs
*
specs
)
const
char
*
cname
,
struct
bdev_specs
*
specs
)
{
{
struct
bdev
*
bdev
=
bdev_get
(
type
);
struct
bdev
*
bdev
;
if
(
!
bdev
)
{
bdev
=
bdev_get
(
type
);
if
(
!
bdev
)
return
NULL
;
return
NULL
;
}
if
(
bdev
->
ops
->
create
(
bdev
,
dest
,
cname
,
specs
)
<
0
)
{
if
(
bdev
->
ops
->
create
(
bdev
,
dest
,
cname
,
specs
)
<
0
)
{
bdev_put
(
bdev
);
bdev_put
(
bdev
);
return
NULL
;
return
NULL
;
}
}
return
bdev
;
return
bdev
;
...
@@ -830,14 +864,18 @@ static struct bdev *bdev_get(const char *type)
...
@@ -830,14 +864,18 @@ static struct bdev *bdev_get(const char *type)
if
(
strcmp
(
bdevs
[
i
].
name
,
type
)
==
0
)
if
(
strcmp
(
bdevs
[
i
].
name
,
type
)
==
0
)
break
;
break
;
}
}
if
(
i
==
numbdevs
)
if
(
i
==
numbdevs
)
return
NULL
;
return
NULL
;
bdev
=
malloc
(
sizeof
(
struct
bdev
));
bdev
=
malloc
(
sizeof
(
struct
bdev
));
if
(
!
bdev
)
if
(
!
bdev
)
return
NULL
;
return
NULL
;
memset
(
bdev
,
0
,
sizeof
(
struct
bdev
));
memset
(
bdev
,
0
,
sizeof
(
struct
bdev
));
bdev
->
ops
=
bdevs
[
i
].
ops
;
bdev
->
ops
=
bdevs
[
i
].
ops
;
bdev
->
type
=
bdevs
[
i
].
name
;
bdev
->
type
=
bdevs
[
i
].
name
;
return
bdev
;
return
bdev
;
}
}
...
@@ -885,7 +923,7 @@ static const struct bdev_type *bdev_query(struct lxc_conf *conf,
...
@@ -885,7 +923,7 @@ static const struct bdev_type *bdev_query(struct lxc_conf *conf,
* the callback system, they can be pulled from there eventually, so we
* the callback system, they can be pulled from there eventually, so we
* don't need to pollute utils.c with these low level functions
* don't need to pollute utils.c with these low level functions
*/
*/
static
int
find_fstype_cb
(
char
*
buffer
,
void
*
data
)
static
int
find_fstype_cb
(
char
*
buffer
,
void
*
data
)
{
{
struct
cbarg
{
struct
cbarg
{
const
char
*
rootfs
;
const
char
*
rootfs
;
...
@@ -905,8 +943,8 @@ static int find_fstype_cb(char* buffer, void *data)
...
@@ -905,8 +943,8 @@ static int find_fstype_cb(char* buffer, void *data)
fstype
+=
lxc_char_left_gc
(
fstype
,
strlen
(
fstype
));
fstype
+=
lxc_char_left_gc
(
fstype
,
strlen
(
fstype
));
fstype
[
lxc_char_right_gc
(
fstype
,
strlen
(
fstype
))]
=
'\0'
;
fstype
[
lxc_char_right_gc
(
fstype
,
strlen
(
fstype
))]
=
'\0'
;
DEBUG
(
"trying to mount '%s'->'%s' with fstype '%s'"
,
DEBUG
(
"trying to mount '%s'->'%s' with fstype '%s'"
,
cbarg
->
rootfs
,
cbarg
->
rootfs
,
cbarg
->
target
,
fstype
);
cbarg
->
target
,
fstype
);
if
(
parse_mntopts
(
cbarg
->
options
,
&
mntflags
,
&
mntdata
)
<
0
)
{
if
(
parse_mntopts
(
cbarg
->
options
,
&
mntflags
,
&
mntdata
)
<
0
)
{
free
(
mntdata
);
free
(
mntdata
);
...
@@ -921,8 +959,8 @@ static int find_fstype_cb(char* buffer, void *data)
...
@@ -921,8 +959,8 @@ static int find_fstype_cb(char* buffer, void *data)
free
(
mntdata
);
free
(
mntdata
);
INFO
(
"mounted '%s' on '%s', with fstype '%s'"
,
INFO
(
"mounted '%s' on '%s', with fstype '%s'"
,
cbarg
->
rootfs
,
cbarg
->
rootfs
,
cbarg
->
target
,
fstype
);
cbarg
->
target
,
fstype
);
return
1
;
return
1
;
}
}
...
@@ -935,8 +973,10 @@ static char *linkderef(char *path, char *dest)
...
@@ -935,8 +973,10 @@ static char *linkderef(char *path, char *dest)
ret
=
stat
(
path
,
&
sbuf
);
ret
=
stat
(
path
,
&
sbuf
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
NULL
;
return
NULL
;
if
(
!
S_ISLNK
(
sbuf
.
st_mode
))
if
(
!
S_ISLNK
(
sbuf
.
st_mode
))
return
path
;
return
path
;
ret
=
readlink
(
path
,
dest
,
MAXPATHLEN
);
ret
=
readlink
(
path
,
dest
,
MAXPATHLEN
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"error reading link %s"
,
path
);
SYSERROR
(
"error reading link %s"
,
path
);
...
@@ -946,6 +986,7 @@ static char *linkderef(char *path, char *dest)
...
@@ -946,6 +986,7 @@ static char *linkderef(char *path, char *dest)
return
NULL
;
return
NULL
;
}
}
dest
[
ret
]
=
'\0'
;
dest
[
ret
]
=
'\0'
;
return
dest
;
return
dest
;
}
}
...
@@ -953,43 +994,46 @@ static char *linkderef(char *path, char *dest)
...
@@ -953,43 +994,46 @@ static char *linkderef(char *path, char *dest)
* is an unprivileged user allowed to make this kind of snapshot
* is an unprivileged user allowed to make this kind of snapshot
*/
*/
static
bool
unpriv_snap_allowed
(
struct
bdev
*
b
,
const
char
*
t
,
bool
snap
,
static
bool
unpriv_snap_allowed
(
struct
bdev
*
b
,
const
char
*
t
,
bool
snap
,
bool
maybesnap
)
bool
maybesnap
)
{
{
if
(
!
t
)
{
if
(
!
t
)
{
// new type will be same as original
// new type will be same as original
// (unless snap && b->type == dir, in which case it will be
// (unless snap && b->type == dir, in which case it will be
// 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
,
"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
)
return
true
;
return
true
;
return
false
;
return
false
;
}
}
// unprivileged users can copy and snapshot dir, overlayfs,
// unprivileged users can copy and snapshot dir, overlayfs,
// 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
,
"overlayfs"
)
==
0
||
strcmp
(
t
,
"overlayfs"
)
==
0
||
strcmp
(
t
,
"btrfs"
)
==
0
||
strcmp
(
t
,
"btrfs"
)
==
0
||
strcmp
(
t
,
"loop"
)
==
0
)
strcmp
(
t
,
"loop"
)
==
0
)
return
true
;
return
true
;
return
false
;
return
false
;
}
}
bool
is_valid_bdev_type
(
const
char
*
type
)
bool
is_valid_bdev_type
(
const
char
*
type
)
{
{
if
(
strcmp
(
type
,
"dir"
)
==
0
||
if
(
strcmp
(
type
,
"dir"
)
==
0
||
strcmp
(
type
,
"btrfs"
)
==
0
||
strcmp
(
type
,
"btrfs"
)
==
0
||
strcmp
(
type
,
"aufs"
)
==
0
||
strcmp
(
type
,
"aufs"
)
==
0
||
strcmp
(
type
,
"loop"
)
==
0
||
strcmp
(
type
,
"loop"
)
==
0
||
strcmp
(
type
,
"lvm"
)
==
0
||
strcmp
(
type
,
"lvm"
)
==
0
||
strcmp
(
type
,
"nbd"
)
==
0
||
strcmp
(
type
,
"nbd"
)
==
0
||
strcmp
(
type
,
"overlayfs"
)
==
0
||
strcmp
(
type
,
"overlayfs"
)
==
0
||
strcmp
(
type
,
"rbd"
)
==
0
||
strcmp
(
type
,
"rbd"
)
==
0
||
strcmp
(
type
,
"zfs"
)
==
0
)
strcmp
(
type
,
"zfs"
)
==
0
)
return
true
;
return
true
;
return
false
;
return
false
;
}
}
src/lxc/bdev/bdev.h
View file @
493de765
...
@@ -23,17 +23,13 @@
...
@@ -23,17 +23,13 @@
#ifndef __LXC_BDEV_H
#ifndef __LXC_BDEV_H
#define __LXC_BDEV_H
#define __LXC_BDEV_H
/* blockdev operations for:
* aufs, dir, raw, btrfs, overlayfs, aufs, lvm, loop, zfs, nbd (qcow2, raw, vdi, qed)
*/
#include
<lxc/lxccontainer.h>
#include
"config.h"
#include <stdint.h>
#include <stdint.h>
#include <sys/mount.h>
#include <sys/mount.h>
#include
"config.h"
#include
<lxc/lxccontainer.h>
/* define constants if the kernel/glibc headers don't define them */
#ifndef MS_DIRSYNC
#ifndef MS_DIRSYNC
#define MS_DIRSYNC 128
#define MS_DIRSYNC 128
#endif
#endif
...
@@ -71,20 +67,21 @@ struct bdev_ops {
...
@@ -71,20 +67,21 @@ struct bdev_ops {
int
(
*
umount
)(
struct
bdev
*
bdev
);
int
(
*
umount
)(
struct
bdev
*
bdev
);
int
(
*
destroy
)(
struct
bdev
*
bdev
);
int
(
*
destroy
)(
struct
bdev
*
bdev
);
int
(
*
create
)(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
int
(
*
create
)(
struct
bdev
*
bdev
,
const
char
*
dest
,
const
char
*
n
,
struct
bdev_specs
*
specs
);
struct
bdev_specs
*
specs
);
/* given original mount, rename the paths for cloned container */
/* given original mount, rename the paths for cloned container */
int
(
*
clone_paths
)(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
oldname
,
int
(
*
clone_paths
)(
struct
bdev
*
orig
,
struct
bdev
*
new
,
const
char
*
cname
,
const
char
*
oldpath
,
const
char
*
lxcpath
,
const
char
*
oldname
,
const
char
*
cname
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
);
const
char
*
oldpath
,
const
char
*
lxcpath
,
int
snap
,
uint64_t
newsize
,
struct
lxc_conf
*
conf
);
bool
can_snapshot
;
bool
can_snapshot
;
bool
can_backup
;
bool
can_backup
;
};
};
/*
/*
* When lxc-start
(conf.c) is mounting a rootfs, then src will be the
* When lxc-start
is mounting a rootfs, then src will be the "lxc.rootfs" value,
*
'lxc.rootfs' value, dest will be mount dir (i.e. $libdir/lxc) When clone
*
dest will be mount dir (i.e. $libdir/lxc) When clone or create is doing so,
*
or create is doing so, then dest will be $lxcpath/$lxcname/rootfs, since
*
then dest will be $lxcpath/$lxcname/rootfs, since we may need to rsync from
*
we may need to rsync from
one to the other.
* one to the other.
* data is so far unused.
* data is so far unused.
*/
*/
struct
bdev
{
struct
bdev
{
...
@@ -93,10 +90,10 @@ struct bdev {
...
@@ -93,10 +90,10 @@ struct bdev {
char
*
src
;
char
*
src
;
char
*
dest
;
char
*
dest
;
char
*
mntopts
;
char
*
mntopts
;
/
/ turn the following into a union if need be
/
* Turn the following into a union if need be. */
/
/ lofd is the open fd for the mounted loopback file
/
* lofd is the open fd for the mounted loopback file. */
int
lofd
;
int
lofd
;
/
/ index for the connected nbd device
/
* index for the connected nbd device. */
int
nbd_idx
;
int
nbd_idx
;
};
};
...
@@ -104,27 +101,27 @@ bool bdev_is_dir(struct lxc_conf *conf, const char *path);
...
@@ -104,27 +101,27 @@ bool bdev_is_dir(struct lxc_conf *conf, const char *path);
bool
bdev_can_backup
(
struct
lxc_conf
*
conf
);
bool
bdev_can_backup
(
struct
lxc_conf
*
conf
);
/*
/*
* Instantiate a bdev object.
The src is used to determine which blockdev
* Instantiate a bdev object.
The src is used to determine which blockdev type
* t
ype this should be. The dst and data are optional, and will be used
* t
his should be. The dst and data are optional, and will be used in case of
*
in case of
mount/umount.
* mount/umount.
*
*
* Optionally, src can be 'dir:/var/lib/lxc/c1' or 'lvm:/dev/lxc/c1'. For
* Optionally, src can be 'dir:/var/lib/lxc/c1' or 'lvm:/dev/lxc/c1'. For
* other backing stores, this will allow additional options.
In particular,
* other backing stores, this will allow additional options. In particular,
* "overlayfs:/var/lib/lxc/canonical/rootfs:/var/lib/lxc/c1/delta" will mean
* "overlayfs:/var/lib/lxc/canonical/rootfs:/var/lib/lxc/c1/delta" will mean
* use /var/lib/lxc/canonical/rootfs as lower dir, and /var/lib/lxc/c1/delta
* use /var/lib/lxc/canonical/rootfs as lower dir, and /var/lib/lxc/c1/delta
* as the upper, writeable layer.
* as the upper, writeable layer.
*/
*/
struct
bdev
*
bdev_init
(
struct
lxc_conf
*
conf
,
const
char
*
src
,
const
char
*
dst
,
struct
bdev
*
bdev_init
(
struct
lxc_conf
*
conf
,
const
char
*
src
,
const
char
*
dst
,
const
char
*
data
);
const
char
*
data
);
struct
bdev
*
bdev_copy
(
struct
lxc_container
*
c0
,
const
char
*
cname
,
struct
bdev
*
bdev_copy
(
struct
lxc_container
*
c0
,
const
char
*
cname
,
const
char
*
lxcpath
,
const
char
*
bdevtype
,
const
char
*
lxcpath
,
const
char
*
bdevtype
,
int
flags
,
int
flags
,
const
char
*
bdevdata
,
uint64_t
newsize
,
const
char
*
bdevdata
,
uint64_t
newsize
,
int
*
needs_rdep
);
int
*
needs_rdep
);
struct
bdev
*
bdev_create
(
const
char
*
dest
,
const
char
*
type
,
const
char
*
cname
,
struct
bdev
*
bdev_create
(
const
char
*
dest
,
const
char
*
type
,
struct
bdev_specs
*
specs
);
const
char
*
cname
,
struct
bdev_specs
*
specs
);
void
bdev_put
(
struct
bdev
*
bdev
);
void
bdev_put
(
struct
bdev
*
bdev
);
bool
bdev_destroy
(
struct
lxc_conf
*
conf
);
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
);
...
@@ -139,6 +136,7 @@ int is_blktype(struct bdev *b);
...
@@ -139,6 +136,7 @@ int is_blktype(struct bdev *b);
int
mount_unknown_fs
(
const
char
*
rootfs
,
const
char
*
target
,
int
mount_unknown_fs
(
const
char
*
rootfs
,
const
char
*
target
,
const
char
*
options
);
const
char
*
options
);
bool
rootfs_is_blockdev
(
struct
lxc_conf
*
conf
);
bool
rootfs_is_blockdev
(
struct
lxc_conf
*
conf
);
/*
/*
* these are really for qemu-nbd support, as container shutdown
* these are really for qemu-nbd support, as container shutdown
* must explicitly request device detach.
* must explicitly request device detach.
...
...
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