]> git.hungrycats.org Git - linux/commitdiff
v2.4.10.0.2 -> v2.4.10.0.3
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:19:55 +0000 (20:19 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:19:55 +0000 (20:19 -0800)
  - more buffers-in-pagecache coherency

drivers/block/loop.c
drivers/ide/ide-disk.c
drivers/ide/ide-floppy.c
fs/block_dev.c
fs/buffer.c
include/linux/fs.h
kernel/ksyms.c
mm/filemap.c

index e5accb20dce24770d58fcb7f9218703f886e6be5..f00a31c7818b1864d6d0342617c38a5d3aac8069 100644 (file)
@@ -719,7 +719,7 @@ static int loop_init_xfer(struct loop_device *lo, int type,struct loop_info *i)
        return err;
 }  
 
-static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
+static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 {
        struct file *filp = lo->lo_backing_file;
        int gfp = lo->old_gfp_mask;
@@ -752,7 +752,7 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_name, 0, LO_NAME_SIZE);
        loop_sizes[lo->lo_number] = 0;
-       invalidate_buffers(dev);
+       invalidate_bdev(bdev, 0);
        filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp;
        lo->lo_state = Lo_unbound;
        fput(filp);
@@ -852,7 +852,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
                err = loop_set_fd(lo, file, inode->i_rdev, arg);
                break;
        case LOOP_CLR_FD:
-               err = loop_clr_fd(lo, inode->i_rdev);
+               err = loop_clr_fd(lo, inode->i_bdev);
                break;
        case LOOP_SET_STATUS:
                err = loop_set_status(lo, (struct loop_info *) arg);
index f7dedd9102b7e133d3762702f86e02d33e99bbca..b6863cfa38d3ca3730cb261752c96a651b49e509 100644 (file)
@@ -481,7 +481,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
 static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
        if (drive->removable && !drive->usage) {
-               invalidate_buffers(inode->i_rdev);
+               invalidate_bdev(inode->i_bdev, 0);
                if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL))
                        drive->doorlocking = 0;
        }
index 235298181e3d45dbae31b064dd05f701cfea7c48..cddd0bbd2d4772834dce8f8a734ccf472f423798 100644 (file)
@@ -1750,7 +1750,7 @@ static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive
        if (!drive->usage) {
                idefloppy_floppy_t *floppy = drive->driver_data;
 
-               invalidate_buffers (inode->i_rdev);
+               invalidate_bdev (inode->i_bdev, 0);
 
                /* IOMEGA Clik! drives do not support lock/unlock commands */
                 if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
index a56d71023901bd5f8e92389248b709bec3d16481..bacd38eff70794e679fc92728ef56970622c8d39 100644 (file)
@@ -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)
index c70bda8fed5d7591b6e9e894ce09f53d4f9cbe5f..4ec521f822dfc65672584ea63a096d98bc139187 100644 (file)
@@ -86,7 +86,6 @@ static int nr_unused_buffer_heads;
 static spinlock_t unused_list_lock = SPIN_LOCK_UNLOCKED;
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
-static void truncate_buffers(kdev_t dev);
 static int grow_buffers(kdev_t dev, unsigned long block, int size);
 static void __refile_buffer(struct buffer_head *);
 
@@ -633,10 +632,11 @@ int inode_has_buffers(struct inode *inode)
    we think the disk contains more recent information than the buffercache.
    The update == 1 pass marks the buffers we need to update, the update == 2
    pass does the actual I/O. */
-void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
+void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
 {
        int i, nlist, slept;
        struct buffer_head * bh, * bh_next;
+       kdev_t dev = to_kdev_t(bdev->bd_dev);   /* will become bdev */
 
  retry:
        slept = 0;
@@ -691,30 +691,16 @@ out:
                goto retry;
 
        /* Get rid of the page cache */
-       truncate_buffers(dev);
+       invalidate_inode_pages(bdev->bd_inode);
 }
 
-void set_blocksize(kdev_t dev, int size)
+void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
 {
-       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;
+       struct block_device *bdev = bdget(dev);
+       if (bdev) {
+               invalidate_bdev(bdev, destroy_dirty_buffers);
+               bdput(bdev);
        }
-       if (blksize_size[MAJOR(dev)][MINOR(dev)] == size)
-               return;
-
-       sync_buffers(dev, 2);
-       blksize_size[MAJOR(dev)][MINOR(dev)] = size;
-       invalidate_buffers(dev);
 }
 
 static void free_more_memory(void)
@@ -2345,13 +2331,6 @@ static int grow_buffers(kdev_t dev, unsigned long block, int size)
        return 1;
 }
 
-static void truncate_buffers(kdev_t dev)
-{
-       struct block_device *bdev = bdget(kdev_t_to_nr(dev));
-       truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
-       atomic_dec(&bdev->bd_count);
-}
-
 static int sync_page_buffers(struct buffer_head *bh, unsigned int gfp_mask)
 {
        struct buffer_head * p = bh;
index 6d6066c6c228d7fc72e86938305c872fdd64d9cd..e7efa4151b33e9fd3500853502a29847e0f39e48 100644 (file)
@@ -1167,6 +1167,7 @@ extern void invalidate_inode_pages2(struct address_space *);
 extern void invalidate_inode_buffers(struct inode *);
 #define invalidate_buffers(dev)        __invalidate_buffers((dev), 0)
 #define destroy_buffers(dev)   __invalidate_buffers((dev), 1)
+extern void invalidate_bdev(struct block_device *, int);
 extern void __invalidate_buffers(kdev_t dev, int);
 extern void sync_inodes(kdev_t);
 extern void sync_unlocked_inodes(void);
index 766a454f44a3c09fa73923aa19798d01fb8e43bb..7a920ffc969457ef716ad9100b189d81b3ad5b52 100644 (file)
@@ -172,6 +172,7 @@ EXPORT_SYMBOL(put_filp);
 EXPORT_SYMBOL(files_lock);
 EXPORT_SYMBOL(check_disk_change);
 EXPORT_SYMBOL(__invalidate_buffers);
+EXPORT_SYMBOL(invalidate_bdev);
 EXPORT_SYMBOL(invalidate_inodes);
 EXPORT_SYMBOL(invalidate_device);
 EXPORT_SYMBOL(invalidate_inode_pages);
index b8d1e90ada584c522371c133064b3f103f8d214e..19acb84a74bcff7dc5188897fd9f63ad791a50f2 100644 (file)
@@ -172,11 +172,7 @@ void invalidate_inode_pages(struct inode * inode)
                page = list_entry(curr, struct page, list);
                curr = curr->next;
 
-               /* We cannot invalidate something in use.. */
-               if (page_count(page) != 1)
-                       continue;
-
-               /* ..or dirty.. */
+               /* We cannot invalidate something in dirty.. */
                if (PageDirty(page))
                        continue;
 
@@ -184,10 +180,20 @@ void invalidate_inode_pages(struct inode * inode)
                if (TryLockPage(page))
                        continue;
 
+               if (page->buffers && !try_to_free_buffers(page, 0))
+                       goto unlock;
+
+               if (page_count(page) != 1)
+                       goto unlock;
+
                __lru_cache_del(page);
                __remove_inode_page(page);
                UnlockPage(page);
                page_cache_release(page);
+               continue;
+unlock:
+               UnlockPage(page);
+               continue;
        }
 
        spin_unlock(&pagemap_lru_lock);