Index: linus-2.6.7/fs/namei.c =================================================================== --- linus-2.6.7.orig/fs/namei.c 2005-03-05 20:24:52.000000000 +0200 +++ linus-2.6.7/fs/namei.c 2005-03-23 13:37:48.563339840 +0200 @@ -758,14 +758,20 @@ lookup_parent: nd->last = this; nd->last_type = LAST_NORM; - if (this.name[0] != '.') - goto return_base; - if (this.len == 1) - nd->last_type = LAST_DOT; - else if (this.len == 2 && this.name[1] == '.') - nd->last_type = LAST_DOTDOT; - else - goto return_base; + if (this.name[0] == '.') { + if (this.len == 1) + nd->last_type = LAST_DOT; + else if (this.len == 2 && this.name[1] == '.') + nd->last_type = LAST_DOTDOT; + } + + if ((nd->last_type == LAST_NORM) && inode->i_op && + inode->i_op->endparentlookup) { + err = inode->i_op->endparentlookup(nd); + if (err) + break; + } + goto return_base; return_reval: /* * We bypassed the ordinary revalidation routines. @@ -1535,9 +1541,16 @@ if (IS_ERR(tmp)) return PTR_ERR(tmp); - error = path_lookup(tmp, LOOKUP_PARENT, &nd); + intent_init(&nd.intent.open, IT_MKNOD); + nd.intent.open.create_mode = mode; + nd.intent.open.create.dev = dev; + + error = path_lookup_it(tmp, LOOKUP_PARENT, &nd); if (error) goto out; + if (nd.intent.open.flags & IT_STATUS_RAW) + goto out2; + dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); @@ -1564,6 +1577,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); +out2: path_release(&nd); out: putname(tmp); @@ -1606,9 +1620,13 @@ struct dentry *dentry; struct nameidata nd; - error = path_lookup(tmp, LOOKUP_PARENT, &nd); + intent_init(&nd.intent.open, IT_MKDIR); + nd.intent.open.create_mode = mode; + error = path_lookup_it(tmp, LOOKUP_PARENT, &nd); if (error) goto out; + if (nd.intent.open.flags & IT_STATUS_RAW) + goto out2; dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -1618,6 +1636,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); +out2: path_release(&nd); out: putname(tmp); @@ -1703,9 +1722,12 @@ if(IS_ERR(name)) return PTR_ERR(name); - error = path_lookup(name, LOOKUP_PARENT, &nd); + intent_init(&nd.intent.open, IT_RMDIR); + error = path_lookup_it(name, LOOKUP_PARENT, &nd); if (error) goto exit; + if (nd.intent.open.flags & IT_STATUS_RAW) + goto exit1; switch(nd.last_type) { case LAST_DOTDOT: @@ -1781,9 +1803,13 @@ if(IS_ERR(name)) return PTR_ERR(name); - error = path_lookup(name, LOOKUP_PARENT, &nd); + intent_init(&nd.intent.open, IT_UNLINK); + error = path_lookup_it(name, LOOKUP_PARENT, &nd); if (error) goto exit; + if (nd.intent.open.flags & IT_STATUS_RAW) + goto exit1; + error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; @@ -1855,9 +1881,13 @@ struct dentry *dentry; struct nameidata nd; - error = path_lookup(to, LOOKUP_PARENT, &nd); + intent_init(&nd.intent.open, IT_SYMLINK); + nd.intent.open.create.link = from; + error = path_lookup_it(to, LOOKUP_PARENT, &nd); if (error) goto out; + if (nd.intent.open.flags & IT_STATUS_RAW) + goto out2; dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -1865,6 +1895,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); +out2: path_release(&nd); out: putname(to); @@ -1936,9 +1967,13 @@ error = __user_walk(oldname, 0, &old_nd); if (error) goto exit; - error = path_lookup(to, LOOKUP_PARENT, &nd); + intent_init(&nd.intent.open, IT_LINK); + nd.intent.open.create.source_nd = &old_nd; + error = path_lookup_it(to, LOOKUP_PARENT, &nd); if (error) goto out; + if (nd.intent.open.flags & IT_STATUS_RAW) + goto out_release; error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out_release; @@ -2119,9 +2154,18 @@ if (error) goto exit; - error = path_lookup(newname, LOOKUP_PARENT, &newnd); + error = -EBUSY; + if (oldnd.last_type != LAST_NORM) + goto exit1; + + intent_init(&newnd.intent.open, IT_RENAME); + newnd.intent.open.create.source_nd = &oldnd; + error = path_lookup_it(newname, LOOKUP_PARENT, &newnd); if (error) goto exit1; + if (newnd.intent.open.flags & IT_STATUS_RAW) { + goto exit2; + } error = -EXDEV; if (oldnd.mnt != newnd.mnt) @@ -2129,8 +2173,6 @@ old_dir = oldnd.dentry; error = -EBUSY; - if (oldnd.last_type != LAST_NORM) - goto exit2; new_dir = newnd.dentry; if (newnd.last_type != LAST_NORM) @@ -2238,6 +2280,7 @@ intent_init(&nd->intent.open, it.op); nd->intent.open.flags = it.flags; nd->intent.open.create_mode = it.create_mode; + nd->intent.open.create = it.create; res = link_path_walk(link, nd); out: if (current->link_count || res || nd->last_type!=LAST_NORM) Index: linus-2.6.7/include/linux/namei.h =================================================================== --- linus-2.6.7.orig/include/linux/namei.h 2005-03-05 20:24:52.000000000 +0200 +++ linus-2.6.7/include/linux/namei.h 2005-03-23 13:34:56.632477304 +0200 @@ -15,9 +15,19 @@ #define IT_UNLINK (1<<5) #define IT_TRUNC (1<<6) #define IT_GETXATTR (1<<7) +#define IT_RMDIR (1<<8) +#define IT_LINK (1<<9) +#define IT_RENAME (1<<10) +#define IT_MKDIR (1<<11) +#define IT_MKNOD (1<<12) +#define IT_SYMLINK (1<<13) +#define IT_CHDIR (1<<14) #define INTENT_MAGIC 0x19620323 - +#define IT_STATUS_RAW (1<<10) /* Setting this in it_flags on exit from lookup + means everything was done already and return + value from lookup is in fact status of + already performed operation */ struct open_intent { int magic; int op; @@ -25,6 +35,11 @@ int flags; int create_mode; union { + unsigned dev; /* For mknod */ + char *link; /* For symlink */ + struct nameidata *source_nd; /* For link/rename */ + } create; + union { void *fs_data; /* FS-specific intent data */ } d; }; Index: linus-2.6.7/include/linux/fs.h =================================================================== --- linus-2.6.7.orig/include/linux/fs.h 2005-03-05 20:24:52.000000000 +0200 +++ linus-2.6.7/include/linux/fs.h 2005-03-23 13:35:08.796628072 +0200 @@ -909,6 +909,7 @@ ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); + int (*endparentlookup) (struct nameidata *); }; struct seq_file;