Whamcloud - gitweb
Updated to apply to "fixed" ext3 tree from RH kernel.
authoradilger <adilger>
Tue, 24 Sep 2002 06:38:36 +0000 (06:38 +0000)
committeradilger <adilger>
Tue, 24 Sep 2002 06:38:36 +0000 (06:38 +0000)
Include patch which can be applied in extN as a prelude to the other
patches, or which can be applied in the source ext3 to fix that also.

lustre/extN/Makefile.am
lustre/extN/ext3-2.4.18-fixes.diff [new file with mode: 0644]
lustre/extN/ext3-2.4.18-ino_sb_macro.diff

index 10ceb7f..3a60114 100644 (file)
@@ -8,7 +8,10 @@ MODULE = extN
 modulefs_DATA = extN.o
 EXTRA_PROGRAMS = extN
 
-EXTNP = htree-ext3-2.4.18.diff linux-2.4.18ea-0.8.26.diff
+# NOTE: if you are not using a RedHat 12.5 or later kernel, then you need to
+#       apply the following patch first, as it fixes a number of bugs in ext3.
+# EXTNP = ext3-2.4.18-fixes.diff
+EXTNP+= htree-ext3-2.4.18.diff linux-2.4.18ea-0.8.26.diff
 EXTNP+= ext3-2.4.18-ino_sb_macro.diff extN-misc-fixup.diff
 EXTNC = balloc.c bitmap.c dir.c file.c fsync.c ialloc.c inode.c ioctl.c
 EXTNC+= namei.c super.c symlink.c
