diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 77 | 
1 files changed, 20 insertions, 57 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 38e721b35d4..172f8491a2b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -70,19 +70,6 @@ static void bdev_inode_switch_bdi(struct inode *inode,  	spin_unlock(&dst->wb.list_lock);  } -sector_t blkdev_max_block(struct block_device *bdev) -{ -	sector_t retval = ~((sector_t)0); -	loff_t sz = i_size_read(bdev->bd_inode); - -	if (sz) { -		unsigned int size = block_size(bdev); -		unsigned int sizebits = blksize_bits(size); -		retval = (sz >> sizebits); -	} -	return retval; -} -  /* Kill _all_ buffers and pagecache , dirty or not.. */  void kill_bdev(struct block_device *bdev)  { @@ -163,52 +150,12 @@ static int  blkdev_get_block(struct inode *inode, sector_t iblock,  		struct buffer_head *bh, int create)  { -	if (iblock >= blkdev_max_block(I_BDEV(inode))) { -		if (create) -			return -EIO; - -		/* -		 * for reads, we're just trying to fill a partial page. -		 * return a hole, they will have to call get_block again -		 * before they can fill it, and they will get -EIO at that -		 * time -		 */ -		return 0; -	}  	bh->b_bdev = I_BDEV(inode);  	bh->b_blocknr = iblock;  	set_buffer_mapped(bh);  	return 0;  } -static int -blkdev_get_blocks(struct inode *inode, sector_t iblock, -		struct buffer_head *bh, int create) -{ -	sector_t end_block = blkdev_max_block(I_BDEV(inode)); -	unsigned long max_blocks = bh->b_size >> inode->i_blkbits; - -	if ((iblock + max_blocks) > end_block) { -		max_blocks = end_block - iblock; -		if ((long)max_blocks <= 0) { -			if (create) -				return -EIO;	/* write fully beyond EOF */ -			/* -			 * It is a read which is fully beyond EOF.  We return -			 * a !buffer_mapped buffer -			 */ -			max_blocks = 0; -		} -	} - -	bh->b_bdev = I_BDEV(inode); -	bh->b_blocknr = iblock; -	bh->b_size = max_blocks << inode->i_blkbits; -	if (max_blocks) -		set_buffer_mapped(bh); -	return 0; -} -  static ssize_t  blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,  			loff_t offset, unsigned long nr_segs) @@ -217,7 +164,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,  	struct inode *inode = file->f_mapping->host;  	return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset, -				    nr_segs, blkdev_get_blocks, NULL, NULL, 0); +				    nr_segs, blkdev_get_block, NULL, NULL, 0);  }  int __sync_blockdev(struct block_device *bdev, int wait) @@ -374,7 +321,7 @@ static int blkdev_write_end(struct file *file, struct address_space *mapping,   * for a block special file file->f_path.dentry->d_inode->i_size is zero   * so we compute the size by hand (just as in block_read/write above)   */ -static loff_t block_llseek(struct file *file, loff_t offset, int origin) +static loff_t block_llseek(struct file *file, loff_t offset, int whence)  {  	struct inode *bd_inode = file->f_mapping->host;  	loff_t size; @@ -384,7 +331,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)  	size = i_size_read(bd_inode);  	retval = -EINVAL; -	switch (origin) { +	switch (whence) {  		case SEEK_END:  			offset += size;  			break; @@ -1597,6 +1544,22 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,  }  EXPORT_SYMBOL_GPL(blkdev_aio_write); +static ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, +			 unsigned long nr_segs, loff_t pos) +{ +	struct file *file = iocb->ki_filp; +	struct inode *bd_inode = file->f_mapping->host; +	loff_t size = i_size_read(bd_inode); + +	if (pos >= size) +		return 0; + +	size -= pos; +	if (size < INT_MAX) +		nr_segs = iov_shorten((struct iovec *)iov, nr_segs, size); +	return generic_file_aio_read(iocb, iov, nr_segs, pos); +} +  /*   * Try to release a page associated with block device when the system   * is under memory pressure. @@ -1627,7 +1590,7 @@ const struct file_operations def_blk_fops = {  	.llseek		= block_llseek,  	.read		= do_sync_read,  	.write		= do_sync_write, -  	.aio_read	= generic_file_aio_read, +	.aio_read	= blkdev_aio_read,  	.aio_write	= blkdev_aio_write,  	.mmap		= generic_file_mmap,  	.fsync		= blkdev_fsync,  |