Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "Add and use folio_next_pos()"

Matthew Wilcox (Oracle) <willy@infradead.org> says:

It's relatively common in filesystems to want to know the end of the
current folio we're looking at. So common in fact that btrfs has its own
helper for that. Lift that helper to filemap and use it everywhere that
I've noticed it could be used. This actually fixes a long-standing bug
in ocfs2 on 32-bit systems with files larger than 2GiB. Presumably this
is not a common configuration, but I've marked it for backport anyway.

The other filesystems are all fine; none of them have a bug, they're
just mildly inefficient. I think this should all go in via Christian's
tree, ideally with acks from the various fs maintainers (cc'd on their
individual patches).

* patches from https://patch.msgid.link/20251024170822.1427218-1-willy@infradead.org:
mm: Use folio_next_pos()
xfs: Use folio_next_pos()
netfs: Use folio_next_pos()
iomap: Use folio_next_pos()
gfs2: Use folio_next_pos()
f2fs: Use folio_next_pos()
ext4: Use folio_next_pos()
buffer: Use folio_next_pos()
btrfs: Use folio_next_pos()
filemap: Add folio_next_pos()

Link: https://patch.msgid.link/20251024170822.1427218-1-willy@infradead.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

+59 -52
+2 -2
fs/btrfs/compression.h
··· 85 85 { 86 86 /* @cur must be inside the folio. */ 87 87 ASSERT(folio_pos(folio) <= cur); 88 - ASSERT(cur < folio_end(folio)); 89 - return min(range_end, folio_end(folio)) - cur; 88 + ASSERT(cur < folio_next_pos(folio)); 89 + return umin(range_end, folio_next_pos(folio)) - cur; 90 90 } 91 91 92 92 int btrfs_alloc_compress_wsm(struct btrfs_fs_info *fs_info);
+4 -3
fs/btrfs/defrag.c
··· 886 886 } 887 887 888 888 lock_start = folio_pos(folio); 889 - lock_end = folio_end(folio) - 1; 889 + lock_end = folio_next_pos(folio) - 1; 890 890 /* Wait for any existing ordered extent in the range */ 891 891 while (1) { 892 892 struct btrfs_ordered_extent *ordered; ··· 1178 1178 1179 1179 if (!folio) 1180 1180 break; 1181 - if (start >= folio_end(folio) || start + len <= folio_pos(folio)) 1181 + if (start >= folio_next_pos(folio) || 1182 + start + len <= folio_pos(folio)) 1182 1183 continue; 1183 1184 btrfs_folio_clamp_clear_checked(fs_info, folio, start, len); 1184 1185 btrfs_folio_clamp_set_dirty(fs_info, folio, start, len); ··· 1220 1219 folios[i] = NULL; 1221 1220 goto free_folios; 1222 1221 } 1223 - cur = folio_end(folios[i]); 1222 + cur = folio_next_pos(folios[i]); 1224 1223 } 1225 1224 for (int i = 0; i < nr_pages; i++) { 1226 1225 if (!folios[i])
+8 -8
fs/btrfs/extent_io.c
··· 333 333 goto out; 334 334 } 335 335 range_start = max_t(u64, folio_pos(folio), start); 336 - range_len = min_t(u64, folio_end(folio), end + 1) - range_start; 336 + range_len = min_t(u64, folio_next_pos(folio), end + 1) - range_start; 337 337 btrfs_folio_set_lock(fs_info, folio, range_start, range_len); 338 338 339 339 processed_end = range_start + range_len - 1; ··· 387 387 ASSERT(orig_end > orig_start); 388 388 389 389 /* The range should at least cover part of the folio */ 390 - ASSERT(!(orig_start >= folio_end(locked_folio) || 390 + ASSERT(!(orig_start >= folio_next_pos(locked_folio) || 391 391 orig_end <= folio_pos(locked_folio))); 392 392 again: 393 393 /* step one, find a bunch of delalloc bytes starting at start */ ··· 493 493 struct btrfs_fs_info *fs_info = folio_to_fs_info(folio); 494 494 495 495 ASSERT(folio_pos(folio) <= start && 496 - start + len <= folio_end(folio)); 496 + start + len <= folio_next_pos(folio)); 497 497 498 498 if (uptodate && btrfs_verify_folio(folio, start, len)) 499 499 btrfs_folio_set_uptodate(fs_info, folio, start, len); ··· 1201 1201 * finished our folio read and unlocked the folio. 1202 1202 */ 1203 1203 if (btrfs_folio_test_dirty(fs_info, folio, cur, blocksize)) { 1204 - u64 range_len = min(folio_end(folio), 1204 + u64 range_len = umin(folio_next_pos(folio), 1205 1205 ordered->file_offset + ordered->num_bytes) - cur; 1206 1206 1207 1207 ret = true; ··· 1223 1223 * So we return true and update @next_ret to the OE/folio boundary. 1224 1224 */ 1225 1225 if (btrfs_folio_test_uptodate(fs_info, folio, cur, blocksize)) { 1226 - u64 range_len = min(folio_end(folio), 1226 + u64 range_len = umin(folio_next_pos(folio), 1227 1227 ordered->file_offset + ordered->num_bytes) - cur; 1228 1228 1229 1229 /* ··· 2215 2215 for (int i = 0; i < num_extent_folios(eb); i++) { 2216 2216 struct folio *folio = eb->folios[i]; 2217 2217 u64 range_start = max_t(u64, eb->start, folio_pos(folio)); 2218 - u32 range_len = min_t(u64, folio_end(folio), 2218 + u32 range_len = min_t(u64, folio_next_pos(folio), 2219 2219 eb->start + eb->len) - range_start; 2220 2220 2221 2221 folio_lock(folio); ··· 2619 2619 continue; 2620 2620 } 2621 2621 2622 - cur_end = min_t(u64, folio_end(folio) - 1, end); 2622 + cur_end = min_t(u64, folio_next_pos(folio) - 1, end); 2623 2623 cur_len = cur_end + 1 - cur; 2624 2624 2625 2625 ASSERT(folio_test_locked(folio)); ··· 3860 3860 for (int i = 0; i < num_extent_folios(eb); i++) { 3861 3861 struct folio *folio = eb->folios[i]; 3862 3862 u64 range_start = max_t(u64, eb->start, folio_pos(folio)); 3863 - u32 range_len = min_t(u64, folio_end(folio), 3863 + u32 range_len = min_t(u64, folio_next_pos(folio), 3864 3864 eb->start + eb->len) - range_start; 3865 3865 3866 3866 bio_add_folio_nofail(&bbio->bio, folio, range_len,
+5 -4
fs/btrfs/file.c
··· 89 89 num_bytes = round_up(write_bytes + pos - start_pos, 90 90 fs_info->sectorsize); 91 91 ASSERT(num_bytes <= U32_MAX); 92 - ASSERT(folio_pos(folio) <= pos && folio_end(folio) >= pos + write_bytes); 92 + ASSERT(folio_pos(folio) <= pos && 93 + folio_next_pos(folio) >= pos + write_bytes); 93 94 94 95 end_of_last_block = start_pos + num_bytes - 1; 95 96 ··· 800 799 u64 len) 801 800 { 802 801 u64 clamp_start = max_t(u64, pos, folio_pos(folio)); 803 - u64 clamp_end = min_t(u64, pos + len, folio_end(folio)); 802 + u64 clamp_end = min_t(u64, pos + len, folio_next_pos(folio)); 804 803 const u32 blocksize = inode_to_fs_info(inode)->sectorsize; 805 804 int ret = 0; 806 805 ··· 1255 1254 * The reserved range goes beyond the current folio, shrink the reserved 1256 1255 * space to the folio boundary. 1257 1256 */ 1258 - if (reserved_start + reserved_len > folio_end(folio)) { 1259 - const u64 last_block = folio_end(folio); 1257 + if (reserved_start + reserved_len > folio_next_pos(folio)) { 1258 + const u64 last_block = folio_next_pos(folio); 1260 1259 1261 1260 shrink_reserved_space(inode, *data_reserved, reserved_start, 1262 1261 reserved_len, last_block - reserved_start,
+6 -5
fs/btrfs/inode.c
··· 409 409 continue; 410 410 } 411 411 412 - index = folio_end(folio) >> PAGE_SHIFT; 412 + index = folio_next_index(folio); 413 413 /* 414 414 * Here we just clear all Ordered bits for every page in the 415 415 * range, then btrfs_mark_ordered_io_finished() will handle ··· 2336 2336 * The range must cover part of the @locked_folio, or a return of 1 2337 2337 * can confuse the caller. 2338 2338 */ 2339 - ASSERT(!(end <= folio_pos(locked_folio) || start >= folio_end(locked_folio))); 2339 + ASSERT(!(end <= folio_pos(locked_folio) || 2340 + start >= folio_next_pos(locked_folio))); 2340 2341 2341 2342 if (should_nocow(inode, start, end)) { 2342 2343 ret = run_delalloc_nocow(inode, locked_folio, start, end); ··· 2744 2743 struct btrfs_inode *inode = fixup->inode; 2745 2744 struct btrfs_fs_info *fs_info = inode->root->fs_info; 2746 2745 u64 page_start = folio_pos(folio); 2747 - u64 page_end = folio_end(folio) - 1; 2746 + u64 page_end = folio_next_pos(folio) - 1; 2748 2747 int ret = 0; 2749 2748 bool free_delalloc_space = true; 2750 2749 ··· 4856 4855 */ 4857 4856 4858 4857 zero_start = max_t(u64, folio_pos(folio), start); 4859 - zero_end = folio_end(folio); 4858 + zero_end = folio_next_pos(folio); 4860 4859 folio_zero_range(folio, zero_start - folio_pos(folio), 4861 4860 zero_end - zero_start); 4862 4861 ··· 5039 5038 * not reach disk, it still affects our page caches. 5040 5039 */ 5041 5040 zero_start = max_t(u64, folio_pos(folio), start); 5042 - zero_end = min_t(u64, folio_end(folio) - 1, end); 5041 + zero_end = min_t(u64, folio_next_pos(folio) - 1, end); 5043 5042 } else { 5044 5043 zero_start = max_t(u64, block_start, start); 5045 5044 zero_end = min_t(u64, block_end, end);
-5
fs/btrfs/misc.h
··· 209 209 return (found_set == start + nbits); 210 210 } 211 211 212 - static inline u64 folio_end(struct folio *folio) 213 - { 214 - return folio_pos(folio) + folio_size(folio); 215 - } 216 - 217 212 #endif
+1 -1
fs/btrfs/ordered-data.c
··· 359 359 if (folio) { 360 360 ASSERT(folio->mapping); 361 361 ASSERT(folio_pos(folio) <= file_offset); 362 - ASSERT(file_offset + len <= folio_end(folio)); 362 + ASSERT(file_offset + len <= folio_next_pos(folio)); 363 363 364 364 /* 365 365 * Ordered flag indicates whether we still have
+3 -2
fs/btrfs/subpage.c
··· 186 186 * unmapped page like dummy extent buffer pages. 187 187 */ 188 188 if (folio->mapping) 189 - ASSERT(folio_pos(folio) <= start && start + len <= folio_end(folio), 189 + ASSERT(folio_pos(folio) <= start && 190 + start + len <= folio_next_pos(folio), 190 191 "start=%llu len=%u folio_pos=%llu folio_size=%zu", 191 192 start, len, folio_pos(folio), folio_size(folio)); 192 193 } ··· 218 217 if (folio_pos(folio) >= orig_start + orig_len) 219 218 *len = 0; 220 219 else 221 - *len = min_t(u64, folio_end(folio), orig_start + orig_len) - *start; 220 + *len = min_t(u64, folio_next_pos(folio), orig_start + orig_len) - *start; 222 221 } 223 222 224 223 static bool btrfs_subpage_end_and_test_lock(const struct btrfs_fs_info *fs_info,
+1 -1
fs/buffer.c
··· 2732 2732 loff_t i_size = i_size_read(inode); 2733 2733 2734 2734 /* Is the folio fully inside i_size? */ 2735 - if (folio_pos(folio) + folio_size(folio) <= i_size) 2735 + if (folio_next_pos(folio) <= i_size) 2736 2736 return __block_write_full_folio(inode, folio, get_block, wbc); 2737 2737 2738 2738 /* Is the folio fully outside i_size? (truncate in progress) */
+5 -5
fs/ext4/inode.c
··· 1319 1319 if (IS_ERR(folio)) 1320 1320 return PTR_ERR(folio); 1321 1321 1322 - if (pos + len > folio_pos(folio) + folio_size(folio)) 1323 - len = folio_pos(folio) + folio_size(folio) - pos; 1322 + if (len > folio_next_pos(folio) - pos) 1323 + len = folio_next_pos(folio) - pos; 1324 1324 1325 1325 from = offset_in_folio(folio, pos); 1326 1326 to = from + len; ··· 2704 2704 2705 2705 if (mpd->map.m_len == 0) 2706 2706 mpd->start_pos = folio_pos(folio); 2707 - mpd->next_pos = folio_pos(folio) + folio_size(folio); 2707 + mpd->next_pos = folio_next_pos(folio); 2708 2708 /* 2709 2709 * Writeout when we cannot modify metadata is simple. 2710 2710 * Just submit the page. For data=journal mode we ··· 3146 3146 if (IS_ERR(folio)) 3147 3147 return PTR_ERR(folio); 3148 3148 3149 - if (pos + len > folio_pos(folio) + folio_size(folio)) 3150 - len = folio_pos(folio) + folio_size(folio) - pos; 3149 + if (len > folio_next_pos(folio) - pos) 3150 + len = folio_next_pos(folio) - pos; 3151 3151 3152 3152 ret = ext4_block_write_begin(NULL, folio, pos, len, 3153 3153 ext4_da_get_block_prep);
+1 -1
fs/f2fs/compress.c
··· 1329 1329 } 1330 1330 1331 1331 folio = page_folio(cc->rpages[last_index]); 1332 - psize = folio_pos(folio) + folio_size(folio); 1332 + psize = folio_next_pos(folio); 1333 1333 1334 1334 err = f2fs_get_node_info(fio.sbi, dn.nid, &ni, false); 1335 1335 if (err)
+1 -2
fs/gfs2/aops.c
··· 81 81 * the page size, the remaining memory is zeroed when mapped, and 82 82 * writes to that region are not written out to the file." 83 83 */ 84 - if (folio_pos(folio) < i_size && 85 - i_size < folio_pos(folio) + folio_size(folio)) 84 + if (folio_pos(folio) < i_size && i_size < folio_next_pos(folio)) 86 85 folio_zero_segment(folio, offset_in_folio(folio, i_size), 87 86 folio_size(folio)); 88 87
+4 -6
fs/iomap/buffered-io.c
··· 707 707 * are not changing pagecache contents. 708 708 */ 709 709 if (!(iter->flags & IOMAP_UNSHARE) && pos <= folio_pos(folio) && 710 - pos + len >= folio_pos(folio) + folio_size(folio)) 710 + pos + len >= folio_next_pos(folio)) 711 711 return 0; 712 712 713 713 ifs = ifs_alloc(iter->inode, folio, iter->flags); ··· 1097 1097 if (!ifs) 1098 1098 return; 1099 1099 1100 - last_byte = min_t(loff_t, end_byte - 1, 1101 - folio_pos(folio) + folio_size(folio) - 1); 1100 + last_byte = min_t(loff_t, end_byte - 1, folio_next_pos(folio) - 1); 1102 1101 first_blk = offset_in_folio(folio, start_byte) >> blkbits; 1103 1102 last_blk = offset_in_folio(folio, last_byte) >> blkbits; 1104 1103 for (i = first_blk; i <= last_blk; i++) { ··· 1128 1129 * Make sure the next punch start is correctly bound to 1129 1130 * the end of this data range, not the end of the folio. 1130 1131 */ 1131 - *punch_start_byte = min_t(loff_t, end_byte, 1132 - folio_pos(folio) + folio_size(folio)); 1132 + *punch_start_byte = min_t(loff_t, end_byte, folio_next_pos(folio)); 1133 1133 } 1134 1134 1135 1135 /* ··· 1168 1170 start_byte, end_byte, iomap, punch); 1169 1171 1170 1172 /* move offset to start of next folio in range */ 1171 - start_byte = folio_pos(folio) + folio_size(folio); 1173 + start_byte = folio_next_pos(folio); 1172 1174 folio_unlock(folio); 1173 1175 folio_put(folio); 1174 1176 }
+1 -1
fs/netfs/buffered_write.c
··· 535 535 folio_unlock(folio); 536 536 err = filemap_fdatawrite_range(mapping, 537 537 folio_pos(folio), 538 - folio_pos(folio) + folio_size(folio)); 538 + folio_next_pos(folio)); 539 539 switch (err) { 540 540 case 0: 541 541 ret = VM_FAULT_RETRY;
+1 -1
fs/netfs/misc.c
··· 298 298 if (folio_test_dirty(folio)) 299 299 return false; 300 300 301 - end = umin(folio_pos(folio) + folio_size(folio), i_size_read(&ctx->inode)); 301 + end = umin(folio_next_pos(folio), i_size_read(&ctx->inode)); 302 302 if (end > ctx->zero_point) 303 303 ctx->zero_point = end; 304 304
+1 -1
fs/ocfs2/alloc.c
··· 6892 6892 ocfs2_map_and_dirty_folio(inode, handle, from, to, folio, 1, 6893 6893 &phys); 6894 6894 6895 - start = folio_next_index(folio) << PAGE_SHIFT; 6895 + start = folio_next_pos(folio); 6896 6896 } 6897 6897 out: 6898 6898 if (folios)
+1 -1
fs/xfs/scrub/xfarray.c
··· 834 834 si->first_folio_idx = xfarray_idx(si->array, 835 835 folio_pos(si->folio) + si->array->obj_size - 1); 836 836 837 - next_pos = folio_pos(si->folio) + folio_size(si->folio); 837 + next_pos = folio_next_pos(si->folio); 838 838 si->last_folio_idx = xfarray_idx(si->array, next_pos - 1); 839 839 if (xfarray_pos(si->array, si->last_folio_idx + 1) > next_pos) 840 840 si->last_folio_idx--;
+1 -1
fs/xfs/xfs_aops.c
··· 271 271 * folio itself and not the start offset that is passed in. 272 272 */ 273 273 xfs_bmap_punch_delalloc_range(ip, XFS_DATA_FORK, pos, 274 - folio_pos(folio) + folio_size(folio), NULL); 274 + folio_next_pos(folio), NULL); 275 275 } 276 276 277 277 /*
+11
include/linux/pagemap.h
··· 942 942 } 943 943 944 944 /** 945 + * folio_next_pos - Get the file position of the next folio. 946 + * @folio: The current folio. 947 + * 948 + * Return: The position of the folio which follows this folio in the file. 949 + */ 950 + static inline loff_t folio_next_pos(const struct folio *folio) 951 + { 952 + return (loff_t)folio_next_index(folio) << PAGE_SHIFT; 953 + } 954 + 955 + /** 945 956 * folio_file_page - The page for a particular index. 946 957 * @folio: The folio which contains this index. 947 958 * @index: The index we want to look up.
+1 -1
mm/shmem.c
··· 1133 1133 same_folio = (lstart >> PAGE_SHIFT) == (lend >> PAGE_SHIFT); 1134 1134 folio = shmem_get_partial_folio(inode, lstart >> PAGE_SHIFT); 1135 1135 if (folio) { 1136 - same_folio = lend < folio_pos(folio) + folio_size(folio); 1136 + same_folio = lend < folio_next_pos(folio); 1137 1137 folio_mark_dirty(folio); 1138 1138 if (!truncate_inode_partial_folio(folio, lstart, lend)) { 1139 1139 start = folio_next_index(folio);
+1 -1
mm/truncate.c
··· 387 387 same_folio = (lstart >> PAGE_SHIFT) == (lend >> PAGE_SHIFT); 388 388 folio = __filemap_get_folio(mapping, lstart >> PAGE_SHIFT, FGP_LOCK, 0); 389 389 if (!IS_ERR(folio)) { 390 - same_folio = lend < folio_pos(folio) + folio_size(folio); 390 + same_folio = lend < folio_next_pos(folio); 391 391 if (!truncate_inode_partial_folio(folio, lstart, lend)) { 392 392 start = folio_next_index(folio); 393 393 if (same_folio)