diff --git a/lustre/extN/ext3-2.4.18-fixes.diff b/lustre/extN/ext3-2.4.18-fixes.diff
new file mode 100644 (file)
index 0000000..cd31486
--- /dev/null
@@ -0,0 +1,490 @@
+diff -ru lum-2.4.18-um30/fs/ext3/balloc.c uml-2.4.18-12.5/fs/ext3/balloc.c
+--- lum-2.4.18-um30/fs/ext3/balloc.c   Mon Feb 25 12:38:08 2002
++++ uml-2.4.18-12.5/fs/ext3/balloc.c   Thu Sep 19 13:40:11 2002
+@@ -276,7 +276,8 @@
+       }
+       lock_super (sb);
+       es = sb->u.ext3_sb.s_es;
+-      if (block < le32_to_cpu(es->s_first_data_block) || 
++      if (block < le32_to_cpu(es->s_first_data_block) ||
++          block + count < block ||
+           (block + count) > le32_to_cpu(es->s_blocks_count)) {
+               ext3_error (sb, "ext3_free_blocks",
+                           "Freeing blocks not in datazone - "
+@@ -309,17 +310,6 @@
+       if (!gdp)
+               goto error_return;
+-      if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
+-          in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
+-          in_range (block, le32_to_cpu(gdp->bg_inode_table),
+-                    sb->u.ext3_sb.s_itb_per_group) ||
+-          in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
+-                    sb->u.ext3_sb.s_itb_per_group))
+-              ext3_error (sb, "ext3_free_blocks",
+-                          "Freeing blocks in system zones - "
+-                          "Block = %lu, count = %lu",
+-                          block, count);
+-
+       /*
+        * We are about to start releasing blocks in the bitmap,
+        * so we need undo access.
+@@ -345,14 +335,24 @@
+       if (err)
+               goto error_return;
+-      for (i = 0; i < count; i++) {
++      for (i = 0; i < count; i++, block++) {
++              if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
++                  block == le32_to_cpu(gdp->bg_inode_bitmap) ||
++                  in_range(block, le32_to_cpu(gdp->bg_inode_table),
++                           sb->u.ext2_sb.s_itb_per_group)) {
++                      ext3_error(sb, __FUNCTION__,
++                                 "Freeing block in system zone - block = %lu",
++                                 block);
++                      continue;
++              }
++
+               /*
+                * An HJ special.  This is expensive...
+                */
+ #ifdef CONFIG_JBD_DEBUG
+               {
+                       struct buffer_head *debug_bh;
+-                      debug_bh = sb_get_hash_table(sb, block + i);
++                      debug_bh = sb_get_hash_table(sb, block);
+                       if (debug_bh) {
+                               BUFFER_TRACE(debug_bh, "Deleted!");
+                               if (!bh2jh(bitmap_bh)->b_committed_data)
+@@ -365,9 +365,8 @@
+ #endif
+               BUFFER_TRACE(bitmap_bh, "clear bit");
+               if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) {
+-                      ext3_error (sb, __FUNCTION__,
+-                                    "bit already cleared for block %lu", 
+-                                    block + i);
++                      ext3_error(sb, __FUNCTION__,
++                                 "bit already cleared for block %lu", block);
+                       BUFFER_TRACE(bitmap_bh, "bit already cleared");
+               } else {
+                       dquot_freed_blocks++;
+@@ -415,7 +417,6 @@
+       if (!err) err = ret;
+       if (overflow && !err) {
+-              block += count;
+               count = overflow;
+               goto do_more;
+       }
+@@ -542,6 +543,7 @@
+       int i, j, k, tmp, alloctmp;
+       int bitmap_nr;
+       int fatal = 0, err;
++      int performed_allocation = 0;
+       struct super_block * sb;
+       struct ext3_group_desc * gdp;
+       struct ext3_super_block * es;
+@@ -575,6 +577,7 @@
+       ext3_debug ("goal=%lu.\n", goal);
++repeat:
+       /*
+        * First, test whether the goal block is free.
+        */
+@@ -644,8 +647,7 @@
+       }
+       /* No space left on the device */
+-      unlock_super (sb);
+-      return 0;
++      goto out;
+ search_back:
+       /* 
+@@ -684,16 +686,28 @@
+       if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
+           tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
+           in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
+-                    sb->u.ext3_sb.s_itb_per_group))
+-              ext3_error (sb, "ext3_new_block",
+-                          "Allocating block in system zone - "
+-                          "block = %u", tmp);
++                    EXT3_SB(sb)->s_itb_per_group)) {
++              ext3_error(sb, __FUNCTION__,
++                         "Allocating block in system zone - block = %u", tmp);
++
++              /* Note: This will potentially use up one of the handle's
++               * buffer credits.  Normally we have way too many credits,
++               * so that is OK.  In _very_ rare cases it might not be OK.
++               * We will trigger an assertion if we run out of credits,
++               * and we will have to do a full fsck of the filesystem -
++               * better than randomly corrupting filesystem metadata.
++               */
++              ext3_set_bit(j, bh->b_data);
++              goto repeat;
++      }
++
+       /* The superblock lock should guard against anybody else beating
+        * us to this point! */
+       J_ASSERT_BH(bh, !ext3_test_bit(j, bh->b_data));
+       BUFFER_TRACE(bh, "setting bitmap bit");
+       ext3_set_bit(j, bh->b_data);
++      performed_allocation = 1;
+ #ifdef CONFIG_JBD_DEBUG
+       {
+@@ -815,6 +829,11 @@
+               ext3_std_error(sb, fatal);
+       }
+       unlock_super (sb);
++      /*
++       * Undo the block allocation
++       */
++      if (!performed_allocation)
++              DQUOT_FREE_BLOCK(inode, 1);
+       return 0;
+       
+ }
+diff -ru lum-2.4.18-um30/fs/ext3/file.c uml-2.4.18-12.5/fs/ext3/file.c
+--- lum-2.4.18-um30/fs/ext3/file.c     Thu Nov 15 14:37:55 2001
++++ uml-2.4.18-12.5/fs/ext3/file.c     Thu Sep 19 13:40:11 2002
+@@ -61,19 +61,52 @@
+ static ssize_t
+ ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+ {
++      int ret, err;
+       struct inode *inode = file->f_dentry->d_inode;
+-      /*
+-       * Nasty: if the file is subject to synchronous writes then we need
+-       * to force generic_osync_inode() to call ext3_write_inode().
+-       * We do that by marking the inode dirty.  This adds much more
+-       * computational expense than we need, but we're going to sync
+-       * anyway.
+-       */
+-      if (IS_SYNC(inode) || (file->f_flags & O_SYNC))
+-              mark_inode_dirty(inode);
++      ret = generic_file_write(file, buf, count, ppos);
+-      return generic_file_write(file, buf, count, ppos);
++      /* Skip file flushing code if there was an error, or if nothing
++         was written. */
++      if (ret <= 0)
++              return ret;
++      
++      /* If the inode is IS_SYNC, or is O_SYNC and we are doing
++           data-journaling, then we need to make sure that we force the
++           transaction to disk to keep all metadata uptodate
++           synchronously. */
++
++      if (file->f_flags & O_SYNC) {
++              /* If we are non-data-journaled, then the dirty data has
++                   already been flushed to backing store by
++                   generic_osync_inode, and the inode has been flushed
++                   too if there have been any modifications other than
++                   mere timestamp updates.
++                 
++                 Open question --- do we care about flushing
++                 timestamps too if the inode is IS_SYNC? */
++              if (!ext3_should_journal_data(inode))
++                      return ret;
++
++              goto force_commit;
++      }
++
++      /* So we know that there has been no forced data flush.  If the
++           inode is marked IS_SYNC, we need to force one ourselves. */
++      if (!IS_SYNC(inode))
++              return ret;
++      
++      /* Open question #2 --- should we force data to disk here too?
++           If we don't, the only impact is that data=writeback
++           filesystems won't flush data to disk automatically on
++           IS_SYNC, only metadata (but historically, that is what ext2
++           has done.) */
++      
++force_commit:
++      err = ext3_force_commit(inode->i_sb);
++      if (err) 
++              return err;
++      return ret;
+ }
+ struct file_operations ext3_file_operations = {
+diff -ru lum-2.4.18-um30/fs/ext3/fsync.c uml-2.4.18-12.5/fs/ext3/fsync.c
+--- lum-2.4.18-um30/fs/ext3/fsync.c    Tue Nov 20 22:34:13 2001
++++ uml-2.4.18-12.5/fs/ext3/fsync.c    Thu Sep 19 13:40:11 2002
+@@ -62,7 +62,12 @@
+        * we'll end up waiting on them in commit.
+        */
+       ret = fsync_inode_buffers(inode);
+-      ret |= fsync_inode_data_buffers(inode);
++
++      /* In writeback mode, we need to force out data buffers too.  In
++       * the other modes, ext3_force_commit takes care of forcing out
++       * just the right data blocks. */
++      if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
++              ret |= fsync_inode_data_buffers(inode);
+       ext3_force_commit(inode->i_sb);
+diff -ru lum-2.4.18-um30/fs/ext3/ialloc.c uml-2.4.18-12.5/fs/ext3/ialloc.c
+--- lum-2.4.18-um30/fs/ext3/ialloc.c   Mon Feb 25 12:38:08 2002
++++ uml-2.4.18-12.5/fs/ext3/ialloc.c   Thu Sep 19 13:40:11 2002
+@@ -392,7 +392,7 @@
+       err = -ENOSPC;
+       if (!gdp)
+-              goto fail;
++              goto out;
+       err = -EIO;
+       bitmap_nr = load_inode_bitmap (sb, i);
+@@ -523,9 +523,10 @@
+       return inode;
+ fail:
++      ext3_std_error(sb, err);
++out:
+       unlock_super(sb);
+       iput(inode);
+-      ext3_std_error(sb, err);
+       return ERR_PTR(err);
+ }
+diff -ru lum-2.4.18-um30/fs/ext3/inode.c uml-2.4.18-12.5/fs/ext3/inode.c
+--- lum-2.4.18-um30/fs/ext3/inode.c    Mon Feb 25 12:38:08 2002
++++ uml-2.4.18-12.5/fs/ext3/inode.c    Thu Sep 19 13:40:11 2002
+@@ -412,6 +412,7 @@
+       return NULL;
+ changed:
++      brelse(bh);
+       *err = -EAGAIN;
+       goto no_block;
+ failure:
+@@ -581,8 +582,6 @@
+                       
+                       parent = nr;
+               }
+-              if (IS_SYNC(inode))
+-                      handle->h_sync = 1;
+       }
+       if (n == num)
+               return 0;
+@@ -950,11 +951,13 @@
+ }
+ static int walk_page_buffers( handle_t *handle,
++                              struct inode *inode,
+                               struct buffer_head *head,
+                               unsigned from,
+                               unsigned to,
+                               int *partial,
+                               int (*fn)(      handle_t *handle,
++                                              struct inode *inode,
+                                               struct buffer_head *bh))
+ {
+       struct buffer_head *bh;
+@@ -972,7 +975,7 @@
+                               *partial = 1;
+                       continue;
+               }
+-              err = (*fn)(handle, bh);
++              err = (*fn)(handle, inode, bh);
+               if (!ret)
+                       ret = err;
+       }
+@@ -1005,7 +1008,7 @@
+  * write.  
+  */
+-static int do_journal_get_write_access(handle_t *handle, 
++static int do_journal_get_write_access(handle_t *handle, struct inode *inode,
+                                      struct buffer_head *bh)
+ {
+       return ext3_journal_get_write_access(handle, bh);
+@@ -1015,8 +1018,8 @@
+                             unsigned from, unsigned to)
+ {
+       struct inode *inode = page->mapping->host;
+-      handle_t *handle = ext3_journal_current_handle();
+       int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
++      handle_t *handle;
+       lock_kernel();
+       handle = ext3_journal_start(inode, needed_blocks);
+@@ -1031,7 +1034,7 @@
+               goto prepare_write_failed;
+       if (ext3_should_journal_data(inode)) {
+-              ret = walk_page_buffers(handle, page->buffers,
++              ret = walk_page_buffers(handle, inode, page->buffers,
+                               from, to, NULL, do_journal_get_write_access);
+               if (ret) {
+                       /*
+@@ -1052,24 +1055,32 @@
+       return ret;
+ }
+-static int journal_dirty_sync_data(handle_t *handle, struct buffer_head *bh)
++static int journal_dirty_sync_data(handle_t *handle, struct inode *inode,
++                                 struct buffer_head *bh)
+ {
+-      return ext3_journal_dirty_data(handle, bh, 0);
++      int ret = ext3_journal_dirty_data(handle, bh, 0);
++      if (bh->b_inode != inode)
++              buffer_insert_inode_data_queue(bh, inode);
++      return ret;
+ }
+ /*
+  * For ext3_writepage().  We also brelse() the buffer to account for
+  * the bget() which ext3_writepage() performs.
+  */
+-static int journal_dirty_async_data(handle_t *handle, struct buffer_head *bh)
++static int journal_dirty_async_data(handle_t *handle, struct inode *inode, 
++                                  struct buffer_head *bh)
+ {
+       int ret = ext3_journal_dirty_data(handle, bh, 1);
++      if (bh->b_inode != inode)
++              buffer_insert_inode_data_queue(bh, inode);
+       __brelse(bh);
+       return ret;
+ }
+ /* For commit_write() in data=journal mode */
+-static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
++static int commit_write_fn(handle_t *handle, struct inode *inode, 
++                         struct buffer_head *bh)
+ {
+       set_bit(BH_Uptodate, &bh->b_state);
+       return ext3_journal_dirty_metadata(handle, bh);
+@@ -1104,7 +1115,7 @@
+               int partial = 0;
+               loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+-              ret = walk_page_buffers(handle, page->buffers,
++              ret = walk_page_buffers(handle, inode, page->buffers,
+                       from, to, &partial, commit_write_fn);
+               if (!partial)
+                       SetPageUptodate(page);
+@@ -1114,7 +1125,7 @@
+               EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
+       } else {
+               if (ext3_should_order_data(inode)) {
+-                      ret = walk_page_buffers(handle, page->buffers,
++                      ret = walk_page_buffers(handle, inode, page->buffers,
+                               from, to, NULL, journal_dirty_sync_data);
+               }
+               /* Be careful here if generic_commit_write becomes a
+@@ -1196,7 +1207,8 @@
+       return generic_block_bmap(mapping,block,ext3_get_block);
+ }
+-static int bget_one(handle_t *handle, struct buffer_head *bh)
++static int bget_one(handle_t *handle, struct inode *inode, 
++                  struct buffer_head *bh)
+ {
+       atomic_inc(&bh->b_count);
+       return 0;
+@@ -1295,7 +1307,7 @@
+                       create_empty_buffers(page,
+                               inode->i_dev, inode->i_sb->s_blocksize);
+               page_buffers = page->buffers;
+-              walk_page_buffers(handle, page_buffers, 0,
++              walk_page_buffers(handle, inode, page_buffers, 0,
+                               PAGE_CACHE_SIZE, NULL, bget_one);
+       }
+@@ -1313,7 +1325,7 @@
+       /* And attach them to the current transaction */
+       if (order_data) {
+-              err = walk_page_buffers(handle, page_buffers,
++              err = walk_page_buffers(handle, inode, page_buffers,
+                       0, PAGE_CACHE_SIZE, NULL, journal_dirty_async_data);
+               if (!ret)
+                       ret = err;
+@@ -1581,8 +1593,10 @@
+               }
+               ext3_mark_inode_dirty(handle, inode);
+               ext3_journal_test_restart(handle, inode);
+-              BUFFER_TRACE(bh, "get_write_access");
+-              ext3_journal_get_write_access(handle, bh);
++              if (bh) {
++                      BUFFER_TRACE(bh, "retaking write access");
++                      ext3_journal_get_write_access(handle, bh);
++              }
+       }
+       /*
+diff -ru lum-2.4.18-um30/fs/ext3/namei.c uml-2.4.18-12.5/fs/ext3/namei.c
+--- lum-2.4.18-um30/fs/ext3/namei.c    Fri Nov  9 15:25:04 2001
++++ uml-2.4.18-12.5/fs/ext3/namei.c    Thu Sep 19 13:40:11 2002
+@@ -354,8 +355,8 @@
+                        */
+                       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+                       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
+-                      ext3_mark_inode_dirty(handle, dir);
+                       dir->i_version = ++event;
++                      ext3_mark_inode_dirty(handle, dir);
+                       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
+                       ext3_journal_dirty_metadata(handle, bh);
+                       brelse(bh);
+@@ -464,8 +465,8 @@
+               inode->i_op = &ext3_file_inode_operations;
+               inode->i_fop = &ext3_file_operations;
+               inode->i_mapping->a_ops = &ext3_aops;
+-              ext3_mark_inode_dirty(handle, inode);
+               err = ext3_add_nondir(handle, dentry, inode);
++              ext3_mark_inode_dirty(handle, inode);
+       }
+       ext3_journal_stop(handle, dir);
+       return err;
+@@ -489,8 +490,8 @@
+       err = PTR_ERR(inode);
+       if (!IS_ERR(inode)) {
+               init_special_inode(inode, mode, rdev);
+-              ext3_mark_inode_dirty(handle, inode);
+               err = ext3_add_nondir(handle, dentry, inode);
++              ext3_mark_inode_dirty(handle, inode);
+       }
+       ext3_journal_stop(handle, dir);
+       return err;
+@@ -933,8 +934,8 @@
+               inode->i_size = l-1;
+       }
+       inode->u.ext3_i.i_disksize = inode->i_size;
+-      ext3_mark_inode_dirty(handle, inode);
+       err = ext3_add_nondir(handle, dentry, inode);
++      ext3_mark_inode_dirty(handle, inode);
+ out_stop:
+       ext3_journal_stop(handle, dir);
+       return err;
+@@ -970,8 +971,8 @@
+       ext3_inc_count(handle, inode);
+       atomic_inc(&inode->i_count);
+-      ext3_mark_inode_dirty(handle, inode);
+       err = ext3_add_nondir(handle, dentry, inode);
++      ext3_mark_inode_dirty(handle, inode);
+       ext3_journal_stop(handle, dir);
+       return err;
+ }
+diff -ru lum-2.4.18-um30/fs/ext3/super.c uml-2.4.18-12.5/fs/ext3/super.c
+--- lum-2.4.18-um30/fs/ext3/super.c    Fri Jul 12 17:59:37 2002
++++ uml-2.4.18-12.5/fs/ext3/super.c    Thu Sep 19 13:40:11 2002
+@@ -1589,8 +1589,10 @@
+               journal_t *journal = EXT3_SB(sb)->s_journal;
+               /* Now we set up the journal barrier. */
++              unlock_super(sb);
+               journal_lock_updates(journal);
+               journal_flush(journal);
++              lock_super(sb);
+               /* Journal blocked and flushed, clear needs_recovery flag. */
+               EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
index 385da3f..a49d5da 100644 (file)
                return -EIO;
        
        /*
-@@ -275,8 +273,9 @@ void ext3_free_blocks (handle_t *handle,
+@@ -275,7 +273,7 @@ void ext3_free_blocks (handle_t *handle,
                return;
        }
        lock_super (sb);
 -      es = sb->u.ext3_sb.s_es;
--      if (block < le32_to_cpu(es->s_first_data_block) || 
 +      es = EXT3_SB(sb)->s_es;
-+      if (block < le32_to_cpu(es->s_first_data_block) ||
-+          block + count < block ||
+       if (block < le32_to_cpu(es->s_first_data_block) ||
+           block + count < block ||
            (block + count) > le32_to_cpu(es->s_blocks_count)) {
-               ext3_error (sb, "ext3_free_blocks",
-                           "Freeing blocks not in datazone - "
-@@ -304,22 +303,11 @@ do_more:
+@@ -304,7 +302,7 @@ do_more:
        if (bitmap_nr < 0)
                goto error_return;
        
        gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
        if (!gdp)
                goto error_return;
--      if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
--          in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
--          in_range (block, le32_to_cpu(gdp->bg_inode_table),
--                    sb->u.ext3_sb.s_itb_per_group) ||
--          in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
--                    sb->u.ext3_sb.s_itb_per_group))
--              ext3_error (sb, "ext3_free_blocks",
--                          "Freeing blocks in system zones - "
--                          "Block = %lu, count = %lu",
--                          block, count);
--
-       /*
-        * We are about to start releasing blocks in the bitmap,
-        * so we need undo access.
-@@ -340,19 +328,29 @@ do_more:
+@@ -330,8 +328,8 @@ do_more:
        if (err)
                goto error_return;
  
        if (err)
                goto error_return;
  
--      for (i = 0; i < count; i++) {
-+      for (i = 0; i < count; i++, block++) {
-+              if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-+                  block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-+                  in_range(block, le32_to_cpu(gdp->bg_inode_table),
+@@ -341,7 +339,7 @@
+               if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
+                   block == le32_to_cpu(gdp->bg_inode_bitmap) ||
+                   in_range(block, le32_to_cpu(gdp->bg_inode_table),
+-                           sb->u.ext2_sb.s_itb_per_group)) {
 +                           EXT3_SB(sb)->s_itb_per_group)) {
-+                      ext3_error(sb, __FUNCTION__,
-+                                 "Freeing block in system zone - block = %lu",
-+                                 block);
-+                      continue;
-+              }
-+
-               /*
-                * An HJ special.  This is expensive...
-                */
- #ifdef CONFIG_JBD_DEBUG
-               {
-                       struct buffer_head *debug_bh;
--                      debug_bh = sb_get_hash_table(sb, block + i);
-+                      debug_bh = sb_get_hash_table(sb, block);
-                       if (debug_bh) {
-                               BUFFER_TRACE(debug_bh, "Deleted!");
-                               if (!bh2jh(bitmap_bh)->b_committed_data)
-@@ -365,9 +363,8 @@ do_more:
- #endif
-               BUFFER_TRACE(bitmap_bh, "clear bit");
-               if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) {
--                      ext3_error (sb, __FUNCTION__,
--                                    "bit already cleared for block %lu", 
--                                    block + i);
-+                      ext3_error(sb, __FUNCTION__,
-+                                 "bit already cleared for block %lu", block);
-                       BUFFER_TRACE(bitmap_bh, "bit already cleared");
-               } else {
-                       dquot_freed_blocks++;
-@@ -410,12 +407,11 @@ do_more:
+                       ext3_error(sb, __FUNCTION__,
+                                  "Freeing block in system zone - block = %lu",
+                                  block);
+@@ -410,8 +407,8 @@ do_more:
        if (!err) err = ret;
  
        /* And the superblock */
        if (!err) err = ret;
  
        if (overflow && !err) {
--              block += count;
-               count = overflow;
-               goto do_more;
-       }
-@@ -564,17 +560,18 @@ int ext3_new_block (handle_t *handle, st
+@@ -564,12 +560,12 @@ int ext3_new_block (handle_t *handle, st
        }
  
        lock_super (sb);
             !capable(CAP_SYS_RESOURCE)))
                goto out;
  
-       ext3_debug ("goal=%lu.\n", goal);
-+repeat:
-       /*
-        * First, test whether the goal block is free.
-        */
 @@ -598,7 +595,7 @@ int ext3_new_block (handle_t *handle, st
                if (bitmap_nr < 0)
                        goto io_error;
        if (fatal) goto out;
  
        tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb)
-@@ -684,10 +681,21 @@ got_block:
-       if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
-           tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
-           in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
--                    sb->u.ext3_sb.s_itb_per_group))
--              ext3_error (sb, "ext3_new_block",
--                          "Allocating block in system zone - "
--                          "block = %u", tmp);
-+                    EXT3_SB(sb)->s_itb_per_group)) {
-+              ext3_error(sb, __FUNCTION__,
-+                         "Allocating block in system zone - block = %u", tmp);
-+
-+              /* Note: This will potentially use up one of the handle's
-+               * buffer credits.  Normally we have way too many credits,
-+               * so that is OK.  In _very_ rare cases it might not be OK.
-+               * We will trigger an assertion if we run out of credits,
-+               * and we will have to do a full fsck of the filesystem -
-+               * better than randomly corrupting filesystem metadata.
-+               */
-+              ext3_set_bit(j, bh->b_data);
-+              goto repeat;
-+      }
-+
-       /* The superblock lock should guard against anybody else beating
-        * us to this point! */
 @@ -796,7 +804,7 @@ got_block:
        if (!fatal) fatal = err;
        
                     i < EXT3_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
                     i++) {
                        /*
-@@ -1015,8 +1018,8 @@ static int ext3_prepare_write(struct fil
-                             unsigned from, unsigned to)
- {
-       struct inode *inode = page->mapping->host;
--      handle_t *handle = ext3_journal_current_handle();
-       int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
-+      handle_t *handle;
-       lock_kernel();
-       handle = ext3_journal_start(inode, needed_blocks);
 @@ -1131,8 +1134,8 @@ static int ext3_commit_write(struct file
                        kunmap(page);
                }
        }
 -      inode->u.ext3_i.i_disksize = inode->i_size;
 +      EXT3_I(inode)->i_disksize = inode->i_size;
-       ext3_mark_inode_dirty(handle, inode);
        err = ext3_add_nondir(handle, dentry, inode);
+       ext3_mark_inode_dirty(handle, inode);
  out_stop:
 --- ./fs/ext3/super.c.orig     Fri Apr 12 10:27:49 2002
 +++ ./fs/ext3/super.c  Tue May  7 16:05:44 2002