diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 97 |
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 | ||
2000 | static unsigned int map_state(sector_t lba, unsigned int *num) | 2000 | static 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 | |||
2011 | static 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; | 2017 | static 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 | ||
2023 | static void map_region(sector_t lba, unsigned int len) | 2038 | static 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 | ||
2044 | static void unmap_region(sector_t lba, unsigned int len) | 2052 | static 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); |
2151 | out: | 2156 | out: |
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) |