2 This file is part of systemd.
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 * DISCLAIMER - The file format mentioned here is private to udev/libudev,
23 * and may be changed without notice.
25 * The udev event queue is exported as a binary log file.
26 * Each log record consists of a sequence number followed by the device path.
28 * When a new event is queued, its details are appended to the log.
29 * When the event finishes, a second record is appended to the log
30 * with the same sequence number but a devpath len of 0.
33 * { 0x0000000000000001 }
34 * { 0x0000000000000001, 0x0019, "/devices/virtual/mem/null" },
35 * { 0x0000000000000002, 0x001b, "/devices/virtual/mem/random" },
36 * { 0x0000000000000001, 0x0000 },
37 * { 0x0000000000000003, 0x0019, "/devices/virtual/mem/zero" },
39 * Events 2 and 3 are still queued, but event 1 has finished.
41 * The queue does not grow indefinitely. It is periodically re-created
42 * to remove finished events. Atomic rename() makes this transparent to readers.
44 * The queue file starts with a single sequence number which specifies the
45 * minimum sequence number in the log that follows. Any events prior to this
46 * sequence number have already finished.
58 #include <sys/types.h>
61 #include "libudev-private.h"
63 static int rebuild_queue_file(struct udev_queue_export *udev_queue_export);
65 struct udev_queue_export {
67 int queued_count; /* number of unfinished events exported in queue file */
69 unsigned long long int seqnum_max; /* earliest sequence number in queue file */
70 unsigned long long int seqnum_min; /* latest sequence number in queue file */
71 int waste_bytes; /* queue file bytes wasted on finished events */
74 struct udev_queue_export *udev_queue_export_new(struct udev *udev)
76 struct udev_queue_export *udev_queue_export;
77 unsigned long long int initial_seqnum;
82 udev_queue_export = calloc(1, sizeof(struct udev_queue_export));
83 if (udev_queue_export == NULL)
85 udev_queue_export->udev = udev;
87 initial_seqnum = udev_get_kernel_seqnum(udev);
88 udev_queue_export->seqnum_min = initial_seqnum;
89 udev_queue_export->seqnum_max = initial_seqnum;
91 udev_queue_export_cleanup(udev_queue_export);
92 if (rebuild_queue_file(udev_queue_export) != 0) {
93 free(udev_queue_export);
97 return udev_queue_export;
100 struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export)
102 if (udev_queue_export == NULL)
104 if (udev_queue_export->queue_file != NULL)
105 fclose(udev_queue_export->queue_file);
106 free(udev_queue_export);
110 void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export)
112 if (udev_queue_export == NULL)
114 unlink("/run/udev/queue.tmp");
115 unlink("/run/udev/queue.bin");
118 static int skip_to(FILE *file, long offset)
122 /* fseek may drop buffered data, avoid it for small seeks */
123 old_offset = ftell(file);
124 if (offset > old_offset && offset - old_offset <= BUFSIZ) {
125 size_t skip_bytes = offset - old_offset;
126 char *buf = alloca(skip_bytes);
128 if (fread(buf, skip_bytes, 1, file) != skip_bytes)
132 return fseek(file, offset, SEEK_SET);
135 struct queue_devpaths {
136 unsigned int devpaths_first; /* index of first queued event */
137 unsigned int devpaths_size;
138 long devpaths[]; /* seqnum -> offset of devpath in queue file (or 0) */
142 * Returns a table mapping seqnum to devpath file offset for currently queued events.
143 * devpaths[i] represents the event with seqnum = i + udev_queue_export->seqnum_min.
145 static struct queue_devpaths *build_index(struct udev_queue_export *udev_queue_export)
147 struct queue_devpaths *devpaths;
148 unsigned long long int range;
151 unsigned long long int seqnum;
152 unsigned long long int n;
155 /* seek to the first event in the file */
156 rewind(udev_queue_export->queue_file);
157 udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum);
159 /* allocate the table */
160 range = udev_queue_export->seqnum_min - udev_queue_export->seqnum_max;
161 if (range - 1 > INT_MAX) {
162 udev_err(udev_queue_export->udev, "queue file overflow\n");
165 devpaths = calloc(1, sizeof(struct queue_devpaths) + (range + 1) * sizeof(long));
166 if (devpaths == NULL)
168 devpaths->devpaths_size = range + 1;
170 /* read all records and populate the table */
172 if (udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum) < 0)
174 n = seqnum - udev_queue_export->seqnum_max;
175 if (n >= devpaths->devpaths_size)
178 devpath_offset = ftell(udev_queue_export->queue_file);
179 devpath_len = udev_queue_skip_devpath(udev_queue_export->queue_file);
184 devpaths->devpaths[n] = devpath_offset;
186 devpaths->devpaths[n] = 0;
189 /* find first queued event */
190 for (i = 0; i < devpaths->devpaths_size; i++) {
191 if (devpaths->devpaths[i] != 0)
194 devpaths->devpaths_first = i;
199 udev_err(udev_queue_export->udev, "queue file corrupted\n");
204 static int rebuild_queue_file(struct udev_queue_export *udev_queue_export)
206 unsigned long long int seqnum;
207 struct queue_devpaths *devpaths = NULL;
208 FILE *new_queue_file = NULL;
211 /* read old queue file */
212 if (udev_queue_export->queue_file != NULL) {
213 devpaths = build_index(udev_queue_export);
214 if (devpaths != NULL)
215 udev_queue_export->seqnum_max += devpaths->devpaths_first;
217 if (devpaths == NULL) {
218 udev_queue_export->queued_count = 0;
219 udev_queue_export->seqnum_max = udev_queue_export->seqnum_min;
222 /* create new queue file */
223 new_queue_file = fopen("/run/udev/queue.tmp", "w+e");
224 if (new_queue_file == NULL)
226 seqnum = udev_queue_export->seqnum_max;
227 fwrite(&seqnum, 1, sizeof(unsigned long long int), new_queue_file);
229 /* copy unfinished events only to the new file */
230 if (devpaths != NULL) {
231 for (i = devpaths->devpaths_first; i < devpaths->devpaths_size; i++) {
232 char devpath[UTIL_PATH_SIZE];
234 unsigned short devpath_len;
236 if (devpaths->devpaths[i] != 0)
238 skip_to(udev_queue_export->queue_file, devpaths->devpaths[i]);
239 err = udev_queue_read_devpath(udev_queue_export->queue_file, devpath, sizeof(devpath));
242 fwrite(&seqnum, sizeof(unsigned long long int), 1, new_queue_file);
243 fwrite(&devpath_len, sizeof(unsigned short), 1, new_queue_file);
244 fwrite(devpath, 1, devpath_len, new_queue_file);
251 fflush(new_queue_file);
252 if (ferror(new_queue_file))
255 /* rename the new file on top of the old one */
256 if (rename("/run/udev/queue.tmp", "/run/udev/queue.bin") != 0)
259 if (udev_queue_export->queue_file != NULL)
260 fclose(udev_queue_export->queue_file);
261 udev_queue_export->queue_file = new_queue_file;
262 udev_queue_export->waste_bytes = 0;
267 udev_err(udev_queue_export->udev, "failed to create queue file: %m\n");
268 udev_queue_export_cleanup(udev_queue_export);
270 if (udev_queue_export->queue_file != NULL) {
271 fclose(udev_queue_export->queue_file);
272 udev_queue_export->queue_file = NULL;
274 if (new_queue_file != NULL)
275 fclose(new_queue_file);
277 if (devpaths != NULL)
279 udev_queue_export->queued_count = 0;
280 udev_queue_export->waste_bytes = 0;
281 udev_queue_export->seqnum_max = udev_queue_export->seqnum_min;
286 static int write_queue_record(struct udev_queue_export *udev_queue_export,
287 unsigned long long int seqnum, const char *devpath, size_t devpath_len)
291 if (udev_queue_export->queue_file == NULL)
294 if (fwrite(&seqnum, sizeof(unsigned long long int), 1, udev_queue_export->queue_file) != 1)
297 len = (devpath_len < USHRT_MAX) ? devpath_len : USHRT_MAX;
298 if (fwrite(&len, sizeof(unsigned short), 1, udev_queue_export->queue_file) != 1)
301 if (fwrite(devpath, 1, len, udev_queue_export->queue_file) != len)
305 /* *must* flush output; caller may fork */
306 if (fflush(udev_queue_export->queue_file) != 0)
312 /* if we failed half way through writing a record to a file,
313 we should not try to write any further records to it. */
314 udev_err(udev_queue_export->udev, "error writing to queue file: %m\n");
315 fclose(udev_queue_export->queue_file);
316 udev_queue_export->queue_file = NULL;
326 static inline size_t queue_record_size(size_t devpath_len)
328 return sizeof(unsigned long long int) + sizeof(unsigned short int) + devpath_len;
331 static int update_queue(struct udev_queue_export *udev_queue_export,
332 struct udev_device *udev_device, enum device_state state)
334 unsigned long long int seqnum = udev_device_get_seqnum(udev_device);
335 const char *devpath = NULL;
336 size_t devpath_len = 0;
340 /* FINISHED records have a zero length devpath */
341 if (state == DEVICE_QUEUED) {
342 devpath = udev_device_get_devpath(udev_device);
343 devpath_len = strlen(devpath);
346 /* recover from an earlier failed rebuild */
347 if (udev_queue_export->queue_file == NULL) {
348 if (rebuild_queue_file(udev_queue_export) != 0)
352 /* if we're removing the last event from the queue, that's the best time to rebuild it */
353 if (state != DEVICE_QUEUED && udev_queue_export->queued_count == 1) {
354 /* we don't need to read the old queue file */
355 fclose(udev_queue_export->queue_file);
356 udev_queue_export->queue_file = NULL;
357 rebuild_queue_file(udev_queue_export);
361 /* try to rebuild the queue files before they grow larger than one page. */
362 bytes = ftell(udev_queue_export->queue_file) + queue_record_size(devpath_len);
363 if ((udev_queue_export->waste_bytes > bytes / 2) && bytes > 4096)
364 rebuild_queue_file(udev_queue_export);
366 /* don't record a finished event, if we already dropped the event in a failed rebuild */
367 if (seqnum < udev_queue_export->seqnum_max)
370 /* now write to the queue */
371 if (state == DEVICE_QUEUED) {
372 udev_queue_export->queued_count++;
373 udev_queue_export->seqnum_min = seqnum;
375 udev_queue_export->waste_bytes += queue_record_size(devpath_len) + queue_record_size(0);
376 udev_queue_export->queued_count--;
378 err = write_queue_record(udev_queue_export, seqnum, devpath, devpath_len);
380 /* try to handle ENOSPC */
381 if (err != 0 && udev_queue_export->queued_count == 0) {
382 udev_queue_export_cleanup(udev_queue_export);
383 err = rebuild_queue_file(udev_queue_export);
389 static int update(struct udev_queue_export *udev_queue_export,
390 struct udev_device *udev_device, enum device_state state)
392 if (update_queue(udev_queue_export, udev_device, state) != 0)
398 int udev_queue_export_device_queued(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device)
400 return update(udev_queue_export, udev_device, DEVICE_QUEUED);
403 int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device)
405 return update(udev_queue_export, udev_device, DEVICE_FINISHED);