]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: Fix bch2_seek_hole() locking
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 27 Mar 2025 17:34:13 +0000 (13:34 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Fri, 28 Mar 2025 15:30:14 +0000 (11:30 -0400)
We can't call bch2_seek_pagecache_hole(), and block on page locks, with
btree locks held.

This is easily fixed because we're at the end of the transaction - we
can just unlock, we don't need a drop_locks_do().

Reported-by: https://github.com/nagalun
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fs-io.c

index 717e7b94c66f87a9bd3ea10f449940886bbac2ce..cc366786f0f9a81b52b787cf9af0e15d50c4a43a 100644 (file)
@@ -999,17 +999,19 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
                                   POS(inode->v.i_ino, offset >> 9),
                                   POS(inode->v.i_ino, U64_MAX),
                                   inum.subvol, BTREE_ITER_slots, k, ({
-                       if (k.k->p.inode != inode->v.i_ino) {
+                       if (k.k->p.inode != inode->v.i_ino ||
+                           !bkey_extent_is_data(k.k)) {
+                               loff_t start_offset = k.k->p.inode == inode->v.i_ino
+                                       ? max(offset, bkey_start_offset(k.k) << 9)
+                                       : offset;
+                               loff_t end_offset = k.k->p.inode == inode->v.i_ino
+                                       ? MAX_LFS_FILESIZE
+                                       : k.k->p.offset << 9;
+
+                               bch2_trans_unlock(trans);
                                next_hole = bch2_seek_pagecache_hole(&inode->v,
-                                               offset, MAX_LFS_FILESIZE, 0, false);
+                                               start_offset, end_offset, 0, false);
                                break;
-                       } else if (!bkey_extent_is_data(k.k)) {
-                               next_hole = bch2_seek_pagecache_hole(&inode->v,
-                                               max(offset, bkey_start_offset(k.k) << 9),
-                                               k.k->p.offset << 9, 0, false);
-
-                               if (next_hole < k.k->p.offset << 9)
-                                       break;
                        } else {
                                offset = max(offset, bkey_start_offset(k.k) << 9);
                        }