[RFC][PATCH] read_cache_page() cleanup

From: Alexander Viro (viro@math.psu.edu)
Date: Sat Mar 10 2001 - 02:44:37 EST

  • Next message: Alexander Viro: "Re: [RFC] Directory index for Ext2 - the pagecache version"

            Folks, looks like we can simplify both the callers of read_cache_page
    and function itself. Without breaking existing code.
    a) all but two callers do the following:

            page = read_cache_page(...);
            if (IS_ERR(page))
                    goto fail;
            wait_on_page(page);
            if (!PageUptodate(page) {
                    page_cache_release(page);
                    page = ERR_PTR(-EIO);
                    goto fail;
            }

    or equivalents of that.

    b) two exceptions are in NFS readdir and symlink handling resp. There we
    do not call wait_on_page(). However, in both cases filler _always_ unlocks
    page before returning. I.e. wait_on_page() would be a no-op - could as
    well have it there.

    c) after moving the wait_on_page() and check for page being not uptodate
    after it into the read_cache_page() the function itself becomes simpler.
    I've substituted __read_cache_page() in place of its call and did an
    obvious cleanup of the result.

    The bottom line: __read_cache_page() is gone, callers of read_cache_page()
    dropped the waiting/handling of async errors, read_cache_page() returns
    either an uptodate page or error.

    Notice that read_cache_page() never was really async - only if we had a
    page already in pagecache, not locked and not uptodate. BTW, if page
    was _not_ in pagecache and filler got an asynchronous error we used
    to cald it again. For no good reason. AFAICS patch below cleans the things
    up and shouldn't break anything - code that used to work should work with
    new variant. I'd definitely like to see it applied - IMO it counts as
    obvious cleanup... Comments?
                                                            Cheers,
                                                                    Al
    Patch (against 2.4.3-pre3) follows:
    diff -urN S3-pre3/fs/namei.c S3-pre3-read_cache_page/fs/namei.c
    --- S3-pre3/fs/namei.c Fri Feb 16 21:20:06 2001
    +++ S3-pre3-read_cache_page/fs/namei.c Sat Mar 10 00:47:09 2001
    @@ -1952,18 +1952,11 @@
             page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage,
                                     NULL);
             if (IS_ERR(page))
    - goto sync_fail;
    - wait_on_page(page);
    - if (!Page_Uptodate(page))
    - goto async_fail;
    + goto fail;
             *ppage = page;
             return kmap(page);
     
    -async_fail:
    - page_cache_release(page);
    - return ERR_PTR(-EIO);
    -
    -sync_fail:
    +fail:
             return (char*)page;
     }
     
    diff -urN S3-pre3/fs/nfs/dir.c S3-pre3-read_cache_page/fs/nfs/dir.c
    --- S3-pre3/fs/nfs/dir.c Thu Mar 8 06:33:59 2001
    +++ S3-pre3-read_cache_page/fs/nfs/dir.c Sat Mar 10 00:47:45 2001
    @@ -197,8 +197,6 @@
                     status = PTR_ERR(page);
                     goto out;
             }
    - if (!Page_Uptodate(page))
    - goto read_error;
     
             /* NOTE: Someone else may have changed the READDIRPLUS flag */
             desc->plus = NFS_USE_READDIRPLUS(inode);
    @@ -210,9 +208,6 @@
      out:
             dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status);
             return status;
    - read_error:
    - page_cache_release(page);
    - return -EIO;
     }
     
     /*
    diff -urN S3-pre3/fs/nfs/symlink.c S3-pre3-read_cache_page/fs/nfs/symlink.c
    --- S3-pre3/fs/nfs/symlink.c Fri Feb 16 22:52:05 2001
    +++ S3-pre3-read_cache_page/fs/nfs/symlink.c Sat Mar 10 00:48:02 2001
    @@ -64,15 +64,10 @@
                                     (filler_t *)nfs_symlink_filler, inode);
             if (IS_ERR(page))
                     goto read_failed;
    - if (!Page_Uptodate(page))
    - goto getlink_read_error;
             *ppage = page;
             p = kmap(page);
             return (char*)(p+1);
                     
    -getlink_read_error:
    - page_cache_release(page);
    - return ERR_PTR(-EIO);
     read_failed:
             return (char*)page;
     }
    diff -urN S3-pre3/fs/umsdos/dir.c S3-pre3-read_cache_page/fs/umsdos/dir.c
    --- S3-pre3/fs/umsdos/dir.c Fri Feb 16 22:52:06 2001
    +++ S3-pre3-read_cache_page/fs/umsdos/dir.c Sat Mar 10 00:48:45 2001
    @@ -692,9 +692,6 @@
             dentry_dst=(struct dentry *)page;
             if (IS_ERR(page))
                     goto out;
    - wait_on_page(page);
    - if (!Page_Uptodate(page))
    - goto async_fail;
     
             dentry_dst = ERR_PTR(-ENOMEM);
             path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
    @@ -776,8 +773,6 @@
             dput(hlink); /* original hlink no longer needed */
             return dentry_dst;
     
    -async_fail:
    - dentry_dst = ERR_PTR(-EIO);
     out_release:
             page_cache_release(page);
             goto out;
    diff -urN S3-pre3/fs/umsdos/emd.c S3-pre3-read_cache_page/fs/umsdos/emd.c
    --- S3-pre3/fs/umsdos/emd.c Thu Mar 8 06:33:59 2001
    +++ S3-pre3-read_cache_page/fs/umsdos/emd.c Sat Mar 10 00:51:54 2001
    @@ -125,9 +125,6 @@
                             (filler_t*)mapping->a_ops->readpage, NULL);
             if (IS_ERR(page))
                     goto sync_fail;
    - wait_on_page(page);
    - if (!Page_Uptodate(page))
    - goto async_fail;
             p = (struct umsdos_dirent*)(kmap(page)+offs);
     
             /* if this is an invalid entry (invalid name length), ignore it */
    @@ -150,12 +147,6 @@
                             page = page2;
                             goto sync_fail;
                     }
    - wait_on_page(page2);
    - if (!Page_Uptodate(page2)) {
    - kunmap(page);
    - page_cache_release(page2);
    - goto async_fail;
    - }
                     memcpy(entry->spare,p->spare,part);
                     memcpy(entry->spare+part,kmap(page2),
                                     recsize+offs-PAGE_CACHE_SIZE);
    @@ -168,9 +159,6 @@
             page_cache_release(page);
             *pos += recsize;
             return ret;
    -async_fail:
    - page_cache_release(page);
    - page = ERR_PTR(-EIO);
     sync_fail:
             return PTR_ERR(page);
     }
    @@ -395,9 +383,6 @@
                             page = read_cache_page(mapping,index,readpage,NULL);
                             if (IS_ERR(page))
                                     goto sync_fail;
    - wait_on_page(page);
    - if (!Page_Uptodate(page))
    - goto async_fail;
                             p = kmap(page);
                     }
     
    @@ -443,12 +428,6 @@
                                     page_cache_release(page);
                                     page = next_page;
                                     goto sync_fail;
    - }
    - wait_on_page(next_page);
    - if (!Page_Uptodate(next_page)) {
    - page_cache_release(page);
    - page = next_page;
    - goto async_fail;
                             }
                             q = kmap(next_page);
                             if (memcmp(entry->name, rentry->name, len) ||
    diff -urN S3-pre3/mm/filemap.c S3-pre3-read_cache_page/mm/filemap.c
    --- S3-pre3/mm/filemap.c Thu Mar 8 06:34:01 2001
    +++ S3-pre3-read_cache_page/mm/filemap.c Sat Mar 10 01:38:21 2001
    @@ -2306,8 +2306,11 @@
             return error;
     }
     
    -static inline
    -struct page *__read_cache_page(struct address_space *mapping,
    +/*
    + * Make sure that @mapping contains a page with index @index, creating a
    + * new one if needed. If that page is not uptodate - try to fill it.
    + */
    +struct page *read_cache_page(struct address_space *mapping,
                                     unsigned long index,
                                     int (*filler)(void *,struct page*),
                                     void *data)
    @@ -2315,7 +2318,8 @@
             struct page **hash = page_hash(mapping, index);
             struct page *page, *cached_page = NULL;
             int err;
    -repeat:
    +
    +retry:
             page = __find_get_page(mapping, index, hash);
             if (!page) {
                     if (!cached_page) {
    @@ -2325,53 +2329,38 @@
                     }
                     page = cached_page;
                     if (add_to_page_cache_unique(page, mapping, index, hash))
    - goto repeat;
    + goto retry;
                     cached_page = NULL;
    - err = filler(data, page);
    - if (err < 0) {
    + } else {
    + lock_page(page);
    + if (!page->mapping) {
    + UnlockPage(page);
                             page_cache_release(page);
    - page = ERR_PTR(err);
    + goto retry;
    + }
    + if (Page_Uptodate(page)) {
    + UnlockPage(page);
    + goto out1;
                     }
             }
    - if (cached_page)
    - page_cache_free(cached_page);
    - return page;
    -}
     
    -/*
    - * Read into the page cache. If a page already exists,
    - * and Page_Uptodate() is not set, try to fill the page.
    - */
    -struct page *read_cache_page(struct address_space *mapping,
    - unsigned long index,
    - int (*filler)(void *,struct page*),
    - void *data)
    -{
    - struct page *page;
    - int err;
    -
    -retry:
    - page = __read_cache_page(mapping, index, filler, data);
    - if (IS_ERR(page) || Page_Uptodate(page))
    - goto out;
    -
    - lock_page(page);
    - if (!page->mapping) {
    - UnlockPage(page);
    - page_cache_release(page);
    - goto retry;
    - }
    - if (Page_Uptodate(page)) {
    - UnlockPage(page);
    - goto out;
    - }
             err = filler(data, page);
             if (err < 0) {
                     page_cache_release(page);
                     page = ERR_PTR(err);
    + goto out1;
             }
    - out:
    + wait_on_page(page);
    + if (!Page_Uptodate(page))
    + goto async_fail;
    +out1:
    + if (cached_page)
    + page_cache_free(cached_page);
             return page;
    +async_fail:
    + page_cache_release(page);
    + page = ERR_PTR(-EIO);
    + goto out1;
     }
     
     static inline struct page * __grab_cache_page(struct address_space *mapping,

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/



    This archive was generated by hypermail 2b29 : Sat Mar 10 2001 - 02:47:33 EST