fs/dcache.c | 20 ++
- fs/exec.c | 18 +-
- fs/namei.c | 338 ++++++++++++++++++++++++++++++++++++++++---------
+ fs/exec.c | 19 +-
+ fs/namei.c | 378 +++++++++++++++++++++++++++++++++++++++++--------
fs/nfsd/vfs.c | 2
- fs/open.c | 120 +++++++++++++++--
+ fs/open.c | 120 +++++++++++++--
+ fs/proc/base.c | 1
fs/stat.c | 8 -
- include/linux/dcache.h | 28 ++++
- include/linux/fs.h | 27 +++
+ include/linux/dcache.h | 31 ++++
+ include/linux/fs.h | 28 +++
kernel/ksyms.c | 1
- 9 files changed, 478 insertions(+), 84 deletions(-)
+ 10 files changed, 522 insertions(+), 85 deletions(-)
---- linux-2.4.18-18.8.0-l12/fs/dcache.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/fs/dcache.c Wed Feb 26 17:31:36 2003
+--- linux-2.4.18-61chaos/fs/dcache.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/fs/dcache.c Sun Jun 1 21:59:04 2003
@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry)
spin_unlock(&dcache_lock);
return 0;
}
#define do_switch(x,y) do { \
---- linux-2.4.18-18.8.0-l12/fs/namei.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/fs/namei.c Wed Feb 26 16:54:17 2003
+--- linux-2.4.18-61chaos/fs/namei.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/fs/namei.c Sun Jun 1 23:14:49 2003
@@ -94,6 +94,13 @@
* XEmacs seems to be relying on it...
*/
{
int err;
if (current->link_count >= max_recursive_link)
-@@ -348,10 +377,14 @@ static inline int do_follow_link(struct
+@@ -348,10 +377,21 @@ static inline int do_follow_link(struct
current->link_count++;
current->total_link_count++;
UPDATE_ATIME(dentry->d_inode);
- err = dentry->d_inode->i_op->follow_link(dentry, nd);
++ nd->it = it;
+ if (dentry->d_inode->i_op->follow_link2)
+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
+ else
+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
++ if (!err && it != NULL && !(it->it_int_flags & IT_FL_FOLLOWED)) {
++ /* vfs_follow_link was never called */
++ intent_release(dentry, it);
++ path_release(nd);
++ err = -ENOLINK;
++ }
current->link_count--;
return err;
loop:
path_release(nd);
return -ELOOP;
}
-@@ -381,15 +414,26 @@ int follow_up(struct vfsmount **mnt, str
+@@ -381,15 +421,26 @@ int follow_up(struct vfsmount **mnt, str
return __follow_up(mnt, dentry);
}
dput(*dentry);
mntput(mounted->mnt_parent);
*dentry = dget(mounted->mnt_root);
-@@ -401,7 +445,7 @@ static inline int __follow_down(struct v
+@@ -401,7 +452,7 @@ static inline int __follow_down(struct v
int follow_down(struct vfsmount **mnt, struct dentry **dentry)
{
}
static inline void follow_dotdot(struct nameidata *nd)
-@@ -437,7 +481,7 @@ static inline void follow_dotdot(struct
+@@ -437,7 +488,7 @@ static inline void follow_dotdot(struct
mntput(nd->mnt);
nd->mnt = parent;
}
;
}
-@@ -449,7 +493,8 @@ static inline void follow_dotdot(struct
+@@ -449,7 +500,8 @@ static inline void follow_dotdot(struct
*
* We expect 'base' to be positive and a directory.
*/
{
struct dentry *dentry;
struct inode *inode;
-@@ -526,18 +571,18 @@ int link_path_walk(const char * name, st
+@@ -526,18 +578,18 @@ int link_path_walk(const char * name, st
break;
}
/* This does the actual lookups.. */
;
err = -ENOENT;
-@@ -548,8 +593,8 @@ int link_path_walk(const char * name, st
+@@ -548,8 +600,8 @@ int link_path_walk(const char * name, st
if (!inode->i_op)
goto out_dput;
dput(dentry);
if (err)
goto return_err;
-@@ -565,7 +610,7 @@ int link_path_walk(const char * name, st
+@@ -565,7 +617,7 @@ int link_path_walk(const char * name, st
nd->dentry = dentry;
}
err = -ENOTDIR;
break;
continue;
/* here ends the main loop */
-@@ -592,22 +637,23 @@ last_component:
+@@ -592,22 +644,23 @@ last_component:
if (err < 0)
break;
}
dput(dentry);
if (err)
goto return_err;
-@@ -621,7 +667,8 @@ last_component:
+@@ -621,7 +674,8 @@ last_component:
goto no_inode;
if (lookup_flags & LOOKUP_DIRECTORY) {
err = -ENOTDIR;
break;
}
goto return_base;
-@@ -658,15 +705,28 @@ out_dput:
+@@ -645,7 +699,24 @@ return_reval:
+ * Check the cached dentry for staleness.
+ */
+ dentry = nd->dentry;
+- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
++ revalidate_again:
++ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
++ err = -ESTALE;
++ if (!dentry->d_op->d_revalidate2(dentry, 0, it)) {
++ struct dentry *new;
++ err = permission(dentry->d_parent->d_inode,
++ MAY_EXEC);
++ if (err)
++ break;
++ new = real_lookup(dentry->d_parent,
++ &dentry->d_name, 0, NULL);
++ d_invalidate(dentry);
++ dput(dentry);
++ dentry = new;
++ goto revalidate_again;
++ }
++ }
++ else if (dentry && dentry->d_op && dentry->d_op->d_revalidate){
+ err = -ESTALE;
+ if (!dentry->d_op->d_revalidate(dentry, 0)) {
+ d_invalidate(dentry);
+@@ -658,15 +729,28 @@ out_dput:
dput(dentry);
break;
}
}
/* SMP-safe */
-@@ -751,6 +811,17 @@ walk_init_root(const char *name, struct
+@@ -751,6 +835,17 @@ walk_init_root(const char *name, struct
}
/* SMP-safe */
int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
{
int error = 0;
-@@ -779,7 +850,8 @@ int path_init(const char *name, unsigned
+@@ -765,6 +860,7 @@ int path_init(const char *name, unsigned
+ {
+ nd->last_type = LAST_ROOT; /* if there are only slashes... */
+ nd->flags = flags;
++ nd->it = NULL;
+ if (*name=='/')
+ return walk_init_root(name,nd);
+ read_lock(¤t->fs->lock);
+@@ -779,7 +875,8 @@ int path_init(const char *name, unsigned
* needs parent already locked. Doesn't follow mounts.
* SMP-safe.
*/
{
struct dentry * dentry;
struct inode *inode;
-@@ -802,13 +874,16 @@ struct dentry * lookup_hash(struct qstr
+@@ -802,13 +899,16 @@ struct dentry * lookup_hash(struct qstr
goto out;
}
dentry = inode->i_op->lookup(inode, new);
unlock_kernel();
if (!dentry)
-@@ -820,6 +895,12 @@ out:
+@@ -820,6 +920,12 @@ out:
return dentry;
}
/* SMP-safe */
struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
{
-@@ -841,7 +922,7 @@ struct dentry * lookup_one_len(const cha
+@@ -841,7 +947,7 @@ struct dentry * lookup_one_len(const cha
}
this.hash = end_name_hash(hash);
access:
return ERR_PTR(-EACCES);
}
-@@ -872,6 +953,23 @@ int __user_walk(const char *name, unsign
+@@ -872,6 +978,23 @@ int __user_walk(const char *name, unsign
return err;
}
/*
* It's inline, so penalty for filesystems that don't use sticky bit is
* minimal.
-@@ -1045,14 +1143,17 @@ int may_open(struct nameidata *nd, int a
+@@ -1045,14 +1168,17 @@ int may_open(struct nameidata *nd, int a
return get_lease(inode, flag);
}
struct nameidata nd;
+ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = open_flags };
int count = 0;
-
- if ((flag+1) & O_ACCMODE)
-@@ -1066,7 +1167,7 @@ struct file *filp_open(const char * path
+
+ if (!capable(CAP_SYS_ADMIN))
+@@ -1069,7 +1195,7 @@ struct file *filp_open(const char * path
* The simplest case - just a plain lookup.
*/
if (!(flag & O_CREAT)) {
if (error)
return ERR_PTR(error);
dentry = nd.dentry;
-@@ -1076,6 +1177,8 @@ struct file *filp_open(const char * path
+@@ -1079,6 +1205,8 @@ struct file *filp_open(const char * path
/*
* Create - we need to know the parent.
*/
error = path_lookup(pathname, LOOKUP_PARENT, &nd);
if (error)
return ERR_PTR(error);
-@@ -1091,7 +1194,7 @@ struct file *filp_open(const char * path
+@@ -1094,7 +1222,7 @@ struct file *filp_open(const char * path
dir = nd.dentry;
down(&dir->d_inode->i_sem);
do_last:
error = PTR_ERR(dentry);
-@@ -1100,6 +1203,7 @@ do_last:
+@@ -1103,6 +1231,7 @@ do_last:
goto exit;
}
/* Negative dentry, just create the file */
if (!dentry->d_inode) {
error = vfs_create(dir->d_inode, dentry,
-@@ -1129,12 +1233,13 @@ do_last:
+@@ -1132,12 +1261,13 @@ do_last:
error = -ELOOP;
if (flag & O_NOFOLLOW)
goto exit_dput;
goto do_link;
dput(nd.dentry);
-@@ -1149,11 +1254,13 @@ ok:
+@@ -1152,11 +1282,13 @@ ok:
if (!S_ISREG(nd.dentry->d_inode->i_mode))
open_flags &= ~O_TRUNC;
path_release(&nd);
return ERR_PTR(error);
-@@ -1172,10 +1279,15 @@ do_link:
+@@ -1175,10 +1307,22 @@ do_link:
* are done. Procfs-like symlinks just set LAST_BIND.
*/
UPDATE_ATIME(dentry->d_inode);
- error = dentry->d_inode->i_op->follow_link(dentry, &nd);
++ nd.it = ⁢
+ if (dentry->d_inode->i_op->follow_link2)
+ error = dentry->d_inode->i_op->follow_link2(dentry, &nd, &it);
+ else
+ error = dentry->d_inode->i_op->follow_link(dentry, &nd);
-+ if (error)
++ if (error) {
++ intent_release(dentry, &it);
++ } else if (!(it.it_int_flags & IT_FL_FOLLOWED)) {
++ /* vfs_follow_link was never called */
+ intent_release(dentry, &it);
++ path_release(&nd);
++ error = -ENOLINK;
++ }
dput(dentry);
if (error)
- return error;
if (nd.last_type == LAST_BIND) {
dentry = nd.dentry;
goto ok;
-@@ -1194,13 +1306,15 @@ do_link:
+@@ -1197,13 +1341,15 @@ do_link:
}
dir = nd.dentry;
down(&dir->d_inode->i_sem);
{
struct dentry *dentry;
-@@ -1208,7 +1322,7 @@ static struct dentry *lookup_create(stru
+@@ -1211,7 +1357,7 @@ static struct dentry *lookup_create(stru
dentry = ERR_PTR(-EEXIST);
if (nd->last_type != LAST_NORM)
goto fail;
if (IS_ERR(dentry))
goto fail;
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1264,7 +1378,19 @@ asmlinkage long sys_mknod(const char * f
+@@ -1267,7 +1413,19 @@ asmlinkage long sys_mknod(const char * f
error = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
error = PTR_ERR(dentry);
mode &= ~current->fs->umask;
-@@ -1285,6 +1411,7 @@ asmlinkage long sys_mknod(const char * f
+@@ -1288,6 +1446,7 @@ asmlinkage long sys_mknod(const char * f
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
path_release(&nd);
out:
putname(tmp);
-@@ -1332,7 +1459,17 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1335,7 +1494,17 @@ asmlinkage long sys_mkdir(const char * p
error = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_mkdir(nd.dentry->d_inode, dentry,
-@@ -1340,6 +1477,7 @@ asmlinkage long sys_mkdir(const char * p
+@@ -1343,6 +1512,7 @@ asmlinkage long sys_mkdir(const char * p
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
path_release(&nd);
out:
putname(tmp);
-@@ -1440,8 +1578,33 @@ asmlinkage long sys_rmdir(const char * p
+@@ -1443,8 +1613,33 @@ asmlinkage long sys_rmdir(const char * p
error = -EBUSY;
goto exit1;
}
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1499,8 +1662,17 @@ asmlinkage long sys_unlink(const char *
+@@ -1502,8 +1697,17 @@ asmlinkage long sys_unlink(const char *
error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
/* Why not before? Because we want correct error value */
-@@ -1567,15 +1739,26 @@ asmlinkage long sys_symlink(const char *
+@@ -1570,15 +1774,26 @@ asmlinkage long sys_symlink(const char *
error = path_lookup(to, LOOKUP_PARENT, &nd);
if (error)
goto out;
putname(to);
}
putname(from);
-@@ -1642,7 +1825,7 @@ asmlinkage long sys_link(const char * ol
+@@ -1645,7 +1860,7 @@ asmlinkage long sys_link(const char * ol
struct dentry *new_dentry;
struct nameidata nd, old_nd;
if (error)
goto exit;
error = path_lookup(to, LOOKUP_PARENT, &nd);
-@@ -1651,7 +1834,17 @@ asmlinkage long sys_link(const char * ol
+@@ -1654,7 +1869,17 @@ asmlinkage long sys_link(const char * ol
error = -EXDEV;
if (old_nd.mnt != nd.mnt)
goto out_release;
error = PTR_ERR(new_dentry);
if (!IS_ERR(new_dentry)) {
error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1695,7 +1888,8 @@ exit:
+@@ -1698,7 +1923,8 @@ exit:
* locking].
*/
int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
struct inode *target;
-@@ -1753,6 +1947,7 @@ int vfs_rename_dir(struct inode *old_dir
+@@ -1756,6 +1982,7 @@ int vfs_rename_dir(struct inode *old_dir
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
if (target) {
if (!error)
target->i_flags |= S_DEAD;
-@@ -1774,7 +1969,8 @@ out_unlock:
+@@ -1777,7 +2004,8 @@ out_unlock:
}
int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
{
int error;
-@@ -1805,6 +2001,7 @@ int vfs_rename_other(struct inode *old_d
+@@ -1808,6 +2036,7 @@ int vfs_rename_other(struct inode *old_d
error = -EBUSY;
else
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
double_up(&old_dir->i_zombie, &new_dir->i_zombie);
if (error)
return error;
-@@ -1816,13 +2013,14 @@ int vfs_rename_other(struct inode *old_d
+@@ -1819,13 +2048,14 @@ int vfs_rename_other(struct inode *old_d
}
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!error) {
if (old_dir == new_dir)
inode_dir_notify(old_dir, DN_RENAME);
-@@ -1864,7 +2062,7 @@ static inline int do_rename(const char *
+@@ -1867,7 +2097,7 @@ static inline int do_rename(const char *
double_lock(new_dir, old_dir);
error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry))
goto exit3;
-@@ -1880,16 +2078,37 @@ static inline int do_rename(const char *
+@@ -1883,16 +2113,37 @@ static inline int do_rename(const char *
if (newnd.last.name[newnd.last.len])
goto exit4;
}
dput(new_dentry);
exit4:
dput(old_dentry);
-@@ -1940,7 +2159,8 @@ out:
+@@ -1943,12 +2194,19 @@ out:
}
static inline int
{
int res = 0;
char *name;
-@@ -1953,7 +2173,7 @@ __vfs_follow_link(struct nameidata *nd,
+ if (IS_ERR(link))
+ goto fail;
++ if (it == NULL)
++ it = nd->it;
++ else if (it != nd->it)
++ printk("it != nd->it: tell phil@clusterfs.com\n");
++ if (it != NULL)
++ it->it_int_flags |= IT_FL_FOLLOWED;
+
+ if (*link == '/') {
+ path_release(nd);
+@@ -1956,7 +2214,7 @@ __vfs_follow_link(struct nameidata *nd,
/* weird __emul_prefix() stuff did it */
goto out;
}
out:
if (current->link_count || res || nd->last_type!=LAST_NORM)
return res;
-@@ -1975,7 +2195,13 @@ fail:
+@@ -1978,7 +2236,13 @@ fail:
int vfs_follow_link(struct nameidata *nd, const char *link)
{
}
/* get the link contents into pagecache */
-@@ -2017,7 +2243,7 @@ int page_follow_link(struct dentry *dent
+@@ -2020,7 +2284,7 @@ int page_follow_link(struct dentry *dent
{
struct page *page = NULL;
char *s = page_getlink(dentry, &page);
if (page) {
kunmap(page);
page_cache_release(page);
---- linux-2.4.18-18.8.0-l12/fs/nfsd/vfs.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/fs/nfsd/vfs.c Wed Feb 26 16:54:17 2003
+--- linux-2.4.18-61chaos/fs/nfsd/vfs.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/fs/nfsd/vfs.c Sun Jun 1 21:59:04 2003
@@ -1298,7 +1298,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
err = nfserr_perm;
} else
unlock_kernel();
if (!err && EX_ISSYNC(tfhp->fh_export)) {
nfsd_sync_dir(tdentry);
---- linux-2.4.18-18.8.0-l12/fs/open.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/fs/open.c Wed Feb 26 16:54:17 2003
+--- linux-2.4.18-61chaos/fs/open.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/fs/open.c Sun Jun 1 21:59:04 2003
@@ -19,6 +19,8 @@
#include <asm/uaccess.h>
/*
* Find an empty file descriptor entry, and mark it busy.
*/
---- linux-2.4.18-18.8.0-l12/fs/stat.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/fs/stat.c Wed Feb 26 16:54:17 2003
+--- linux-2.4.18-61chaos/fs/stat.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/fs/stat.c Sun Jun 1 21:59:04 2003
@@ -104,10 +104,12 @@ int vfs_stat(char *name, struct kstat *s
{
struct nameidata nd;
path_release(&nd);
}
return error;
---- linux-2.4.18-18.8.0-l12/fs/exec.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/fs/exec.c Wed Feb 26 16:54:17 2003
-@@ -103,13 +103,18 @@ static inline void put_binfmt(struct lin
+--- linux-2.4.18-61chaos/fs/exec.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/fs/exec.c Sun Jun 1 21:59:04 2003
+@@ -112,13 +112,18 @@ static inline void put_binfmt(struct lin
*
* Also note that we take the address to load from from the file itself.
*/
if (error)
goto out;
-@@ -121,7 +126,8 @@ asmlinkage long sys_uselib(const char *
+@@ -130,7 +135,8 @@ asmlinkage long sys_uselib(const char *
if (error)
goto exit;
error = PTR_ERR(file);
if (IS_ERR(file))
goto out;
-@@ -350,8 +356,9 @@ struct file *open_exec(const char *name)
+@@ -359,8 +365,9 @@ struct file *open_exec(const char *name)
struct inode *inode;
struct file *file;
int err = 0;
file = ERR_PTR(err);
if (!err) {
inode = nd.dentry->d_inode;
-@@ -363,7 +370,8 @@ struct file *open_exec(const char *name)
+@@ -372,8 +379,9 @@ struct file *open_exec(const char *name)
err = -EACCES;
file = ERR_PTR(err);
if (!err) {
- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(nd.dentry, &it);
if (!IS_ERR(file)) {
++ intent_release(nd.dentry, &it);
err = deny_write_access(file);
if (err) {
-@@ -976,7 +984,7 @@ int do_coredump(long signr, struct pt_re
+ fput(file);
+@@ -384,6 +392,7 @@ out:
+ return file;
+ }
+ }
++ intent_release(nd.dentry, &it);
+ path_release(&nd);
+ }
+ goto out;
+@@ -1104,7 +1113,7 @@ int do_coredump(long signr, struct pt_re
goto close_fail;
if (!file->f_op->write)
goto close_fail;
goto close_fail;
retval = binfmt->core_dump(signr, regs, file);
---- linux-2.4.18-18.8.0-l12/include/linux/dcache.h~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/include/linux/dcache.h Wed Feb 26 17:01:30 2003
-@@ -6,6 +6,25 @@
+--- linux-2.4.18-61chaos/include/linux/dcache.h~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
++++ linux-2.4.18-61chaos-root/include/linux/dcache.h Sun Jun 1 22:02:31 2003
+@@ -6,6 +6,28 @@
#include <asm/atomic.h>
#include <linux/mount.h>
+#define IT_LOOKUP (1<<4)
+#define IT_UNLINK (1<<5)
+
++#define IT_FL_LOCKED (1)
++#define IT_FL_FOLLOWED (1<<1) /* set by vfs_follow_link */
++
+struct lookup_intent {
+ int it_op;
+ int it_mode;
+ int it_flags;
+ int it_disposition;
+ int it_status;
-+ struct iattr *it_iattr;
++ int it_int_flags;
+ __u64 it_lock_handle[2];
+ int it_lock_mode;
+ void *it_data;
/*
* linux/include/linux/dcache.h
*
-@@ -78,6 +97,7 @@ struct dentry {
+@@ -78,6 +100,7 @@ struct dentry {
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */
unsigned long d_vfs_flags;
void * d_fsdata; /* fs-specific data */
void * d_extra_attributes; /* TUX-specific data */
-@@ -91,8 +111,15 @@ struct dentry_operations {
+@@ -91,8 +114,15 @@ struct dentry_operations {
int (*d_delete)(struct dentry *);
void (*d_release)(struct dentry *);
void (*d_iput)(struct dentry *, struct inode *);
/* the dentry parameter passed to d_hash and d_compare is the parent
* directory of the entries to be compared. It is used in case these
* functions need any directory specific information for determining
-@@ -124,6 +151,7 @@ d_iput: no no yes
+@@ -124,6 +154,7 @@ d_iput: no no yes
* s_nfsd_free_path semaphore will be down
*/
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
extern spinlock_t dcache_lock;
---- linux-2.4.18-18.8.0-l12/include/linux/fs.h~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/include/linux/fs.h Wed Feb 26 17:31:42 2003
-@@ -338,6 +338,8 @@ extern void set_bh_page(struct buffer_he
+--- linux-2.4.18-61chaos/include/linux/fs.h~vfs_intent-2.4.18-18 Sun Jun 1 21:59:03 2003
++++ linux-2.4.18-61chaos-root/include/linux/fs.h Sun Jun 1 22:01:46 2003
+@@ -339,6 +339,8 @@ extern void set_bh_page(struct buffer_he
#define ATTR_MTIME_SET 256
#define ATTR_FORCE 512 /* Not a change, but a change it */
#define ATTR_ATTR_FLAG 1024
/*
* This is the Inode Attributes structure, used for notify_change(). It
-@@ -576,6 +578,7 @@ struct file {
+@@ -578,6 +580,7 @@ struct file {
/* needed for tty driver, and maybe others */
void *private_data;
/* preallocated helper kiobuf to speedup O_DIRECT */
struct kiobuf *f_iobuf;
-@@ -836,7 +839,9 @@ extern int vfs_symlink(struct inode *, s
+@@ -707,6 +710,7 @@ struct nameidata {
+ struct qstr last;
+ unsigned int flags;
+ int last_type;
++ struct lookup_intent *it;
+ };
+
+ #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
+@@ -840,7 +844,9 @@ extern int vfs_symlink(struct inode *, s
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
extern int vfs_rmdir(struct inode *, struct dentry *);
extern int vfs_unlink(struct inode *, struct dentry *);
/*
* File types
-@@ -897,20 +902,33 @@ struct file_operations {
+@@ -901,20 +907,33 @@ struct file_operations {
struct inode_operations {
int (*create) (struct inode *,struct dentry *,int);
struct dentry * (*lookup) (struct inode *,struct dentry *);
int (*getattr) (struct dentry *, struct iattr *);
};
-@@ -1112,7 +1130,7 @@ static inline int get_lease(struct inode
+@@ -1119,7 +1138,7 @@ static inline int get_lease(struct inode
asmlinkage long sys_open(const char *, int, int);
asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
extern struct file *filp_open(const char *, int, int);
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
-@@ -1381,6 +1399,7 @@ typedef int (*read_actor_t)(read_descrip
+@@ -1388,6 +1407,7 @@ typedef int (*read_actor_t)(read_descrip
extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_walk(const char *, struct nameidata *));
extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1392,6 +1411,8 @@ extern struct dentry * lookup_one_len(co
+@@ -1399,6 +1419,8 @@ extern struct dentry * lookup_one_len(co
extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
#define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
#define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
extern void inode_init_once(struct inode *);
extern void iput(struct inode *);
-@@ -1492,6 +1513,8 @@ extern struct file_operations generic_ro
+@@ -1499,6 +1521,8 @@ extern struct file_operations generic_ro
extern int vfs_readlink(struct dentry *, char *, int, const char *);
extern int vfs_follow_link(struct nameidata *, const char *);
extern int page_readlink(struct dentry *, char *, int);
extern int page_follow_link(struct dentry *, struct nameidata *);
extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.18-18.8.0-l12/kernel/ksyms.c~vfs_intent-2.4.18-18 Wed Feb 26 16:54:17 2003
-+++ linux-2.4.18-18.8.0-l12-phil/kernel/ksyms.c Wed Feb 26 16:54:17 2003
-@@ -293,6 +293,7 @@ EXPORT_SYMBOL(read_cache_page);
+--- linux-2.4.18-61chaos/kernel/ksyms.c~vfs_intent-2.4.18-18 Sun Jun 1 21:59:03 2003
++++ linux-2.4.18-61chaos-root/kernel/ksyms.c Sun Jun 1 21:59:04 2003
+@@ -294,6 +294,7 @@ EXPORT_SYMBOL(read_cache_page);
EXPORT_SYMBOL(set_page_dirty);
EXPORT_SYMBOL(vfs_readlink);
EXPORT_SYMBOL(vfs_follow_link);
EXPORT_SYMBOL(page_readlink);
EXPORT_SYMBOL(page_follow_link);
EXPORT_SYMBOL(page_symlink_inode_operations);
+
+_
+--- linux/fs/proc/base.c.old Sat Jun 7 00:55:09 2003
++++ linux/fs/proc/base.c Sat Jun 7 00:55:33 2003
+@@ -465,6 +465,9 @@
+
+ error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
+ nd->last_type = LAST_BIND;
++
++ if (nd->it != NULL)
++ nd->it->it_int_flags |= IT_FL_FOLLOWED;
+ out:
+ return error;
+ }