--- fs/reiser4/Makefile | 1 fs/reiser4/checksum.c | 29 ++++++++++++++++++++++++++ fs/reiser4/checksum.h | 39 +++++++++++++++++++++++++++++++++++ fs/reiser4/plugin/node/node.c | 3 +- fs/reiser4/plugin/node/node.h | 3 ++ fs/reiser4/plugin/node/node41.c | 44 +++++++++++++++++++++++++++++++--------- fs/reiser4/plugin/node/node41.h | 2 + fs/reiser4/super.h | 1 fs/reiser4/super_ops.c | 7 ++++++ fs/reiser4/wander.c | 13 ++++++++++- fs/reiser4/znode.c | 3 -- fs/reiser4/znode.h | 1 12 files changed, 133 insertions(+), 13 deletions(-) --- a/fs/reiser4/plugin/node/node.h +++ b/fs/reiser4/plugin/node/node.h @@ -233,6 +233,9 @@ typedef struct node_plugin { /* change plugin id of items which are in a node already. Currently it is Used in tail conversion for regular * files */ int (*set_item_plugin) (coord_t * coord, item_id); + /* calculate and check/update znode's checksum + (if @check is true, then check, otherwise update) */ + int (*csum)(znode *node, int check); } node_plugin; typedef enum { --- a/fs/reiser4/Makefile +++ b/fs/reiser4/Makefile @@ -48,6 +48,7 @@ reiser4-y := \ safe_link.o \ blocknrlist.o \ discard.o \ + checksum.o \ \ plugin/plugin.o \ plugin/plugin_set.o \ --- /dev/null +++ b/fs/reiser4/checksum.c @@ -0,0 +1,29 @@ +#include <linux/err.h> +#include "debug.h" +#include "checksum.h" + +int reiser4_init_csum_tfm(struct crypto_shash **tfm) +{ + *tfm = crypto_alloc_shash("crc32c", 0, 0); + if (IS_ERR(*tfm)) { + *tfm = NULL; + return 1; + } + return 0; +} + +void reiser4_done_csum_tfm(struct crypto_shash *tfm) +{ + crypto_free_shash(tfm); +} + +/* + Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + scroll-step: 1 + End: +*/ --- /dev/null +++ b/fs/reiser4/checksum.h @@ -0,0 +1,39 @@ +#ifndef __CHECKSUM__ +#define __CHECKSUM__ + +#include <crypto/hash.h> + +int reiser4_init_csum_tfm(struct crypto_shash **tfm); +void reiser4_done_csum_tfm(struct crypto_shash *tfm); +u32 static inline reiser4_crc32c(struct crypto_shash *tfm, + u32 crc, const void *address, + unsigned int length) +{ + struct { + struct shash_desc shash; + char ctx[4]; + } desc; + int err; + + desc.shash.tfm = tfm; + desc.shash.flags = 0; + *(u32 *)desc.ctx = crc; + + err = crypto_shash_update(&desc.shash, address, length); + BUG_ON(err); + return *(u32 *)desc.ctx; +} + +#endif /* __CHECKSUM__ */ + +/* + Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + scroll-step: 1 + End: +*/ + --- a/fs/reiser4/plugin/node/node.c +++ b/fs/reiser4/plugin/node/node.c @@ -153,7 +153,8 @@ node_plugin node_plugins[LAST_NODE_ID] = .fast_cut = fast_cut_node40, .max_item_size = max_item_size_node41, .prepare_removal = prepare_removal_node40, - .set_item_plugin = set_item_plugin_node40 + .set_item_plugin = set_item_plugin_node40, + .csum = csum_node41 } }; --- a/fs/reiser4/super_ops.c +++ b/fs/reiser4/super_ops.c @@ -6,6 +6,7 @@ #include "ktxnmgrd.h" #include "flush.h" #include "safe_link.h" +#include "checksum.h" #include <linux/vfs.h> #include <linux/writeback.h> @@ -249,6 +250,7 @@ static void reiser4_put_super(struct sup get_super_private(super)->df_plug->release(super); reiser4_done_formatted_fake(super); + reiser4_done_csum_tfm(sbinfo->csum_tfm); /* stop daemons: ktxnmgr and entd */ reiser4_done_entd(super); @@ -514,6 +516,10 @@ static int fill_super(struct super_block goto failed_init_sinfo; sbinfo = get_super_private(super); + + if ((result = reiser4_init_csum_tfm(&sbinfo->csum_tfm)) != 0) + goto failed_init_csum_tfm; + /* initialize various reiser4 parameters, parse mount options */ if ((result = reiser4_init_super_data(super, data)) != 0) goto failed_init_super_data; @@ -592,6 +598,7 @@ static int fill_super(struct super_block failed_init_super_data: reiser4_done_fs_info(super); failed_init_sinfo: + failed_init_csum_tfm: reiser4_exit_context(&ctx); return result; } --- a/fs/reiser4/plugin/node/node41.c +++ b/fs/reiser4/plugin/node/node41.c @@ -17,6 +17,7 @@ #include "../../tap.h" #include "../../tree.h" #include "../../super.h" +#include "../../checksum.h" #include "../../reiser4.h" #include <asm/uaccess.h> @@ -27,7 +28,7 @@ * node41 layout it almost the same as node40: * node41_header is at the beginning and a table of item headers * is at the end. Ther difference is that node41_header contains - * a 32-bit reference counter (see node41.h) + * a 32-bit checksum (see node41.h) */ static const __u32 REISER4_NODE41_MAGIC = 0x19051966; @@ -41,12 +42,43 @@ static inline node41_header *node41_node return (node41_header *)zdata(node); } +int csum_node41(znode *node, int check) +{ + __u32 cpu_csum; + + cpu_csum = reiser4_crc32c(get_current_super_private()->csum_tfm, + ~0, + zdata(node), + sizeof(struct node40_header)); + cpu_csum = reiser4_crc32c(get_current_super_private()->csum_tfm, + cpu_csum, + zdata(node) + sizeof(struct node41_header), + reiser4_get_current_sb()->s_blocksize - + sizeof(node41_header)); + if (check) + return cpu_csum == nh41_get_csum(node41_node_header(node)); + else { + nh41_set_csum(node41_node_header(node), cpu_csum); + return 1; + } +} + /* * plugin->u.node.parse * look for description of this method in plugin/node/node.h */ int parse_node41(znode *node /* node to parse */) { + int ret; + + ret = csum_node41(node, 1/* check */); + if (!ret) { + warning("edward-1645", + "block %llu: bad checksum. FSCK?", + *jnode_get_block(ZJNODE(node))); + reiser4_handle_error(); + return RETERR(-EIO); + } return parse_node40_common(node, REISER4_NODE41_MAGIC); } @@ -56,14 +88,8 @@ int parse_node41(znode *node /* node to */ int init_node41(znode *node /* node to initialise */) { - node41_header *header41; - - init_node40_common(node, node_plugin_by_id(NODE41_ID), - sizeof(node41_header), REISER4_NODE41_MAGIC); - - header41 = node41_node_header(node); - nh41_set_csum(header41, 0); - return 0; + return init_node40_common(node, node_plugin_by_id(NODE41_ID), + sizeof(node41_header), REISER4_NODE41_MAGIC); } /* --- a/fs/reiser4/plugin/node/node41.h +++ b/fs/reiser4/plugin/node/node41.h @@ -29,10 +29,12 @@ int max_item_size_node41(void); int shift_node41(coord_t *from, znode *to, shift_direction pend, int delete_child, int including_stop_coord, carry_plugin_info *info); +int csum_node41(znode *node, int check); #ifdef GUESS_EXISTS int guess_node41(const znode * node); #endif +extern void reiser4_handle_error(void); /* __REISER4_NODE41_H__ */ #endif --- a/fs/reiser4/znode.c +++ b/fs/reiser4/znode.c @@ -635,7 +635,7 @@ int zload_ra(znode * node /* znode to lo } /* load content of node into memory */ -int zload(znode * node) +int zload(znode *node) { return zload_ra(node, NULL); } @@ -651,7 +651,6 @@ int zinit_new(znode * node /* znode to i void zrelse(znode * node /* znode to release references to */ ) { assert("nikita-1381", znode_invariant(node)); - jrelse(ZJNODE(node)); } --- a/fs/reiser4/super.h +++ b/fs/reiser4/super.h @@ -275,6 +275,7 @@ struct reiser4_super_info_data { * more details */ struct d_cursor_info d_info; + struct crypto_shash *csum_tfm; #ifdef CONFIG_REISER4_BADBLOCKS /* Alternative master superblock offset (in bytes) */ --- a/fs/reiser4/wander.c +++ b/fs/reiser4/wander.c @@ -769,8 +769,19 @@ static int write_jnodes_to_disk_extent( JF_SET(cur, JNODE_WRITEBACK); JF_CLR(cur, JNODE_DIRTY); ON_DEBUG(cur->written++); - spin_unlock_jnode(cur); + assert("edward-1647", + ergo(jnode_is_znode(cur), JF_ISSET(cur, JNODE_PARSED))); + spin_unlock_jnode(cur); + /* + * update checksum + */ + if (jnode_is_znode(cur)) { + zload(JZNODE(cur)); + if (node_plugin_by_node(JZNODE(cur))->csum) + node_plugin_by_node(JZNODE(cur))->csum(JZNODE(cur), 0); + zrelse(JZNODE(cur)); + } ClearPageError(pg); set_page_writeback(pg); --- a/fs/reiser4/znode.h +++ b/fs/reiser4/znode.h @@ -172,6 +172,7 @@ extern int zload_ra(znode * node, ra_inf extern int zinit_new(znode * node, gfp_t gfp_flags); extern void zrelse(znode * node); extern void znode_change_parent(znode * new_parent, reiser4_block_nr * block); +extern void znode_update_csum(znode *node); /* size of data in znode */ static inline unsigned