Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
steam
systemd
Commits
8260358d
Commit
8260358d
authored
Sep 25, 2010
by
Lennart Poettering
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
readahead: parse command line arguments
parent
437dca8b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
184 additions
and
17 deletions
+184
-17
src/readahead-collect.c
src/readahead-collect.c
+105
-11
src/readahead-common.c
src/readahead-common.c
+2
-2
src/readahead-common.h
src/readahead-common.h
+1
-2
src/readahead-replay.c
src/readahead-replay.c
+76
-2
No files found.
src/readahead-collect.c
View file @
8260358d
...
...
@@ -40,6 +40,7 @@
#include <linux/fiemap.h>
#include <sys/ioctl.h>
#include <sys/vfs.h>
#include <getopt.h>
#include "missing.h"
#include "util.h"
...
...
@@ -48,20 +49,20 @@
#include "ioprio.h"
#include "readahead-common.h"
#define MINCORE_VEC_SIZE (READAHEAD_FILE_SIZE_MAX/PAGE_SIZE)
#define TIMEOUT_USEC (2*USEC_PER_MINUTE)
/* fixme:
*
* - detect ssd on btrfs/lvm...
* - read ahead directories
* - sd_readahead_cancel
* - gzip?
* - remount rw
* - are filenames from anotify normalized regards /../ and // and /./?
* - remount rw?
* - does ioprio_set work with fadvise()?
*/
static
unsigned
arg_files_max
=
16
*
1024
;
static
off_t
arg_file_size_max
=
READAHEAD_FILE_SIZE_MAX
;
static
usec_t
arg_timeout
=
2
*
USEC_PER_MINUTE
;
static
int
btrfs_defrag
(
int
fd
)
{
struct
btrfs_ioctl_vol_args
data
;
...
...
@@ -74,7 +75,7 @@ static int btrfs_defrag(int fd) {
static
int
pack_file
(
FILE
*
pack
,
const
char
*
fn
,
bool
on_btrfs
)
{
struct
stat
st
;
void
*
start
=
MAP_FAILED
;
uint8_t
vec
[
MINCORE_VEC_SIZE
]
;
uint8_t
*
vec
;
uint32_t
b
,
c
;
size_t
l
,
pages
;
bool
mapped
;
...
...
@@ -89,7 +90,7 @@ static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
goto
finish
;
}
if
((
k
=
file_verify
(
fd
,
fn
,
&
st
))
<=
0
)
{
if
((
k
=
file_verify
(
fd
,
fn
,
arg_file_size_max
,
&
st
))
<=
0
)
{
r
=
k
;
goto
finish
;
}
...
...
@@ -104,6 +105,9 @@ static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
goto
finish
;
}
pages
=
l
/
PAGE_SIZE
;
vec
=
alloca
(
pages
);
if
(
mincore
(
start
,
l
,
vec
)
<
0
)
{
log_warning
(
"mincore(%s) failed: %m"
,
fn
);
r
=
-
errno
;
...
...
@@ -113,7 +117,6 @@ static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
fputs
(
fn
,
pack
);
fputc
(
'\n'
,
pack
);
pages
=
l
/
PAGE_SIZE
;
mapped
=
false
;
for
(
c
=
0
;
c
<
pages
;
c
++
)
{
bool
new_mapped
=
!!
(
vec
[
c
]
&
1
);
...
...
@@ -248,7 +251,7 @@ static int collect(const char *root) {
goto
finish
;
}
not_after
=
now
(
CLOCK_MONOTONIC
)
+
TIMEOUT_USEC
;
not_after
=
now
(
CLOCK_MONOTONIC
)
+
arg_timeout
;
my_pid
=
getpid
();
...
...
@@ -274,7 +277,7 @@ static int collect(const char *root) {
usec_t
t
;
int
h
;
if
(
hashmap_size
(
files
)
>
READAHEAD_FILES_MAX
)
{
if
(
hashmap_size
(
files
)
>
arg_files_max
)
{
log_debug
(
"Reached maximum number of read ahead files, ending collection."
);
break
;
}
...
...
@@ -464,18 +467,109 @@ finish:
return
r
;
}
static
int
help
(
void
)
{
printf
(
"%s [OPTIONS...] [DIRECTORY]
\n\n
"
"Collect read-ahead data on early boot.
\n\n
"
" -h --help Show this help
\n
"
" --max-files=INT Maximum number of files to read ahead
\n
"
" --max-file-size=BYTES Maximum size of files to read ahead
\n
"
" --timeout=USEC Maximum time to spend collecting data
\n
"
,
program_invocation_short_name
);
return
0
;
}
static
int
parse_argv
(
int
argc
,
char
*
argv
[])
{
enum
{
ARG_FILES_MAX
=
0x100
,
ARG_FILE_SIZE_MAX
,
ARG_TIMEOUT
};
static
const
struct
option
options
[]
=
{
{
"help"
,
no_argument
,
NULL
,
'h'
},
{
"files-max"
,
required_argument
,
NULL
,
ARG_FILES_MAX
},
{
"file-size-max"
,
required_argument
,
NULL
,
ARG_FILE_SIZE_MAX
},
{
"timeout"
,
required_argument
,
NULL
,
ARG_TIMEOUT
},
{
NULL
,
0
,
NULL
,
0
}
};
int
c
;
assert
(
argc
>=
0
);
assert
(
argv
);
while
((
c
=
getopt_long
(
argc
,
argv
,
"h"
,
options
,
NULL
))
>=
0
)
{
switch
(
c
)
{
case
'h'
:
help
();
return
0
;
case
ARG_FILES_MAX
:
if
(
safe_atou
(
optarg
,
&
arg_files_max
)
<
0
||
arg_files_max
<=
0
)
{
log_error
(
"Failed to parse maximum number of files %s."
,
optarg
);
return
-
EINVAL
;
}
break
;
case
ARG_FILE_SIZE_MAX
:
{
unsigned
long
long
ull
;
if
(
safe_atollu
(
optarg
,
&
ull
)
<
0
||
ull
<=
0
)
{
log_error
(
"Failed to parse maximum file size %s."
,
optarg
);
return
-
EINVAL
;
}
arg_file_size_max
=
(
off_t
)
ull
;
break
;
}
case
ARG_TIMEOUT
:
if
(
parse_usec
(
optarg
,
&
arg_timeout
)
<
0
||
arg_timeout
<=
0
)
{
log_error
(
"Failed to parse timeout %s."
,
optarg
);
return
-
EINVAL
;
}
break
;
case
'?'
:
return
-
EINVAL
;
default:
log_error
(
"Unknown option code %c"
,
c
);
return
-
EINVAL
;
}
}
if
(
optind
!=
argc
&&
optind
!=
argc
-
1
)
{
help
();
return
-
EINVAL
;
}
return
1
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
r
;
log_set_target
(
LOG_TARGET_SYSLOG_OR_KMSG
);
log_parse_environment
();
log_open
();
if
((
r
=
parse_argv
(
argc
,
argv
))
<=
0
)
return
r
<
0
?
EXIT_FAILURE
:
EXIT_SUCCESS
;
if
(
!
enough_ram
())
{
log_info
(
"Disabling readahead collector due to low memory."
);
return
0
;
}
if
(
collect
(
argc
>=
2
?
argv
[
1
]
:
"/"
)
<
0
)
if
(
collect
(
optind
<
argc
?
argv
[
optind
]
:
"/"
)
<
0
)
return
1
;
return
0
;
...
...
src/readahead-common.c
View file @
8260358d
...
...
@@ -29,7 +29,7 @@
#include "readahead-common.h"
#include "util.h"
int
file_verify
(
int
fd
,
const
char
*
fn
,
struct
stat
*
st
)
{
int
file_verify
(
int
fd
,
const
char
*
fn
,
off_t
file_size_max
,
struct
stat
*
st
)
{
assert
(
fd
>=
0
);
assert
(
fn
);
assert
(
st
);
...
...
@@ -44,7 +44,7 @@ int file_verify(int fd, const char *fn, struct stat *st) {
return
0
;
}
if
(
st
->
st_size
<=
0
||
st
->
st_size
>
READAHEAD_FILE_SIZE_MAX
)
{
if
(
st
->
st_size
<=
0
||
st
->
st_size
>
file_size_max
)
{
log_debug
(
"Not preloading file %s with size out of bounds %zi"
,
fn
,
st
->
st_size
);
return
0
;
}
...
...
src/readahead-common.h
View file @
8260358d
...
...
@@ -25,9 +25,8 @@
#include <sys/stat.h>
#define READAHEAD_FILE_SIZE_MAX (128*1024*1024)
#define READAHEAD_FILES_MAX (16*1024)
int
file_verify
(
int
fd
,
const
char
*
fn
,
struct
stat
*
st
);
int
file_verify
(
int
fd
,
const
char
*
fn
,
off_t
file_size_max
,
struct
stat
*
st
);
int
fs_on_ssd
(
const
char
*
p
);
...
...
src/readahead-replay.c
View file @
8260358d
...
...
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
#include "missing.h"
#include "util.h"
...
...
@@ -40,6 +41,8 @@
#include "ioprio.h"
#include "readahead-common.h"
static
off_t
arg_file_size_max
=
READAHEAD_FILE_SIZE_MAX
;
static
int
unpack_file
(
FILE
*
pack
)
{
char
fn
[
PATH_MAX
];
int
r
=
0
,
fd
=
-
1
;
...
...
@@ -56,7 +59,7 @@ static int unpack_file(FILE *pack) {
if
((
fd
=
open
(
fn
,
O_RDONLY
|
O_CLOEXEC
|
O_NOATIME
|
O_NOCTTY
|
O_NOFOLLOW
))
<
0
)
log_warning
(
"open(%s) failed: %m"
,
fn
);
else
if
(
file_verify
(
fd
,
fn
,
&
st
)
<=
0
)
{
else
if
(
file_verify
(
fd
,
fn
,
arg_file_size_max
,
&
st
)
<=
0
)
{
close_nointr_nofail
(
fd
);
fd
=
-
1
;
}
...
...
@@ -210,18 +213,89 @@ finish:
return
r
;
}
static
int
help
(
void
)
{
printf
(
"%s [OPTIONS...] [DIRECTORY]
\n\n
"
"Replay collected read-ahead data on early boot.
\n\n
"
" -h --help Show this help
\n
"
" --max-file-size=BYTES Maximum size of files to read ahead
\n
"
,
program_invocation_short_name
);
return
0
;
}
static
int
parse_argv
(
int
argc
,
char
*
argv
[])
{
enum
{
ARG_FILE_SIZE_MAX
};
static
const
struct
option
options
[]
=
{
{
"help"
,
no_argument
,
NULL
,
'h'
},
{
"file-size-max"
,
required_argument
,
NULL
,
ARG_FILE_SIZE_MAX
},
{
NULL
,
0
,
NULL
,
0
}
};
int
c
;
assert
(
argc
>=
0
);
assert
(
argv
);
while
((
c
=
getopt_long
(
argc
,
argv
,
"h"
,
options
,
NULL
))
>=
0
)
{
switch
(
c
)
{
case
'h'
:
help
();
return
0
;
case
ARG_FILE_SIZE_MAX
:
{
unsigned
long
long
ull
;
if
(
safe_atollu
(
optarg
,
&
ull
)
<
0
||
ull
<=
0
)
{
log_error
(
"Failed to parse maximum file size %s."
,
optarg
);
return
-
EINVAL
;
}
arg_file_size_max
=
(
off_t
)
ull
;
break
;
}
case
'?'
:
return
-
EINVAL
;
default:
log_error
(
"Unknown option code %c"
,
c
);
return
-
EINVAL
;
}
}
if
(
optind
!=
argc
&&
optind
!=
argc
-
1
)
{
help
();
return
-
EINVAL
;
}
return
1
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
r
;
log_set_target
(
LOG_TARGET_SYSLOG_OR_KMSG
);
log_parse_environment
();
log_open
();
if
((
r
=
parse_argv
(
argc
,
argv
))
<=
0
)
return
r
<
0
?
EXIT_FAILURE
:
EXIT_SUCCESS
;
if
(
!
enough_ram
())
{
log_info
(
"Disabling readahead replay due to low memory."
);
return
0
;
}
if
(
replay
(
argc
>=
2
?
argv
[
1
]
:
"/"
)
<
0
)
if
(
replay
(
optind
<
argc
?
argv
[
optind
]
:
"/"
)
<
0
)
return
1
;
return
0
;
...
...
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