From cadfb79ef5d84a50eb0c6f39e6771bf37e995059 Mon Sep 17 00:00:00 2001 From: wangdi Date: Wed, 23 Apr 2003 09:58:35 +0000 Subject: [PATCH] add vfs_intent_hp_2.4.19.patch --- .../patches/vfs_intent_hp_2.4.19.patch | 1546 ++++++++++++++++++++ 1 file changed, 1546 insertions(+) create mode 100644 lustre/kernel_patches/patches/vfs_intent_hp_2.4.19.patch diff --git a/lustre/kernel_patches/patches/vfs_intent_hp_2.4.19.patch b/lustre/kernel_patches/patches/vfs_intent_hp_2.4.19.patch new file mode 100644 index 0000000..adf311f --- /dev/null +++ b/lustre/kernel_patches/patches/vfs_intent_hp_2.4.19.patch @@ -0,0 +1,1546 @@ + fs/dcache.c | 20 ++ + fs/exec.c | 16 +- + fs/namei.c | 351 +++++++++++++++++++++++++++++++++++++++++-------- + fs/nfsd/vfs.c | 2 + fs/open.c | 144 +++++++++++++++----- + fs/stat.c | 24 ++- + include/linux/dcache.h | 28 +++ + include/linux/fs.h | 31 ++++ + kernel/ksyms.c | 1 + 9 files changed, 506 insertions(+), 111 deletions(-) + +--- linux-2.4.19-hp3_pnnl1/fs/dcache.c~vfs_intent_hp_2.4.19 2003-04-23 16:52:44.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/fs/dcache.c 2003-04-23 17:07:19.000000000 +0800 +@@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry) + spin_unlock(&dcache_lock); + return 0; + } ++ ++ /* network invalidation by Lustre */ ++ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { ++ spin_unlock(&dcache_lock); ++ return 0; ++ } ++ + /* + * Check whether to do a partial shrink_dcache + * to get rid of unused child entries. +@@ -616,6 +623,7 @@ struct dentry * d_alloc(struct dentry * + dentry->d_op = NULL; + dentry->d_fsdata = NULL; + dentry->d_mounted = 0; ++ dentry->d_it = NULL; + INIT_LIST_HEAD(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_LIST_HEAD(&dentry->d_subdirs); +@@ -830,13 +838,19 @@ void d_delete(struct dentry * dentry) + * Adds a dentry to the hash according to its name. + */ + +-void d_rehash(struct dentry * entry) ++void __d_rehash(struct dentry * entry, int lock) + { + struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); + if (!list_empty(&entry->d_hash)) BUG(); +- spin_lock(&dcache_lock); ++ if (lock) spin_lock(&dcache_lock); + list_add(&entry->d_hash, list); +- spin_unlock(&dcache_lock); ++ if (lock) spin_unlock(&dcache_lock); ++} ++EXPORT_SYMBOL(__d_rehash); ++ ++void d_rehash(struct dentry * entry) ++{ ++ __d_rehash(entry, 1); + } + + #define do_switch(x,y) do { \ +--- linux-2.4.19-hp3_pnnl1/fs/namei.c~vfs_intent_hp_2.4.19 2003-04-11 17:41:45.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/fs/namei.c 2003-04-23 17:07:19.000000000 +0800 +@@ -94,6 +94,13 @@ + * XEmacs seems to be relying on it... + */ + ++void intent_release(struct dentry *de, struct lookup_intent *it) ++{ ++ if (it && de->d_op && de->d_op->d_intent_release) ++ de->d_op->d_intent_release(de, it); ++ ++} ++ + /* In order to reduce some races, while at the same time doing additional + * checking and hopefully speeding things up, we copy filenames to the + * kernel data space before using them.. +@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd) + * Internal lookup() using the new generic dcache. + * SMP-safe + */ +-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) ++static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, ++ int flags, struct lookup_intent *it) + { + struct dentry * dentry = d_lookup(parent, name); + ++ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) { ++ if (!dentry->d_op->d_revalidate2(dentry, flags, it) && ++ !d_invalidate(dentry)) { ++ dput(dentry); ++ dentry = NULL; ++ } ++ return dentry; ++ } else + if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { + if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { + dput(dentry); +@@ -281,11 +297,14 @@ static struct dentry * cached_lookup(str + * make sure that nobody added the entry to the dcache in the meantime.. + * SMP-safe + */ +-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) ++static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, ++ int flags, struct lookup_intent *it) + { + struct dentry * result; + struct inode *dir = parent->d_inode; + ++again: ++ + down(&dir->i_sem); + /* + * First re-do the cached lookup just in case it was created +@@ -300,6 +319,9 @@ static struct dentry * real_lookup(struc + result = ERR_PTR(-ENOMEM); + if (dentry) { + lock_kernel(); ++ if (dir->i_op->lookup2) ++ result = dir->i_op->lookup2(dir, dentry, it); ++ else + result = dir->i_op->lookup(dir, dentry); + unlock_kernel(); + if (result) +@@ -321,6 +343,12 @@ static struct dentry * real_lookup(struc + dput(result); + result = ERR_PTR(-ENOENT); + } ++ } else if (result->d_op && result->d_op->d_revalidate2) { ++ if (!result->d_op->d_revalidate2(result, flags, it) && ++ !d_invalidate(result)) { ++ dput(result); ++ goto again; ++ } + } + return result; + } +@@ -332,7 +360,8 @@ static struct dentry * real_lookup(struc + * Without that kind of total limit, nasty chains of consecutive + * symlinks can cause almost arbitrarily long lookups. + */ +-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) ++static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, ++ struct lookup_intent *it) + { + int err; + if (current->link_count >= 5) +@@ -346,10 +375,14 @@ 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); ++ 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); + current->link_count--; + return err; + loop: ++ intent_release(dentry, it); + path_release(nd); + return -ELOOP; + } +@@ -379,15 +412,26 @@ int follow_up(struct vfsmount **mnt, str + return __follow_up(mnt, dentry); + } + +-static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) ++static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry, ++ struct lookup_intent *it) + { + struct vfsmount *mounted; + + spin_lock(&dcache_lock); + mounted = lookup_mnt(*mnt, *dentry); + if (mounted) { ++ int opc = 0, mode = 0; + *mnt = mntget(mounted); + spin_unlock(&dcache_lock); ++ if (it) { ++ opc = it->it_op; ++ mode = it->it_mode; ++ } ++ intent_release(*dentry, it); ++ if (it) { ++ it->it_op = opc; ++ it->it_mode = mode; ++ } + dput(*dentry); + mntput(mounted->mnt_parent); + *dentry = dget(mounted->mnt_root); +@@ -399,7 +443,7 @@ static inline int __follow_down(struct v + + int follow_down(struct vfsmount **mnt, struct dentry **dentry) + { +- return __follow_down(mnt,dentry); ++ return __follow_down(mnt,dentry,NULL); + } + + static inline void follow_dotdot(struct nameidata *nd) +@@ -435,7 +479,7 @@ static inline void follow_dotdot(struct + mntput(nd->mnt); + nd->mnt = parent; + } +- while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry)) ++ while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry, NULL)) + ; + } + +@@ -447,7 +491,8 @@ static inline void follow_dotdot(struct + * + * We expect 'base' to be positive and a directory. + */ +-int link_path_walk(const char * name, struct nameidata *nd) ++int link_path_walk_it(const char *name, struct nameidata *nd, ++ struct lookup_intent *it) + { + struct dentry *dentry; + struct inode *inode; +@@ -520,15 +565,15 @@ int link_path_walk(const char * name, st + break; + } + /* This does the actual lookups.. */ +- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); ++ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); + if (!dentry) { +- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); ++ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + break; + } + /* Check mountpoints.. */ +- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry)) ++ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, NULL)) + ; + + err = -ENOENT; +@@ -539,8 +584,8 @@ int link_path_walk(const char * name, st + if (!inode->i_op) + goto out_dput; + +- if (inode->i_op->follow_link) { +- err = do_follow_link(dentry, nd); ++ if (inode->i_op->follow_link || inode->i_op->follow_link2) { ++ err = do_follow_link(dentry, nd, NULL); + dput(dentry); + if (err) + goto return_err; +@@ -556,7 +601,7 @@ int link_path_walk(const char * name, st + nd->dentry = dentry; + } + err = -ENOTDIR; +- if (!inode->i_op->lookup) ++ if (!inode->i_op->lookup && !inode->i_op->lookup2) + break; + continue; + /* here ends the main loop */ +@@ -583,19 +628,20 @@ last_component: + if (err < 0) + break; + } +- dentry = cached_lookup(nd->dentry, &this, 0); ++ dentry = cached_lookup(nd->dentry, &this, 0, it); + if (!dentry) { +- dentry = real_lookup(nd->dentry, &this, 0); ++ dentry = real_lookup(nd->dentry, &this, 0, it); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + break; + } +- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry)) ++ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, it)) + ; + inode = dentry->d_inode; + if ((lookup_flags & LOOKUP_FOLLOW) +- && inode && inode->i_op && inode->i_op->follow_link) { +- err = do_follow_link(dentry, nd); ++ && inode && inode->i_op && ++ (inode->i_op->follow_link || inode->i_op->follow_link2)) { ++ err = do_follow_link(dentry, nd, it); + dput(dentry); + if (err) + goto return_err; +@@ -609,7 +655,8 @@ last_component: + goto no_inode; + if (lookup_flags & LOOKUP_DIRECTORY) { + err = -ENOTDIR; +- if (!inode->i_op || !inode->i_op->lookup) ++ if (!inode->i_op || ++ (!inode->i_op->lookup && !inode->i_op->lookup2)) + break; + } + goto return_base; +@@ -633,6 +680,23 @@ return_reval: + * Check the cached dentry for staleness. + */ + dentry = nd->dentry; ++ 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)) { +@@ -646,15 +710,28 @@ out_dput: + dput(dentry); + break; + } ++ if (err) ++ intent_release(nd->dentry, it); + path_release(nd); + return_err: + return err; + } + ++int link_path_walk(const char * name, struct nameidata *nd) ++{ ++ return link_path_walk_it(name, nd, NULL); ++} ++ ++int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) ++{ ++ current->total_link_count = 0; ++ return link_path_walk_it(name, nd, it); ++} ++ + int path_walk(const char * name, struct nameidata *nd) + { + current->total_link_count = 0; +- return link_path_walk(name, nd); ++ return link_path_walk_it(name, nd, NULL); + } + + /* SMP-safe */ +@@ -757,7 +834,8 @@ int path_init(const char *name, unsigned + * needs parent already locked. Doesn't follow mounts. + * SMP-safe. + */ +-struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ++struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, ++ struct lookup_intent *it) + { + struct dentry * dentry; + struct inode *inode; +@@ -780,13 +858,16 @@ struct dentry * lookup_hash(struct qstr + goto out; + } + +- dentry = cached_lookup(base, name, 0); ++ dentry = cached_lookup(base, name, 0, it); + if (!dentry) { + struct dentry *new = d_alloc(base, name); + dentry = ERR_PTR(-ENOMEM); + if (!new) + goto out; + lock_kernel(); ++ if (inode->i_op->lookup2) ++ dentry = inode->i_op->lookup2(inode, new, it); ++ else + dentry = inode->i_op->lookup(inode, new); + unlock_kernel(); + if (!dentry) +@@ -798,6 +879,12 @@ out: + return dentry; + } + ++struct dentry * lookup_hash(struct qstr *name, struct dentry * base) ++{ ++ return lookup_hash_it(name, base, NULL); ++} ++ ++ + /* SMP-safe */ + struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) + { +@@ -819,7 +906,7 @@ struct dentry * lookup_one_len(const cha + } + this.hash = end_name_hash(hash); + +- return lookup_hash(&this, base); ++ return lookup_hash_it(&this, base, NULL); + access: + return ERR_PTR(-EACCES); + } +@@ -851,6 +938,23 @@ int __user_walk(const char *name, unsign + return err; + } + ++int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, ++ struct lookup_intent *it) ++{ ++ char *tmp; ++ int err; ++ ++ tmp = getname(name); ++ err = PTR_ERR(tmp); ++ if (!IS_ERR(tmp)) { ++ err = 0; ++ if (path_init(tmp, flags, nd)) ++ err = path_walk_it(tmp, nd, it); ++ putname(tmp); ++ } ++ return err; ++} ++ + /* + * It's inline, so penalty for filesystems that don't use sticky bit is + * minimal. +@@ -987,7 +1091,8 @@ exit_lock: + * for symlinks (where the permissions are checked later). + * SMP-safe + */ +-int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) ++int open_namei_it(const char *pathname, int flag, int mode, ++ struct nameidata *nd, struct lookup_intent *it) + { + int acc_mode, error = 0; + struct inode *inode; +@@ -1002,7 +1107,7 @@ int open_namei(const char * pathname, in + */ + if (!(flag & O_CREAT)) { + if (path_init(pathname, lookup_flags(flag), nd)) +- error = path_walk(pathname, nd); ++ error = path_walk_it(pathname, nd, it); + if (error) + return error; + dentry = nd->dentry; +@@ -1012,6 +1117,11 @@ int open_namei(const char * pathname, in + /* + * Create - we need to know the parent. + */ ++ if (it) { ++ it->it_mode = mode; ++ it->it_op |= IT_CREAT; ++ } ++ + if (path_init(pathname, LOOKUP_PARENT, nd)) + error = path_walk(pathname, nd); + if (error) +@@ -1028,7 +1138,7 @@ int open_namei(const char * pathname, in + + dir = nd->dentry; + down(&dir->d_inode->i_sem); +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + + do_last: + error = PTR_ERR(dentry); +@@ -1037,6 +1147,7 @@ do_last: + goto exit; + } + ++ it->it_mode = mode; + /* Negative dentry, just create the file */ + if (!dentry->d_inode) { + if (!IS_POSIXACL(dir->d_inode)) +@@ -1066,12 +1177,13 @@ do_last: + error = -ELOOP; + if (flag & O_NOFOLLOW) + goto exit_dput; +- while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); ++ while (__follow_down(&nd->mnt,&dentry,it) && d_mountpoint(dentry)); + } + error = -ENOENT; + if (!dentry->d_inode) + goto exit_dput; +- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) ++ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link || ++ dentry->d_inode->i_op->follow_link2)) + goto do_link; + + dput(nd->dentry); +@@ -1145,7 +1257,7 @@ ok: + if (!error) { + DQUOT_INIT(inode); + +- error = do_truncate(dentry, 0); ++ error = do_truncate(dentry, 0, 1); + } + put_write_access(inode); + if (error) +@@ -1157,8 +1269,10 @@ ok: + return 0; + + exit_dput: ++ intent_release(dentry, it); + dput(dentry); + exit: ++ intent_release(nd->dentry, it); + path_release(nd); + return error; + +@@ -1177,7 +1291,12 @@ 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); ++ 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) ++ intent_release(dentry, it); + dput(dentry); + if (error) + return error; +@@ -1199,13 +1318,20 @@ do_link: + } + dir = nd->dentry; + down(&dir->d_inode->i_sem); +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + putname(nd->last.name); + goto do_last; + } + ++int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) ++{ ++ return open_namei_it(pathname, flag, mode, nd, NULL); ++} ++ ++ + /* SMP-safe */ +-static struct dentry *lookup_create(struct nameidata *nd, int is_dir) ++static struct dentry *lookup_create(struct nameidata *nd, int is_dir, ++ struct lookup_intent *it) + { + struct dentry *dentry; + +@@ -1213,7 +1339,7 @@ static struct dentry *lookup_create(stru + dentry = ERR_PTR(-EEXIST); + if (nd->last_type != LAST_NORM) + goto fail; +- dentry = lookup_hash(&nd->last, nd->dentry); ++ dentry = lookup_hash_it(&nd->last, nd->dentry, it); + if (IS_ERR(dentry)) + goto fail; + if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) +@@ -1270,7 +1396,19 @@ asmlinkage long sys_mknod(const char * f + error = path_walk(tmp, &nd); + if (error) + goto out; +- dentry = lookup_create(&nd, 0); ++ ++ if (nd.dentry->d_inode->i_op->mknod2) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->mknod2(nd.dentry->d_inode, ++ nd.last.name, ++ nd.last.len, ++ mode, dev); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out2; ++ } ++ ++ dentry = lookup_create(&nd, 0, NULL); + error = PTR_ERR(dentry); + + if (!IS_POSIXACL(nd.dentry->d_inode)) +@@ -1292,6 +1430,7 @@ asmlinkage long sys_mknod(const char * f + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); ++out2: + path_release(&nd); + out: + putname(tmp); +@@ -1340,15 +1479,25 @@ asmlinkage long sys_mkdir(const char * p + error = path_walk(tmp, &nd); + if (error) + goto out; +- dentry = lookup_create(&nd, 1); ++ if (nd.dentry->d_inode->i_op->mkdir2) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->mkdir2(nd.dentry->d_inode, ++ nd.last.name, ++ nd.last.len, ++ mode); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out2; ++ } ++ dentry = lookup_create(&nd, 1, NULL); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { +- if (!IS_POSIXACL(nd.dentry->d_inode)) +- mode &= ~current->fs->umask; +- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); ++ error = vfs_mkdir(nd.dentry->d_inode, dentry, ++ mode & ~current->fs->umask); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); ++out2: + path_release(&nd); + out: + putname(tmp); +@@ -1450,8 +1599,33 @@ asmlinkage long sys_rmdir(const char * p + error = -EBUSY; + goto exit1; + } ++ if (nd.dentry->d_inode->i_op->rmdir2) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ struct dentry *last; ++ ++ down(&nd.dentry->d_inode->i_sem); ++ last = lookup_hash_it(&nd.last, nd.dentry, NULL); ++ up(&nd.dentry->d_inode->i_sem); ++ if (IS_ERR(last)) { ++ error = PTR_ERR(last); ++ goto exit1; ++ } ++ if (d_mountpoint(last)) { ++ dput(last); ++ error = -EBUSY; ++ goto exit1; ++ } ++ dput(last); ++ ++ error = op->rmdir2(nd.dentry->d_inode, ++ nd.last.name, ++ nd.last.len); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto exit1; ++ } + down(&nd.dentry->d_inode->i_sem); +- dentry = lookup_hash(&nd.last, nd.dentry); ++ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = vfs_rmdir(nd.dentry->d_inode, dentry); +@@ -1510,8 +1684,17 @@ asmlinkage long sys_unlink(const char * + error = -EISDIR; + if (nd.last_type != LAST_NORM) + goto exit1; ++ if (nd.dentry->d_inode->i_op->unlink2) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->unlink2(nd.dentry->d_inode, ++ nd.last.name, ++ nd.last.len); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto exit1; ++ } + down(&nd.dentry->d_inode->i_sem); +- dentry = lookup_hash(&nd.last, nd.dentry); ++ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + /* Why not before? Because we want correct error value */ +@@ -1579,15 +1762,26 @@ asmlinkage long sys_symlink(const char * + error = path_walk(to, &nd); + if (error) + goto out; +- dentry = lookup_create(&nd, 0); ++ if (nd.dentry->d_inode->i_op->symlink2) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->symlink2(nd.dentry->d_inode, ++ nd.last.name, ++ nd.last.len, ++ from); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out2; ++ } ++ dentry = lookup_create(&nd, 0, NULL); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = vfs_symlink(nd.dentry->d_inode, dentry, from); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); ++ out2: + path_release(&nd); +-out: ++ out: + putname(to); + } + putname(from); +@@ -1670,7 +1864,17 @@ asmlinkage long sys_link(const char * ol + error = -EXDEV; + if (old_nd.mnt != nd.mnt) + goto out_release; +- new_dentry = lookup_create(&nd, 0); ++ if (nd.dentry->d_inode->i_op->link2) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->link2(old_nd.dentry->d_inode, ++ nd.dentry->d_inode, ++ nd.last.name, ++ nd.last.len); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out_release; ++ } ++ new_dentry = lookup_create(&nd, 0, NULL); + error = PTR_ERR(new_dentry); + if (!IS_ERR(new_dentry)) { + error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); +@@ -1716,7 +1920,8 @@ exit: + * locking]. + */ + int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, +- struct inode *new_dir, struct dentry *new_dentry) ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it) + { + int error; + struct inode *target; +@@ -1774,6 +1979,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); ++ intent_release(new_dentry, it); + if (target) { + if (!error) + target->i_flags |= S_DEAD; +@@ -1795,7 +2001,8 @@ out_unlock: + } + + int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, +- struct inode *new_dir, struct dentry *new_dentry) ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it) + { + int error; + +@@ -1826,6 +2033,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); ++ intent_release(new_dentry, it); + double_up(&old_dir->i_zombie, &new_dir->i_zombie); + if (error) + return error; +@@ -1837,13 +2045,14 @@ int vfs_rename_other(struct inode *old_d + } + + int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, +- struct inode *new_dir, struct dentry *new_dentry) ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it) + { + int error; + if (S_ISDIR(old_dentry->d_inode->i_mode)) +- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry); ++ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it); + else +- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); ++ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it); + if (!error) { + if (old_dir == new_dir) + inode_dir_notify(old_dir, DN_RENAME); +@@ -1888,7 +2097,7 @@ static inline int do_rename(const char * + + double_lock(new_dir, old_dir); + +- old_dentry = lookup_hash(&oldnd.last, old_dir); ++ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); + error = PTR_ERR(old_dentry); + if (IS_ERR(old_dentry)) + goto exit3; +@@ -1904,16 +2113,37 @@ static inline int do_rename(const char * + if (newnd.last.name[newnd.last.len]) + goto exit4; + } +- new_dentry = lookup_hash(&newnd.last, new_dir); ++ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); + error = PTR_ERR(new_dentry); + if (IS_ERR(new_dentry)) + goto exit4; + ++ if (old_dir->d_inode->i_op->rename2) { ++ lock_kernel(); ++ /* don't rename mount point. mds will take care of ++ * the rest sanity checking */ ++ if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) { ++ error = -EBUSY; ++ goto exit5; ++ } ++ ++ error = old_dir->d_inode->i_op->rename2(old_dir->d_inode, ++ new_dir->d_inode, ++ oldnd.last.name, ++ oldnd.last.len, ++ newnd.last.name, ++ newnd.last.len); ++ unlock_kernel(); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto exit5; ++ } ++ + lock_kernel(); + error = vfs_rename(old_dir->d_inode, old_dentry, +- new_dir->d_inode, new_dentry); ++ new_dir->d_inode, new_dentry, NULL); + unlock_kernel(); +- ++exit5: + dput(new_dentry); + exit4: + dput(old_dentry); +@@ -1964,7 +2194,8 @@ out: + } + + static inline int +-__vfs_follow_link(struct nameidata *nd, const char *link) ++__vfs_follow_link(struct nameidata *nd, const char *link, ++ struct lookup_intent *it) + { + int res = 0; + char *name; +@@ -1977,7 +2208,7 @@ __vfs_follow_link(struct nameidata *nd, + /* weird __emul_prefix() stuff did it */ + goto out; + } +- res = link_path_walk(link, nd); ++ res = link_path_walk_it(link, nd, it); + out: + if (current->link_count || res || nd->last_type!=LAST_NORM) + return res; +@@ -1999,7 +2230,13 @@ fail: + + int vfs_follow_link(struct nameidata *nd, const char *link) + { +- return __vfs_follow_link(nd, link); ++ return __vfs_follow_link(nd, link, NULL); ++} ++ ++int vfs_follow_link_it(struct nameidata *nd, const char *link, ++ struct lookup_intent *it) ++{ ++ return __vfs_follow_link(nd, link, it); + } + + /* get the link contents into pagecache */ +@@ -2041,7 +2278,7 @@ int page_follow_link(struct dentry *dent + { + struct page *page = NULL; + char *s = page_getlink(dentry, &page); +- int res = __vfs_follow_link(nd, s); ++ int res = __vfs_follow_link(nd, s, NULL); + if (page) { + kunmap(page); + page_cache_release(page); +--- linux-2.4.19-hp3_pnnl1/fs/nfsd/vfs.c~vfs_intent_hp_2.4.19 2002-08-03 08:39:45.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/fs/nfsd/vfs.c 2003-04-23 17:07:19.000000000 +0800 +@@ -1295,7 +1295,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru + err = nfserr_perm; + } else + #endif +- err = vfs_rename(fdir, odentry, tdir, ndentry); ++ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); + if (!err && EX_ISSYNC(tfhp->fh_export)) { + nfsd_sync_dir(tdentry); + nfsd_sync_dir(fdentry); +--- linux-2.4.19-hp3_pnnl1/fs/open.c~vfs_intent_hp_2.4.19 2002-08-03 08:39:45.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/fs/open.c 2003-04-23 17:07:19.000000000 +0800 +@@ -19,6 +19,8 @@ + #include + + #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) ++extern int path_walk_it(const char *name, struct nameidata *nd, ++ struct lookup_intent *it); + + int vfs_statfs(struct super_block *sb, struct statfs *buf) + { +@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct + write_unlock(&files->file_lock); + } + +-int do_truncate(struct dentry *dentry, loff_t length) ++int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) + { + struct inode *inode = dentry->d_inode; ++ struct inode_operations *op = dentry->d_inode->i_op; + int error; + struct iattr newattrs; + +@@ -108,7 +111,14 @@ int do_truncate(struct dentry *dentry, l + down(&inode->i_sem); + newattrs.ia_size = length; + newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; +- error = notify_change(dentry, &newattrs); ++ if (called_from_open) ++ newattrs.ia_valid |= ATTR_FROM_OPEN; ++ if (op->setattr_raw) { ++ newattrs.ia_valid |= ATTR_RAW; ++ newattrs.ia_ctime = CURRENT_TIME; ++ error = op->setattr_raw(inode, &newattrs); ++ } else ++ error = notify_change(dentry, &newattrs); + up(&inode->i_sem); + return error; + } +@@ -118,12 +128,13 @@ static inline long do_sys_truncate(const + struct nameidata nd; + struct inode * inode; + int error; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + + error = -EINVAL; + if (length < 0) /* sorry, but loff_t says... */ + goto out; + +- error = user_path_walk(path, &nd); ++ error = user_path_walk_it(path, &nd, &it); + if (error) + goto out; + inode = nd.dentry->d_inode; +@@ -163,11 +174,13 @@ static inline long do_sys_truncate(const + error = locks_verify_truncate(inode, NULL, length); + if (!error) { + DQUOT_INIT(inode); +- error = do_truncate(nd.dentry, length); ++ intent_release(nd.dentry, &it); ++ error = do_truncate(nd.dentry, length, 0); + } + put_write_access(inode); + + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -215,7 +228,7 @@ static inline long do_sys_ftruncate(unsi + + error = locks_verify_truncate(inode, file, length); + if (!error) +- error = do_truncate(dentry, length); ++ error = do_truncate(dentry, length, 0); + out_putf: + fput(file); + out: +@@ -260,11 +273,13 @@ asmlinkage long sys_utime(char * filenam + struct inode * inode; + struct iattr newattrs; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, NULL); + if (error) + goto out; + inode = nd.dentry->d_inode; + ++ /* this is safe without a Lustre lock because it only depends ++ on the super block */ + error = -EROFS; + if (IS_RDONLY(inode)) + goto dput_and_out; +@@ -279,11 +294,29 @@ asmlinkage long sys_utime(char * filenam + goto dput_and_out; + + newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; +- } else { ++ } ++ ++ if (inode->i_op->setattr_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ ++ newattrs.ia_valid |= ATTR_RAW; ++ error = op->setattr_raw(inode, &newattrs); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto dput_and_out; ++ } ++ ++ error = -EROFS; ++ if (IS_RDONLY(inode)) ++ goto dput_and_out; ++ ++ error = -EPERM; ++ if (!times) { + if (current->fsuid != inode->i_uid && + (error = permission(inode,MAY_WRITE)) != 0) + goto dput_and_out; + } ++ + error = notify_change(nd.dentry, &newattrs); + dput_and_out: + path_release(&nd); +@@ -304,12 +337,14 @@ asmlinkage long sys_utimes(char * filena + struct inode * inode; + struct iattr newattrs; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, NULL); + + if (error) + goto out; + inode = nd.dentry->d_inode; + ++ /* this is safe without a Lustre lock because it only depends ++ on the super block */ + error = -EROFS; + if (IS_RDONLY(inode)) + goto dput_and_out; +@@ -324,7 +359,20 @@ asmlinkage long sys_utimes(char * filena + newattrs.ia_atime = times[0].tv_sec; + newattrs.ia_mtime = times[1].tv_sec; + newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; +- } else { ++ } ++ ++ if (inode->i_op->setattr_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ ++ newattrs.ia_valid |= ATTR_RAW; ++ error = op->setattr_raw(inode, &newattrs); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto dput_and_out; ++ } ++ ++ error = -EPERM; ++ if (!utimes) { + if (current->fsuid != inode->i_uid && + (error = permission(inode,MAY_WRITE)) != 0) + goto dput_and_out; +@@ -347,6 +395,7 @@ asmlinkage long sys_access(const char * + int old_fsuid, old_fsgid; + kernel_cap_t old_cap; + int res; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; +@@ -364,13 +413,14 @@ asmlinkage long sys_access(const char * + else + current->cap_effective = current->cap_permitted; + +- res = user_path_walk(filename, &nd); ++ res = user_path_walk_it(filename, &nd, &it); + if (!res) { + res = permission(nd.dentry->d_inode, mode); + /* SuS v2 requires we report a read only fs too */ + if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) + && !special_file(nd.dentry->d_inode->i_mode)) + res = -EROFS; ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + +@@ -385,17 +435,10 @@ asmlinkage long sys_chdir(const char * f + { + int error; + struct nameidata nd; +- char *name; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; ++ ++ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); + +- name = getname(filename); +- error = PTR_ERR(name); +- if (IS_ERR(name)) +- goto out; +- +- error = 0; +- if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd)) +- error = path_walk(name, &nd); +- putname(name); + if (error) + goto out; + +@@ -406,6 +449,7 @@ asmlinkage long sys_chdir(const char * f + set_fs_pwd(current->fs, nd.mnt, nd.dentry); + + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -445,17 +489,10 @@ asmlinkage long sys_chroot(const char * + { + int error; + struct nameidata nd; +- char *name; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; ++ ++ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); + +- name = getname(filename); +- error = PTR_ERR(name); +- if (IS_ERR(name)) +- goto out; +- +- path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW | +- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); +- error = path_walk(name, &nd); +- putname(name); + if (error) + goto out; + +@@ -471,6 +508,7 @@ asmlinkage long sys_chroot(const char * + set_fs_altroot(); + error = 0; + dput_and_out: ++ intent_release(nd.dentry, &it); + path_release(&nd); + out: + return error; +@@ -525,6 +563,18 @@ asmlinkage long sys_chmod(const char * f + if (IS_RDONLY(inode)) + goto dput_and_out; + ++ if (inode->i_op->setattr_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ ++ newattrs.ia_mode = mode; ++ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; ++ newattrs.ia_valid |= ATTR_RAW; ++ error = op->setattr_raw(inode, &newattrs); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto dput_and_out; ++ } ++ + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto dput_and_out; +@@ -555,6 +605,20 @@ static int chown_common(struct dentry * + error = -EROFS; + if (IS_RDONLY(inode)) + goto out; ++ ++ if (inode->i_op->setattr_raw) { ++ struct inode_operations *op = dentry->d_inode->i_op; ++ ++ newattrs.ia_uid = user; ++ newattrs.ia_gid = group; ++ newattrs.ia_valid = ATTR_UID | ATTR_GID; ++ newattrs.ia_valid |= ATTR_RAW; ++ error = op->setattr_raw(inode, &newattrs); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ return error; ++ } ++ + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto out; +@@ -655,10 +719,12 @@ asmlinkage long sys_fchown(unsigned int + * for the internal routines (ie open_namei()/follow_link() etc). 00 is + * used by symlinks. + */ ++ + struct file *filp_open(const char * filename, int flags, int mode) + { + int namei_flags, error; + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = flags }; + + namei_flags = flags; + if ((namei_flags+1) & O_ACCMODE) +@@ -666,14 +732,15 @@ struct file *filp_open(const char * file + if (namei_flags & O_TRUNC) + namei_flags |= 2; + +- error = open_namei(filename, namei_flags, mode, &nd); +- if (!error) +- return dentry_open(nd.dentry, nd.mnt, flags); ++ error = open_namei_it(filename, namei_flags, mode, &nd, &it); ++ if (error) ++ return ERR_PTR(error); + +- return ERR_PTR(error); ++ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); + } + +-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) ++struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, ++ int flags, struct lookup_intent *it) + { + struct file * f; + struct inode *inode; +@@ -716,6 +783,7 @@ struct file *dentry_open(struct dentry * + } + f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + ++ intent_release(dentry, it); + return f; + + cleanup_all: +@@ -730,11 +798,17 @@ cleanup_all: + cleanup_file: + put_filp(f); + cleanup_dentry: ++ intent_release(dentry, it); + dput(dentry); + mntput(mnt); + return ERR_PTR(error); + } + ++struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) ++{ ++ return dentry_open_it(dentry, mnt, flags, NULL); ++} ++ + /* + * Find an empty file descriptor entry, and mark it busy. + */ +--- linux-2.4.19-hp3_pnnl1/fs/stat.c~vfs_intent_hp_2.4.19 2003-04-23 17:06:53.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/fs/stat.c 2003-04-23 17:07:19.000000000 +0800 +@@ -135,13 +135,15 @@ static int cp_new_stat(struct inode * in + asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_old_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -151,13 +153,15 @@ asmlinkage long sys_stat(char * filename + asmlinkage long sys_newstat(char * filename, struct stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -172,13 +176,15 @@ asmlinkage long sys_newstat(char * filen + asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_old_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -189,13 +195,15 @@ asmlinkage long sys_lstat(char * filenam + asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) + { + struct nameidata nd; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + int error; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -333,12 +341,14 @@ asmlinkage long sys_stat64(char * filena + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + +- error = user_path_walk(filename, &nd); ++ error = user_path_walk_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat64(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +@@ -348,12 +358,14 @@ asmlinkage long sys_lstat64(char * filen + { + struct nameidata nd; + int error; ++ struct lookup_intent it = { .it_op = IT_GETATTR }; + +- error = user_path_walk_link(filename, &nd); ++ error = user_path_walk_link_it(filename, &nd, &it); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_new_stat64(nd.dentry->d_inode, statbuf); ++ intent_release(nd.dentry, &it); + path_release(&nd); + } + return error; +--- linux-2.4.19-hp3_pnnl1/include/linux/dcache.h~vfs_intent_hp_2.4.19 2002-08-03 08:39:45.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/include/linux/dcache.h 2003-04-23 17:07:19.000000000 +0800 +@@ -6,6 +6,25 @@ + #include + #include + ++#define IT_OPEN (1) ++#define IT_CREAT (1<<1) ++#define IT_READDIR (1<<2) ++#define IT_GETATTR (1<<3) ++#define IT_LOOKUP (1<<4) ++#define IT_UNLINK (1<<5) ++ ++struct lookup_intent { ++ int it_op; ++ int it_mode; ++ int it_flags; ++ int it_disposition; ++ int it_status; ++ struct iattr *it_iattr; ++ __u64 it_lock_handle[2]; ++ int it_lock_mode; ++ void *it_data; ++}; ++ + /* + * linux/include/linux/dcache.h + * +@@ -78,6 +97,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 */ ++ struct lookup_intent *d_it; + unsigned long d_vfs_flags; + void * d_fsdata; /* fs-specific data */ + unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ +@@ -90,8 +110,15 @@ struct dentry_operations { + int (*d_delete)(struct dentry *); + void (*d_release)(struct dentry *); + void (*d_iput)(struct dentry *, struct inode *); ++ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *); ++ void (*d_intent_release)(struct dentry *, struct lookup_intent *); + }; + ++/* defined in fs/namei.c */ ++extern void intent_release(struct dentry *de, struct lookup_intent *it); ++/* defined in fs/dcache.c */ ++extern void __d_rehash(struct dentry * entry, int lock); ++ + /* 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 +@@ -123,6 +150,7 @@ d_iput: no no yes + * s_nfsd_free_path semaphore will be down + */ + #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ ++#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ + + extern spinlock_t dcache_lock; + +--- linux-2.4.19-hp3_pnnl1/include/linux/fs.h~vfs_intent_hp_2.4.19 2003-04-23 16:25:28.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/include/linux/fs.h 2003-04-23 17:07:19.000000000 +0800 +@@ -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 ++#define ATTR_RAW 2048 /* file system, not vfs will massage attrs */ ++#define ATTR_FROM_OPEN 4096 /* called from open path, ie O_TRUNC */ + + /* + * This is the Inode Attributes structure, used for notify_change(). It +@@ -575,6 +577,7 @@ struct file { + + /* needed for tty driver, and maybe others */ + void *private_data; ++ struct lookup_intent *f_intent; + + /* preallocated helper kiobuf to speedup O_DIRECT */ + struct kiobuf *f_iobuf; +@@ -815,7 +818,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 *); +-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); ++int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry, ++ struct lookup_intent *it); + + /* + * File types +@@ -876,20 +881,33 @@ struct file_operations { + struct inode_operations { + int (*create) (struct inode *,struct dentry *,int); + struct dentry * (*lookup) (struct inode *,struct dentry *); ++ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *); + int (*link) (struct dentry *,struct inode *,struct dentry *); ++ int (*link2) (struct inode *,struct inode *, const char *, int); + int (*unlink) (struct inode *,struct dentry *); ++ int (*unlink2) (struct inode *, const char *, int); + int (*symlink) (struct inode *,struct dentry *,const char *); ++ int (*symlink2) (struct inode *, const char *, int, const char *); + int (*mkdir) (struct inode *,struct dentry *,int); ++ int (*mkdir2) (struct inode *, const char *, int,int); + int (*rmdir) (struct inode *,struct dentry *); ++ int (*rmdir2) (struct inode *, const char *, int); + int (*mknod) (struct inode *,struct dentry *,int,int); ++ int (*mknod2) (struct inode *, const char *, int,int,int); + int (*rename) (struct inode *, struct dentry *, + struct inode *, struct dentry *); ++ int (*rename2) (struct inode *, struct inode *, ++ const char *oldname, int oldlen, ++ const char *newname, int newlen); + int (*readlink) (struct dentry *, char *,int); + int (*follow_link) (struct dentry *, struct nameidata *); ++ int (*follow_link2) (struct dentry *, struct nameidata *, ++ struct lookup_intent *it); + void (*truncate) (struct inode *); + int (*permission) (struct inode *, int); + int (*revalidate) (struct dentry *); + int (*setattr) (struct dentry *, struct iattr *); ++ int (*setattr_raw) (struct inode *, struct iattr *); + int (*getattr) (struct dentry *, struct iattr *); + int (*setxattr) (struct dentry *, const char *, void *, size_t, int); + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); +@@ -1086,10 +1104,14 @@ 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 int do_truncate(struct dentry *, loff_t start); ++extern int do_truncate(struct dentry *, loff_t start, int called_from_open); + + extern struct file *filp_open(const char *, int, int); + extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); ++extern int open_namei_it(const char *filename, int namei_flags, int mode, ++ struct nameidata *nd, struct lookup_intent *it); ++extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, ++ int flags, struct lookup_intent *it); + extern int filp_close(struct file *, fl_owner_t id); + extern char * getname(const char *); + +@@ -1354,6 +1376,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(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); + extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); + extern int FASTCALL(path_walk(const char *, struct nameidata *)); + extern int FASTCALL(link_path_walk(const char *, struct nameidata *)); +@@ -1364,6 +1387,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) ++#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) ++#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) + + extern void inode_init_once(struct inode *); + extern void iput(struct inode *); +@@ -1499,6 +1524,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 vfs_follow_link_it(struct nameidata *, const char *, ++ struct lookup_intent *it); + 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.19-hp3_pnnl1/kernel/ksyms.c~vfs_intent_hp_2.4.19 2003-04-23 16:25:29.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/kernel/ksyms.c 2003-04-23 17:07:19.000000000 +0800 +@@ -293,6 +293,7 @@ EXPORT_SYMBOL(read_cache_page); + EXPORT_SYMBOL(set_page_dirty); + EXPORT_SYMBOL(vfs_readlink); + EXPORT_SYMBOL(vfs_follow_link); ++EXPORT_SYMBOL(vfs_follow_link_it); + EXPORT_SYMBOL(page_readlink); + EXPORT_SYMBOL(page_follow_link); + EXPORT_SYMBOL(page_symlink_inode_operations); +--- linux-2.4.19-hp3_pnnl1/fs/exec.c~vfs_intent_hp_2.4.19 2003-04-23 16:12:58.000000000 +0800 ++++ linux-2.4.19-hp3_pnnl1-root/fs/exec.c 2003-04-23 17:21:09.000000000 +0800 +@@ -109,8 +109,9 @@ asmlinkage long sys_uselib(const char * + struct file * file; + struct nameidata nd; + int error; +- +- error = user_path_walk(library, &nd); ++ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY }; ++ ++ error = user_path_walk_it(library, &nd, &it); + if (error) + goto out; + +@@ -122,7 +123,7 @@ asmlinkage long sys_uselib(const char * + if (error) + goto exit; + +- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); ++ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); + error = PTR_ERR(file); + if (IS_ERR(file)) + goto out; +@@ -344,9 +345,10 @@ struct file *open_exec(const char *name) + struct inode *inode; + struct file *file; + int err = 0; +- ++ struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY }; ++ + if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd)) +- err = path_walk(name, &nd); ++ err = path_walk_it(name, &nd, &it); + file = ERR_PTR(err); + if (!err) { + inode = nd.dentry->d_inode; +@@ -358,7 +360,7 @@ 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); + if (!IS_ERR(file)) { + err = deny_write_access(file); + if (err) { +@@ -1058,7 +1060,7 @@ int do_coredump(long signr, struct pt_re + goto close_fail; + if (!file->f_op->write) + goto close_fail; +- if (do_truncate(file->f_dentry, 0) != 0) ++ if (do_truncate(file->f_dentry, 0, 0) != 0) + goto close_fail; + + retval = binfmt->core_dump(signr, regs, file); + +_ -- 1.8.3.1