Skip to content

Commit f5ce815

Browse files
bostroessermartinkpetersen
authored andcommitted
scsi: target: tcmu: Support DATA_BLOCK_SIZE = N * PAGE_SIZE
Change tcmu to support DATA_BLOCK_SIZE being a multiple of PAGE_SIZE. There are two reasons why one would like to have a bigger DATA_BLOCK_SIZE: 1) If userspace - e.g. due to data compression, encryption or deduplication - needs to have receive or transmit data in a consecutive buffer, we can define DATA_BLOCK_SIZE to the maximum size of a SCSI READ/WRITE to enforce that userspace sees just one consecutive buffer. That way we can avoid the need for doing data copy in userspace. 2) Using a bigger data block size can speed up command processing in tcmu. The number of free data blocks to look up in bitmap is reduced substantially. The lookup for data pages in radix_tree can be done more efficiently if there are multiple pages in a data block. The maximum number of IOVs to set up is lower so cmd entries in the ring become smaller. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bodo Stroesser <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 8b084d9 commit f5ce815

File tree

1 file changed

+116
-89
lines changed

1 file changed

+116
-89
lines changed

drivers/target/target_core_user.c

Lines changed: 116 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@
6767
#define CMDR_SIZE (MB_CMDR_SIZE - CMDR_OFF)
6868

6969
/*
70-
* For data area, the block size is PAGE_SIZE and
71-
* the total size is 256K * PAGE_SIZE.
70+
* For data area, the default block size is PAGE_SIZE and
71+
* the default total size is 256K * PAGE_SIZE.
7272
*/
73-
#define DATA_BLOCK_SIZE PAGE_SIZE
7473
#define DATA_PAGES_PER_BLK 1
75-
#define DATA_BLOCK_BITS_DEF (256 * 1024)
74+
#define DATA_BLOCK_SIZE (DATA_PAGES_PER_BLK * PAGE_SIZE)
75+
#define DATA_AREA_PAGES_DEF (256 * 1024)
7676

77-
#define TCMU_MBS_TO_PAGES(_mbs) (_mbs << (20 - PAGE_SHIFT))
77+
#define TCMU_MBS_TO_PAGES(_mbs) ((size_t)_mbs << (20 - PAGE_SHIFT))
7878
#define TCMU_PAGES_TO_MBS(_pages) (_pages >> (20 - PAGE_SHIFT))
7979

8080
/*
@@ -138,7 +138,7 @@ struct tcmu_dev {
138138
/* Offset of data area from start of mb */
139139
/* Must add data_off and mb_addr to get the address */
140140
size_t data_off;
141-
size_t data_size;
141+
int data_area_mb;
142142
uint32_t max_blocks;
143143
size_t mmap_pages;
144144

@@ -501,31 +501,39 @@ static void tcmu_cmd_free_data(struct tcmu_cmd *tcmu_cmd, uint32_t len)
501501

