diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 400 |
1 files changed, 190 insertions, 210 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 22e6efdc17ea..6f3f5fa37acf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -24,15 +24,11 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_error.h" | 28 | #include "xfs_error.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
38 | #include "xfs_inode_item.h" | 34 | #include "xfs_inode_item.h" |
@@ -56,33 +52,61 @@ STATIC void xlog_recover_check_summary(xlog_t *); | |||
56 | #define xlog_recover_check_summary(log) | 52 | #define xlog_recover_check_summary(log) |
57 | #endif | 53 | #endif |
58 | 54 | ||
59 | |||
60 | /* | 55 | /* |
61 | * Sector aligned buffer routines for buffer create/read/write/access | 56 | * Sector aligned buffer routines for buffer create/read/write/access |
62 | */ | 57 | */ |
63 | 58 | ||
64 | #define XLOG_SECTOR_ROUNDUP_BBCOUNT(log, bbs) \ | 59 | /* |
65 | ( ((log)->l_sectbb_mask && (bbs & (log)->l_sectbb_mask)) ? \ | 60 | * Verify the given count of basic blocks is valid number of blocks |
66 | ((bbs + (log)->l_sectbb_mask + 1) & ~(log)->l_sectbb_mask) : (bbs) ) | 61 | * to specify for an operation involving the given XFS log buffer. |
67 | #define XLOG_SECTOR_ROUNDDOWN_BLKNO(log, bno) ((bno) & ~(log)->l_sectbb_mask) | 62 | * Returns nonzero if the count is valid, 0 otherwise. |
63 | */ | ||
68 | 64 | ||
65 | static inline int | ||
66 | xlog_buf_bbcount_valid( | ||
67 | xlog_t *log, | ||
68 | int bbcount) | ||
69 | { | ||
70 | return bbcount > 0 && bbcount <= log->l_logBBsize; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Allocate a buffer to hold log data. The buffer needs to be able | ||
75 | * to map to a range of nbblks basic blocks at any valid (basic | ||
76 | * block) offset within the log. | ||
77 | */ | ||
69 | STATIC xfs_buf_t * | 78 | STATIC xfs_buf_t * |
70 | xlog_get_bp( | 79 | xlog_get_bp( |
71 | xlog_t *log, | 80 | xlog_t *log, |
72 | int nbblks) | 81 | int nbblks) |
73 | { | 82 | { |
74 | if (nbblks <= 0 || nbblks > log->l_logBBsize) { | 83 | if (!xlog_buf_bbcount_valid(log, nbblks)) { |
75 | xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); | 84 | xlog_warn("XFS: Invalid block length (0x%x) given for buffer", |
76 | XFS_ERROR_REPORT("xlog_get_bp(1)", | 85 | nbblks); |
77 | XFS_ERRLEVEL_HIGH, log->l_mp); | 86 | XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); |
78 | return NULL; | 87 | return NULL; |
79 | } | 88 | } |
80 | 89 | ||
81 | if (log->l_sectbb_log) { | 90 | /* |
82 | if (nbblks > 1) | 91 | * We do log I/O in units of log sectors (a power-of-2 |
83 | nbblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); | 92 | * multiple of the basic block size), so we round up the |
84 | nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); | 93 | * requested size to acommodate the basic blocks required |
85 | } | 94 | * for complete log sectors. |
95 | * | ||
96 | * In addition, the buffer may be used for a non-sector- | ||
97 | * aligned block offset, in which case an I/O of the | ||
98 | * requested size could extend beyond the end of the | ||
99 | * buffer. If the requested size is only 1 basic block it | ||
100 | * will never straddle a sector boundary, so this won't be | ||
101 | * an issue. Nor will this be a problem if the log I/O is | ||
102 | * done in basic blocks (sector size 1). But otherwise we | ||
103 | * extend the buffer by one extra log sector to ensure | ||
104 | * there's space to accomodate this possiblility. | ||
105 | */ | ||
106 | if (nbblks > 1 && log->l_sectBBsize > 1) | ||
107 | nbblks += log->l_sectBBsize; | ||
108 | nbblks = round_up(nbblks, log->l_sectBBsize); | ||
109 | |||
86 | return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp); | 110 | return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp); |
87 | } | 111 | } |
88 | 112 | ||
@@ -93,6 +117,10 @@ xlog_put_bp( | |||
93 | xfs_buf_free(bp); | 117 | xfs_buf_free(bp); |
94 | } | 118 | } |
95 | 119 | ||
120 | /* | ||
121 | * Return the address of the start of the given block number's data | ||
122 | * in a log buffer. The buffer covers a log sector-aligned region. | ||
123 | */ | ||
96 | STATIC xfs_caddr_t | 124 | STATIC xfs_caddr_t |
97 | xlog_align( | 125 | xlog_align( |
98 | xlog_t *log, | 126 | xlog_t *log, |
@@ -100,15 +128,10 @@ xlog_align( | |||
100 | int nbblks, | 128 | int nbblks, |
101 | xfs_buf_t *bp) | 129 | xfs_buf_t *bp) |
102 | { | 130 | { |
103 | xfs_caddr_t ptr; | 131 | xfs_daddr_t offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1); |
104 | 132 | ||
105 | if (!log->l_sectbb_log) | 133 | ASSERT(BBTOB(offset + nbblks) <= XFS_BUF_SIZE(bp)); |
106 | return XFS_BUF_PTR(bp); | 134 | return XFS_BUF_PTR(bp) + BBTOB(offset); |
107 | |||
108 | ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask); | ||
109 | ASSERT(XFS_BUF_SIZE(bp) >= | ||
110 | BBTOB(nbblks + (blk_no & log->l_sectbb_mask))); | ||
111 | return ptr; | ||
112 | } | 135 | } |
113 | 136 | ||
114 | 137 | ||
@@ -124,21 +147,18 @@ xlog_bread_noalign( | |||
124 | { | 147 | { |
125 | int error; | 148 | int error; |
126 | 149 | ||
127 | if (nbblks <= 0 || nbblks > log->l_logBBsize) { | 150 | if (!xlog_buf_bbcount_valid(log, nbblks)) { |
128 | xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); | 151 | xlog_warn("XFS: Invalid block length (0x%x) given for buffer", |
129 | XFS_ERROR_REPORT("xlog_bread(1)", | 152 | nbblks); |
130 | XFS_ERRLEVEL_HIGH, log->l_mp); | 153 | XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); |
131 | return EFSCORRUPTED; | 154 | return EFSCORRUPTED; |
132 | } | 155 | } |
133 | 156 | ||
134 | if (log->l_sectbb_log) { | 157 | blk_no = round_down(blk_no, log->l_sectBBsize); |
135 | blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); | 158 | nbblks = round_up(nbblks, log->l_sectBBsize); |
136 | nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); | ||
137 | } | ||
138 | 159 | ||
139 | ASSERT(nbblks > 0); | 160 | ASSERT(nbblks > 0); |
140 | ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp)); | 161 | ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp)); |
141 | ASSERT(bp); | ||
142 | 162 | ||
143 | XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); | 163 | XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); |
144 | XFS_BUF_READ(bp); | 164 | XFS_BUF_READ(bp); |
@@ -186,17 +206,15 @@ xlog_bwrite( | |||
186 | { | 206 | { |
187 | int error; | 207 | int error; |
188 | 208 | ||
189 | if (nbblks <= 0 || nbblks > log->l_logBBsize) { | 209 | if (!xlog_buf_bbcount_valid(log, nbblks)) { |
190 | xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); | 210 | xlog_warn("XFS: Invalid block length (0x%x) given for buffer", |
191 | XFS_ERROR_REPORT("xlog_bwrite(1)", | 211 | nbblks); |
192 | XFS_ERRLEVEL_HIGH, log->l_mp); | 212 | XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); |
193 | return EFSCORRUPTED; | 213 | return EFSCORRUPTED; |
194 | } | 214 | } |
195 | 215 | ||
196 | if (log->l_sectbb_log) { | 216 | blk_no = round_down(blk_no, log->l_sectBBsize); |
197 | blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); | 217 | nbblks = round_up(nbblks, log->l_sectBBsize); |
198 | nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); | ||
199 | } | ||
200 | 218 | ||
201 | ASSERT(nbblks > 0); | 219 | ASSERT(nbblks > 0); |
202 | ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp)); | 220 | ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp)); |
@@ -327,39 +345,38 @@ xlog_find_cycle_start( | |||
327 | { | 345 | { |
328 | xfs_caddr_t offset; | 346 | xfs_caddr_t offset; |
329 | xfs_daddr_t mid_blk; | 347 | xfs_daddr_t mid_blk; |
348 | xfs_daddr_t end_blk; | ||
330 | uint mid_cycle; | 349 | uint mid_cycle; |
331 | int error; | 350 | int error; |
332 | 351 | ||
333 | mid_blk = BLK_AVG(first_blk, *last_blk); | 352 | end_blk = *last_blk; |
334 | while (mid_blk != first_blk && mid_blk != *last_blk) { | 353 | mid_blk = BLK_AVG(first_blk, end_blk); |
354 | while (mid_blk != first_blk && mid_blk != end_blk) { | ||
335 | error = xlog_bread(log, mid_blk, 1, bp, &offset); | 355 | error = xlog_bread(log, mid_blk, 1, bp, &offset); |
336 | if (error) | 356 | if (error) |
337 | return error; | 357 | return error; |
338 | mid_cycle = xlog_get_cycle(offset); | 358 | mid_cycle = xlog_get_cycle(offset); |
339 | if (mid_cycle == cycle) { | 359 | if (mid_cycle == cycle) |
340 | *last_blk = mid_blk; | 360 | end_blk = mid_blk; /* last_half_cycle == mid_cycle */ |
341 | /* last_half_cycle == mid_cycle */ | 361 | else |
342 | } else { | 362 | first_blk = mid_blk; /* first_half_cycle == mid_cycle */ |
343 | first_blk = mid_blk; | 363 | mid_blk = BLK_AVG(first_blk, end_blk); |
344 | /* first_half_cycle == mid_cycle */ | ||
345 | } | ||
346 | mid_blk = BLK_AVG(first_blk, *last_blk); | ||
347 | } | 364 | } |
348 | ASSERT((mid_blk == first_blk && mid_blk+1 == *last_blk) || | 365 | ASSERT((mid_blk == first_blk && mid_blk+1 == end_blk) || |
349 | (mid_blk == *last_blk && mid_blk-1 == first_blk)); | 366 | (mid_blk == end_blk && mid_blk-1 == first_blk)); |
367 | |||
368 | *last_blk = end_blk; | ||
350 | 369 | ||
351 | return 0; | 370 | return 0; |
352 | } | 371 | } |
353 | 372 | ||
354 | /* | 373 | /* |
355 | * Check that the range of blocks does not contain the cycle number | 374 | * Check that a range of blocks does not contain stop_on_cycle_no. |
356 | * given. The scan needs to occur from front to back and the ptr into the | 375 | * Fill in *new_blk with the block offset where such a block is |
357 | * region must be updated since a later routine will need to perform another | 376 | * found, or with -1 (an invalid block number) if there is no such |
358 | * test. If the region is completely good, we end up returning the same | 377 | * block in the range. The scan needs to occur from front to back |
359 | * last block number. | 378 | * and the pointer into the region must be updated since a later |
360 | * | 379 | * routine will need to perform another test. |
361 | * Set blkno to -1 if we encounter no errors. This is an invalid block number | ||
362 | * since we don't ever expect logs to get this large. | ||
363 | */ | 380 | */ |
364 | STATIC int | 381 | STATIC int |
365 | xlog_find_verify_cycle( | 382 | xlog_find_verify_cycle( |
@@ -376,12 +393,16 @@ xlog_find_verify_cycle( | |||
376 | xfs_caddr_t buf = NULL; | 393 | xfs_caddr_t buf = NULL; |
377 | int error = 0; | 394 | int error = 0; |
378 | 395 | ||
396 | /* | ||
397 | * Greedily allocate a buffer big enough to handle the full | ||
398 | * range of basic blocks we'll be examining. If that fails, | ||
399 | * try a smaller size. We need to be able to read at least | ||
400 | * a log sector, or we're out of luck. | ||
401 | */ | ||
379 | bufblks = 1 << ffs(nbblks); | 402 | bufblks = 1 << ffs(nbblks); |
380 | |||
381 | while (!(bp = xlog_get_bp(log, bufblks))) { | 403 | while (!(bp = xlog_get_bp(log, bufblks))) { |
382 | /* can't get enough memory to do everything in one big buffer */ | ||
383 | bufblks >>= 1; | 404 | bufblks >>= 1; |
384 | if (bufblks <= log->l_sectbb_log) | 405 | if (bufblks < log->l_sectBBsize) |
385 | return ENOMEM; | 406 | return ENOMEM; |
386 | } | 407 | } |
387 | 408 | ||
@@ -629,7 +650,7 @@ xlog_find_head( | |||
629 | * In this case we want to find the first block with cycle | 650 | * In this case we want to find the first block with cycle |
630 | * number matching last_half_cycle. We expect the log to be | 651 | * number matching last_half_cycle. We expect the log to be |
631 | * some variation on | 652 | * some variation on |
632 | * x + 1 ... | x ... | 653 | * x + 1 ... | x ... | x |
633 | * The first block with cycle number x (last_half_cycle) will | 654 | * The first block with cycle number x (last_half_cycle) will |
634 | * be where the new head belongs. First we do a binary search | 655 | * be where the new head belongs. First we do a binary search |
635 | * for the first occurrence of last_half_cycle. The binary | 656 | * for the first occurrence of last_half_cycle. The binary |
@@ -639,11 +660,13 @@ xlog_find_head( | |||
639 | * the log, then we look for occurrences of last_half_cycle - 1 | 660 | * the log, then we look for occurrences of last_half_cycle - 1 |
640 | * at the end of the log. The cases we're looking for look | 661 | * at the end of the log. The cases we're looking for look |
641 | * like | 662 | * like |
642 | * x + 1 ... | x | x + 1 | x ... | 663 | * v binary search stopped here |
643 | * ^ binary search stopped here | 664 | * x + 1 ... | x | x + 1 | x ... | x |
665 | * ^ but we want to locate this spot | ||
644 | * or | 666 | * or |
645 | * x + 1 ... | x ... | x - 1 | x | ||
646 | * <---------> less than scan distance | 667 | * <---------> less than scan distance |
668 | * x + 1 ... | x ... | x - 1 | x | ||
669 | * ^ we want to locate this spot | ||
647 | */ | 670 | */ |
648 | stop_on_cycle = last_half_cycle; | 671 | stop_on_cycle = last_half_cycle; |
649 | if ((error = xlog_find_cycle_start(log, bp, first_blk, | 672 | if ((error = xlog_find_cycle_start(log, bp, first_blk, |
@@ -699,16 +722,16 @@ xlog_find_head( | |||
699 | * certainly not the head of the log. By searching for | 722 | * certainly not the head of the log. By searching for |
700 | * last_half_cycle-1 we accomplish that. | 723 | * last_half_cycle-1 we accomplish that. |
701 | */ | 724 | */ |
702 | start_blk = log_bbnum - num_scan_bblks + head_blk; | ||
703 | ASSERT(head_blk <= INT_MAX && | 725 | ASSERT(head_blk <= INT_MAX && |
704 | (xfs_daddr_t) num_scan_bblks - head_blk >= 0); | 726 | (xfs_daddr_t) num_scan_bblks >= head_blk); |
727 | start_blk = log_bbnum - (num_scan_bblks - head_blk); | ||
705 | if ((error = xlog_find_verify_cycle(log, start_blk, | 728 | if ((error = xlog_find_verify_cycle(log, start_blk, |
706 | num_scan_bblks - (int)head_blk, | 729 | num_scan_bblks - (int)head_blk, |
707 | (stop_on_cycle - 1), &new_blk))) | 730 | (stop_on_cycle - 1), &new_blk))) |
708 | goto bp_err; | 731 | goto bp_err; |
709 | if (new_blk != -1) { | 732 | if (new_blk != -1) { |
710 | head_blk = new_blk; | 733 | head_blk = new_blk; |
711 | goto bad_blk; | 734 | goto validate_head; |
712 | } | 735 | } |
713 | 736 | ||
714 | /* | 737 | /* |
@@ -726,7 +749,7 @@ xlog_find_head( | |||
726 | head_blk = new_blk; | 749 | head_blk = new_blk; |
727 | } | 750 | } |
728 | 751 | ||
729 | bad_blk: | 752 | validate_head: |
730 | /* | 753 | /* |
731 | * Now we need to make sure head_blk is not pointing to a block in | 754 | * Now we need to make sure head_blk is not pointing to a block in |
732 | * the middle of a log record. | 755 | * the middle of a log record. |
@@ -748,7 +771,7 @@ xlog_find_head( | |||
748 | if ((error = xlog_find_verify_log_record(log, start_blk, | 771 | if ((error = xlog_find_verify_log_record(log, start_blk, |
749 | &head_blk, 0)) == -1) { | 772 | &head_blk, 0)) == -1) { |
750 | /* We hit the beginning of the log during our search */ | 773 | /* We hit the beginning of the log during our search */ |
751 | start_blk = log_bbnum - num_scan_bblks + head_blk; | 774 | start_blk = log_bbnum - (num_scan_bblks - head_blk); |
752 | new_blk = log_bbnum; | 775 | new_blk = log_bbnum; |
753 | ASSERT(start_blk <= INT_MAX && | 776 | ASSERT(start_blk <= INT_MAX && |
754 | (xfs_daddr_t) log_bbnum-start_blk >= 0); | 777 | (xfs_daddr_t) log_bbnum-start_blk >= 0); |
@@ -833,12 +856,12 @@ xlog_find_tail( | |||
833 | if (*head_blk == 0) { /* special case */ | 856 | if (*head_blk == 0) { /* special case */ |
834 | error = xlog_bread(log, 0, 1, bp, &offset); | 857 | error = xlog_bread(log, 0, 1, bp, &offset); |
835 | if (error) | 858 | if (error) |
836 | goto bread_err; | 859 | goto done; |
837 | 860 | ||
838 | if (xlog_get_cycle(offset) == 0) { | 861 | if (xlog_get_cycle(offset) == 0) { |
839 | *tail_blk = 0; | 862 | *tail_blk = 0; |
840 | /* leave all other log inited values alone */ | 863 | /* leave all other log inited values alone */ |
841 | goto exit; | 864 | goto done; |
842 | } | 865 | } |
843 | } | 866 | } |
844 | 867 | ||
@@ -849,7 +872,7 @@ xlog_find_tail( | |||
849 | for (i = (int)(*head_blk) - 1; i >= 0; i--) { | 872 | for (i = (int)(*head_blk) - 1; i >= 0; i--) { |
850 | error = xlog_bread(log, i, 1, bp, &offset); | 873 | error = xlog_bread(log, i, 1, bp, &offset); |
851 | if (error) | 874 | if (error) |
852 | goto bread_err; | 875 | goto done; |
853 | 876 | ||
854 | if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) { | 877 | if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) { |
855 | found = 1; | 878 | found = 1; |
@@ -866,7 +889,7 @@ xlog_find_tail( | |||
866 | for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) { | 889 | for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) { |
867 | error = xlog_bread(log, i, 1, bp, &offset); | 890 | error = xlog_bread(log, i, 1, bp, &offset); |
868 | if (error) | 891 | if (error) |
869 | goto bread_err; | 892 | goto done; |
870 | 893 | ||
871 | if (XLOG_HEADER_MAGIC_NUM == | 894 | if (XLOG_HEADER_MAGIC_NUM == |
872 | be32_to_cpu(*(__be32 *)offset)) { | 895 | be32_to_cpu(*(__be32 *)offset)) { |
@@ -941,7 +964,7 @@ xlog_find_tail( | |||
941 | umount_data_blk = (i + hblks) % log->l_logBBsize; | 964 | umount_data_blk = (i + hblks) % log->l_logBBsize; |
942 | error = xlog_bread(log, umount_data_blk, 1, bp, &offset); | 965 | error = xlog_bread(log, umount_data_blk, 1, bp, &offset); |
943 | if (error) | 966 | if (error) |
944 | goto bread_err; | 967 | goto done; |
945 | 968 | ||
946 | op_head = (xlog_op_header_t *)offset; | 969 | op_head = (xlog_op_header_t *)offset; |
947 | if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) { | 970 | if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) { |
@@ -987,12 +1010,10 @@ xlog_find_tail( | |||
987 | * But... if the -device- itself is readonly, just skip this. | 1010 | * But... if the -device- itself is readonly, just skip this. |
988 | * We can't recover this device anyway, so it won't matter. | 1011 | * We can't recover this device anyway, so it won't matter. |
989 | */ | 1012 | */ |
990 | if (!xfs_readonly_buftarg(log->l_mp->m_logdev_targp)) { | 1013 | if (!xfs_readonly_buftarg(log->l_mp->m_logdev_targp)) |
991 | error = xlog_clear_stale_blocks(log, tail_lsn); | 1014 | error = xlog_clear_stale_blocks(log, tail_lsn); |
992 | } | ||
993 | 1015 | ||
994 | bread_err: | 1016 | done: |
995 | exit: | ||
996 | xlog_put_bp(bp); | 1017 | xlog_put_bp(bp); |
997 | 1018 | ||
998 | if (error) | 1019 | if (error) |
@@ -1152,16 +1173,22 @@ xlog_write_log_records( | |||
1152 | xfs_caddr_t offset; | 1173 | xfs_caddr_t offset; |
1153 | xfs_buf_t *bp; | 1174 | xfs_buf_t *bp; |
1154 | int balign, ealign; | 1175 | int balign, ealign; |
1155 | int sectbb = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); | 1176 | int sectbb = log->l_sectBBsize; |
1156 | int end_block = start_block + blocks; | 1177 | int end_block = start_block + blocks; |
1157 | int bufblks; | 1178 | int bufblks; |
1158 | int error = 0; | 1179 | int error = 0; |
1159 | int i, j = 0; | 1180 | int i, j = 0; |
1160 | 1181 | ||
1182 | /* | ||
1183 | * Greedily allocate a buffer big enough to handle the full | ||
1184 | * range of basic blocks to be written. If that fails, try | ||
1185 | * a smaller size. We need to be able to write at least a | ||
1186 | * log sector, or we're out of luck. | ||
1187 | */ | ||
1161 | bufblks = 1 << ffs(blocks); | 1188 | bufblks = 1 << ffs(blocks); |
1162 | while (!(bp = xlog_get_bp(log, bufblks))) { | 1189 | while (!(bp = xlog_get_bp(log, bufblks))) { |
1163 | bufblks >>= 1; | 1190 | bufblks >>= 1; |
1164 | if (bufblks <= log->l_sectbb_log) | 1191 | if (bufblks < sectbb) |
1165 | return ENOMEM; | 1192 | return ENOMEM; |
1166 | } | 1193 | } |
1167 | 1194 | ||
@@ -1169,7 +1196,7 @@ xlog_write_log_records( | |||
1169 | * the buffer in the starting sector not covered by the first | 1196 | * the buffer in the starting sector not covered by the first |
1170 | * write below. | 1197 | * write below. |
1171 | */ | 1198 | */ |
1172 | balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block); | 1199 | balign = round_down(start_block, sectbb); |
1173 | if (balign != start_block) { | 1200 | if (balign != start_block) { |
1174 | error = xlog_bread_noalign(log, start_block, 1, bp); | 1201 | error = xlog_bread_noalign(log, start_block, 1, bp); |
1175 | if (error) | 1202 | if (error) |
@@ -1188,7 +1215,7 @@ xlog_write_log_records( | |||
1188 | * the buffer in the final sector not covered by the write. | 1215 | * the buffer in the final sector not covered by the write. |
1189 | * If this is the same sector as the above read, skip it. | 1216 | * If this is the same sector as the above read, skip it. |
1190 | */ | 1217 | */ |
1191 | ealign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, end_block); | 1218 | ealign = round_down(end_block, sectbb); |
1192 | if (j == 0 && (start_block + endcount > ealign)) { | 1219 | if (j == 0 && (start_block + endcount > ealign)) { |
1193 | offset = XFS_BUF_PTR(bp); | 1220 | offset = XFS_BUF_PTR(bp); |
1194 | balign = BBTOB(ealign - start_block); | 1221 | balign = BBTOB(ealign - start_block); |
@@ -1408,6 +1435,7 @@ xlog_recover_add_item( | |||
1408 | 1435 | ||
1409 | STATIC int | 1436 | STATIC int |
1410 | xlog_recover_add_to_cont_trans( | 1437 | xlog_recover_add_to_cont_trans( |
1438 | struct log *log, | ||
1411 | xlog_recover_t *trans, | 1439 | xlog_recover_t *trans, |
1412 | xfs_caddr_t dp, | 1440 | xfs_caddr_t dp, |
1413 | int len) | 1441 | int len) |
@@ -1434,6 +1462,7 @@ xlog_recover_add_to_cont_trans( | |||
1434 | memcpy(&ptr[old_len], dp, len); /* d, s, l */ | 1462 | memcpy(&ptr[old_len], dp, len); /* d, s, l */ |
1435 | item->ri_buf[item->ri_cnt-1].i_len += len; | 1463 | item->ri_buf[item->ri_cnt-1].i_len += len; |
1436 | item->ri_buf[item->ri_cnt-1].i_addr = ptr; | 1464 | item->ri_buf[item->ri_cnt-1].i_addr = ptr; |
1465 | trace_xfs_log_recover_item_add_cont(log, trans, item, 0); | ||
1437 | return 0; | 1466 | return 0; |
1438 | } | 1467 | } |
1439 | 1468 | ||
@@ -1452,6 +1481,7 @@ xlog_recover_add_to_cont_trans( | |||
1452 | */ | 1481 | */ |
1453 | STATIC int | 1482 | STATIC int |
1454 | xlog_recover_add_to_trans( | 1483 | xlog_recover_add_to_trans( |
1484 | struct log *log, | ||
1455 | xlog_recover_t *trans, | 1485 | xlog_recover_t *trans, |
1456 | xfs_caddr_t dp, | 1486 | xfs_caddr_t dp, |
1457 | int len) | 1487 | int len) |
@@ -1510,6 +1540,7 @@ xlog_recover_add_to_trans( | |||
1510 | item->ri_buf[item->ri_cnt].i_addr = ptr; | 1540 | item->ri_buf[item->ri_cnt].i_addr = ptr; |
1511 | item->ri_buf[item->ri_cnt].i_len = len; | 1541 | item->ri_buf[item->ri_cnt].i_len = len; |
1512 | item->ri_cnt++; | 1542 | item->ri_cnt++; |
1543 | trace_xfs_log_recover_item_add(log, trans, item, 0); | ||
1513 | return 0; | 1544 | return 0; |
1514 | } | 1545 | } |
1515 | 1546 | ||
@@ -1521,20 +1552,22 @@ xlog_recover_add_to_trans( | |||
1521 | */ | 1552 | */ |
1522 | STATIC int | 1553 | STATIC int |
1523 | xlog_recover_reorder_trans( | 1554 | xlog_recover_reorder_trans( |
1524 | xlog_recover_t *trans) | 1555 | struct log *log, |
1556 | xlog_recover_t *trans, | ||
1557 | int pass) | ||
1525 | { | 1558 | { |
1526 | xlog_recover_item_t *item, *n; | 1559 | xlog_recover_item_t *item, *n; |
1527 | LIST_HEAD(sort_list); | 1560 | LIST_HEAD(sort_list); |
1528 | 1561 | ||
1529 | list_splice_init(&trans->r_itemq, &sort_list); | 1562 | list_splice_init(&trans->r_itemq, &sort_list); |
1530 | list_for_each_entry_safe(item, n, &sort_list, ri_list) { | 1563 | list_for_each_entry_safe(item, n, &sort_list, ri_list) { |
1531 | xfs_buf_log_format_t *buf_f; | 1564 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; |
1532 | |||
1533 | buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; | ||
1534 | 1565 | ||
1535 | switch (ITEM_TYPE(item)) { | 1566 | switch (ITEM_TYPE(item)) { |
1536 | case XFS_LI_BUF: | 1567 | case XFS_LI_BUF: |
1537 | if (!(buf_f->blf_flags & XFS_BLI_CANCEL)) { | 1568 | if (!(buf_f->blf_flags & XFS_BLF_CANCEL)) { |
1569 | trace_xfs_log_recover_item_reorder_head(log, | ||
1570 | trans, item, pass); | ||
1538 | list_move(&item->ri_list, &trans->r_itemq); | 1571 | list_move(&item->ri_list, &trans->r_itemq); |
1539 | break; | 1572 | break; |
1540 | } | 1573 | } |
@@ -1543,6 +1576,8 @@ xlog_recover_reorder_trans( | |||
1543 | case XFS_LI_QUOTAOFF: | 1576 | case XFS_LI_QUOTAOFF: |
1544 | case XFS_LI_EFD: | 1577 | case XFS_LI_EFD: |
1545 | case XFS_LI_EFI: | 1578 | case XFS_LI_EFI: |
1579 | trace_xfs_log_recover_item_reorder_tail(log, | ||
1580 | trans, item, pass); | ||
1546 | list_move_tail(&item->ri_list, &trans->r_itemq); | 1581 | list_move_tail(&item->ri_list, &trans->r_itemq); |
1547 | break; | 1582 | break; |
1548 | default: | 1583 | default: |
@@ -1592,8 +1627,10 @@ xlog_recover_do_buffer_pass1( | |||
1592 | /* | 1627 | /* |
1593 | * If this isn't a cancel buffer item, then just return. | 1628 | * If this isn't a cancel buffer item, then just return. |
1594 | */ | 1629 | */ |
1595 | if (!(flags & XFS_BLI_CANCEL)) | 1630 | if (!(flags & XFS_BLF_CANCEL)) { |
1631 | trace_xfs_log_recover_buf_not_cancel(log, buf_f); | ||
1596 | return; | 1632 | return; |
1633 | } | ||
1597 | 1634 | ||
1598 | /* | 1635 | /* |
1599 | * Insert an xfs_buf_cancel record into the hash table of | 1636 | * Insert an xfs_buf_cancel record into the hash table of |
@@ -1627,6 +1664,7 @@ xlog_recover_do_buffer_pass1( | |||
1627 | while (nextp != NULL) { | 1664 | while (nextp != NULL) { |
1628 | if (nextp->bc_blkno == blkno && nextp->bc_len == len) { | 1665 | if (nextp->bc_blkno == blkno && nextp->bc_len == len) { |
1629 | nextp->bc_refcount++; | 1666 | nextp->bc_refcount++; |
1667 | trace_xfs_log_recover_buf_cancel_ref_inc(log, buf_f); | ||
1630 | return; | 1668 | return; |
1631 | } | 1669 | } |
1632 | prevp = nextp; | 1670 | prevp = nextp; |
@@ -1640,13 +1678,14 @@ xlog_recover_do_buffer_pass1( | |||
1640 | bcp->bc_refcount = 1; | 1678 | bcp->bc_refcount = 1; |
1641 | bcp->bc_next = NULL; | 1679 | bcp->bc_next = NULL; |
1642 | prevp->bc_next = bcp; | 1680 | prevp->bc_next = bcp; |
1681 | trace_xfs_log_recover_buf_cancel_add(log, buf_f); | ||
1643 | } | 1682 | } |
1644 | 1683 | ||
1645 | /* | 1684 | /* |
1646 | * Check to see whether the buffer being recovered has a corresponding | 1685 | * Check to see whether the buffer being recovered has a corresponding |
1647 | * entry in the buffer cancel record table. If it does then return 1 | 1686 | * entry in the buffer cancel record table. If it does then return 1 |
1648 | * so that it will be cancelled, otherwise return 0. If the buffer is | 1687 | * so that it will be cancelled, otherwise return 0. If the buffer is |
1649 | * actually a buffer cancel item (XFS_BLI_CANCEL is set), then decrement | 1688 | * actually a buffer cancel item (XFS_BLF_CANCEL is set), then decrement |
1650 | * the refcount on the entry in the table and remove it from the table | 1689 | * the refcount on the entry in the table and remove it from the table |
1651 | * if this is the last reference. | 1690 | * if this is the last reference. |
1652 | * | 1691 | * |
@@ -1671,7 +1710,7 @@ xlog_check_buffer_cancelled( | |||
1671 | * There is nothing in the table built in pass one, | 1710 | * There is nothing in the table built in pass one, |
1672 | * so this buffer must not be cancelled. | 1711 | * so this buffer must not be cancelled. |
1673 | */ | 1712 | */ |
1674 | ASSERT(!(flags & XFS_BLI_CANCEL)); | 1713 | ASSERT(!(flags & XFS_BLF_CANCEL)); |
1675 | return 0; | 1714 | return 0; |
1676 | } | 1715 | } |
1677 | 1716 | ||
@@ -1683,7 +1722,7 @@ xlog_check_buffer_cancelled( | |||
1683 | * There is no corresponding entry in the table built | 1722 | * There is no corresponding entry in the table built |
1684 | * in pass one, so this buffer has not been cancelled. | 1723 | * in pass one, so this buffer has not been cancelled. |
1685 | */ | 1724 | */ |
1686 | ASSERT(!(flags & XFS_BLI_CANCEL)); | 1725 | ASSERT(!(flags & XFS_BLF_CANCEL)); |
1687 | return 0; | 1726 | return 0; |
1688 | } | 1727 | } |
1689 | 1728 | ||
@@ -1702,7 +1741,7 @@ xlog_check_buffer_cancelled( | |||
1702 | * one in the table and remove it if this is the | 1741 | * one in the table and remove it if this is the |
1703 | * last reference. | 1742 | * last reference. |
1704 | */ | 1743 | */ |
1705 | if (flags & XFS_BLI_CANCEL) { | 1744 | if (flags & XFS_BLF_CANCEL) { |
1706 | bcp->bc_refcount--; | 1745 | bcp->bc_refcount--; |
1707 | if (bcp->bc_refcount == 0) { | 1746 | if (bcp->bc_refcount == 0) { |
1708 | if (prevp == NULL) { | 1747 | if (prevp == NULL) { |
@@ -1722,7 +1761,7 @@ xlog_check_buffer_cancelled( | |||
1722 | * We didn't find a corresponding entry in the table, so | 1761 | * We didn't find a corresponding entry in the table, so |
1723 | * return 0 so that the buffer is NOT cancelled. | 1762 | * return 0 so that the buffer is NOT cancelled. |
1724 | */ | 1763 | */ |
1725 | ASSERT(!(flags & XFS_BLI_CANCEL)); | 1764 | ASSERT(!(flags & XFS_BLF_CANCEL)); |
1726 | return 0; | 1765 | return 0; |
1727 | } | 1766 | } |
1728 | 1767 | ||
@@ -1779,6 +1818,8 @@ xlog_recover_do_inode_buffer( | |||
1779 | unsigned int *data_map = NULL; | 1818 | unsigned int *data_map = NULL; |
1780 | unsigned int map_size = 0; | 1819 | unsigned int map_size = 0; |
1781 | 1820 | ||
1821 | trace_xfs_log_recover_buf_inode_buf(mp->m_log, buf_f); | ||
1822 | |||
1782 | switch (buf_f->blf_type) { | 1823 | switch (buf_f->blf_type) { |
1783 | case XFS_LI_BUF: | 1824 | case XFS_LI_BUF: |
1784 | data_map = buf_f->blf_data_map; | 1825 | data_map = buf_f->blf_data_map; |
@@ -1822,8 +1863,8 @@ xlog_recover_do_inode_buffer( | |||
1822 | nbits = xfs_contig_bits(data_map, map_size, | 1863 | nbits = xfs_contig_bits(data_map, map_size, |
1823 | bit); | 1864 | bit); |
1824 | ASSERT(nbits > 0); | 1865 | ASSERT(nbits > 0); |
1825 | reg_buf_offset = bit << XFS_BLI_SHIFT; | 1866 | reg_buf_offset = bit << XFS_BLF_SHIFT; |
1826 | reg_buf_bytes = nbits << XFS_BLI_SHIFT; | 1867 | reg_buf_bytes = nbits << XFS_BLF_SHIFT; |
1827 | item_index++; | 1868 | item_index++; |
1828 | } | 1869 | } |
1829 | 1870 | ||
@@ -1837,7 +1878,7 @@ xlog_recover_do_inode_buffer( | |||
1837 | } | 1878 | } |
1838 | 1879 | ||
1839 | ASSERT(item->ri_buf[item_index].i_addr != NULL); | 1880 | ASSERT(item->ri_buf[item_index].i_addr != NULL); |
1840 | ASSERT((item->ri_buf[item_index].i_len % XFS_BLI_CHUNK) == 0); | 1881 | ASSERT((item->ri_buf[item_index].i_len % XFS_BLF_CHUNK) == 0); |
1841 | ASSERT((reg_buf_offset + reg_buf_bytes) <= XFS_BUF_COUNT(bp)); | 1882 | ASSERT((reg_buf_offset + reg_buf_bytes) <= XFS_BUF_COUNT(bp)); |
1842 | 1883 | ||
1843 | /* | 1884 | /* |
@@ -1845,9 +1886,8 @@ xlog_recover_do_inode_buffer( | |||
1845 | * current di_next_unlinked field. Extract its value | 1886 | * current di_next_unlinked field. Extract its value |
1846 | * and copy it to the buffer copy. | 1887 | * and copy it to the buffer copy. |
1847 | */ | 1888 | */ |
1848 | logged_nextp = (xfs_agino_t *) | 1889 | logged_nextp = item->ri_buf[item_index].i_addr + |
1849 | ((char *)(item->ri_buf[item_index].i_addr) + | 1890 | next_unlinked_offset - reg_buf_offset; |
1850 | (next_unlinked_offset - reg_buf_offset)); | ||
1851 | if (unlikely(*logged_nextp == 0)) { | 1891 | if (unlikely(*logged_nextp == 0)) { |
1852 | xfs_fs_cmn_err(CE_ALERT, mp, | 1892 | xfs_fs_cmn_err(CE_ALERT, mp, |
1853 | "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", | 1893 | "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", |
@@ -1874,6 +1914,7 @@ xlog_recover_do_inode_buffer( | |||
1874 | /*ARGSUSED*/ | 1914 | /*ARGSUSED*/ |
1875 | STATIC void | 1915 | STATIC void |
1876 | xlog_recover_do_reg_buffer( | 1916 | xlog_recover_do_reg_buffer( |
1917 | struct xfs_mount *mp, | ||
1877 | xlog_recover_item_t *item, | 1918 | xlog_recover_item_t *item, |
1878 | xfs_buf_t *bp, | 1919 | xfs_buf_t *bp, |
1879 | xfs_buf_log_format_t *buf_f) | 1920 | xfs_buf_log_format_t *buf_f) |
@@ -1885,6 +1926,8 @@ xlog_recover_do_reg_buffer( | |||
1885 | unsigned int map_size = 0; | 1926 | unsigned int map_size = 0; |
1886 | int error; | 1927 | int error; |
1887 | 1928 | ||
1929 | trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f); | ||
1930 | |||
1888 | switch (buf_f->blf_type) { | 1931 | switch (buf_f->blf_type) { |
1889 | case XFS_LI_BUF: | 1932 | case XFS_LI_BUF: |
1890 | data_map = buf_f->blf_data_map; | 1933 | data_map = buf_f->blf_data_map; |
@@ -1900,9 +1943,9 @@ xlog_recover_do_reg_buffer( | |||
1900 | nbits = xfs_contig_bits(data_map, map_size, bit); | 1943 | nbits = xfs_contig_bits(data_map, map_size, bit); |
1901 | ASSERT(nbits > 0); | 1944 | ASSERT(nbits > 0); |
1902 | ASSERT(item->ri_buf[i].i_addr != NULL); | 1945 | ASSERT(item->ri_buf[i].i_addr != NULL); |
1903 | ASSERT(item->ri_buf[i].i_len % XFS_BLI_CHUNK == 0); | 1946 | ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0); |
1904 | ASSERT(XFS_BUF_COUNT(bp) >= | 1947 | ASSERT(XFS_BUF_COUNT(bp) >= |
1905 | ((uint)bit << XFS_BLI_SHIFT)+(nbits<<XFS_BLI_SHIFT)); | 1948 | ((uint)bit << XFS_BLF_SHIFT)+(nbits<<XFS_BLF_SHIFT)); |
1906 | 1949 | ||
1907 | /* | 1950 | /* |
1908 | * Do a sanity check if this is a dquot buffer. Just checking | 1951 | * Do a sanity check if this is a dquot buffer. Just checking |
@@ -1911,7 +1954,7 @@ xlog_recover_do_reg_buffer( | |||
1911 | */ | 1954 | */ |
1912 | error = 0; | 1955 | error = 0; |
1913 | if (buf_f->blf_flags & | 1956 | if (buf_f->blf_flags & |
1914 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { | 1957 | (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { |
1915 | if (item->ri_buf[i].i_addr == NULL) { | 1958 | if (item->ri_buf[i].i_addr == NULL) { |
1916 | cmn_err(CE_ALERT, | 1959 | cmn_err(CE_ALERT, |
1917 | "XFS: NULL dquot in %s.", __func__); | 1960 | "XFS: NULL dquot in %s.", __func__); |
@@ -1923,8 +1966,7 @@ xlog_recover_do_reg_buffer( | |||
1923 | item->ri_buf[i].i_len, __func__); | 1966 | item->ri_buf[i].i_len, __func__); |
1924 | goto next; | 1967 | goto next; |
1925 | } | 1968 | } |
1926 | error = xfs_qm_dqcheck((xfs_disk_dquot_t *) | 1969 | error = xfs_qm_dqcheck(item->ri_buf[i].i_addr, |
1927 | item->ri_buf[i].i_addr, | ||
1928 | -1, 0, XFS_QMOPT_DOWARN, | 1970 | -1, 0, XFS_QMOPT_DOWARN, |
1929 | "dquot_buf_recover"); | 1971 | "dquot_buf_recover"); |
1930 | if (error) | 1972 | if (error) |
@@ -1932,9 +1974,9 @@ xlog_recover_do_reg_buffer( | |||
1932 | } | 1974 | } |
1933 | 1975 | ||
1934 | memcpy(xfs_buf_offset(bp, | 1976 | memcpy(xfs_buf_offset(bp, |
1935 | (uint)bit << XFS_BLI_SHIFT), /* dest */ | 1977 | (uint)bit << XFS_BLF_SHIFT), /* dest */ |
1936 | item->ri_buf[i].i_addr, /* source */ | 1978 | item->ri_buf[i].i_addr, /* source */ |
1937 | nbits<<XFS_BLI_SHIFT); /* length */ | 1979 | nbits<<XFS_BLF_SHIFT); /* length */ |
1938 | next: | 1980 | next: |
1939 | i++; | 1981 | i++; |
1940 | bit += nbits; | 1982 | bit += nbits; |
@@ -2083,6 +2125,8 @@ xlog_recover_do_dquot_buffer( | |||
2083 | { | 2125 | { |
2084 | uint type; | 2126 | uint type; |
2085 | 2127 | ||
2128 | trace_xfs_log_recover_buf_dquot_buf(log, buf_f); | ||
2129 | |||
2086 | /* | 2130 | /* |
2087 | * Filesystems are required to send in quota flags at mount time. | 2131 | * Filesystems are required to send in quota flags at mount time. |
2088 | */ | 2132 | */ |
@@ -2091,11 +2135,11 @@ xlog_recover_do_dquot_buffer( | |||
2091 | } | 2135 | } |
2092 | 2136 | ||
2093 | type = 0; | 2137 | type = 0; |
2094 | if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF) | 2138 | if (buf_f->blf_flags & XFS_BLF_UDQUOT_BUF) |
2095 | type |= XFS_DQ_USER; | 2139 | type |= XFS_DQ_USER; |
2096 | if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF) | 2140 | if (buf_f->blf_flags & XFS_BLF_PDQUOT_BUF) |
2097 | type |= XFS_DQ_PROJ; | 2141 | type |= XFS_DQ_PROJ; |
2098 | if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF) | 2142 | if (buf_f->blf_flags & XFS_BLF_GDQUOT_BUF) |
2099 | type |= XFS_DQ_GROUP; | 2143 | type |= XFS_DQ_GROUP; |
2100 | /* | 2144 | /* |
2101 | * This type of quotas was turned off, so ignore this buffer | 2145 | * This type of quotas was turned off, so ignore this buffer |
@@ -2103,7 +2147,7 @@ xlog_recover_do_dquot_buffer( | |||
2103 | if (log->l_quotaoffs_flag & type) | 2147 | if (log->l_quotaoffs_flag & type) |
2104 | return; | 2148 | return; |
2105 | 2149 | ||
2106 | xlog_recover_do_reg_buffer(item, bp, buf_f); | 2150 | xlog_recover_do_reg_buffer(mp, item, bp, buf_f); |
2107 | } | 2151 | } |
2108 | 2152 | ||
2109 | /* | 2153 | /* |
@@ -2116,7 +2160,7 @@ xlog_recover_do_dquot_buffer( | |||
2116 | * here which overlaps that may be stale. | 2160 | * here which overlaps that may be stale. |
2117 | * | 2161 | * |
2118 | * When meta-data buffers are freed at run time we log a buffer item | 2162 | * When meta-data buffers are freed at run time we log a buffer item |
2119 | * with the XFS_BLI_CANCEL bit set to indicate that previous copies | 2163 | * with the XFS_BLF_CANCEL bit set to indicate that previous copies |
2120 | * of the buffer in the log should not be replayed at recovery time. | 2164 | * of the buffer in the log should not be replayed at recovery time. |
2121 | * This is so that if the blocks covered by the buffer are reused for | 2165 | * This is so that if the blocks covered by the buffer are reused for |
2122 | * file data before we crash we don't end up replaying old, freed | 2166 | * file data before we crash we don't end up replaying old, freed |
@@ -2135,7 +2179,7 @@ xlog_recover_do_buffer_trans( | |||
2135 | xlog_recover_item_t *item, | 2179 | xlog_recover_item_t *item, |
2136 | int pass) | 2180 | int pass) |
2137 | { | 2181 | { |
2138 | xfs_buf_log_format_t *buf_f; | 2182 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; |
2139 | xfs_mount_t *mp; | 2183 | xfs_mount_t *mp; |
2140 | xfs_buf_t *bp; | 2184 | xfs_buf_t *bp; |
2141 | int error; | 2185 | int error; |
@@ -2145,12 +2189,10 @@ xlog_recover_do_buffer_trans( | |||
2145 | ushort flags; | 2189 | ushort flags; |
2146 | uint buf_flags; | 2190 | uint buf_flags; |
2147 | 2191 | ||
2148 | buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; | ||
2149 | |||
2150 | if (pass == XLOG_RECOVER_PASS1) { | 2192 | if (pass == XLOG_RECOVER_PASS1) { |
2151 | /* | 2193 | /* |
2152 | * In this pass we're only looking for buf items | 2194 | * In this pass we're only looking for buf items |
2153 | * with the XFS_BLI_CANCEL bit set. | 2195 | * with the XFS_BLF_CANCEL bit set. |
2154 | */ | 2196 | */ |
2155 | xlog_recover_do_buffer_pass1(log, buf_f); | 2197 | xlog_recover_do_buffer_pass1(log, buf_f); |
2156 | return 0; | 2198 | return 0; |
@@ -2164,9 +2206,11 @@ xlog_recover_do_buffer_trans( | |||
2164 | */ | 2206 | */ |
2165 | cancel = xlog_recover_do_buffer_pass2(log, buf_f); | 2207 | cancel = xlog_recover_do_buffer_pass2(log, buf_f); |
2166 | if (cancel) { | 2208 | if (cancel) { |
2209 | trace_xfs_log_recover_buf_cancel(log, buf_f); | ||
2167 | return 0; | 2210 | return 0; |
2168 | } | 2211 | } |
2169 | } | 2212 | } |
2213 | trace_xfs_log_recover_buf_recover(log, buf_f); | ||
2170 | switch (buf_f->blf_type) { | 2214 | switch (buf_f->blf_type) { |
2171 | case XFS_LI_BUF: | 2215 | case XFS_LI_BUF: |
2172 | blkno = buf_f->blf_blkno; | 2216 | blkno = buf_f->blf_blkno; |
@@ -2185,7 +2229,7 @@ xlog_recover_do_buffer_trans( | |||
2185 | 2229 | ||
2186 | mp = log->l_mp; | 2230 | mp = log->l_mp; |
2187 | buf_flags = XBF_LOCK; | 2231 | buf_flags = XBF_LOCK; |
2188 | if (!(flags & XFS_BLI_INODE_BUF)) | 2232 | if (!(flags & XFS_BLF_INODE_BUF)) |
2189 | buf_flags |= XBF_MAPPED; | 2233 | buf_flags |= XBF_MAPPED; |
2190 | 2234 | ||
2191 | bp = xfs_buf_read(mp->m_ddev_targp, blkno, len, buf_flags); | 2235 | bp = xfs_buf_read(mp->m_ddev_targp, blkno, len, buf_flags); |
@@ -2198,13 +2242,13 @@ xlog_recover_do_buffer_trans( | |||
2198 | } | 2242 | } |
2199 | 2243 | ||
2200 | error = 0; | 2244 | error = 0; |
2201 | if (flags & XFS_BLI_INODE_BUF) { | 2245 | if (flags & XFS_BLF_INODE_BUF) { |
2202 | error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); | 2246 | error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); |
2203 | } else if (flags & | 2247 | } else if (flags & |
2204 | (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { | 2248 | (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { |
2205 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); | 2249 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); |
2206 | } else { | 2250 | } else { |
2207 | xlog_recover_do_reg_buffer(item, bp, buf_f); | 2251 | xlog_recover_do_reg_buffer(mp, item, bp, buf_f); |
2208 | } | 2252 | } |
2209 | if (error) | 2253 | if (error) |
2210 | return XFS_ERROR(error); | 2254 | return XFS_ERROR(error); |
@@ -2265,10 +2309,9 @@ xlog_recover_do_inode_trans( | |||
2265 | } | 2309 | } |
2266 | 2310 | ||
2267 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { | 2311 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { |
2268 | in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; | 2312 | in_f = item->ri_buf[0].i_addr; |
2269 | } else { | 2313 | } else { |
2270 | in_f = (xfs_inode_log_format_t *)kmem_alloc( | 2314 | in_f = kmem_alloc(sizeof(xfs_inode_log_format_t), KM_SLEEP); |
2271 | sizeof(xfs_inode_log_format_t), KM_SLEEP); | ||
2272 | need_free = 1; | 2315 | need_free = 1; |
2273 | error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); | 2316 | error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); |
2274 | if (error) | 2317 | if (error) |
@@ -2284,8 +2327,10 @@ xlog_recover_do_inode_trans( | |||
2284 | if (xlog_check_buffer_cancelled(log, in_f->ilf_blkno, | 2327 | if (xlog_check_buffer_cancelled(log, in_f->ilf_blkno, |
2285 | in_f->ilf_len, 0)) { | 2328 | in_f->ilf_len, 0)) { |
2286 | error = 0; | 2329 | error = 0; |
2330 | trace_xfs_log_recover_inode_cancel(log, in_f); | ||
2287 | goto error; | 2331 | goto error; |
2288 | } | 2332 | } |
2333 | trace_xfs_log_recover_inode_recover(log, in_f); | ||
2289 | 2334 | ||
2290 | bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, | 2335 | bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, |
2291 | XBF_LOCK); | 2336 | XBF_LOCK); |
@@ -2314,7 +2359,7 @@ xlog_recover_do_inode_trans( | |||
2314 | error = EFSCORRUPTED; | 2359 | error = EFSCORRUPTED; |
2315 | goto error; | 2360 | goto error; |
2316 | } | 2361 | } |
2317 | dicp = (xfs_icdinode_t *)(item->ri_buf[1].i_addr); | 2362 | dicp = item->ri_buf[1].i_addr; |
2318 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { | 2363 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { |
2319 | xfs_buf_relse(bp); | 2364 | xfs_buf_relse(bp); |
2320 | xfs_fs_cmn_err(CE_ALERT, mp, | 2365 | xfs_fs_cmn_err(CE_ALERT, mp, |
@@ -2337,6 +2382,7 @@ xlog_recover_do_inode_trans( | |||
2337 | /* do nothing */ | 2382 | /* do nothing */ |
2338 | } else { | 2383 | } else { |
2339 | xfs_buf_relse(bp); | 2384 | xfs_buf_relse(bp); |
2385 | trace_xfs_log_recover_inode_skip(log, in_f); | ||
2340 | error = 0; | 2386 | error = 0; |
2341 | goto error; | 2387 | goto error; |
2342 | } | 2388 | } |
@@ -2404,7 +2450,7 @@ xlog_recover_do_inode_trans( | |||
2404 | } | 2450 | } |
2405 | 2451 | ||
2406 | /* The core is in in-core format */ | 2452 | /* The core is in in-core format */ |
2407 | xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr); | 2453 | xfs_dinode_to_disk(dip, item->ri_buf[1].i_addr); |
2408 | 2454 | ||
2409 | /* the rest is in on-disk format */ | 2455 | /* the rest is in on-disk format */ |
2410 | if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { | 2456 | if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { |
@@ -2521,7 +2567,7 @@ xlog_recover_do_quotaoff_trans( | |||
2521 | return (0); | 2567 | return (0); |
2522 | } | 2568 | } |
2523 | 2569 | ||
2524 | qoff_f = (xfs_qoff_logformat_t *)item->ri_buf[0].i_addr; | 2570 | qoff_f = item->ri_buf[0].i_addr; |
2525 | ASSERT(qoff_f); | 2571 | ASSERT(qoff_f); |
2526 | 2572 | ||
2527 | /* | 2573 | /* |
@@ -2565,9 +2611,8 @@ xlog_recover_do_dquot_trans( | |||
2565 | if (mp->m_qflags == 0) | 2611 | if (mp->m_qflags == 0) |
2566 | return (0); | 2612 | return (0); |
2567 | 2613 | ||
2568 | recddq = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr; | 2614 | recddq = item->ri_buf[1].i_addr; |
2569 | 2615 | if (recddq == NULL) { | |
2570 | if (item->ri_buf[1].i_addr == NULL) { | ||
2571 | cmn_err(CE_ALERT, | 2616 | cmn_err(CE_ALERT, |
2572 | "XFS: NULL dquot in %s.", __func__); | 2617 | "XFS: NULL dquot in %s.", __func__); |
2573 | return XFS_ERROR(EIO); | 2618 | return XFS_ERROR(EIO); |
@@ -2597,7 +2642,7 @@ xlog_recover_do_dquot_trans( | |||
2597 | * The other possibility, of course, is that the quota subsystem was | 2642 | * The other possibility, of course, is that the quota subsystem was |
2598 | * removed since the last mount - ENOSYS. | 2643 | * removed since the last mount - ENOSYS. |
2599 | */ | 2644 | */ |
2600 | dq_f = (xfs_dq_logformat_t *)item->ri_buf[0].i_addr; | 2645 | dq_f = item->ri_buf[0].i_addr; |
2601 | ASSERT(dq_f); | 2646 | ASSERT(dq_f); |
2602 | if ((error = xfs_qm_dqcheck(recddq, | 2647 | if ((error = xfs_qm_dqcheck(recddq, |
2603 | dq_f->qlf_id, | 2648 | dq_f->qlf_id, |
@@ -2664,7 +2709,7 @@ xlog_recover_do_efi_trans( | |||
2664 | return 0; | 2709 | return 0; |
2665 | } | 2710 | } |
2666 | 2711 | ||
2667 | efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; | 2712 | efi_formatp = item->ri_buf[0].i_addr; |
2668 | 2713 | ||
2669 | mp = log->l_mp; | 2714 | mp = log->l_mp; |
2670 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2715 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
@@ -2710,7 +2755,7 @@ xlog_recover_do_efd_trans( | |||
2710 | return; | 2755 | return; |
2711 | } | 2756 | } |
2712 | 2757 | ||
2713 | efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; | 2758 | efd_formatp = item->ri_buf[0].i_addr; |
2714 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + | 2759 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + |
2715 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || | 2760 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || |
2716 | (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + | 2761 | (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + |
@@ -2758,11 +2803,12 @@ xlog_recover_do_trans( | |||
2758 | int error = 0; | 2803 | int error = 0; |
2759 | xlog_recover_item_t *item; | 2804 | xlog_recover_item_t *item; |
2760 | 2805 | ||
2761 | error = xlog_recover_reorder_trans(trans); | 2806 | error = xlog_recover_reorder_trans(log, trans, pass); |
2762 | if (error) | 2807 | if (error) |
2763 | return error; | 2808 | return error; |
2764 | 2809 | ||
2765 | list_for_each_entry(item, &trans->r_itemq, ri_list) { | 2810 | list_for_each_entry(item, &trans->r_itemq, ri_list) { |
2811 | trace_xfs_log_recover_item_recover(log, trans, item, pass); | ||
2766 | switch (ITEM_TYPE(item)) { | 2812 | switch (ITEM_TYPE(item)) { |
2767 | case XFS_LI_BUF: | 2813 | case XFS_LI_BUF: |
2768 | error = xlog_recover_do_buffer_trans(log, item, pass); | 2814 | error = xlog_recover_do_buffer_trans(log, item, pass); |
@@ -2919,8 +2965,9 @@ xlog_recover_process_data( | |||
2919 | error = xlog_recover_unmount_trans(trans); | 2965 | error = xlog_recover_unmount_trans(trans); |
2920 | break; | 2966 | break; |
2921 | case XLOG_WAS_CONT_TRANS: | 2967 | case XLOG_WAS_CONT_TRANS: |
2922 | error = xlog_recover_add_to_cont_trans(trans, | 2968 | error = xlog_recover_add_to_cont_trans(log, |
2923 | dp, be32_to_cpu(ohead->oh_len)); | 2969 | trans, dp, |
2970 | be32_to_cpu(ohead->oh_len)); | ||
2924 | break; | 2971 | break; |
2925 | case XLOG_START_TRANS: | 2972 | case XLOG_START_TRANS: |
2926 | xlog_warn( | 2973 | xlog_warn( |
@@ -2930,7 +2977,7 @@ xlog_recover_process_data( | |||
2930 | break; | 2977 | break; |
2931 | case 0: | 2978 | case 0: |
2932 | case XLOG_CONTINUE_TRANS: | 2979 | case XLOG_CONTINUE_TRANS: |
2933 | error = xlog_recover_add_to_trans(trans, | 2980 | error = xlog_recover_add_to_trans(log, trans, |
2934 | dp, be32_to_cpu(ohead->oh_len)); | 2981 | dp, be32_to_cpu(ohead->oh_len)); |
2935 | break; | 2982 | break; |
2936 | default: | 2983 | default: |
@@ -3139,7 +3186,7 @@ xlog_recover_process_one_iunlink( | |||
3139 | int error; | 3186 | int error; |
3140 | 3187 | ||
3141 | ino = XFS_AGINO_TO_INO(mp, agno, agino); | 3188 | ino = XFS_AGINO_TO_INO(mp, agno, agino); |
3142 | error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0); | 3189 | error = xfs_iget(mp, NULL, ino, 0, 0, &ip); |
3143 | if (error) | 3190 | if (error) |
3144 | goto fail; | 3191 | goto fail; |
3145 | 3192 | ||
@@ -3331,42 +3378,6 @@ xlog_pack_data( | |||
3331 | } | 3378 | } |
3332 | } | 3379 | } |
3333 | 3380 | ||
3334 | #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY) | ||
3335 | STATIC void | ||
3336 | xlog_unpack_data_checksum( | ||
3337 | xlog_rec_header_t *rhead, | ||
3338 | xfs_caddr_t dp, | ||
3339 | xlog_t *log) | ||
3340 | { | ||
3341 | __be32 *up = (__be32 *)dp; | ||
3342 | uint chksum = 0; | ||
3343 | int i; | ||
3344 | |||
3345 | /* divide length by 4 to get # words */ | ||
3346 | for (i=0; i < be32_to_cpu(rhead->h_len) >> 2; i++) { | ||
3347 | chksum ^= be32_to_cpu(*up); | ||
3348 | up++; | ||
3349 | } | ||
3350 | if (chksum != be32_to_cpu(rhead->h_chksum)) { | ||
3351 | if (rhead->h_chksum || | ||
3352 | ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) { | ||
3353 | cmn_err(CE_DEBUG, | ||
3354 | "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n", | ||
3355 | be32_to_cpu(rhead->h_chksum), chksum); | ||
3356 | cmn_err(CE_DEBUG, | ||
3357 | "XFS: Disregard message if filesystem was created with non-DEBUG kernel"); | ||
3358 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { | ||
3359 | cmn_err(CE_DEBUG, | ||
3360 | "XFS: LogR this is a LogV2 filesystem\n"); | ||
3361 | } | ||
3362 | log->l_flags |= XLOG_CHKSUM_MISMATCH; | ||
3363 | } | ||
3364 | } | ||
3365 | } | ||
3366 | #else | ||
3367 | #define xlog_unpack_data_checksum(rhead, dp, log) | ||
3368 | #endif | ||
3369 | |||
3370 | STATIC void | 3381 | STATIC void |
3371 | xlog_unpack_data( | 3382 | xlog_unpack_data( |
3372 | xlog_rec_header_t *rhead, | 3383 | xlog_rec_header_t *rhead, |
@@ -3390,8 +3401,6 @@ xlog_unpack_data( | |||
3390 | dp += BBSIZE; | 3401 | dp += BBSIZE; |
3391 | } | 3402 | } |
3392 | } | 3403 | } |
3393 | |||
3394 | xlog_unpack_data_checksum(rhead, dp, log); | ||
3395 | } | 3404 | } |
3396 | 3405 | ||
3397 | STATIC int | 3406 | STATIC int |
@@ -3490,7 +3499,7 @@ xlog_do_recovery_pass( | |||
3490 | hblks = 1; | 3499 | hblks = 1; |
3491 | } | 3500 | } |
3492 | } else { | 3501 | } else { |
3493 | ASSERT(log->l_sectbb_log == 0); | 3502 | ASSERT(log->l_sectBBsize == 1); |
3494 | hblks = 1; | 3503 | hblks = 1; |
3495 | hbp = xlog_get_bp(log, 1); | 3504 | hbp = xlog_get_bp(log, 1); |
3496 | h_size = XLOG_BIG_RECORD_BSIZE; | 3505 | h_size = XLOG_BIG_RECORD_BSIZE; |
@@ -3946,10 +3955,6 @@ xlog_recover_check_summary( | |||
3946 | xfs_agf_t *agfp; | 3955 | xfs_agf_t *agfp; |
3947 | xfs_buf_t *agfbp; | 3956 | xfs_buf_t *agfbp; |
3948 | xfs_buf_t *agibp; | 3957 | xfs_buf_t *agibp; |
3949 | xfs_buf_t *sbbp; | ||
3950 | #ifdef XFS_LOUD_RECOVERY | ||
3951 | xfs_sb_t *sbp; | ||
3952 | #endif | ||
3953 | xfs_agnumber_t agno; | 3958 | xfs_agnumber_t agno; |
3954 | __uint64_t freeblks; | 3959 | __uint64_t freeblks; |
3955 | __uint64_t itotal; | 3960 | __uint64_t itotal; |
@@ -3984,30 +3989,5 @@ xlog_recover_check_summary( | |||
3984 | xfs_buf_relse(agibp); | 3989 | xfs_buf_relse(agibp); |
3985 | } | 3990 | } |
3986 | } | 3991 | } |
3987 | |||
3988 | sbbp = xfs_getsb(mp, 0); | ||
3989 | #ifdef XFS_LOUD_RECOVERY | ||
3990 | sbp = &mp->m_sb; | ||
3991 | xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(sbbp)); | ||
3992 | cmn_err(CE_NOTE, | ||
3993 | "xlog_recover_check_summary: sb_icount %Lu itotal %Lu", | ||
3994 | sbp->sb_icount, itotal); | ||
3995 | cmn_err(CE_NOTE, | ||
3996 | "xlog_recover_check_summary: sb_ifree %Lu itotal %Lu", | ||
3997 | sbp->sb_ifree, ifree); | ||
3998 | cmn_err(CE_NOTE, | ||
3999 | "xlog_recover_check_summary: sb_fdblocks %Lu freeblks %Lu", | ||
4000 | sbp->sb_fdblocks, freeblks); | ||
4001 | #if 0 | ||
4002 | /* | ||
4003 | * This is turned off until I account for the allocation | ||
4004 | * btree blocks which live in free space. | ||
4005 | */ | ||
4006 | ASSERT(sbp->sb_icount == itotal); | ||
4007 | ASSERT(sbp->sb_ifree == ifree); | ||
4008 | ASSERT(sbp->sb_fdblocks == freeblks); | ||
4009 | #endif | ||
4010 | #endif | ||
4011 | xfs_buf_relse(sbbp); | ||
4012 | } | 3992 | } |
4013 | #endif /* DEBUG */ | 3993 | #endif /* DEBUG */ |