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
2e2cbfd2
Commit
2e2cbfd2
authored
Apr 22, 2017
by
Stéphane Graber
Committed by
GitHub
Apr 22, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1520 from brauner/2017-04-22/improve_loop
utils: use loop device helpers from LXD
parents
170a3771
c6868a1f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
160 additions
and
190 deletions
+160
-190
lxcloop.c
src/lxc/bdev/lxcloop.c
+9
-100
conf.c
src/lxc/conf.c
+11
-89
utils.c
src/lxc/utils.c
+123
-0
utils.h
src/lxc/utils.h
+17
-1
No files found.
src/lxc/bdev/lxcloop.c
View file @
2e2cbfd2
...
...
@@ -35,19 +35,9 @@
#include "lxcloop.h"
#include "utils.h"
#ifndef LO_FLAGS_AUTOCLEAR
#define LO_FLAGS_AUTOCLEAR 4
#endif
#ifndef LOOP_CTL_GET_FREE
#define LOOP_CTL_GET_FREE 0x4C82
#endif
lxc_log_define
(
lxcloop
,
lxc
);
static
int
do_loop_create
(
const
char
*
path
,
uint64_t
size
,
const
char
*
fstype
);
static
int
find_free_loopdev_no_control
(
int
*
retfd
,
char
*
namep
);
static
int
find_free_loopdev
(
int
*
retfd
,
char
*
namep
);
/*
* No idea what the original blockdev will be called, but the copy will be
...
...
@@ -174,47 +164,26 @@ int loop_detect(const char *path)
int
loop_mount
(
struct
bdev
*
bdev
)
{
int
lfd
,
ffd
=
-
1
,
ret
=
-
1
;
struct
loop_info64
lo
;
char
loname
[
100
];
int
ret
,
loopfd
;
char
loname
[
MAXPATHLEN
];
if
(
strcmp
(
bdev
->
type
,
"loop"
))
return
-
22
;
if
(
!
bdev
->
src
||
!
bdev
->
dest
)
return
-
22
;
if
(
find_free_loopdev
(
&
lfd
,
loname
)
<
0
)
return
-
22
;
ffd
=
open
(
bdev
->
src
+
5
,
O_RDWR
);
if
(
ffd
<
0
)
{
SYSERROR
(
"Error opening backing file %s"
,
bdev
->
src
);
goto
out
;
}
if
(
ioctl
(
lfd
,
LOOP_SET_FD
,
ffd
)
<
0
)
{
SYSERROR
(
"Error attaching backing file to loop dev"
);
goto
out
;
}
memset
(
&
lo
,
0
,
sizeof
(
lo
));
lo
.
lo_flags
=
LO_FLAGS_AUTOCLEAR
;
if
(
ioctl
(
lfd
,
LOOP_SET_STATUS64
,
&
lo
)
<
0
)
{
SYSERROR
(
"Error setting autoclear on loop dev"
);
goto
out
;
}
loopfd
=
lxc_prepare_loop_dev
(
bdev
->
src
+
5
,
loname
,
LO_FLAGS_AUTOCLEAR
);
if
(
loopfd
<
0
)
return
-
1
;
DEBUG
(
"prepared loop device
\"
%s
\"
"
,
loname
);
ret
=
mount_unknown_fs
(
loname
,
bdev
->
dest
,
bdev
->
mntopts
);
if
(
ret
<
0
)
ERROR
(
"
Error mounting %s"
,
bdev
->
src
);
ERROR
(
"
failed to mount rootfs
\"
%s
\"
onto
\"
%s
\"
via loop device
\"
%s
\"
"
,
bdev
->
src
,
bdev
->
dest
,
loname
);
else
bdev
->
lofd
=
lfd
;
bdev
->
lofd
=
loopfd
;
DEBUG
(
"mounted rootfs
\"
%s
\"
onto
\"
%s
\"
via loop device
\"
%s
\"
"
,
bdev
->
src
,
bdev
->
dest
,
loname
);
out:
if
(
ffd
>
-
1
)
close
(
ffd
);
if
(
ret
<
0
)
{
close
(
lfd
);
bdev
->
lofd
=
-
1
;
}
return
ret
;
}
...
...
@@ -266,63 +235,3 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype)
return
0
;
}
static
int
find_free_loopdev_no_control
(
int
*
retfd
,
char
*
namep
)
{
struct
dirent
*
direntp
;
struct
loop_info64
lo
;
DIR
*
dir
;
int
fd
=
-
1
;
dir
=
opendir
(
"/dev"
);
if
(
!
dir
)
{
SYSERROR
(
"Error opening /dev"
);
return
-
1
;
}
while
((
direntp
=
readdir
(
dir
)))
{
if
(
!
direntp
)
break
;
if
(
strncmp
(
direntp
->
d_name
,
"loop"
,
4
)
!=
0
)
continue
;
fd
=
openat
(
dirfd
(
dir
),
direntp
->
d_name
,
O_RDWR
);
if
(
fd
<
0
)
continue
;
if
(
ioctl
(
fd
,
LOOP_GET_STATUS64
,
&
lo
)
==
0
||
errno
!=
ENXIO
)
{
close
(
fd
);
fd
=
-
1
;
continue
;
}
// We can use this fd
snprintf
(
namep
,
100
,
"/dev/%s"
,
direntp
->
d_name
);
break
;
}
closedir
(
dir
);
if
(
fd
==
-
1
)
{
ERROR
(
"No loop device found"
);
return
-
1
;
}
*
retfd
=
fd
;
return
0
;
}
static
int
find_free_loopdev
(
int
*
retfd
,
char
*
namep
)
{
int
rc
,
fd
=
-
1
;
int
ctl
=
open
(
"/dev/loop-control"
,
O_RDWR
);
if
(
ctl
<
0
)
return
find_free_loopdev_no_control
(
retfd
,
namep
);
rc
=
ioctl
(
ctl
,
LOOP_CTL_GET_FREE
);
if
(
rc
>=
0
)
{
snprintf
(
namep
,
100
,
"/dev/loop%d"
,
rc
);
fd
=
open
(
namep
,
O_RDWR
);
}
close
(
ctl
);
if
(
fd
==
-
1
)
{
ERROR
(
"No loop device found"
);
return
-
1
;
}
*
retfd
=
fd
;
return
0
;
}
src/lxc/conf.c
View file @
2e2cbfd2
...
...
@@ -573,7 +573,7 @@ static int run_script(const char *name, const char *section, const char *script,
}
static
int
mount_rootfs_dir
(
const
char
*
rootfs
,
const
char
*
target
,
const
char
*
options
)
const
char
*
options
)
{
unsigned
long
mntflags
;
char
*
mntdata
;
...
...
@@ -590,99 +590,21 @@ static int mount_rootfs_dir(const char *rootfs, const char *target,
return
ret
;
}
static
int
setup_lodev
(
const
char
*
rootfs
,
int
fd
,
struct
loop_info64
*
loinfo
)
static
int
lxc_mount_rootfs_file
(
const
char
*
rootfs
,
const
char
*
target
,
const
char
*
options
)
{
int
rfd
;
int
ret
=
-
1
;
rfd
=
open
(
rootfs
,
O_RDWR
);
if
(
rfd
<
0
)
{
SYSERROR
(
"failed to open '%s'"
,
rootfs
);
return
-
1
;
}
memset
(
loinfo
,
0
,
sizeof
(
*
loinfo
));
loinfo
->
lo_flags
=
LO_FLAGS_AUTOCLEAR
;
if
(
ioctl
(
fd
,
LOOP_SET_FD
,
rfd
))
{
SYSERROR
(
"failed to LOOP_SET_FD"
);
goto
out
;
}
if
(
ioctl
(
fd
,
LOOP_SET_STATUS64
,
loinfo
))
{
SYSERROR
(
"failed to LOOP_SET_STATUS64"
);
goto
out
;
}
ret
=
0
;
out:
close
(
rfd
);
return
ret
;
}
static
int
mount_rootfs_file
(
const
char
*
rootfs
,
const
char
*
target
,
const
char
*
options
)
{
struct
dirent
*
direntp
;
struct
loop_info64
loinfo
;
int
ret
=
-
1
,
fd
=
-
1
,
rc
;
DIR
*
dir
;
int
ret
,
loopfd
;
char
path
[
MAXPATHLEN
];
dir
=
opendir
(
"/dev"
);
if
(
!
dir
)
{
SYSERROR
(
"failed to open '/dev'"
);
loopfd
=
lxc_prepare_loop_dev
(
rootfs
,
path
,
LO_FLAGS_AUTOCLEAR
);
if
(
loopfd
<
0
)
return
-
1
;
}
while
((
direntp
=
readdir
(
dir
)))
{
if
(
!
direntp
)
break
;
DEBUG
(
"prepared loop device
\"
%s
\"
"
,
path
);
if
(
!
strcmp
(
direntp
->
d_name
,
"."
))
continue
;
if
(
!
strcmp
(
direntp
->
d_name
,
".."
))
continue
;
if
(
strncmp
(
direntp
->
d_name
,
"loop"
,
4
))
continue
;
rc
=
snprintf
(
path
,
MAXPATHLEN
,
"/dev/%s"
,
direntp
->
d_name
);
if
(
rc
<
0
||
rc
>=
MAXPATHLEN
)
continue
;
fd
=
open
(
path
,
O_RDWR
);
if
(
fd
<
0
)
continue
;
if
(
ioctl
(
fd
,
LOOP_GET_STATUS64
,
&
loinfo
)
==
0
)
{
close
(
fd
);
continue
;
}
if
(
errno
!=
ENXIO
)
{
WARN
(
"unexpected error for ioctl on '%s': %m"
,
direntp
->
d_name
);
close
(
fd
);
continue
;
}
DEBUG
(
"found '%s' free lodev"
,
path
);
ret
=
setup_lodev
(
rootfs
,
fd
,
&
loinfo
);
if
(
!
ret
)
ret
=
mount_unknown_fs
(
path
,
target
,
options
);
close
(
fd
);
break
;
}
ret
=
mount_unknown_fs
(
path
,
target
,
options
);
close
(
loopfd
);
if
(
closedir
(
dir
))
WARN
(
"failed to close directory"
);
DEBUG
(
"mounted rootfs
\"
%s
\"
on loop device
\"
%s
\"
via loop device
\"
%s
\"
"
,
rootfs
,
target
,
path
);
return
ret
;
}
...
...
@@ -915,7 +837,7 @@ static int mount_rootfs(const char *rootfs, const char *target, const char *opti
}
rtfs_type
[]
=
{
{
S_IFDIR
,
mount_rootfs_dir
},
{
S_IFBLK
,
mount_rootfs_block
},
{
S_IFREG
,
mount_rootfs_file
},
{
S_IFREG
,
lxc_
mount_rootfs_file
},
};
if
(
!
realpath
(
rootfs
,
absrootfs
))
{
...
...
src/lxc/utils.c
View file @
2e2cbfd2
...
...
@@ -2070,3 +2070,126 @@ int lxc_setgroups(int size, gid_t list[])
return
0
;
}
static
int
lxc_get_unused_loop_dev_legacy
(
char
*
loop_name
)
{
struct
dirent
*
dp
;
struct
loop_info64
lo64
;
DIR
*
dir
;
int
dfd
=
-
1
,
fd
=
-
1
,
ret
=
-
1
;
dir
=
opendir
(
"/dev"
);
if
(
!
dir
)
return
-
1
;
while
((
dp
=
readdir
(
dir
)))
{
if
(
!
dp
)
break
;
if
(
strncmp
(
dp
->
d_name
,
"loop"
,
4
)
!=
0
)
continue
;
dfd
=
dirfd
(
dir
);
if
(
dfd
<
0
)
continue
;
fd
=
openat
(
dfd
,
dp
->
d_name
,
O_RDWR
);
if
(
fd
<
0
)
continue
;
ret
=
ioctl
(
fd
,
LOOP_GET_STATUS64
,
&
lo64
);
if
(
ret
<
0
)
{
if
(
ioctl
(
fd
,
LOOP_GET_STATUS64
,
&
lo64
)
==
0
||
errno
!=
ENXIO
)
{
close
(
fd
);
fd
=
-
1
;
continue
;
}
}
ret
=
snprintf
(
loop_name
,
LO_NAME_SIZE
,
"/dev/%s"
,
dp
->
d_name
);
if
(
ret
<
0
||
ret
>=
LO_NAME_SIZE
)
{
close
(
fd
);
fd
=
-
1
;
continue
;
}
break
;
}
closedir
(
dir
);
if
(
fd
<
0
)
return
-
1
;
return
fd
;
}
static
int
lxc_get_unused_loop_dev
(
char
*
name_loop
)
{
int
loop_nr
,
ret
;
int
fd_ctl
=
-
1
,
fd_tmp
=
-
1
;
fd_ctl
=
open
(
"/dev/loop-control"
,
O_RDWR
|
O_CLOEXEC
);
if
(
fd_ctl
<
0
)
return
-
ENODEV
;
loop_nr
=
ioctl
(
fd_ctl
,
LOOP_CTL_GET_FREE
);
if
(
loop_nr
<
0
)
goto
on_error
;
ret
=
snprintf
(
name_loop
,
LO_NAME_SIZE
,
"/dev/loop%d"
,
loop_nr
);
if
(
ret
<
0
||
ret
>=
LO_NAME_SIZE
)
goto
on_error
;
fd_tmp
=
open
(
name_loop
,
O_RDWR
|
O_CLOEXEC
);
if
(
fd_tmp
<
0
)
goto
on_error
;
on_error
:
close
(
fd_ctl
);
return
fd_tmp
;
}
int
lxc_prepare_loop_dev
(
const
char
*
source
,
char
*
loop_dev
,
int
flags
)
{
int
ret
;
struct
loop_info64
lo64
;
int
fd_img
=
-
1
,
fret
=
-
1
,
fd_loop
=
-
1
;
fd_loop
=
lxc_get_unused_loop_dev
(
loop_dev
);
if
(
fd_loop
<
0
)
{
if
(
fd_loop
==
-
ENODEV
)
fd_loop
=
lxc_get_unused_loop_dev_legacy
(
loop_dev
);
else
goto
on_error
;
}
fd_img
=
open
(
source
,
O_RDWR
|
O_CLOEXEC
);
if
(
fd_img
<
0
)
goto
on_error
;
ret
=
ioctl
(
fd_loop
,
LOOP_SET_FD
,
fd_img
);
if
(
ret
<
0
)
goto
on_error
;
memset
(
&
lo64
,
0
,
sizeof
(
lo64
));
lo64
.
lo_flags
=
flags
;
ret
=
ioctl
(
fd_loop
,
LOOP_SET_STATUS64
,
&
lo64
);
if
(
ret
<
0
)
goto
on_error
;
fret
=
0
;
on_error
:
if
(
fd_img
>=
0
)
close
(
fd_img
);
if
(
fret
<
0
&&
fd_loop
>=
0
)
{
close
(
fd_loop
);
fd_loop
=
-
1
;
}
return
fd_loop
;
}
src/lxc/utils.h
View file @
2e2cbfd2
...
...
@@ -23,15 +23,19 @@
#ifndef __LXC_UTILS_H
#define __LXC_UTILS_H
/* Properly support loop devices on 32bit systems. */
#define _FILE_OFFSET_BITS 64
#include "config.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <linux/loop.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include "initutils.h"
...
...
@@ -164,6 +168,15 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
}
#endif
/* loop devices */
#ifndef LO_FLAGS_AUTOCLEAR
#define LO_FLAGS_AUTOCLEAR 4
#endif
#ifndef LOOP_CTL_GET_FREE
#define LOOP_CTL_GET_FREE 0x4C82
#endif
/* Struct to carry child pid from lxc_popen() to lxc_pclose().
* Not an opaque struct to allow direct access to the underlying FILE *
* (i.e., struct lxc_popen_FILE *file; fgets(buf, sizeof(buf), file->f))
...
...
@@ -332,4 +345,7 @@ int lxc_safe_long(const char *numstr, long int *converted);
int
lxc_switch_uid_gid
(
uid_t
uid
,
gid_t
gid
);
int
lxc_setgroups
(
int
size
,
gid_t
list
[]);
/* Find an unused loop device and associate it with source. */
int
lxc_prepare_loop_dev
(
const
char
*
source
,
char
*
loop_dev
,
int
flags
);
#endif
/* __LXC_UTILS_H */
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