diff options
author | Karel Zak | 2014-06-09 11:59:44 +0200 |
---|---|---|
committer | Karel Zak | 2014-06-09 11:59:44 +0200 |
commit | 3bbdae633f4a1dda5f95ee6c61f18a1c8ef12250 (patch) | |
tree | 2047e86cd087dbe1ff9d3c7d7eda348577dcfc2f /disk-utils/fsck.c | |
parent | lib/fileutils: add stripoff_last_component() from libmount (diff) | |
download | kernel-qcow2-util-linux-3bbdae633f4a1dda5f95ee6c61f18a1c8ef12250.tar.gz kernel-qcow2-util-linux-3bbdae633f4a1dda5f95ee6c61f18a1c8ef12250.tar.xz kernel-qcow2-util-linux-3bbdae633f4a1dda5f95ee6c61f18a1c8ef12250.zip |
fsck: use private lock file rather than whole-disk directly
It seems overkill to lock directly whole-disk device (for -l) when we use the
lock only to synchronize fsck instances.
It's fsck private business, so don't use system files, but let's use private
/run/fsck/<diskname>.lock file.
Addresses: https://bugs.freedesktop.org/show_bug.cgi?id=79576
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'disk-utils/fsck.c')
-rw-r--r-- | disk-utils/fsck.c | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/disk-utils/fsck.c b/disk-utils/fsck.c index 7c7043ac1..de5fb5b7c 100644 --- a/disk-utils/fsck.c +++ b/disk-utils/fsck.c @@ -53,6 +53,7 @@ #include "exitcodes.h" #include "c.h" #include "closestream.h" +#include "fileutils.h" #define XALLOC_EXIT_CODE FSCK_EX_ERROR #include "xalloc.h" @@ -64,6 +65,8 @@ #define MAX_DEVICES 32 #define MAX_ARGS 32 +#define FSCK_RUNTIME_DIRNAME "/run/fsck" + static const char *ignored_types[] = { "ignore", "iso9660", @@ -100,7 +103,10 @@ struct fsck_fs_data struct fsck_instance { int pid; int flags; /* FLAG_{DONE|PROGRESS} */ - int lock; /* flock()ed whole disk file descriptor or -1 */ + + int lock; /* flock()ed lockpath file descriptor or -1 */ + char *lockpath; /* /run/fsck/<diskname>.lock or NULL */ + int exit_status; struct timeval start_time; struct timeval end_time; @@ -327,19 +333,40 @@ static int is_irrotational_disk(dev_t disk) static void lock_disk(struct fsck_instance *inst) { dev_t disk = fs_get_disk(inst->fs, 1); - char *diskname; + char *diskpath = NULL, *diskname; + + inst->lock = -1; if (!disk || is_irrotational_disk(disk)) - return; + goto done; + + diskpath = blkid_devno_to_devname(disk); + if (!diskpath) + goto done; + + if (access(FSCK_RUNTIME_DIRNAME, F_OK) != 0) { + int rc = mkdir(FSCK_RUNTIME_DIRNAME, + S_IWUSR| + S_IRUSR|S_IRGRP|S_IROTH| + S_IXUSR|S_IXGRP|S_IXOTH); + if (rc && errno != EEXIST) { + warn(_("cannot create directory %s"), + FSCK_RUNTIME_DIRNAME); + goto done; + } + } - diskname = blkid_devno_to_devname(disk); + diskname = stripoff_last_component(diskpath); if (!diskname) - return; + diskname = diskpath; + + xasprintf(&inst->lockpath, FSCK_RUNTIME_DIRNAME "/%s.lock", diskname); if (verbose) - printf(_("Locking disk %s ... "), diskname); + printf(_("Locking disk by %s ... "), inst->lockpath); - inst->lock = open(diskname, O_CLOEXEC | O_RDONLY); + inst->lock = open(inst->lockpath, O_RDONLY|O_CREAT|O_CLOEXEC, + S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); if (inst->lock >= 0) { int rc = -1; @@ -359,21 +386,31 @@ static void lock_disk(struct fsck_instance *inst) /* TRANSLATORS: These are followups to "Locking disk...". */ printf("%s.\n", inst->lock >= 0 ? _("succeeded") : _("failed")); - free(diskname); + +done: + if (inst->lock < 0) { + free(inst->lockpath); + inst->lockpath = NULL; + } + free(diskpath); return; } static void unlock_disk(struct fsck_instance *inst) { - if (inst->lock >= 0) { - /* explicitly unlock, don't rely on close(), maybe some library - * (e.g. liblkid) has still open the device. - */ - flock(inst->lock, LOCK_UN); - close(inst->lock); + if (inst->lock < 0) + return; - inst->lock = -1; - } + if (verbose) + printf(_("Unlocking %s.\n"), inst->lockpath); + + close(inst->lock); /* unlock */ + unlink(inst->lockpath); + + free(inst->lockpath); + + inst->lock = -1; + inst->lockpath = NULL; } static void free_instance(struct fsck_instance *i) @@ -381,6 +418,7 @@ static void free_instance(struct fsck_instance *i) if (lockdisk) unlock_disk(i); free(i->prog); + free(i->lockpath); mnt_unref_fs(i->fs); free(i); return; |