X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnfs%2Fsymlink.c;h=525c136c7d8ce34ff341151cd9c7230bff8cc5b1;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=fabadfbfd47ea43890cfb30df05b48ec16174564;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index fabadfbfd..525c136c7 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -23,21 +23,17 @@ #include #include #include +#include /* 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); @@ -50,61 +46,42 @@ error: return -EIO; } -static char *nfs_getlink(struct inode *inode, struct page **ppage) +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; - *ppage = page; - p = kmap(page); - return (char*)(p+1); + } + nd_set_link(nd, kmap(page)); + return page; getlink_read_error: page_cache_release(page); - page = ERR_PTR(-EIO); read_failed: - return (char*)page; -} - -static int nfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) -{ - struct inode *inode = dentry->d_inode; - struct page *page = NULL; - int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(inode,&page)); - if (page) { - kunmap(page); - page_cache_release(page); - } - return res; -} - -static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) -{ - struct inode *inode = dentry->d_inode; - struct page *page = NULL; - int res = vfs_follow_link(nd, nfs_getlink(inode,&page)); - if (page) { - kunmap(page); - page_cache_release(page); - } - return res; + nd_set_link(nd, err); + return NULL; } /* * symlinks can't do much... */ struct inode_operations nfs_symlink_inode_operations = { - .readlink = nfs_readlink, + .readlink = generic_readlink, .follow_link = nfs_follow_link, + .put_link = page_put_link, .getattr = nfs_getattr, .setattr = nfs_setattr, };