sb=n Use alternate superblock at this location.
-+iopen Makes an invisible pseudo-directory called
++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
+ if (ext3_iopen_get_inode(inode))
+ return;
-+
++
if(ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/iopen.c Sun Nov 16 01:27:31 2003
+++ linux-2.4.19.SuSE/fs/ext3/iopen.c Sun Nov 16 01:27:31 2003
-@@ -0,0 +1,259 @@
+@@ -0,0 +1,258 @@
+/*
+ * 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.
-+ *
++ *
+ *
+ * Invariants:
+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
+ struct list_head *lp;
+ struct dentry *alternate;
+ char buf[IOPEN_NAME_LEN];
-+
++
+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ return ERR_PTR(-ENOENT);
+ }
+
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++
+ /* preferrably return a connected dentry */
+ spin_lock(&dcache_lock);
+ list_for_each(lp, &inode->i_dentry) {
+ }
+
+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
++ alternate = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias);
+ dget_locked(alternate);
+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
+ return alternate;
+ }
+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
++
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
+ spin_unlock(&dcache_lock);
+
-+ d_add(dentry, inode);
+ return NULL;
+}
+
+{
+ const unsigned char *old_name, *new_name;
+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
++ 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)
+
+/* This function is spliced into ext3_lookup and does the move of a
+ * disconnected dentry (if it exists) to a connected dentry.
++ * Caller must hold dcache_lock.
+ */
+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode)
+{
+ 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_NFSD_DISCONNECTED) {
+ }
+ }
+
-+ if (!goal) {
-+ spin_unlock(&dcache_lock);
-+ return NULL;
-+ }
++ if (!goal)
++ return NULL;
+
+ /* Move the goal to the de hash queue - like d_move() */
+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
+ list_add(&de->d_child, &de->d_parent->d_subdirs);
+ __d_rehash(goal, 0);
-+ spin_unlock(&dcache_lock);
+
+ return goal;
+}
+
+ inode = iget(dir->i_sb, EXT3_BAD_INO);
+
-+ if (!inode)
++ if (!inode)
+ return 0;
+ d_add(dentry, inode);
+ return 1;
+ inode->u.ext3_i.i_dtime = 0;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
+ * (for stat), not the fs block
-+ * size */
++ * size */
+ inode->i_blocks = 0;
+ inode->i_version = 1;
+ inode->i_generation = 0;
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/iopen.h Sun Nov 16 01:27:31 2003
+++ linux-2.4.19.SuSE/fs/ext3/iopen.h Sun Nov 16 01:27:31 2003
-@@ -0,0 +1,13 @@
+@@ -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);
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++ struct inode *inode);
Index: linux-2.4.19.SuSE/fs/ext3/namei.c
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/namei.c Sun Nov 16 01:23:20 2003
/*
* define how far ahead to read directories while searching them.
-@@ -922,16 +922,21 @@
- return NULL;
- }
- #endif
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
-
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -922,10 +922,14 @@
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
-@@ -943,6 +948,12 @@
+@@ -943,7 +948,28 @@
return ERR_PTR(-EACCES);
}
}
+- d_add(dentry, inode);
++
++ /* verify this dentry is really new */
++ assert(!dentry->d_inode);
++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
++ assert(list_empty(&dentry->d_hash)); /* d_rehash */
++ assert(list_empty(&dentry->d_subdirs));
+
++ spin_lock(&dcache_lock);
+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) {
++ spin_unlock(&dcache_lock);
+ iput(inode);
+ return alternate;
+ }
+
- d_add(dentry, inode);
++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
++ if (inode) /* d_instantiate */
++ list_add(&dentry->d_alias, &inode->i_dentry);
++ dentry->d_inode = inode;
++
++ __d_rehash(dentry, 0); /* d_rehash */
++ spin_unlock(&dcache_lock);
++
return NULL;
}
+
Index: linux-2.4.19.SuSE/fs/ext3/super.c
===================================================================
--- linux-2.4.19.SuSE.orig/fs/ext3/super.c Sun Nov 16 01:19:22 2003
+++ linux-2.4.19.SuSE/fs/ext3/super.c Sun Nov 16 01:27:31 2003
-@@ -864,6 +864,17 @@
+@@ -864,6 +864,18 @@
|| !strcmp (this_char, "quota")
|| !strcmp (this_char, "usrquota"))
/* Don't do anything ;-) */ ;
+ else if (!strcmp (this_char, "iopen")) {
+ set_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ } else if (!strcmp (this_char, "noiopen")) {
++ }
++ else if (!strcmp (this_char, "noiopen")) {
+ clear_opt (sbi->s_mount_opt, IOPEN);
+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
+ }