]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
orangefs_readahead: don't overflow the bufmap slot.
authorMike Marshall <hubcap@omnibond.com>
Thu, 2 Apr 2026 22:07:25 +0000 (18:07 -0400)
committerMike Marshall <hubcap@omnibond.com>
Tue, 7 Apr 2026 15:26:48 +0000 (11:26 -0400)
generic/340 showed that this caller of wait_for_direct_io was
sometimes asking for more than a bufmap slot could hold. This splits
the calls up if needed.

Signed-off-by: Mike Marshall <hubcap@omnibond.com>
fs/orangefs/inode.c

index 2d4710d0e05e195855186c6bedd211bc419abc36..af7c9432e141be140d35ccd733a03f8e281b5d27 100644 (file)
@@ -224,6 +224,8 @@ static void orangefs_readahead(struct readahead_control *rac)
        loff_t new_start = readahead_pos(rac);
        int ret;
        size_t new_len = 0;
+       size_t this_size;
+       size_t remaining;
 
        loff_t bytes_remaining = inode->i_size - readahead_pos(rac);
        loff_t pages_remaining = bytes_remaining / PAGE_SIZE;
@@ -239,17 +241,33 @@ static void orangefs_readahead(struct readahead_control *rac)
        offset = readahead_pos(rac);
        i_pages = &rac->mapping->i_pages;
 
-       iov_iter_xarray(&iter, ITER_DEST, i_pages, offset, readahead_length(rac));
+       iov_iter_xarray(&iter, ITER_DEST, i_pages,
+                               offset, readahead_length(rac));
 
-       /* read in the pages. */
-       if ((ret = wait_for_direct_io(ORANGEFS_IO_READ, inode,
-                       &offset, &iter, readahead_length(rac),
-                       inode->i_size, NULL, NULL, rac->file)) < 0)
-               gossip_debug(GOSSIP_FILE_DEBUG,
-                       "%s: wait_for_direct_io failed. \n", __func__);
-       else
-               ret = 0;
+       remaining = readahead_length(rac);
+       while (remaining) {
+               if (remaining > 4194304)
+                       this_size = 4194304;
+               else
+                       this_size = remaining;
+
+               /* read in the pages. */
+               if ((ret = wait_for_direct_io(ORANGEFS_IO_READ, inode,
+                               &offset, &iter, this_size,
+                               inode->i_size, NULL, NULL, rac->file)) < 0) {
+                       gossip_debug(GOSSIP_FILE_DEBUG,
+                               "%s: wait_for_direct_io failed. :%d: \n",
+                               __func__, ret);
+                       goto cleanup;
+               } else {
+                       ret = 0;
+               }
+
+               remaining -= this_size;
+               offset += this_size;
+       }
 
+cleanup:
        /* clean up. */
        while ((folio = readahead_folio(rac))) {
                if (!ret)