This is reiser4 update for 2.6.12-rc2-mm3

fs/reiser4/plugin/compress/compress.h     |    2
fs/reiser4/plugin/plugin.h                |    1
fs/reiser4/status_flags.c                 |    1
fs/reiser4/txnmgr.c                       |    2
fs/reiser4/vfs_ops.c                      |    2

diff -puN fs/reiser4/plugin/compress/compress.c~reiser4-crc-update-1.900 fs/reiser4/plugin/compress/compress.c


fs/reiser4/as_ops.c                       |    6 --
fs/reiser4/cluster.h                      |   16 ++---
fs/reiser4/flush.c                        |   14 +---
fs/reiser4/plugin/compress/compress.c     |    5 +
fs/reiser4/plugin/compress/compress.h     |    2
fs/reiser4/plugin/compress/minilzo.c      |   10 ---
fs/reiser4/plugin/cryptcompress.c         |   89 ++++++++++++++++++------------
fs/reiser4/plugin/cryptcompress.h         |   13 +++-
fs/reiser4/plugin/file/file.c             |   75 ++++++++++++-------------
fs/reiser4/plugin/file/file.h             |    4 +
fs/reiser4/plugin/file/tail_conversion.c  |   13 ++++
fs/reiser4/plugin/item/ctail.c            |   32 +++++-----
fs/reiser4/plugin/item/extent_file_ops.c  |   40 +++++++++----
fs/reiser4/plugin/item/extent_flush_ops.c |   14 ++++
fs/reiser4/plugin/item/tail.c             |   26 ++++++--
fs/reiser4/plugin/plugin.h                |    1
fs/reiser4/plugin/space/bitmap.c          |    8 +-
fs/reiser4/status_flags.c                 |    1
fs/reiser4/super.h                        |    4 +
fs/reiser4/tree_walk.c                    |    4 -
fs/reiser4/txnmgr.c                       |    8 +-
fs/reiser4/vfs_ops.c                      |    8 +-
22 files changed, 239 insertions(+), 154 deletions(-)

diff -puN fs/reiser4/cluster.h~reiser4-update-2 fs/reiser4/cluster.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/cluster.h~reiser4-update-2  2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/cluster.h      2005-04-29 15:12:56.000000000 +0400
@@ -26,34 +26,34 @@ static inline int inode_cluster_shift (s
}

static inline unsigned
-page_cluster_shift(struct inode * inode)
+cluster_nrpages_shift(struct inode * inode)
{
-       return inode_cluster_shift(inode) + PAGE_CACHE_SHIFT;
+       return inode_cluster_shift(inode) - PAGE_CACHE_SHIFT;
}

/* cluster size in page units */
static inline unsigned cluster_nrpages (struct inode * inode)
{
-       return (1U << inode_cluster_shift(inode));
+       return 1U << cluster_nrpages_shift(inode);
}

static inline size_t inode_cluster_size (struct inode * inode)
{
       assert("edward-96", inode != NULL);

-       return (PAGE_CACHE_SIZE << inode_cluster_shift(inode));
+       return 1U << inode_cluster_shift(inode);
}

static inline unsigned long
pg_to_clust(unsigned long idx, struct inode * inode)
{
-       return idx >> inode_cluster_shift(inode);
+       return idx >> cluster_nrpages_shift(inode);
}

static inline unsigned long
clust_to_pg(unsigned long idx, struct inode * inode)
{
-       return idx << inode_cluster_shift(inode);
+       return idx << cluster_nrpages_shift(inode);
}

static inline unsigned long
@@ -103,14 +103,14 @@ count_to_nrpages(loff_t count)
static inline unsigned long
count_to_nrclust(loff_t count, struct inode * inode)
{
-       return count_to_nr(count, page_cluster_shift(inode));
+       return count_to_nr(count, inode_cluster_shift(inode));
}

/* number of clusters occupied by @count pages */
static inline cloff_t
pgcount_to_nrclust(pgoff_t count, struct inode * inode)
{
-       return count_to_nr(count, inode_cluster_shift(inode));
+       return count_to_nr(count, cluster_nrpages_shift(inode));
}

