Index: linux-2.4.21-suse2/fs/ext3/extents.c
===================================================================
--- linux-2.4.21-suse2.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.21-suse2/fs/ext3/extents.c 2004-09-12 19:52:27.000000000 +0400
-@@ -0,0 +1,2262 @@
++++ linux-2.4.21-suse2/fs/ext3/extents.c 2004-11-03 00:34:45.404241880 +0300
+@@ -0,0 +1,2269 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+}
+
+static inline void
-+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, struct ext3_extent *ex)
++ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block,
++ __u32 len, __u32 start, int type)
+{
++ EXT_ASSERT(len > 0);
+ if (tree->cex) {
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(ex->ee_len);
-+ tree->cex->ee_block = ex->ee_block;
-+ tree->cex->ee_start = ex->ee_start;
-+ tree->cex->ee_len = ex->ee_len;
++ tree->cex->ec_type = type;
++ tree->cex->ec_block = block;
++ tree->cex->ec_len = len;
++ tree->cex->ec_start = start;
+ }
+}
+
+ unsigned long block)
+{
+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent *ex, gex;
++ unsigned long lblock, len;
++ struct ext3_extent *ex;
+
+ if (!tree->cex)
+ return;
+ ex = path[depth].p_ext;
+ if (ex == NULL) {
+ /* there is no extent yet, so gap is [0;-] */
-+ gex.ee_block = 0;
-+ gex.ee_len = EXT_CACHE_MARK;
++ lblock = 0;
++ len = EXT_MAX_BLOCK;
+ ext_debug(tree, "cache gap(whole file):");
+ } else if (block < ex->ee_block) {
-+ gex.ee_block = block;
-+ gex.ee_len = ex->ee_block - block;
++ lblock = block;
++ len = ex->ee_block - block;
+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
+ (unsigned long) block,
+ (unsigned long) ex->ee_block,
+ (unsigned long) ex->ee_len);
+ } else if (block >= ex->ee_block + ex->ee_len) {
-+ gex.ee_block = ex->ee_block + ex->ee_len;
-+ gex.ee_len = ext3_ext_next_allocated_block(path);
++ lblock = ex->ee_block + ex->ee_len;
++ len = ext3_ext_next_allocated_block(path);
+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
+ (unsigned long) ex->ee_block,
+ (unsigned long) ex->ee_len,
+ (unsigned long) block);
-+ EXT_ASSERT(gex.ee_len > gex.ee_block);
-+ gex.ee_len = gex.ee_len - gex.ee_block;
++ EXT_ASSERT(len > lblock);
++ len = len - lblock;
+ } else {
++ lblock = len = 0;
+ BUG();
+ }
+
-+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) gex.ee_block,
-+ (unsigned long) gex.ee_len);
-+ gex.ee_start = EXT_CACHE_MARK;
-+ ext3_ext_put_in_cache(tree, &gex);
++ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len);
++ ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP);
+}
+
+static inline int
+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
+ struct ext3_extent *ex)
+{
-+ struct ext3_extent *cex = tree->cex;
++ struct ext3_ext_cache *cex = tree->cex;
+
+ /* is there cache storage at all? */
+ if (!cex)
-+ return 0;
++ return EXT3_EXT_CACHE_NO;
+
+ /* has cache valid data? */
-+ if (cex->ee_len == 0)
-+ return 0;
-+
-+ if (block >= cex->ee_block && block < cex->ee_block + cex->ee_len) {
-+ ex->ee_block = cex->ee_block;
-+ ex->ee_start = cex->ee_start;
-+ ex->ee_len = cex->ee_len;
++ if (cex->ec_type == EXT3_EXT_CACHE_NO)
++ return EXT3_EXT_CACHE_NO;
++
++ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP ||
++ cex->ec_type == EXT3_EXT_CACHE_EXTENT);
++ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
++ ex->ee_block = cex->ec_block;
++ ex->ee_start = cex->ec_start;
++ ex->ee_len = cex->ec_len;
+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
+ (unsigned long) block,
+ (unsigned long) ex->ee_block,
+ (unsigned long) ex->ee_len,
+ (unsigned long) ex->ee_start);
-+ return 1;
++ return cex->ec_type;
+ }
+
+ /* not in cache */
-+ return 0;
++ return EXT3_EXT_CACHE_NO;
+}
+
+/*
+ tree->root = (void *) EXT3_I(inode)->i_data;
+ tree->buffer = (void *) inode;
+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
-+ tree->cex = (struct ext3_extent *) &EXT3_I(inode)->i_cached_extent;
++ tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent;
+ tree->ops = &ext3_blockmap_helpers;
+}
+
+ down_write(&EXT3_I(inode)->truncate_sem);
+
+ /* check in cache */
-+ if (ext3_ext_in_cache(&tree, iblock, &newex)) {
-+ if (newex.ee_start == EXT_CACHE_MARK) {
-+ /* this is cached gap */
++ if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) {
++ if (goal == EXT3_EXT_CACHE_GAP) {
+ if (!create) {
+ /* block isn't allocated yet and
+ * user don't want to allocate it */
+ goto out2;
+ }
+ /* we should allocate requested block */
-+ } else if (newex.ee_start) {
++ } else if (goal == EXT3_EXT_CACHE_EXTENT) {
+ /* block is already allocated */
+ newblock = iblock - newex.ee_block + newex.ee_start;
+ goto out;
++ } else {
++ EXT_ASSERT(0);
+ }
+ }
+
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
+ (int) iblock, ex->ee_block, ex->ee_len,
+ newblock);
-+ ext3_ext_put_in_cache(&tree, ex);
++ ext3_ext_put_in_cache(&tree, ex->ee_block,
++ ex->ee_len, ex->ee_start,
++ EXT3_EXT_CACHE_EXTENT);
+ goto out;
+ }
+ }
+ newblock = newex.ee_start;
+ set_bit(BH_New, &bh_result->b_state);
+
-+ ext3_ext_put_in_cache(&tree, &newex);
++ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
++ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+out:
+ ext3_ext_show_leaf(&tree, path);
+ set_bit(BH_Mapped, &bh_result->b_state);
+
Index: linux-2.4.21-suse2/fs/ext3/ialloc.c
===================================================================
---- linux-2.4.21-suse2.orig/fs/ext3/ialloc.c 2004-09-12 19:52:26.000000000 +0400
-+++ linux-2.4.21-suse2/fs/ext3/ialloc.c 2004-09-12 19:53:34.000000000 +0400
-@@ -592,10 +592,21 @@
+--- linux-2.4.21-suse2.orig/fs/ext3/ialloc.c 2004-11-02 20:31:37.000000000 +0300
++++ linux-2.4.21-suse2/fs/ext3/ialloc.c 2004-11-02 20:34:00.000000000 +0300
+@@ -592,10 +592,22 @@
iloc.bh = NULL;
goto fail;
}
-
+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, inode);
++ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
++ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
++ ext3_extents_initialize_blockmap(handle, inode);
+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
+ if (err) goto fail;
init_rwsem(&inode->u.ext3_i.xattr_sem);
Index: linux-2.4.21-suse2/fs/ext3/inode.c
===================================================================
---- linux-2.4.21-suse2.orig/fs/ext3/inode.c 2004-09-12 19:52:27.000000000 +0400
-+++ linux-2.4.21-suse2/fs/ext3/inode.c 2004-09-12 19:52:27.000000000 +0400
+--- linux-2.4.21-suse2.orig/fs/ext3/inode.c 2004-11-02 20:31:38.000000000 +0300
++++ linux-2.4.21-suse2/fs/ext3/inode.c 2004-11-02 20:34:00.000000000 +0300
@@ -853,6 +853,16 @@
goto reread;
}
handle = start_transaction(inode);
if (IS_ERR(handle))
return; /* AKPM: return what? */
-@@ -2664,6 +2677,9 @@
+@@ -2324,6 +2337,7 @@
+ for (block = 0; block < EXT3_N_BLOCKS; block++)
+ inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
+ INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
++ memset(&inode->u.ext3_i.i_cached_extent, 0, sizeof(__u32) * 4);
+
+ brelse (iloc.bh);
+
+@@ -2664,6 +2678,9 @@
int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
int ret;
if (ext3_should_journal_data(inode))
ret = 3 * (bpp + indirects) + 2;
else
-@@ -3100,7 +3116,7 @@
+@@ -3100,7 +3117,7 @@
/* alloc blocks one by one */
for (i = 0; i < nblocks; i++) {
&bh_tmp, 1, 1);
if (ret)
break;
-@@ -3176,7 +3192,7 @@
+@@ -3176,7 +3193,7 @@
if (blocks[i] != 0)
continue;
"allocating block %ld\n", rc, iblock);
Index: linux-2.4.21-suse2/fs/ext3/Makefile
===================================================================
---- linux-2.4.21-suse2.orig/fs/ext3/Makefile 2004-09-12 19:52:25.000000000 +0400
-+++ linux-2.4.21-suse2/fs/ext3/Makefile 2004-09-12 19:52:27.000000000 +0400
+--- linux-2.4.21-suse2.orig/fs/ext3/Makefile 2004-11-02 20:31:33.000000000 +0300
++++ linux-2.4.21-suse2/fs/ext3/Makefile 2004-11-02 20:31:39.000000000 +0300
@@ -12,7 +12,10 @@
export-objs := ext3-exports.o
export-objs += xattr.o
Index: linux-2.4.21-suse2/fs/ext3/super.c
===================================================================
---- linux-2.4.21-suse2.orig/fs/ext3/super.c 2004-09-12 19:52:26.000000000 +0400
-+++ linux-2.4.21-suse2/fs/ext3/super.c 2004-09-12 19:52:27.000000000 +0400
+--- linux-2.4.21-suse2.orig/fs/ext3/super.c 2004-11-02 20:31:37.000000000 +0300
++++ linux-2.4.21-suse2/fs/ext3/super.c 2004-11-02 20:31:39.000000000 +0300
@@ -624,6 +624,7 @@
int i;
failed_mount3:
Index: linux-2.4.21-suse2/fs/ext3/ioctl.c
===================================================================
---- linux-2.4.21-suse2.orig/fs/ext3/ioctl.c 2004-09-12 19:52:25.000000000 +0400
-+++ linux-2.4.21-suse2/fs/ext3/ioctl.c 2004-09-12 19:52:27.000000000 +0400
+--- linux-2.4.21-suse2.orig/fs/ext3/ioctl.c 2004-11-02 20:31:32.000000000 +0300
++++ linux-2.4.21-suse2/fs/ext3/ioctl.c 2004-11-02 20:31:39.000000000 +0300
@@ -174,6 +174,10 @@
return ret;
}
}
Index: linux-2.4.21-suse2/include/linux/ext3_fs.h
===================================================================
---- linux-2.4.21-suse2.orig/include/linux/ext3_fs.h 2004-09-12 19:52:26.000000000 +0400
-+++ linux-2.4.21-suse2/include/linux/ext3_fs.h 2004-09-12 19:52:50.000000000 +0400
+--- linux-2.4.21-suse2.orig/include/linux/ext3_fs.h 2004-11-02 20:31:37.000000000 +0300
++++ linux-2.4.21-suse2/include/linux/ext3_fs.h 2004-11-02 20:31:39.000000000 +0300
@@ -184,6 +184,7 @@
#define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
Index: linux-2.4.21-suse2/include/linux/ext3_extents.h
===================================================================
--- linux-2.4.21-suse2.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.21-suse2/include/linux/ext3_extents.h 2004-09-12 19:52:27.000000000 +0400
-@@ -0,0 +1,237 @@
++++ linux-2.4.21-suse2/include/linux/ext3_extents.h 2004-11-02 20:34:00.000000000 +0300
+@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
+ * Written by Alex Tomas <alex@clusterfs.com>
+ * if EXT_DEBUG is defined you can use 'extdebug' mount option
+ * to get lots of info what's going on
+ */
-+#define EXT_DEBUG
++#define EXT_DEBUG_
+#ifdef EXT_DEBUG
+#define ext_debug(tree,fmt,a...) \
+do { \
+ */
+
+/*
++ * storage for cached extent
++ */
++struct ext3_ext_cache {
++ __u32 ec_start;
++ __u32 ec_block;
++ __u32 ec_len;
++ __u32 ec_type;
++};
++
++#define EXT3_EXT_CACHE_NO 0
++#define EXT3_EXT_CACHE_GAP 1
++#define EXT3_EXT_CACHE_EXTENT 2
++
++/*
+ * ext3_extents_tree is used to pass initial information
+ * to top-level extents API
+ */
+ void *buffer; /* will be passed as arg to ^^ routines */
+ int buffer_len;
+ void *private;
-+ struct ext3_extent *cex;/* last found extent */
++ struct ext3_ext_cache *cex;/* last found extent */
+ struct ext3_extents_helpers *ops;
+};
+
+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
+{
+ if (tree->cex)
-+ tree->cex->ee_len = 0;
++ tree->cex->ec_type = EXT3_EXT_CACHE_NO;
+}
+
+
+
Index: linux-2.4.21-suse2/include/linux/ext3_fs_i.h
===================================================================
---- linux-2.4.21-suse2.orig/include/linux/ext3_fs_i.h 2004-09-12 19:52:27.000000000 +0400
-+++ linux-2.4.21-suse2/include/linux/ext3_fs_i.h 2004-09-12 19:52:27.000000000 +0400
+--- linux-2.4.21-suse2.orig/include/linux/ext3_fs_i.h 2004-11-02 20:31:37.000000000 +0300
++++ linux-2.4.21-suse2/include/linux/ext3_fs_i.h 2004-11-02 20:45:16.000000000 +0300
@@ -90,6 +90,8 @@
* by other means, so we have truncate_sem.
*/
struct rw_semaphore truncate_sem;
+
-+ __u32 i_cached_extent[3];
++ __u32 i_cached_extent[4];
};
#endif /* _LINUX_EXT3_FS_I */