aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2013-04-16 09:11:58 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-02 18:45:56 -0400
commitb90ebc3d5c41c9164ae04efd2e4f8204c2a186f1 (patch)
treeb74225a28bb0322c6cb755349abc7a8299198c2c
parentcc34a8e663b2908b9ab487dab8456d117a1e0b93 (diff)
[SCSI] scsi_debug: fix logical block provisioning support
provisioning map (map_storep) is a bitmap accessed by bitops. So the allocation size should be a multiple of sizeof(unsigned long) and also the bitmap should be cleared by using bitmap_clear() instead of memset(). Otherwise it will cause problem on big-endian architecture if the number of bits is not a multiple of BITS_PER_LONG. I tried testing the logical block provisioning support in scsi_debug, but it didn't work as I expected. For example, load scsi_debug module with UNMAP command supported and fill the storage with random data. # modprobe scsi_debug lbpu=1 # dd if=/dev/urandom of=/dev/sdb Then, try to unmap LBA 0, but Get LBA status reports: # sg_unmap --lba=0 --num=1 /dev/sdb # sg_get_lba_status --lba=0 /dev/sdb descriptor LBA: 0x0000000000000000 blocks: 16384 mapped This is unexpected result. Because UNMAP command to LBA 0 finished without any errors, but Get LBA status shows that LBA 0 is still mapped. This problem is due to the wrong translation between LBA and index of provisioning map. Fix it by using correct translation functions. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Acked-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/scsi_debug.c81
1 files changed, 41 insertions, 40 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 4b5d3887ff47..154d9870dc5a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1997,24 +1997,39 @@ out:
1997 return ret; 1997 return ret;
1998} 1998}
1999 1999
2000static unsigned int map_state(sector_t lba, unsigned int *num) 2000static unsigned long lba_to_map_index(sector_t lba)
2001{
2002 if (scsi_debug_unmap_alignment) {
2003 lba += scsi_debug_unmap_granularity -
2004 scsi_debug_unmap_alignment;
2005 }
2006 do_div(lba, scsi_debug_unmap_granularity);
2007
2008 return lba;
2009}
2010
2011static sector_t map_index_to_lba(unsigned long index)
2001{ 2012{
2002 unsigned int granularity, alignment, mapped; 2013 return index * scsi_debug_unmap_granularity -
2003 sector_t block, next, end; 2014 scsi_debug_unmap_alignment;
2015}
2004 2016
2005 granularity = scsi_debug_unmap_granularity; 2017static unsigned int map_state(sector_t lba, unsigned int *num)
2006 alignment = granularity - scsi_debug_unmap_alignment; 2018{
2007 block = lba + alignment; 2019 sector_t end;
2008 do_div(block, granularity); 2020 unsigned int mapped;
2021 unsigned long index;
2022 unsigned long next;
2009 2023
2010 mapped = test_bit(block, map_storep); 2024 index = lba_to_map_index(lba);
2025 mapped = test_bit(index, map_storep);
2011 2026
2012 if (mapped) 2027 if (mapped)
2013 next = find_next_zero_bit(map_storep, map_size, block); 2028 next = find_next_zero_bit(map_storep, map_size, index);
2014 else 2029 else
2015 next = find_next_bit(map_storep, map_size, block); 2030 next = find_next_bit(map_storep, map_size, index);
2016 2031
2017 end = next * granularity - scsi_debug_unmap_alignment; 2032 end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
2018 *num = end - lba; 2033 *num = end - lba;
2019 2034
2020 return mapped; 2035 return mapped;
@@ -2022,48 +2037,37 @@ static unsigned int map_state(sector_t lba, unsigned int *num)
2022 2037
2023static void map_region(sector_t lba, unsigned int len) 2038static void map_region(sector_t lba, unsigned int len)
2024{ 2039{
2025 unsigned int granularity, alignment;
2026 sector_t end = lba + len; 2040 sector_t end = lba + len;
2027 2041
2028 granularity = scsi_debug_unmap_granularity;
2029 alignment = granularity - scsi_debug_unmap_alignment;
2030
2031 while (lba < end) { 2042 while (lba < end) {
2032 sector_t block, rem; 2043 unsigned long index = lba_to_map_index(lba);
2033
2034 block = lba + alignment;
2035 rem = do_div(block, granularity);
2036 2044
2037 if (block < map_size) 2045 if (index < map_size)
2038 set_bit(block, map_storep); 2046 set_bit(index, map_storep);
2039 2047
2040 lba += granularity - rem; 2048 lba = map_index_to_lba(index + 1);
2041 } 2049 }
2042} 2050}
2043 2051
2044static void unmap_region(sector_t lba, unsigned int len) 2052static void unmap_region(sector_t lba, unsigned int len)
2045{ 2053{
2046 unsigned int granularity, alignment;
2047 sector_t end = lba + len; 2054 sector_t end = lba + len;
2048 2055
2049 granularity = scsi_debug_unmap_granularity;
2050 alignment = granularity - scsi_debug_unmap_alignment;
2051
2052 while (lba < end) { 2056 while (lba < end) {
2053 sector_t block, rem; 2057 unsigned long index = lba_to_map_index(lba);
2054
2055 block = lba + alignment;
2056 rem = do_div(block, granularity);
2057 2058
2058 if (rem == 0 && lba + granularity < end && block < map_size) { 2059 if (lba == map_index_to_lba(index) &&
2059 clear_bit(block, map_storep); 2060 lba + scsi_debug_unmap_granularity <= end &&
2060 if (scsi_debug_lbprz) 2061 index < map_size) {
2062 clear_bit(index, map_storep);
2063 if (scsi_debug_lbprz) {
2061 memset(fake_storep + 2064 memset(fake_storep +
2062 lba * scsi_debug_sector_size, 0, 2065 lba * scsi_debug_sector_size, 0,
2063 scsi_debug_sector_size * 2066 scsi_debug_sector_size *
2064 scsi_debug_unmap_granularity); 2067 scsi_debug_unmap_granularity);
2068 }
2065 } 2069 }
2066 lba += granularity - rem; 2070 lba = map_index_to_lba(index + 1);
2067 } 2071 }
2068} 2072}
2069 2073
@@ -3402,8 +3406,6 @@ static int __init scsi_debug_init(void)
3402 3406
3403 /* Logical Block Provisioning */ 3407 /* Logical Block Provisioning */
3404 if (scsi_debug_lbp()) { 3408 if (scsi_debug_lbp()) {
3405 unsigned int map_bytes;
3406
3407 scsi_debug_unmap_max_blocks = 3409 scsi_debug_unmap_max_blocks =
3408 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU); 3410 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
3409 3411
@@ -3422,9 +3424,8 @@ static int __init scsi_debug_init(void)
3422 return -EINVAL; 3424 return -EINVAL;
3423 } 3425 }
3424 3426
3425 map_size = (sdebug_store_sectors / scsi_debug_unmap_granularity); 3427 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
3426 map_bytes = map_size >> 3; 3428 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
3427 map_storep = vmalloc(map_bytes);
3428 3429
3429 printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n", 3430 printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
3430 map_size); 3431 map_size);
@@ -3435,7 +3436,7 @@ static int __init scsi_debug_init(void)
3435 goto free_vm; 3436 goto free_vm;
3436 } 3437 }
3437 3438
3438 memset(map_storep, 0x0, map_bytes); 3439 bitmap_zero(map_storep, map_size);
3439 3440
3440 /* Map first 1KB for partition table */ 3441 /* Map first 1KB for partition table */
3441 if (scsi_debug_num_parts) 3442 if (scsi_debug_num_parts)