aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2012-05-16 19:05:26 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-05-17 15:02:43 -0400
commitcd9323fd68aee3c1c6b5b21e5746c9d1b586fb58 (patch)
treea1e5045e68a8a081a2e932846a0bf951128d93db
parentedc318d9fea6854df752ec8c645b960b0d5a1d23 (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.c22
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)
605static sector_t fd_get_blocks(struct se_device *dev) 605static 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
614static struct se_subsystem_api fileio_template = { 624static struct se_subsystem_api fileio_template = {