[3/3] debuginfod: When retrieving files from cache, update atime manually

Message ID 20230324004805.156080-3-heftig@archlinux.org
State Committed
Headers
Series [1/3] debuginfod: Replace futimes with futimens |

Commit Message

Jan Alexander Steffens \(heftig\) March 24, 2023, 12:48 a.m. UTC
  The cache cleaning logic requires atime to be correct (strictatime) but
most users on Linux only have relatime or even noatime.

Attempt to update the atime manually so that the cache works properly.

Signed-off-by: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
---
 debuginfod/debuginfod-client.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
  

Comments

Frank Ch. Eigler March 29, 2023, 8:54 p.m. UTC | #1
Hi -

> The cache cleaning logic requires atime to be correct (strictatime) but
> most users on Linux only have relatime or even noatime.

This is not really correct: relatime is the kernel default and works
fine with the cache.  atime values updated once a day are still plenty
for caches with a multi-day preservation default.

> Attempt to update the atime manually so that the cache works properly.

Has this been observed to work on noatime-mounted filesystems?  It's
at worst harmless so we could merge it, but it's kind of weird.  Do
you know such precedents in other software that consumes atime?

- FChE
  
Jan Alexander Steffens \(heftig\) March 29, 2023, 9:32 p.m. UTC | #2
On Wed, Mar 29, 2023 at 10:54 PM Frank Ch. Eigler <fche@redhat.com> wrote:

> Hi -
>
> > The cache cleaning logic requires atime to be correct (strictatime) but
> > most users on Linux only have relatime or even noatime.
>
> This is not really correct: relatime is the kernel default and works
> fine with the cache.  atime values updated once a day are still plenty
> for caches with a multi-day preservation default.
>

Ah, I didn't know about the one-day threshold. So that means only
noatime is actually affected.


>
> > Attempt to update the atime manually so that the cache works properly.
>
> Has this been observed to work on noatime-mounted filesystems?  It's
> at worst harmless so we could merge it, but it's kind of weird.  Do
> you know such precedents in other software that consumes atime?
>

Yes, I have a noatime-mounted btrfs (because with snapshots, relatime
can cause entire directory trees to get copied-on-write) and with this
patch series the cache seems to work properly. Without it it is pretty
broken, immediately evicting files that were just downloaded.

The only software I know of that uses atime is mutt, although I have
never used it myself. Looking through the source of mutt and neomutt
on GitHub shows that they use the same approach:

https://github.com/muttmua/mutt/blob/1066be975f284ce6fdbb00a4e41b1738d52887d0/muttlib.c#L2204-L2212
(mutt muttlib.c:2204)

https://github.com/neomutt/neomutt/blob/d13dd3bb912d93f73dd4dd2d476e1c37d31a8422/mutt/file.c#L1062-L1075
(neomutt mutt/file.c:1062)
  

Patch

diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 1a2d7573..484dc7b3 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -618,6 +618,19 @@  path_escape (const char *src, char *dest)
   dest[q] = '\0';
 }
 
+/* Attempt to update the atime */
+static void
+update_atime (int fd)
+{
+  struct timespec tvs[2];
+
+  tvs[0].tv_sec = tvs[1].tv_sec = 0;
+  tvs[0].tv_nsec = UTIME_NOW;
+  tvs[1].tv_nsec = UTIME_OMIT;
+
+  (void) futimens (fd, tvs);  /* best effort */
+}
+
 /* Attempt to read an ELF/DWARF section with name SECTION from FD and write
    it to a separate file in the debuginfod cache.  If successful the absolute
    path of the separate file containing SECTION will be stored in USR_PATH.
@@ -761,6 +774,7 @@  extract_section (int fd, const char *section, char *fd_path, char **usr_path)
 	    *usr_path = sec_path;
 	  else
 	    free (sec_path);
+	  update_atime(fd);
 	  rc = sec_fd;
 	  goto out2;
 	}
@@ -1098,6 +1112,7 @@  debuginfod_query_server (debuginfod_client *c,
                 }
             }
           /* Success!!!! */
+          update_atime(fd);
           rc = fd;
           goto out;
         }