Merge to kernel-2.6.20-1.2949.fc6.vs2.2.0.1
[linux-2.6.git] / fs / nfs / symlink.c
index d601eb7..525c136 100644 (file)
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
  */
+
 static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
        int error;
 
-       /* We place the length at the beginning of the page,
-        * in host byte order, followed by the string.  The
-        * XDR response verification will NULL terminate it.
-        */
-       lock_kernel();
-       error = NFS_PROTO(inode)->readlink(inode, page);
-       unlock_kernel();
+       error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE);
        if (error < 0)
                goto error;
        SetPageUptodate(page);
@@ -51,54 +46,33 @@ error:
        return -EIO;
 }
 
-enum {
-       Page_Offset = (PAGE_SIZE - sizeof(void *)) / 4
-};
-
-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;
-       u32 *p;
+       void *err;
 
-       page = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
-       if (page)
+       err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
+       if (err)
                goto read_failed;
        page = read_cache_page(&inode->i_data, 0,
                                (filler_t *)nfs_symlink_filler, inode);
-       if (IS_ERR(page))
+       if (IS_ERR(page)) {
+               err = page;
                goto read_failed;
-       if (!PageUptodate(page))
+       }
+       if (!PageUptodate(page)) {
+               err = ERR_PTR(-EIO);
                goto getlink_read_error;
-       p = kmap(page);
-       if (*p > Page_Offset * 4 - 1 - 4)
-               goto too_long;
-       *(struct page **)(p + Page_Offset) = page;
-
-       nd_set_link(nd, (char *)(p+1));
-       return 0;
+       }
+       nd_set_link(nd, kmap(page));
+       return page;
 
-too_long:
-       kunmap(page);
-       page_cache_release(page);
-       page = ERR_PTR(-ENAMETOOLONG);
-       goto read_failed;
 getlink_read_error:
        page_cache_release(page);
-       page = ERR_PTR(-EIO);
 read_failed:
-       nd_set_link(nd, (char*)page);
-       return 0;
-}
-
-static void nfs_put_link(struct dentry *dentry, struct nameidata *nd)
-{
-       u32 *s = (u32 *)nd_get_link(nd);
-       if (!IS_ERR(s)) {
-               struct page *page = *(struct page **)(s + Page_Offset - 1);
-               kunmap(page);
-               page_cache_release(page);
-       }
+       nd_set_link(nd, err);
+       return NULL;
 }
 
 /*
@@ -107,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,
 };