X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fblock_dev.c;h=fc7028b685f29ab94d5db4ef26dbb897573c6af5;hb=fac105d05e4b410c586de55dfbf34f40a95f6977;hp=1715d6b5f411a2d6db22c9a38de9cab971e40bf6;hpb=ee2fae03d68e702866a8661fbee7ff2f2f3754d7;p=linux-2.6-omap-h63xx.git diff --git a/fs/block_dev.c b/fs/block_dev.c index 1715d6b5f41..fc7028b685f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -129,6 +129,46 @@ blkdev_get_block(struct inode *inode, sector_t iblock, return 0; } +static int +blkdev_get_blocks(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + sector_t end_block = 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) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; + + return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode), + iov, offset, nr_segs, blkdev_get_blocks, NULL); +} + +#if 0 static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) { struct kiocb *iocb = bio->bi_private; @@ -146,7 +186,7 @@ static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) iocb->ki_nbytes = -EIO; if (atomic_dec_and_test(bio_count)) { - if (iocb->ki_nbytes < 0) + if ((long)iocb->ki_nbytes < 0) aio_complete(iocb, iocb->ki_nbytes, 0); else aio_complete(iocb, iocb->ki_left, 0); @@ -190,6 +230,12 @@ static struct page *blk_get_page(unsigned long addr, size_t count, int rw, return pvec->page[pvec->idx++]; } +/* return a page back to pvec array */ +static void blk_unget_page(struct page *page, struct pvec *pvec) +{ + pvec->page[--pvec->idx] = page; +} + static ssize_t blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) @@ -278,6 +324,8 @@ same_bio: count = min(count, nbytes); goto same_bio; } + } else { + blk_unget_page(page, &pvec); } /* bio is ready, submit it */ @@ -315,6 +363,7 @@ backout: return PTR_ERR(page); goto completion; } +#endif static int blkdev_writepage(struct page *page, struct writeback_control *wbc) { @@ -411,7 +460,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { memset(bdev, 0, sizeof(*bdev)); mutex_init(&bdev->bd_mutex); - mutex_init(&bdev->bd_mount_mutex); + sema_init(&bdev->bd_mount_sem, 1); INIT_LIST_HEAD(&bdev->bd_inodes); INIT_LIST_HEAD(&bdev->bd_list); #ifdef CONFIG_SYSFS