lkml.org 
[lkml]   [2000]   [Oct]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: PATCH: killing read_ahead[]


    On Wed, 25 Oct 2000, Alexander Viro wrote:

    > I can do the proof-of-concept patch (below 10Kb, ext2 + generic code, with
    > the need to repeat the fs-specific parts for other filesystems) in an
    > hour. Clearance?

    OK, it didn't take an hour. Warning: completely untested, needs
    (trivial) changes to other filesystems.

    Rules: when you change i_size for inode with non-trivial ->a_ops -
    either call update_cached_size(inode) or do the equivalent by hands
    (e.g. generic_commit_write have to mess with i_size value to update the
    ->size_in_pages and ->last_page_size - we already have them calculated).
    Ditto for the places where you set ->a_ops.

    Invariants:
    inode->i_mapping->size_in_pages ==
    (inode->i_size + PAGE_CACHE_SIZE - 1)>>PAGE_CACHE_SHIFT;
    inode->i_size == ((....->size_in_pages-1)<<PAGE_CACHE_SHIFT) +
    ....->last_page_size;

    Linus, what do you think about that? I can do the remaining filesystems
    and give it initial testing today.

    diff -urN rc10-pre5/fs/buffer.c rc10-pre5-size_in_pages/fs/buffer.c
    --- rc10-pre5/fs/buffer.c Tue Oct 24 01:27:28 2000
    +++ rc10-pre5-size_in_pages/fs/buffer.c Wed Oct 25 17:46:25 2000
    @@ -1751,6 +1751,9 @@
    kunmap(page);
    if (pos > inode->i_size) {
    inode->i_size = pos;
    + /* to is always positive */
    + page->mapping->size_in_pages = page->index+1;
    + page->mapping->last_page_size = to;
    mark_inode_dirty(inode);
    }
    return 0;
    @@ -1835,19 +1838,22 @@
    int block_write_full_page(struct page *page, get_block_t *get_block)
    {
    struct inode *inode = (struct inode*)page->mapping->host;
    - unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
    + unsigned long end_index = page->mapping->size_in_pages;
    unsigned offset;
    int err;

    /* easy case */
    - if (page->index < end_index)
    - return __block_write_full_page(inode, page, get_block);
    -
    - /* things got complicated... */
    - offset = inode->i_size & (PAGE_CACHE_SIZE-1);
    + if (page->index+1 < end_index)
    + goto easy;
    /* OK, are we completely out? */
    - if (page->index >= end_index+1 || !offset)
    + if (page->index+1 > end_index)
    return -EIO;
    +
    + offset = inode->i_mapping->last_page_size;
    + /* Another easy case - 'partial' page is not */
    + if (offset == PAGE_CACHE_SIZE)
    + goto easy;
    +
    /* Sigh... will have to work, then... */
    err = __block_prepare_write(inode, page, 0, offset, get_block);
    if (!err) {
    @@ -1860,6 +1866,8 @@
    }
    ClearPageUptodate(page);
    goto done;
    +easy:
    + return __block_write_full_page(inode, page, get_block);
    }

    int generic_block_bmap(struct address_space *mapping, long block, get_block_t *get_block)
    diff -urN rc10-pre5/fs/ext2/inode.c rc10-pre5-size_in_pages/fs/ext2/inode.c
    --- rc10-pre5/fs/ext2/inode.c Wed Oct 4 03:44:54 2000
    +++ rc10-pre5-size_in_pages/fs/ext2/inode.c Wed Oct 25 17:41:24 2000
    @@ -54,6 +54,8 @@
    mark_inode_dirty(inode);
    ext2_update_inode(inode, IS_SYNC(inode));
    inode->i_size = 0;
    + inode.i_data->size_in_pages = 0;
    + inode.i_data->last_page_size = PAGE_CACHE_SIZE;
    if (inode->i_blocks)
    ext2_truncate (inode);
    ext2_free_inode (inode);
    @@ -1063,6 +1065,7 @@
    inode->i_op = &ext2_file_inode_operations;
    inode->i_fop = &ext2_file_operations;
    inode->i_mapping->a_ops = &ext2_aops;
    + update_cached_size(inode);
    } else if (S_ISDIR(inode->i_mode)) {
    inode->i_op = &ext2_dir_inode_operations;
    inode->i_fop = &ext2_dir_operations;
    @@ -1072,6 +1075,7 @@
    else {
    inode->i_op = &page_symlink_inode_operations;
    inode->i_mapping->a_ops = &ext2_aops;
    + update_cached_size(inode);
    }
    } else
    init_special_inode(inode, inode->i_mode,
    diff -urN rc10-pre5/fs/inode.c rc10-pre5-size_in_pages/fs/inode.c
    --- rc10-pre5/fs/inode.c Tue Oct 24 01:27:29 2000
    +++ rc10-pre5-size_in_pages/fs/inode.c Wed Oct 25 17:39:28 2000
    @@ -529,6 +529,8 @@
    inode->i_bdev = NULL;
    inode->i_data.a_ops = &empty_aops;
    inode->i_data.host = (void*)inode;
    + inode->i_data.size_in_pages = 0;
    + inode->i_data.last_page_size = PAGE_CACHE_SIZE;
    inode->i_mapping = &inode->i_data;
    }

    diff -urN rc10-pre5/include/linux/fs.h rc10-pre5-size_in_pages/include/linux/fs.h
    --- rc10-pre5/include/linux/fs.h Tue Oct 24 01:27:36 2000
    +++ rc10-pre5-size_in_pages/include/linux/fs.h Wed Oct 25 17:31:40 2000
    @@ -366,6 +366,8 @@
    struct vm_area_struct *i_mmap; /* list of private mappings */
    struct vm_area_struct *i_mmap_shared; /* list of shared mappings */
    spinlock_t i_shared_lock; /* and spinlock protecting it */
    + unsigned long size_in_pages;
    + unsigned last_page_size;
    };

    struct block_device {
    @@ -456,6 +458,16 @@
    #define I_LOCK 2
    #define I_FREEING 4
    #define I_CLEAR 8
    +
    +static inline void update_cached_size(struct inode *inode)
    +{
    + loff_t size = inode->i_size;
    + inode->i_mapping.size_in_pages =
    + (size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
    + if ((size &= ~PAGE_CACHE_MASK) == 0)
    + size = PAGE_CACHE_SIZE;
    + inode->i_mapping.last_page_size = size;
    +}

    extern void __mark_inode_dirty(struct inode *);
    static inline void mark_inode_dirty(struct inode *inode)
    diff -urN rc10-pre5/mm/filemap.c rc10-pre5-size_in_pages/mm/filemap.c
    --- rc10-pre5/mm/filemap.c Tue Oct 24 01:27:38 2000
    +++ rc10-pre5-size_in_pages/mm/filemap.c Wed Oct 25 17:43:01 2000
    @@ -429,8 +429,7 @@
    */
    static inline int page_cache_read(struct file * file, unsigned long offset)
    {
    - struct inode *inode = file->f_dentry->d_inode;
    - struct address_space *mapping = inode->i_mapping;
    + struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
    struct page **hash = page_hash(mapping, offset);
    struct page *page;

    @@ -633,8 +632,7 @@
    */
    static void drop_behind(struct file * file, unsigned long index)
    {
    - struct inode *inode = file->f_dentry->d_inode;
    - struct address_space *mapping = inode->i_mapping;
    + struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
    struct page **hash;
    struct page *page;
    unsigned long start;
    @@ -794,7 +792,7 @@
    struct file * filp, struct inode * inode,
    struct page * page)
    {
    - unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
    + unsigned long end_index = inode->i_mapping->size_in_pages;
    unsigned long index = page->index;
    unsigned long max_ahead, ahead;
    unsigned long raend;
    @@ -819,8 +817,8 @@
    filp->f_rawin = 0;
    filp->f_ralen = 1;
    if (!max_ahead) {
    - filp->f_raend = index + filp->f_ralen;
    - filp->f_rawin += filp->f_ralen;
    + filp->f_raend = index + 1;
    + filp->f_rawin = 1;
    }
    }
    }
    @@ -966,14 +964,14 @@

    for (;;) {
    struct page *page, **hash;
    - unsigned long end_index, nr;
    + unsigned nr;

    - end_index = inode->i_size >> PAGE_CACHE_SHIFT;
    - if (index > end_index)
    + if (index >= mapping->size_in_pages)
    break;
    +
    nr = PAGE_CACHE_SIZE;
    - if (index == end_index) {
    - nr = inode->i_size & ~PAGE_CACHE_MASK;
    + if (index == mapping->size_in_pages - 1) {
    + nr = mapping->last_page_size;
    if (nr <= offset)
    break;
    }
    @@ -1328,10 +1326,9 @@
    {
    int error;
    struct file *file = area->vm_file;
    - struct inode *inode = file->f_dentry->d_inode;
    - struct address_space *mapping = inode->i_mapping;
    + struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
    struct page *page, **hash, *old_page;
    - unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
    + unsigned long size = mapping->size_in_pages;

    unsigned long pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;

    @@ -1910,8 +1907,7 @@
    if (!vma->vm_file)
    return error;
    file = vma->vm_file;
    - size = (file->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >>
    - PAGE_CACHE_SHIFT;
    + size = file->f_dentry->d_inode->i_mapping->size_in_pages;

    start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
    if (end > vma->vm_end)
    diff -urN rc10-pre5/mm/memory.c rc10-pre5-size_in_pages/mm/memory.c
    --- rc10-pre5/mm/memory.c Tue Oct 24 01:27:38 2000
    +++ rc10-pre5-size_in_pages/mm/memory.c Wed Oct 25 17:44:14 2000
    @@ -979,6 +979,7 @@
    if (inode->i_size < offset)
    goto do_expand;
    inode->i_size = offset;
    + update_cached_size(inode);
    truncate_inode_pages(mapping, offset);
    spin_lock(&mapping->i_shared_lock);
    if (!mapping->i_mmap && !mapping->i_mmap_shared)
    @@ -1013,6 +1014,7 @@
    }
    }
    inode->i_size = offset;
    + update_cached_size(inode);
    if (inode->i_op && inode->i_op->truncate)
    inode->i_op->truncate(inode);
    out:
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 12:41    [W:0.031 / U:94.588 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site