Loading fs/btrfs/ctree.c +4 −5 Original line number Diff line number Diff line Loading @@ -109,14 +109,14 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) return 1; if (k1.objectid < k2->objectid) return -1; if (k1.flags > k2->flags) return 1; if (k1.flags < k2->flags) return -1; if (k1.offset > k2->offset) return 1; if (k1.offset < k2->offset) return -1; if (k1.flags > k2->flags) return 1; if (k1.flags < k2->flags) return -1; return 0; } Loading Loading @@ -1165,7 +1165,6 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root BUG(); ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); if (ret == 0) { btrfs_release_path(root, path); return -EEXIST; } if (ret < 0) Loading fs/btrfs/ctree.h +32 −15 Original line number Diff line number Diff line Loading @@ -21,6 +21,9 @@ struct btrfs_transaction; */ #define BTRFS_NAME_LEN 255 /* 32 bytes in various csum fields */ #define BTRFS_CSUM_SIZE 32 /* * the key defines the order in the tree, and so it also defines (optimal) * block layout. objectid corresonds to the inode number. The flags Loading @@ -37,21 +40,21 @@ struct btrfs_transaction; */ struct btrfs_disk_key { __le64 objectid; __le32 flags; __le64 offset; __le32 flags; } __attribute__ ((__packed__)); struct btrfs_key { u64 objectid; u32 flags; u64 offset; u32 flags; } __attribute__ ((__packed__)); /* * every tree block (leaf or node) starts with this header. */ struct btrfs_header { __le32 csum[8]; u8 csum[BTRFS_CSUM_SIZE]; u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* which block this node is supposed to live in */ __le64 generation; Loading @@ -75,7 +78,7 @@ struct buffer_head; * it currently lacks any block count etc etc */ struct btrfs_super_block { __le32 csum[8]; u8 csum[BTRFS_CSUM_SIZE]; /* the first 3 fields must match struct btrfs_header */ u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* this block number */ Loading Loading @@ -147,7 +150,7 @@ struct btrfs_extent_item { } __attribute__ ((__packed__)); struct btrfs_inode_timespec { __le32 sec; __le64 sec; __le32 nsec; } __attribute__ ((__packed__)); Loading Loading @@ -214,6 +217,10 @@ struct btrfs_file_extent_item { __le64 num_blocks; } __attribute__ ((__packed__)); struct btrfs_csum_item { u8 csum[BTRFS_CSUM_SIZE]; } __attribute__ ((__packed__)); struct btrfs_inode_map_item { struct btrfs_disk_key key; } __attribute__ ((__packed__)); Loading Loading @@ -283,27 +290,32 @@ struct btrfs_root { * a (hopefully) huge chunk of disk */ #define BTRFS_EXTENT_DATA_KEY 4 /* * csum items have the checksums for data in the extents */ #define BTRFS_CSUM_ITEM_KEY 5 /* * root items point to tree roots. There are typically in the root * tree used by the super block to find all the other trees */ #define BTRFS_ROOT_ITEM_KEY 5 #define BTRFS_ROOT_ITEM_KEY 6 /* * extent items are in the extent map tree. These record which blocks * are used, and how many references there are to each block */ #define BTRFS_EXTENT_ITEM_KEY 6 #define BTRFS_EXTENT_ITEM_KEY 7 /* * the inode map records which inode numbers are in use and where * they actually live on disk */ #define BTRFS_INODE_MAP_ITEM_KEY 7 #define BTRFS_INODE_MAP_ITEM_KEY 8 /* * string items are for debugging. They just store a short string of * data in the FS */ #define BTRFS_STRING_ITEM_KEY 8 #define BTRFS_STRING_ITEM_KEY 9 static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) { Loading Loading @@ -407,15 +419,15 @@ static inline void btrfs_set_inode_compat_flags(struct btrfs_inode_item *i, i->compat_flags = cpu_to_le16(val); } static inline u32 btrfs_timespec_sec(struct btrfs_inode_timespec *ts) static inline u64 btrfs_timespec_sec(struct btrfs_inode_timespec *ts) { return le32_to_cpu(ts->sec); return le64_to_cpu(ts->sec); } static inline void btrfs_set_timespec_sec(struct btrfs_inode_timespec *ts, u32 val) u64 val) { ts->sec = cpu_to_le32(val); ts->sec = cpu_to_le64(val); } static inline u32 btrfs_timespec_nsec(struct btrfs_inode_timespec *ts) Loading @@ -429,8 +441,6 @@ static inline void btrfs_set_timespec_nsec(struct btrfs_inode_timespec *ts, ts->nsec = cpu_to_le32(val); } static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) { return le64_to_cpu(ei->owner); Loading Loading @@ -905,4 +915,11 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 objectid, u64 blocknr, int mod); int btrfs_csum_file_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len); int btrfs_csum_verify_file_block(struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len); #endif fs/btrfs/disk-io.c +26 −11 Original line number Diff line number Diff line Loading @@ -127,31 +127,46 @@ static int btree_get_block(struct inode *inode, sector_t iblock, return 0; } static int csum_tree_block(struct btrfs_root * root, struct buffer_head *bh, int verify) int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, char *result) { struct btrfs_node *node = btrfs_buffer_node(bh); struct scatterlist sg; struct crypto_hash *tfm = root->fs_info->hash_tfm; struct hash_desc desc; int ret; char result[32]; desc.tfm = tfm; desc.flags = 0; sg_init_one(&sg, bh->b_data + 32, bh->b_size - 32); sg_init_one(&sg, data, len); spin_lock(&root->fs_info->hash_lock); ret = crypto_hash_digest(&desc, &sg, bh->b_size - 32, result); ret = crypto_hash_digest(&desc, &sg, len, result); spin_unlock(&root->fs_info->hash_lock); if (ret) { printk("sha256 digest failed\n"); } return ret; } static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, int verify) { char result[BTRFS_CSUM_SIZE]; int ret; struct btrfs_node *node; ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE, bh->b_size - BTRFS_CSUM_SIZE, result); if (ret) return ret; if (verify) { if (memcmp(node->header.csum, result, sizeof(result))) printk("csum verify failed on %Lu\n", bh->b_blocknr); return -EINVAL; } else memcpy(node->header.csum, result, sizeof(node->header.csum)); if (memcmp(bh->b_data, result, BTRFS_CSUM_SIZE)) { printk("checksum verify failed on %lu\n", bh->b_blocknr); return 1; } } else { node = btrfs_buffer_node(bh); memcpy(&node->header.csum, result, BTRFS_CSUM_SIZE); } return 0; } Loading fs/btrfs/disk-io.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,4 +39,6 @@ void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf); int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root); struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr); int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, char *result); #endif fs/btrfs/file-item.c +60 −0 Original line number Diff line number Diff line Loading @@ -57,3 +57,63 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); return ret; } int btrfs_csum_file_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len) { int ret; struct btrfs_key file_key; struct btrfs_path path; struct btrfs_csum_item *item; btrfs_init_path(&path); file_key.objectid = objectid; file_key.offset = offset; file_key.flags = 0; btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); ret = btrfs_insert_empty_item(trans, root, &path, &file_key, BTRFS_CSUM_SIZE); if (ret != 0 && ret != -EEXIST) goto fail; item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], struct btrfs_csum_item); ret = 0; ret = btrfs_csum_data(root, data, len, item->csum); mark_buffer_dirty(path.nodes[0]); fail: btrfs_release_path(root, &path); return ret; } int btrfs_csum_verify_file_block(struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len) { int ret; struct btrfs_key file_key; struct btrfs_path path; struct btrfs_csum_item *item; char result[BTRFS_CSUM_SIZE]; btrfs_init_path(&path); file_key.objectid = objectid; file_key.offset = offset; file_key.flags = 0; btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); ret = btrfs_search_slot(NULL, root, &file_key, &path, 0, 0); if (ret) goto fail; item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], struct btrfs_csum_item); ret = 0; ret = btrfs_csum_data(root, data, len, result); WARN_ON(ret); if (memcmp(result, item->csum, BTRFS_CSUM_SIZE)) ret = 1; fail: btrfs_release_path(root, &path); return ret; } Loading
fs/btrfs/ctree.c +4 −5 Original line number Diff line number Diff line Loading @@ -109,14 +109,14 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) return 1; if (k1.objectid < k2->objectid) return -1; if (k1.flags > k2->flags) return 1; if (k1.flags < k2->flags) return -1; if (k1.offset > k2->offset) return 1; if (k1.offset < k2->offset) return -1; if (k1.flags > k2->flags) return 1; if (k1.flags < k2->flags) return -1; return 0; } Loading Loading @@ -1165,7 +1165,6 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root BUG(); ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); if (ret == 0) { btrfs_release_path(root, path); return -EEXIST; } if (ret < 0) Loading
fs/btrfs/ctree.h +32 −15 Original line number Diff line number Diff line Loading @@ -21,6 +21,9 @@ struct btrfs_transaction; */ #define BTRFS_NAME_LEN 255 /* 32 bytes in various csum fields */ #define BTRFS_CSUM_SIZE 32 /* * the key defines the order in the tree, and so it also defines (optimal) * block layout. objectid corresonds to the inode number. The flags Loading @@ -37,21 +40,21 @@ struct btrfs_transaction; */ struct btrfs_disk_key { __le64 objectid; __le32 flags; __le64 offset; __le32 flags; } __attribute__ ((__packed__)); struct btrfs_key { u64 objectid; u32 flags; u64 offset; u32 flags; } __attribute__ ((__packed__)); /* * every tree block (leaf or node) starts with this header. */ struct btrfs_header { __le32 csum[8]; u8 csum[BTRFS_CSUM_SIZE]; u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* which block this node is supposed to live in */ __le64 generation; Loading @@ -75,7 +78,7 @@ struct buffer_head; * it currently lacks any block count etc etc */ struct btrfs_super_block { __le32 csum[8]; u8 csum[BTRFS_CSUM_SIZE]; /* the first 3 fields must match struct btrfs_header */ u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* this block number */ Loading Loading @@ -147,7 +150,7 @@ struct btrfs_extent_item { } __attribute__ ((__packed__)); struct btrfs_inode_timespec { __le32 sec; __le64 sec; __le32 nsec; } __attribute__ ((__packed__)); Loading Loading @@ -214,6 +217,10 @@ struct btrfs_file_extent_item { __le64 num_blocks; } __attribute__ ((__packed__)); struct btrfs_csum_item { u8 csum[BTRFS_CSUM_SIZE]; } __attribute__ ((__packed__)); struct btrfs_inode_map_item { struct btrfs_disk_key key; } __attribute__ ((__packed__)); Loading Loading @@ -283,27 +290,32 @@ struct btrfs_root { * a (hopefully) huge chunk of disk */ #define BTRFS_EXTENT_DATA_KEY 4 /* * csum items have the checksums for data in the extents */ #define BTRFS_CSUM_ITEM_KEY 5 /* * root items point to tree roots. There are typically in the root * tree used by the super block to find all the other trees */ #define BTRFS_ROOT_ITEM_KEY 5 #define BTRFS_ROOT_ITEM_KEY 6 /* * extent items are in the extent map tree. These record which blocks * are used, and how many references there are to each block */ #define BTRFS_EXTENT_ITEM_KEY 6 #define BTRFS_EXTENT_ITEM_KEY 7 /* * the inode map records which inode numbers are in use and where * they actually live on disk */ #define BTRFS_INODE_MAP_ITEM_KEY 7 #define BTRFS_INODE_MAP_ITEM_KEY 8 /* * string items are for debugging. They just store a short string of * data in the FS */ #define BTRFS_STRING_ITEM_KEY 8 #define BTRFS_STRING_ITEM_KEY 9 static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) { Loading Loading @@ -407,15 +419,15 @@ static inline void btrfs_set_inode_compat_flags(struct btrfs_inode_item *i, i->compat_flags = cpu_to_le16(val); } static inline u32 btrfs_timespec_sec(struct btrfs_inode_timespec *ts) static inline u64 btrfs_timespec_sec(struct btrfs_inode_timespec *ts) { return le32_to_cpu(ts->sec); return le64_to_cpu(ts->sec); } static inline void btrfs_set_timespec_sec(struct btrfs_inode_timespec *ts, u32 val) u64 val) { ts->sec = cpu_to_le32(val); ts->sec = cpu_to_le64(val); } static inline u32 btrfs_timespec_nsec(struct btrfs_inode_timespec *ts) Loading @@ -429,8 +441,6 @@ static inline void btrfs_set_timespec_nsec(struct btrfs_inode_timespec *ts, ts->nsec = cpu_to_le32(val); } static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) { return le64_to_cpu(ei->owner); Loading Loading @@ -905,4 +915,11 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 objectid, u64 blocknr, int mod); int btrfs_csum_file_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len); int btrfs_csum_verify_file_block(struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len); #endif
fs/btrfs/disk-io.c +26 −11 Original line number Diff line number Diff line Loading @@ -127,31 +127,46 @@ static int btree_get_block(struct inode *inode, sector_t iblock, return 0; } static int csum_tree_block(struct btrfs_root * root, struct buffer_head *bh, int verify) int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, char *result) { struct btrfs_node *node = btrfs_buffer_node(bh); struct scatterlist sg; struct crypto_hash *tfm = root->fs_info->hash_tfm; struct hash_desc desc; int ret; char result[32]; desc.tfm = tfm; desc.flags = 0; sg_init_one(&sg, bh->b_data + 32, bh->b_size - 32); sg_init_one(&sg, data, len); spin_lock(&root->fs_info->hash_lock); ret = crypto_hash_digest(&desc, &sg, bh->b_size - 32, result); ret = crypto_hash_digest(&desc, &sg, len, result); spin_unlock(&root->fs_info->hash_lock); if (ret) { printk("sha256 digest failed\n"); } return ret; } static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, int verify) { char result[BTRFS_CSUM_SIZE]; int ret; struct btrfs_node *node; ret = btrfs_csum_data(root, bh->b_data + BTRFS_CSUM_SIZE, bh->b_size - BTRFS_CSUM_SIZE, result); if (ret) return ret; if (verify) { if (memcmp(node->header.csum, result, sizeof(result))) printk("csum verify failed on %Lu\n", bh->b_blocknr); return -EINVAL; } else memcpy(node->header.csum, result, sizeof(node->header.csum)); if (memcmp(bh->b_data, result, BTRFS_CSUM_SIZE)) { printk("checksum verify failed on %lu\n", bh->b_blocknr); return 1; } } else { node = btrfs_buffer_node(bh); memcpy(&node->header.csum, result, BTRFS_CSUM_SIZE); } return 0; } Loading
fs/btrfs/disk-io.h +2 −0 Original line number Diff line number Diff line Loading @@ -39,4 +39,6 @@ void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf); int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root); struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr); int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, char *result); #endif
fs/btrfs/file-item.c +60 −0 Original line number Diff line number Diff line Loading @@ -57,3 +57,63 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); return ret; } int btrfs_csum_file_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len) { int ret; struct btrfs_key file_key; struct btrfs_path path; struct btrfs_csum_item *item; btrfs_init_path(&path); file_key.objectid = objectid; file_key.offset = offset; file_key.flags = 0; btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); ret = btrfs_insert_empty_item(trans, root, &path, &file_key, BTRFS_CSUM_SIZE); if (ret != 0 && ret != -EEXIST) goto fail; item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], struct btrfs_csum_item); ret = 0; ret = btrfs_csum_data(root, data, len, item->csum); mark_buffer_dirty(path.nodes[0]); fail: btrfs_release_path(root, &path); return ret; } int btrfs_csum_verify_file_block(struct btrfs_root *root, u64 objectid, u64 offset, char *data, size_t len) { int ret; struct btrfs_key file_key; struct btrfs_path path; struct btrfs_csum_item *item; char result[BTRFS_CSUM_SIZE]; btrfs_init_path(&path); file_key.objectid = objectid; file_key.offset = offset; file_key.flags = 0; btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); ret = btrfs_search_slot(NULL, root, &file_key, &path, 0, 0); if (ret) goto fail; item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], struct btrfs_csum_item); ret = 0; ret = btrfs_csum_data(root, data, len, result); WARN_ON(ret); if (memcmp(result, item->csum, BTRFS_CSUM_SIZE)) ret = 1; fail: btrfs_release_path(root, &path); return ret; }