From: wangdi Date: Thu, 9 Oct 2003 15:20:21 +0000 (+0000) Subject: update 2.6.0-test6 patches X-Git-Tag: v1_7_0_51~2^7~433 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=22d10200bef3c63b8970158ecf8e8842353f7665;p=fs%2Flustre-release.git update 2.6.0-test6 patches --- diff --git a/lustre/kernel_patches/patches/export_symbols-2.6.0-test6.patch b/lustre/kernel_patches/patches/export_symbols-2.6.0-test6.patch new file mode 100644 index 0000000..93aa5ff --- /dev/null +++ b/lustre/kernel_patches/patches/export_symbols-2.6.0-test6.patch @@ -0,0 +1,68 @@ +Index: linux-2.6.0-test6/fs/filesystems.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/filesystems.c 2003-09-28 08:50:40.000000000 +0800 ++++ linux-2.6.0-test6/fs/filesystems.c 2003-10-07 18:07:58.000000000 +0800 +@@ -27,7 +27,7 @@ + */ + + static struct file_system_type *file_systems; +-static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED; ++rwlock_t file_systems_lock = RW_LOCK_UNLOCKED; + + /* WARNING: This can be used only if we _already_ own a reference */ + void get_filesystem(struct file_system_type *fs) +Index: linux-2.6.0-test6/include/linux/fs.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/fs.h 2003-10-07 16:09:11.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/fs.h 2003-10-09 19:47:24.996871688 +0800 +@@ -1385,6 +1385,7 @@ + + extern struct file_operations generic_ro_fops; + ++extern rwlock_t file_systems_lock; + #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) + + extern int vfs_readlink(struct dentry *, char __user *, int, const char *); +Index: linux-2.6.0-test6/kernel/ksyms.c +=================================================================== +--- linux-2.6.0-test6.orig/kernel/ksyms.c 2003-10-07 16:09:09.000000000 +0800 ++++ linux-2.6.0-test6/kernel/ksyms.c 2003-10-07 18:07:58.000000000 +0800 +@@ -393,3 +393,4 @@ + EXPORT_SYMBOL(dump_oncpu); + EXPORT_SYMBOL(dump_function_ptr); + #endif ++EXPORT_SYMBOL(file_systems_lock); +Index: linux-2.6.0-test6/include/linux/ext2_fs_sb.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/ext2_fs_sb.h 2003-09-28 08:50:57.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/ext2_fs_sb.h 2003-10-07 18:07:58.000000000 +0800 +@@ -16,9 +16,11 @@ + #ifndef _LINUX_EXT2_FS_SB + #define _LINUX_EXT2_FS_SB + ++#ifndef EXT_INCLUDE ++#define EXT_INCLUDE + #include + #include +- ++#endif + /* + * second extended-fs super-block data in memory + */ +Index: linux-2.6.0-test6/include/linux/ext3_fs_sb.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/ext3_fs_sb.h 2003-09-28 08:51:00.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/ext3_fs_sb.h 2003-10-07 18:07:58.000000000 +0800 +@@ -19,9 +19,12 @@ + #ifdef __KERNEL__ + #include + #include ++#ifndef EXT_INCLUDE ++#define EXT_INCLUDE + #include + #include + #endif ++#endif + + /* + * third extended-fs super-block data in memory diff --git a/lustre/kernel_patches/patches/iopen-2.6.0-test6.patch b/lustre/kernel_patches/patches/iopen-2.6.0-test6.patch new file mode 100644 index 0000000..3d99db8 --- /dev/null +++ b/lustre/kernel_patches/patches/iopen-2.6.0-test6.patch @@ -0,0 +1,424 @@ + Documentation/filesystems/ext2.txt | 16 ++ + fs/ext3/Makefile | 2 + fs/ext3/inode.c | 3 + fs/ext3/iopen.c | 239 +++++++++++++++++++++++++++++++++++++ + fs/ext3/iopen.h | 15 ++ + fs/ext3/namei.c | 13 ++ + fs/ext3/super.c | 11 + + include/linux/ext3_fs.h | 2 + 8 files changed, 300 insertions(+), 1 deletion(-) + +Index: linux-2.6.0-test6/Documentation/filesystems/ext2.txt +=================================================================== +--- linux-2.6.0-test6.orig/Documentation/filesystems/ext2.txt 2003-10-07 16:19:10.593048704 +0800 ++++ linux-2.6.0-test6/Documentation/filesystems/ext2.txt 2003-10-07 16:19:49.129190320 +0800 +@@ -35,6 +35,22 @@ + + sb=n Use alternate superblock at this location. + ++iopen Makes an invisible pseudo-directory called ++ __iopen__ available in the root directory ++ of the filesystem. Allows open-by-inode- ++ number. i.e., inode 3145 can be accessed ++ via /mntpt/__iopen__/3145 ++ ++iopen_nopriv This option makes the iopen directory be ++ world-readable. This may be safer since it ++ allows daemons to run as an unprivileged user, ++ however it significantly changes the security ++ model of a Unix filesystem, since previously ++ all files under a mode 700 directory were not ++ generally avilable even if the ++ permissions on the file itself is ++ world-readable. ++ + grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. + + +Index: linux-2.6.0-test6/fs/ext3/inode.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/ext3/inode.c 2003-10-07 16:19:10.595048400 +0800 ++++ linux-2.6.0-test6/fs/ext3/inode.c 2003-10-07 16:19:49.131190016 +0800 +@@ -37,6 +37,7 @@ + #include + #include + #include "xattr.h" ++#include "iopen.h" + #include "acl.h" + + /* +@@ -2479,6 +2480,8 @@ + ei->i_acl = EXT3_ACL_NOT_CACHED; + ei->i_default_acl = EXT3_ACL_NOT_CACHED; + #endif ++ if (ext3_iopen_get_inode(inode)) ++ return; + if (ext3_get_inode_loc(inode, &iloc, 0)) + goto bad_inode; + bh = iloc.bh; +Index: linux-2.6.0-test6/fs/ext3/iopen.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/ext3/iopen.c 2003-10-07 16:19:49.109193360 +0800 ++++ linux-2.6.0-test6/fs/ext3/iopen.c 2003-10-07 16:19:49.132189864 +0800 +@@ -0,0 +1,239 @@ ++ ++ ++/* ++ * linux/fs/ext3/iopen.c ++ * ++ * Special support for open by inode number ++ * ++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). ++ * ++ * This file may be redistributed under the terms of the GNU General ++ * Public License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "iopen.h" ++ ++#ifndef assert ++#define assert(test) J_ASSERT(test) ++#endif ++ ++#define IOPEN_NAME_LEN 32 ++ ++/* ++ * This implements looking up an inode by number. ++ */ ++static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) ++{ ++ struct inode * inode; ++ unsigned long ino; ++ struct list_head *lp; ++ struct dentry *alternate; ++ char buf[IOPEN_NAME_LEN]; ++ ++ if (dentry->d_name.len >= IOPEN_NAME_LEN) ++ return ERR_PTR(-ENAMETOOLONG); ++ ++ memcpy(buf, dentry->d_name.name, dentry->d_name.len); ++ buf[dentry->d_name.len] = 0; ++ ++ if (strcmp(buf, ".") == 0) ++ ino = dir->i_ino; ++ else if (strcmp(buf, "..") == 0) ++ ino = EXT3_ROOT_INO; ++ else ++ ino = simple_strtoul(buf, 0, 0); ++ ++ if ((ino != EXT3_ROOT_INO && ++ //ino != EXT3_ACL_IDX_INO && ++ //ino != EXT3_ACL_DATA_INO && ++ ino < EXT3_FIRST_INO(dir->i_sb)) || ++ ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count)) ++ return ERR_PTR(-ENOENT); ++ ++ inode = iget(dir->i_sb, ino); ++ if (!inode) ++ return ERR_PTR(-EACCES); ++ if (is_bad_inode(inode)) { ++ iput(inode); ++ return ERR_PTR(-ENOENT); ++ } ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ list_for_each(lp, &inode->i_dentry) { ++ alternate = list_entry(lp, struct dentry, d_alias); ++ assert(!(alternate->d_flags & DCACHE_DISCONNECTED)); ++ } ++ ++ if (!list_empty(&inode->i_dentry)) { ++ alternate = list_entry(inode->i_dentry.next, ++ struct dentry, d_alias); ++ dget_locked(alternate); ++ alternate->d_vfs_flags |= DCACHE_REFERENCED; ++ iput(inode); ++ spin_unlock(&dcache_lock); ++ return alternate; ++ } ++ dentry->d_flags |= DCACHE_DISCONNECTED; ++ spin_unlock(&dcache_lock); ++ ++ d_add(dentry, inode); ++ return NULL; ++} ++ ++#define do_switch(x,y) do { \ ++ __typeof__ (x) __tmp = x; \ ++ x = y; y = __tmp; } while (0) ++ ++static inline void switch_names(struct dentry * dentry, struct dentry * target) ++{ ++ const unsigned char *old_name, *new_name; ++ ++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); ++ old_name = target->d_name.name; ++ new_name = dentry->d_name.name; ++ if (old_name == target->d_iname) ++ old_name = dentry->d_iname; ++ if (new_name == dentry->d_iname) ++ new_name = target->d_iname; ++ target->d_name.name = new_name; ++ dentry->d_name.name = old_name; ++} ++ ++ ++struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode) ++{ ++ struct dentry *tmp, *goal = NULL; ++ struct list_head *lp; ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ /* verify this dentry is really new */ ++ assert(!de->d_inode); ++ assert(list_empty(&de->d_subdirs)); ++ assert(list_empty(&de->d_alias)); ++ ++ ++ list_for_each(lp, &inode->i_dentry) { ++ tmp = list_entry(lp, struct dentry, d_alias); ++ if (tmp->d_flags & DCACHE_DISCONNECTED) { ++ assert(tmp->d_alias.next == &inode->i_dentry); ++ assert(tmp->d_alias.prev == &inode->i_dentry); ++ goal = tmp; ++ dget_locked(goal); ++ break; ++ } ++ } ++ ++ if (!goal) { ++ spin_unlock(&dcache_lock); ++ return NULL; ++ } ++ ++ /* Move the goal to the de hash queue */ ++ goal->d_flags &= ~DCACHE_DISCONNECTED; ++ hlist_add_before(&goal->d_hash, &de->d_hash); ++ hlist_del(&goal->d_hash); ++ ++ list_del(&goal->d_child); ++ list_del(&de->d_child); ++ ++ /* Switch the parents and the names.. */ ++ switch_names(goal, de); ++ do_switch(goal->d_parent, de->d_parent); ++ do_switch(goal->d_name.len, de->d_name.len); ++ do_switch(goal->d_name.hash, de->d_name.hash); ++ ++ /* And add them back to the (new) parent lists */ ++ list_add(&goal->d_child, &goal->d_parent->d_subdirs); ++ list_add(&de->d_child, &de->d_parent->d_subdirs); ++ ++ spin_unlock(&dcache_lock); ++ return goal; ++} ++ ++/* ++ * These are the special structures for the iopen pseudo directory. ++ */ ++ ++static struct inode_operations iopen_inode_operations = { ++ lookup: iopen_lookup, /* BKL held */ ++}; ++ ++static struct file_operations iopen_file_operations = { ++ read: generic_read_dir, ++}; ++ ++static int match_dentry(struct dentry *dentry, const char *name) ++{ ++ int len; ++ ++ len = strlen(name); ++ if (dentry->d_name.len != len) ++ return 0; ++ if (strncmp(dentry->d_name.name, name, len)) ++ return 0; ++ return 1; ++} ++ ++/* ++ * This function is spliced into ext3_lookup and returns 1 the file ++ * name is __iopen__ and dentry has been filled in appropriately. ++ */ ++int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry) ++{ ++ struct inode * inode; ++ ++ if (dir->i_ino != EXT3_ROOT_INO || ++ !test_opt(dir->i_sb, IOPEN) || ++ !match_dentry(dentry, "__iopen__")) ++ return 0; ++ ++ inode = iget(dir->i_sb, EXT3_BAD_INO); ++ ++ if (!inode) ++ return 0; ++ d_add(dentry, inode); ++ return 1; ++} ++ ++/* ++ * This function is spliced into read_inode; it returns 1 if inode ++ * number is the one for /__iopen__, in which case the inode is filled ++ * in appropriately. Otherwise, this fuction returns 0. ++ */ ++int ext3_iopen_get_inode(struct inode * inode) ++{ ++ if (inode->i_ino != EXT3_BAD_INO) ++ return 0; ++ ++ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR; ++ if (test_opt(inode->i_sb, IOPEN_NOPRIV)) ++ inode->i_mode |= 0777; ++ inode->i_uid = 0; ++ inode->i_gid = 0; ++ inode->i_nlink = 1; ++ inode->i_size = 4096; ++ inode->i_atime = CURRENT_TIME; ++ inode->i_ctime = CURRENT_TIME; ++ inode->i_mtime = CURRENT_TIME; ++ EXT3_I(inode)->i_dtime = 0; ++ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size ++ * (for stat), not the fs block ++ * size */ ++ inode->i_blocks = 0; ++ inode->i_version = 1; ++ inode->i_generation = 0; ++ ++ inode->i_op = &iopen_inode_operations; ++ inode->i_fop = &iopen_file_operations; ++ inode->i_mapping->a_ops = 0; ++ ++ return 1; ++} +Index: linux-2.6.0-test6/fs/ext3/iopen.h +=================================================================== +--- linux-2.6.0-test6.orig/fs/ext3/iopen.h 2003-10-07 16:19:49.109193360 +0800 ++++ linux-2.6.0-test6/fs/ext3/iopen.h 2003-10-07 16:19:49.132189864 +0800 +@@ -0,0 +1,15 @@ ++/* ++ * iopen.h ++ * ++ * Special support for opening files by inode number. ++ * ++ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). ++ * ++ * This file may be redistributed under the terms of the GNU General ++ * Public License. ++ */ ++ ++extern int ext3_check_for_iopen(struct inode * dir, struct dentry *dentry); ++extern int ext3_iopen_get_inode(struct inode * inode); ++ ++ +Index: linux-2.6.0-test6/fs/ext3/namei.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/ext3/namei.c 2003-10-07 16:19:10.597048096 +0800 ++++ linux-2.6.0-test6/fs/ext3/namei.c 2003-10-07 16:19:49.133189712 +0800 +@@ -37,6 +37,7 @@ + #include + #include + #include "xattr.h" ++#include "iopen.h" + #include "acl.h" + + /* +@@ -970,15 +971,21 @@ + } + #endif + ++struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode); ++ + static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) + { + struct inode * inode; + struct ext3_dir_entry_2 * de; + struct buffer_head * bh; ++ struct dentry *alternate = NULL; + + if (dentry->d_name.len > EXT3_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + ++ if (ext3_check_for_iopen(dir, dentry)) ++ return NULL; ++ + bh = ext3_find_entry(dentry, &de); + inode = NULL; + if (bh) { +@@ -991,6 +998,12 @@ + } + if (inode) + return d_splice_alias(inode, dentry); ++ ++ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) { ++ iput(inode); ++ return alternate; ++ } ++ + d_add(dentry, inode); + return NULL; + } +Index: linux-2.6.0-test6/fs/ext3/super.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/ext3/super.c 2003-10-07 16:19:10.599047792 +0800 ++++ linux-2.6.0-test6/fs/ext3/super.c 2003-10-07 16:25:14.799680880 +0800 +@@ -534,7 +534,7 @@ + Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload, + Opt_commit, Opt_journal_update, Opt_journal_inum, + Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, +- Opt_ignore, Opt_err, ++ Opt_ignore, Opt_err, Opt_iopen, Opt_noiopen, Opt_iopen_nopriv, + }; + + static match_table_t tokens = { +@@ -573,6 +573,9 @@ + {Opt_ignore, "noquota"}, + {Opt_ignore, "quota"}, + {Opt_ignore, "usrquota"}, ++ {Opt_iopen, "iopen"}, ++ {Opt_noiopen, "noiopen"}, ++ {Opt_iopen_nopriv, "iopen_nopriv"}, + {Opt_err, NULL} + }; + +@@ -760,6 +763,18 @@ + case Opt_abort: + set_opt(sbi->s_mount_opt, ABORT); + break; ++ case Opt_iopen: ++ set_opt (sbi->s_mount_opt, IOPEN); ++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ break; ++ case Opt_noiopen: ++ clear_opt (sbi->s_mount_opt, IOPEN); ++ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ break; ++ case Opt_iopen_nopriv: ++ set_opt (sbi->s_mount_opt, IOPEN); ++ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV); ++ break; + case Opt_ignore: + break; + default: +Index: linux-2.6.0-test6/include/linux/ext3_fs.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/ext3_fs.h 2003-10-07 16:19:10.600047640 +0800 ++++ linux-2.6.0-test6/include/linux/ext3_fs.h 2003-10-07 16:19:49.136189256 +0800 +@@ -324,6 +324,8 @@ + #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ + #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ + #define EXT3_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ ++#define EXT3_MOUNT_IOPEN 0x10000 /* Allow access via iopen */ ++#define EXT3_MOUNT_IOPEN_NOPRIV 0x20000 /* Make iopen world-readable */ + + /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ + #ifndef _LINUX_EXT2_FS_H diff --git a/lustre/kernel_patches/patches/vfs_intent_2.6.0-test6.patch b/lustre/kernel_patches/patches/vfs_intent_2.6.0-test6.patch new file mode 100644 index 0000000..5dd86e0 --- /dev/null +++ b/lustre/kernel_patches/patches/vfs_intent_2.6.0-test6.patch @@ -0,0 +1,754 @@ + fs/exec.c | 18 +++++++--- + fs/namei.c | 86 +++++++++++++++++++++++++++++++++++++++++++++---- + fs/namespace.c | 2 + + fs/nfs/dir.c | 4 +- + fs/open.c | 62 +++++++++++++++++++++++------------ + fs/stat.c | 24 ++++++++++--- + include/linux/dcache.h | 3 + + include/linux/fs.h | 8 ++++ + include/linux/namei.h | 56 ++++++++++++++++++++++++++----- + kernel/ksyms.c | 8 ++++ + 10 files changed, 222 insertions(+), 49 deletions(-) + +Index: linux-2.6.0-test6/fs/exec.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/exec.c 2003-10-07 15:14:14.000000000 +0800 ++++ linux-2.6.0-test6/fs/exec.c 2003-10-07 15:33:15.000000000 +0800 +@@ -120,8 +120,11 @@ + struct file * file; + struct nameidata nd; + int error; ++ intent_init(&nd.intent, IT_OPEN); + +- nd.intent.open.flags = O_RDONLY; ++ error = user_path_walk_it(library, &nd); ++ ++ nd.intent.it_flags = O_RDONLY; + error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); + if (error) + goto out; +@@ -134,7 +137,7 @@ + if (error) + goto exit; + +- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); ++ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &nd.intent); + error = PTR_ERR(file); + if (IS_ERR(file)) + goto out; +@@ -471,8 +474,13 @@ + struct file *open_exec(const char *name) + { + struct nameidata nd; +- int err = path_lookup(name, LOOKUP_FOLLOW, &nd); +- struct file *file = ERR_PTR(err); ++ int err; ++ struct file *file; ++ ++ intent_init(&nd.intent, IT_OPEN); ++ nd.intent.it_flags = O_RDONLY; ++ err = path_lookup(name, LOOKUP_FOLLOW, &nd); ++ file = ERR_PTR(err); + + if (!err) { + struct inode *inode = nd.dentry->d_inode; +@@ -484,7 +492,7 @@ + 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, &nd.intent); + if (!IS_ERR(file)) { + err = deny_write_access(file); + if (err) { +Index: linux-2.6.0-test6/fs/namei.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/namei.c 2003-10-07 15:14:14.000000000 +0800 ++++ linux-2.6.0-test6/fs/namei.c 2003-10-07 15:33:15.000000000 +0800 +@@ -264,8 +264,19 @@ + return 0; + } + ++void intent_release(struct lookup_intent *it) ++{ ++ if (!it) ++ return; ++ if (it->it_magic != INTENT_MAGIC) ++ return; ++ if (it->it_op_release) ++ it->it_op_release(it); ++} ++ + void path_release(struct nameidata *nd) + { ++ intent_release(&nd->intent); + dput(nd->dentry); + mntput(nd->mnt); + } +@@ -342,7 +353,10 @@ + { + struct dentry * result; + struct inode *dir = parent->d_inode; ++ int counter = 0; + ++again: ++ counter++; + down(&dir->i_sem); + /* + * First re-do the cached lookup just in case it was created +@@ -381,7 +395,10 @@ + if (result->d_op && result->d_op->d_revalidate) { + if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { + dput(result); +- result = ERR_PTR(-ENOENT); ++ if (counter > 10) ++ result = ERR_PTR(-ESTALE); ++ if (!IS_ERR(result)) ++ goto again; + } + } + return result; +@@ -556,6 +573,31 @@ + return PTR_ERR(dentry); + } + ++static int revalidate_special(struct nameidata *nd) ++{ ++ struct dentry *dentry = nd->dentry; ++ int err, counter = 0; ++ ++ if (!dentry->d_op || !dentry->d_op->d_revalidate) ++ return 0; ++ revalidate_again: ++ if (!dentry->d_op->d_revalidate(dentry, nd)) { ++ struct dentry *new; ++ if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC,nd))) ++ return err; ++ new = real_lookup(dentry->d_parent, &dentry->d_name, nd); ++ d_invalidate(dentry); ++ dput(dentry); ++ dentry = new; ++ counter++; ++ if (counter < 10) ++ goto revalidate_again; ++ printk("excessive revalidate_it loops\n"); ++ return -ESTALE; ++ } ++ return 0; ++} ++ + /* + * Name resolution. + * +@@ -656,7 +698,9 @@ + + if (inode->i_op->follow_link) { + mntget(next.mnt); ++ nd->flags |= LOOKUP_LINK_NOTLAST; + err = do_follow_link(next.dentry, nd); ++ nd->flags &= ~LOOKUP_LINK_NOTLAST; + dput(next.dentry); + mntput(next.mnt); + if (err) +@@ -695,6 +739,11 @@ + inode = nd->dentry->d_inode; + /* fallthrough */ + case 1: ++ nd->flags |= LOOKUP_LAST; ++ err = revalidate_special(nd); ++ nd->flags &= ~LOOKUP_LAST; ++ if (err) ++ break; + goto return_reval; + } + if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { +@@ -702,7 +751,9 @@ + if (err < 0) + break; + } ++ nd->flags |= LOOKUP_LAST; + err = do_lookup(nd, &this, &next); ++ nd->flags &= ~LOOKUP_LAST; + if (err) + break; + follow_mount(&next.mnt, &next.dentry); +@@ -928,7 +979,7 @@ + } + + /* SMP-safe */ +-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) ++struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct nameidata *nd) + { + unsigned long hash; + struct qstr this; +@@ -948,11 +999,16 @@ + } + this.hash = end_name_hash(hash); + +- return lookup_hash(&this, base); ++ return __lookup_hash(&this, base, nd); + access: + return ERR_PTR(-EACCES); + } + ++struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) ++{ ++ return lookup_one_len_it(name, base, len, NULL); ++} ++ + /* + * namei() + * +@@ -964,11 +1020,12 @@ + * that namei follows links, while lnamei does not. + * SMP-safe + */ +-int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) ++int __user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd) + { + char *tmp = getname(name); + int err = PTR_ERR(tmp); + ++ + if (!IS_ERR(tmp)) { + err = path_lookup(tmp, flags, nd); + putname(tmp); +@@ -976,6 +1033,12 @@ + return err; + } + ++int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) ++{ ++ intent_init(&nd->intent, IT_LOOKUP); ++ return __user_walk_it(name, flags, nd); ++} ++ + /* + * It's inline, so penalty for filesystems that don't use sticky bit is + * minimal. +@@ -1248,8 +1311,8 @@ + acc_mode |= MAY_APPEND; + + /* Fill in the open() intent data */ +- nd->intent.open.flags = flag; +- nd->intent.open.create_mode = mode; ++ nd->intent.it_flags = flag; ++ nd->intent.it_create_mode = mode; + + /* + * The simplest case - just a plain lookup. +@@ -1265,6 +1328,7 @@ + /* + * Create - we need to know the parent. + */ ++ nd->intent.it_op |= IT_CREAT; + error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd); + if (error) + return error; +@@ -1281,7 +1345,9 @@ + dir = nd->dentry; + nd->flags &= ~LOOKUP_PARENT; + down(&dir->d_inode->i_sem); ++ nd->flags |= LOOKUP_LAST; + dentry = __lookup_hash(&nd->last, nd->dentry, nd); ++ nd->flags &= ~LOOKUP_LAST; + + do_last: + error = PTR_ERR(dentry); +@@ -1386,7 +1452,9 @@ + } + dir = nd->dentry; + down(&dir->d_inode->i_sem); ++ nd->flags |= LOOKUP_LAST; + dentry = __lookup_hash(&nd->last, nd->dentry, nd); ++ nd->flags &= ~LOOKUP_LAST; + putname(nd->last.name); + goto do_last; + } +@@ -2148,7 +2216,9 @@ + __vfs_follow_link(struct nameidata *nd, const char *link) + { + int res = 0; ++ struct lookup_intent it = nd->intent; + char *name; ++ + if (IS_ERR(link)) + goto fail; + +@@ -2158,6 +2228,10 @@ + /* weird __emul_prefix() stuff did it */ + goto out; + } ++ ++ intent_init(&nd->intent, it.it_op); ++ nd->intent.it_flags = it.it_flags; ++ nd->intent.it_create_mode = it.it_create_mode; + res = link_path_walk(link, nd); + out: + if (current->link_count || res || nd->last_type!=LAST_NORM) +Index: linux-2.6.0-test6/fs/namespace.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/namespace.c 2003-09-28 08:50:31.000000000 +0800 ++++ linux-2.6.0-test6/fs/namespace.c 2003-10-07 15:33:15.000000000 +0800 +@@ -738,6 +738,7 @@ + int retval = 0; + int mnt_flags = 0; + ++ intent_init(&nd.intent, IT_LOOKUP); + /* Discard magic */ + if ((flags & MS_MGC_MSK) == MS_MGC_VAL) + flags &= ~MS_MGC_MSK; +@@ -947,6 +948,7 @@ + mntput(old_pwdmnt); + } + } ++EXPORT_SYMBOL(set_fs_pwd); + + static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) + { +Index: linux-2.6.0-test6/fs/open.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/open.c 2003-10-07 15:14:14.000000000 +0800 ++++ linux-2.6.0-test6/fs/open.c 2003-10-07 15:33:15.000000000 +0800 +@@ -202,7 +202,7 @@ + struct nameidata nd; + struct inode * inode; + int error; +- ++ intent_init(&nd.intent, IT_GETATTR); + error = -EINVAL; + if (length < 0) /* sorry, but loff_t says... */ + goto out; +@@ -461,6 +461,7 @@ + int old_fsuid, old_fsgid; + kernel_cap_t old_cap; + int res; ++ intent_init(&nd.intent, IT_GETATTR); + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; +@@ -492,6 +493,7 @@ + if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) + && !special_file(nd.dentry->d_inode->i_mode)) + res = -EROFS; ++ + path_release(&nd); + } + +@@ -506,6 +508,7 @@ + { + struct nameidata nd; + int error; ++ intent_init(&nd.intent, IT_GETATTR); + + error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); + if (error) +@@ -557,6 +560,7 @@ + { + struct nameidata nd; + int error; ++ intent_init(&nd.intent, IT_GETATTR); + + error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); + if (error) +@@ -629,7 +633,7 @@ + error = -EROFS; + if (IS_RDONLY(inode)) + goto dput_and_out; +- ++ + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto dput_and_out; +@@ -737,25 +741,8 @@ + * 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; +- +- namei_flags = flags; +- if ((namei_flags+1) & O_ACCMODE) +- namei_flags++; +- 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); +- +- return ERR_PTR(error); +-} +- +-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; +@@ -767,6 +754,7 @@ + goto cleanup_dentry; + f->f_flags = flags; + f->f_mode = (flags+1) & O_ACCMODE; ++ f->f_it = it; + inode = dentry->d_inode; + if (f->f_mode & FMODE_WRITE) { + error = get_write_access(inode); +@@ -786,6 +774,7 @@ + error = f->f_op->open(inode,f); + if (error) + goto cleanup_all; ++ intent_release(it); + } + f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + +@@ -810,11 +799,42 @@ + cleanup_file: + put_filp(f); + cleanup_dentry: ++ intent_release(it); + dput(dentry); + mntput(mnt); + return ERR_PTR(error); + } + ++struct file *filp_open(const char * filename, int flags, int mode) ++{ ++ int namei_flags, error; ++ struct file * temp_filp; ++ struct nameidata nd; ++ intent_init(&nd.intent, IT_OPEN); ++ ++ namei_flags = flags; ++ if ((namei_flags+1) & O_ACCMODE) ++ namei_flags++; ++ if (namei_flags & O_TRUNC) ++ namei_flags |= 2; ++ ++ error = open_namei(filename, namei_flags, mode, &nd); ++ if (!error) { ++ temp_filp = dentry_open_it(nd.dentry, nd.mnt, flags, &nd.intent); ++ return temp_filp; ++ } ++ return ERR_PTR(error); ++} ++ ++ ++struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) ++{ ++ struct lookup_intent it; ++ intent_init(&it, IT_LOOKUP); ++ ++ return dentry_open_it(dentry, mnt, flags, &it); ++} ++ + /* + * Find an empty file descriptor entry, and mark it busy. + */ +Index: linux-2.6.0-test6/fs/stat.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/stat.c 2003-09-28 08:50:10.000000000 +0800 ++++ linux-2.6.0-test6/fs/stat.c 2003-10-07 15:33:15.000000000 +0800 +@@ -33,7 +33,7 @@ + stat->blksize = inode->i_blksize; + } + +-int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) ++int vfs_getattr_it(struct vfsmount *mnt, struct dentry *dentry, struct lookup_intent *it, struct kstat *stat) + { + struct inode *inode = dentry->d_inode; + int retval; +@@ -44,6 +44,8 @@ + + if (inode->i_op->getattr) + return inode->i_op->getattr(mnt, dentry, stat); ++ if (inode->i_op->getattr_it) ++ return inode->i_op->getattr_it(mnt, dentry, it, stat); + + generic_fillattr(inode, stat); + if (!stat->blksize) { +@@ -56,14 +58,20 @@ + return 0; + } + ++int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) ++{ ++ return vfs_getattr_it(mnt, dentry, NULL, stat); ++} ++ + int vfs_stat(char __user *name, struct kstat *stat) + { + struct nameidata nd; + int error; ++ intent_init(&nd.intent, IT_GETATTR); + +- error = user_path_walk(name, &nd); ++ error = user_path_walk_it(name, &nd); + if (!error) { +- error = vfs_getattr(nd.mnt, nd.dentry, stat); ++ error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat); + path_release(&nd); + } + return error; +@@ -73,10 +81,11 @@ + { + struct nameidata nd; + int error; ++ intent_init(&nd.intent, IT_GETATTR); + +- error = user_path_walk_link(name, &nd); ++ error = user_path_walk_link_it(name, &nd); + if (!error) { +- error = vfs_getattr(nd.mnt, nd.dentry, stat); ++ error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat); + path_release(&nd); + } + return error; +@@ -86,9 +95,12 @@ + { + struct file *f = fget(fd); + int error = -EBADF; ++ struct nameidata nd; ++ intent_init(&nd.intent, IT_GETATTR); + + if (f) { +- error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat); ++ error = vfs_getattr_it(f->f_vfsmnt, f->f_dentry, &nd.intent, stat); ++ intent_release(&nd.intent); + fput(f); + } + return error; +Index: linux-2.6.0-test6/include/linux/dcache.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/dcache.h 2003-09-28 08:51:16.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/dcache.h 2003-10-07 15:33:15.000000000 +0800 +@@ -4,6 +4,7 @@ + #ifdef __KERNEL__ + + #include ++#include + #include + #include + #include +@@ -35,6 +36,8 @@ + char name_str[0]; + }; + ++#include ++ + struct dentry_stat_t { + int nr_dentry; + int nr_unused; +Index: linux-2.6.0-test6/include/linux/fs.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/fs.h 2003-10-07 15:14:15.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/fs.h 2003-10-07 15:34:10.000000000 +0800 +@@ -243,6 +243,8 @@ + #define ATTR_ATTR_FLAG 1024 + #define ATTR_KILL_SUID 2048 + #define ATTR_KILL_SGID 4096 ++#define ATTR_RAW 8192 /* file system, not vfs will massage attrs */ ++#define ATTR_FROM_OPEN 16384 /* called from open path, ie O_TRUNC */ + + /* + * This is the Inode Attributes structure, used for notify_change(). It +@@ -402,6 +404,7 @@ + struct block_device *i_bdev; + struct cdev *i_cdev; + int i_cindex; ++ void *i_filterdata; + + unsigned long i_dnotify_mask; /* Directory notify events */ + struct dnotify_struct *i_dnotify; /* for directory notifications */ +@@ -530,6 +533,7 @@ + struct list_head f_ep_links; + spinlock_t f_ep_lock; + struct address_space *f_mapping; ++ struct lookup_intent *f_it; + }; + extern spinlock_t files_lock; + #define file_list_lock() spin_lock(&files_lock); +@@ -839,7 +843,9 @@ + void (*truncate) (struct inode *); + int (*permission) (struct inode *, int, struct nameidata *); + int (*setattr) (struct dentry *, struct iattr *); ++ int (*setattr_raw) (struct inode *, struct iattr *); + int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); ++ int (*getattr_it) (struct vfsmount *, struct dentry *, struct lookup_intent *, struct kstat *); + int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); + ssize_t (*listxattr) (struct dentry *, char *, size_t); +@@ -1052,6 +1058,7 @@ + extern int unregister_filesystem(struct file_system_type *); + extern struct vfsmount *kern_mount(struct file_system_type *); + extern int may_umount(struct vfsmount *); ++struct vfsmount *do_kern_mount(const char *type, int flags, const char *name, void *data); + extern long do_mount(char *, char *, char *, unsigned long, void *); + + extern int vfs_statfs(struct super_block *, struct kstatfs *); +@@ -1119,6 +1126,7 @@ + + extern struct file *filp_open(const char *, int, int); + extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); ++extern struct file * dentry_open_it(struct dentry *, struct vfsmount *, int, struct lookup_intent *); + extern int filp_close(struct file *, fl_owner_t id); + extern char * getname(const char __user *); + +Index: linux-2.6.0-test6/include/linux/namei.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/namei.h 2003-09-28 08:50:15.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/namei.h 2003-10-07 15:33:15.000000000 +0800 +@@ -2,25 +2,55 @@ + #define _LINUX_NAMEI_H + + #include ++#include + + struct vfsmount; ++struct nameidata; + +-struct open_intent { +- int flags; +- int create_mode; ++/* intent opcodes */ ++#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) ++#define IT_TRUNC (1<<6) ++#define IT_GETXATTR (1<<7) ++ ++struct lustre_intent_data { ++ int it_disposition; ++ int it_status; ++ __u64 it_lock_handle; ++ void *it_data; ++ int it_lock_mode; + }; + ++#define INTENT_MAGIC 0x19620323 ++struct lookup_intent { ++ int it_magic; ++ void (*it_op_release)(struct lookup_intent *); ++ int it_op; ++ int it_flags; ++ int it_create_mode; ++ union { ++ struct lustre_intent_data lustre; ++ } d; ++}; ++ ++static inline void intent_init(struct lookup_intent *it, int op) ++{ ++ memset(it, 0, sizeof(*it)); ++ it->it_magic = INTENT_MAGIC; ++ it->it_op = op; ++} ++ + struct nameidata { + struct dentry *dentry; + struct vfsmount *mnt; + struct qstr last; + unsigned int flags; + int last_type; +- +- /* Intent data */ +- union { +- struct open_intent open; +- } intent; ++ struct lookup_intent intent; + }; + + /* +@@ -41,6 +71,9 @@ + #define LOOKUP_CONTINUE 4 + #define LOOKUP_PARENT 16 + #define LOOKUP_NOALT 32 ++#define LOOKUP_LAST (1<<6) ++#define LOOKUP_LINK_NOTLAST (1<<7) ++ + /* + * Intent data + */ +@@ -49,6 +82,12 @@ + #define LOOKUP_ACCESS (0x0400) + + extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *)); ++extern int FASTCALL(__user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd)); ++#define user_path_walk_it(name,nd) \ ++ __user_walk_it(name, LOOKUP_FOLLOW, nd) ++#define user_path_walk_link_it(name,nd) \ ++ __user_walk_it(name, 0, nd) ++extern void intent_release(struct lookup_intent *); + #define user_path_walk(name,nd) \ + __user_walk(name, LOOKUP_FOLLOW, nd) + #define user_path_walk_link(name,nd) \ +@@ -60,7 +99,6 @@ + + extern struct dentry * lookup_one_len(const char *, struct dentry *, int); + extern struct dentry * lookup_hash(struct qstr *, struct dentry *); +- + extern int follow_down(struct vfsmount **, struct dentry **); + extern int follow_up(struct vfsmount **, struct dentry **); + +Index: linux-2.6.0-test6/kernel/ksyms.c +=================================================================== +--- linux-2.6.0-test6.orig/kernel/ksyms.c 2003-10-07 15:21:57.000000000 +0800 ++++ linux-2.6.0-test6/kernel/ksyms.c 2003-10-07 15:33:15.000000000 +0800 +@@ -220,11 +220,18 @@ + EXPORT_SYMBOL(unregister_filesystem); + EXPORT_SYMBOL(__mntput); + EXPORT_SYMBOL(may_umount); ++EXPORT_SYMBOL(reparent_to_init); + + /* interrupt handling */ + EXPORT_SYMBOL(request_irq); + EXPORT_SYMBOL(free_irq); + ++/* lustre */ ++EXPORT_SYMBOL(do_kern_mount); ++EXPORT_SYMBOL(exit_files); ++//EXPORT_SYMBOL(kmem_cache_validate); ++ ++ + /* waitqueue handling */ + EXPORT_SYMBOL(add_wait_queue); + EXPORT_SYMBOL(add_wait_queue_exclusive); +Index: linux-2.6.0-test6/fs/nfs/dir.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/nfs/dir.c 2003-09-28 08:50:20.000000000 +0800 ++++ linux-2.6.0-test6/fs/nfs/dir.c 2003-10-07 15:33:15.000000000 +0800 +@@ -652,7 +652,7 @@ + return 0; + if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) + return 0; +- return (nd->intent.open.flags & O_EXCL) != 0; ++ return (nd->intent.it_flags & O_EXCL) != 0; + } + + static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) +@@ -825,7 +825,7 @@ + attr.ia_valid = ATTR_MODE; + + if (nd && (nd->flags & LOOKUP_CREATE)) +- open_flags = nd->intent.open.flags; ++ open_flags = nd->intent.it_flags; + + /* + * The 0 argument passed into the create function should one day +Index: linux-2.6.0-test6/fs/inode.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/inode.c 2003-10-07 15:14:14.000000000 +0800 ++++ linux-2.6.0-test6/fs/inode.c 2003-10-07 15:38:08.000000000 +0800 +@@ -224,6 +224,7 @@ + inodes_stat.nr_unused--; + } + ++EXPORT_SYMBOL(__iget); + /** + * clear_inode - clear an inode + * @inode: inode to clear diff --git a/lustre/kernel_patches/patches/vfs_nointent_2.6.0-test6.patch b/lustre/kernel_patches/patches/vfs_nointent_2.6.0-test6.patch new file mode 100644 index 0000000..7c2ea35 --- /dev/null +++ b/lustre/kernel_patches/patches/vfs_nointent_2.6.0-test6.patch @@ -0,0 +1,411 @@ + 0 files changed + +Index: linux-2.6.0-test6/fs/namei.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/namei.c 2003-10-07 15:33:15.000000000 +0800 ++++ linux-2.6.0-test6/fs/namei.c 2003-10-07 15:39:16.000000000 +0800 +@@ -1270,7 +1270,7 @@ + if (!error) { + DQUOT_INIT(inode); + +- error = do_truncate(dentry, 0); ++ error = do_truncate(dentry, 0, 1); + } + put_write_access(inode); + if (error) +@@ -1521,6 +1521,7 @@ + char * tmp; + struct dentry * dentry; + struct nameidata nd; ++ intent_init(&nd.intent, IT_LOOKUP); + + if (S_ISDIR(mode)) + return -EPERM; +@@ -1531,6 +1532,15 @@ + error = path_lookup(tmp, LOOKUP_PARENT, &nd); + if (error) + goto out; ++ ++ if (nd.dentry->d_inode->i_op->mknod_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->mknod_raw(&nd, mode, dev); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out2; ++ } ++ + dentry = lookup_create(&nd, 0); + error = PTR_ERR(dentry); + +@@ -1557,6 +1567,7 @@ + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); ++out2: + path_release(&nd); + out: + putname(tmp); +@@ -1598,10 +1609,18 @@ + if (!IS_ERR(tmp)) { + struct dentry *dentry; + struct nameidata nd; ++ intent_init(&nd.intent, IT_LOOKUP); + + error = path_lookup(tmp, LOOKUP_PARENT, &nd); + if (error) + goto out; ++ if (nd.dentry->d_inode->i_op->mkdir_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->mkdir_raw(&nd, mode); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out2; ++ } + dentry = lookup_create(&nd, 1); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { +@@ -1611,6 +1630,7 @@ + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); ++out2: + path_release(&nd); + out: + putname(tmp); +@@ -1691,6 +1711,7 @@ + char * name; + struct dentry *dentry; + struct nameidata nd; ++ intent_init(&nd.intent, IT_LOOKUP); + + name = getname(pathname); + if(IS_ERR(name)) +@@ -1711,6 +1732,16 @@ + error = -EBUSY; + goto exit1; + } ++ ++ if (nd.dentry->d_inode->i_op->rmdir_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ ++ error = op->rmdir_raw(&nd); ++ /* 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); + error = PTR_ERR(dentry); +@@ -1769,6 +1800,7 @@ + struct dentry *dentry; + struct nameidata nd; + struct inode *inode = NULL; ++ intent_init(&nd.intent, IT_LOOKUP); + + name = getname(pathname); + if(IS_ERR(name)) +@@ -1780,6 +1812,13 @@ + error = -EISDIR; + if (nd.last_type != LAST_NORM) + goto exit1; ++ if (nd.dentry->d_inode->i_op->unlink_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->unlink_raw(&nd); ++ /* 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); + error = PTR_ERR(dentry); +@@ -1847,10 +1886,18 @@ + if (!IS_ERR(to)) { + struct dentry *dentry; + struct nameidata nd; ++ intent_init(&nd.intent, IT_LOOKUP); + + error = path_lookup(to, LOOKUP_PARENT, &nd); + if (error) + goto out; ++ if (nd.dentry->d_inode->i_op->symlink_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->symlink_raw(&nd, from); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out2; ++ } + dentry = lookup_create(&nd, 0); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { +@@ -1858,6 +1905,7 @@ + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); ++out2: + path_release(&nd); + out: + putname(to); +@@ -1921,6 +1969,8 @@ + struct nameidata nd, old_nd; + int error; + char * to; ++ intent_init(&nd.intent, IT_LOOKUP); ++ intent_init(&old_nd.intent, IT_LOOKUP); + + to = getname(newname); + if (IS_ERR(to)) +@@ -1935,6 +1985,13 @@ + error = -EXDEV; + if (old_nd.mnt != nd.mnt) + goto out_release; ++ if (nd.dentry->d_inode->i_op->link_raw) { ++ struct inode_operations *op = nd.dentry->d_inode->i_op; ++ error = op->link_raw(&old_nd, &nd); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto out_release; ++ } + new_dentry = lookup_create(&nd, 0); + error = PTR_ERR(new_dentry); + if (!IS_ERR(new_dentry)) { +@@ -1985,7 +2042,7 @@ + * 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) + { + int error = 0; + struct inode *target; +@@ -2030,7 +2087,7 @@ + } + + 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 inode *target; + int error; +@@ -2107,6 +2164,8 @@ + struct dentry * old_dentry, *new_dentry; + struct dentry * trap; + struct nameidata oldnd, newnd; ++ intent_init(&oldnd.intent, IT_LOOKUP); ++ intent_init(&newnd.intent, IT_LOOKUP); + + error = path_lookup(oldname, LOOKUP_PARENT, &oldnd); + if (error) +@@ -2129,6 +2188,13 @@ + if (newnd.last_type != LAST_NORM) + goto exit2; + ++ if (old_dir->d_inode->i_op->rename_raw) { ++ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); ++ /* the file system wants to use normal vfs path now */ ++ if (error != -EOPNOTSUPP) ++ goto exit2; ++ } ++ + trap = lock_rename(new_dir, old_dir); + + old_dentry = lookup_hash(&oldnd.last, old_dir); +@@ -2160,8 +2226,7 @@ + if (new_dentry == trap) + goto exit5; + +- error = vfs_rename(old_dir->d_inode, old_dentry, +- new_dir->d_inode, new_dentry); ++ error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); + exit5: + dput(new_dentry); + exit4: +Index: linux-2.6.0-test6/fs/open.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/open.c 2003-10-07 15:33:15.000000000 +0800 ++++ linux-2.6.0-test6/fs/open.c 2003-10-07 15:40:41.000000000 +0800 +@@ -178,9 +178,10 @@ + return error; + } + +-int do_truncate(struct dentry *dentry, loff_t length) ++int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) + { + int err; ++ struct inode_operations *op = dentry->d_inode->i_op; + struct iattr newattrs; + + /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ +@@ -191,7 +192,14 @@ + newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; + down(&dentry->d_inode->i_sem); + down_write(&dentry->d_inode->i_alloc_sem); +- err = 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; ++ err = op->setattr_raw(dentry->d_inode, &newattrs); ++ } else ++ err = notify_change(dentry, &newattrs); + up_write(&dentry->d_inode->i_alloc_sem); + up(&dentry->d_inode->i_sem); + return err; +@@ -247,7 +255,7 @@ + error = locks_verify_truncate(inode, NULL, length); + if (!error) { + DQUOT_INIT(inode); +- error = do_truncate(nd.dentry, length); ++ error = do_truncate(nd.dentry, length, 0); + } + put_write_access(inode); + +@@ -299,7 +307,7 @@ + + 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: +@@ -378,9 +386,19 @@ + (error = permission(inode,MAY_WRITE,&nd)) != 0) + goto dput_and_out; + } +- down(&inode->i_sem); +- error = notify_change(nd.dentry, &newattrs); +- up(&inode->i_sem); ++ 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; ++ } else { ++ down(&inode->i_sem); ++ error = notify_change(nd.dentry, &newattrs); ++ up(&inode->i_sem); ++ } + dput_and_out: + path_release(&nd); + out: +@@ -431,9 +449,19 @@ + (error = permission(inode,MAY_WRITE,&nd)) != 0) + goto dput_and_out; + } +- down(&inode->i_sem); +- error = notify_change(nd.dentry, &newattrs); +- up(&inode->i_sem); ++ 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; ++ } else { ++ down(&inode->i_sem); ++ error = notify_change(nd.dentry, &newattrs); ++ up(&inode->i_sem); ++ } + dput_and_out: + path_release(&nd); + out: +@@ -634,6 +662,18 @@ + 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; +@@ -667,6 +707,18 @@ + if (IS_RDONLY(inode)) + goto out; + error = -EPERM; ++ 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; ++ } + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto out; + newattrs.ia_valid = ATTR_CTIME; +@@ -680,6 +732,7 @@ + } + if (!S_ISDIR(inode->i_mode)) + newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; ++ + down(&inode->i_sem); + error = notify_change(dentry, &newattrs); + up(&inode->i_sem); +Index: linux-2.6.0-test6/include/linux/fs.h +=================================================================== +--- linux-2.6.0-test6.orig/include/linux/fs.h 2003-10-07 15:34:10.000000000 +0800 ++++ linux-2.6.0-test6/include/linux/fs.h 2003-10-07 15:39:17.000000000 +0800 +@@ -831,13 +831,20 @@ + int (*create) (struct inode *,struct dentry *,int, struct nameidata *); + struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); + int (*link) (struct dentry *,struct inode *,struct dentry *); ++ int (*link_raw) (struct nameidata *,struct nameidata *); + int (*unlink) (struct inode *,struct dentry *); ++ int (*unlink_raw) (struct nameidata *); + int (*symlink) (struct inode *,struct dentry *,const char *); ++ int (*symlink_raw) (struct nameidata *,const char *); + int (*mkdir) (struct inode *,struct dentry *,int); ++ int (*mkdir_raw) (struct nameidata *,int); + int (*rmdir) (struct inode *,struct dentry *); ++ int (*rmdir_raw) (struct nameidata *); + int (*mknod) (struct inode *,struct dentry *,int,dev_t); ++ int (*mknod_raw) (struct nameidata *,int,dev_t); + int (*rename) (struct inode *, struct dentry *, + struct inode *, struct dentry *); ++ int (*rename_raw) (struct nameidata *, struct nameidata *); + int (*readlink) (struct dentry *, char __user *,int); + int (*follow_link) (struct dentry *, struct nameidata *); + void (*truncate) (struct inode *); +@@ -1122,7 +1129,7 @@ + + asmlinkage long sys_open(const char __user *, 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); +Index: linux-2.6.0-test6/fs/exec.c +=================================================================== +--- linux-2.6.0-test6.orig/fs/exec.c 2003-10-07 15:33:15.000000000 +0800 ++++ linux-2.6.0-test6/fs/exec.c 2003-10-07 15:39:17.000000000 +0800 +@@ -1390,7 +1390,7 @@ + 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);