]>
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 bool enough_ram ( void ) {
120 assert_se ( sysinfo (& si
) >= 0 );
122 return si
. totalram
> 127 * 1024 * 1024 ; /* Enable readahead only
123 * with at least 128MB
127 int open_inotify ( void ) {
130 if (( fd
= inotify_init1 ( IN_CLOEXEC
| IN_NONBLOCK
)) < 0 ) {
131 log_error ( "Failed to create inotify handle: %m" );
135 mkdir ( "/dev/.systemd" , 0755 );
136 mkdir ( "/dev/.systemd/readahead" , 0755 );
138 if ( inotify_add_watch ( fd
, "/dev/.systemd/readahead" , IN_CREATE
) < 0 ) {
139 log_error ( "Failed to watch /dev/.systemd/readahead: %m" );
140 close_nointr_nofail ( fd
);
147 ReadaheadShared
* shared_get ( void ) {
149 ReadaheadShared
* m
= NULL
;
151 mkdir ( "/dev/.systemd" , 0755 );
152 mkdir ( "/dev/.systemd/readahead" , 0755 );
154 if (( fd
= open ( "/dev/.systemd/readahead/shared" , O_CREAT
| O_RDWR
| O_CLOEXEC
, 0644 )) < 0 ) {
155 log_error ( "Failed to create shared memory segment: %m" );
159 if ( ftruncate ( fd
, sizeof ( ReadaheadShared
)) < 0 ) {
160 log_error ( "Failed to truncate shared memory segment: %m" );
164 if (( m
= mmap ( NULL
, sizeof ( ReadaheadShared
), PROT_WRITE
| PROT_READ
, MAP_SHARED
, fd
, 0 )) == MAP_FAILED
) {
165 log_error ( "Failed to mmap shared memory segment: %m" );
172 close_nointr_nofail ( fd
);
178 #define BUMP_REQUEST_NR (16*1024)
180 int bump_request_nr ( const char * p
) {
182 struct udev
* udev
= NULL
;
183 struct udev_device
* udev_device
= NULL
, * look_at
= NULL
;
184 const char * nr_requests
;
186 char nr
[ 64 ], * ap
= NULL
;
191 if ( stat ( p
, & st
) < 0 )
194 if ( major ( st
. st_dev
) == 0 )
197 if (!( udev
= udev_new ()))
200 if (!( udev_device
= udev_device_new_from_devnum ( udev
, 'b' , st
. st_dev
))) {
205 look_at
= udev_device
;
206 if (!( nr_requests
= udev_device_get_sysattr_value ( look_at
, "queue/nr_requests" ))) {
208 /* Hmm, if the block device doesn't have a queue
209 * subdir, the let's look in the parent */
210 look_at
= udev_device_get_parent ( udev_device
);
211 nr_requests
= udev_device_get_sysattr_value ( look_at
, "queue/nr_requests" );
219 if ( safe_atou64 ( nr_requests
, & u
) >= 0 && u
>= BUMP_REQUEST_NR
) {
224 if ( asprintf (& ap
, "%s/queue/nr_requests" , udev_device_get_syspath ( look_at
)) < 0 ) {
229 snprintf ( nr
, sizeof ( nr
), "%lu" , ( unsigned long ) BUMP_REQUEST_NR
);
231 if (( r
= write_one_line_file ( ap
, nr
)) < 0 )
234 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
);
239 udev_device_unref ( udev_device
);