]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
lib/freader: support reading more than 2 folios
authorMykyta Yatsenko <yatsenko@meta.com>
Sun, 26 Oct 2025 20:38:47 +0000 (20:38 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 27 Oct 2025 16:56:27 +0000 (09:56 -0700)
freader_fetch currently reads from at most two folios. When a read spans
into a third folio, the overflow bytes are copied adjacent to the second
folio’s data instead of being handled as a separate folio.
This patch modifies fetch algorithm to support reading from many folios.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Reviewed-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20251026203853.135105-5-mykyta.yatsenko5@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
lib/buildid.c

index df06e492810d188d665c4895912f13a076893b42..aaf61dfc091958bdb3ccab945a84edc660c516f6 100644 (file)
@@ -108,18 +108,21 @@ const void *freader_fetch(struct freader *r, loff_t file_off, size_t sz)
         */
        folio_sz = folio_size(r->folio);
        if (file_off + sz > r->folio_off + folio_sz) {
-               int part_sz = r->folio_off + folio_sz - file_off;
-
-               /* copy the part that resides in the current folio */
-               memcpy(r->buf, r->addr + (file_off - r->folio_off), part_sz);
-
-               /* fetch next folio */
-               r->err = freader_get_folio(r, r->folio_off + folio_sz);
-               if (r->err)
-                       return NULL;
-
-               /* copy the rest of requested data */
-               memcpy(r->buf + part_sz, r->addr, sz - part_sz);
+               u64 part_sz = r->folio_off + folio_sz - file_off, off;
+
+               memcpy(r->buf, r->addr + file_off - r->folio_off, part_sz);
+               off = part_sz;
+
+               while (off < sz) {
+                       /* fetch next folio */
+                       r->err = freader_get_folio(r, r->folio_off + folio_sz);
+                       if (r->err)
+                               return NULL;
+                       folio_sz = folio_size(r->folio);
+                       part_sz = min_t(u64, sz - off, folio_sz);
+                       memcpy(r->buf + off, r->addr, part_sz);
+                       off += part_sz;
+               }
 
                return r->buf;
        }