Whamcloud - gitweb
Fix for failed assertion in iopen_connect_dentry (2.4 kernels only, from b1_0).
authoradilger <adilger>
Mon, 9 Feb 2004 22:29:42 +0000 (22:29 +0000)
committeradilger <adilger>
Mon, 9 Feb 2004 22:29:42 +0000 (22:29 +0000)
b=1792, b=2517

20 files changed:
lustre/ChangeLog
lustre/kernel_patches/patches/ext3-noread-2.4.20.patch
lustre/kernel_patches/patches/ext3-noread-2.4.21-chaos.patch
lustre/kernel_patches/patches/ext3-noread-2.4.21-suse2.patch
lustre/kernel_patches/patches/iopen-2.4.18-2.patch
lustre/kernel_patches/patches/iopen-2.4.18.patch
lustre/kernel_patches/patches/iopen-2.4.19-suse.patch
lustre/kernel_patches/patches/iopen-2.4.20.patch
lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch
lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch
lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch
lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch
lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch
lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch
lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch
lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch
lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch
lustre/kernel_patches/patches/vfs_intent_2.6.0-test1.patch
lustre/kernel_patches/patches/vfs_intent_2.6.0-test6.patch
lustre/kernel_patches/patches/vfs_intent_2.6.0.patch

index 021e734..8999bec 100644 (file)
@@ -1,16 +1,22 @@
 tbd         Cluster File Systems, Inc. <info@clusterfs.com>
        * version 1.2.0
        * bug fixes
-       - reduce journal credits needed for BRW writes (2370)
-       - orphan handling to avoid losing space on client/server crashes
-       - ptlrpcd can be blocked, stopping ALL progress (2477)
-       - recovery for initial connections (2355)
-       - orphan recovery problems in b_eq (1934)
-       - block all file creations until orphan recovery completes (1901)
-       - client remove rq_connection from request struct (2423)
-       - conf-sanity test_5, proper cleanup in umount log not availale (2640)
-       - recovery timer race (2670)
-       - mdc_close recovey bug (2532)
+       - reduce journal credits needed for BRW writes (2370)
+       - orphan handling to avoid losing space on client/server crashes
+       - ptlrpcd can be blocked, stopping ALL progress (2477)
+       - recovery for initial connections (2355)
+       - orphan recovery problems in b_eq (1934)
+       - block all file creations until orphan recovery completes (1901)
+       - client remove rq_connection from request struct (2423)
+       - conf-sanity test_5, proper cleanup in umount log not availale (2640)
+       - recovery timer race (2670)
+       - mdc_close recovey bug (2532)
+
+2004-02-06  Cluster File Systems, Inc. <info@clusterfs.com>
+       * version 1.0.4
+       * kernel patches
+       - fix for failed assertion in iopen_connect_dentry (1792,2517)
+
 
 2004-01-27  Cluster File Systems, Inc. <info@clusterfs.com>
        * version 1.0.3
index b14b869..f8270b2 100644 (file)
        inode->u.ext3_i.i_state = EXT3_STATE_NEW;
 -      err = ext3_mark_inode_dirty(handle, inode);
 -      if (err) goto fail;
-+      err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+      if (err) goto fail;
-+      BUFFER_TRACE(iloc->bh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, iloc.bh);
-+      if (err) {
-+              brelse(iloc.bh);
-+              iloc.bh = NULL;
-+              goto fail;
-+      }
-+      err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+      if (err) goto fail;
-+ 
++      err = ext3_get_inode_loc_new(inode, &iloc, 1);
++      if (err) goto fail;
++      BUFFER_TRACE(iloc->bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, iloc.bh);
++      if (err) {
++              brelse(iloc.bh);
++              iloc.bh = NULL;
++              goto fail;
++      }
++      err = ext3_mark_iloc_dirty(handle, inode, &iloc);
++      if (err) goto fail;
++
 +
        
        unlock_super (sb);
 -
 -int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
 +#define NUM_INODE_PREREAD     16
-+  
++
 +/*
-+  * ext3_get_inode_loc returns with an extra refcount against the inode's
-+  * underlying buffer_head on success.  If this is for a new inode allocation
-+  * (new is non-zero) then we may be able to optimize away the read if there
-+  * are no other in-use inodes in this inode table block.  If we need to do
-+  * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+  * if we are doing lots of creates/updates.
-+  */
++ * ext3_get_inode_loc returns with an extra refcount against the inode's
++ * underlying buffer_head on success.  If this is for a new inode allocation
++ * (new is non-zero) then we may be able to optimize away the read if there
++ * are no other in-use inodes in this inode table block.  If we need to do
++ * a read, then read in a whole chunk of blocks to avoid blocking again soon
++ * if we are doing lots of creates/updates.
++ */
 +int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
  {
 -      struct buffer_head *bh = 0;
-+      struct buffer_head *bh[NUM_INODE_PREREAD];
++      struct buffer_head *bh[NUM_INODE_PREREAD];
        unsigned long block;
        unsigned long block_group;
        unsigned long group_desc;
        }
  
 -      gdp = (struct ext3_group_desc *) bh->b_data;
