X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournal-file.c;h=7f5d7c27b21d22823f4d4fa937cfb4cd20365cb1;hp=8c17620ed339bf9576bf498e2d6ad02018983df8;hb=71100051c5d351daac20610f3a4b8c14901088d8;hpb=48496df65c3ad1e3ad055d2b4632da7b73211715 diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 8c17620ed..7f5d7c27b 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -48,7 +48,7 @@ #define DEFAULT_MAX_USE_UPPER (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ /* This is the upper bound if we deduce max_size from max_use */ -#define DEFAULT_MAX_SIZE_UPPER (16ULL*1024ULL*1024ULL) /* 16 MiB */ +#define DEFAULT_MAX_SIZE_UPPER (128ULL*1024ULL*1024ULL) /* 128 MiB */ /* This is the upper bound if we deduce the keep_free value from the * file system size */ @@ -1727,6 +1727,9 @@ int journal_file_open( (flags & O_ACCMODE) != O_RDWR) return -EINVAL; + if (!endswith(fname, ".journal")) + return -EINVAL; + f = new0(JournalFile, 1); if (!f) return -ENOMEM; @@ -1840,7 +1843,7 @@ int journal_file_rotate(JournalFile **f) { l = strlen(old_file->path); - p = new(char, l + 1 + 16 + 1 + 32 + 1 + 16 + 1); + p = new(char, l + 1 + 32 + 1 + 16 + 1 + 16 + 1); if (!p) return -ENOMEM; @@ -1867,6 +1870,46 @@ int journal_file_rotate(JournalFile **f) { return r; } +int journal_file_open_reliably( + const char *fname, + int flags, + mode_t mode, + JournalFile *template, + JournalFile **ret) { + + int r; + size_t l; + char *p; + + r = journal_file_open(fname, flags, mode, template, ret); + if (r != -EBADMSG) + return r; + + if ((flags & O_ACCMODE) == O_RDONLY) + return r; + + if (!(flags & O_CREAT)) + return r; + + /* The file is corrupted. Rotate it away and try it again (but only once) */ + + l = strlen(fname); + if (asprintf(&p, "%.*s@%016llx-%016llx.journal~", + (int) (l-8), fname, + (unsigned long long) now(CLOCK_REALTIME), + random_ull()) < 0) + return -ENOMEM; + + r = rename(fname, p); + free(p); + if (r < 0) + return -errno; + + log_warning("File %s corrupted, renaming and replacing.", fname); + + return journal_file_open(fname, flags, mode, template, ret); +} + struct vacuum_info { off_t usage; char *filename; @@ -1874,6 +1917,8 @@ struct vacuum_info { uint64_t realtime; sd_id128_t seqnum_id; uint64_t seqnum; + + bool have_seqnum; }; static int vacuum_compare(const void *_a, const void *_b) { @@ -1882,7 +1927,8 @@ static int vacuum_compare(const void *_a, const void *_b) { a = _a; b = _b; - if (sd_id128_equal(a->seqnum_id, b->seqnum_id)) { + if (a->have_seqnum && b->have_seqnum && + sd_id128_equal(a->seqnum_id, b->seqnum_id)) { if (a->seqnum < b->seqnum) return -1; else if (a->seqnum > b->seqnum) @@ -1895,8 +1941,10 @@ static int vacuum_compare(const void *_a, const void *_b) { return -1; else if (a->realtime > b->realtime) return 1; - else + else if (a->have_seqnum && b->have_seqnum) return memcmp(&a->seqnum_id, &b->seqnum_id, 16); + else + return strcmp(a->filename, b->filename); } int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free) { @@ -1923,6 +1971,7 @@ int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t m char *p; unsigned long long seqnum, realtime; sd_id128_t seqnum_id; + bool have_seqnum; k = readdir_r(d, &buf, &de); if (k != 0) { @@ -1933,41 +1982,71 @@ int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t m if (!de) break; - if (!dirent_is_file_with_suffix(de, ".journal")) + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) + continue; + + if (!S_ISREG(st.st_mode)) continue; q = strlen(de->d_name); - if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) - continue; + if (endswith(de->d_name, ".journal")) { - if (de->d_name[q-8-16-1] != '-' || - de->d_name[q-8-16-1-16-1] != '-' || - de->d_name[q-8-16-1-16-1-32-1] != '@') - continue; + /* Vacuum archived files */ - if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) - continue; + if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) + continue; - if (!S_ISREG(st.st_mode)) - continue; + if (de->d_name[q-8-16-1] != '-' || + de->d_name[q-8-16-1-16-1] != '-' || + de->d_name[q-8-16-1-16-1-32-1] != '@') + continue; - p = strdup(de->d_name); - if (!p) { - r = -ENOMEM; - goto finish; - } + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } - de->d_name[q-8-16-1-16-1] = 0; - if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { - free(p); - continue; - } + de->d_name[q-8-16-1-16-1] = 0; + if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { + free(p); + continue; + } - if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { - free(p); + if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { + free(p); + continue; + } + + have_seqnum = true; + + } else if (endswith(de->d_name, ".journal~")) { + unsigned long long tmp; + + /* Vacuum corrupted files */ + + if (q < 1 + 16 + 1 + 16 + 8 + 1) + continue; + + if (de->d_name[q-1-8-16-1] != '-' || + de->d_name[q-1-8-16-1-16-1] != '@') + continue; + + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } + + if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { + free(p); + continue; + } + + have_seqnum = false; + } else continue; - } if (n_list >= n_allocated) { struct vacuum_info *j; @@ -1988,6 +2067,7 @@ int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t m list[n_list].seqnum = seqnum; list[n_list].realtime = realtime; list[n_list].seqnum_id = seqnum_id; + list[n_list].have_seqnum = have_seqnum; sum += list[n_list].usage;