X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fblock_dev.c;h=d19d07c49ad319a3375b983933e8725029f3a973;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=5c3f09b861728fcc7baa0adb3721b32e2206e011;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/fs/block_dev.c b/fs/block_dev.c index 5c3f09b86..d19d07c49 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -137,13 +137,26 @@ static int blkdev_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, struct buffer_head *bh, int create) { - if ((iblock + max_blocks) > max_block(I_BDEV(inode))) - return -EIO; + sector_t end_block = max_block(I_BDEV(inode)); + + 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; - set_buffer_mapped(bh); + if (max_blocks) + set_buffer_mapped(bh); return 0; } @@ -224,7 +237,7 @@ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) * pseudo-fs */ -static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(bdev_lock); static kmem_cache_t * bdev_cachep; static struct inode *bdev_alloc_inode(struct super_block *sb) @@ -666,7 +679,7 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) EXPORT_SYMBOL(blkdev_get); -int blkdev_open(struct inode * inode, struct file * filp) +static int blkdev_open(struct inode * inode, struct file * filp) { struct block_device *bdev; int res; @@ -695,8 +708,6 @@ int blkdev_open(struct inode * inode, struct file * filp) return res; } -EXPORT_SYMBOL(blkdev_open); - int blkdev_put(struct block_device *bdev) { int ret = 0; @@ -793,13 +804,14 @@ struct file_operations def_blk_fops = { .mmap = generic_file_mmap, .fsync = block_fsync, .ioctl = block_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_blkdev_ioctl, +#endif .readv = generic_file_readv, .writev = generic_file_write_nolock, .sendfile = generic_file_sendfile, }; -EXPORT_SYMBOL(def_blk_fops); - int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) { int res;