+++ /dev/null
-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;
-@@ -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);
-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);