patch-2.3.30 linux/fs/nfs/symlink.c
Next file: linux/fs/nfs/write.c
Previous file: linux/fs/nfs/read.c
Back to the patch index
Back to the overall index
- Lines: 175
- Date:
Sun Dec 5 08:42:03 1999
- Orig file:
v2.3.29/linux/fs/nfs/symlink.c
- Orig date:
Tue Nov 23 22:42:21 1999
diff -u --recursive --new-file v2.3.29/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
@@ -46,126 +46,101 @@
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
/* Symlink caching in the page cache is even more simplistic
* and straight-forward than readdir caching.
*/
-static struct page *try_to_get_symlink_page(struct dentry *dentry, struct inode *inode)
+static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
{
struct nfs_readlinkargs rl_args;
- struct page *page, **hash, *page_cache;
-
- page = NULL;
- page_cache = page_cache_alloc();
- if (!page_cache)
- goto out;
-
- hash = page_hash(&inode->i_data, 0);
-repeat:
- page = __find_lock_page(&inode->i_data, 0, hash);
- if (page) {
- page_cache_free(page_cache);
- goto unlock_out;
- }
-
- page = page_cache;
- if (add_to_page_cache_unique(page, &inode->i_data, 0, hash)) {
- page_cache_release(page);
- goto repeat;
- }
-
kmap(page);
-
/* 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.
*/
rl_args.fh = NFS_FH(dentry);
- rl_args.buffer = (const void *)page_address(page_cache);
- if (rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK,
+ rl_args.buffer = (const void *)page_address(page);
+ if (rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_READLINK,
&rl_args, NULL, 0) < 0)
goto error;
SetPageUptodate(page);
-unlock_out:
kunmap(page);
UnlockPage(page);
-out:
- return page;
+ return 0;
error:
SetPageError(page);
- goto unlock_out;
+ kunmap(page);
+ UnlockPage(page);
+ return -EIO;
}
-static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static char *nfs_getlink(struct dentry *dentry, struct page **ppage)
{
struct inode *inode = dentry->d_inode;
struct page *page;
- u32 *p, len;
+ u32 *p;
/* Caller revalidated the directory inode already. */
- page = find_get_page(&inode->i_data, 0);
- if (!page)
- goto no_readlink_page;
+ 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 readlink_read_error;
-success:
+ goto followlink_read_error;
+ *ppage = page;
p = (u32 *) kmap(page);
- len = *p++;
+ return (char*)(p+1);
+
+followlink_read_error:
+ page_cache_release(page);
+ return ERR_PTR(-EIO);
+read_failed:
+ return (char*)page;
+}
+
+static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ struct page *page = NULL;
+ u32 len;
+ char *s = nfs_getlink(dentry, &page);
+ UPDATE_ATIME(dentry->d_inode);
+
+ len = PTR_ERR(s);
+ if (IS_ERR(s))
+ goto out;
+
+ len = strlen(s);
if (len > buflen)
len = buflen;
- copy_to_user(buffer, p, len);
+ copy_to_user(buffer, s, len);
kunmap(page);
page_cache_release(page);
+out:
return len;
-
-no_readlink_page:
- page = try_to_get_symlink_page(dentry, inode);
- if (!page)
- goto no_page;
- if (Page_Uptodate(page))
- goto success;
-readlink_read_error:
- page_cache_release(page);
-no_page:
- return -EIO;
}
static struct dentry *
nfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
{
struct dentry *result;
- struct inode *inode = dentry->d_inode;
- struct page *page;
- u32 *p;
+ struct page *page = NULL;
+ char *s = nfs_getlink(dentry, &page);
+ UPDATE_ATIME(dentry->d_inode);
+
+ if (IS_ERR(s))
+ goto fail;
+
+ result = lookup_dentry(s, base, follow);
- /* Caller revalidated the directory inode already. */
- page = find_get_page(&inode->i_data, 0);
- if (!page)
- goto no_followlink_page;
- if (!Page_Uptodate(page))
- goto followlink_read_error;
-success:
- p = (u32 *) kmap(page);
- result = lookup_dentry((char *) (p + 1), base, follow);
kunmap(page);
page_cache_release(page);
return result;
-no_followlink_page:
- page = try_to_get_symlink_page(dentry, inode);
- if (!page)
- goto no_page;
- if (Page_Uptodate(page))
- goto success;
-followlink_read_error:
- page_cache_release(page);
-no_page:
- return ERR_PTR(-EIO);
+fail:
+ return (struct dentry *)s;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)