-+      gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
++      gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
        /*
         * Figure out the offset within the block group inode table
         */
 -              goto bad_inode;
 -      }
 -      offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+              (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
++              (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
  
 -      iloc->bh = bh;
 -      iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+      bh[0] = sb_getblk(inode->i_sb, block);
-+      if (buffer_uptodate(bh[0]))
-+              goto done;
-+ 
-+      /* If we don't really need to read this block, and it isn't already
-+       * in memory, then we just zero it out.  Otherwise, we keep the
-+       * current block contents (deleted inode data) for posterity.
-+       */
-+      if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+              lock_buffer(bh[0]);
-+              memset(bh[0]->b_data, 0, bh[0]->b_size);
-+              mark_buffer_uptodate(bh[0], 1);
-+              unlock_buffer(bh[0]);
-+      } else {
-+              unsigned long block_end, itable_end;
-+              int count = 1;
-+ 
-+              itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+                              inode->i_sb->u.ext3_sb.s_itb_per_group;
-+              block_end = block + NUM_INODE_PREREAD;
-+              if (block_end > itable_end)
-+                      block_end = itable_end;
-+
-+              for (++block; block < block_end; block++) {
-+                      bh[count] = sb_getblk(inode->i_sb, block);
-+                      if (count && (buffer_uptodate(bh[count]) ||
-+                                    buffer_locked(bh[count]))) {
-+                              __brelse(bh[count]);
-+                      } else
-+                              count++;
-+              }
-+ 
-+              ll_rw_block(READ, count, bh);
-+ 
-+              /* Release all but the block we actually need (bh[0]) */
-+              while (--count > 0)
-+                      __brelse(bh[count]);
-+ 
-+              wait_on_buffer(bh[0]);
-+              if (!buffer_uptodate(bh[0])) {
-+                      ext3_error(inode->i_sb, __FUNCTION__,
-+                                 "unable to read inode block - "
-+                                 "inode=%lu, block=%lu", inode->i_ino,
-+                                 bh[0]->b_blocknr);
-+                      goto bad_inode;
-+              }
-+      }
-+  done:
-+      offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+  
-+      iloc->bh = bh[0];
-+      iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
++      bh[0] = sb_getblk(inode->i_sb, block);
++      if (buffer_uptodate(bh[0]))
++              goto done;
++
++      /* If we don't really need to read this block, and it isn't already
++       * in memory, then we just zero it out.  Otherwise, we keep the
++       * current block contents (deleted inode data) for posterity.
++       */
++      if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
++              lock_buffer(bh[0]);
++              memset(bh[0]->b_data, 0, bh[0]->b_size);
++              mark_buffer_uptodate(bh[0], 1);
++              unlock_buffer(bh[0]);
++      } else {
++              unsigned long block_end, itable_end;
++              int count = 1;
++
++              itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
++                              inode->i_sb->u.ext3_sb.s_itb_per_group;
++              block_end = block + NUM_INODE_PREREAD;
++              if (block_end > itable_end)
++                      block_end = itable_end;
++
++              for (++block; block < block_end; block++) {
++                      bh[count] = sb_getblk(inode->i_sb, block);
++                      if (count && (buffer_uptodate(bh[count]) ||
++                                    buffer_locked(bh[count]))) {
++                              __brelse(bh[count]);
++                      } else
++                              count++;
++              }
++
++              ll_rw_block(READ, count, bh);
++
++              /* Release all but the block we actually need (bh[0]) */
++              while (--count > 0)
++                      __brelse(bh[count]);
++
++              wait_on_buffer(bh[0]);
++              if (!buffer_uptodate(bh[0])) {
++                      ext3_error(inode->i_sb, __FUNCTION__,
++                                 "unable to read inode block - "
++                                 "inode=%lu, block=%lu", inode->i_ino,
++                                 bh[0]->b_blocknr);
++                      goto bad_inode;
++              }
++      }
++done:
++      offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
++
++      iloc->bh = bh[0];
++      iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
        iloc->block_group = block_group;
        
        return 0;
  
 +int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
 +{
-+      return ext3_get_inode_loc_new(inode, iloc, 0);
++      return ext3_get_inode_loc_new(inode, iloc, 0);
 +}
-+ 
++
  void ext3_read_inode(struct inode * inode)
  {
        struct ext3_iloc iloc;
index 55d1537..1903baa 100644 (file)
@@ -59,17 +59,17 @@ Index: linux-2.4.21-chaos/fs/ext3/ialloc.c
        ei->i_state = EXT3_STATE_NEW;
 -      err = ext3_mark_inode_dirty(handle, inode);
 -      if (err) goto fail;
-+      err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+      if (err) goto fail;
-+      BUFFER_TRACE(iloc->bh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, iloc.bh);
-+      if (err) {
-+              brelse(iloc.bh);
-+              iloc.bh = NULL;
-+              goto fail;
-+      }
-+      err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+      if (err) goto fail;
++      err = ext3_get_inode_loc_new(inode, &iloc, 1);
++      if (err) goto fail;
++      BUFFER_TRACE(iloc->bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, iloc.bh);
++      if (err) {
++              brelse(iloc.bh);
++              iloc.bh = NULL;
++              goto fail;
++      }
++      err = ext3_mark_iloc_dirty(handle, inode, &iloc);
++      if (err) goto fail;
 + 
 +
  
@@ -90,21 +90,21 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
 -
 -int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
 +#define NUM_INODE_PREREAD     16
-+  
++
 +/*
-+  * ext3_get_inode_loc returns with an extra refcount against the inode's
-+  * underlying buffer_head on success.  If this is for a new inode allocation
-+  * (new is non-zero) then we may be able to optimize away the read if there
-+  * are no other in-use inodes in this inode table block.  If we need to do
-+  * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+  * if we are doing lots of creates/updates.
-+  */
++ * ext3_get_inode_loc returns with an extra refcount against the inode's
++ * underlying buffer_head on success.  If this is for a new inode allocation
++ * (new is non-zero) then we may be able to optimize away the read if there
++ * are no other in-use inodes in this inode table block.  If we need to do
++ * a read, then read in a whole chunk of blocks to avoid blocking again soon
++ * if we are doing lots of creates/updates.
++ */
 +int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
  {
        struct super_block *sb = inode->i_sb;
        struct ext3_sb_info *sbi = EXT3_SB(sb);
 -      struct buffer_head *bh = 0;
-+      struct buffer_head *bh[NUM_INODE_PREREAD];
++      struct buffer_head *bh[NUM_INODE_PREREAD];
        unsigned long block;
        unsigned long block_group;
        unsigned long group_desc;
@@ -120,7 +120,7 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
        }
  
 -      gdp = (struct ext3_group_desc *) bh->b_data;
-+      gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data);
++      gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data);
        /*
         * Figure out the offset within the block group inode table
         */
