Skip to content

Commit c85af72

Browse files
committed
Merge branch 'block-7.1' into for-next
* block-7.1: ublk: avoid unpinning pages under maple tree spinlock ublk: refactor common helper ublk_shmem_remove_ranges() ublk: fix maple tree lockdep warning in ublk_buf_cleanup selftests: ublk: add ublk auto integrity test selftests: ublk: enable test_integrity_02.sh on fio 3.42 selftests: ublk: remove unused argument to _cleanup
2 parents f53ce51 + 309e02d commit c85af72

53 files changed

Lines changed: 232 additions & 98 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

drivers/block/ublk_drv.c

Lines changed: 70 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5421,39 +5421,88 @@ static int ublk_ctrl_reg_buf(struct ublk_device *ub,
54215421
return ret;
54225422
}
54235423

5424-
static int __ublk_ctrl_unreg_buf(struct ublk_device *ub, int buf_index)
5424+
static void ublk_unpin_range_pages(unsigned long base_pfn,
5425+
unsigned long nr_pages)
5426+
{
5427+
#define UBLK_UNPIN_BATCH 32
5428+
struct page *pages[UBLK_UNPIN_BATCH];
5429+
unsigned long off;
5430+
5431+
for (off = 0; off < nr_pages; ) {
5432+
unsigned int batch = min_t(unsigned long,
5433+
nr_pages - off, UBLK_UNPIN_BATCH);
5434+
unsigned int j;
5435+
5436+
for (j = 0; j < batch; j++)
5437+
pages[j] = pfn_to_page(base_pfn + off + j);
5438+
unpin_user_pages(pages, batch);
5439+
off += batch;
5440+
}
5441+
}
5442+
5443+
/*
5444+
* Inner loop: erase up to UBLK_REMOVE_BATCH matching ranges under
5445+
* mas_lock, collecting them into an xarray. Then drop the lock and
5446+
* unpin pages + free ranges outside spinlock context.
5447+
*
5448+
* Returns true if the tree walk completed, false if more ranges remain.
5449+
* Xarray key is the base PFN, value encodes nr_pages via xa_mk_value().
5450+
*/
5451+
#define UBLK_REMOVE_BATCH 64
5452+
5453+
static bool __ublk_shmem_remove_ranges(struct ublk_device *ub,
5454+
int buf_index, int *ret)
54255455
{
54265456
MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX);
54275457
struct ublk_buf_range *range;
5428-
struct page *pages[32];
5429-
int ret = -ENOENT;
5458+
struct xarray to_unpin;
5459+
unsigned long idx;
5460+
unsigned int count = 0;
5461+
bool done = false;
5462+
void *entry;
5463+
5464+
xa_init(&to_unpin);
54305465

54315466
mas_lock(&mas);
54325467
mas_for_each(&mas, range, ULONG_MAX) {
5433-
unsigned long base, nr, off;
5468+
unsigned long nr;
54345469

5435-
if (range->buf_index != buf_index)
5470+
if (buf_index >= 0 && range->buf_index != buf_index)
54365471
continue;
54375472

5438-
ret = 0;
5439-
base = mas.index;
5440-
nr = mas.last - base + 1;
5473+
*ret = 0;
5474+
nr = mas.last - mas.index + 1;
5475+
if (xa_err(xa_store(&to_unpin, mas.index,
5476+
xa_mk_value(nr), GFP_ATOMIC)))
5477+
goto unlock;
54415478
mas_erase(&mas);
5442-
5443-
for (off = 0; off < nr; ) {
5444-
unsigned int batch = min_t(unsigned long,
5445-
nr - off, 32);
5446-
unsigned int j;
5447-
5448-
for (j = 0; j < batch; j++)
5449-
pages[j] = pfn_to_page(base + off + j);
5450-
unpin_user_pages(pages, batch);
5451-
off += batch;
5452-
}
54535479
kfree(range);
5480+
if (++count >= UBLK_REMOVE_BATCH)
5481+
goto unlock;
54545482
}
5483+
done = true;
5484+
unlock:
54555485
mas_unlock(&mas);
54565486

5487+
xa_for_each(&to_unpin, idx, entry)
5488+
ublk_unpin_range_pages(idx, xa_to_value(entry));
5489+
xa_destroy(&to_unpin);
5490+
5491+
return done;
5492+
}
5493+
5494+
/*
5495+
* Remove ranges from the maple tree matching buf_index, unpin pages
5496+
* and free range structs. If buf_index < 0, remove all ranges.
5497+
* Processes ranges in batches to avoid holding the maple tree spinlock
5498+
* across potentially expensive page unpinning.
5499+
*/
5500+
static int ublk_shmem_remove_ranges(struct ublk_device *ub, int buf_index)
5501+
{
5502+
int ret = -ENOENT;
5503+
5504+
while (!__ublk_shmem_remove_ranges(ub, buf_index, &ret))
5505+
cond_resched();
54575506
return ret;
54585507
}
54595508

@@ -5472,7 +5521,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54725521

54735522
memflags = ublk_lock_buf_tree(ub);
54745523

