From 213202f49b828a9d39e901b8acc6445e245fe622 Mon Sep 17 00:00:00 2001 From: adilger Date: Tue, 24 Sep 2002 06:38:36 +0000 Subject: [PATCH] Updated to apply to "fixed" ext3 tree from RH kernel. 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 | 5 +- lustre/extN/ext3-2.4.18-fixes.diff | 490 ++++++++++++++++++++++++++++++ lustre/extN/ext3-2.4.18-ino_sb_macro.diff | 122 +------- 3 files changed, 510 insertions(+), 107 deletions(-) create mode 100644 lustre/extN/ext3-2.4.18-fixes.diff diff --git a/lustre/extN/Makefile.am b/lustre/extN/Makefile.am index 10ceb7f..3a60114 100644 --- a/lustre/extN/Makefile.am +++ b/lustre/extN/Makefile.am @@ -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 index 0000000..cd31486 --- /dev/null +++ b/lustre/extN/ext3-2.4.18-fixes.diff @@ -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); diff --git a/lustre/extN/ext3-2.4.18-ino_sb_macro.diff b/lustre/extN/ext3-2.4.18-ino_sb_macro.diff index 385da3f..a49d5da 100644 --- a/lustre/extN/ext3-2.4.18-ino_sb_macro.diff +++ b/lustre/extN/ext3-2.4.18-ino_sb_macro.diff @@ -168,19 +168,16 @@ 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; @@ -189,22 +186,7 @@ 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; @@ -215,42 +197,16 @@ 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 */ @@ -261,11 +217,7 @@ 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); @@ -282,12 +234,6 @@ !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; @@ -329,32 +275,6 @@ 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; @@ -923,16 +843,6 @@ 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); } @@ -1428,8 +1338,8 @@ } - 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 -- 1.8.3.1