@@ -137,62 +137,62 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
 -              goto bad_inode;
 -      }
 -      offset &= (EXT3_BLOCK_SIZE(sb) - 1);
-+              (offset * EXT3_INODE_SIZE(sb) >> EXT3_BLOCK_SIZE_BITS(sb));
++              (offset * EXT3_INODE_SIZE(sb) >> EXT3_BLOCK_SIZE_BITS(sb));
  
 -      iloc->bh = bh;
 -      iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+      bh[0] = sb_getblk(inode->i_sb, block);
-+      if (buffer_uptodate(bh[0]))
-+              goto done;
++      bh[0] = sb_getblk(inode->i_sb, block);
++      if (buffer_uptodate(bh[0]))
++              goto done;
 + 
-+      /* If we don't really need to read this block, and it isn't already
-+       * in memory, then we just zero it out.  Otherwise, we keep the
-+       * current block contents (deleted inode data) for posterity.
-+       */
-+      if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+              lock_buffer(bh[0]);
-+              memset(bh[0]->b_data, 0, bh[0]->b_size);
-+              mark_buffer_uptodate(bh[0], 1);
-+              unlock_buffer(bh[0]);
-+      } else {
-+              unsigned long block_end, itable_end;
-+              int count = 1;
++      /* If we don't really need to read this block, and it isn't already
++       * in memory, then we just zero it out.  Otherwise, we keep the
++       * current block contents (deleted inode data) for posterity.
++       */
++      if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
++              lock_buffer(bh[0]);
++              memset(bh[0]->b_data, 0, bh[0]->b_size);
++              mark_buffer_uptodate(bh[0], 1);
++              unlock_buffer(bh[0]);
++      } else {
++              unsigned long block_end, itable_end;
++              int count = 1;
 + 
-+              itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+                              inode->i_sb->u.ext3_sb.s_itb_per_group;
-+              block_end = block + NUM_INODE_PREREAD;
-+              if (block_end > itable_end)
-+                      block_end = itable_end;
++              itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
++                              inode->i_sb->u.ext3_sb.s_itb_per_group;
++              block_end = block + NUM_INODE_PREREAD;
++              if (block_end > itable_end)
++                      block_end = itable_end;
 +
-+              for (++block; block < block_end; block++) {
-+                      bh[count] = sb_getblk(inode->i_sb, block);
-+                      if (count && (buffer_uptodate(bh[count]) ||
-+                                    buffer_locked(bh[count]))) {
-+                              __brelse(bh[count]);
-+                      } else
-+                              count++;
-+              }
++              for (++block; block < block_end; block++) {
++                      bh[count] = sb_getblk(inode->i_sb, block);
++                      if (count && (buffer_uptodate(bh[count]) ||
++                                    buffer_locked(bh[count]))) {
++                              __brelse(bh[count]);
++                      } else
++                              count++;
++              }
 + 
-+              ll_rw_block(READ, count, bh);
++              ll_rw_block(READ, count, bh);
 + 
-+              /* Release all but the block we actually need (bh[0]) */
-+              while (--count > 0)
-+                      __brelse(bh[count]);
++              /* Release all but the block we actually need (bh[0]) */
++              while (--count > 0)
++                      __brelse(bh[count]);
 + 
-+              wait_on_buffer(bh[0]);
-+              if (!buffer_uptodate(bh[0])) {
-+                      ext3_error(inode->i_sb, __FUNCTION__,
-+                                 "unable to read inode block - "
-+                                 "inode=%lu, block=%lu", inode->i_ino,
-+                                 bh[0]->b_blocknr);
-+                      goto bad_inode;
-+              }
-+      }
-+  done:
-+      offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+  
-+      iloc->bh = bh[0];
-+      iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
++              wait_on_buffer(bh[0]);
++              if (!buffer_uptodate(bh[0])) {
++                      ext3_error(inode->i_sb, __FUNCTION__,
++                                 "unable to read inode block - "
++                                 "inode=%lu, block=%lu", inode->i_ino,
++                                 bh[0]->b_blocknr);
++                      goto bad_inode;
++              }
++      }
++ done:
++      offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
++
++      iloc->bh = bh[0];
++      iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
        iloc->block_group = block_group;
        
        return 0;
@@ -202,7 +202,7 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
  
 +int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
 +{
-+      return ext3_get_inode_loc_new(inode, iloc, 0);
++      return ext3_get_inode_loc_new(inode, iloc, 0);
 +}
 + 
  void ext3_read_inode(struct inode * inode)
