aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c97
1 files changed, 50 insertions, 47 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 5add6f4e7928..0a537a0515ca 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,47 +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 block * scsi_debug_sector_size, 0, 2065 lba * scsi_debug_sector_size, 0,
2063 scsi_debug_sector_size); 2066 scsi_debug_sector_size *
2067 scsi_debug_unmap_granularity);
2068 }
2064 } 2069 }
2065 lba += granularity - rem; 2070 lba = map_index_to_lba(index + 1);
2066 } 2071 }
2067} 2072}
2068 2073
@@ -2089,7 +2094,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
2089 2094
2090 write_lock_irqsave(&atomic_rw, iflags); 2095 write_lock_irqsave(&atomic_rw, iflags);
2091 ret = do_device_access(SCpnt, devip, lba, num, 1); 2096 ret = do_device_access(SCpnt, devip, lba, num, 1);
2092 if (scsi_debug_unmap_granularity) 2097 if (scsi_debug_lbp())
2093 map_region(lba, num); 2098 map_region(lba, num);
2094 write_unlock_irqrestore(&atomic_rw, iflags); 2099 write_unlock_irqrestore(&atomic_rw, iflags);
2095 if (-1 == ret) 2100 if (-1 == ret)
@@ -2122,7 +2127,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
2122 2127
2123 write_lock_irqsave(&atomic_rw, iflags); 2128 write_lock_irqsave(&atomic_rw, iflags);
2124 2129
2125 if (unmap && scsi_debug_unmap_granularity) { 2130 if (unmap && scsi_debug_lbp()) {
2126 unmap_region(lba, num); 2131 unmap_region(lba, num);
2127 goto out; 2132 goto out;
2128 } 2133 }
@@ -2146,7 +2151,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
2146 fake_storep + (lba * scsi_debug_sector_size), 2151 fake_storep + (lba * scsi_debug_sector_size),
2147 scsi_debug_sector_size); 2152 scsi_debug_sector_size);
2148 2153
2149 if (scsi_debug_unmap_granularity) 2154 if (scsi_debug_lbp())
2150 map_region(lba, num); 2155 map_region(lba, num);
2151out: 2156out:
2152 write_unlock_irqrestore(&atomic_rw, iflags); 2157 write_unlock_irqrestore(&atomic_rw, iflags);
@@ -3389,8 +3394,6 @@ static int __init scsi_debug_init(void)
3389 3394
3390 /* Logical Block Provisioning */ 3395 /* Logical Block Provisioning */
3391 if (scsi_debug_lbp()) { 3396 if (scsi_debug_lbp()) {
3392 unsigned int map_bytes;
3393
3394 scsi_debug_unmap_max_blocks = 3397 scsi_debug_unmap_max_blocks =
3395 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU); 3398 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
3396 3399
@@ -3401,16 +3404,16 @@ static int __init scsi_debug_init(void)
3401 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU); 3404 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
3402 3405
3403 if (scsi_debug_unmap_alignment && 3406 if (scsi_debug_unmap_alignment &&
3404 scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) { 3407 scsi_debug_unmap_granularity <=
3408 scsi_debug_unmap_alignment) {
3405 printk(KERN_ERR 3409 printk(KERN_ERR
3406 "%s: ERR: unmap_granularity < unmap_alignment\n", 3410 "%s: ERR: unmap_granularity <= unmap_alignment\n",
3407 __func__); 3411 __func__);
3408 return -EINVAL; 3412 return -EINVAL;
3409 } 3413 }
3410 3414
3411 map_size = (sdebug_store_sectors / scsi_debug_unmap_granularity); 3415 map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
3412 map_bytes = map_size >> 3; 3416 map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
3413 map_storep = vmalloc(map_bytes);
3414 3417
3415 printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n", 3418 printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
3416 map_size); 3419 map_size);
@@ -3421,7 +3424,7 @@ static int __init scsi_debug_init(void)
3421 goto free_vm; 3424 goto free_vm;
3422 } 3425 }
3423 3426
3424 memset(map_storep, 0x0, map_bytes); 3427 bitmap_zero(map_storep, map_size);
3425 3428
3426 /* Map first 1KB for partition table */ 3429 /* Map first 1KB for partition table */
3427 if (scsi_debug_num_parts) 3430 if (scsi_debug_num_parts)