static inline loff_t
diff -puN fs/reiser4/flush.c~reiser4-update-2 fs/reiser4/flush.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/flush.c~reiser4-update-2    2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/flush.c        2005-04-29 15:12:56.000000000 +0400
@@ -440,9 +440,6 @@ assert("nikita-3435",                                                       \
ON_DEBUG(atomic_t flush_cnt;)


-/* FIXME: remove me */#define FLUSH_CHECKS_CONGESTION 1
-
-#if defined (FLUSH_CHECKS_CONGESTION)
/* check fs backing device for write congestion */
static int check_write_congestion (void)
{
@@ -453,10 +450,9 @@ static int check_write_congestion (void)
       bdi = get_super_fake(sb)->i_mapping->backing_dev_info;
       return  bdi_write_congested(bdi);
}
-#endif /* FLUSH_CHECKS_CONGESTION */

/* conditionally write flush queue */
-static int write_prepped_nodes (flush_pos_t * pos, int check_congestion)
+static int write_prepped_nodes (flush_pos_t * pos)
{
       int ret;

@@ -466,10 +462,8 @@ static int write_prepped_nodes (flush_po
       if (!(pos->flags & JNODE_FLUSH_WRITE_BLOCKS))
               return 0;

-#if defined (FLUSH_CHECKS_CONGESTION)
-       if (check_congestion && check_write_congestion())
+       if (check_write_congestion())
               return 0;
-#endif /* FLUSH_CHECKS_CONGESTION */

       ret = write_fq(pos->fq, pos->nr_written,
                      WRITEOUT_SINGLE_STREAM | WRITEOUT_FOR_PAGE_RECLAIM);
@@ -889,7 +883,7 @@ static int rapid_flush (flush_pos_t * po
       if (!wbq_available())
               return 0;

-       return write_prepped_nodes(pos, 1);
+       return write_prepped_nodes(pos);
}

#else
@@ -1483,7 +1477,7 @@ out:
               int ret1;

               /* NOTE: seems like io is done under long term locks. */
-               ret1 = write_prepped_nodes(pos, 1);
+               ret1 = write_prepped_nodes(pos);
               if (ret1 < 0)
                       return ret1;
       }
diff -puN fs/reiser4/plugin/compress/compress.c~reiser4-update-2 fs/reiser4/plugin/compress/compress.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/compress/compress.c~reiser4-update-2 2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/compress/compress.c     2005-04-29 15:12:56.000000000 +0400
@@ -372,6 +372,7 @@ compression_plugin compression_plugins[L
                                .alloc = NULL,
                                .free = NULL,
                                .min_tfm_size = NULL,
+                                .checksum = NULL,
                                .compress = NULL,
                                .decompress = NULL}
       ,
@@ -391,6 +392,7 @@ compression_plugin compression_plugins[L
                                .alloc = lzo1_alloc,
                                .free = lzo1_free,
                                .min_tfm_size = lzo1_min_tfm_size,
+                                .checksum = reiser4_adler32,
                                .compress = lzo1_compress,
                                .decompress = lzo1_decompress}
       ,
@@ -410,6 +412,7 @@ compression_plugin compression_plugins[L
                                .alloc = NULL,
                                .free = NULL,
                                .min_tfm_size = NULL,
+                                .checksum = reiser4_adler32,
                                .compress = NULL,
                                .decompress = lzo1_decompress}
       ,
@@ -429,6 +432,7 @@ compression_plugin compression_plugins[L
                                 .alloc = gzip1_alloc,
                                 .free = gzip1_free,
                                 .min_tfm_size = gzip1_min_tfm_size,
+                                 .checksum = NULL,
                                 .compress = gzip1_compress,
                                 .decompress = gzip1_decompress}
       ,
@@ -448,6 +452,7 @@ compression_plugin compression_plugins[L
                                 .alloc = gzip1_nocompress_alloc,
                                 .free = gzip1_nocompress_free,
                                 .min_tfm_size = NULL,
+                                 .checksum = NULL,
                                 .compress = NULL,
                                 .decompress = gzip1_decompress}
};
diff -puN fs/reiser4/plugin/compress/compress.h~reiser4-update-2 fs/reiser4/plugin/compress/compress.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/compress/compress.h~reiser4-update-2 2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/compress/compress.h     2005-04-29 15:12:56.000000000 +0400
@@ -23,6 +23,8 @@ typedef enum {
typedef void * coa_t;
typedef coa_t coa_set[LAST_COMPRESSION_ID];

+__u32 reiser4_adler32(char * data, __u32 len);
+
#endif /* __FS_REISER4_COMPRESS_H__ */

/* Make Linus happy.
diff -puN fs/reiser4/plugin/compress/minilzo.c~reiser4-update-2 fs/reiser4/plugin/compress/minilzo.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/compress/minilzo.c~reiser4-update-2  2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/compress/minilzo.c      2005-04-29 15:12:56.000000000 +0400
@@ -1110,16 +1110,6 @@ _lzo_config_check(void)

    COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t));

-#if defined(__LZO_IN_MINLZO)
-    if (r == 1)
-    {
-       lzo_uint32 adler;
-       adler = lzo_adler32(0, NULL, 0);
-       adler = lzo_adler32(adler, lzo_copyright(), 200);
-       r &= __lzo_assert(adler == 0xc76f1751L);
-    }
-#endif
-
    if (r == 1)
    {
       r &= __lzo_assert(!schedule_insns_bug());
diff -puN fs/reiser4/plugin/cryptcompress.c~reiser4-update-2 fs/reiser4/plugin/cryptcompress.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/cryptcompress.c~reiser4-update-2     2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/cryptcompress.c 2005-04-29 19:10:38.000000000 +0400
@@ -98,7 +98,7 @@ crc_inode_ok(struct inode * inode)
       reiser4_inode * info = reiser4_inode_data(inode);
       cryptcompress_info_t * data = cryptcompress_inode_data(inode);

-       if ((info->cluster_shift <= MAX_CLUSTER_SHIFT) &&
+       if (cluster_shift_ok(info->cluster_shift) &&
           (data->tfm[CRYPTO_TFM] == NULL) &&
           (data->tfm[DIGEST_TFM] == NULL))
               return 1;
@@ -338,7 +338,7 @@ inode_invert_compression(struct inode *

       assert("edward-1308", inode != NULL);

-       result = force_plugin(inode,
+       result = force_plugin(inode,
                             PSET_COMPRESSION,
                             compression_plugin_to_plugin
                             (dual_compression(inode_compression_plugin(inode))));
@@ -386,12 +386,12 @@ inode_set_cluster(struct inode * object,
                  this is a necessary parameter for cryptcompress object */
               warning("edward-418", "create_cryptcompress: default cluster size"
                       " (%u) was assigned for the object %llu\n",
-                       (1U << PAGE_CACHE_SHIFT << DEFAULT_CLUSTER_SHIFT),
+                       (1U << DEFAULT_CLUSTER_SHIFT),
                       (unsigned long long)get_inode_oid(object));
               init_default_cluster(&def);
               data = &def;
       }
-       assert("edward-697", *data <= MAX_CLUSTER_SHIFT);
+       assert("edward-697", cluster_shift_ok(*data));

       info->cluster_shift = *data;
       info->extmask |= (1 << CLUSTER_STAT);
@@ -863,7 +863,7 @@ try_encrypt(struct inode * inode)
static int
save_compressed(int old_size, int new_size, struct inode * inode)
{
-       return (new_size + DC_CHECKSUM_SIZE + max_crypto_overhead(inode) < old_size);
+       return (new_size + (int)DC_CHECKSUM_SIZE + max_crypto_overhead(inode) < old_size);
}

/* guess if the cluster was compressed */
@@ -882,11 +882,40 @@ need_decompression(reiser4_cluster_t * c
                fsize_to_count(clust, inode));
}

-static void set_compression_magic(__u8 * magic)
+/* append checksum at the end of input transform stream
+   and increment its length */
+static void
+dc_set_checksum(compression_plugin * cplug, tfm_cluster_t * tc)
{
-       /* FIXME-EDWARD: Use a checksum here */
-       assert("edward-279", magic != NULL);
-       memset(magic, 0, DC_CHECKSUM_SIZE);
+       __u32 checksum;
+
+       assert("edward-1309", tc != NULL);
+       assert("edward-1310", tc->len > 0);
+       assert("edward-1311", cplug->checksum != NULL);
+
+       checksum = cplug->checksum(tfm_stream_data(tc, OUTPUT_STREAM), tc->len);
+       cputod32(checksum, (d32 *)(tfm_stream_data(tc, OUTPUT_STREAM) + tc->len));
+       tc->len += (int)DC_CHECKSUM_SIZE;
+}
+
+/* returns 0 if checksums coincide, otherwise returns 1,
+   decremrnt the length of input transform stream */
+static int
+dc_check_checksum(compression_plugin * cplug, tfm_cluster_t * tc)
+{
+       assert("edward-1312", tc != NULL);
+       assert("edward-1313", tc->len > (int)DC_CHECKSUM_SIZE);
+       assert("edward-1314", cplug->checksum != NULL);
+
+       if (cplug->checksum(tfm_stream_data(tc, INPUT_STREAM),  tc->len - (int)DC_CHECKSUM_SIZE) !=
+           d32tocpu((d32 *)(tfm_stream_data(tc, INPUT_STREAM) + tc->len - (int)DC_CHECKSUM_SIZE))) {
+               warning("edward-156", "bad disk cluster checksum %d, (should be %d)\n",
+                       (int)d32tocpu((d32 *)(tfm_stream_data(tc, INPUT_STREAM) + tc->len - (int)DC_CHECKSUM_SIZE)),
+                       (int)cplug->checksum(tfm_stream_data(tc, INPUT_STREAM),  tc->len - (int)DC_CHECKSUM_SIZE));
+               return 1;
+       }
+       tc->len -= (int)DC_CHECKSUM_SIZE;
+       return 0;
}