index b4b5048..66274d8 100644 (file)
        inode->u.ext3_i.i_state = EXT3_STATE_NEW;
 -      err = ext3_mark_inode_dirty(handle, inode);
 -      if (err) goto fail;
-+      err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+      if (err) goto fail;
-+      BUFFER_TRACE(iloc->bh, "get_write_access");
-+      err = ext3_journal_get_write_access(handle, iloc.bh);
-+      if (err) {
-+              brelse(iloc.bh);
-+              iloc.bh = NULL;
-+              goto fail;
-+      }
-+      err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+      if (err) goto fail;
++      err = ext3_get_inode_loc_new(inode, &iloc, 1);
++      if (err) goto fail;
++      BUFFER_TRACE(iloc->bh, "get_write_access");
++      err = ext3_journal_get_write_access(handle, iloc.bh);
++      if (err) {
++              brelse(iloc.bh);
++              iloc.bh = NULL;
++              goto fail;
++      }
++      err = ext3_mark_iloc_dirty(handle, inode, &iloc);
++      if (err) goto fail;
 + 
 +
  
 -
 -int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
 +#define NUM_INODE_PREREAD     16
-+  
++
 +/*
-+  * ext3_get_inode_loc returns with an extra refcount against the inode's
-+  * underlying buffer_head on success.  If this is for a new inode allocation
-+  * (new is non-zero) then we may be able to optimize away the read if there
-+  * are no other in-use inodes in this inode table block.  If we need to do
-+  * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+  * if we are doing lots of creates/updates.
-+  */
++ * ext3_get_inode_loc returns with an extra refcount against the inode's
++ * underlying buffer_head on success.  If this is for a new inode allocation
++ * (new is non-zero) then we may be able to optimize away the read if there
++ * are no other in-use inodes in this inode table block.  If we need to do
++ * a read, then read in a whole chunk of blocks to avoid blocking again soon
++ * if we are doing lots of creates/updates.
++ */
 +int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
  {
 -      struct buffer_head *bh = 0;
-+      struct buffer_head *bh[NUM_INODE_PREREAD];
++      struct buffer_head *bh[NUM_INODE_PREREAD];
        unsigned long block;
        unsigned long block_group;
        unsigned long group_desc;
        }
  
 -      gdp = (struct ext3_group_desc *) bh->b_data;
-+      gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
++      gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
        /*
         * Figure out the offset within the block group inode table
         */
 -              goto bad_inode;
 -      }
 -      offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+              (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
++              (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
  
 -      iloc->bh = bh;
 -      iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+      bh[0] = sb_getblk(inode->i_sb, block);
-+      if (buffer_uptodate(bh[0]))
-+              goto done;
++      bh[0] = sb_getblk(inode->i_sb, block);
++      if (buffer_uptodate(bh[0]))
++              goto done;
 + 
-+      /* If we don't really need to read this block, and it isn't already
-+       * in memory, then we just zero it out.  Otherwise, we keep the
-+       * current block contents (deleted inode data) for posterity.
-+       */
-+      if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+              lock_buffer(bh[0]);
-+              memset(bh[0]->b_data, 0, bh[0]->b_size);
-+              mark_buffer_uptodate(bh[0], 1);
-+              unlock_buffer(bh[0]);
-+      } else {
-+              unsigned long block_end, itable_end;
-+              int count = 1;
++      /* If we don't really need to read this block, and it isn't already
++       * in memory, then we just zero it out.  Otherwise, we keep the
++       * current block contents (deleted inode data) for posterity.
++       */
++      if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
++              lock_buffer(bh[0]);
++              memset(bh[0]->b_data, 0, bh[0]->b_size);
++              mark_buffer_uptodate(bh[0], 1);
++              unlock_buffer(bh[0]);
++      } else {
++              unsigned long block_end, itable_end;
++              int count = 1;
 + 
-+              itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+                              inode->i_sb->u.ext3_sb.s_itb_per_group;
-+              block_end = block + NUM_INODE_PREREAD;
-+              if (block_end > itable_end)
-+                      block_end = itable_end;
++              itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
++                              inode->i_sb->u.ext3_sb.s_itb_per_group;
++              block_end = block + NUM_INODE_PREREAD;
++              if (block_end > itable_end)
++                      block_end = itable_end;
 +
-+              for (++block; block < block_end; block++) {
-+                      bh[count] = sb_getblk(inode->i_sb, block);
-+                      if (count && (buffer_uptodate(bh[count]) ||
-+                                    buffer_locked(bh[count]))) {
-+                              __brelse(bh[count]);
-+                      } else
-+                              count++;
-+              }
++              for (++block; block < block_end; block++) {
++                      bh[count] = sb_getblk(inode->i_sb, block);
++                      if (count && (buffer_uptodate(bh[count]) ||
++                                    buffer_locked(bh[count]))) {
++                              __brelse(bh[count]);
++                      } else
++                              count++;
++              }
 + 
-+              ll_rw_block(READ, count, bh);
++              ll_rw_block(READ, count, bh);
 + 
-+              /* Release all but the block we actually need (bh[0]) */
-+              while (--count > 0)
-+                      __brelse(bh[count]);
++              /* Release all but the block we actually need (bh[0]) */
++              while (--count > 0)
++                      __brelse(bh[count]);
 + 
-+              wait_on_buffer(bh[0]);
-+              if (!buffer_uptodate(bh[0])) {
-+                      ext3_error(inode->i_sb, __FUNCTION__,
-+                                 "unable to read inode block - "
-+                                 "inode=%lu, block=%lu", inode->i_ino,
-+                                 bh[0]->b_blocknr);
-+                      goto bad_inode;
-+              }
-+      }
-+  done:
-+      offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+  
-+      iloc->bh = bh[0];
-+      iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
++              wait_on_buffer(bh[0]);
++              if (!buffer_uptodate(bh[0])) {
++                      ext3_error(inode->i_sb, __FUNCTION__,
++                                 "unable to read inode block - "
++                                 "inode=%lu, block=%lu", inode->i_ino,
++                                 bh[0]->b_blocknr);
++                      goto bad_inode;
++              }
++      }
++ done:
++      offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
++
++      iloc->bh = bh[0];
++      iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
        iloc->block_group = block_group;
        
        return 0;
  
 +int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
 +{
-+      return ext3_get_inode_loc_new(inode, iloc, 0);
++      return ext3_get_inode_loc_new(inode, iloc, 0);
 +}
 + 
  void ext3_read_inode(struct inode * inode)
