The patch titled
     reiser4: fix disk cluster synchronization
has been added to the -mm tree.  Its filename is
     reiser4-fix-disk-cluster-synchronization.patch

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/

------------------------------------------------------
Subject: reiser4: fix disk cluster synchronization
From: Edward Shishkin <[EMAIL PROTECTED]>

Problem:
(2.6.24-rc3-mm2) BUG: unable to handle kernel NULL
pointer dereference at virtual address 00000024
EIP is at convert_ctail+0x14e/0x166

Bug: When updating disk clusters convert_ctail()
looks at inode which is already evicted from memory
or reused for other needs.

Fixup: Keep all needed file-specific info in
convert_item_info before disk cluster update
(when inode is pinned), then forget about inode.

Cleanups in plugin/file/file_conversion.c

Signed-off-by: Edward Shishkin <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 fs/reiser4/flush.h                       |    9 ----
 fs/reiser4/plugin/file/file_conversion.c |   42 +++++---------------
 fs/reiser4/plugin/item/ctail.c           |   44 ++++++++++-----------
 3 files changed, 35 insertions(+), 60 deletions(-)

diff -puN fs/reiser4/flush.h~reiser4-fix-disk-cluster-synchronization 
fs/reiser4/flush.h
--- a/fs/reiser4/flush.h~reiser4-fix-disk-cluster-synchronization
+++ a/fs/reiser4/flush.h
@@ -59,8 +59,8 @@ struct flush_scan {
 struct convert_item_info {
        dc_item_stat d_cur;     /* disk cluster state of the current item */
        dc_item_stat d_next;    /* disk cluster state of the next slum item */
-       struct inode *inode;
-       flow_t flow;
+       int cluster_shift;      /* disk cluster shift */
+       flow_t flow;            /* disk cluster data */
 };
 
 struct convert_info {
@@ -242,11 +242,6 @@ do {                                                       
                \
                       item_convert_data(pos)->d_cur,                   \
                       item_convert_data(pos)->d_next,                  \
                       item_convert_data(pos)->flow.length);            \
-               printk("inode %llu, size = %llu, cluster %lu\n",        \
-                      (unsigned long long)get_inode_oid                \
-                      (item_convert_data(pos)->inode),                 \
-                      i_size_read(item_convert_data(pos)->inode),      \
-                      convert_data(pos)->clust.index);                 \
        }                                                               \
 } while (0)
 #else
diff -puN 
fs/reiser4/plugin/file/file_conversion.c~reiser4-fix-disk-cluster-synchronization
 fs/reiser4/plugin/file/file_conversion.c
--- 
a/fs/reiser4/plugin/file/file_conversion.c~reiser4-fix-disk-cluster-synchronization
+++ a/fs/reiser4/plugin/file/file_conversion.c
@@ -430,27 +430,6 @@ static int reserve_cryptcompress2unixfil
                 BA_CAN_COMMIT);
 }
 
-/* clear flag that indicated conversion and update
-   stat-data with new (unix-file - specific) info */
-static int complete_file_conversion(struct inode *inode)
-{
-       int result;
-
-       grab_space_enable();
-       result =
-           reiser4_grab_space(inode_file_plugin(inode)->estimate.update(inode),
-                              BA_CAN_COMMIT);
-       if (result == 0) {
-               reiser4_inode_clr_flag(inode, REISER4_FILE_CONV_IN_PROGRESS);
-               result = reiser4_update_sd(inode);
-       }
-       if (result)
-               warning("edward-1452",
-                       "Converting %llu to unix-file: update sd failed (%i)",
-                       (unsigned long long)get_inode_oid(inode), result);
-       return 0;
-}
-
 /**
  * Convert cryptcompress file plugin to unix_file plugin.
  */
@@ -468,6 +447,7 @@ static int cryptcompress2unixfile(struct
        result = reserve_cryptcompress2unixfile(inode);
        if (result)
                goto out;
+       /* tell kill_hook to not truncate pages */
        reiser4_inode_set_flag(inode, REISER4_FILE_CONV_IN_PROGRESS);
        result = cut_disk_cluster(inode, 0);
        if (result)
@@ -494,18 +474,17 @@ static int cryptcompress2unixfile(struct
                if (result)
                        break;
        }
-       if (!result) {
-               uf_info->container = UF_CONTAINER_EXTENTS;
-               complete_file_conversion(inode);
-       }
+       if (unlikely(result))
+               goto out;
+       uf_info->container = UF_CONTAINER_EXTENTS;
+       result = reiser4_update_sd(inode);
  out:
        all_grabbed2free();
-       if (result)
-               warning("edward-1453", "Failed to convert file %llu: ret=%i",
-                       (unsigned long long)get_inode_oid(inode), result);
        return result;
 }
 
+#define convert_file_plugin cryptcompress2unixfile
+
 /**
  * This is called by ->write() method of a cryptcompress file plugin.
  * Make a decision about the most reasonable file plugin id to manage
@@ -611,10 +590,13 @@ ssize_t reiser4_write_careful(struct fil
         * Perform conversion to the new plugin.
         */
        down_read(&reiser4_inode_data(inode)->conv_sem);
-       result = cryptcompress2unixfile(file, inode, &cont);
+       result = convert_file_plugin(file, inode, &cont);
        up_read(&reiser4_inode_data(inode)->conv_sem);
        if (result) {
-               warning("edward-1544", "file conversion failed: %d", result);
+               warning("edward-1544",
+                       "Inode %llu: file plugin conversion failed (%d)",
+                       (unsigned long long)get_inode_oid(inode),
+                       result);
                context_set_commit_async(ctx);
                goto exit;
        }
