X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=libudev%2Flibudev-queue-private.c;h=e0a7b53b8136b592a1c647fc6bdfc0265017de61;hp=9ae680c386a9c7bc0f74458bb64988f55b828732;hb=289a1821a4a7636ce42a6c7adc3a9bb49421a5ea;hpb=98631e1c21090db8fe8800f2a6658592406670ac diff --git a/libudev/libudev-queue-private.c b/libudev/libudev-queue-private.c index 9ae680c38..e0a7b53b8 100644 --- a/libudev/libudev-queue-private.c +++ b/libudev/libudev-queue-private.c @@ -19,19 +19,22 @@ * * When a new event is queued, its details are appended to the log. * When the event finishes, a second record is appended to the log - * with the same sequence number but a null devpath. + * with the same sequence number but a devpath len of 0. * * Example: - * {1, "/devices/virtual/mem/null" }, - * {2, "/devices/virtual/mem/zero" }, - * {1, "" }, - * Event 2 is still queued, but event 1 has been finished + * { 0x0000000000000001 } + * { 0x0000000000000001, 0x0019, "/devices/virtual/mem/null" }, + * { 0x0000000000000002, 0x001b, "/devices/virtual/mem/random" }, + * { 0x0000000000000001, 0x0000 }, + * { 0x0000000000000003, 0x0019, "/devices/virtual/mem/zero" }, * - * The queue does not grow indefinitely. It is periodically re-created - * to remove finished events. Atomic rename() makes this transparent to readers. + * Events 2 and 3 are still queued, but event 1 has finished. + * + * The queue does not grow indefinitely. It is periodically re-created + * to remove finished events. Atomic rename() makes this transparent to readers. * * The queue file starts with a single sequence number which specifies the - * minimum sequence number in the log that follows. Any events prior to this + * minimum sequence number in the log that follows. Any events prior to this * sequence number have already finished. */ @@ -42,9 +45,9 @@ #include #include #include +#include #include #include -#include #include "libudev.h" #include "libudev-private.h" @@ -53,7 +56,6 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export); struct udev_queue_export { struct udev *udev; - int failed_count; /* number of failed events exported */ int queued_count; /* number of unfinished events exported in queue file */ FILE *queue_file; unsigned long long int seqnum_max; /* earliest sequence number in queue file */ @@ -87,23 +89,25 @@ struct udev_queue_export *udev_queue_export_new(struct udev *udev) return udev_queue_export; } -void udev_queue_export_unref(struct udev_queue_export *udev_queue_export) +struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export) { if (udev_queue_export == NULL) - return; + return NULL; if (udev_queue_export->queue_file != NULL) fclose(udev_queue_export->queue_file); free(udev_queue_export); + return NULL; } void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export) { char filename[UTIL_PATH_SIZE]; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL); + if (udev_queue_export == NULL) + return; + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.tmp", NULL); unlink(filename); - - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.bin", NULL); unlink(filename); } @@ -155,12 +159,12 @@ static struct queue_devpaths *build_index(struct udev_queue_export *udev_queue_e return NULL; } devpaths = calloc(1, sizeof(struct queue_devpaths) + (range + 1) * sizeof(long)); - if (index == NULL) + if (devpaths == NULL) return NULL; devpaths->devpaths_size = range + 1; /* read all records and populate the table */ - while(1) { + for (;;) { if (udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum) < 0) break; n = seqnum - udev_queue_export->seqnum_max; @@ -218,7 +222,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export) } /* create new queue file */ - util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL); + util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_run_path(udev_queue_export->udev), "/queue.tmp", NULL); new_queue_file = fopen(filename_tmp, "w+"); if (new_queue_file == NULL) goto error; @@ -252,7 +256,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export) goto error; /* rename the new file on top of the old one */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.bin", NULL); if (rename(filename_tmp, filename) != 0) goto error; @@ -299,8 +303,10 @@ static int write_queue_record(struct udev_queue_export *udev_queue_export, len = (devpath_len < USHRT_MAX) ? devpath_len : USHRT_MAX; if (fwrite(&len, sizeof(unsigned short), 1, udev_queue_export->queue_file) != 1) goto write_error; - if (fwrite(devpath, 1, len, udev_queue_export->queue_file) != len) - goto write_error; + if (len > 0) { + if (fwrite(devpath, 1, len, udev_queue_export->queue_file) != len) + goto write_error; + } /* *must* flush output; caller may fork */ if (fflush(udev_queue_export->queue_file) != 0) @@ -321,7 +327,6 @@ write_error: enum device_state { DEVICE_QUEUED, DEVICE_FINISHED, - DEVICE_FAILED, }; static inline size_t queue_record_size(size_t devpath_len) @@ -338,6 +343,7 @@ static int update_queue(struct udev_queue_export *udev_queue_export, int bytes; int err; + /* FINISHED records have a zero length devpath */ if (state == DEVICE_QUEUED) { devpath = udev_device_get_devpath(udev_device); devpath_len = strlen(devpath); @@ -349,12 +355,9 @@ static int update_queue(struct udev_queue_export *udev_queue_export, return -1; } - /* when the queue files grow too large, they must be garbage collected and rebuilt */ - bytes = ftell(udev_queue_export->queue_file) + queue_record_size(devpath_len); - /* if we're removing the last event from the queue, that's the best time to rebuild it */ - if (state != DEVICE_QUEUED && udev_queue_export->queued_count == 1 && bytes > 2048) { - /* because we don't need to read the old queue file */ + if (state != DEVICE_QUEUED && udev_queue_export->queued_count == 1) { + /* we don't need to read the old queue file */ fclose(udev_queue_export->queue_file); udev_queue_export->queue_file = NULL; rebuild_queue_file(udev_queue_export); @@ -362,6 +365,7 @@ static int update_queue(struct udev_queue_export *udev_queue_export, } /* try to rebuild the queue files before they grow larger than one page. */ + bytes = ftell(udev_queue_export->queue_file) + queue_record_size(devpath_len); if ((udev_queue_export->waste_bytes > bytes / 2) && bytes > 4096) rebuild_queue_file(udev_queue_export); @@ -388,66 +392,9 @@ static int update_queue(struct udev_queue_export *udev_queue_export, return err; } -static void update_failed(struct udev_queue_export *udev_queue_export, - struct udev_device *udev_device, enum device_state state) -{ - struct udev *udev = udev_device_get_udev(udev_device); - char filename[UTIL_PATH_SIZE]; - char *s; - size_t l; - - if (state != DEVICE_FAILED && udev_queue_export->failed_count == 0) - return; - - /* location of failed file */ - s = filename; - l = util_strpcpyl(&s, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/failed/", NULL); - util_path_encode(udev_device_get_devpath(udev_device), s, l); - - switch (state) { - case DEVICE_FAILED: - /* record event in the failed directory */ - if (udev_queue_export->failed_count == 0) - util_create_path(udev, filename); - udev_queue_export->failed_count++; - - udev_selinux_setfscreatecon(udev, filename, S_IFLNK); - symlink(udev_device_get_devpath(udev_device), filename); - udev_selinux_resetfscreatecon(udev); - break; - - case DEVICE_QUEUED: - /* delete failed file */ - if (unlink(filename) == 0) { - util_delete_path(udev, filename); - udev_queue_export->failed_count--; - } - break; - - case DEVICE_FINISHED: - if (udev_device_get_devpath_old(udev_device) != NULL) { - /* "move" event - rename failed file to current name, do not delete failed */ - char filename_old[UTIL_PATH_SIZE]; - - s = filename_old; - l = util_strpcpyl(&s, sizeof(filename_old), udev_get_dev_path(udev_queue_export->udev), "/.udev/failed/", NULL); - util_path_encode(udev_device_get_devpath_old(udev_device), s, l); - - if (rename(filename_old, filename) == 0) - info(udev, "renamed devpath, moved failed state of '%s' to %s'\n", - udev_device_get_devpath_old(udev_device), udev_device_get_devpath(udev_device)); - } - break; - } - - return; -} - static int update(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device, enum device_state state) { - update_failed(udev_queue_export, udev_device, state); - if (update_queue(udev_queue_export, udev_device, state) != 0) return -1; @@ -463,8 +410,3 @@ int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_expor { return update(udev_queue_export, udev_device, DEVICE_FINISHED); } - -int udev_queue_export_device_failed(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device) -{ - return update(udev_queue_export, udev_device, DEVICE_FAILED); -}