If the inode nr for each file is available in the pack file we can
easily detect replaced files (like they result from package upgrades)
which we can then skip to readahead.
* drop /.readahead on bigger upgrades with yum
* drop /.readahead on bigger upgrades with yum
-* add inode nr check to readahead to suppress preloading changed files
-
* add support for /bin/mount -s
* GC unreferenced jobs (such as .device jobs)
* add support for /bin/mount -s
* GC unreferenced jobs (such as .device jobs)
void *start = MAP_FAILED;
uint8_t *vec;
uint32_t b, c;
void *start = MAP_FAILED;
uint8_t *vec;
uint32_t b, c;
size_t l, pages;
bool mapped;
int r = 0, fd = -1, k;
size_t l, pages;
bool mapped;
int r = 0, fd = -1, k;
assert(pack);
assert(fn);
assert(pack);
assert(fn);
- if ((fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW)) < 0) {
+ fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0) {
if (errno == ENOENT)
return 0;
if (errno == ENOENT)
return 0;
- if ((k = file_verify(fd, fn, arg_file_size_max, &st)) <= 0) {
+ k = file_verify(fd, fn, arg_file_size_max, &st);
+ if (k <= 0) {
btrfs_defrag(fd);
l = PAGE_ALIGN(st.st_size);
btrfs_defrag(fd);
l = PAGE_ALIGN(st.st_size);
- if ((start = mmap(NULL, l, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+ start = mmap(NULL, l, PROT_READ, MAP_SHARED, fd, 0);
+ if (start == MAP_FAILED) {
log_warning("mmap(%s) failed: %m", fn);
r = -errno;
goto finish;
}
pages = l / page_size();
log_warning("mmap(%s) failed: %m", fn);
r = -errno;
goto finish;
}
pages = l / page_size();
vec = alloca(pages);
memset(vec, 0, pages);
if (mincore(start, l, vec) < 0) {
vec = alloca(pages);
memset(vec, 0, pages);
if (mincore(start, l, vec) < 0) {
fputs(fn, pack);
fputc('\n', pack);
fputs(fn, pack);
fputc('\n', pack);
+ /* Store the inode, so that we notice when the file is deleted */
+ inode = (uint64_t) st.st_ino;
+ fwrite(&inode, sizeof(inode), 1, pack);
+
mapped = false;
for (c = 0; c < pages; c++) {
bool new_mapped = !!(vec[c] & 1);
mapped = false;
for (c = 0; c < pages; c++) {
bool new_mapped = !!(vec[c] & 1);
- if (!(pack = fopen(pack_fn_new, "we"))) {
+ pack = fopen(pack_fn_new, "we");
+ if (!pack) {
log_error("Failed to open pack file: %m");
r = -errno;
goto finish;
}
log_error("Failed to open pack file: %m");
r = -errno;
goto finish;
}
- fputs(CANONICAL_HOST "\n", pack);
+ fputs(CANONICAL_HOST ";VERSION=2\n", pack);
putc(on_ssd ? 'S' : 'R', pack);
if (on_ssd || on_btrfs) {
putc(on_ssd ? 'S' : 'R', pack);
if (on_ssd || on_btrfs) {
int r = 0, fd = -1;
bool any = false;
struct stat st;
int r = 0, fd = -1;
bool any = false;
struct stat st;
char_array_0(fn);
truncate_nl(fn);
char_array_0(fn);
truncate_nl(fn);
- if ((fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW)) < 0) {
+ fd = open(fn, O_RDONLY|O_CLOEXEC|O_NOATIME|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0) {
if (errno != ENOENT && errno != EPERM && errno != EACCES)
log_warning("open(%s) failed: %m", fn);
if (errno != ENOENT && errno != EPERM && errno != EACCES)
log_warning("open(%s) failed: %m", fn);
+ if (fread(&inode, sizeof(inode), 1, pack) != 1) {
+ log_error("Premature end of pack file.");
+ r = -EIO;
+ goto finish;
+ }
+
+ if (fd >= 0) {
+ /* If the inode changed the file got deleted, so just
+ * ignore this entry */
+ if (st.st_ino != (uint64_t) inode) {
+ close_nointr_nofail(fd);
+ fd = -1;
+ }
+ }
+
for (;;) {
uint32_t b, c;
for (;;) {
uint32_t b, c;
- if (!streq(line, CANONICAL_HOST "\n")) {
- log_debug("Pack file host type mismatch.");
+ if (!streq(line, CANONICAL_HOST ";VERSION=2\n")) {
+ log_debug("Pack file host or version type mismatch.");