]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/readahead-common.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/sysinfo.h>
26 #include <sys/inotify.h>
33 #include "readahead-common.h"
36 int file_verify ( int fd
, const char * fn
, off_t file_size_max
, struct stat
* st
) {
41 if ( fstat ( fd
, st
) < 0 ) {
42 log_warning ( "fstat(%s) failed: %m" , fn
);
46 if (! S_ISREG ( st
-> st_mode
)) {
47 log_debug ( "Not preloading special file %s" , fn
);
51 if ( st
-> st_size
<= 0 || st
-> st_size
> file_size_max
) {
52 log_debug ( "Not preloading file %s with size out of bounds %llu" , fn
, ( unsigned long long ) st
-> st_size
);
59 int fs_on_ssd ( const char * p
) {
61 struct udev
* udev
= NULL
;
62 struct udev_device
* udev_device
= NULL
, * look_at
= NULL
;
64 const char * devtype
, * rotational
, * model
, * id
;
71 if ( major ( st
. st_dev
) == 0 )
74 if (!( udev
= udev_new ()))
77 if (!( udev_device
= udev_device_new_from_devnum ( udev
, 'b' , st
. st_dev
)))
80 if (( devtype
= udev_device_get_property_value ( udev_device
, "DEVTYPE" )) &&
81 streq ( devtype
, "partition" ))
82 look_at
= udev_device_get_parent ( udev_device
);
84 look_at
= udev_device
;
89 /* First, try high-level property */
90 if (( id
= udev_device_get_property_value ( look_at
, "ID_SSD" ))) {
95 /* Second, try kernel attribute */
96 if (( rotational
= udev_device_get_sysattr_value ( look_at
, "queue/rotational" )))
97 if (( b
= streq ( rotational
, "0" )))
100 /* Finally, fallback to heuristics */
101 if (!( look_at
= udev_device_get_parent ( look_at
)))
104 if (( model
= udev_device_get_sysattr_value ( look_at
, "model" )))
105 b
= !! strstr ( model
, "SSD" );
109 udev_device_unref ( udev_device
);
117 int fs_on_read_only ( const char * p
) {
119 struct udev
* udev
= NULL
;
120 struct udev_device
* udev_device
= NULL
;
122 const char * read_only
;
126 if ( stat ( p
, & st
) < 0 )
129 if ( major ( st
. st_dev
) == 0 )
132 if (!( udev
= udev_new ()))
135 if (!( udev_device
= udev_device_new_from_devnum ( udev
, 'b' , st
. st_dev
)))
138 if (( read_only
= udev_device_get_sysattr_value ( udev_device
, "ro" )))
139 if (( b
= streq ( read_only
, "1" )))
144 udev_device_unref ( udev_device
);
152 bool enough_ram ( void ) {
155 assert_se ( sysinfo (& si
) >= 0 );
157 /* Enable readahead only with at least 128MB memory */
158 return si
. totalram
> 127 * 1024 * 1024 / si
. mem_unit
;
161 int open_inotify ( void ) {
164 if (( fd
= inotify_init1 ( IN_CLOEXEC
| IN_NONBLOCK
)) < 0 ) {
165 log_error ( "Failed to create inotify handle: %m" );
169 mkdir ( "/run/systemd" , 0755 );
170 mkdir ( "/run/systemd/readahead" , 0755 );
172 if ( inotify_add_watch ( fd
, "/run/systemd/readahead" , IN_CREATE
) < 0 ) {
173 log_error ( "Failed to watch /run/systemd/readahead: %m" );
174 close_nointr_nofail ( fd
);
181 ReadaheadShared
* shared_get ( void ) {
183 ReadaheadShared
* m
= NULL
;
185 mkdir ( "/run/systemd" , 0755 );
186 mkdir ( "/run/systemd/readahead" , 0755 );
188 if (( fd
= open ( "/run/systemd/readahead/shared" , O_CREAT
| O_RDWR
| O_CLOEXEC
, 0644 )) < 0 ) {
189 log_error ( "Failed to create shared memory segment: %m" );
193 if ( ftruncate ( fd
, sizeof ( ReadaheadShared
)) < 0 ) {
194 log_error ( "Failed to truncate shared memory segment: %m" );
198 if (( m
= mmap ( NULL
, sizeof ( ReadaheadShared
), PROT_WRITE
| PROT_READ
, MAP_SHARED
, fd
, 0 )) == MAP_FAILED
) {
199 log_error ( "Failed to mmap shared memory segment: %m" );
206 close_nointr_nofail ( fd
);
211 #define BUMP_REQUEST_NR (16*1024)
213 int bump_request_nr ( const char * p
) {
215 struct udev
* udev
= NULL
;
216 struct udev_device
* udev_device
= NULL
, * look_at
= NULL
;
217 const char * nr_requests
;
219 char nr
[ 64 ], * ap
= NULL
;
224 if ( stat ( p
, & st
) < 0 )
227 if ( major ( st
. st_dev
) == 0 )
230 if (!( udev
= udev_new ()))
233 if (!( udev_device
= udev_device_new_from_devnum ( udev
, 'b' , st
. st_dev
))) {
238 look_at
= udev_device
;
239 if (!( nr_requests
= udev_device_get_sysattr_value ( look_at
, "queue/nr_requests" ))) {
241 /* Hmm, if the block device doesn't have a queue
242 * subdir, the let's look in the parent */
243 look_at
= udev_device_get_parent ( udev_device
);
244 nr_requests
= udev_device_get_sysattr_value ( look_at
, "queue/nr_requests" );
252 if ( safe_atou64 ( nr_requests
, & u
) >= 0 && u
>= BUMP_REQUEST_NR
) {
257 if ( asprintf (& ap
, "%s/queue/nr_requests" , udev_device_get_syspath ( look_at
)) < 0 ) {
262 snprintf ( nr
, sizeof ( nr
), "%lu" , ( unsigned long ) BUMP_REQUEST_NR
);
264 if (( r
= write_one_line_file ( ap
, nr
)) < 0 )
267 log_info ( "Bumped block_nr parameter of %s to %lu. This is a temporary hack and should be removed one day." , udev_device_get_devnode ( look_at
), ( unsigned long ) BUMP_REQUEST_NR
);
272 udev_device_unref ( udev_device
);