diff -puN 
fs/reiser4/plugin/item/ctail.c~reiser4-fix-disk-cluster-synchronization 
fs/reiser4/plugin/item/ctail.c
--- a/fs/reiser4/plugin/item/ctail.c~reiser4-fix-disk-cluster-synchronization
+++ a/fs/reiser4/plugin/item/ctail.c
@@ -896,14 +896,13 @@ static int insert_unprepped_ctail(struct
 
 static int
 insert_cryptcompress_flow(coord_t * coord, lock_handle * lh, flow_t * f,
-                         struct inode *inode)
+                         int cluster_shift)
 {
        int result;
        carry_pool *pool;
        carry_level *lowest_level;
        reiser4_item_data *data;
        carry_op *op;
-       int cluster_shift = inode_cluster_shift(inode);
 
        pool =
            init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) +
@@ -954,15 +953,14 @@ insert_cryptcompress_flow(coord_t * coor
 /* Implementation of CRC_APPEND_ITEM mode of ctail conversion */
 static int insert_cryptcompress_flow_in_place(coord_t * coord,
                                              lock_handle * lh, flow_t * f,
-                                             struct inode *inode)
+                                             int cluster_shift)
 {
        int ret;
        coord_t pos;
        lock_handle lock;
 
-       assert("edward-674", f->length <= inode_scaled_cluster_size(inode));
-       assert("edward-484", coord->between == AT_UNIT
-              || coord->between == AFTER_ITEM);
+       assert("edward-484",
+              coord->between == AT_UNIT || coord->between == AFTER_ITEM);
        assert("edward-485", item_id_by_coord(coord) == CTAIL_ID);
 
        coord_dup(&pos, coord);
@@ -972,7 +970,7 @@ static int insert_cryptcompress_flow_in_
        init_lh(&lock);
        copy_lh(&lock, lh);
 
-       ret = insert_cryptcompress_flow(&pos, &lock, f, inode);
+       ret = insert_cryptcompress_flow(&pos, &lock, f, cluster_shift);
        done_lh(&lock);
        assert("edward-1347", znode_is_write_locked(lh->node));
        assert("edward-1228", !ret);
@@ -1079,7 +1077,7 @@ static int do_convert_ctail(flush_pos_t 
                    insert_cryptcompress_flow_in_place(&pos->coord,
                                                       &pos->lock,
                                                       &info->flow,
-                                                      info->inode);
+                                                      info->cluster_shift);
                break;
        case CRC_OVERWRITE_ITEM:
                assert("edward-1230", info->flow.length != 0);
@@ -1157,14 +1155,18 @@ static int should_attach_convert_idata(f
        return result;
 }
 
-/* plugin->init_convert_data() */
-static int
-init_convert_data_ctail(struct convert_item_info * idata, struct inode *inode)
+/**
+ * Collect all needed information about the object here,
+ * as in-memory inode can be evicted from memory before
+ * disk update completion.
+ */
+static int init_convert_data_ctail(struct convert_item_info * idata,
+                                  struct inode *inode)
 {
        assert("edward-813", idata != NULL);
        assert("edward-814", inode != NULL);
 
-       idata->inode = inode;
+       idata->cluster_shift = inode_cluster_shift(inode);
        idata->d_cur = DC_FIRST_ITEM;
        idata->d_next = DC_INVALID_STATE;
 
@@ -1295,15 +1297,13 @@ static int attach_convert_idata(flush_po
        inc_item_convert_count(pos);
 
        /* prepare flow for insertion */
-       fplug->flow_by_inode(info->inode,
+       fplug->flow_by_inode(inode,
                             (const char __user *)tfm_stream_data(&clust->tc, 
OUTPUT_STREAM),
                             0 /* kernel space */ ,
                             clust->tc.len,
                             clust_to_off(clust->index, inode),
                             WRITE_OP, &info->flow);
        jput(pos->child);
-
-       assert("edward-683", cryptcompress_inode_ok(inode));
        return 0;
       err:
        jput(pos->child);
@@ -1320,7 +1320,6 @@ static void detach_convert_idata(struct 
        assert("edward-840", sq->itm != NULL);
 
        info = sq->itm;
-       assert("edward-255", info->inode != NULL);
        assert("edward-1212", info->flow.length == 0);
 
        free_item_convert_data(sq);
@@ -1591,13 +1590,12 @@ int convert_ctail(flush_pos_t * pos)
        case CRC_OVERWRITE_ITEM:
                if (coord_is_unprepped_ctail(&pos->coord)) {
                        /* convert unpprepped ctail to prepped one */
-                       int shift;
-                       shift =
-                           inode_cluster_shift(item_convert_data(pos)->inode);
-                       assert("edward-1259", cluster_shift_ok(shift));
-                       put_unaligned((d8)shift,
-                               &ctail_formatted_at(&pos->coord)->
-                               cluster_shift);
+                       assert("edward-1259",
+                              cluster_shift_ok(item_convert_data(pos)->
+                                               cluster_shift));
+                       put_unaligned((d8)item_convert_data(pos)->cluster_shift,
+                                     &ctail_formatted_at(&pos->coord)->
+                                     cluster_shift);
                }
                break;
        }
_

Patches currently in -mm which might be from [EMAIL PROTECTED] are

reiser4-replace-uid==0-check-with-capability.patch
reiser4-specify-splice-file-operations.patch
reiser4-fix-dummy-ioctl_cryptcompress.patch
reiser4-granulate-rw-serialization-when-accessing-file-conversion-set.patch
reiser4-fix-disk-cluster-synchronization.patch
reiser4-use-balance_dirty_pages_ratelimited_nr.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to