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

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


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 : Mon May 15 2000 - 21:00:20 EST