Skip to content

Commit 0a08238

Browse files
committed
Merge tag 'xfs-fixes-6.14-rc2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs bug fixes from Carlos Maiolino: "A few fixes for XFS, but the most notable one is: - xfs: remove xfs_buf_cache.bc_lock which has been hit by different persons including syzbot" * tag 'xfs-fixes-6.14-rc2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: remove xfs_buf_cache.bc_lock xfs: Add error handling for xfs_reflink_cancel_cow_range xfs: Propagate errors from xfs_reflink_cancel_cow_range in xfs_dax_write_iomap_end xfs: don't call remap_verify_area with sb write protection held xfs: remove an out of data comment in _xfs_buf_alloc xfs: fix the entry condition of exact EOF block allocation optimization
2 parents 2014c95 + a9ab28b commit 0a08238

File tree

6 files changed

+58
-76
lines changed

6 files changed

+58
-76
lines changed

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3563,12 +3563,12 @@ xfs_bmap_btalloc_at_eof(
35633563
int error;
35643564

35653565
/*
3566-
* If there are already extents in the file, try an exact EOF block
3567-
* allocation to extend the file as a contiguous extent. If that fails,
3568-
* or it's the first allocation in a file, just try for a stripe aligned
3569-
* allocation.
3566+
* If there are already extents in the file, and xfs_bmap_adjacent() has
3567+
* given a better blkno, try an exact EOF block allocation to extend the
3568+
* file as a contiguous extent. If that fails, or it's the first
3569+
* allocation in a file, just try for a stripe aligned allocation.
35703570
*/
3571-
if (ap->offset) {
3571+
if (ap->eof) {
35723572
xfs_extlen_t nextminlen = 0;
35733573

35743574
/*
@@ -3736,7 +3736,8 @@ xfs_bmap_btalloc_best_length(
37363736
int error;
37373737

37383738
ap->blkno = XFS_INO_TO_FSB(args->mp, ap->ip->i_ino);
3739-
xfs_bmap_adjacent(ap);
3739+
if (!xfs_bmap_adjacent(ap))
3740+
ap->eof = false;
37403741

37413742
/*
37423743
* Search for an allocation group with a single extent large enough for

fs/xfs/xfs_buf.c

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ struct kmem_cache *xfs_buf_cache;
4141
*
4242
* xfs_buf_rele:
4343
* b_lock
44-
* pag_buf_lock
45-
* lru_lock
44+
* lru_lock
4645
*
4746
* xfs_buftarg_drain_rele
4847
* lru_lock
@@ -220,23 +219,25 @@ _xfs_buf_alloc(
220219
*/
221220
flags &= ~(XBF_UNMAPPED | XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD);
222221

223-
spin_lock_init(&bp->b_lock);
222+
/*
223+
* A new buffer is held and locked by the owner. This ensures that the
224+
* buffer is owned by the caller and racing RCU lookups right after
225+
* inserting into the hash table are safe (and will have to wait for
226+
* the unlock to do anything non-trivial).
227+
*/
224228
bp->b_hold = 1;
229+
sema_init(&bp->b_sema, 0); /* held, no waiters */
230+
231+
spin_lock_init(&bp->b_lock);
225232
atomic_set(&bp->b_lru_ref, 1);
226233
init_completion(&bp->b_iowait);
227234
INIT_LIST_HEAD(&bp->b_lru);
228235
INIT_LIST_HEAD(&bp->b_list);
229236
INIT_LIST_HEAD(&bp->b_li_list);
230-
sema_init(&bp->b_sema, 0); /* held, no waiters */
231237
bp->b_target = target;
232238
bp->b_mount = target->bt_mount;
233239
bp->b_flags = flags;
234240

235-
/*
236-
* Set length and io_length to the same value initially.
237-
* I/O routines should use io_length, which will be the same in
238-
* most cases but may be reset (e.g. XFS recovery).
239-
*/
240241
error = xfs_buf_get_maps(bp, nmaps);
241242
if (error) {
242243
kmem_cache_free(xfs_buf_cache, bp);
@@ -502,7 +503,6 @@ int
502503
xfs_buf_cache_init(
503504
struct xfs_buf_cache *bch)
504505
{
505-
spin_lock_init(&bch->bc_lock);
506506
return rhashtable_init(&bch->bc_hash, &xfs_buf_hash_params);
507507
}
508508

@@ -652,28 +652,29 @@ xfs_buf_find_insert(
652652
if (error)
653653
goto out_free_buf;
654654

655-
spin_lock(&bch->bc_lock);
655+
/* The new buffer keeps the perag reference until it is freed. */
656+
new_bp->b_pag = pag;
657+
658+
rcu_read_lock();
656659
bp = rhashtable_lookup_get_insert_fast(&bch->bc_hash,
657660
&new_bp->b_rhash_head, xfs_buf_hash_params);
658661
if (IS_ERR(bp)) {
662+
rcu_read_unlock();
659663
error = PTR_ERR(bp);
660-
spin_unlock(&bch->bc_lock);
661664
goto out_free_buf;
662665
}
663666
if (bp && xfs_buf_try_hold(bp)) {
664667
/* found an existing buffer */
665-
spin_unlock(&bch->bc_lock);
668+
rcu_read_unlock();
666669
error = xfs_buf_find_lock(bp, flags);
667670
if (error)
668671
xfs_buf_rele(bp);
669672
else
670673
*bpp = bp;
671674
goto out_free_buf;
672675
}
676+
rcu_read_unlock();
673677

674-
/* The new buffer keeps the perag reference until it is freed. */
675-
new_bp->b_pag = pag;
676-
spin_unlock(&bch->bc_lock);
677678
*bpp = new_bp;
678679
return 0;
679680

@@ -1090,7 +1091,6 @@ xfs_buf_rele_cached(
10901091
}
10911092

10921093
/* we are asked to drop the last reference */
1093-
spin_lock(&bch->bc_lock);
10941094
__xfs_buf_ioacct_dec(bp);
10951095
if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
10961096
/*
@@ -1102,7 +1102,6 @@ xfs_buf_rele_cached(
11021102
bp->b_state &= ~XFS_BSTATE_DISPOSE;
11031103
else
11041104
bp->b_hold--;
1105-
spin_unlock(&bch->bc_lock);
11061105
} else {
11071106
bp->b_hold--;
11081107
/*
@@ -1120,7 +1119,6 @@ xfs_buf_rele_cached(
11201119
ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
11211120
rhashtable_remove_fast(&bch->bc_hash, &bp->b_rhash_head,
11221121
xfs_buf_hash_params);
1123-
spin_unlock(&bch->bc_lock);
11241122
if (pag)
11251123
xfs_perag_put(pag);
11261124
freebuf = true;

fs/xfs/xfs_buf.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ typedef unsigned int xfs_buf_flags_t;
8080
#define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */
8181

8282
struct xfs_buf_cache {
83-
spinlock_t bc_lock;
8483
struct rhashtable bc_hash;
8584
};
8685

fs/xfs/xfs_exchrange.c

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -329,22 +329,6 @@ xfs_exchrange_mappings(
329329
* successfully but before locks are dropped.
330330
*/
331331

332-
/* Verify that we have security clearance to perform this operation. */
333-
static int
334-
xfs_exchange_range_verify_area(
335-
struct xfs_exchrange *fxr)
336-
{
337-
int ret;
338-
339-
ret = remap_verify_area(fxr->file1, fxr->file1_offset, fxr->length,
340-
true);
341-
if (ret)
342-
return ret;
343-
344-
return remap_verify_area(fxr->file2, fxr->file2_offset, fxr->length,
345-
true);
346-
}
347-
348332
/*
349333
* Performs necessary checks before doing a range exchange, having stabilized
350334
* mutable inode attributes via i_rwsem.
@@ -355,11 +339,13 @@ xfs_exchange_range_checks(
355339
unsigned int alloc_unit)
356340
{
357341
struct inode *inode1 = file_inode(fxr->file1);
342+
loff_t size1 = i_size_read(inode1);
358343
struct inode *inode2 = file_inode(fxr->file2);
344+
loff_t size2 = i_size_read(inode2);
359345
uint64_t allocmask = alloc_unit - 1;
360346
int64_t test_len;
361347
uint64_t blen;
362-
loff_t size1, size2, tmp;
348+
loff_t tmp;
363349
int error;
364350

365351
/* Don't touch certain kinds of inodes */
@@ -368,24 +354,25 @@ xfs_exchange_range_checks(
368354
if (IS_SWAPFILE(inode1) || IS_SWAPFILE(inode2))
369355
return -ETXTBSY;
370356

371-
size1 = i_size_read(inode1);
372-
size2 = i_size_read(inode2);
373-
374357
/* Ranges cannot start after EOF. */
375358
if (fxr->file1_offset > size1 || fxr->file2_offset > size2)
376359
return -EINVAL;
377360

378-
/*
379-
* If the caller said to exchange to EOF, we set the length of the
380-
* request large enough to cover everything to the end of both files.
381-
*/
382361
if (fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) {
362+
/*
363+
* If the caller said to exchange to EOF, we set the length of
364+
* the request large enough to cover everything to the end of
365+
* both files.
366+
*/
383367
fxr->length = max_t(int64_t, size1 - fxr->file1_offset,
384368
size2 - fxr->file2_offset);
385-
386-
error = xfs_exchange_range_verify_area(fxr);
387-
if (error)
388-
return error;
369+
} else {
370+
/*
371+
* Otherwise we require both ranges to end within EOF.
372+
*/
373+
if (fxr->file1_offset + fxr->length > size1 ||
374+
fxr->file2_offset + fxr->length > size2)
375+
return -EINVAL;
389376
}
390377

391378
/*
@@ -401,15 +388,6 @@ xfs_exchange_range_checks(
401388
check_add_overflow(fxr->file2_offset, fxr->length, &tmp))
402389
return -EINVAL;
403390

404-
/*
405-
* We require both ranges to end within EOF, unless we're exchanging
406-
* to EOF.
407-
*/
408-
if (!(fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) &&
409-
(fxr->file1_offset + fxr->length > size1 ||
410-
fxr->file2_offset + fxr->length > size2))
411-
return -EINVAL;
412-
413391
/*
414392
* Make sure we don't hit any file size limits. If we hit any size
415393
* limits such that test_length was adjusted, we abort the whole
@@ -747,6 +725,7 @@ xfs_exchange_range(
747725
{
748726
struct inode *inode1 = file_inode(fxr->file1);
749727
struct inode *inode2 = file_inode(fxr->file2);
728+
loff_t check_len = fxr->length;
750729
int ret;
751730

752731
BUILD_BUG_ON(XFS_EXCHANGE_RANGE_ALL_FLAGS &
@@ -779,14 +758,18 @@ xfs_exchange_range(
779758
return -EBADF;
780759

781760
/*
782-
* If we're not exchanging to EOF, we can check the areas before
783-
* stabilizing both files' i_size.
761+
* If we're exchanging to EOF we can't calculate the length until taking
762+
* the iolock. Pass a 0 length to remap_verify_area similar to the
763+
* FICLONE and FICLONERANGE ioctls that support cloning to EOF as well.
784764
*/
785-
if (!(fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF)) {
786-
ret = xfs_exchange_range_verify_area(fxr);
787-
if (ret)
788-
return ret;
789-
}
765+
if (fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF)
766+
check_len = 0;
767+
ret = remap_verify_area(fxr->file1, fxr->file1_offset, check_len, true);
768+
if (ret)
769+
return ret;
770+
ret = remap_verify_area(fxr->file2, fxr->file2_offset, check_len, true);
771+
if (ret)
772+
return ret;
790773

791774
/* Update cmtime if the fd/inode don't forbid it. */
792775
if (!(fxr->file1->f_mode & FMODE_NOCMTIME) && !IS_NOCMTIME(inode1))

fs/xfs/xfs_inode.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,8 +1404,11 @@ xfs_inactive(
14041404
goto out;
14051405

14061406
/* Try to clean out the cow blocks if there are any. */
1407-
if (xfs_inode_has_cow_data(ip))
1408-
xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true);
1407+
if (xfs_inode_has_cow_data(ip)) {
1408+
error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true);
1409+
if (error)
1410+
goto out;
1411+
}
14091412

14101413
if (VFS_I(ip)->i_nlink != 0) {
14111414
/*

fs/xfs/xfs_iomap.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -976,10 +976,8 @@ xfs_dax_write_iomap_end(
976976
if (!xfs_is_cow_inode(ip))
977977
return 0;
978978

979-
if (!written) {
980-
xfs_reflink_cancel_cow_range(ip, pos, length, true);
981-
return 0;
982-
}
979+
if (!written)
980+
return xfs_reflink_cancel_cow_range(ip, pos, length, true);
983981

984982
return xfs_reflink_end_cow(ip, pos, written);
985983
}

0 commit comments

Comments
 (0)