diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:19:55 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:19:55 -0800 |
| commit | fbc139f54fdb7edfec470421c2cc885d3796dfcd (patch) | |
| tree | d0b9ab9415d682b9b5c09ff5eb75962947851664 /fs/block_dev.c | |
| parent | d51c905ac6b3d259cf977038b23163d00a869c1b (diff) | |
v2.4.10.0.2 -> v2.4.10.0.3
- more buffers-in-pagecache coherency
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index a56d71023901..bacd38eff707 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -79,6 +79,45 @@ static loff_t blkdev_size(kdev_t dev) return (loff_t) blocks << BLOCK_SIZE_BITS; } +/* Kill _all_ buffers, dirty or not.. */ +static void kill_bdev(struct block_device *bdev) +{ + invalidate_bdev(bdev, 1); + truncate_inode_pages(bdev->bd_inode->i_mapping, 0); +} + +static inline void kill_buffers(kdev_t dev) +{ + struct block_device *bdev = bdget(dev); + if (bdev) { + kill_bdev(bdev); + bdput(bdev); + } +} + +void set_blocksize(kdev_t dev, int size) +{ + extern int *blksize_size[]; + + if (!blksize_size[MAJOR(dev)]) + return; + + /* Size must be a power of two, and between 512 and PAGE_SIZE */ + if (size > PAGE_SIZE || size < 512 || (size & (size-1))) + panic("Invalid blocksize passed to set_blocksize"); + + if (blksize_size[MAJOR(dev)][MINOR(dev)] == 0 && size == BLOCK_SIZE) { + blksize_size[MAJOR(dev)][MINOR(dev)] = size; + return; + } + if (blksize_size[MAJOR(dev)][MINOR(dev)] == size) + return; + + sync_buffers(dev, 2); + blksize_size[MAJOR(dev)][MINOR(dev)] = size; + kill_buffers(dev); +} + static inline int blkdev_get_block(struct inode * inode, long iblock, struct buffer_head * bh_result) { int err; @@ -352,21 +391,19 @@ static int blkdev_commit_write(struct file *file, struct page *page, */ static loff_t block_llseek(struct file *file, loff_t offset, int origin) { - long long retval; - kdev_t dev; + /* ewww */ + loff_t size = file->f_dentry->d_inode->i_bdev->bd_inode->i_size; + loff_t retval; switch (origin) { case 2: - dev = file->f_dentry->d_inode->i_rdev; - if (blk_size[MAJOR(dev)]) - offset += (loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS; - /* else? return -EINVAL? */ + offset += size; break; case 1: offset += file->f_pos; } retval = -EINVAL; - if (offset >= 0) { + if (offset >= 0 && offset <= size) { if (offset != file->f_pos) { file->f_pos = offset; file->f_reada = 0; @@ -532,7 +569,6 @@ struct block_device *bdget(dev_t dev) new_bdev->bd_dev = dev; new_bdev->bd_op = NULL; new_bdev->bd_inode = inode; - inode->i_size = blkdev_size(dev); inode->i_rdev = to_kdev_t(dev); inode->i_bdev = new_bdev; inode->i_data.a_ops = &def_blk_aops; @@ -767,6 +803,7 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind) ret = bdev->bd_op->open(bdev->bd_inode, &fake_file); if (!ret) { bdev->bd_openers++; + bdev->bd_inode->i_size = blkdev_size(rdev); } else if (!bdev->bd_openers) bdev->bd_op = NULL; } @@ -798,15 +835,18 @@ int blkdev_open(struct inode * inode, struct file * filp) lock_kernel(); if (!bdev->bd_op) bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev)); + if (bdev->bd_op) { ret = 0; if (bdev->bd_op->open) ret = bdev->bd_op->open(inode,filp); - if (!ret) + if (!ret) { bdev->bd_openers++; - else if (!bdev->bd_openers) + bdev->bd_inode->i_size = blkdev_size(inode->i_rdev); + } else if (!bdev->bd_openers) bdev->bd_op = NULL; } + unlock_kernel(); up(&bdev->bd_sem); if (ret) @@ -822,14 +862,12 @@ int blkdev_put(struct block_device *bdev, int kind) down(&bdev->bd_sem); lock_kernel(); - if (kind == BDEV_FILE) { + if (kind == BDEV_FILE) __block_fsync(bd_inode); - } else if (kind == BDEV_FS) + else if (kind == BDEV_FS) fsync_no_super(rdev); - if (!--bdev->bd_openers) { - truncate_inode_pages(bd_inode->i_mapping, 0); - invalidate_buffers(rdev); - } + if (!--bdev->bd_openers) + kill_bdev(bdev); if (bdev->bd_op->release) ret = bdev->bd_op->release(bd_inode, NULL); if (!bdev->bd_openers) |
