fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / nfs / symlink.c
index 35f1065..525c136 100644 (file)
 
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
- *
- * At the beginning of the page we store pointer to struct page in question,
- * simplifying nfs_put_link() (if inode got invalidated we can't find the page
- * to be freed via pagecache lookup).
- * The NUL-terminated string follows immediately thereafter.
  */
 
-struct nfs_symlink {
-       struct page *page;
-       char body[0];
-};
-
 static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
-       const unsigned int pgbase = offsetof(struct nfs_symlink, body);
-       const unsigned int pglen = PAGE_SIZE - pgbase;
        int error;
 
-       lock_kernel();
-       error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen);
-       unlock_kernel();
+       error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
        if (error < 0)
                goto error;
        SetPageUptodate(page);
@@ -60,12 +46,13 @@ error:
        return -EIO;
 }
 
-static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        struct page *page;
-       struct nfs_symlink *p;
-       void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
+       void *err;
+
+       err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
        if (err)
                goto read_failed;
        page = read_cache_page(&inode->i_data, 0,
@@ -78,31 +65,14 @@ static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
                err = ERR_PTR(-EIO);
                goto getlink_read_error;
        }
-       p = kmap(page);
-       p->page = page;
-       nd_set_link(nd, p->body);
-       return 0;
+       nd_set_link(nd, kmap(page));
+       return page;
 
 getlink_read_error:
        page_cache_release(page);
 read_failed:
        nd_set_link(nd, err);
-       return 0;
-}
-
-static void nfs_put_link(struct dentry *dentry, struct nameidata *nd)
-{
-       char *s = nd_get_link(nd);
-       if (!IS_ERR(s)) {
-               struct nfs_symlink *p;
-               struct page *page;
-
-               p = container_of(s, struct nfs_symlink, body[0]);
-               page = p->page;
-
-               kunmap(page);
-               page_cache_release(page);
-       }
+       return NULL;
 }
 
 /*
@@ -111,7 +81,7 @@ static void nfs_put_link(struct dentry *dentry, struct nameidata *nd)
 struct inode_operations nfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .follow_link    = nfs_follow_link,
-       .put_link       = nfs_put_link,
+       .put_link       = page_put_link,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
 };