aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4_extents.h11
-rw-r--r--fs/ext4/extents.c50
2 files changed, 61 insertions, 0 deletions
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index 94822e74ef73..cb1b2c919963 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -114,6 +114,17 @@ struct ext4_extent_header {
114 114
115#define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) 115#define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
116 116
117#define EXT4_EXTENT_TAIL_OFFSET(hdr) \
118 (sizeof(struct ext4_extent_header) + \
119 (sizeof(struct ext4_extent) * le16_to_cpu((hdr)->eh_max)))
120
121static inline struct ext4_extent_tail *
122find_ext4_extent_tail(struct ext4_extent_header *eh)
123{
124 return (struct ext4_extent_tail *)(((void *)eh) +
125 EXT4_EXTENT_TAIL_OFFSET(eh));
126}
127
117/* 128/*
118 * Array of ext4_ext_path contains path to some extent. 129 * Array of ext4_ext_path contains path to some extent.
119 * Creation/lookup routines use it for traversal/splitting/etc. 130 * Creation/lookup routines use it for traversal/splitting/etc.
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 8c1334ee8c7f..6f3b49bd34c7 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -52,6 +52,46 @@
52#define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ 52#define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */
53#define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ 53#define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */
54 54
55static __le32 ext4_extent_block_csum(struct inode *inode,
56 struct ext4_extent_header *eh)
57{
58 struct ext4_inode_info *ei = EXT4_I(inode);
59 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
60 __u32 csum;
61
62 csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)eh,
63 EXT4_EXTENT_TAIL_OFFSET(eh));
64 return cpu_to_le32(csum);
65}
66
67static int ext4_extent_block_csum_verify(struct inode *inode,
68 struct ext4_extent_header *eh)
69{
70 struct ext4_extent_tail *et;
71
72 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
73 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
74 return 1;
75
76 et = find_ext4_extent_tail(eh);
77 if (et->et_checksum != ext4_extent_block_csum(inode, eh))
78 return 0;
79 return 1;
80}
81
82static void ext4_extent_block_csum_set(struct inode *inode,
83 struct ext4_extent_header *eh)
84{
85 struct ext4_extent_tail *et;
86
87 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
88 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
89 return;
90
91 et = find_ext4_extent_tail(eh);
92 et->et_checksum = ext4_extent_block_csum(inode, eh);
93}
94
55static int ext4_split_extent(handle_t *handle, 95static int ext4_split_extent(handle_t *handle,
56 struct inode *inode, 96 struct inode *inode,
57 struct ext4_ext_path *path, 97 struct ext4_ext_path *path,
@@ -117,6 +157,7 @@ static int __ext4_ext_dirty(const char *where, unsigned int line,
117{ 157{
118 int err; 158 int err;
119 if (path->p_bh) { 159 if (path->p_bh) {
160 ext4_extent_block_csum_set(inode, ext_block_hdr(path->p_bh));
120 /* path points to block */ 161 /* path points to block */
121 err = __ext4_handle_dirty_metadata(where, line, handle, 162 err = __ext4_handle_dirty_metadata(where, line, handle,
122 inode, path->p_bh); 163 inode, path->p_bh);
@@ -391,6 +432,12 @@ static int __ext4_ext_check(const char *function, unsigned int line,
391 error_msg = "invalid extent entries"; 432 error_msg = "invalid extent entries";
392 goto corrupted; 433 goto corrupted;
393 } 434 }
435 /* Verify checksum on non-root extent tree nodes */
436 if (ext_depth(inode) != depth &&
437 !ext4_extent_block_csum_verify(inode, eh)) {
438 error_msg = "extent tree corrupted";
439 goto corrupted;
440 }
394 return 0; 441 return 0;
395 442
396corrupted: 443corrupted:
@@ -930,6 +977,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
930 le16_add_cpu(&neh->eh_entries, m); 977 le16_add_cpu(&neh->eh_entries, m);
931 } 978 }
932 979
980 ext4_extent_block_csum_set(inode, neh);
933 set_buffer_uptodate(bh); 981 set_buffer_uptodate(bh);
934 unlock_buffer(bh); 982 unlock_buffer(bh);
935 983
@@ -1008,6 +1056,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
1008 sizeof(struct ext4_extent_idx) * m); 1056 sizeof(struct ext4_extent_idx) * m);
1009 le16_add_cpu(&neh->eh_entries, m); 1057 le16_add_cpu(&neh->eh_entries, m);
1010 } 1058 }
1059 ext4_extent_block_csum_set(inode, neh);
1011 set_buffer_uptodate(bh); 1060 set_buffer_uptodate(bh);
1012 unlock_buffer(bh); 1061 unlock_buffer(bh);
1013 1062
@@ -1105,6 +1154,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
1105 else 1154 else
1106 neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); 1155 neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0));
1107 neh->eh_magic = EXT4_EXT_MAGIC; 1156 neh->eh_magic = EXT4_EXT_MAGIC;
1157 ext4_extent_block_csum_set(inode, neh);
1108 set_buffer_uptodate(bh); 1158 set_buffer_uptodate(bh);
1109 unlock_buffer(bh); 1159 unlock_buffer(bh);
1110 1160