3 fs/namei.c | 378 +++++++++++++++++++++++++++++++++++++++++--------
5 fs/open.c | 120 +++++++++++++--
8 include/linux/dcache.h | 31 ++++
9 include/linux/fs.h | 28 +++
11 10 files changed, 522 insertions(+), 85 deletions(-)
13 --- linux-2.4.18-61chaos/fs/dcache.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
14 +++ linux-2.4.18-61chaos-root/fs/dcache.c Sun Jun 1 21:59:04 2003
15 @@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry)
16 spin_unlock(&dcache_lock);
20 + /* network invalidation by Lustre */
21 + if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
22 + spin_unlock(&dcache_lock);
27 * Check whether to do a partial shrink_dcache
28 * to get rid of unused child entries.
29 @@ -645,6 +652,7 @@ struct dentry * d_alloc(struct dentry *
30 dentry->d_fsdata = NULL;
31 dentry->d_extra_attributes = NULL;
32 dentry->d_mounted = 0;
33 + dentry->d_it = NULL;
34 INIT_LIST_HEAD(&dentry->d_hash);
35 INIT_LIST_HEAD(&dentry->d_lru);
36 INIT_LIST_HEAD(&dentry->d_subdirs);
37 @@ -859,13 +867,19 @@ void d_delete(struct dentry * dentry)
38 * Adds a dentry to the hash according to its name.
41 -void d_rehash(struct dentry * entry)
42 +void __d_rehash(struct dentry * entry, int lock)
44 struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
45 if (!list_empty(&entry->d_hash)) BUG();
46 - spin_lock(&dcache_lock);
47 + if (lock) spin_lock(&dcache_lock);
48 list_add(&entry->d_hash, list);
49 - spin_unlock(&dcache_lock);
50 + if (lock) spin_unlock(&dcache_lock);
52 +EXPORT_SYMBOL(__d_rehash);
54 +void d_rehash(struct dentry * entry)
56 + __d_rehash(entry, 1);
59 #define do_switch(x,y) do { \
60 --- linux-2.4.18-61chaos/fs/namei.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
61 +++ linux-2.4.18-61chaos-root/fs/namei.c Sun Jun 1 23:14:49 2003
63 * XEmacs seems to be relying on it...
66 +void intent_release(struct dentry *de, struct lookup_intent *it)
68 + if (it && de->d_op && de->d_op->d_intent_release)
69 + de->d_op->d_intent_release(de, it);
73 /* In order to reduce some races, while at the same time doing additional
74 * checking and hopefully speeding things up, we copy filenames to the
75 * kernel data space before using them..
76 @@ -260,10 +267,19 @@ void path_release(struct nameidata *nd)
77 * Internal lookup() using the new generic dcache.
80 -static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
81 +static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
82 + int flags, struct lookup_intent *it)
84 struct dentry * dentry = d_lookup(parent, name);
86 + if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
87 + if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
88 + !d_invalidate(dentry)) {
94 if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
95 if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
97 @@ -281,11 +297,14 @@ static struct dentry * cached_lookup(str
98 * make sure that nobody added the entry to the dcache in the meantime..
101 -static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
102 +static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
103 + int flags, struct lookup_intent *it)
105 struct dentry * result;
106 struct inode *dir = parent->d_inode;
112 * First re-do the cached lookup just in case it was created
113 @@ -300,6 +319,9 @@ static struct dentry * real_lookup(struc
114 result = ERR_PTR(-ENOMEM);
117 + if (dir->i_op->lookup2)
118 + result = dir->i_op->lookup2(dir, dentry, it);
120 result = dir->i_op->lookup(dir, dentry);
123 @@ -321,6 +343,12 @@ static struct dentry * real_lookup(struc
125 result = ERR_PTR(-ENOENT);
127 + } else if (result->d_op && result->d_op->d_revalidate2) {
128 + if (!result->d_op->d_revalidate2(result, flags, it) &&
129 + !d_invalidate(result)) {
136 @@ -334,7 +362,8 @@ int max_recursive_link = 5;
137 * Without that kind of total limit, nasty chains of consecutive
138 * symlinks can cause almost arbitrarily long lookups.
140 -static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
141 +static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
142 + struct lookup_intent *it)
145 if (current->link_count >= max_recursive_link)
146 @@ -348,10 +377,21 @@ static inline int do_follow_link(struct
147 current->link_count++;
148 current->total_link_count++;
149 UPDATE_ATIME(dentry->d_inode);
150 - err = dentry->d_inode->i_op->follow_link(dentry, nd);
152 + if (dentry->d_inode->i_op->follow_link2)
153 + err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
155 + err = dentry->d_inode->i_op->follow_link(dentry, nd);
156 + if (!err && it != NULL && !(it->it_int_flags & IT_FL_FOLLOWED)) {
157 + /* vfs_follow_link was never called */
158 + intent_release(dentry, it);
162 current->link_count--;
165 + intent_release(dentry, it);
169 @@ -381,15 +421,26 @@ int follow_up(struct vfsmount **mnt, str
170 return __follow_up(mnt, dentry);
173 -static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
174 +static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry,
175 + struct lookup_intent *it)
177 struct vfsmount *mounted;
179 spin_lock(&dcache_lock);
180 mounted = lookup_mnt(*mnt, *dentry);
182 + int opc = 0, mode = 0;
183 *mnt = mntget(mounted);
184 spin_unlock(&dcache_lock);
187 + mode = it->it_mode;
189 + intent_release(*dentry, it);
192 + it->it_mode = mode;
195 mntput(mounted->mnt_parent);
196 *dentry = dget(mounted->mnt_root);
197 @@ -401,7 +452,7 @@ static inline int __follow_down(struct v
199 int follow_down(struct vfsmount **mnt, struct dentry **dentry)
201 - return __follow_down(mnt,dentry);
202 + return __follow_down(mnt,dentry,NULL);
205 static inline void follow_dotdot(struct nameidata *nd)
206 @@ -437,7 +488,7 @@ static inline void follow_dotdot(struct
210 - while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry))
211 + while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry, NULL))
215 @@ -449,7 +500,8 @@ static inline void follow_dotdot(struct
217 * We expect 'base' to be positive and a directory.
219 -int link_path_walk(const char * name, struct nameidata *nd)
220 +int link_path_walk_it(const char *name, struct nameidata *nd,
221 + struct lookup_intent *it)
223 struct dentry *dentry;
225 @@ -526,18 +578,18 @@ int link_path_walk(const char * name, st
228 /* This does the actual lookups.. */
229 - dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
230 + dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
232 err = -EWOULDBLOCKIO;
235 - dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
236 + dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
237 err = PTR_ERR(dentry);
241 /* Check mountpoints.. */
242 - while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
243 + while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, NULL))
247 @@ -548,8 +600,8 @@ int link_path_walk(const char * name, st
251 - if (inode->i_op->follow_link) {
252 - err = do_follow_link(dentry, nd);
253 + if (inode->i_op->follow_link || inode->i_op->follow_link2) {
254 + err = do_follow_link(dentry, nd, NULL);
258 @@ -565,7 +617,7 @@ int link_path_walk(const char * name, st
262 - if (!inode->i_op->lookup)
263 + if (!inode->i_op->lookup && !inode->i_op->lookup2)
266 /* here ends the main loop */
267 @@ -592,22 +644,23 @@ last_component:
271 - dentry = cached_lookup(nd->dentry, &this, 0);
272 + dentry = cached_lookup(nd->dentry, &this, 0, it);
274 err = -EWOULDBLOCKIO;
277 - dentry = real_lookup(nd->dentry, &this, 0);
278 + dentry = real_lookup(nd->dentry, &this, 0, it);
279 err = PTR_ERR(dentry);
283 - while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
284 + while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, it))
286 inode = dentry->d_inode;
287 if ((lookup_flags & LOOKUP_FOLLOW)
288 - && inode && inode->i_op && inode->i_op->follow_link) {
289 - err = do_follow_link(dentry, nd);
290 + && inode && inode->i_op &&
291 + (inode->i_op->follow_link || inode->i_op->follow_link2)) {
292 + err = do_follow_link(dentry, nd, it);
296 @@ -621,7 +674,8 @@ last_component:
298 if (lookup_flags & LOOKUP_DIRECTORY) {
300 - if (!inode->i_op || !inode->i_op->lookup)
301 + if (!inode->i_op ||
302 + (!inode->i_op->lookup && !inode->i_op->lookup2))
306 @@ -645,7 +699,24 @@ return_reval:
307 * Check the cached dentry for staleness.
310 - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
312 + if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
314 + if (!dentry->d_op->d_revalidate2(dentry, 0, it)) {
315 + struct dentry *new;
316 + err = permission(dentry->d_parent->d_inode,
320 + new = real_lookup(dentry->d_parent,
321 + &dentry->d_name, 0, NULL);
322 + d_invalidate(dentry);
325 + goto revalidate_again;
328 + else if (dentry && dentry->d_op && dentry->d_op->d_revalidate){
330 if (!dentry->d_op->d_revalidate(dentry, 0)) {
331 d_invalidate(dentry);
332 @@ -658,15 +729,28 @@ out_dput:
337 + intent_release(nd->dentry, it);
343 +int link_path_walk(const char * name, struct nameidata *nd)
345 + return link_path_walk_it(name, nd, NULL);
348 +int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
350 + current->total_link_count = 0;
351 + return link_path_walk_it(name, nd, it);
354 int path_walk(const char * name, struct nameidata *nd)
356 current->total_link_count = 0;
357 - return link_path_walk(name, nd);
358 + return link_path_walk_it(name, nd, NULL);
362 @@ -751,6 +835,17 @@ walk_init_root(const char *name, struct
366 +int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
367 + struct lookup_intent *it)
370 + if (path_init(path, flags, nd))
371 + error = path_walk_it(path, nd, it);
377 int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
380 @@ -765,6 +860,7 @@ int path_init(const char *name, unsigned
382 nd->last_type = LAST_ROOT; /* if there are only slashes... */
386 return walk_init_root(name,nd);
387 read_lock(¤t->fs->lock);
388 @@ -779,7 +875,8 @@ int path_init(const char *name, unsigned
389 * needs parent already locked. Doesn't follow mounts.
392 -struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
393 +struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
394 + struct lookup_intent *it)
396 struct dentry * dentry;
398 @@ -802,13 +899,16 @@ struct dentry * lookup_hash(struct qstr
402 - dentry = cached_lookup(base, name, 0);
403 + dentry = cached_lookup(base, name, 0, it);
405 struct dentry *new = d_alloc(base, name);
406 dentry = ERR_PTR(-ENOMEM);
410 + if (inode->i_op->lookup2)
411 + dentry = inode->i_op->lookup2(inode, new, it);
413 dentry = inode->i_op->lookup(inode, new);
416 @@ -820,6 +920,12 @@ out:
420 +struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
422 + return lookup_hash_it(name, base, NULL);
427 struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
429 @@ -841,7 +947,7 @@ struct dentry * lookup_one_len(const cha
431 this.hash = end_name_hash(hash);
433 - return lookup_hash(&this, base);
434 + return lookup_hash_it(&this, base, NULL);
436 return ERR_PTR(-EACCES);
438 @@ -872,6 +978,23 @@ int __user_walk(const char *name, unsign
442 +int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
443 + struct lookup_intent *it)
448 + tmp = getname(name);
449 + err = PTR_ERR(tmp);
450 + if (!IS_ERR(tmp)) {
452 + if (path_init(tmp, flags, nd))
453 + err = path_walk_it(tmp, nd, it);
460 * It's inline, so penalty for filesystems that don't use sticky bit is
462 @@ -1045,14 +1168,17 @@ int may_open(struct nameidata *nd, int a
463 return get_lease(inode, flag);
466 +extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
467 + int flags, struct lookup_intent *it);
469 struct file *filp_open(const char * pathname, int open_flags, int mode)
471 int acc_mode, error = 0;
472 - struct inode *inode;
473 struct dentry *dentry;
475 int flag = open_flags;
477 + struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = open_flags };
480 if (!capable(CAP_SYS_ADMIN))
481 @@ -1069,7 +1195,7 @@ struct file *filp_open(const char * path
482 * The simplest case - just a plain lookup.
484 if (!(flag & O_CREAT)) {
485 - error = path_lookup(pathname, lookup_flags(flag), &nd);
486 + error = path_lookup_it(pathname, lookup_flags(flag), &nd, &it);
488 return ERR_PTR(error);
490 @@ -1079,6 +1205,8 @@ struct file *filp_open(const char * path
492 * Create - we need to know the parent.
495 + it.it_op |= IT_CREAT;
496 error = path_lookup(pathname, LOOKUP_PARENT, &nd);
498 return ERR_PTR(error);
499 @@ -1094,7 +1222,7 @@ struct file *filp_open(const char * path
502 down(&dir->d_inode->i_sem);
503 - dentry = lookup_hash(&nd.last, nd.dentry);
504 + dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
507 error = PTR_ERR(dentry);
508 @@ -1103,6 +1231,7 @@ do_last:
513 /* Negative dentry, just create the file */
514 if (!dentry->d_inode) {
515 error = vfs_create(dir->d_inode, dentry,
516 @@ -1132,12 +1261,13 @@ do_last:
518 if (flag & O_NOFOLLOW)
520 - while (__follow_down(&nd.mnt,&dentry) && d_mountpoint(dentry));
521 + while (__follow_down(&nd.mnt,&dentry,&it) && d_mountpoint(dentry));
524 if (!dentry->d_inode)
526 - if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
527 + if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
528 + dentry->d_inode->i_op->follow_link2))
532 @@ -1152,11 +1282,13 @@ ok:
533 if (!S_ISREG(nd.dentry->d_inode->i_mode))
534 open_flags &= ~O_TRUNC;
536 - return dentry_open(nd.dentry, nd.mnt, open_flags);
537 + return dentry_open_it(nd.dentry, nd.mnt, open_flags, &it);
540 + intent_release(dentry, &it);
543 + intent_release(nd.dentry, &it);
545 return ERR_PTR(error);
547 @@ -1175,10 +1307,22 @@ do_link:
548 * are done. Procfs-like symlinks just set LAST_BIND.
550 UPDATE_ATIME(dentry->d_inode);
551 - error = dentry->d_inode->i_op->follow_link(dentry, &nd);
553 + if (dentry->d_inode->i_op->follow_link2)
554 + error = dentry->d_inode->i_op->follow_link2(dentry, &nd, &it);
556 + error = dentry->d_inode->i_op->follow_link(dentry, &nd);
558 + intent_release(dentry, &it);
559 + } else if (!(it.it_int_flags & IT_FL_FOLLOWED)) {
560 + /* vfs_follow_link was never called */
561 + intent_release(dentry, &it);
568 + return ERR_PTR(error);
569 if (nd.last_type == LAST_BIND) {
572 @@ -1197,13 +1341,15 @@ do_link:
575 down(&dir->d_inode->i_sem);
576 - dentry = lookup_hash(&nd.last, nd.dentry);
577 + dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
578 putname(nd.last.name);
584 -static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
585 +static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
586 + struct lookup_intent *it)
588 struct dentry *dentry;
590 @@ -1211,7 +1357,7 @@ static struct dentry *lookup_create(stru
591 dentry = ERR_PTR(-EEXIST);
592 if (nd->last_type != LAST_NORM)
594 - dentry = lookup_hash(&nd->last, nd->dentry);
595 + dentry = lookup_hash_it(&nd->last, nd->dentry, it);
598 if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
599 @@ -1267,7 +1413,19 @@ asmlinkage long sys_mknod(const char * f
600 error = path_lookup(tmp, LOOKUP_PARENT, &nd);
603 - dentry = lookup_create(&nd, 0);
605 + if (nd.dentry->d_inode->i_op->mknod2) {
606 + struct inode_operations *op = nd.dentry->d_inode->i_op;
607 + error = op->mknod2(nd.dentry->d_inode,
611 + /* the file system wants to use normal vfs path now */
612 + if (error != -EOPNOTSUPP)
616 + dentry = lookup_create(&nd, 0, NULL);
617 error = PTR_ERR(dentry);
619 mode &= ~current->fs->umask;
620 @@ -1288,6 +1446,7 @@ asmlinkage long sys_mknod(const char * f
623 up(&nd.dentry->d_inode->i_sem);
628 @@ -1335,7 +1494,17 @@ asmlinkage long sys_mkdir(const char * p
629 error = path_lookup(tmp, LOOKUP_PARENT, &nd);
632 - dentry = lookup_create(&nd, 1);
633 + if (nd.dentry->d_inode->i_op->mkdir2) {
634 + struct inode_operations *op = nd.dentry->d_inode->i_op;
635 + error = op->mkdir2(nd.dentry->d_inode,
639 + /* the file system wants to use normal vfs path now */
640 + if (error != -EOPNOTSUPP)
643 + dentry = lookup_create(&nd, 1, NULL);
644 error = PTR_ERR(dentry);
645 if (!IS_ERR(dentry)) {
646 error = vfs_mkdir(nd.dentry->d_inode, dentry,
647 @@ -1343,6 +1512,7 @@ asmlinkage long sys_mkdir(const char * p
650 up(&nd.dentry->d_inode->i_sem);
655 @@ -1443,8 +1613,33 @@ asmlinkage long sys_rmdir(const char * p
659 + if (nd.dentry->d_inode->i_op->rmdir2) {
660 + struct inode_operations *op = nd.dentry->d_inode->i_op;
661 + struct dentry *last;
663 + down(&nd.dentry->d_inode->i_sem);
664 + last = lookup_hash_it(&nd.last, nd.dentry, NULL);
665 + up(&nd.dentry->d_inode->i_sem);
666 + if (IS_ERR(last)) {
667 + error = PTR_ERR(last);
670 + if (d_mountpoint(last)) {
677 + error = op->rmdir2(nd.dentry->d_inode,
680 + /* the file system wants to use normal vfs path now */
681 + if (error != -EOPNOTSUPP)
684 down(&nd.dentry->d_inode->i_sem);
685 - dentry = lookup_hash(&nd.last, nd.dentry);
686 + dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
687 error = PTR_ERR(dentry);
688 if (!IS_ERR(dentry)) {
689 error = vfs_rmdir(nd.dentry->d_inode, dentry);
690 @@ -1502,8 +1697,17 @@ asmlinkage long sys_unlink(const char *
692 if (nd.last_type != LAST_NORM)
694 + if (nd.dentry->d_inode->i_op->unlink2) {
695 + struct inode_operations *op = nd.dentry->d_inode->i_op;
696 + error = op->unlink2(nd.dentry->d_inode,
699 + /* the file system wants to use normal vfs path now */
700 + if (error != -EOPNOTSUPP)
703 down(&nd.dentry->d_inode->i_sem);
704 - dentry = lookup_hash(&nd.last, nd.dentry);
705 + dentry = lookup_hash_it(&nd.last, nd.dentry, NULL);
706 error = PTR_ERR(dentry);
707 if (!IS_ERR(dentry)) {
708 /* Why not before? Because we want correct error value */
709 @@ -1570,15 +1774,26 @@ asmlinkage long sys_symlink(const char *
710 error = path_lookup(to, LOOKUP_PARENT, &nd);
713 - dentry = lookup_create(&nd, 0);
714 + if (nd.dentry->d_inode->i_op->symlink2) {
715 + struct inode_operations *op = nd.dentry->d_inode->i_op;
716 + error = op->symlink2(nd.dentry->d_inode,
720 + /* the file system wants to use normal vfs path now */
721 + if (error != -EOPNOTSUPP)
724 + dentry = lookup_create(&nd, 0, NULL);
725 error = PTR_ERR(dentry);
726 if (!IS_ERR(dentry)) {
727 error = vfs_symlink(nd.dentry->d_inode, dentry, from);
730 up(&nd.dentry->d_inode->i_sem);
738 @@ -1645,7 +1860,7 @@ asmlinkage long sys_link(const char * ol
739 struct dentry *new_dentry;
740 struct nameidata nd, old_nd;
742 - error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
743 + error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, NULL);
746 error = path_lookup(to, LOOKUP_PARENT, &nd);
747 @@ -1654,7 +1869,17 @@ asmlinkage long sys_link(const char * ol
749 if (old_nd.mnt != nd.mnt)
751 - new_dentry = lookup_create(&nd, 0);
752 + if (nd.dentry->d_inode->i_op->link2) {
753 + struct inode_operations *op = nd.dentry->d_inode->i_op;
754 + error = op->link2(old_nd.dentry->d_inode,
755 + nd.dentry->d_inode,
758 + /* the file system wants to use normal vfs path now */
759 + if (error != -EOPNOTSUPP)
762 + new_dentry = lookup_create(&nd, 0, NULL);
763 error = PTR_ERR(new_dentry);
764 if (!IS_ERR(new_dentry)) {
765 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
766 @@ -1698,7 +1923,8 @@ exit:
769 int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
770 - struct inode *new_dir, struct dentry *new_dentry)
771 + struct inode *new_dir, struct dentry *new_dentry,
772 + struct lookup_intent *it)
775 struct inode *target;
776 @@ -1756,6 +1982,7 @@ int vfs_rename_dir(struct inode *old_dir
779 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
780 + intent_release(new_dentry, it);
783 target->i_flags |= S_DEAD;
784 @@ -1777,7 +2004,8 @@ out_unlock:
787 int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
788 - struct inode *new_dir, struct dentry *new_dentry)
789 + struct inode *new_dir, struct dentry *new_dentry,
790 + struct lookup_intent *it)
794 @@ -1808,6 +2036,7 @@ int vfs_rename_other(struct inode *old_d
797 error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
798 + intent_release(new_dentry, it);
799 double_up(&old_dir->i_zombie, &new_dir->i_zombie);
802 @@ -1819,13 +2048,14 @@ int vfs_rename_other(struct inode *old_d
805 int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
806 - struct inode *new_dir, struct dentry *new_dentry)
807 + struct inode *new_dir, struct dentry *new_dentry,
808 + struct lookup_intent *it)
811 if (S_ISDIR(old_dentry->d_inode->i_mode))
812 - error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
813 + error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
815 - error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
816 + error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
818 if (old_dir == new_dir)
819 inode_dir_notify(old_dir, DN_RENAME);
820 @@ -1867,7 +2097,7 @@ static inline int do_rename(const char *
822 double_lock(new_dir, old_dir);
824 - old_dentry = lookup_hash(&oldnd.last, old_dir);
825 + old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL);
826 error = PTR_ERR(old_dentry);
827 if (IS_ERR(old_dentry))
829 @@ -1883,16 +2113,37 @@ static inline int do_rename(const char *
830 if (newnd.last.name[newnd.last.len])
833 - new_dentry = lookup_hash(&newnd.last, new_dir);
834 + new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL);
835 error = PTR_ERR(new_dentry);
836 if (IS_ERR(new_dentry))
839 + if (old_dir->d_inode->i_op->rename2) {
841 + /* don't rename mount point. mds will take care of
842 + * the rest sanity checking */
843 + if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) {
848 + error = old_dir->d_inode->i_op->rename2(old_dir->d_inode,
855 + /* the file system wants to use normal vfs path now */
856 + if (error != -EOPNOTSUPP)
861 error = vfs_rename(old_dir->d_inode, old_dentry,
862 - new_dir->d_inode, new_dentry);
863 + new_dir->d_inode, new_dentry, NULL);
870 @@ -1943,12 +2194,19 @@ out:
874 -__vfs_follow_link(struct nameidata *nd, const char *link)
875 +__vfs_follow_link(struct nameidata *nd, const char *link,
876 + struct lookup_intent *it)
884 + else if (it != nd->it)
885 + printk("it != nd->it: tell phil@clusterfs.com\n");
887 + it->it_int_flags |= IT_FL_FOLLOWED;
891 @@ -1956,7 +2214,7 @@ __vfs_follow_link(struct nameidata *nd,
892 /* weird __emul_prefix() stuff did it */
895 - res = link_path_walk(link, nd);
896 + res = link_path_walk_it(link, nd, it);
898 if (current->link_count || res || nd->last_type!=LAST_NORM)
900 @@ -1978,7 +2236,13 @@ fail:
902 int vfs_follow_link(struct nameidata *nd, const char *link)
904 - return __vfs_follow_link(nd, link);
905 + return __vfs_follow_link(nd, link, NULL);
908 +int vfs_follow_link_it(struct nameidata *nd, const char *link,
909 + struct lookup_intent *it)
911 + return __vfs_follow_link(nd, link, it);
914 /* get the link contents into pagecache */
915 @@ -2020,7 +2284,7 @@ int page_follow_link(struct dentry *dent
917 struct page *page = NULL;
918 char *s = page_getlink(dentry, &page);
919 - int res = __vfs_follow_link(nd, s);
920 + int res = __vfs_follow_link(nd, s, NULL);
923 page_cache_release(page);
924 --- linux-2.4.18-61chaos/fs/nfsd/vfs.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
925 +++ linux-2.4.18-61chaos-root/fs/nfsd/vfs.c Sun Jun 1 21:59:04 2003
926 @@ -1298,7 +1298,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
930 - err = vfs_rename(fdir, odentry, tdir, ndentry);
931 + err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
933 if (!err && EX_ISSYNC(tfhp->fh_export)) {
934 nfsd_sync_dir(tdentry);
935 --- linux-2.4.18-61chaos/fs/open.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
936 +++ linux-2.4.18-61chaos-root/fs/open.c Sun Jun 1 21:59:04 2003
938 #include <asm/uaccess.h>
940 #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
941 +extern int path_walk_it(const char *name, struct nameidata *nd,
942 + struct lookup_intent *it);
944 int vfs_statfs(struct super_block *sb, struct statfs *buf)
946 @@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct
947 write_unlock(&files->file_lock);
950 -int do_truncate(struct dentry *dentry, loff_t length)
951 +int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
953 struct inode *inode = dentry->d_inode;
954 + struct inode_operations *op = dentry->d_inode->i_op;
956 struct iattr newattrs;
958 @@ -108,7 +111,14 @@ int do_truncate(struct dentry *dentry, l
960 newattrs.ia_size = length;
961 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
962 - error = notify_change(dentry, &newattrs);
963 + if (called_from_open)
964 + newattrs.ia_valid |= ATTR_FROM_OPEN;
965 + if (op->setattr_raw) {
966 + newattrs.ia_valid |= ATTR_RAW;
967 + newattrs.ia_ctime = CURRENT_TIME;
968 + error = op->setattr_raw(inode, &newattrs);
970 + error = notify_change(dentry, &newattrs);
974 @@ -118,12 +128,13 @@ static inline long do_sys_truncate(const
976 struct inode * inode;
978 + struct lookup_intent it = { .it_op = IT_GETATTR };
981 if (length < 0) /* sorry, but loff_t says... */
984 - error = user_path_walk(path, &nd);
985 + error = user_path_walk_it(path, &nd, &it);
988 inode = nd.dentry->d_inode;
989 @@ -163,11 +174,13 @@ static inline long do_sys_truncate(const
990 error = locks_verify_truncate(inode, NULL, length);
993 - error = do_truncate(nd.dentry, length);
994 + intent_release(nd.dentry, &it);
995 + error = do_truncate(nd.dentry, length, 0);
997 put_write_access(inode);
1000 + intent_release(nd.dentry, &it);
1004 @@ -215,7 +228,7 @@ static inline long do_sys_ftruncate(unsi
1006 error = locks_verify_truncate(inode, file, length);
1008 - error = do_truncate(dentry, length);
1009 + error = do_truncate(dentry, length, 0);
1013 @@ -260,11 +273,13 @@ asmlinkage long sys_utime(char * filenam
1014 struct inode * inode;
1015 struct iattr newattrs;
1017 - error = user_path_walk(filename, &nd);
1018 + error = user_path_walk_it(filename, &nd, NULL);
1021 inode = nd.dentry->d_inode;
1023 + /* this is safe without a Lustre lock because it only depends
1024 + on the super block */
1026 if (IS_RDONLY(inode))
1028 @@ -279,11 +294,29 @@ asmlinkage long sys_utime(char * filenam
1031 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
1035 + if (inode->i_op->setattr_raw) {
1036 + struct inode_operations *op = nd.dentry->d_inode->i_op;
1038 + newattrs.ia_valid |= ATTR_RAW;
1039 + error = op->setattr_raw(inode, &newattrs);
1040 + /* the file system wants to use normal vfs path now */
1041 + if (error != -EOPNOTSUPP)
1042 + goto dput_and_out;
1046 + if (IS_RDONLY(inode))
1047 + goto dput_and_out;
1051 if (current->fsuid != inode->i_uid &&
1052 (error = permission(inode,MAY_WRITE)) != 0)
1056 error = notify_change(nd.dentry, &newattrs);
1059 @@ -304,12 +337,14 @@ asmlinkage long sys_utimes(char * filena
1060 struct inode * inode;
1061 struct iattr newattrs;
1063 - error = user_path_walk(filename, &nd);
1064 + error = user_path_walk_it(filename, &nd, NULL);
1068 inode = nd.dentry->d_inode;
1070 + /* this is safe without a Lustre lock because it only depends
1071 + on the super block */
1073 if (IS_RDONLY(inode))
1075 @@ -324,7 +359,20 @@ asmlinkage long sys_utimes(char * filena
1076 newattrs.ia_atime = times[0].tv_sec;
1077 newattrs.ia_mtime = times[1].tv_sec;
1078 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
1082 + if (inode->i_op->setattr_raw) {
1083 + struct inode_operations *op = nd.dentry->d_inode->i_op;
1085 + newattrs.ia_valid |= ATTR_RAW;
1086 + error = op->setattr_raw(inode, &newattrs);
1087 + /* the file system wants to use normal vfs path now */
1088 + if (error != -EOPNOTSUPP)
1089 + goto dput_and_out;
1094 if (current->fsuid != inode->i_uid &&
1095 (error = permission(inode,MAY_WRITE)) != 0)
1097 @@ -347,6 +395,7 @@ asmlinkage long sys_access(const char *
1098 int old_fsuid, old_fsgid;
1099 kernel_cap_t old_cap;
1101 + struct lookup_intent it = { .it_op = IT_GETATTR };
1103 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
1105 @@ -364,13 +413,14 @@ asmlinkage long sys_access(const char *
1107 current->cap_effective = current->cap_permitted;
1109 - res = user_path_walk(filename, &nd);
1110 + res = user_path_walk_it(filename, &nd, &it);
1112 res = permission(nd.dentry->d_inode, mode);
1113 /* SuS v2 requires we report a read only fs too */
1114 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
1115 && !special_file(nd.dentry->d_inode->i_mode))
1117 + intent_release(nd.dentry, &it);
1121 @@ -385,8 +435,11 @@ asmlinkage long sys_chdir(const char * f
1124 struct nameidata nd;
1125 + struct lookup_intent it = { .it_op = IT_GETATTR };
1127 - error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
1128 + error = __user_walk_it(filename,
1129 + LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,
1134 @@ -397,6 +450,7 @@ asmlinkage long sys_chdir(const char * f
1135 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
1138 + intent_release(nd.dentry, &it);
1142 @@ -436,9 +490,10 @@ asmlinkage long sys_chroot(const char *
1145 struct nameidata nd;
1146 + struct lookup_intent it = { .it_op = IT_GETATTR };
1148 - error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1149 - LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
1150 + error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
1151 + LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
1155 @@ -454,6 +509,7 @@ asmlinkage long sys_chroot(const char *
1159 + intent_release(nd.dentry, &it);
1163 @@ -508,6 +564,18 @@ asmlinkage long sys_chmod(const char * f
1164 if (IS_RDONLY(inode))
1167 + if (inode->i_op->setattr_raw) {
1168 + struct inode_operations *op = nd.dentry->d_inode->i_op;
1170 + newattrs.ia_mode = mode;
1171 + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1172 + newattrs.ia_valid |= ATTR_RAW;
1173 + error = op->setattr_raw(inode, &newattrs);
1174 + /* the file system wants to use normal vfs path now */
1175 + if (error != -EOPNOTSUPP)
1176 + goto dput_and_out;
1180 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1182 @@ -538,6 +606,20 @@ static int chown_common(struct dentry *
1184 if (IS_RDONLY(inode))
1187 + if (inode->i_op->setattr_raw) {
1188 + struct inode_operations *op = dentry->d_inode->i_op;
1190 + newattrs.ia_uid = user;
1191 + newattrs.ia_gid = group;
1192 + newattrs.ia_valid = ATTR_UID | ATTR_GID;
1193 + newattrs.ia_valid |= ATTR_RAW;
1194 + error = op->setattr_raw(inode, &newattrs);
1195 + /* the file system wants to use normal vfs path now */
1196 + if (error != -EOPNOTSUPP)
1201 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
1203 @@ -628,7 +710,8 @@ extern ssize_t do_readahead(struct file
1204 /* for files over a certains size it doesn't pay to do readahead on open */
1205 #define READAHEAD_CUTOFF 48000
1207 -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1208 +struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
1209 + int flags, struct lookup_intent *it)
1212 struct inode *inode;
1213 @@ -649,7 +732,7 @@ struct file *dentry_open(struct dentry *
1214 error = locks_verify_locked(inode);
1217 - error = do_truncate(dentry, 0);
1218 + error = do_truncate(dentry, 0, 1);
1220 if (error || !(f->f_mode & FMODE_WRITE))
1221 put_write_access(inode);
1222 @@ -693,6 +776,7 @@ struct file *dentry_open(struct dentry *
1223 do_readahead(f, 0, (48 * 1024) >> PAGE_SHIFT);
1226 + intent_release(dentry, it);
1230 @@ -707,11 +791,17 @@ cleanup_all:
1234 + intent_release(dentry, it);
1237 return ERR_PTR(error);
1240 +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
1242 + return dentry_open_it(dentry, mnt, flags, NULL);
1246 * Find an empty file descriptor entry, and mark it busy.
1248 --- linux-2.4.18-61chaos/fs/stat.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
1249 +++ linux-2.4.18-61chaos-root/fs/stat.c Sun Jun 1 21:59:04 2003
1250 @@ -104,10 +104,12 @@ int vfs_stat(char *name, struct kstat *s
1252 struct nameidata nd;
1254 + struct lookup_intent it = { .it_op = IT_GETATTR };
1256 - error = user_path_walk(name, &nd);
1257 + error = user_path_walk_it(name, &nd, &it);
1259 error = do_getattr(nd.mnt, nd.dentry, stat);
1260 + intent_release(nd.dentry, &it);
1264 @@ -117,10 +119,12 @@ int vfs_lstat(char *name, struct kstat *
1266 struct nameidata nd;
1268 + struct lookup_intent it = { .it_op = IT_GETATTR };
1270 - error = user_path_walk_link(name, &nd);
1271 + error = user_path_walk_link_it(name, &nd, &it);
1273 error = do_getattr(nd.mnt, nd.dentry, stat);
1274 + intent_release(nd.dentry, &it);
1278 --- linux-2.4.18-61chaos/fs/exec.c~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
1279 +++ linux-2.4.18-61chaos-root/fs/exec.c Sun Jun 1 21:59:04 2003
1280 @@ -112,13 +112,18 @@ static inline void put_binfmt(struct lin
1282 * Also note that we take the address to load from from the file itself.
1284 +extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
1285 + int flags, struct lookup_intent *it);
1286 +int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
1287 + struct lookup_intent *it);
1288 asmlinkage long sys_uselib(const char * library)
1291 struct nameidata nd;
1293 + struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY };
1295 - error = user_path_walk(library, &nd);
1296 + error = user_path_walk_it(library, &nd, &it);
1300 @@ -130,7 +135,8 @@ asmlinkage long sys_uselib(const char *
1304 - file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
1305 + file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
1306 + intent_release(nd.dentry, &it);
1307 error = PTR_ERR(file);
1310 @@ -359,8 +365,9 @@ struct file *open_exec(const char *name)
1311 struct inode *inode;
1314 + struct lookup_intent it = { .it_op = IT_OPEN, .it_flags = O_RDONLY };
1316 - err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
1317 + err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
1318 file = ERR_PTR(err);
1320 inode = nd.dentry->d_inode;
1321 @@ -372,8 +379,9 @@ struct file *open_exec(const char *name)
1323 file = ERR_PTR(err);
1325 - file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
1326 + file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
1327 if (!IS_ERR(file)) {
1328 + intent_release(nd.dentry, &it);
1329 err = deny_write_access(file);
1332 @@ -384,6 +392,7 @@ out:
1336 + intent_release(nd.dentry, &it);
1340 @@ -1104,7 +1113,7 @@ int do_coredump(long signr, struct pt_re
1342 if (!file->f_op->write)
1344 - if (do_truncate(file->f_dentry, 0) != 0)
1345 + if (do_truncate(file->f_dentry, 0, 0) != 0)
1348 retval = binfmt->core_dump(signr, regs, file);
1349 --- linux-2.4.18-61chaos/include/linux/dcache.h~vfs_intent-2.4.18-18 Sun Jun 1 21:55:14 2003
1350 +++ linux-2.4.18-61chaos-root/include/linux/dcache.h Sun Jun 1 22:02:31 2003
1352 #include <asm/atomic.h>
1353 #include <linux/mount.h>
1355 +#define IT_OPEN (1)
1356 +#define IT_CREAT (1<<1)
1357 +#define IT_READDIR (1<<2)
1358 +#define IT_GETATTR (1<<3)
1359 +#define IT_LOOKUP (1<<4)
1360 +#define IT_UNLINK (1<<5)
1362 +#define IT_FL_LOCKED (1)
1363 +#define IT_FL_FOLLOWED (1<<1) /* set by vfs_follow_link */
1365 +struct lookup_intent {
1369 + int it_disposition;
1372 + __u64 it_lock_handle[2];
1378 * linux/include/linux/dcache.h
1380 @@ -78,6 +100,7 @@ struct dentry {
1381 unsigned long d_time; /* used by d_revalidate */
1382 struct dentry_operations *d_op;
1383 struct super_block * d_sb; /* The root of the dentry tree */
1384 + struct lookup_intent *d_it;
1385 unsigned long d_vfs_flags;
1386 void * d_fsdata; /* fs-specific data */
1387 void * d_extra_attributes; /* TUX-specific data */
1388 @@ -91,8 +114,15 @@ struct dentry_operations {
1389 int (*d_delete)(struct dentry *);
1390 void (*d_release)(struct dentry *);
1391 void (*d_iput)(struct dentry *, struct inode *);
1392 + int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
1393 + void (*d_intent_release)(struct dentry *, struct lookup_intent *);
1396 +/* defined in fs/namei.c */
1397 +extern void intent_release(struct dentry *de, struct lookup_intent *it);
1398 +/* defined in fs/dcache.c */
1399 +extern void __d_rehash(struct dentry * entry, int lock);
1401 /* the dentry parameter passed to d_hash and d_compare is the parent
1402 * directory of the entries to be compared. It is used in case these
1403 * functions need any directory specific information for determining
1404 @@ -124,6 +154,7 @@ d_iput: no no yes
1405 * s_nfsd_free_path semaphore will be down
1407 #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
1408 +#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
1410 extern spinlock_t dcache_lock;
1412 --- linux-2.4.18-61chaos/include/linux/fs.h~vfs_intent-2.4.18-18 Sun Jun 1 21:59:03 2003
1413 +++ linux-2.4.18-61chaos-root/include/linux/fs.h Sun Jun 1 22:01:46 2003
1414 @@ -339,6 +339,8 @@ extern void set_bh_page(struct buffer_he
1415 #define ATTR_MTIME_SET 256
1416 #define ATTR_FORCE 512 /* Not a change, but a change it */
1417 #define ATTR_ATTR_FLAG 1024
1418 +#define ATTR_RAW 2048 /* file system, not vfs will massage attrs */
1419 +#define ATTR_FROM_OPEN 4096 /* called from open path, ie O_TRUNC */
1422 * This is the Inode Attributes structure, used for notify_change(). It
1423 @@ -578,6 +580,7 @@ struct file {
1425 /* needed for tty driver, and maybe others */
1427 + struct lookup_intent *f_intent;
1429 /* preallocated helper kiobuf to speedup O_DIRECT */
1430 struct kiobuf *f_iobuf;
1431 @@ -707,6 +710,7 @@ struct nameidata {
1435 + struct lookup_intent *it;
1438 #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
1439 @@ -840,7 +844,9 @@ extern int vfs_symlink(struct inode *, s
1440 extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
1441 extern int vfs_rmdir(struct inode *, struct dentry *);
1442 extern int vfs_unlink(struct inode *, struct dentry *);
1443 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
1444 +int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1445 + struct inode *new_dir, struct dentry *new_dentry,
1446 + struct lookup_intent *it);
1450 @@ -901,20 +907,33 @@ struct file_operations {
1451 struct inode_operations {
1452 int (*create) (struct inode *,struct dentry *,int);
1453 struct dentry * (*lookup) (struct inode *,struct dentry *);
1454 + struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
1455 int (*link) (struct dentry *,struct inode *,struct dentry *);
1456 + int (*link2) (struct inode *,struct inode *, const char *, int);
1457 int (*unlink) (struct inode *,struct dentry *);
1458 + int (*unlink2) (struct inode *, const char *, int);
1459 int (*symlink) (struct inode *,struct dentry *,const char *);
1460 + int (*symlink2) (struct inode *, const char *, int, const char *);
1461 int (*mkdir) (struct inode *,struct dentry *,int);
1462 + int (*mkdir2) (struct inode *, const char *, int,int);
1463 int (*rmdir) (struct inode *,struct dentry *);
1464 + int (*rmdir2) (struct inode *, const char *, int);
1465 int (*mknod) (struct inode *,struct dentry *,int,int);
1466 + int (*mknod2) (struct inode *, const char *, int,int,int);
1467 int (*rename) (struct inode *, struct dentry *,
1468 struct inode *, struct dentry *);
1469 + int (*rename2) (struct inode *, struct inode *,
1470 + const char *oldname, int oldlen,
1471 + const char *newname, int newlen);
1472 int (*readlink) (struct dentry *, char *,int);
1473 int (*follow_link) (struct dentry *, struct nameidata *);
1474 + int (*follow_link2) (struct dentry *, struct nameidata *,
1475 + struct lookup_intent *it);
1476 void (*truncate) (struct inode *);
1477 int (*permission) (struct inode *, int);
1478 int (*revalidate) (struct dentry *);
1479 int (*setattr) (struct dentry *, struct iattr *);
1480 + int (*setattr_raw) (struct inode *, struct iattr *);
1481 int (*getattr) (struct dentry *, struct iattr *);
1484 @@ -1119,7 +1138,7 @@ static inline int get_lease(struct inode
1486 asmlinkage long sys_open(const char *, int, int);
1487 asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
1488 -extern int do_truncate(struct dentry *, loff_t start);
1489 +extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
1491 extern struct file *filp_open(const char *, int, int);
1492 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
1493 @@ -1388,6 +1407,7 @@ typedef int (*read_actor_t)(read_descrip
1494 extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
1496 extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
1497 +extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
1498 extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
1499 extern int FASTCALL(path_walk(const char *, struct nameidata *));
1500 extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
1501 @@ -1399,6 +1419,8 @@ extern struct dentry * lookup_one_len(co
1502 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
1503 #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
1504 #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
1505 +#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
1506 +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
1508 extern void inode_init_once(struct inode *);
1509 extern void iput(struct inode *);
1510 @@ -1499,6 +1521,8 @@ extern struct file_operations generic_ro
1512 extern int vfs_readlink(struct dentry *, char *, int, const char *);
1513 extern int vfs_follow_link(struct nameidata *, const char *);
1514 +extern int vfs_follow_link_it(struct nameidata *, const char *,
1515 + struct lookup_intent *it);
1516 extern int page_readlink(struct dentry *, char *, int);
1517 extern int page_follow_link(struct dentry *, struct nameidata *);
1518 extern struct inode_operations page_symlink_inode_operations;
1519 --- linux-2.4.18-61chaos/kernel/ksyms.c~vfs_intent-2.4.18-18 Sun Jun 1 21:59:03 2003
1520 +++ linux-2.4.18-61chaos-root/kernel/ksyms.c Sun Jun 1 21:59:04 2003
1521 @@ -294,6 +294,7 @@ EXPORT_SYMBOL(read_cache_page);
1522 EXPORT_SYMBOL(set_page_dirty);
1523 EXPORT_SYMBOL(vfs_readlink);
1524 EXPORT_SYMBOL(vfs_follow_link);
1525 +EXPORT_SYMBOL(vfs_follow_link_it);
1526 EXPORT_SYMBOL(page_readlink);
1527 EXPORT_SYMBOL(page_follow_link);
1528 EXPORT_SYMBOL(page_symlink_inode_operations);
1531 --- linux/fs/proc/base.c.old Sat Jun 7 00:55:09 2003
1532 +++ linux/fs/proc/base.c Sat Jun 7 00:55:33 2003
1535 error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
1536 nd->last_type = LAST_BIND;
1538 + if (nd->it != NULL)
1539 + nd->it->it_int_flags |= IT_FL_FOLLOWED;