index c971a83..8215730 100644 (file)
@@ -14,7 +14,7 @@
  
  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;
 --- /dev/null  2003-01-30 03:24:37.000000000 -0700
 +++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c   2003-07-09 17:13:02.000000000 -0600
-@@ -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.
 + *
 +      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_del(&goal->d_hash);
-+      list_add(&goal->d_hash, &de->d_hash);
++      list_del_init(&goal->d_hash);
 +
 +      list_del(&goal->d_child);
 +      list_del(&de->d_child);
 +      /* 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);
++      __d_rehash(goal, 0);
 +
 +      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;
 +}
 --- /dev/null  2003-01-30 03:24:37.000000000 -0700
 +++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h   2003-07-09 17:13:02.000000000 -0600
-@@ -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);
 --- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-2.4.18    2003-07-09 13:32:38.000000000 -0600
 +++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c   2003-07-09 17:13:02.000000000 -0600
 @@ -34,6 +34,7 @@
  
  /*
   * define how far ahead to read directories while searching them.
-@@ -703,16 +704,21 @@ cleanup_and_exit:
-       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)
- {
+@@ -709,10 +710,14 @@ cleanup_and_exit:
        struct inode * inode;
        struct ext3_dir_entry_2 * de;
        struct buffer_head * bh;
        bh = ext3_find_entry(dentry, &de);
        inode = NULL;
        if (bh) {
-@@ -723,6 +729,12 @@ static struct dentry *ext3_lookup(struct
+@@ -723,7 +729,28 @@ static struct dentry *ext3_lookup(struct
                if (!inode)
                        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;
  }
 --- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-2.4.18    2003-07-09 13:32:38.000000000 -0600
 +++ linux-2.4.18-p4smp-braam/fs/ext3/super.c   2003-07-09 17:13:02.000000000 -0600
-@@ -831,6 +831,17 @@ static int parse_options (char * options
+@@ -831,6 +831,18 @@ static int parse_options (char * options
                         || !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);
 +              }
index 7fc40f7..202ebc6 100644 (file)
@@ -14,7 +14,7 @@
  
  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;
 --- /dev/null  2003-01-30 03:24:37.000000000 -0700
 +++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.c   2003-07-09 17:13:02.000000000 -0600
-@@ -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.
 + *
 +      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;
 +}
 --- /dev/null  2003-01-30 03:24:37.000000000 -0700
 +++ linux-2.4.18-p4smp-braam/fs/ext3/iopen.h   2003-07-09 17:13:02.000000000 -0600
-@@ -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);
 --- linux-2.4.18-p4smp/fs/ext3/namei.c~iopen-2.4.18    2003-07-09 13:32:38.000000000 -0600
 +++ linux-2.4.18-p4smp-braam/fs/ext3/namei.c   2003-07-09 17:13:02.000000000 -0600
 @@ -34,6 +34,7 @@
  
  /*
   * define how far ahead to read directories while searching them.
-@@ -703,16 +704,21 @@ cleanup_and_exit:
-               brelse (bh_use[ra_ptr]);
-       return ret;
- }
-+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode);
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
+@@ -703,10 +704,14 @@ cleanup_and_exit:
        struct inode * inode;
        struct ext3_dir_entry_2 * de;
        struct buffer_head * bh;
        bh = ext3_find_entry(dentry, &de);
        inode = NULL;
        if (bh) {
-@@ -723,6 +729,12 @@ static struct dentry *ext3_lookup(struct
+@@ -723,7 +729,28 @@ static struct dentry *ext3_lookup(struct
                if (!inode)
                        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;
  }
 --- linux-2.4.18-p4smp/fs/ext3/super.c~iopen-2.4.18    2003-07-09 13:32:38.000000000 -0600
 +++ linux-2.4.18-p4smp-braam/fs/ext3/super.c   2003-07-09 17:13:02.000000000 -0600
-@@ -831,6 +831,17 @@ static int parse_options (char * options
+@@ -831,6 +831,18 @@ static int parse_options (char * options
                         || !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);
 +              }
index ab267bb..ad213c9 100644 (file)
@@ -16,7 +16,7 @@ Index: linux-2.4.19.SuSE/Documentation/filesystems/ext2.txt
  
  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
@@ -66,7 +66,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/inode.c
        
 +      if (ext3_iopen_get_inode(inode))
 +              return;
-+      
++
        if(ext3_get_inode_loc(inode, &iloc))
                goto bad_inode;
        bh = iloc.bh;
@@ -74,17 +74,17 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 ===================================================================
 --- 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
@@ -130,7 +130,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +      struct list_head *lp;
 +      struct dentry *alternate;
 +      char buf[IOPEN_NAME_LEN];
-+      
++
 +      if (dentry->d_name.len >= IOPEN_NAME_LEN)
 +              return ERR_PTR(-ENAMETOOLONG);
 +
@@ -159,6 +159,9 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +              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) {
@@ -167,7 +170,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +      }
 +
 +      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;
@@ -176,9 +179,14 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +              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;
 +}
 +
@@ -190,7 +198,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +{
 +      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)
@@ -203,6 +211,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +
 +/* 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)
 +{
@@ -210,13 +219,6 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +      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) {
@@ -228,10 +230,8 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +              }
 +      }
 +
-+      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;
@@ -250,7 +250,6 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +      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;
 +}
@@ -294,7 +293,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +
 +      inode = iget(dir->i_sb, EXT3_BAD_INO);
 +
-+      if (!inode) 
++      if (!inode)
 +              return 0;
 +      d_add(dentry, inode);
 +      return 1;
@@ -323,7 +322,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.c
 +      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;
@@ -338,20 +337,22 @@ Index: linux-2.4.19.SuSE/fs/ext3/iopen.h
 ===================================================================
 --- 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
@@ -365,14 +366,7 @@ Index: linux-2.4.19.SuSE/fs/ext3/namei.c
  
  /*
   * 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;
@@ -387,31 +381,49 @@ Index: linux-2.4.19.SuSE/fs/ext3/namei.c
        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);
 +              }
index dcf2fc0..8800e1f 100644 (file)
@@ -8,13 +8,15 @@
  include/linux/ext3_fs.h            |    2 
  8 files changed, 318 insertions(+), 2 deletions(-)
 
---- linux/Documentation/filesystems/ext2.txt~iopen-2.4.20      Wed Jul 11 15:44:45 2001
-+++ linux-mmonroe/Documentation/filesystems/ext2.txt   Thu Jul 10 12:28:54 2003
-@@ -35,6 +35,22 @@ resgid=n                    The group ID which may use th
+Index: linux-2.4.22-uml/Documentation/filesystems/ext2.txt
+===================================================================
+--- linux-2.4.22-uml.orig/Documentation/filesystems/ext2.txt   2001-07-11 16:44:45.000000000 -0600
++++ linux-2.4.22-uml/Documentation/filesystems/ext2.txt        2004-01-30 14:18:10.000000000 -0700
+@@ -35,6 +35,22 @@
  
  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
  grpquota,noquota,quota,usrquota       Quota options are silently ignored by ext2.
  
  
---- linux/fs/ext3/Makefile~iopen-2.4.20        Thu Jul 10 12:28:44 2003
-+++ linux-mmonroe/fs/ext3/Makefile     Thu Jul 10 12:28:54 2003
-@@ -11,7 +11,7 @@ O_TARGET := ext3.o
+Index: linux-2.4.22-uml/fs/ext3/Makefile
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/Makefile     2004-01-30 14:17:58.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/Makefile  2004-01-30 14:18:10.000000000 -0700
+@@ -11,7 +11,7 @@
  
  export-objs := ext3-exports.o
  
                ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
  obj-m    := $(O_TARGET)
  
---- linux/fs/ext3/inode.c~iopen-2.4.20 Thu Jul 10 12:28:46 2003
-+++ linux-mmonroe/fs/ext3/inode.c      Thu Jul 10 12:28:54 2003
+Index: linux-2.4.22-uml/fs/ext3/inode.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/inode.c      2004-01-30 14:17:59.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/inode.c   2004-01-30 14:18:10.000000000 -0700
 @@ -31,6 +31,7 @@
  #include <linux/highuid.h>
  #include <linux/quotaops.h>
  
  /*
   * SEARCH_FROM_ZERO forces each block allocation to search from the start
-@@ -2253,6 +2254,9 @@ void ext3_read_inode(struct inode * inod
+@@ -2153,6 +2154,9 @@
        struct buffer_head *bh;
        int block;
        
 +      if (ext3_iopen_get_inode(inode))
 +              return;
-+      
++
        if(ext3_get_inode_loc(inode, &iloc))
                goto bad_inode;
        bh = iloc.bh;
---- /dev/null  Tue Jan 28 04:00:01 2003
-+++ linux-mmonroe/fs/ext3/iopen.c      Thu Jul 10 12:28:54 2003
-@@ -0,0 +1,259 @@
+Index: linux-2.4.22-uml/fs/ext3/iopen.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/iopen.c      2004-01-30 14:18:10.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/iopen.c   2004-01-30 14:18:10.000000000 -0700
+@@ -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;
 +
 +      return 1;
 +}
---- /dev/null  Tue Jan 28 04:00:01 2003
-+++ linux-mmonroe/fs/ext3/iopen.h      Thu Jul 10 12:28:54 2003
-@@ -0,0 +1,13 @@
+Index: linux-2.4.22-uml/fs/ext3/iopen.h
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/iopen.h      2004-01-30 14:18:10.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/iopen.h   2004-01-30 14:18:10.000000000 -0700
+@@ -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);
---- linux/fs/ext3/namei.c~iopen-2.4.20 Thu Jul 10 12:28:46 2003
-+++ linux-mmonroe/fs/ext3/namei.c      Thu Jul 10 12:28:54 2003
++extern struct dentry *iopen_connect_dentry(struct dentry *de,
++                                         struct inode *inode);
+Index: linux-2.4.22-uml/fs/ext3/namei.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/namei.c      2004-01-30 14:17:59.000000000 -0700
++++ linux-2.4.22-uml/fs/ext3/namei.c   2004-01-30 14:19:44.000000000 -0700
 @@ -35,7 +35,7 @@
  #include <linux/string.h>
  #include <linux/locks.h>
  
  /*
   * define how far ahead to read directories while searching them.
-@@ -921,16 +921,21 @@ errout:
-       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)
- {
+@@ -927,10 +927,14 @@
        struct inode * inode;
        struct ext3_dir_entry_2 * de;
        struct buffer_head * bh;
        bh = ext3_find_entry(dentry, &de);
        inode = NULL;
        if (bh) {
-@@ -942,6 +947,12 @@ static struct dentry *ext3_lookup(struct
+@@ -942,7 +946,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;
  }
---- linux/fs/ext3/super.c~iopen-2.4.20 Thu Jul 10 12:28:45 2003
-+++ linux-mmonroe/fs/ext3/super.c      Thu Jul 10 12:28:54 2003
-@@ -835,6 +835,17 @@ static int parse_options (char * options
+Index: linux-2.4.22-uml/fs/ext3/super.c
+===================================================================
+--- linux-2.4.22-uml.orig/fs/ext3/super.c      Sun Nov 16 01:19:22 2003
++++ linux-2.4.22-uml/fs/ext3/super.c   Sun Nov 16 01:27:31 2003
+@@ -839,6 +839,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);
 +              }
                else if (!strcmp (this_char, "journal")) {
                        /* @@@ FIXME */
                        /* Eventually we will want to be able to create
---- linux/include/linux/ext3_fs.h~iopen-2.4.20 Thu Jul 10 12:28:46 2003
-+++ linux-mmonroe/include/linux/ext3_fs.h      Thu Jul 10 12:30:12 2003
-@@ -322,6 +322,8 @@ struct ext3_inode {
+Index: linux-2.4.22-uml/include/linux/ext3_fs.h
+===================================================================
+--- linux-2.4.22-uml.orig/include/linux/ext3_fs.h      2004-01-30 14:17:59.000000000 -0700
++++ linux-2.4.22-uml/include/linux/ext3_fs.h   2004-01-30 14:18:10.000000000 -0700
+@@ -322,6 +322,8 @@
  #define EXT3_MOUNT_UPDATE_JOURNAL     0x1000  /* Update the journal format */
  #define EXT3_MOUNT_NO_UID32           0x2000  /* Disable 32-bit UIDs */
  #define EXT3_MOUNT_XATTR_USER         0x4000  /* Extended user attributes */
  #define EXT3_MOUNT_ASYNCDEL           0x20000 /* Delayed deletion */
  
  /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
