Re: [PATCH] int (*readpage)(struct file *, struct page *);

From: Alexander Viro (aviro@redhat.com)
Date: Fri May 12 2000 - 05:52:20 EDT

  • Next message: Malcolm Beattie: "Re: For Alan Cox ..."

    On Fri, 12 May 2000, Roman V. Shaposhnick wrote:

    > Jeff,
    >
    > I see no point in your arguments. The situation is pretty simple:
    >
    > 1. if it's general -- use it with extreme care and check
    > every new unstable kernel for modifications.
    > 2. if it's yours -- just track changes in relevant
    > areas.
    >
    > what else do you need ?

    Erm... For one thing, to avoid doing pagecache handling by hands?

    > On Thu, May 11, 2000 at 12:55:03PM -0600, Jeff V. Merkey wrote:
    [snip]
    > > static int nwfs_symlink_readpage(struct dentry *dentry, struct page
    > > *page)
    > > {
    > > register int length, count;
    > > BYTE *buf = (BYTE *) kmap(page);
    > >
    > > length = dentry->d_inode->i_size; // I assume I should be using
    > > page->mapping->host here to
    > > // obtain the inode * to get the
    > > size?
    > >
    > > count = nwfs_readlink(dentry, buf, length);

                                  ^^^^^^ --- see that?

    > > int nwfs_readlink(struct dentry *dentry, char *buffer, int bufsiz)
    > > {
    > > size_t size = dentry->d_inode->i_size;
    > > loff_t loffs = 0;
    > > ssize_t ret;
    > > struct file filp;
    > >
    > > NWFSSet(&filp, 0, sizeof(struct file));
    > > filp.f_reada = 1;
    > > filp.f_dentry = dentry;
    > > filp.f_reada = 0;
    > > filp.f_flags = O_RDONLY;

            Ewwww... Jeff, is it really needed? I mean,
                    1) do you actually need the dentry here - isn't inode enough?
                    2) fake struct file... ;-/

    > > Looks like NCPFS, SMPFS, NWFS, and several other FS's will be affected
    > > and need to instrument this change.

            One way around it is to use nfs/symlink.c trick - do RPC with result
    in pagecache and use the page+<offset_of_symlink_body> (in RPC reply, that is).
    In case of NFS you have a helper function that gets a page, forms a READLINK
    request in it and passes it to RPC, asking for reply in the same place. Result
    has symlink body at offset 4 bytes, thus the rest of code there. Function is
    nfs_symlink_filler(), the rest is done with

    static char *nfs_getlink(struct dentry *dentry, struct page **ppage)
    {
            struct inode *inode = dentry->d_inode;
            struct page *page;
            u32 *p;

            page = read_cache_page(&inode->i_data, 0,
                                    (filler_t *)nfs_symlink_filler, dentry);
            if (IS_ERR(page))
                    goto read_failed;
            if (!Page_Uptodate(page))
                    goto getlink_read_error;
            *ppage = page;
            p = (u32 *) kmap(page);
            return (char*)(p+1); /* offset 4 from the beginning of reply */

    getlink_read_error:
            page_cache_release(page);
            return ERR_PTR(-EIO);
    read_failed:
            return (char*)page;
    }

    does the trick - nfs_follow_link() and nfs_readlink() are trivially done via
    that. Modify as you feel appropriate and there you go.

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



    This archive was generated by hypermail 2b29 : Fri May 12 2000 - 05:58:01 EDT