aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/inode.c')
-rw-r--r--fs/ocfs2/inode.c228
1 files changed, 219 insertions, 9 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 36294446d960..12f4a9e9800f 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -53,6 +53,7 @@
53#include "xattr.h" 53#include "xattr.h"
54#include "refcounttree.h" 54#include "refcounttree.h"
55#include "ocfs2_trace.h" 55#include "ocfs2_trace.h"
56#include "filecheck.h"
56 57
57#include "buffer_head_io.h" 58#include "buffer_head_io.h"
58 59
@@ -74,6 +75,14 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
74 struct inode *inode, 75 struct inode *inode,
75 struct buffer_head *fe_bh); 76 struct buffer_head *fe_bh);
76 77
78static int ocfs2_filecheck_read_inode_block_full(struct inode *inode,
79 struct buffer_head **bh,
80 int flags, int type);
81static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
82 struct buffer_head *bh);
83static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
84 struct buffer_head *bh);
85
77void ocfs2_set_inode_flags(struct inode *inode) 86void ocfs2_set_inode_flags(struct inode *inode)
78{ 87{
79 unsigned int flags = OCFS2_I(inode)->ip_attr; 88 unsigned int flags = OCFS2_I(inode)->ip_attr;
@@ -127,6 +136,7 @@ struct inode *ocfs2_ilookup(struct super_block *sb, u64 blkno)
127struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, 136struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
128 int sysfile_type) 137 int sysfile_type)
129{ 138{
139 int rc = 0;
130 struct inode *inode = NULL; 140 struct inode *inode = NULL;
131 struct super_block *sb = osb->sb; 141 struct super_block *sb = osb->sb;
132 struct ocfs2_find_inode_args args; 142 struct ocfs2_find_inode_args args;
@@ -161,12 +171,17 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,
161 } 171 }
162 trace_ocfs2_iget5_locked(inode->i_state); 172 trace_ocfs2_iget5_locked(inode->i_state);
163 if (inode->i_state & I_NEW) { 173 if (inode->i_state & I_NEW) {
164 ocfs2_read_locked_inode(inode, &args); 174 rc = ocfs2_read_locked_inode(inode, &args);
165 unlock_new_inode(inode); 175 unlock_new_inode(inode);
166 } 176 }
167 if (is_bad_inode(inode)) { 177 if (is_bad_inode(inode)) {
168 iput(inode); 178 iput(inode);
169 inode = ERR_PTR(-ESTALE); 179 if ((flags & OCFS2_FI_FLAG_FILECHECK_CHK) ||
180 (flags & OCFS2_FI_FLAG_FILECHECK_FIX))
181 /* Return OCFS2_FILECHECK_ERR_XXX related errno */
182 inode = ERR_PTR(rc);
183 else
184 inode = ERR_PTR(-ESTALE);
170 goto bail; 185 goto bail;
171 } 186 }
172 187
@@ -410,7 +425,7 @@ static int ocfs2_read_locked_inode(struct inode *inode,
410 struct ocfs2_super *osb; 425 struct ocfs2_super *osb;
411 struct ocfs2_dinode *fe; 426 struct ocfs2_dinode *fe;
412 struct buffer_head *bh = NULL; 427 struct buffer_head *bh = NULL;
413 int status, can_lock; 428 int status, can_lock, lock_level = 0;
414 u32 generation = 0; 429 u32 generation = 0;
415 430
416 status = -EINVAL; 431 status = -EINVAL;
@@ -478,7 +493,7 @@ static int ocfs2_read_locked_inode(struct inode *inode,
478 mlog_errno(status); 493 mlog_errno(status);
479 return status; 494 return status;
480 } 495 }
481 status = ocfs2_inode_lock(inode, NULL, 0); 496 status = ocfs2_inode_lock(inode, NULL, lock_level);
482 if (status) { 497 if (status) {
483 make_bad_inode(inode); 498 make_bad_inode(inode);
484 mlog_errno(status); 499 mlog_errno(status);
@@ -495,16 +510,32 @@ static int ocfs2_read_locked_inode(struct inode *inode,
495 } 510 }
496 511
497 if (can_lock) { 512 if (can_lock) {
498 status = ocfs2_read_inode_block_full(inode, &bh, 513 if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK)
499 OCFS2_BH_IGNORE_CACHE); 514 status = ocfs2_filecheck_read_inode_block_full(inode,
515 &bh, OCFS2_BH_IGNORE_CACHE, 0);
516 else if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX)
517 status = ocfs2_filecheck_read_inode_block_full(inode,
518 &bh, OCFS2_BH_IGNORE_CACHE, 1);
519 else
520 status = ocfs2_read_inode_block_full(inode,
521 &bh, OCFS2_BH_IGNORE_CACHE);
500 } else { 522 } else {
501 status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh); 523 status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
502 /* 524 /*
503 * If buffer is in jbd, then its checksum may not have been 525 * If buffer is in jbd, then its checksum may not have been
504 * computed as yet. 526 * computed as yet.
505 */ 527 */
506 if (!status && !buffer_jbd(bh)) 528 if (!status && !buffer_jbd(bh)) {
507 status = ocfs2_validate_inode_block(osb->sb, bh); 529 if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK)
530 status = ocfs2_filecheck_validate_inode_block(
531 osb->sb, bh);
532 else if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX)
533 status = ocfs2_filecheck_repair_inode_block(
534 osb->sb, bh);
535 else
536 status = ocfs2_validate_inode_block(
537 osb->sb, bh);
538 }
508 } 539 }
509 if (status < 0) { 540 if (status < 0) {
510 mlog_errno(status); 541 mlog_errno(status);
@@ -532,11 +563,24 @@ static int ocfs2_read_locked_inode(struct inode *inode,
532 563
533 BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno)); 564 BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
534 565
566 if (buffer_dirty(bh) && !buffer_jbd(bh)) {
567 if (can_lock) {
568 ocfs2_inode_unlock(inode, lock_level);
569 lock_level = 1;
570 ocfs2_inode_lock(inode, NULL, lock_level);
571 }
572 status = ocfs2_write_block(osb, bh, INODE_CACHE(inode));
573 if (status < 0) {
574 mlog_errno(status);
575 goto bail;
576 }
577 }
578
535 status = 0; 579 status = 0;
536 580
537bail: 581bail:
538 if (can_lock) 582 if (can_lock)
539 ocfs2_inode_unlock(inode, 0); 583 ocfs2_inode_unlock(inode, lock_level);
540 584
541 if (status < 0) 585 if (status < 0)
542 make_bad_inode(inode); 586 make_bad_inode(inode);
@@ -1126,6 +1170,9 @@ static void ocfs2_clear_inode(struct inode *inode)
1126 mlog_bug_on_msg(!list_empty(&oi->ip_io_markers), 1170 mlog_bug_on_msg(!list_empty(&oi->ip_io_markers),
1127 "Clear inode of %llu, inode has io markers\n", 1171 "Clear inode of %llu, inode has io markers\n",
1128 (unsigned long long)oi->ip_blkno); 1172 (unsigned long long)oi->ip_blkno);
1173 mlog_bug_on_msg(!list_empty(&oi->ip_unwritten_list),
1174 "Clear inode of %llu, inode has unwritten extents\n",
1175 (unsigned long long)oi->ip_blkno);
1129 1176
1130 ocfs2_extent_map_trunc(inode, 0); 1177 ocfs2_extent_map_trunc(inode, 0);
1131 1178
@@ -1397,6 +1444,169 @@ bail:
1397 return rc; 1444 return rc;
1398} 1445}
1399 1446
1447static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
1448 struct buffer_head *bh)
1449{
1450 int rc = 0;
1451 struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
1452
1453 trace_ocfs2_filecheck_validate_inode_block(
1454 (unsigned long long)bh->b_blocknr);
1455
1456 BUG_ON(!buffer_uptodate(bh));
1457
1458 /*
1459 * Call ocfs2_validate_meta_ecc() first since it has ecc repair
1460 * function, but we should not return error immediately when ecc
1461 * validation fails, because the reason is quite likely the invalid
1462 * inode number inputed.
1463 */
1464 rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check);
1465 if (rc) {
1466 mlog(ML_ERROR,
1467 "Filecheck: checksum failed for dinode %llu\n",
1468 (unsigned long long)bh->b_blocknr);
1469 rc = -OCFS2_FILECHECK_ERR_BLOCKECC;
1470 }
1471
1472 if (!OCFS2_IS_VALID_DINODE(di)) {
1473 mlog(ML_ERROR,
1474 "Filecheck: invalid dinode #%llu: signature = %.*s\n",
1475 (unsigned long long)bh->b_blocknr, 7, di->i_signature);
1476 rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
1477 goto bail;
1478 } else if (rc)
1479 goto bail;
1480
1481 if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
1482 mlog(ML_ERROR,
1483 "Filecheck: invalid dinode #%llu: i_blkno is %llu\n",
1484 (unsigned long long)bh->b_blocknr,
1485 (unsigned long long)le64_to_cpu(di->i_blkno));
1486 rc = -OCFS2_FILECHECK_ERR_BLOCKNO;
1487 goto bail;
1488 }
1489
1490 if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
1491 mlog(ML_ERROR,
1492 "Filecheck: invalid dinode #%llu: OCFS2_VALID_FL "
1493 "not set\n",
1494 (unsigned long long)bh->b_blocknr);
1495 rc = -OCFS2_FILECHECK_ERR_VALIDFLAG;
1496 goto bail;
1497 }
1498
1499 if (le32_to_cpu(di->i_fs_generation) !=
1500 OCFS2_SB(sb)->fs_generation) {
1501 mlog(ML_ERROR,
1502 "Filecheck: invalid dinode #%llu: fs_generation is %u\n",
1503 (unsigned long long)bh->b_blocknr,
1504 le32_to_cpu(di->i_fs_generation));
1505 rc = -OCFS2_FILECHECK_ERR_GENERATION;
1506 goto bail;
1507 }
1508
1509bail:
1510 return rc;
1511}
1512
1513static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
1514 struct buffer_head *bh)
1515{
1516 int changed = 0;
1517 struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
1518
1519 if (!ocfs2_filecheck_validate_inode_block(sb, bh))
1520 return 0;
1521
1522 trace_ocfs2_filecheck_repair_inode_block(
1523 (unsigned long long)bh->b_blocknr);
1524
1525 if (ocfs2_is_hard_readonly(OCFS2_SB(sb)) ||
1526 ocfs2_is_soft_readonly(OCFS2_SB(sb))) {
1527 mlog(ML_ERROR,
1528 "Filecheck: cannot repair dinode #%llu "
1529 "on readonly filesystem\n",
1530 (unsigned long long)bh->b_blocknr);
1531 return -OCFS2_FILECHECK_ERR_READONLY;
1532 }
1533
1534 if (buffer_jbd(bh)) {
1535 mlog(ML_ERROR,
1536 "Filecheck: cannot repair dinode #%llu, "
1537 "its buffer is in jbd\n",
1538 (unsigned long long)bh->b_blocknr);
1539 return -OCFS2_FILECHECK_ERR_INJBD;
1540 }
1541
1542 if (!OCFS2_IS_VALID_DINODE(di)) {
1543 /* Cannot fix invalid inode block */
1544 return -OCFS2_FILECHECK_ERR_INVALIDINO;
1545 }
1546
1547 if (!(di->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
1548 /* Cannot just add VALID_FL flag back as a fix,
1549 * need more things to check here.
1550 */
1551 return -OCFS2_FILECHECK_ERR_VALIDFLAG;
1552 }
1553
1554 if (le64_to_cpu(di->i_blkno) != bh->b_blocknr) {
1555 di->i_blkno = cpu_to_le64(bh->b_blocknr);
1556 changed = 1;
1557 mlog(ML_ERROR,
1558 "Filecheck: reset dinode #%llu: i_blkno to %llu\n",
1559 (unsigned long long)bh->b_blocknr,
1560 (unsigned long long)le64_to_cpu(di->i_blkno));
1561 }
1562
1563 if (le32_to_cpu(di->i_fs_generation) !=
1564 OCFS2_SB(sb)->fs_generation) {
1565 di->i_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
1566 changed = 1;
1567 mlog(ML_ERROR,
1568 "Filecheck: reset dinode #%llu: fs_generation to %u\n",
1569 (unsigned long long)bh->b_blocknr,
1570 le32_to_cpu(di->i_fs_generation));
1571 }
1572
1573 if (changed || ocfs2_validate_meta_ecc(sb, bh->b_data, &di->i_check)) {
1574 ocfs2_compute_meta_ecc(sb, bh->b_data, &di->i_check);
1575 mark_buffer_dirty(bh);
1576 mlog(ML_ERROR,
1577 "Filecheck: reset dinode #%llu: compute meta ecc\n",
1578 (unsigned long long)bh->b_blocknr);
1579 }
1580
1581 return 0;
1582}
1583
1584static int
1585ocfs2_filecheck_read_inode_block_full(struct inode *inode,
1586 struct buffer_head **bh,
1587 int flags, int type)
1588{
1589 int rc;
1590 struct buffer_head *tmp = *bh;
1591
1592 if (!type) /* Check inode block */
1593 rc = ocfs2_read_blocks(INODE_CACHE(inode),
1594 OCFS2_I(inode)->ip_blkno,
1595 1, &tmp, flags,
1596 ocfs2_filecheck_validate_inode_block);
1597 else /* Repair inode block */
1598 rc = ocfs2_read_blocks(INODE_CACHE(inode),
1599 OCFS2_I(inode)->ip_blkno,
1600 1, &tmp, flags,
1601 ocfs2_filecheck_repair_inode_block);
1602
1603 /* If ocfs2_read_blocks() got us a new bh, pass it up. */
1604 if (!rc && !*bh)
1605 *bh = tmp;
1606
1607 return rc;
1608}
1609
1400int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh, 1610int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
1401 int flags) 1611 int flags)
1402{ 1612{