5475-
ret = __ublk_ctrl_unreg_buf(ub, index);
5524+
ret = ublk_shmem_remove_ranges(ub, index);
54765525
if (!ret)
54775526
ida_free(&ub->buf_ida, index);
54785527

@@ -5482,27 +5531,7 @@ static int ublk_ctrl_unreg_buf(struct ublk_device *ub,
54825531

54835532
static void ublk_buf_cleanup(struct ublk_device *ub)
54845533
{
5485-
MA_STATE(mas, &ub->buf_tree, 0, ULONG_MAX);
5486-
struct ublk_buf_range *range;
5487-
struct page *pages[32];
5488-
5489-
mas_for_each(&mas, range, ULONG_MAX) {
5490-
unsigned long base = mas.index;
5491-
unsigned long nr = mas.last - base + 1;
5492-
unsigned long off;
5493-
5494-
for (off = 0; off < nr; ) {
5495-
unsigned int batch = min_t(unsigned long,
5496-
nr - off, 32);
5497-
unsigned int j;
5498-
5499-
for (j = 0; j < batch; j++)
5500-
pages[j] = pfn_to_page(base + off + j);
5501-
unpin_user_pages(pages, batch);
5502-
off += batch;
5503-
}
5504-
kfree(range);
5505-
}
5534+
ublk_shmem_remove_ranges(ub, -1);
55065535
mtree_destroy(&ub->buf_tree);
55075536
ida_destroy(&ub->buf_ida);
55085537
}

tools/testing/selftests/ublk/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ TEST_PROGS += test_loop_07.sh
3737

3838
TEST_PROGS += test_integrity_01.sh
3939
TEST_PROGS += test_integrity_02.sh
40+
TEST_PROGS += test_integrity_03.sh
4041

4142
TEST_PROGS += test_recover_01.sh
4243
TEST_PROGS += test_recover_02.sh

tools/testing/selftests/ublk/test_batch_01.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dev_id=$(_add_ublk_dev -t loop -q 2 -b "${UBLK_BACKFILES[0]}")
1818
_check_add_dev $TID $?
1919

2020
if ! _mkfs_mount_test /dev/ublkb"${dev_id}"; then
21-
_cleanup_test "generic"
21+
_cleanup_test
2222
_show_result $TID 255
2323
fi
2424

@@ -27,5 +27,5 @@ _check_add_dev $TID $?
2727
_mkfs_mount_test /dev/ublkb"${dev_id}"
2828
ERR_CODE=$?
2929

30-
_cleanup_test "generic"
30+
_cleanup_test
3131
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_batch_02.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrit
2525
--iodepth=32 --size=100M --numjobs=4 > /dev/null 2>&1
2626
ERR_CODE=$?
2727

28-
_cleanup_test "generic"
28+
_cleanup_test
2929
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_batch_03.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrit
2525
--iodepth=32 --size=100M --numjobs=4 > /dev/null 2>&1
2626
ERR_CODE=$?
2727

28-
_cleanup_test "generic"
28+
_cleanup_test
2929
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_generic_02.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ for _ in $(seq 100); do
2929
done
3030

3131
if ! kill -0 "$btrace_pid" 2>/dev/null; then
32-
_cleanup_test "null"
32+
_cleanup_test
3333
exit "$UBLK_SKIP_CODE"
3434
fi
3535

@@ -51,5 +51,5 @@ if grep -q "^out_of_order:" "$UBLK_TMP"; then
5151
grep "^out_of_order:" "$UBLK_TMP"
5252
ERR_CODE=255
5353
fi
54-
_cleanup_test "null"
54+
_cleanup_test
5555
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_generic_03.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ fi
2323
if [ "$max_segment_size" != "32768" ]; then
2424
ERR_CODE=255
2525
fi
26-
_cleanup_test "null"
26+
_cleanup_test
2727
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_generic_06.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ if [ $ELAPSED -ge 5 ]; then
3636
ERR_CODE=255
3737
fi
3838

39-
_cleanup_test "fault_inject"
39+
_cleanup_test
4040
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_generic_07.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ if [ "$ERR_CODE" -eq 0 ]; then
2323
ERR_CODE=$?
2424
fi
2525

26-
_cleanup_test "generic"
26+
_cleanup_test
2727
_show_result $TID $ERR_CODE

tools/testing/selftests/ublk/test_generic_08.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dev_id=$(_add_ublk_dev -t loop -q 2 --auto_zc "${UBLK_BACKFILES[0]}")
1818
_check_add_dev $TID $?
1919

2020
if ! _mkfs_mount_test /dev/ublkb"${dev_id}"; then
21-
_cleanup_test "generic"
21+
_cleanup_test
2222
_show_result $TID 255
2323
fi
2424

@@ -27,5 +27,5 @@ _check_add_dev $TID $?
2727
_mkfs_mount_test /dev/ublkb"${dev_id}"
2828
ERR_CODE=$?
2929

30-
_cleanup_test "generic"
30+
_cleanup_test
3131
_show_result $TID $ERR_CODE

0 commit comments

Comments
 (0)