diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-05-16 19:05:26 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-05-17 15:02:43 -0400 |
commit | cd9323fd68aee3c1c6b5b21e5746c9d1b586fb58 (patch) | |
tree | a1e5045e68a8a081a2e932846a0bf951128d93db | |
parent | edc318d9fea6854df752ec8c645b960b0d5a1d23 (diff) |
target: Fix bug in handling of FILEIO + block_device resize ops
This patch fixes a bug in the handling of FILEIO w/ underlying block_device
resize operations where the original fd_dev->fd_dev_size was incorrectly being
used in fd_get_blocks() for READ_CAPACITY response payloads.
This patch avoids using fd_dev->fd_dev_size for FILEIO devices with
an underlying block_device, and instead changes fd_get_blocks() to
get the sector count directly from i_size_read() as recommended by hch.
Reported-by: Christoph Hellwig <hch@lst.de>
Cc: <stable@vger.kernel.org>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_file.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 7ed58e2df791..f286955331a2 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -169,6 +169,7 @@ static struct se_device *fd_create_virtdevice( | |||
169 | inode = file->f_mapping->host; | 169 | inode = file->f_mapping->host; |
170 | if (S_ISBLK(inode->i_mode)) { | 170 | if (S_ISBLK(inode->i_mode)) { |
171 | struct request_queue *q; | 171 | struct request_queue *q; |
172 | unsigned long long dev_size; | ||
172 | /* | 173 | /* |
173 | * Setup the local scope queue_limits from struct request_queue->limits | 174 | * Setup the local scope queue_limits from struct request_queue->limits |
174 | * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. | 175 | * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. |
@@ -183,13 +184,12 @@ static struct se_device *fd_create_virtdevice( | |||
183 | * one (1) logical sector from underlying struct block_device | 184 | * one (1) logical sector from underlying struct block_device |
184 | */ | 185 | */ |
185 | fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); | 186 | fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); |
186 | fd_dev->fd_dev_size = (i_size_read(file->f_mapping->host) - | 187 | dev_size = (i_size_read(file->f_mapping->host) - |
187 | fd_dev->fd_block_size); | 188 | fd_dev->fd_block_size); |
188 | 189 | ||
189 | pr_debug("FILEIO: Using size: %llu bytes from struct" | 190 | pr_debug("FILEIO: Using size: %llu bytes from struct" |
190 | " block_device blocks: %llu logical_block_size: %d\n", | 191 | " block_device blocks: %llu logical_block_size: %d\n", |
191 | fd_dev->fd_dev_size, | 192 | dev_size, div_u64(dev_size, fd_dev->fd_block_size), |
192 | div_u64(fd_dev->fd_dev_size, fd_dev->fd_block_size), | ||
193 | fd_dev->fd_block_size); | 193 | fd_dev->fd_block_size); |
194 | } else { | 194 | } else { |
195 | if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) { | 195 | if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) { |
@@ -605,10 +605,20 @@ static u32 fd_get_device_type(struct se_device *dev) | |||
605 | static sector_t fd_get_blocks(struct se_device *dev) | 605 | static sector_t fd_get_blocks(struct se_device *dev) |
606 | { | 606 | { |
607 | struct fd_dev *fd_dev = dev->dev_ptr; | 607 | struct fd_dev *fd_dev = dev->dev_ptr; |
608 | unsigned long long blocks_long = div_u64(fd_dev->fd_dev_size, | 608 | struct file *f = fd_dev->fd_file; |
609 | dev->se_sub_dev->se_dev_attrib.block_size); | 609 | struct inode *i = f->f_mapping->host; |
610 | unsigned long long dev_size; | ||
611 | /* | ||
612 | * When using a file that references an underlying struct block_device, | ||
613 | * ensure dev_size is always based on the current inode size in order | ||
614 | * to handle underlying block_device resize operations. | ||
615 | */ | ||
616 | if (S_ISBLK(i->i_mode)) | ||
617 | dev_size = (i_size_read(i) - fd_dev->fd_block_size); | ||
618 | else | ||
619 | dev_size = fd_dev->fd_dev_size; | ||
610 | 620 | ||
611 | return blocks_long; | 621 | return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size); |
612 | } | 622 | } |
613 | 623 | ||
614 | static struct se_subsystem_api fileio_template = { | 624 | static struct se_subsystem_api fileio_template = { |