502502
static inline int tcmu_get_empty_block(struct tcmu_dev *udev,
503503
struct tcmu_cmd *tcmu_cmd,
504-
int prev_dbi, int *iov_cnt)
504+
int prev_dbi, int length, int *iov_cnt)
505505
{
506+
XA_STATE(xas, &udev->data_pages, 0);
506507
struct page *page;
507-
int dbi;
508+
int i, cnt, dbi;
509+
int page_cnt = DIV_ROUND_UP(length, PAGE_SIZE);
508510

509511
dbi = find_first_zero_bit(udev->data_bitmap, udev->dbi_thresh);
510512
if (dbi == udev->dbi_thresh)
511513
return -1;
512514

513-
page = xa_load(&udev->data_pages, dbi);
514-
if (!page) {
515-
if (atomic_add_return(1, &global_page_count) >
516-
tcmu_global_max_pages)
517-
schedule_delayed_work(&tcmu_unmap_work, 0);
515+
/* Count the number of already allocated pages */
516+
xas_set(&xas, dbi * DATA_PAGES_PER_BLK);
517+
for (cnt = 0; xas_next(&xas) && cnt < page_cnt;)
518+
cnt++;
518519

520+
for (i = cnt; i < page_cnt; i++) {
519521
/* try to get new page from the mm */
520522
page = alloc_page(GFP_NOIO);
521523
if (!page)
522-
goto err_alloc;
524+
break;
523525

524-
if (xa_store(&udev->data_pages, dbi, page, GFP_NOIO))
525-
goto err_insert;
526+
if (xa_store(&udev->data_pages, dbi * DATA_PAGES_PER_BLK + i,
527+
page, GFP_NOIO)) {
528+
__free_page(page);
529+
break;
530+
}
526531
}
532+
if (atomic_add_return(i - cnt, &global_page_count) >
533+
tcmu_global_max_pages)
534+
schedule_delayed_work(&tcmu_unmap_work, 0);
527535

528-
if (dbi > udev->dbi_max)
536+
if (i && dbi > udev->dbi_max)
529537
udev->dbi_max = dbi;
530538

531539
set_bit(dbi, udev->data_bitmap);
@@ -534,23 +542,19 @@ static inline int tcmu_get_empty_block(struct tcmu_dev *udev,
534542
if (dbi != prev_dbi + 1)
535543
*iov_cnt += 1;
536544

537-
return dbi;
538-
err_insert:
539-
__free_page(page);
540-
err_alloc:
541-
atomic_dec(&global_page_count);
542-
return -1;
545+
return i == page_cnt ? dbi : -1;
543546
}
544547

545548
static int tcmu_get_empty_blocks(struct tcmu_dev *udev,
546-
struct tcmu_cmd *tcmu_cmd, int dbi_cnt)
549+
struct tcmu_cmd *tcmu_cmd, int length)
547550
{
548551
/* start value of dbi + 1 must not be a valid dbi */
549552
int dbi = -2;
550-
int i, iov_cnt = 0;
553+
int blk_len, iov_cnt = 0;
551554

552-
for (i = 0; i < dbi_cnt; i++) {
553-
dbi = tcmu_get_empty_block(udev, tcmu_cmd, dbi, &iov_cnt);
555+
for (; length > 0; length -= DATA_BLOCK_SIZE) {
556+
blk_len = min_t(int, length, DATA_BLOCK_SIZE);
557+
dbi = tcmu_get_empty_block(udev, tcmu_cmd, dbi, blk_len, &iov_cnt);
554558
if (dbi < 0)
555559
return -1;
556560
}
@@ -698,9 +702,11 @@ static inline void tcmu_copy_data(struct tcmu_dev *udev,
698702
struct scatterlist *sg, unsigned int sg_nents,
699703
struct iovec **iov, size_t data_len)
700704
{
705+
XA_STATE(xas, &udev->data_pages, 0);
701706
/* start value of dbi + 1 must not be a valid dbi */
702707
int dbi = -2;
703-
size_t block_remaining, cp_len;
708+
size_t page_remaining, cp_len;
709+
int page_cnt, page_inx;
704710
struct sg_mapping_iter sg_iter;
705711
unsigned int sg_flags;
706712
struct page *page;
@@ -718,37 +724,48 @@ static inline void tcmu_copy_data(struct tcmu_dev *udev,
718724
data_len);
719725
else
720726
dbi = tcmu_cmd_get_dbi(tcmu_cmd);
721-
page = tcmu_get_block_page(udev, dbi);
722-
if (direction == TCMU_DATA_AREA_TO_SG)
723-
flush_dcache_page(page);
724-
data_page_start = kmap_atomic(page);
725-
block_remaining = DATA_BLOCK_SIZE;
726-
727-
while (block_remaining && data_len) {
728-
if (!sg_miter_next(&sg_iter)) {
729-
/* set length to 0 to abort outer loop */
730-
data_len = 0;
731-
pr_debug("tcmu_move_data: aborting data copy due to exhausted sg_list\n");
732-
break;
727+
728+
page_cnt = DIV_ROUND_UP(data_len, PAGE_SIZE);
729+
if (page_cnt > DATA_PAGES_PER_BLK)
730+
page_cnt = DATA_PAGES_PER_BLK;
731+
732+
xas_set(&xas, dbi * DATA_PAGES_PER_BLK);
733+
for (page_inx = 0; page_inx < page_cnt && data_len; page_inx++) {
734+
page = xas_next(&xas);
735+
736+
if (direction == TCMU_DATA_AREA_TO_SG)
737+
flush_dcache_page(page);
738+
data_page_start = kmap_atomic(page);
739+
page_remaining = PAGE_SIZE;
740+
741+
while (page_remaining && data_len) {
742+
if (!sg_miter_next(&sg_iter)) {
743+
/* set length to 0 to abort outer loop */
744+
data_len = 0;
745+
pr_debug("%s: aborting data copy due to exhausted sg_list\n",
746+
__func__);
747+
break;
748+
}
749+
cp_len = min3(sg_iter.length, page_remaining,
750+
data_len);
751+
752+
data_addr = data_page_start +
753+
PAGE_SIZE - page_remaining;
754+
if (direction == TCMU_SG_TO_DATA_AREA)
755+
memcpy(data_addr, sg_iter.addr, cp_len);
756+
else
757+
memcpy(sg_iter.addr, data_addr, cp_len);
758+
759+
data_len -= cp_len;
760+
page_remaining -= cp_len;
761+
sg_iter.consumed = cp_len;
733762
}
734-
cp_len = min3(sg_iter.length, block_remaining, data_len);
763+
sg_miter_stop(&sg_iter);
735764

736-
data_addr = data_page_start +
737-
DATA_BLOCK_SIZE - block_remaining;
765+
kunmap_atomic(data_page_start);
738766
if (direction == TCMU_SG_TO_DATA_AREA)
739-
memcpy(data_addr, sg_iter.addr, cp_len);
740-
else
741-
memcpy(sg_iter.addr, data_addr, cp_len);
742-
743-
data_len -= cp_len;
744-
block_remaining -= cp_len;
745-
sg_iter.consumed = cp_len;
767+
flush_dcache_page(page);
746768
}
747-
sg_miter_stop(&sg_iter);
748-
749-
kunmap_atomic(data_page_start);
750-
if (direction == TCMU_SG_TO_DATA_AREA)
751-
flush_dcache_page(page);
752769
}
753770
}
754771

@@ -858,13 +875,12 @@ static int tcmu_alloc_data_space(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
858875
udev->dbi_thresh = udev->max_blocks;
859876
}
860877

861-
iov_cnt = tcmu_get_empty_blocks(udev, cmd,
862-
cmd->dbi_cnt - cmd->dbi_bidi_cnt);
878+
iov_cnt = tcmu_get_empty_blocks(udev, cmd, cmd->se_cmd->data_length);
863879
if (iov_cnt < 0)
864880
return -1;
865881

866882
if (cmd->dbi_bidi_cnt) {
867-
ret = tcmu_get_empty_blocks(udev, cmd, cmd->dbi_bidi_cnt);
883+
ret = tcmu_get_empty_blocks(udev, cmd, cmd->data_len_bidi);
868884
if (ret < 0)
869885
return -1;
870886
}
@@ -1020,9 +1036,9 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
10201036
if (!list_empty(&udev->qfull_queue))
10211037
goto queue;
10221038

1023-
if (data_length > udev->data_size) {
1039+
if (data_length > udev->max_blocks * DATA_BLOCK_SIZE) {
10241040
pr_warn("TCMU: Request of size %zu is too big for %zu data area\n",
1025-
data_length, udev->data_size);
1041+
data_length, udev->max_blocks * DATA_BLOCK_SIZE);
10261042
*scsi_err = TCM_INVALID_CDB_FIELD;
10271043
return -1;
10281044
}
@@ -1570,7 +1586,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
15701586
udev->cmd_time_out = TCMU_TIME_OUT;
15711587
udev->qfull_time_out = -1;
15721588

1573-
udev->max_blocks = DATA_BLOCK_BITS_DEF;
1589+
udev->max_blocks = DATA_AREA_PAGES_DEF / DATA_PAGES_PER_BLK;
1590+
udev->data_area_mb = TCMU_PAGES_TO_MBS(DATA_AREA_PAGES_DEF);
15741591
mutex_init(&udev->cmdr_lock);
15751592

15761593
INIT_LIST_HEAD(&udev->node);
@@ -1607,19 +1624,24 @@ static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd)
16071624
return -EINVAL;
16081625
}
16091626

1610-
static void tcmu_blocks_release(struct xarray *blocks, unsigned long first,
1627+
static u32 tcmu_blocks_release(struct xarray *blocks, unsigned long first,
16111628
unsigned long last)
16121629
{
1613-
XA_STATE(xas, blocks, first);
1630+
XA_STATE(xas, blocks, first * DATA_PAGES_PER_BLK);
16141631
struct page *page;
1632+
u32 pages_freed = 0;
16151633

16161634
xas_lock(&xas);
1617-
xas_for_each(&xas, page, last) {
1635+
xas_for_each(&xas, page, (last + 1) * DATA_PAGES_PER_BLK - 1) {
16181636
xas_store(&xas, NULL);
16191637
__free_page(page);
1620-
atomic_dec(&global_page_count);
1638+
pages_freed++;
16211639
}
16221640
xas_unlock(&xas);
1641+
1642+
atomic_sub(pages_freed, &global_page_count);
1643+
1644+
return pages_freed;
16231645
}
16241646

16251647
static void tcmu_remove_all_queued_tmr(struct tcmu_dev *udev)
@@ -2086,6 +2108,7 @@ static int tcmu_configure_device(struct se_device *dev)
20862108
struct tcmu_dev *udev = TCMU_DEV(dev);
20872109
struct uio_info *info;
20882110
struct tcmu_mailbox *mb;
2111+
size_t data_size;
20892112
int ret = 0;
20902113

20912114
ret = tcmu_update_uio_info(udev);
@@ -2113,8 +2136,8 @@ static int tcmu_configure_device(struct se_device *dev)
21132136
udev->cmdr = (void *)mb + CMDR_OFF;
21142137
udev->cmdr_size = CMDR_SIZE;
21152138
udev->data_off = MB_CMDR_SIZE;
2116-
udev->data_size = udev->max_blocks * DATA_BLOCK_SIZE;
2117-
udev->mmap_pages = (udev->data_size + MB_CMDR_SIZE) >> PAGE_SHIFT;
2139+
data_size = TCMU_MBS_TO_PAGES(udev->data_area_mb) << PAGE_SHIFT;
2140+
udev->mmap_pages = (data_size + MB_CMDR_SIZE) >> PAGE_SHIFT;
21182141
udev->dbi_thresh = 0; /* Default in Idle state */
21192142

21202143
/* Initialise the mailbox of the ring buffer */
@@ -2126,14 +2149,13 @@ static int tcmu_configure_device(struct se_device *dev)
21262149
mb->cmdr_size = udev->cmdr_size;
21272150

21282151
WARN_ON(!PAGE_ALIGNED(udev->data_off));
2129-
WARN_ON(udev->data_size % PAGE_SIZE);
2130-
WARN_ON(udev->data_size % DATA_BLOCK_SIZE);
2152+
WARN_ON(data_size % PAGE_SIZE);
21312153

21322154
info->version = __stringify(TCMU_MAILBOX_VERSION);
21332155

21342156
info->mem[0].name = "tcm-user command & data buffer";
21352157
info->mem[0].addr = (phys_addr_t)(uintptr_t)udev->mb_addr;
2136-
info->mem[0].size = udev->data_size + MB_CMDR_SIZE;
2158+
info->mem[0].size = data_size + MB_CMDR_SIZE;
21372159
info->mem[0].memtype = UIO_MEM_NONE;
21382160

21392161
info->irqcontrol = tcmu_irqcontrol;
@@ -2343,20 +2365,28 @@ static int tcmu_set_dev_attrib(substring_t *arg, u32 *dev_attrib)
23432365

23442366
static int tcmu_set_max_blocks_param(struct tcmu_dev *udev, substring_t *arg)
23452367
{
2346-
int val, ret, blks;
2368+
int val, ret;
23472369

23482370
ret = match_int(arg, &val);
23492371
if (ret < 0) {
23502372
pr_err("match_int() failed for max_data_area_mb=. Error %d.\n",
23512373
ret);
23522374
return ret;
23532375
}
2354-
2355-
blks = TCMU_MBS_TO_PAGES(val) / DATA_PAGES_PER_BLK;
2356-
if (blks <= 0) {
2376+
if (val <= 0) {
23572377
pr_err("Invalid max_data_area %d.\n", val);
23582378
return -EINVAL;
23592379
}
2380+
if (val > TCMU_PAGES_TO_MBS(tcmu_global_max_pages)) {
2381+
pr_err("%d is too large. Adjusting max_data_area_mb to global limit of %u\n",
2382+
val, TCMU_PAGES_TO_MBS(tcmu_global_max_pages));
2383+
val = TCMU_PAGES_TO_MBS(tcmu_global_max_pages);
2384+
}
2385+
if (TCMU_MBS_TO_PAGES(val) < DATA_PAGES_PER_BLK) {
2386+
pr_err("Invalid max_data_area %d (%zu pages): smaller than data_pages_per_blk (%d pages).\n",
2387+
val, TCMU_MBS_TO_PAGES(val), DATA_PAGES_PER_BLK);
2388+
return -EINVAL;
2389+
}
23602390

23612391
mutex_lock(&udev->cmdr_lock);
23622392
if (udev->data_bitmap) {
@@ -2365,12 +2395,8 @@ static int tcmu_set_max_blocks_param(struct tcmu_dev *udev, substring_t *arg)
23652395
goto unlock;
23662396
}
23672397

2368-
udev->max_blocks = blks;
2369-
if (udev->max_blocks * DATA_PAGES_PER_BLK > tcmu_global_max_pages) {
2370-
pr_err("%d is too large. Adjusting max_data_area_mb to global limit of %u\n",
2371-
val, TCMU_PAGES_TO_MBS(tcmu_global_max_pages));
2372-
udev->max_blocks = tcmu_global_max_pages / DATA_PAGES_PER_BLK;
2373-
}
2398+
udev->data_area_mb = val;
2399+
udev->max_blocks = TCMU_MBS_TO_PAGES(val) / DATA_PAGES_PER_BLK;
23742400

23752401
unlock:
23762402
mutex_unlock(&udev->cmdr_lock);
@@ -2448,8 +2474,7 @@ static ssize_t tcmu_show_configfs_dev_params(struct se_device *dev, char *b)
24482474
bl = sprintf(b + bl, "Config: %s ",
24492475
udev->dev_config[0] ? udev->dev_config : "NULL");
24502476
bl += sprintf(b + bl, "Size: %llu ", udev->dev_size);
2451-
bl += sprintf(b + bl, "MaxDataAreaMB: %u\n",
2452-
TCMU_PAGES_TO_MBS(udev->max_blocks * DATA_PAGES_PER_BLK));
2477+
bl += sprintf(b + bl, "MaxDataAreaMB: %u\n", udev->data_area_mb);
24532478

24542479
return bl;
24552480
}
@@ -2543,8 +2568,7 @@ static ssize_t tcmu_max_data_area_mb_show(struct config_item *item, char *page)
25432568
struct se_dev_attrib, da_group);
25442569
struct tcmu_dev *udev = TCMU_DEV(da->da_dev);
25452570

2546-
return snprintf(page, PAGE_SIZE, "%u\n",
2547-
TCMU_PAGES_TO_MBS(udev->max_blocks * DATA_PAGES_PER_BLK));
2571+
return snprintf(page, PAGE_SIZE, "%u\n", udev->data_area_mb);
25482572
}
25492573
CONFIGFS_ATTR_RO(tcmu_, max_data_area_mb);
25502574

@@ -2902,7 +2926,8 @@ static void find_free_blocks(void)
29022926
{
29032927
struct tcmu_dev *udev;
29042928
loff_t off;
2905-
u32 start, end, block, total_freed = 0;
2929+
u32 pages_freed, total_pages_freed = 0;
2930+
u32 start, end, block, total_blocks_freed = 0;
29062931

29072932
if (atomic_read(&global_page_count) <= tcmu_global_max_pages)
29082933
return;
@@ -2949,12 +2974,14 @@ static void find_free_blocks(void)
29492974
unmap_mapping_range(udev->inode->i_mapping, off, 0, 1);
29502975

29512976
/* Release the block pages */
2952-
tcmu_blocks_release(&udev->data_pages, start, end - 1);
2977+
pages_freed = tcmu_blocks_release(&udev->data_pages, start, end - 1);
29532978
mutex_unlock(&udev->cmdr_lock);
29542979

2955-
total_freed += end - start;
2956-
pr_debug("Freed %u blocks (total %u) from %s.\n", end - start,
2957-
total_freed, udev->name);
2980+
total_pages_freed += pages_freed;
2981+
total_blocks_freed += end - start;
2982+
pr_debug("Freed %u pages (total %u) from %u blocks (total %u) from %s.\n",
2983+
pages_freed, total_pages_freed, end - start,
2984+
total_blocks_freed, udev->name);
29582985
}
29592986
mutex_unlock(&root_udev_mutex);
29602987

0 commit comments

Comments
 (0)