-
-_
index 74d1d85..16bde95 100644 (file)
@@ -16,7 +16,7 @@ Index: linux-2.4.21-chaos/Documentation/filesystems/ext2.txt
  
  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
@@ -66,7 +66,7 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c
        
 +      if (ext3_iopen_get_inode(inode))
 +              return;
-+      
++
        if(ext3_get_inode_loc(inode, &iloc))
                goto bad_inode;
        bh = iloc.bh;
@@ -74,17 +74,17 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/iopen.c    2003-01-30 13:24:37.000000000 +0300
 +++ linux-2.4.21-chaos/fs/ext3/iopen.c 2003-12-12 16:19:05.000000000 +0300
-@@ -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
@@ -130,7 +130,7 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +      struct list_head *lp;
 +      struct dentry *alternate;
 +      char buf[IOPEN_NAME_LEN];
-+      
++
 +      if (dentry->d_name.len >= IOPEN_NAME_LEN)
 +              return ERR_PTR(-ENAMETOOLONG);
 +
@@ -159,6 +159,9 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +              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) {
@@ -167,7 +170,7 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +      }
 +
 +      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;
@@ -176,9 +179,14 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +              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;
 +}
 +
@@ -190,7 +198,7 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +{
 +      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)
@@ -203,6 +211,7 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +
 +/* 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)
 +{
@@ -210,13 +219,6 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +      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) {
@@ -228,10 +230,8 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +              }
 +      }
 +
-+      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;
@@ -250,7 +250,6 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +      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;
 +}
@@ -294,7 +293,7 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +
 +      inode = iget(dir->i_sb, EXT3_BAD_INO);
 +
-+      if (!inode) 
++      if (!inode)
 +              return 0;
 +      d_add(dentry, inode);
 +      return 1;
@@ -323,7 +322,7 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c
 +      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;
@@ -338,20 +337,22 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.h
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/iopen.h    2003-01-30 13:24:37.000000000 +0300
 +++ linux-2.4.21-chaos/fs/ext3/iopen.h 2003-12-12 16:19:05.000000000 +0300
-@@ -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.21-chaos/fs/ext3/namei.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/namei.c    2003-12-12 16:18:59.000000000 +0300
@@ -365,14 +366,7 @@ Index: linux-2.4.21-chaos/fs/ext3/namei.c
  
  /*
   * 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;
@@ -387,31 +381,49 @@ Index: linux-2.4.21-chaos/fs/ext3/namei.c
        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.21-chaos/fs/ext3/super.c
 ===================================================================
 --- linux-2.4.21-chaos.orig/fs/ext3/super.c    2003-12-12 16:18:51.000000000 +0300
 +++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 16:19:05.000000000 +0300
-@@ -890,6 +890,17 @@
+@@ -890,6 +890,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);
 +              }
index 2efed4f..e29ae29 100644 (file)
  {
        struct dentry * result;
        struct inode *dir = parent->d_inode;
-+        int counter = 0;
++      int counter = 0;
  
 +again:
-+        counter++;
++      counter++;
        down(&dir->i_sem);
        /*
         * First re-do the cached lookup just in case it was created
 +              if (!result->d_op->d_revalidate_it(result, flags, it) &&
 +                  !d_invalidate(result)) {
 +                      dput(result);
-+                        if (counter > 10)
-+                                result = ERR_PTR(-ESTALE);
-+                        if (!IS_ERR(result))
-+                                goto again;
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
 +              }
        }
        return result;
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index 98fd550..5fbd0fc 100644 (file)
@@ -453,11 +453,11 @@ Index: linux-2.4.19-pre1/fs/namei.c
 +                                                &dentry->d_name, 0, NULL);
 +                              d_invalidate(dentry);
 +                              dput(dentry);
-+                                if (IS_ERR(new)) { 
-+                                        err = PTR_ERR(new);
-+                                        break;
-+                                }
-+                                nd->dentry = new;
++                              if (IS_ERR(new)) { 
++                                      err = PTR_ERR(new);
++                                      break;
++                              }
++                              nd->dentry = new;
 +                      }
 +              } else
 +              if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
@@ -1406,8 +1406,8 @@ Index: linux-2.4.19-pre1/fs/stat.c
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index b49babd..6b6027a 100644 (file)
@@ -436,11 +436,11 @@ Index: linux-2.4.19.SuSE/fs/namei.c
 +                                                &dentry->d_name, 0, NULL);
 +                              d_invalidate(dentry);
 +                              dput(dentry);
-+                                if (IS_ERR(new)) { 
-+                                        err = PTR_ERR(new);
-+                                        break;
-+                                }
-+                                nd->dentry = new;
++                              if (IS_ERR(new)) { 
++                                      err = PTR_ERR(new);
++                                      break;
++                              }
++                              nd->dentry = new;
 +                      }
 +              } else
                if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
@@ -1386,8 +1386,8 @@ Index: linux-2.4.19.SuSE/fs/stat.c
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index a632e00..082b8b7 100644 (file)
 +                                                &dentry->d_name, 0, NULL);
 +                              d_invalidate(dentry);
 +                              dput(dentry);
-+                                if (IS_ERR(new)) { 
-+                                        err = PTR_ERR(new);
-+                                        break;
-+                                }
-+                                nd->dentry = new;
++                              if (IS_ERR(new)) { 
++                                      err = PTR_ERR(new);
++                                      break;
++                              }
++                              nd->dentry = new;
 +                      }
 +              } else
                if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index c4c79b1..7d83b5e 100644 (file)
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index 1ceb50d..7587ad2 100644 (file)
@@ -1390,8 +1390,8 @@ Index: linux-2.4.21-chaos/fs/stat.c
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index 98c6c37..492e32a 100644 (file)
@@ -1398,8 +1398,8 @@ Index: linux-2.4.21-suse2/fs/stat.c
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index ace8619..ff5ef61 100644 (file)
  {
        struct inode * inode = dentry->d_inode;
 -      if (inode->i_op && inode->i_op->revalidate)
-+        if (!inode)
-+                return -ENOENT;
++      if (!inode)
++              return -ENOENT;
 +      if (inode->i_op && inode->i_op->revalidate_it)
 +              return inode->i_op->revalidate_it(dentry, it);
 +      else if (inode->i_op && inode->i_op->revalidate)
index 1f840e8..3d75965 100644 (file)
  {
        struct dentry * result;
        struct inode *dir = parent->d_inode;
-+        int counter = 0;
++      int counter = 0;
  
 +again:
-+        counter++;
++      counter++;
        down(&dir->i_sem);
        /*
         * First re-do the cached lookup just in case it was created
                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;
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
                }
        }
        return result;
index 5dd86e0..6742227 100644 (file)
@@ -89,10 +89,10 @@ Index: linux-2.6.0-test6/fs/namei.c
  {
        struct dentry * result;
        struct inode *dir = parent->d_inode;
-+        int counter = 0;
++      int counter = 0;
  
 +again:
-+        counter++;
++      counter++;
        down(&dir->i_sem);
        /*
         * First re-do the cached lookup just in case it was created
@@ -101,10 +101,10 @@ Index: linux-2.6.0-test6/fs/namei.c
                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;
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
                }
        }
        return result;
index 8fa267c..7514caa 100644 (file)
@@ -89,10 +89,10 @@ Index: linux-2.6.0/fs/namei.c
  {
        struct dentry * result;
        struct inode *dir = parent->d_inode;
-+        int counter = 0;
++      int counter = 0;
  
 +again:
-+        counter++;
++      counter++;
        down(&dir->i_sem);
        /*
         * First re-do the cached lookup just in case it was created
@@ -101,10 +101,10 @@ Index: linux-2.6.0/fs/namei.c
                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;
++                      if (counter > 10)
++                              result = ERR_PTR(-ESTALE);
++                      if (!IS_ERR(result))
++                              goto again;
                }
        }
        return result;