reiser4_internal int
@@ -951,9 +980,8 @@ deflate_cluster(reiser4_cluster_t * clus
               if (save_compressed(tc->len, dst_len, inode)) {
                       /* accept */
                       tc->len = dst_len;
-
-                       set_compression_magic(tfm_stream_data(tc, OUTPUT_STREAM) + tc->len);
-                       tc->len += DC_CHECKSUM_SIZE;
+                       if (cplug->checksum != NULL)
+                               dc_set_checksum(cplug, tc);
                       transformed = 1;
               }
#if defined(SMART_COMPRESSION_MODE)
@@ -1020,7 +1048,6 @@ inflate_cluster(reiser4_cluster_t * clus
               transformed = 1;
       }
       if (need_decompression(clust, inode, 0)) {
-               __u8 magic[DC_CHECKSUM_SIZE];
               unsigned dst_len = inode_cluster_size(inode);
               compression_plugin * cplug = inode_compression_plugin(inode);

@@ -1033,12 +1060,12 @@ inflate_cluster(reiser4_cluster_t * clus
               assert("edward-1305", cplug->decompress != NULL);
               assert("edward-910", tfm_cluster_is_set(tc));

-               /* Check compression magic for possible IO errors.
+               /* Check compression checksum for possible IO errors.

                  End-of-cluster format created before encryption:

                  data
-                  compression_magic  (4)   Indicates presence of compression
+                  checksum           (4)   Indicates presence of compression
                                           infrastructure, should be private.
                                           Can be absent.
                  crypto_overhead          Created by ->align() method of crypto-plugin,
@@ -1050,17 +1077,11 @@ inflate_cluster(reiser4_cluster_t * clus
                  tail_size           (1)   size of aligning tail,
                                            1 <= tail_size <= blksize
               */
-               set_compression_magic(magic);
-
-               if (memcmp(tfm_stream_data(tc, INPUT_STREAM) + (tc->len - (size_t)DC_CHECKSUM_SIZE),
-                          magic, (size_t)DC_CHECKSUM_SIZE)) {
-                       printk("edward-156: wrong compression magic %d (should be %d)\n",
-                              *((int *)(tfm_stream_data(tc, INPUT_STREAM) + (tc->len - (size_t)DC_CHECKSUM_SIZE))), *((int *)magic));
-                       result = -EIO;
-                       return result;
+               if (cplug->checksum != NULL) {
+                       result = dc_check_checksum(cplug, tc);
+                       if (result)
+                               return RETERR(-EIO);
               }
-               tc->len -= (size_t)DC_CHECKSUM_SIZE;
-
               /* decompress cluster */
               cplug->decompress(get_coa(tc, cplug->h.id),
                                 tfm_stream_data(tc, INPUT_STREAM), tc->len,
@@ -1328,13 +1349,13 @@ try_capture_cluster(reiser4_cluster_t *
       assert("edward-1033", clust->pages[0] != NULL);

       node = jprivate(clust->pages[0]);
-
+
       assert("edward-1035", node != NULL);
-
+
       LOCK_JNODE(node);
       if (clust->win)
               inode_set_new_size(clust, inode);
-
+
       result = try_capture(node, ZNODE_WRITE_LOCK, 0, 0);
       if (result)
               goto exit;
@@ -2183,8 +2204,10 @@ jnode_truncate_ok(struct inode *inode, c
{
       jnode * node;
       node = jlookup(current_tree, get_inode_oid(inode), clust_to_pg(index, inode));
-       if (node)
+       if (node) {
+               warning("edward-1315", "jnode %p is untruncated\n", node);
               jput(node);
+       }
       return (node == NULL);
}
#endif
@@ -2362,7 +2385,7 @@ set_cluster_params(struct inode * inode,
       assert("edward-197", clust != NULL);
       assert("edward-1072", win != NULL);
       assert("edward-198", inode != NULL);
-       assert("edward-747", reiser4_inode_data(inode)->cluster_shift <= MAX_CLUSTER_SHIFT);
+       assert("edward-747", cluster_shift_ok(reiser4_inode_data(inode)->cluster_shift));

       result = alloc_cluster_pgset(clust, cluster_nrpages(inode));
       if (result)
@@ -2418,7 +2441,7 @@ write_cryptcompress_flow(struct file * f
       assert("edward-161", schedulable());
       assert("edward-748", crc_inode_ok(inode));
       assert("edward-159", current_blocksize == PAGE_CACHE_SIZE);
-       assert("edward-749", reiser4_inode_data(inode)->cluster_shift <= MAX_CLUSTER_SHIFT);
+       assert("edward-749", cluster_shift_ok(reiser4_inode_data(inode)->cluster_shift));
       assert("edward-1274", get_current_context()->grabbed_blocks == 0);

       result = check_cryptcompress(inode);
@@ -2674,7 +2697,7 @@ static void
set_append_cluster_key(const coord_t *coord, reiser4_key *key, struct inode *inode)
{
       item_key_by_coord(coord, key);
-       set_key_offset(key, ((__u64)(clust_by_coord(coord, inode)) + 1) << inode_cluster_shift(inode) << PAGE_CACHE_SHIFT);
+       set_key_offset(key, clust_to_off(clust_by_coord(coord, inode) + 1, inode));
}

/* If @index > 0, find real disk cluster of the index (@index - 1),
@@ -3286,7 +3309,7 @@ capture_cryptcompress(struct inode *inod
               return 0;

       info = cryptcompress_inode_data(inode);
-       nrpages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       nrpages = count_to_nrpages(i_size_read(inode));

       if (wbc->sync_mode != WB_SYNC_ALL)
               to_capture = min_count(wbc->nr_to_write, MAX_CLUSTERS_TO_CAPTURE(inode));
diff -puN fs/reiser4/plugin/cryptcompress.h~reiser4-update-2 fs/reiser4/plugin/cryptcompress.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/cryptcompress.h~reiser4-update-2     2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/cryptcompress.h 2005-04-29 15:12:56.000000000 +0400
@@ -11,13 +11,22 @@
#include <linux/vmalloc.h>

#define MIN_CLUSTER_SIZE PAGE_CACHE_SIZE
-#define MAX_CLUSTER_SHIFT 4
-#define MAX_CLUSTER_NRPAGES (1 << MAX_CLUSTER_SHIFT)
+#define MIN_CLUSTER_SHIFT PAGE_CACHE_SHIFT
+#define MAX_CLUSTER_SHIFT 16
+#define MAX_CLUSTER_NRPAGES (1U << MAX_CLUSTER_SHIFT >> PAGE_CACHE_SHIFT)
#define DEFAULT_CLUSTER_SHIFT 0
#define DC_CHECKSUM_SIZE 4
#define MIN_CRYPTO_BLOCKSIZE 8
 //#define LAZY_COMPRESSION_MODE

+#if REISER4_DEBUG
+static inline int
+cluster_shift_ok (int shift)
+{
+       return (shift >= MIN_CLUSTER_SHIFT) && (shift <= MAX_CLUSTER_SHIFT);
+}
+#endif
+
typedef unsigned long cloff_t;

/* Set of transform id's supported by reiser4,
diff -puN fs/reiser4/plugin/file/file.c~reiser4-update-2 fs/reiser4/plugin/file/file.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/file/file.c~reiser4-update-2 2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/file/file.c     2005-04-29 19:10:38.000000000 +0400
@@ -733,8 +733,10 @@ load_file_hint(struct file *file, hint_t
               if (IS_ERR(fsdata))
                       return PTR_ERR(fsdata);

+               spin_lock_inode(file->f_dentry->d_inode);
               if (seal_is_set(&fsdata->reg.hint.seal)) {
                       *hint = fsdata->reg.hint;
+                       spin_unlock_inode(file->f_dentry->d_inode);
                       /* force re-validation of the coord on the first
                        * iteration of the read/write loop. */
                       hint->ext_coord.valid = 0;
@@ -743,6 +745,7 @@ load_file_hint(struct file *file, hint_t
                       return 0;
               }
               memset(&fsdata->reg.hint, 0, sizeof(hint_t));
+               spin_unlock_inode(file->f_dentry->d_inode);
       }
       hint_init_zero(hint);
       return 0;
@@ -762,7 +765,10 @@ save_file_hint(struct file *file, const
       assert("vs-965", !IS_ERR(fsdata));
       assert("nikita-19891",
              coords_equal(&hint->seal.coord1, &hint->ext_coord.coord));
+
+       spin_lock_inode(file->f_dentry->d_inode);
       fsdata->reg.hint = *hint;
+       spin_unlock_inode(file->f_dentry->d_inode);
       return;
}

@@ -1341,6 +1347,9 @@ capture_unix_file(struct inode *inode, s
                * this function is out of reiser4 context and may safely
                * sleep on semaphore.
                */
+               assert("", LOCK_CNT_NIL(inode_sem_w));
+               assert("", LOCK_CNT_NIL(inode_sem_r));
+#if 0
               if (is_in_reiser4_context()) {
                       if (down_read_trylock(&uf_info->latch) == 0) {
/* ZAM-FIXME-HANS: please explain this error handling here, grep for
@@ -1348,6 +1357,7 @@ capture_unix_file(struct inode *inode, s
 * represent busy loops that we should recode.  Also tell me whether
 * any of them fail to return EBUSY to user space, and if yes, then
 * recode them to not use the EBUSY macro.*/
+                               warning("", "does this ever happen?");
                               result = RETERR(-EBUSY);
                               reiser4_exit_context(&ctx);
                               break;
@@ -1355,7 +1365,9 @@ capture_unix_file(struct inode *inode, s
               } else
                       down_read(&uf_info->latch);
               LOCK_CNT_INC(inode_sem_r);
-
+#endif
+               txn_restart_current();
+               get_nonexclusive_access(uf_info, 0);
               while (to_capture > 0) {
                       pgoff_t start;

@@ -1390,8 +1402,11 @@ capture_unix_file(struct inode *inode, s
                       /* there may be left more pages */
                       redirty_inode(inode);

+               drop_nonexclusive_access(uf_info);
+/*
               up_read(&uf_info->latch);
               LOCK_CNT_DEC(inode_sem_r);
+*/
               if (result < 0) {
                       /* error happened */
                       reiser4_exit_context(&ctx);
@@ -1502,12 +1517,13 @@ readpage_unix_file(void *vp, struct page
       if (result != CBK_COORD_FOUND) {
               /* this indicates file corruption */
               done_lh(&lh);
+               unlock_page(page);
               return result;
       }

       if (PageUptodate(page)) {
               done_lh(&lh);
-               unlock_page(page);
+               unlock_page(page);
               return 0;
       }

@@ -1515,6 +1531,7 @@ readpage_unix_file(void *vp, struct page
       result = zload(coord->node);
       if (result) {
               done_lh(&lh);
+               unlock_page(page);
               return result;
       }

@@ -1531,6 +1548,7 @@ readpage_unix_file(void *vp, struct page

               zrelse(coord->node);
               done_lh(&lh);
+               unlock_page(page);
               return RETERR(-EIO);
       }

@@ -1546,14 +1564,17 @@ readpage_unix_file(void *vp, struct page
               set_key_offset(&key, (loff_t) (page->index + 1) << PAGE_CACHE_SHIFT);
               /* FIXME should call set_hint() */
               unset_hint(&hint);
-       } else
+       } else {
+               unlock_page(page);
               unset_hint(&hint);
+       }
       zrelse(coord->node);
       done_lh(&lh);

       save_file_hint(file, &hint);

-       assert("vs-979", ergo(result == 0, (PageLocked(page) || PageUptodate(page))));
+       assert("vs-979", ergo(result == 0, (PageLocked(page) || PageUptodate(page))));
+       assert("vs-9791", ergo(result != 0, !PageLocked(page)));

       return result;
}
@@ -1631,7 +1652,7 @@ reiser4_put_user_pages(struct page **pag

/* this is called with nonexclusive access obtained, file's container can not change */
static size_t
-read_file(hint_t *hint, file_container_t container,
+read_file(hint_t *hint,
         struct file *file, /* file to write to */
         char *buf, /* address of user-space buffer */
         size_t count, /* number of bytes to write */
@@ -1646,33 +1667,6 @@ read_file(hint_t *hint, file_container_t

       inode = file->f_dentry->d_inode;

-       /* we have nonexclusive access (NA) obtained. File's container may not
-          change until we drop NA. If possible - calculate read function
-          beforehand */
-       switch(container) {
-       case UF_CONTAINER_EXTENTS:
-               read_f = item_plugin_by_id(EXTENT_POINTER_ID)->s.file.read;
-               break;
-
-       case UF_CONTAINER_TAILS:
-               /* this is read-ahead for tails-only files */
-               result = reiser4_file_readahead(file, *off, count);
-               if (result)
-                       return result;
-
-               read_f = item_plugin_by_id(FORMATTING_ID)->s.file.read;
-               break;
-
-       case UF_CONTAINER_UNKNOWN:
-               read_f = 0;
-               break;
-
-       case UF_CONTAINER_EMPTY:
-       default:
-               warning("vs-1297", "File (ino %llu) has unexpected state: %d\n",
-                       (unsigned long long)get_inode_oid(inode), container);
-               return RETERR(-EIO);
-       }

       /* build flow */
       assert("vs-1250", inode_file_plugin(inode)->flow_by_inode == flow_by_inode_unix_file);
@@ -1704,9 +1698,9 @@ read_file(hint_t *hint, file_container_t
               if (hint->ext_coord.valid == 0)
                       validate_extended_coord(&hint->ext_coord, get_key_offset(&flow.key));

+               assert("vs-4", hint->ext_coord.valid == 1);
               /* call item's read method */
-               if (!read_f)
-                       read_f = item_plugin_by_coord(coord)->s.file.read;
+               read_f = item_plugin_by_coord(coord)->s.file.read;
               result = read_f(file, &flow, hint);
               zrelse(loaded);
               done_lh(hint->ext_coord.lh);
@@ -1807,7 +1801,7 @@ read_unix_file(struct file *file, char *
                       to_read = inode->i_size - *off;

               assert("vs-1706", to_read <= left);
-               read = read_file(&hint, uf_info->container, file, buf, to_read, off);
+               read = read_file(&hint, file, buf, to_read, off);

               if (user_space)
                       reiser4_put_user_pages(pages, nr_pages);
@@ -2059,6 +2053,7 @@ mmap_unix_file(struct file *file, struct
       inode = file->f_dentry->d_inode;
       uf_info = unix_file_inode_data(inode);

+       down(&uf_info->write);
       get_exclusive_access(uf_info);

       if (!IS_RDONLY(inode) && (vma->vm_flags & (VM_MAYWRITE | VM_SHARED))) {
@@ -2067,12 +2062,14 @@ mmap_unix_file(struct file *file, struct
               result = finish_conversion(inode);
               if (result) {
                       drop_exclusive_access(uf_info);
+                       up(&uf_info->write);
                       return result;
               }

               result = find_file_state(uf_info);
               if (result != 0) {
                       drop_exclusive_access(uf_info);
+                       up(&uf_info->write);
                       return result;
               }

@@ -2084,6 +2081,7 @@ mmap_unix_file(struct file *file, struct
                       result = check_pages_unix_file(inode);
                       if (result) {
                               drop_exclusive_access(uf_info);
+                               up(&uf_info->write);
                               return result;
                       }
               }
@@ -2097,6 +2095,7 @@ mmap_unix_file(struct file *file, struct
       }

       drop_exclusive_access(uf_info);
+       up(&uf_info->write);
       return result;
}

@@ -2299,9 +2298,9 @@ write_unix_file(struct file *file, /* fi
                               (unsigned long long)get_inode_oid(inode));
       }

+       save_file_hint(file, &hint);
       up(&uf_info->write);
       current->backing_dev_info = 0;
-       save_file_hint(file, &hint);

       return count ? count : result;
}
@@ -2317,6 +2316,7 @@ release_unix_file(struct inode *object,
       uf_info = unix_file_inode_data(object);
       result = 0;

+       down(&uf_info->write);
       get_exclusive_access(uf_info);
       if (atomic_read(&file->f_dentry->d_count) == 1 &&
           uf_info->container == UF_CONTAINER_EXTENTS &&
@@ -2329,6 +2329,7 @@ release_unix_file(struct inode *object,
               }
       }
       drop_exclusive_access(uf_info);
+       up(&uf_info->write);
       return 0;
}

@@ -2578,7 +2579,7 @@ init_inode_data_unix_file(struct inode *
       init_inode_ordering(inode, crd, create);
}

-/* plugin->u.file.pre_delete
+/* plugin->u.file.pre_delete

   We need this because generic_delete_inode calls truncate_inode_pages before
   filesystem's delete_inode method. As result of this, reiser4 tree may have
diff -puN fs/reiser4/plugin/file/file.h~reiser4-update-2 fs/reiser4/plugin/file/file.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/file/file.h~reiser4-update-2 2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/file/file.h     2005-04-29 15:12:56.000000000 +0400
@@ -85,6 +85,10 @@ typedef struct unix_file_info {
} unix_file_info_t;

struct unix_file_info *unix_file_inode_data(const struct inode * inode);
+void get_exclusive_access(unix_file_info_t *);
+void drop_exclusive_access(unix_file_info_t *);
+void get_nonexclusive_access(unix_file_info_t *, int);
+void drop_nonexclusive_access(unix_file_info_t *);

#include "../item/extent.h"
#include "../item/tail.h"
diff -puN fs/reiser4/plugin/file/tail_conversion.c~reiser4-update-2 fs/reiser4/plugin/file/tail_conversion.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/file/tail_conversion.c~reiser4-update-2      2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/file/tail_conversion.c  2005-04-29 15:12:56.000000000 +0400
@@ -32,6 +32,7 @@ get_exclusive_access(unix_file_info_t *u
       BUG_ON(get_current_context()->trans->atom != NULL);
       LOCK_CNT_INC(inode_sem_w);
       down_write(&uf_info->latch);
+       uf_info->exclusive_use = 1;
       assert("vs-1713", uf_info->ea_owner == NULL);
       assert("vs-1713", atomic_read(&uf_info->nr_neas) == 0);
       ON_DEBUG(uf_info->ea_owner = current);
@@ -43,6 +44,7 @@ drop_exclusive_access(unix_file_info_t *
       assert("vs-1714", uf_info->ea_owner == current);
       assert("vs-1715", atomic_read(&uf_info->nr_neas) == 0);
       ON_DEBUG(uf_info->ea_owner = NULL);
+       uf_info->exclusive_use = 0;
       up_write(&uf_info->latch);
       assert("nikita-3049", LOCK_CNT_NIL(inode_sem_r));
       assert("nikita-3049", LOCK_CNT_GTZ(inode_sem_w));
@@ -408,8 +410,19 @@ tail2extent(unix_file_info_t *uf_info)
                       release_all_pages(pages, sizeof_array(pages));
                       if (result)
                               goto error;
+                       /* we have to drop exclusive access to avoid deadlock
+                        * which may happen because called by
+                        * reiser4_writepages capture_unix_file requires to get
+                        * non-exclusive access to a file. It is safe to drop
+                        * EA in the middle of tail2extent conversion because
+                        * write_unix_file/unix_setattr(truncate)/release_unix_file(extent2tail)
+                        * are serialized by uf_info->write semaphore and
+                        * because read_unix_file works (should at least) on
+                        * partially converted files */
+                       drop_exclusive_access(uf_info);
                       /* throttle the conversion */
                       reiser4_throttle_write(inode);
+                       get_exclusive_access(uf_info);
               }
       }

diff -puN fs/reiser4/plugin/item/ctail.c~reiser4-update-2 fs/reiser4/plugin/item/ctail.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/item/ctail.c~reiser4-update-2        2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/item/ctail.c    2005-04-29 19:10:38.000000000 +0400
@@ -54,11 +54,10 @@ cluster_shift_by_coord(const coord_t * c
}

static unsigned long
-pg_by_coord(const coord_t * coord)
+off_by_coord(const coord_t * coord)
{
       reiser4_key  key;
-
-       return get_key_offset(item_key_by_coord(coord, &key)) >> PAGE_CACHE_SHIFT;
+       return get_key_offset(item_key_by_coord(coord, &key));
}

static int
@@ -88,7 +87,7 @@ clust_by_coord(const coord_t * coord, st
               assert("edward-1237", !coord_is_unprepped_ctail(coord));
               shift = cluster_shift_by_coord(coord);
       }
-       return pg_by_coord(coord) >> shift;
+       return off_by_coord(coord) >> shift;
}

static int unsigned long
@@ -100,7 +99,7 @@ disk_cluster_size (const coord_t * coord
          is meaninless if ctail is unprepped */
       assert("edward-1238", !coord_is_unprepped_ctail(coord));

-       return PAGE_CACHE_SIZE << cluster_shift_by_coord(coord);
+       return 1 << cluster_shift_by_coord(coord);
}

/* true if the key is of first disk cluster item */
@@ -235,15 +234,18 @@ init_ctail(coord_t * to /* coord of item
       return 0;
}

+/* plugin->u.item.b.lookup:
+   NULL: We are looking for item keys only */
+
+#if REISER4_DEBUG
reiser4_internal int
ctail_ok (const coord_t *coord)
{
       return coord_is_unprepped_ctail(coord) ||
-               (cluster_shift_by_coord(coord) <= MAX_CLUSTER_SHIFT);
+               cluster_shift_ok(cluster_shift_by_coord(coord));
}

-/* plugin->u.item.b.lookup:
-   NULL: We are looking for item keys only */
+/* plugin->u.item.b.check */
reiser4_internal int
check_ctail (const coord_t * coord, const char **error)
{
@@ -254,9 +256,7 @@ check_ctail (const coord_t * coord, cons
       }
       return 0;
}
-
-/* plugin->u.item.b.check */
-
+#endif

/* plugin->u.item.b.paste */
reiser4_internal int
@@ -860,7 +860,7 @@ reiser4_internal reiser4_key *
append_key_ctail(const coord_t *coord, reiser4_key *key)
{
       assert("edward-1241", item_id_by_coord(coord) == CTAIL_ID);
-       assert("edward-1242", cluster_shift_by_coord(coord) <= MAX_CLUSTER_SHIFT);
+       assert("edward-1242", cluster_shift_ok(cluster_shift_by_coord(coord)));

       item_key_by_coord(coord, key);
       set_key_offset(key, ((__u64)(clust_by_coord(coord, NULL)) + 1) << cluster_shift_by_coord(coord) << PAGE_CACHE_SHIFT);
@@ -1067,7 +1067,7 @@ do_convert_ctail(flush_pos_t * pos, crc_
       switch (mode) {
       case CRC_APPEND_ITEM:
               assert("edward-1229", info->flow.length != 0);
-               assert("edward-1256", cluster_shift_by_coord(&pos->coord) <= MAX_CLUSTER_SHIFT);
+               assert("edward-1256", cluster_shift_ok(cluster_shift_by_coord(&pos->coord)));
               result = insert_crc_flow_in_place(&pos->coord, &pos->lock, &info->flow, info->inode);
               break;
       case CRC_OVERWRITE_ITEM:
@@ -1360,7 +1360,9 @@ utmost_child_ctail(const coord_t * coord
       if (!is_disk_cluster_key(&key, coord))
               *child = NULL;
       else
-               *child = jlookup(current_tree, get_key_objectid(item_key_by_coord(coord, &key)), pg_by_coord(coord));
+               *child = jlookup(current_tree,
+                                get_key_objectid(item_key_by_coord(coord, &key)),
+                                off_to_pg(get_key_offset(&key)));
       return 0;
}

@@ -1601,7 +1603,7 @@ convert_ctail(flush_pos_t * pos)
                       /* convert unpprepped ctail to prepped one */
                       int shift;
                       shift = inode_cluster_shift(item_convert_data(pos)->inode);
-                       assert("edward-1259", shift <= MAX_CLUSTER_SHIFT);
+                       assert("edward-1259", cluster_shift_ok(shift));
                       cputod8(shift, &ctail_formatted_at(&pos->coord)->cluster_shift);
               }
               break;
diff -puN fs/reiser4/plugin/item/extent_file_ops.c~reiser4-update-2 fs/reiser4/plugin/item/extent_file_ops.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/item/extent_file_ops.c~reiser4-update-2      2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/item/extent_file_ops.c  2005-04-29 19:10:38.000000000 +0400
@@ -644,6 +644,8 @@ extent_balance_dirty_pages(struct inode
                          hint_t *hint)
{
       int result;
+       int excl;
+       unix_file_info_t *uf_info;

       if (hint->ext_coord.valid)
               set_hint(hint, &f->key, ZNODE_WRITE_LOCK);
@@ -666,7 +668,19 @@ extent_balance_dirty_pages(struct inode
                       return result;
       }

-       reiser4_throttle_write(inode);
+       if (!reiser4_is_set(inode->i_sb, REISER4_ATOMIC_WRITE)) {
+               uf_info = unix_file_inode_data(inode);
+               excl = unix_file_inode_data(inode)->exclusive_use;
+               if (excl)
+                       drop_exclusive_access(uf_info);
+               else
+                       drop_nonexclusive_access(uf_info);
+               reiser4_throttle_write(inode);
+               if (excl)
+                       get_exclusive_access(uf_info);
+               else
+                       get_nonexclusive_access(uf_info, 0);
+       }
       return 0;
}

@@ -1185,7 +1199,6 @@ extent_readpage_filler(void *data, struc
                                     TWIG_LEVEL, CBK_UNIQUE, NULL);
               if (result != CBK_COORD_FOUND) {
                       unset_hint(hint);
-                       lock_page(page);
                       return result;
               }
               ext_coord->valid = 0;
@@ -1194,7 +1207,12 @@ extent_readpage_filler(void *data, struc
       if (zload(ext_coord->coord.node)) {
               unset_hint(hint);
               done_lh(ext_coord->lh);
-               lock_page(page);
+               return RETERR(-EIO);
+       }
+       if (!item_is_extent(&ext_coord->coord)) {
+               /* tail conversion is running in parallel */
+               unset_hint(hint);
+               done_lh(ext_coord->lh);
               return RETERR(-EIO);
       }

@@ -1208,6 +1226,8 @@ extent_readpage_filler(void *data, struc
       if (!PageUptodate(page)) {
               result = do_readpage_extent(ext_by_ext_coord(ext_coord),
                                           ext_coord->extension.extent.pos_in_unit, page);
+               if (result)
+                       unlock_page(page);
       } else {
               unlock_page(page);
               result = 0;
@@ -1262,16 +1282,14 @@ call_readpage(struct file *file, struct
       if (result)
               return result;

+       lock_page(page);
       if (!PageUptodate(page)) {
-               lock_page(page);
-               if (!PageUptodate(page)) {
-                       unlock_page(page);
-                       page_detach_jnode(page, page->mapping, page->index);
-                       warning("jmacd-97178", "page is not up to date");
-                       return RETERR(-EIO);
-               }
               unlock_page(page);
+               page_detach_jnode(page, page->mapping, page->index);
+               warning("jmacd-97178", "page is not up to date");
+               return RETERR(-EIO);
       }
+       unlock_page(page);
       return 0;
}

@@ -1349,7 +1367,7 @@ read_extent(struct file *file, flow_t *f
               } else {
                       if (!PageUptodate(page)) {
                               lock_page(page);
-
+
                               assert("", page->mapping == mapping);
                               if (PageUptodate(page))
                                       unlock_page(page);
diff -puN fs/reiser4/plugin/item/extent_flush_ops.c~reiser4-update-2 fs/reiser4/plugin/item/extent_flush_ops.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/item/extent_flush_ops.c~reiser4-update-2     2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/item/extent_flush_ops.c 2005-04-29 15:12:56.000000000 +0400
@@ -279,7 +279,9 @@ exit:
/* ask block allocator for some blocks */
static void
extent_allocate_blocks(reiser4_blocknr_hint *preceder,
-                      reiser4_block_nr wanted_count, reiser4_block_nr *first_allocated, reiser4_block_nr *allocated, block_stage_t block_stage)
+                      reiser4_block_nr wanted_count,
+                      reiser4_block_nr *first_allocated, reiser4_block_nr *allocated,
+                      block_stage_t block_stage)
{
       *allocated = wanted_count;
       preceder->max_dist = 0; /* scan whole disk, if needed */
@@ -288,7 +290,7 @@ extent_allocate_blocks(reiser4_blocknr_h
       preceder->block_stage = block_stage;

       /* FIXME: we do not handle errors here now */
-       check_me("vs-420", reiser4_alloc_blocks (preceder, first_allocated, allocated, BA_PERMANENT) == 0);
+       check_me("vs-420", reiser4_alloc_blocks(preceder, first_allocated, allocated, BA_PERMANENT) == 0);
       /* update flush_pos's preceder to last allocated block number */
       preceder->blk = *first_allocated + *allocated - 1;
}
@@ -795,6 +797,10 @@ alloc_extent(flush_pos_t *flush_pos)
               else
                       block_stage = BLOCK_UNALLOCATED;

+               /* look at previous unit if possible. If it is allocated, make preceder more precise */
+               if (coord->unit_pos && (state_of_extent(ext - 1) == ALLOCATED_EXTENT))
+                       pos_hint(flush_pos)->blk = extent_get_start(ext - 1) + extent_get_width(ext - 1);
+
               /* allocate new block numbers for protected nodes */
               extent_allocate_blocks(pos_hint(flush_pos), protected, &first_allocated, &allocated, block_stage);

@@ -934,6 +940,10 @@ squalloc_extent(znode *left, const coord
               else
                       block_stage = BLOCK_UNALLOCATED;

+               /* look at previous unit if possible. If it is allocated, make preceder more precise */
+               if (coord->unit_pos && (state_of_extent(ext - 1) == ALLOCATED_EXTENT))
+                       pos_hint(flush_pos)->blk = extent_get_start(ext - 1) + extent_get_width(ext - 1);
+
               /* allocate new block numbers for protected nodes */
               extent_allocate_blocks(pos_hint(flush_pos), protected, &first_allocated, &allocated, block_stage);
               if (allocated != protected)
diff -puN fs/reiser4/plugin/item/tail.c~reiser4-update-2 fs/reiser4/plugin/item/tail.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/item/tail.c~reiser4-update-2 2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/item/tail.c     2005-04-29 19:10:38.000000000 +0400
@@ -454,6 +454,8 @@ tail_balance_dirty_pages(struct address_
{
       int result;
       struct inode *inode;
+       int excl;
+       unix_file_info_t *uf_info;

       if (hint->ext_coord.valid)
               set_hint(hint, &f->key, ZNODE_WRITE_LOCK);
@@ -475,12 +477,24 @@ tail_balance_dirty_pages(struct address_
                       return result;
       }

-       /* FIXME-VS: this is temporary: the problem is that bdp takes inodes
-          from sb's dirty list and it looks like nobody puts there inodes of
-          files which are built of tails */
-       move_inode_out_from_sync_inodes_loop(mapping);
-
-       reiser4_throttle_write(inode);
+       if (!reiser4_is_set(inode->i_sb, REISER4_ATOMIC_WRITE)) {
+               /* FIXME-VS: this is temporary: the problem is that bdp takes
+                  inodes from sb's dirty list and it looks like nobody puts
+                  there inodes of files which are built of tails */
+               move_inode_out_from_sync_inodes_loop(mapping);
+
+               uf_info = unix_file_inode_data(inode);
+               excl = unix_file_inode_data(inode)->exclusive_use;
+               if (excl)
+                       drop_exclusive_access(uf_info);
+               else
+                       drop_nonexclusive_access(uf_info);
+               reiser4_throttle_write(inode);
+               if (excl)
+                       get_exclusive_access(uf_info);
+               else
+                       get_nonexclusive_access(uf_info, 0);
+       }
       return 0;
}

diff -puN fs/reiser4/plugin/plugin.h~reiser4-update-2 fs/reiser4/plugin/plugin.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/plugin.h~reiser4-update-2    2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/plugin.h        2005-04-29 15:12:56.000000000 +0400
@@ -454,6 +454,7 @@ typedef struct compression_plugin {
       void (*free) (coa_t coa, tfm_action act);
       /* minimal size of the flow we still try to compress */
       int (*min_tfm_size) (void);
+       __u32 (*checksum) (char * data, __u32 length);
       /* main transform procedures */
       void (*compress)   (coa_t coa, __u8 *src_first, unsigned src_len,
                           __u8 *dst_first, unsigned *dst_len);
diff -puN fs/reiser4/plugin/space/bitmap.c~reiser4-update-2 fs/reiser4/plugin/space/bitmap.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/plugin/space/bitmap.c~reiser4-update-2      2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/plugin/space/bitmap.c  2005-04-29 15:12:56.000000000 +0400
@@ -461,11 +461,11 @@ reiser4_set_bits(char *addr, bmap_off_t
    Jean-loup Gailly        Mark Adler
    [email protected]          [email protected]

-    The above comment applies only to the adler32 function.
+    The above comment applies only to the reiser4_adler32 function.
*/

-static __u32
-adler32(char *data, __u32 len)
+reiser4_internal __u32
+reiser4_adler32(char *data, __u32 len)
{
       unsigned char *t = data;
       __u32 s1 = 1;
@@ -493,7 +493,7 @@ adler32(char *data, __u32 len)
static __u32
bnode_calc_crc(const struct bitmap_node *bnode, unsigned long size)
{
-       return adler32(bnode_commit_data(bnode), bmap_size(size));
+       return reiser4_adler32(bnode_commit_data(bnode), bmap_size(size));
}


diff -puN fs/reiser4/status_flags.c~reiser4-update-2 fs/reiser4/status_flags.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/status_flags.c~reiser4-update-2     2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/status_flags.c 2005-04-29 15:12:56.000000000 +0400
@@ -3,7 +3,6 @@

/* Functions that deal with reiser4 status block, query status and update it, if needed */

-#include <linux/page-flags.h>
#include <linux/bio.h>
#include <linux/highmem.h>
#include <linux/fs.h>
diff -puN fs/reiser4/super.h~reiser4-update-2 fs/reiser4/super.h
--- linux-2.6.12-rc2-mm3/fs/reiser4/super.h~reiser4-update-2    2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/super.h        2005-04-29 15:12:56.000000000 +0400
@@ -63,7 +63,9 @@ typedef enum {
        * directories. */
       REISER4_NO_PSEUDO = 5,
       /* load all bitmap blocks at mount time */
-       REISER4_DONT_LOAD_BITMAP = 6
+       REISER4_DONT_LOAD_BITMAP = 6,
+       /* enforce atomicity during write(2) */
+       REISER4_ATOMIC_WRITE = 7
} reiser4_fs_flag;

/*
diff -puN fs/reiser4/tree_walk.c~reiser4-update-2 fs/reiser4/tree_walk.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/tree_walk.c~reiser4-update-2        2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/tree_walk.c    2005-04-29 15:12:56.000000000 +0400
@@ -238,7 +238,7 @@ link_left_and_right(znode * left, znode

                       ON_DEBUG(left->right_version = atomic_inc_return(&delim_key_version););

-               } else if (ZF_ISSET(left->right, JNODE_HEARD_BANSHEE)) {
+               } else if (ZF_ISSET(left->right, JNODE_HEARD_BANSHEE) && left->right != right) {

                       ON_DEBUG(
                               left->right->left_version = atomic_inc_return(&delim_key_version);
@@ -271,7 +271,7 @@ link_left_and_right(znode * left, znode

                       ON_DEBUG(right->left_version = atomic_inc_return(&delim_key_version););

-               } else if (ZF_ISSET(right->left, JNODE_HEARD_BANSHEE)) {
+               } else if (ZF_ISSET(right->left, JNODE_HEARD_BANSHEE) && right->left != left) {

                       ON_DEBUG(
                               right->left->right_version = atomic_inc_return(&delim_key_version);
diff -puN fs/reiser4/txnmgr.c~reiser4-update-2 fs/reiser4/txnmgr.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/txnmgr.c~reiser4-update-2   2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/txnmgr.c       2005-04-29 19:10:38.000000000 +0400
@@ -1385,7 +1385,7 @@ static int txn_try_to_fuse_small_atom (t
       int atom_stage;
       txn_atom *atom_2;
       int repeat;
-
+
       assert ("zam-1051", atom->stage < ASTAGE_PRE_COMMIT);

       atom_stage = atom->stage;
@@ -1415,9 +1415,9 @@ static int txn_try_to_fuse_small_atom (t
                       UNLOCK_ATOM(atom_2);
               }
       }
-       spin_unlock_txnmgr(tmgr);
       atom->flags |= ATOM_CANCEL_FUSION;
- out:
+ out:
+       spin_unlock_txnmgr(tmgr);
       if (repeat) {
               UNLOCK_ATOM(atom);
               return -E_REPEAT;
@@ -1507,7 +1507,7 @@ flush_some_atom(long *nr_submitted, cons
       ret = flush_current_atom(flags, nr_submitted, &atom);
       if (ret == 0) {
               if (*nr_submitted == 0 || atom_should_commit_asap(atom)) {
-                       if (atom->capture_count < tmgr->atom_min_size &&
+                       if (atom->capture_count < tmgr->atom_min_size &&
                           !(atom->flags & ATOM_CANCEL_FUSION)) {
                               ret =txn_try_to_fuse_small_atom(tmgr, atom);
                               if (ret == -E_REPEAT)
diff -puN fs/reiser4/vfs_ops.c~reiser4-update-2 fs/reiser4/vfs_ops.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/vfs_ops.c~reiser4-update-2  2005-04-29 15:12:56.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/vfs_ops.c      2005-04-29 19:10:38.000000000 +0400
@@ -530,7 +530,7 @@ reiser4_destroy_inode(struct inode *inod
       kmem_cache_free(inode_cache, container_of(info, reiser4_inode_object, p));
}

-/* put_inode of super_operations
+/* put_inode of super_operations

   we use put_inode to call pre_delete method of file plugin if it is defined
   and if inode is unlinked and if it is about to drop inode reference count to
@@ -542,7 +542,7 @@ reiser4_put_inode(struct inode *inode)
       file_plugin *fplug;

       fplug = inode_file_plugin(inode);
-       if (fplug == NULL ||
+       if (fplug == NULL ||
           inode->i_nlink != 0 ||
           atomic_read(&inode->i_count) > 1 ||
           fplug->pre_delete == NULL)
@@ -551,7 +551,7 @@ reiser4_put_inode(struct inode *inode)
       init_context(&ctx, inode->i_sb);
       /* kill cursors which might be attached to inode if it were a directory one */
       kill_cursors(inode);
-       fplug->pre_delete(inode);
+       fplug->pre_delete(inode);
       reiser4_exit_context(&ctx);
}

@@ -1022,6 +1022,8 @@ do {                                              \
       /* Don't load all bitmap blocks at mount time, it is useful
          for machines with tiny RAM and large disks. */
       PUSH_BIT_OPT("dont_load_bitmap", REISER4_DONT_LOAD_BITMAP);
+       /* disable transaction commits during write() */
+       PUSH_BIT_OPT("atomic_write", REISER4_ATOMIC_WRITE);

       PUSH_OPT ({
               /* tree traversal readahead parameters:
diff -puN fs/reiser4/as_ops.c~reiser4-update-2 fs/reiser4/as_ops.c
--- linux-2.6.12-rc2-mm3/fs/reiser4/as_ops.c~reiser4-update-2   2005-04-29 18:48:49.000000000 +0400
+++ linux-2.6.12-rc2-mm3-root/fs/reiser4/as_ops.c       2005-04-29 18:48:49.000000000 +0400
@@ -158,13 +158,9 @@ reiser4_readpage(struct file *f /* file
               result = fplug->readpage(f, page);
       else
               result = RETERR(-EINVAL);
-       if (result != 0) {
-               SetPageError(page);
-               unlock_page(page);
-       }

       reiser4_exit_context(&ctx);
-       return 0;
+       return result;
}

static int filler(void *vp, struct page *page)

_