diff -urN RC8-rc1-bk3/fs/afs/mntpt.c RC8-rc1-bk3-symlink/fs/afs/mntpt.c --- RC8-rc1-bk3/fs/afs/mntpt.c Wed Jul 14 14:02:58 2004 +++ RC8-rc1-bk3-symlink/fs/afs/mntpt.c Thu Jul 15 06:21:31 2004 @@ -235,7 +235,7 @@ */ static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) { - struct nameidata newnd; + struct dentry *old_dentry; struct vfsmount *newmnt; int err; @@ -247,15 +247,18 @@ nd->dentry->d_name.name); newmnt = afs_mntpt_do_automount(dentry); - if (IS_ERR(newmnt)) + if (IS_ERR(newmnt)) { + path_release(nd); return PTR_ERR(newmnt); + } - struct_cpy(&newnd, nd); - newnd.dentry = dentry; - err = do_add_mount(newmnt, &newnd, 0, &afs_vfsmounts); + old_dentry = nd->dentry; + nd->dentry = dentry; + err = do_add_mount(newmnt, nd, 0, &afs_vfsmounts); + nd->dentry = old_dentry; + path_release(nd); if (!err) { - path_release(nd); mntget(newmnt); nd->mnt = newmnt; dget(newmnt->mnt_root); diff -urN RC8-rc1-bk3/fs/cifs/cifsfs.c RC8-rc1-bk3-symlink/fs/cifs/cifsfs.c --- RC8-rc1-bk3/fs/cifs/cifsfs.c Wed Jul 14 14:02:13 2004 +++ RC8-rc1-bk3-symlink/fs/cifs/cifsfs.c Thu Jul 15 06:21:31 2004 @@ -518,6 +518,7 @@ struct inode_operations cifs_symlink_inode_ops = { .readlink = cifs_readlink, .follow_link = cifs_follow_link, + .put_link = cifs_put_link, .permission = cifs_permission, /* BB add the following two eventually */ /* revalidate: cifs_revalidate, diff -urN RC8-rc1-bk3/fs/cifs/cifsfs.h RC8-rc1-bk3-symlink/fs/cifs/cifsfs.h --- RC8-rc1-bk3/fs/cifs/cifsfs.h Wed Jul 14 14:02:13 2004 +++ RC8-rc1-bk3-symlink/fs/cifs/cifsfs.h Thu Jul 15 06:21:31 2004 @@ -85,6 +85,7 @@ /* Functions related to symlinks */ extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); +extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd); extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen); extern int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname); diff -urN RC8-rc1-bk3/fs/cifs/link.c RC8-rc1-bk3-symlink/fs/cifs/link.c --- RC8-rc1-bk3/fs/cifs/link.c Wed Jul 14 14:02:13 2004 +++ RC8-rc1-bk3-symlink/fs/cifs/link.c Thu Jul 15 06:29:25 2004 @@ -20,6 +20,7 @@ */ #include #include +#include #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -94,7 +95,7 @@ int rc = -EACCES; int xid; char *full_path = NULL; - char * target_path; + char * target_path = ERR_PTR(-ENOMEM); struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; @@ -104,22 +105,17 @@ full_path = build_path_from_dentry(direntry); up(&direntry->d_sb->s_vfs_rename_sem); - if(full_path == NULL) { - FreeXid(xid); - return -ENOMEM; - } + if (!full_path) + goto out; + cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; target_path = kmalloc(PATH_MAX, GFP_KERNEL); - if(target_path == NULL) { - if (full_path) - kfree(full_path); - FreeXid(xid); - return -ENOMEM; + if (!target_path) { + target_path = ERR_PTR(-ENOMEM); + goto out; } - /* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */ - /* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */ /* BB add read reparse point symlink code and Unix extensions symlink code here BB */ if (pTcon->ses->capabilities & CAP_UNIX) @@ -139,16 +135,16 @@ /* BB Add special case check for Samba DFS symlinks */ target_path[PATH_MAX-1] = 0; - rc = vfs_follow_link(nd, target_path); + } else { + kfree(target_path); + target_path = ERR_PTR(rc); } - /* else EACCESS */ - if (target_path) - kfree(target_path); - if (full_path) - kfree(full_path); +out: + kfree(full_path); FreeXid(xid); - return rc; + nd_set_link(nd, target_path); + return 0; } int @@ -325,4 +321,11 @@ } FreeXid(xid); return rc; +} + +void cifs_put_link(struct dentry *direntry, struct nameidata *nd) +{ + char *p = nd_get_link(nd); + if (!IS_ERR(p)) + kfree(p); } diff -urN RC8-rc1-bk3/fs/namei.c RC8-rc1-bk3-symlink/fs/namei.c --- RC8-rc1-bk3/fs/namei.c Wed Jul 14 14:02:58 2004 +++ RC8-rc1-bk3-symlink/fs/namei.c Thu Jul 15 06:21:31 2004 @@ -868,29 +868,31 @@ return 0; /* something went wrong... */ if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { - struct nameidata nd_root; + struct dentry *old_dentry = nd->dentry; + struct vfsmount *old_mnt = nd->mnt; + struct qstr last = nd->last; + int last_type = nd->last_type; /* * NAME was not found in alternate root or it's a directory. Try to find * it in the normal root: */ - nd_root.last_type = LAST_ROOT; - nd_root.flags = nd->flags; - nd_root.depth = 0; - memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent)); + nd->last_type = LAST_ROOT; read_lock(¤t->fs->lock); - nd_root.mnt = mntget(current->fs->rootmnt); - nd_root.dentry = dget(current->fs->root); + nd->mnt = mntget(current->fs->rootmnt); + nd->dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); - if (path_walk(name, &nd_root)) - return 1; - if (nd_root.dentry->d_inode) { + if (path_walk(name, nd) == 0) { + if (nd->dentry->d_inode) { + dput(old_dentry); + mntput(old_mnt); + return 1; + } path_release(nd); - nd->dentry = nd_root.dentry; - nd->mnt = nd_root.mnt; - nd->last = nd_root.last; - return 1; } - path_release(&nd_root); + nd->dentry = old_dentry; + nd->mnt = old_mnt; + nd->last = last; + nd->last_type = last_type; } return 1; } @@ -943,8 +945,7 @@ } nd->mnt = mntget(current->fs->rootmnt); nd->dentry = dget(current->fs->root); - } - else{ + } else { nd->mnt = mntget(current->fs->pwdmnt); nd->dentry = dget(current->fs->pwd); } @@ -2299,12 +2300,8 @@ int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) { struct page *page; - char *s = page_getlink(dentry, &page); - if (!IS_ERR(s)) { - nd_set_link(nd, s); - s = NULL; - } - return PTR_ERR(s); + nd_set_link(nd, page_getlink(dentry, &page)); + return 0; } void page_put_link(struct dentry *dentry, struct nameidata *nd) diff -urN RC8-rc1-bk3/fs/ncpfs/inode.c RC8-rc1-bk3-symlink/fs/ncpfs/inode.c --- RC8-rc1-bk3/fs/ncpfs/inode.c Wed Jul 14 14:02:14 2004 +++ RC8-rc1-bk3-symlink/fs/ncpfs/inode.c Thu Jul 15 06:31:10 2004 @@ -235,8 +235,9 @@ #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) static struct inode_operations ncp_symlink_inode_operations = { - .readlink = page_readlink, - .follow_link = page_follow_link, + .readlink = generic_readlink, + .follow_link = page_follow_link_light, + .put_link = page_put_link, .setattr = ncp_notify_change, }; #endif diff -urN RC8-rc1-bk3/fs/nfs/symlink.c RC8-rc1-bk3-symlink/fs/nfs/symlink.c --- RC8-rc1-bk3/fs/nfs/symlink.c Mon May 26 22:21:40 2003 +++ RC8-rc1-bk3-symlink/fs/nfs/symlink.c Thu Jul 15 06:31:59 2004 @@ -23,6 +23,7 @@ #include #include #include +#include /* Symlink caching in the page cache is even more simplistic * and straight-forward than readdir caching. @@ -50,8 +51,13 @@ return -EIO; } -static char *nfs_getlink(struct inode *inode, struct page **ppage) +enum { + Page_Offset = (PAGE_SIZE - sizeof(void *)) / 4 +}; + +static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) { + struct inode *inode = dentry->d_inode; struct page *page; u32 *p; @@ -64,47 +70,44 @@ goto read_failed; if (!PageUptodate(page)) goto getlink_read_error; - *ppage = page; p = kmap(page); - return (char*)(p+1); + 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; +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: - 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; + nd_set_link(nd, (char*)page); + return 0; } -static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void nfs_put_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) { + 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); } - return res; } /* * 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 = nfs_put_link, .getattr = nfs_getattr, .setattr = nfs_setattr, }; diff -urN RC8-rc1-bk3/fs/sysfs/symlink.c RC8-rc1-bk3-symlink/fs/sysfs/symlink.c --- RC8-rc1-bk3/fs/sysfs/symlink.c Wed Jun 16 10:26:24 2004 +++ RC8-rc1-bk3-symlink/fs/sysfs/symlink.c Thu Jul 15 06:38:39 2004 @@ -5,12 +5,14 @@ #include #include #include +#include #include "sysfs.h" static struct inode_operations sysfs_symlink_inode_operations = { - .readlink = sysfs_readlink, + .readlink = generic_readlink, .follow_link = sysfs_follow_link, + .put_link = sysfs_put_link, }; static int init_symlink(struct inode * inode) @@ -140,38 +142,21 @@ } -int sysfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) +int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) { - int error = 0; + int error = -ENOMEM; unsigned long page = get_zeroed_page(GFP_KERNEL); - - if (!page) - return -ENOMEM; - - error = sysfs_getlink(dentry, (char *) page); - if (!error) - error = vfs_readlink(dentry, buffer, buflen, (char *) page); - - free_page(page); - - return error; + if (page) + error = sysfs_getlink(dentry, (char *) page); + nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); + return 0; } -int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) +void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) { - int error = 0; - unsigned long page = get_zeroed_page(GFP_KERNEL); - - if (!page) - return -ENOMEM; - - error = sysfs_getlink(dentry, (char *) page); - if (!error) - error = vfs_follow_link(nd, (char *) page); - - free_page(page); - - return error; + char *page = nd_get_link(nd); + if (!IS_ERR(page)) + free_page((unsigned long)page); } EXPORT_SYMBOL(sysfs_create_link); diff -urN RC8-rc1-bk3/fs/sysfs/sysfs.h RC8-rc1-bk3-symlink/fs/sysfs/sysfs.h --- RC8-rc1-bk3/fs/sysfs/sysfs.h Wed Jun 16 10:26:24 2004 +++ RC8-rc1-bk3-symlink/fs/sysfs/sysfs.h Thu Jul 15 06:21:31 2004 @@ -12,8 +12,8 @@ extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); extern void sysfs_remove_subdir(struct dentry *); -extern int sysfs_readlink(struct dentry *, char __user *, int ); extern int sysfs_follow_link(struct dentry *, struct nameidata *); +extern void sysfs_put_link(struct dentry *, struct nameidata *); extern struct rw_semaphore sysfs_rename_sem; static inline struct kobject *sysfs_get_kobject(struct dentry *dentry) diff -urN RC8-rc1-bk3/include/asm-i386/asm_offsets.h RC8-rc1-bk3-symlink/include/asm-i386/asm_offsets.h --- RC8-rc1-bk3/include/asm-i386/asm_offsets.h Wed Dec 31 19:00:00 1969 +++ RC8-rc1-bk3-symlink/include/asm-i386/asm_offsets.h Thu Jul 15 06:26:50 2004 @@ -0,0 +1,43 @@ +#ifndef __ASM_OFFSETS_H__ +#define __ASM_OFFSETS_H__ +/* + * DO NOT MODIFY. + * + * This file was generated by arch/i386/Makefile + * + */ + +#define SIGCONTEXT_eax 44 /* offsetof(struct sigcontext, eax) */ +#define SIGCONTEXT_ebx 32 /* offsetof(struct sigcontext, ebx) */ +#define SIGCONTEXT_ecx 40 /* offsetof(struct sigcontext, ecx) */ +#define SIGCONTEXT_edx 36 /* offsetof(struct sigcontext, edx) */ +#define SIGCONTEXT_esi 20 /* offsetof(struct sigcontext, esi) */ +#define SIGCONTEXT_edi 16 /* offsetof(struct sigcontext, edi) */ +#define SIGCONTEXT_ebp 24 /* offsetof(struct sigcontext, ebp) */ +#define SIGCONTEXT_esp 28 /* offsetof(struct sigcontext, esp) */ +#define SIGCONTEXT_eip 56 /* offsetof(struct sigcontext, eip) */ + +#define CPUINFO_x86 0 /* offsetof(struct cpuinfo_x86, x86) */ +#define CPUINFO_x86_vendor 1 /* offsetof(struct cpuinfo_x86, x86_vendor) */ +#define CPUINFO_x86_model 2 /* offsetof(struct cpuinfo_x86, x86_model) */ +#define CPUINFO_x86_mask 3 /* offsetof(struct cpuinfo_x86, x86_mask) */ +#define CPUINFO_hard_math 6 /* offsetof(struct cpuinfo_x86, hard_math) */ +#define CPUINFO_cpuid_level 8 /* offsetof(struct cpuinfo_x86, cpuid_level) */ +#define CPUINFO_x86_capability 12 /* offsetof(struct cpuinfo_x86, x86_capability) */ +#define CPUINFO_x86_vendor_id 36 /* offsetof(struct cpuinfo_x86, x86_vendor_id) */ + +#define TI_task 0 /* offsetof(struct thread_info, task) */ +#define TI_exec_domain 4 /* offsetof(struct thread_info, exec_domain) */ +#define TI_flags 8 /* offsetof(struct thread_info, flags) */ +#define TI_status 12 /* offsetof(struct thread_info, status) */ +#define TI_cpu 16 /* offsetof(struct thread_info, cpu) */ +#define TI_preempt_count 20 /* offsetof(struct thread_info, preempt_count) */ +#define TI_addr_limit 24 /* offsetof(struct thread_info, addr_limit) */ +#define TI_restart_block 28 /* offsetof(struct thread_info, restart_block) */ + +#define EXEC_DOMAIN_handler 4 /* offsetof(struct exec_domain, handler) */ +#define RT_SIGFRAME_sigcontext 164 /* offsetof(struct rt_sigframe, uc.uc_mcontext) */ +#define TSS_sysenter_esp0 -8700 /* offsetof(struct tss_struct, esp0) - sizeof(struct tss_struct) */ +#define PAGE_SIZE_asm 4096 /* PAGE_SIZE */ + +#endif