aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/namei.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2012-04-29 18:41:10 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-04-29 18:41:10 -0400
commitb0336e8d2108e6302aecaadd17c6c0bd686da22d (patch)
tree063ec0bc590950b7ca0e2c5d5ed8a1c259ce1675 /fs/ext4/namei.c
parentdbe89444042ab6540bc304343cfdcbc8b95d003d (diff)
ext4: calculate and verify checksums of directory leaf blocks
Calculate and verify the checksums for directory leaf blocks (i.e. blocks that only contain actual directory entries). The checksum lives in what looks to be an unused directory entry with a 0 name_len at the end of the block. This scheme is not used for internal htree nodes because the mechanism in place there only costs one dx_entry, whereas the "empty" directory entry would cost two dx_entries. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/namei.c')
-rw-r--r--fs/ext4/namei.c260
1 files changed, 245 insertions, 15 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index f8efedde7593..5861d64929f6 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -189,6 +189,115 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
189 struct inode *inode); 189 struct inode *inode);
190 190
191/* checksumming functions */ 191/* checksumming functions */
192#define EXT4_DIRENT_TAIL(block, blocksize) \
193 ((struct ext4_dir_entry_tail *)(((void *)(block)) + \
194 ((blocksize) - \
195 sizeof(struct ext4_dir_entry_tail))))
196
197static void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
198 unsigned int blocksize)
199{
200 memset(t, 0, sizeof(struct ext4_dir_entry_tail));
201 t->det_rec_len = ext4_rec_len_to_disk(
202 sizeof(struct ext4_dir_entry_tail), blocksize);
203 t->det_reserved_ft = EXT4_FT_DIR_CSUM;
204}
205
206/* Walk through a dirent block to find a checksum "dirent" at the tail */
207static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
208 struct ext4_dir_entry *de)
209{
210 struct ext4_dir_entry_tail *t;
211
212#ifdef PARANOID
213 struct ext4_dir_entry *d, *top;
214
215 d = de;
216 top = (struct ext4_dir_entry *)(((void *)de) +
217 (EXT4_BLOCK_SIZE(inode->i_sb) -
218 sizeof(struct ext4_dir_entry_tail)));
219 while (d < top && d->rec_len)
220 d = (struct ext4_dir_entry *)(((void *)d) +
221 le16_to_cpu(d->rec_len));
222
223 if (d != top)
224 return NULL;
225
226 t = (struct ext4_dir_entry_tail *)d;
227#else
228 t = EXT4_DIRENT_TAIL(de, EXT4_BLOCK_SIZE(inode->i_sb));
229#endif
230
231 if (t->det_reserved_zero1 ||
232 le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) ||
233 t->det_reserved_zero2 ||
234 t->det_reserved_ft != EXT4_FT_DIR_CSUM)
235 return NULL;
236
237 return t;
238}
239
240static __le32 ext4_dirent_csum(struct inode *inode,
241 struct ext4_dir_entry *dirent, int size)
242{
243 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
244 struct ext4_inode_info *ei = EXT4_I(inode);
245 __u32 csum;
246
247 csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size);
248 return cpu_to_le32(csum);
249}
250
251int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
252{
253 struct ext4_dir_entry_tail *t;
254
255 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
256 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
257 return 1;
258
259 t = get_dirent_tail(inode, dirent);
260 if (!t) {
261 EXT4_ERROR_INODE(inode, "metadata_csum set but no space in dir "
262 "leaf for checksum. Please run e2fsck -D.");
263 return 0;
264 }
265
266 if (t->det_checksum != ext4_dirent_csum(inode, dirent,
267 (void *)t - (void *)dirent))
268 return 0;
269
270 return 1;
271}
272
273static void ext4_dirent_csum_set(struct inode *inode,
274 struct ext4_dir_entry *dirent)
275{
276 struct ext4_dir_entry_tail *t;
277
278 if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
279 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
280 return;
281
282 t = get_dirent_tail(inode, dirent);
283 if (!t) {
284 EXT4_ERROR_INODE(inode, "metadata_csum set but no space in dir "
285 "leaf for checksum. Please run e2fsck -D.");
286 return;
287 }
288
289 t->det_checksum = ext4_dirent_csum(inode, dirent,
290 (void *)t - (void *)dirent);
291}
292
293static inline int ext4_handle_dirty_dirent_node(handle_t *handle,
294 struct inode *inode,
295 struct buffer_head *bh)
296{
297 ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data);
298 return ext4_handle_dirty_metadata(handle, inode, bh);
299}
300
192static struct dx_countlimit *get_dx_countlimit(struct inode *inode, 301static struct dx_countlimit *get_dx_countlimit(struct inode *inode,
193 struct ext4_dir_entry *dirent, 302 struct ext4_dir_entry *dirent,
194 int *offset) 303 int *offset)
@@ -737,6 +846,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
737 if (!(bh = ext4_bread (NULL, dir, block, 0, &err))) 846 if (!(bh = ext4_bread (NULL, dir, block, 0, &err)))
738 return err; 847 return err;
739 848
849 if (!buffer_verified(bh) &&
850 !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data))
851 return -EIO;
852 set_buffer_verified(bh);
853
740 de = (struct ext4_dir_entry_2 *) bh->b_data; 854 de = (struct ext4_dir_entry_2 *) bh->b_data;
741 top = (struct ext4_dir_entry_2 *) ((char *) de + 855 top = (struct ext4_dir_entry_2 *) ((char *) de +
742 dir->i_sb->s_blocksize - 856 dir->i_sb->s_blocksize -
@@ -1096,6 +1210,15 @@ restart:
1096 brelse(bh); 1210 brelse(bh);
1097 goto next; 1211 goto next;
1098 } 1212 }
1213 if (!buffer_verified(bh) &&
1214 !ext4_dirent_csum_verify(dir,
1215 (struct ext4_dir_entry *)bh->b_data)) {
1216 EXT4_ERROR_INODE(dir, "checksumming directory "
1217 "block %lu", (unsigned long)block);
1218 brelse(bh);
1219 goto next;
1220 }
1221 set_buffer_verified(bh);
1099 i = search_dirblock(bh, dir, d_name, 1222 i = search_dirblock(bh, dir, d_name,
1100 block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); 1223 block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
1101 if (i == 1) { 1224 if (i == 1) {
@@ -1147,6 +1270,16 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
1147 if (!(bh = ext4_bread(NULL, dir, block, 0, err))) 1270 if (!(bh = ext4_bread(NULL, dir, block, 0, err)))
1148 goto errout; 1271 goto errout;
1149 1272
1273 if (!buffer_verified(bh) &&
1274 !ext4_dirent_csum_verify(dir,
1275 (struct ext4_dir_entry *)bh->b_data)) {
1276 EXT4_ERROR_INODE(dir, "checksumming directory "
1277 "block %lu", (unsigned long)block);
1278 brelse(bh);
1279 *err = -EIO;
1280 goto errout;
1281 }
1282 set_buffer_verified(bh);
1150 retval = search_dirblock(bh, dir, d_name, 1283 retval = search_dirblock(bh, dir, d_name,
1151 block << EXT4_BLOCK_SIZE_BITS(sb), 1284 block << EXT4_BLOCK_SIZE_BITS(sb),
1152 res_dir); 1285 res_dir);
@@ -1319,8 +1452,14 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1319 char *data1 = (*bh)->b_data, *data2; 1452 char *data1 = (*bh)->b_data, *data2;
1320 unsigned split, move, size; 1453 unsigned split, move, size;
1321 struct ext4_dir_entry_2 *de = NULL, *de2; 1454 struct ext4_dir_entry_2 *de = NULL, *de2;
1455 struct ext4_dir_entry_tail *t;
1456 int csum_size = 0;
1322 int err = 0, i; 1457 int err = 0, i;
1323 1458
1459 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
1460 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1461 csum_size = sizeof(struct ext4_dir_entry_tail);
1462
1324 bh2 = ext4_append (handle, dir, &newblock, &err); 1463 bh2 = ext4_append (handle, dir, &newblock, &err);
1325 if (!(bh2)) { 1464 if (!(bh2)) {
1326 brelse(*bh); 1465 brelse(*bh);
@@ -1367,10 +1506,20 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1367 /* Fancy dance to stay within two buffers */ 1506 /* Fancy dance to stay within two buffers */
1368 de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize); 1507 de2 = dx_move_dirents(data1, data2, map + split, count - split, blocksize);
1369 de = dx_pack_dirents(data1, blocksize); 1508 de = dx_pack_dirents(data1, blocksize);
1370 de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de, 1509 de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) -
1510 (char *) de,
1371 blocksize); 1511 blocksize);
1372 de2->rec_len = ext4_rec_len_to_disk(data2 + blocksize - (char *) de2, 1512 de2->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) -
1513 (char *) de2,
1373 blocksize); 1514 blocksize);
1515 if (csum_size) {
1516 t = EXT4_DIRENT_TAIL(data2, blocksize);
1517 initialize_dirent_tail(t, blocksize);
1518
1519 t = EXT4_DIRENT_TAIL(data1, blocksize);
1520 initialize_dirent_tail(t, blocksize);
1521 }
1522
1374 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); 1523 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1));
1375 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); 1524 dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
1376 1525
@@ -1381,7 +1530,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
1381 de = de2; 1530 de = de2;
1382 } 1531 }
1383 dx_insert_block(frame, hash2 + continued, newblock); 1532 dx_insert_block(frame, hash2 + continued, newblock);
1384 err = ext4_handle_dirty_metadata(handle, dir, bh2); 1533 err = ext4_handle_dirty_dirent_node(handle, dir, bh2);
1385 if (err) 1534 if (err)
1386 goto journal_error; 1535 goto journal_error;
1387 err = ext4_handle_dirty_dx_node(handle, dir, frame->bh); 1536 err = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
@@ -1421,11 +1570,16 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1421 unsigned short reclen; 1570 unsigned short reclen;
1422 int nlen, rlen, err; 1571 int nlen, rlen, err;
1423 char *top; 1572 char *top;
1573 int csum_size = 0;
1574
1575 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
1576 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1577 csum_size = sizeof(struct ext4_dir_entry_tail);
1424 1578
1425 reclen = EXT4_DIR_REC_LEN(namelen); 1579 reclen = EXT4_DIR_REC_LEN(namelen);
1426 if (!de) { 1580 if (!de) {
1427 de = (struct ext4_dir_entry_2 *)bh->b_data; 1581 de = (struct ext4_dir_entry_2 *)bh->b_data;
1428 top = bh->b_data + blocksize - reclen; 1582 top = bh->b_data + (blocksize - csum_size) - reclen;
1429 while ((char *) de <= top) { 1583 while ((char *) de <= top) {
1430 if (ext4_check_dir_entry(dir, NULL, de, bh, offset)) 1584 if (ext4_check_dir_entry(dir, NULL, de, bh, offset))
1431 return -EIO; 1585 return -EIO;
@@ -1481,7 +1635,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1481 dir->i_version++; 1635 dir->i_version++;
1482 ext4_mark_inode_dirty(handle, dir); 1636 ext4_mark_inode_dirty(handle, dir);
1483 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); 1637 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
1484 err = ext4_handle_dirty_metadata(handle, dir, bh); 1638 err = ext4_handle_dirty_dirent_node(handle, dir, bh);
1485 if (err) 1639 if (err)
1486 ext4_std_error(dir->i_sb, err); 1640 ext4_std_error(dir->i_sb, err);
1487 return 0; 1641 return 0;
@@ -1502,6 +1656,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1502 struct dx_frame frames[2], *frame; 1656 struct dx_frame frames[2], *frame;
1503 struct dx_entry *entries; 1657 struct dx_entry *entries;
1504 struct ext4_dir_entry_2 *de, *de2; 1658 struct ext4_dir_entry_2 *de, *de2;
1659 struct ext4_dir_entry_tail *t;
1505 char *data1, *top; 1660 char *data1, *top;
1506 unsigned len; 1661 unsigned len;
1507 int retval; 1662 int retval;
@@ -1509,6 +1664,11 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1509 struct dx_hash_info hinfo; 1664 struct dx_hash_info hinfo;
1510 ext4_lblk_t block; 1665 ext4_lblk_t block;
1511 struct fake_dirent *fde; 1666 struct fake_dirent *fde;
1667 int csum_size = 0;
1668
1669 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
1670 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1671 csum_size = sizeof(struct ext4_dir_entry_tail);
1512 1672
1513 blocksize = dir->i_sb->s_blocksize; 1673 blocksize = dir->i_sb->s_blocksize;
1514 dxtrace(printk(KERN_DEBUG "Creating index: inode %lu\n", dir->i_ino)); 1674 dxtrace(printk(KERN_DEBUG "Creating index: inode %lu\n", dir->i_ino));
@@ -1529,7 +1689,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1529 brelse(bh); 1689 brelse(bh);
1530 return -EIO; 1690 return -EIO;
1531 } 1691 }
1532 len = ((char *) root) + blocksize - (char *) de; 1692 len = ((char *) root) + (blocksize - csum_size) - (char *) de;
1533 1693
1534 /* Allocate new block for the 0th block's dirents */ 1694 /* Allocate new block for the 0th block's dirents */
1535 bh2 = ext4_append(handle, dir, &block, &retval); 1695 bh2 = ext4_append(handle, dir, &block, &retval);
@@ -1545,8 +1705,15 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1545 top = data1 + len; 1705 top = data1 + len;
1546 while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) 1706 while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top)
1547 de = de2; 1707 de = de2;
1548 de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de, 1708 de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) -
1709 (char *) de,
1549 blocksize); 1710 blocksize);
1711
1712 if (csum_size) {
1713 t = EXT4_DIRENT_TAIL(data1, blocksize);
1714 initialize_dirent_tail(t, blocksize);
1715 }
1716
1550 /* Initialize the root; the dot dirents already exist */ 1717 /* Initialize the root; the dot dirents already exist */
1551 de = (struct ext4_dir_entry_2 *) (&root->dotdot); 1718 de = (struct ext4_dir_entry_2 *) (&root->dotdot);
1552 de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2), 1719 de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2),
@@ -1572,7 +1739,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
1572 bh = bh2; 1739 bh = bh2;
1573 1740
1574 ext4_handle_dirty_dx_node(handle, dir, frame->bh); 1741 ext4_handle_dirty_dx_node(handle, dir, frame->bh);
1575 ext4_handle_dirty_metadata(handle, dir, bh); 1742 ext4_handle_dirty_dirent_node(handle, dir, bh);
1576 1743
1577 de = do_split(handle,dir, &bh, frame, &hinfo, &retval); 1744 de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
1578 if (!de) { 1745 if (!de) {
@@ -1608,11 +1775,17 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1608 struct inode *dir = dentry->d_parent->d_inode; 1775 struct inode *dir = dentry->d_parent->d_inode;
1609 struct buffer_head *bh; 1776 struct buffer_head *bh;
1610 struct ext4_dir_entry_2 *de; 1777 struct ext4_dir_entry_2 *de;
1778 struct ext4_dir_entry_tail *t;
1611 struct super_block *sb; 1779 struct super_block *sb;
1612 int retval; 1780 int retval;
1613 int dx_fallback=0; 1781 int dx_fallback=0;
1614 unsigned blocksize; 1782 unsigned blocksize;
1615 ext4_lblk_t block, blocks; 1783 ext4_lblk_t block, blocks;
1784 int csum_size = 0;
1785
1786 if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
1787 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
1788 csum_size = sizeof(struct ext4_dir_entry_tail);
1616 1789
1617 sb = dir->i_sb; 1790 sb = dir->i_sb;
1618 blocksize = sb->s_blocksize; 1791 blocksize = sb->s_blocksize;
@@ -1631,6 +1804,11 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1631 bh = ext4_bread(handle, dir, block, 0, &retval); 1804 bh = ext4_bread(handle, dir, block, 0, &retval);
1632 if(!bh) 1805 if(!bh)
1633 return retval; 1806 return retval;
1807 if (!buffer_verified(bh) &&
1808 !ext4_dirent_csum_verify(dir,
1809 (struct ext4_dir_entry *)bh->b_data))
1810 return -EIO;
1811 set_buffer_verified(bh);
1634 retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); 1812 retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
1635 if (retval != -ENOSPC) { 1813 if (retval != -ENOSPC) {
1636 brelse(bh); 1814 brelse(bh);
@@ -1647,7 +1825,13 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
1647 return retval; 1825 return retval;
1648 de = (struct ext4_dir_entry_2 *) bh->b_data; 1826 de = (struct ext4_dir_entry_2 *) bh->b_data;
1649 de->inode = 0; 1827 de->inode = 0;
1650 de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize); 1828 de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize);
1829
1830 if (csum_size) {
1831 t = EXT4_DIRENT_TAIL(bh->b_data, blocksize);
1832 initialize_dirent_tail(t, blocksize);
1833 }
1834
1651 retval = add_dirent_to_buf(handle, dentry, inode, de, bh); 1835 retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
1652 brelse(bh); 1836 brelse(bh);
1653 if (retval == 0) 1837 if (retval == 0)
@@ -1679,6 +1863,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
1679 if (!(bh = ext4_bread(handle,dir, dx_get_block(frame->at), 0, &err))) 1863 if (!(bh = ext4_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
1680 goto cleanup; 1864 goto cleanup;
1681 1865
1866 if (!buffer_verified(bh) &&
1867 !ext4_dirent_csum_verify(dir, (struct ext4_dir_entry *)bh->b_data))
1868 goto journal_error;
1869 set_buffer_verified(bh);
1870
1682 BUFFER_TRACE(bh, "get_write_access"); 1871 BUFFER_TRACE(bh, "get_write_access");
1683 err = ext4_journal_get_write_access(handle, bh); 1872 err = ext4_journal_get_write_access(handle, bh);
1684 if (err) 1873 if (err)
@@ -1804,12 +1993,17 @@ static int ext4_delete_entry(handle_t *handle,
1804{ 1993{
1805 struct ext4_dir_entry_2 *de, *pde; 1994 struct ext4_dir_entry_2 *de, *pde;
1806 unsigned int blocksize = dir->i_sb->s_blocksize; 1995 unsigned int blocksize = dir->i_sb->s_blocksize;
1996 int csum_size = 0;
1807 int i, err; 1997 int i, err;
1808 1998
1999 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
2000 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
2001 csum_size = sizeof(struct ext4_dir_entry_tail);
2002
1809 i = 0; 2003 i = 0;
1810 pde = NULL; 2004 pde = NULL;
1811 de = (struct ext4_dir_entry_2 *) bh->b_data; 2005 de = (struct ext4_dir_entry_2 *) bh->b_data;
1812 while (i < bh->b_size) { 2006 while (i < bh->b_size - csum_size) {
1813 if (ext4_check_dir_entry(dir, NULL, de, bh, i)) 2007 if (ext4_check_dir_entry(dir, NULL, de, bh, i))
1814 return -EIO; 2008 return -EIO;
1815 if (de == de_del) { 2009 if (de == de_del) {
@@ -1830,7 +2024,7 @@ static int ext4_delete_entry(handle_t *handle,
1830 de->inode = 0; 2024 de->inode = 0;
1831 dir->i_version++; 2025 dir->i_version++;
1832 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); 2026 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
1833 err = ext4_handle_dirty_metadata(handle, dir, bh); 2027 err = ext4_handle_dirty_dirent_node(handle, dir, bh);
1834 if (unlikely(err)) { 2028 if (unlikely(err)) {
1835 ext4_std_error(dir->i_sb, err); 2029 ext4_std_error(dir->i_sb, err);
1836 return err; 2030 return err;
@@ -1972,9 +2166,15 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1972 struct inode *inode; 2166 struct inode *inode;
1973 struct buffer_head *dir_block = NULL; 2167 struct buffer_head *dir_block = NULL;
1974 struct ext4_dir_entry_2 *de; 2168 struct ext4_dir_entry_2 *de;
2169 struct ext4_dir_entry_tail *t;
1975 unsigned int blocksize = dir->i_sb->s_blocksize; 2170 unsigned int blocksize = dir->i_sb->s_blocksize;
2171 int csum_size = 0;
1976 int err, retries = 0; 2172 int err, retries = 0;
1977 2173
2174 if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
2175 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
2176 csum_size = sizeof(struct ext4_dir_entry_tail);
2177
1978 if (EXT4_DIR_LINK_MAX(dir)) 2178 if (EXT4_DIR_LINK_MAX(dir))
1979 return -EMLINK; 2179 return -EMLINK;
1980 2180
@@ -2015,16 +2215,24 @@ retry:
2015 ext4_set_de_type(dir->i_sb, de, S_IFDIR); 2215 ext4_set_de_type(dir->i_sb, de, S_IFDIR);
2016 de = ext4_next_entry(de, blocksize); 2216 de = ext4_next_entry(de, blocksize);
2017 de->inode = cpu_to_le32(dir->i_ino); 2217 de->inode = cpu_to_le32(dir->i_ino);
2018 de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(1), 2218 de->rec_len = ext4_rec_len_to_disk(blocksize -
2219 (csum_size + EXT4_DIR_REC_LEN(1)),
2019 blocksize); 2220 blocksize);
2020 de->name_len = 2; 2221 de->name_len = 2;
2021 strcpy(de->name, ".."); 2222 strcpy(de->name, "..");
2022 ext4_set_de_type(dir->i_sb, de, S_IFDIR); 2223 ext4_set_de_type(dir->i_sb, de, S_IFDIR);
2023 set_nlink(inode, 2); 2224 set_nlink(inode, 2);
2225
2226 if (csum_size) {
2227 t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize);
2228 initialize_dirent_tail(t, blocksize);
2229 }
2230
2024 BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); 2231 BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
2025 err = ext4_handle_dirty_metadata(handle, inode, dir_block); 2232 err = ext4_handle_dirty_dirent_node(handle, inode, dir_block);
2026 if (err) 2233 if (err)
2027 goto out_clear_inode; 2234 goto out_clear_inode;
2235 set_buffer_verified(dir_block);
2028 err = ext4_mark_inode_dirty(handle, inode); 2236 err = ext4_mark_inode_dirty(handle, inode);
2029 if (!err) 2237 if (!err)
2030 err = ext4_add_entry(handle, dentry, inode); 2238 err = ext4_add_entry(handle, dentry, inode);
@@ -2074,6 +2282,14 @@ static int empty_dir(struct inode *inode)
2074 inode->i_ino); 2282 inode->i_ino);
2075 return 1; 2283 return 1;
2076 } 2284 }
2285 if (!buffer_verified(bh) &&
2286 !ext4_dirent_csum_verify(inode,
2287 (struct ext4_dir_entry *)bh->b_data)) {
2288 EXT4_ERROR_INODE(inode, "checksum error reading directory "
2289 "lblock 0");
2290 return -EIO;
2291 }
2292 set_buffer_verified(bh);
2077 de = (struct ext4_dir_entry_2 *) bh->b_data; 2293 de = (struct ext4_dir_entry_2 *) bh->b_data;
2078 de1 = ext4_next_entry(de, sb->s_blocksize); 2294 de1 = ext4_next_entry(de, sb->s_blocksize);
2079 if (le32_to_cpu(de->inode) != inode->i_ino || 2295 if (le32_to_cpu(de->inode) != inode->i_ino ||
@@ -2105,6 +2321,14 @@ static int empty_dir(struct inode *inode)
2105 offset += sb->s_blocksize; 2321 offset += sb->s_blocksize;
2106 continue; 2322 continue;
2107 } 2323 }
2324 if (!buffer_verified(bh) &&
2325 !ext4_dirent_csum_verify(inode,
2326 (struct ext4_dir_entry *)bh->b_data)) {
2327 EXT4_ERROR_INODE(inode, "checksum error "
2328 "reading directory lblock 0");
2329 return -EIO;
2330 }
2331 set_buffer_verified(bh);
2108 de = (struct ext4_dir_entry_2 *) bh->b_data; 2332 de = (struct ext4_dir_entry_2 *) bh->b_data;
2109 } 2333 }
2110 if (ext4_check_dir_entry(inode, NULL, de, bh, offset)) { 2334 if (ext4_check_dir_entry(inode, NULL, de, bh, offset)) {
@@ -2605,6 +2829,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
2605 dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval); 2829 dir_bh = ext4_bread(handle, old_inode, 0, 0, &retval);
2606 if (!dir_bh) 2830 if (!dir_bh)
2607 goto end_rename; 2831 goto end_rename;
2832 if (!buffer_verified(dir_bh) &&
2833 !ext4_dirent_csum_verify(old_inode,
2834 (struct ext4_dir_entry *)dir_bh->b_data))
2835 goto end_rename;
2836 set_buffer_verified(dir_bh);
2608 if (le32_to_cpu(PARENT_INO(dir_bh->b_data, 2837 if (le32_to_cpu(PARENT_INO(dir_bh->b_data,
2609 old_dir->i_sb->s_blocksize)) != old_dir->i_ino) 2838 old_dir->i_sb->s_blocksize)) != old_dir->i_ino)
2610 goto end_rename; 2839 goto end_rename;
@@ -2635,7 +2864,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
2635 ext4_current_time(new_dir); 2864 ext4_current_time(new_dir);
2636 ext4_mark_inode_dirty(handle, new_dir); 2865 ext4_mark_inode_dirty(handle, new_dir);
2637 BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata"); 2866 BUFFER_TRACE(new_bh, "call ext4_handle_dirty_metadata");
2638 retval = ext4_handle_dirty_metadata(handle, new_dir, new_bh); 2867 retval = ext4_handle_dirty_dirent_node(handle, new_dir, new_bh);
2639 if (unlikely(retval)) { 2868 if (unlikely(retval)) {
2640 ext4_std_error(new_dir->i_sb, retval); 2869 ext4_std_error(new_dir->i_sb, retval);
2641 goto end_rename; 2870 goto end_rename;
@@ -2689,7 +2918,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
2689 PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = 2918 PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) =
2690 cpu_to_le32(new_dir->i_ino); 2919 cpu_to_le32(new_dir->i_ino);
2691 BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); 2920 BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata");
2692 retval = ext4_handle_dirty_metadata(handle, old_inode, dir_bh); 2921 retval = ext4_handle_dirty_dirent_node(handle, old_inode,
2922 dir_bh);
2693 if (retval) { 2923 if (retval) {
2694 ext4_std_error(old_dir->i_sb, retval); 2924 ext4_std_error(old_dir->i_sb, retval);
2695 goto end_rename; 2925 goto end_rename;