diff options
Diffstat (limited to 'fs/ocfs2/super.c')
-rw-r--r-- | fs/ocfs2/super.c | 170 |
1 files changed, 131 insertions, 39 deletions
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index fa1be1b304d1..56f0cb395820 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -162,6 +162,7 @@ enum { | |||
162 | Opt_nointr, | 162 | Opt_nointr, |
163 | Opt_hb_none, | 163 | Opt_hb_none, |
164 | Opt_hb_local, | 164 | Opt_hb_local, |
165 | Opt_hb_global, | ||
165 | Opt_data_ordered, | 166 | Opt_data_ordered, |
166 | Opt_data_writeback, | 167 | Opt_data_writeback, |
167 | Opt_atime_quantum, | 168 | Opt_atime_quantum, |
@@ -177,6 +178,8 @@ enum { | |||
177 | Opt_noacl, | 178 | Opt_noacl, |
178 | Opt_usrquota, | 179 | Opt_usrquota, |
179 | Opt_grpquota, | 180 | Opt_grpquota, |
181 | Opt_coherency_buffered, | ||
182 | Opt_coherency_full, | ||
180 | Opt_resv_level, | 183 | Opt_resv_level, |
181 | Opt_dir_resv_level, | 184 | Opt_dir_resv_level, |
182 | Opt_err, | 185 | Opt_err, |
@@ -190,6 +193,7 @@ static const match_table_t tokens = { | |||
190 | {Opt_nointr, "nointr"}, | 193 | {Opt_nointr, "nointr"}, |
191 | {Opt_hb_none, OCFS2_HB_NONE}, | 194 | {Opt_hb_none, OCFS2_HB_NONE}, |
192 | {Opt_hb_local, OCFS2_HB_LOCAL}, | 195 | {Opt_hb_local, OCFS2_HB_LOCAL}, |
196 | {Opt_hb_global, OCFS2_HB_GLOBAL}, | ||
193 | {Opt_data_ordered, "data=ordered"}, | 197 | {Opt_data_ordered, "data=ordered"}, |
194 | {Opt_data_writeback, "data=writeback"}, | 198 | {Opt_data_writeback, "data=writeback"}, |
195 | {Opt_atime_quantum, "atime_quantum=%u"}, | 199 | {Opt_atime_quantum, "atime_quantum=%u"}, |
@@ -205,6 +209,8 @@ static const match_table_t tokens = { | |||
205 | {Opt_noacl, "noacl"}, | 209 | {Opt_noacl, "noacl"}, |
206 | {Opt_usrquota, "usrquota"}, | 210 | {Opt_usrquota, "usrquota"}, |
207 | {Opt_grpquota, "grpquota"}, | 211 | {Opt_grpquota, "grpquota"}, |
212 | {Opt_coherency_buffered, "coherency=buffered"}, | ||
213 | {Opt_coherency_full, "coherency=full"}, | ||
208 | {Opt_resv_level, "resv_level=%u"}, | 214 | {Opt_resv_level, "resv_level=%u"}, |
209 | {Opt_dir_resv_level, "dir_resv_level=%u"}, | 215 | {Opt_dir_resv_level, "dir_resv_level=%u"}, |
210 | {Opt_err, NULL} | 216 | {Opt_err, NULL} |
@@ -514,11 +520,11 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) | |||
514 | 520 | ||
515 | mlog_entry_void(); | 521 | mlog_entry_void(); |
516 | 522 | ||
517 | for (i = 0; i < NUM_SYSTEM_INODES; i++) { | 523 | for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) { |
518 | inode = osb->system_inodes[i]; | 524 | inode = osb->global_system_inodes[i]; |
519 | if (inode) { | 525 | if (inode) { |
520 | iput(inode); | 526 | iput(inode); |
521 | osb->system_inodes[i] = NULL; | 527 | osb->global_system_inodes[i] = NULL; |
522 | } | 528 | } |
523 | } | 529 | } |
524 | 530 | ||
@@ -534,6 +540,20 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) | |||
534 | osb->root_inode = NULL; | 540 | osb->root_inode = NULL; |
535 | } | 541 | } |
536 | 542 | ||
543 | if (!osb->local_system_inodes) | ||
544 | goto out; | ||
545 | |||
546 | for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) { | ||
547 | if (osb->local_system_inodes[i]) { | ||
548 | iput(osb->local_system_inodes[i]); | ||
549 | osb->local_system_inodes[i] = NULL; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | kfree(osb->local_system_inodes); | ||
554 | osb->local_system_inodes = NULL; | ||
555 | |||
556 | out: | ||
537 | mlog_exit(0); | 557 | mlog_exit(0); |
538 | } | 558 | } |
539 | 559 | ||
@@ -608,8 +628,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) | |||
608 | int ret = 0; | 628 | int ret = 0; |
609 | struct mount_options parsed_options; | 629 | struct mount_options parsed_options; |
610 | struct ocfs2_super *osb = OCFS2_SB(sb); | 630 | struct ocfs2_super *osb = OCFS2_SB(sb); |
611 | 631 | u32 tmp; | |
612 | lock_kernel(); | ||
613 | 632 | ||
614 | if (!ocfs2_parse_options(sb, data, &parsed_options, 1) || | 633 | if (!ocfs2_parse_options(sb, data, &parsed_options, 1) || |
615 | !ocfs2_check_set_options(sb, &parsed_options)) { | 634 | !ocfs2_check_set_options(sb, &parsed_options)) { |
@@ -617,8 +636,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) | |||
617 | goto out; | 636 | goto out; |
618 | } | 637 | } |
619 | 638 | ||
620 | if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) != | 639 | tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL | |
621 | (parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) { | 640 | OCFS2_MOUNT_HB_NONE; |
641 | if ((osb->s_mount_opt & tmp) != (parsed_options.mount_opt & tmp)) { | ||
622 | ret = -EINVAL; | 642 | ret = -EINVAL; |
623 | mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n"); | 643 | mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n"); |
624 | goto out; | 644 | goto out; |
@@ -717,7 +737,6 @@ unlock_osb: | |||
717 | MS_POSIXACL : 0); | 737 | MS_POSIXACL : 0); |
718 | } | 738 | } |
719 | out: | 739 | out: |
720 | unlock_kernel(); | ||
721 | return ret; | 740 | return ret; |
722 | } | 741 | } |
723 | 742 | ||
@@ -809,23 +828,29 @@ bail: | |||
809 | 828 | ||
810 | static int ocfs2_verify_heartbeat(struct ocfs2_super *osb) | 829 | static int ocfs2_verify_heartbeat(struct ocfs2_super *osb) |
811 | { | 830 | { |
812 | if (ocfs2_mount_local(osb)) { | 831 | u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL; |
813 | if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { | 832 | |
833 | if (osb->s_mount_opt & hb_enabled) { | ||
834 | if (ocfs2_mount_local(osb)) { | ||
814 | mlog(ML_ERROR, "Cannot heartbeat on a locally " | 835 | mlog(ML_ERROR, "Cannot heartbeat on a locally " |
815 | "mounted device.\n"); | 836 | "mounted device.\n"); |
816 | return -EINVAL; | 837 | return -EINVAL; |
817 | } | 838 | } |
818 | } | 839 | if (ocfs2_userspace_stack(osb)) { |
819 | |||
820 | if (ocfs2_userspace_stack(osb)) { | ||
821 | if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { | ||
822 | mlog(ML_ERROR, "Userspace stack expected, but " | 840 | mlog(ML_ERROR, "Userspace stack expected, but " |
823 | "o2cb heartbeat arguments passed to mount\n"); | 841 | "o2cb heartbeat arguments passed to mount\n"); |
824 | return -EINVAL; | 842 | return -EINVAL; |
825 | } | 843 | } |
844 | if (((osb->s_mount_opt & OCFS2_MOUNT_HB_GLOBAL) && | ||
845 | !ocfs2_cluster_o2cb_global_heartbeat(osb)) || | ||
846 | ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) && | ||
847 | ocfs2_cluster_o2cb_global_heartbeat(osb))) { | ||
848 | mlog(ML_ERROR, "Mismatching o2cb heartbeat modes\n"); | ||
849 | return -EINVAL; | ||
850 | } | ||
826 | } | 851 | } |
827 | 852 | ||
828 | if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) { | 853 | if (!(osb->s_mount_opt & hb_enabled)) { |
829 | if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) && | 854 | if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) && |
830 | !ocfs2_userspace_stack(osb)) { | 855 | !ocfs2_userspace_stack(osb)) { |
831 | mlog(ML_ERROR, "Heartbeat has to be started to mount " | 856 | mlog(ML_ERROR, "Heartbeat has to be started to mount " |
@@ -1291,6 +1316,7 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1291 | { | 1316 | { |
1292 | int status; | 1317 | int status; |
1293 | char *p; | 1318 | char *p; |
1319 | u32 tmp; | ||
1294 | 1320 | ||
1295 | mlog_entry("remount: %d, options: \"%s\"\n", is_remount, | 1321 | mlog_entry("remount: %d, options: \"%s\"\n", is_remount, |
1296 | options ? options : "(none)"); | 1322 | options ? options : "(none)"); |
@@ -1322,7 +1348,10 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1322 | mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; | 1348 | mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; |
1323 | break; | 1349 | break; |
1324 | case Opt_hb_none: | 1350 | case Opt_hb_none: |
1325 | mopt->mount_opt &= ~OCFS2_MOUNT_HB_LOCAL; | 1351 | mopt->mount_opt |= OCFS2_MOUNT_HB_NONE; |
1352 | break; | ||
1353 | case Opt_hb_global: | ||
1354 | mopt->mount_opt |= OCFS2_MOUNT_HB_GLOBAL; | ||
1326 | break; | 1355 | break; |
1327 | case Opt_barrier: | 1356 | case Opt_barrier: |
1328 | if (match_int(&args[0], &option)) { | 1357 | if (match_int(&args[0], &option)) { |
@@ -1438,6 +1467,12 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1438 | case Opt_grpquota: | 1467 | case Opt_grpquota: |
1439 | mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; | 1468 | mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; |
1440 | break; | 1469 | break; |
1470 | case Opt_coherency_buffered: | ||
1471 | mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED; | ||
1472 | break; | ||
1473 | case Opt_coherency_full: | ||
1474 | mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED; | ||
1475 | break; | ||
1441 | case Opt_acl: | 1476 | case Opt_acl: |
1442 | mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; | 1477 | mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; |
1443 | mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; | 1478 | mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; |
@@ -1477,6 +1512,15 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1477 | } | 1512 | } |
1478 | } | 1513 | } |
1479 | 1514 | ||
1515 | /* Ensure only one heartbeat mode */ | ||
1516 | tmp = mopt->mount_opt & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL | | ||
1517 | OCFS2_MOUNT_HB_NONE); | ||
1518 | if (hweight32(tmp) != 1) { | ||
1519 | mlog(ML_ERROR, "Invalid heartbeat mount options\n"); | ||
1520 | status = 0; | ||
1521 | goto bail; | ||
1522 | } | ||
1523 | |||
1480 | status = 1; | 1524 | status = 1; |
1481 | 1525 | ||
1482 | bail: | 1526 | bail: |
@@ -1490,10 +1534,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1490 | unsigned long opts = osb->s_mount_opt; | 1534 | unsigned long opts = osb->s_mount_opt; |
1491 | unsigned int local_alloc_megs; | 1535 | unsigned int local_alloc_megs; |
1492 | 1536 | ||
1493 | if (opts & OCFS2_MOUNT_HB_LOCAL) | 1537 | if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) { |
1494 | seq_printf(s, ",_netdev,heartbeat=local"); | 1538 | seq_printf(s, ",_netdev"); |
1495 | else | 1539 | if (opts & OCFS2_MOUNT_HB_LOCAL) |
1496 | seq_printf(s, ",heartbeat=none"); | 1540 | seq_printf(s, ",%s", OCFS2_HB_LOCAL); |
1541 | else | ||
1542 | seq_printf(s, ",%s", OCFS2_HB_GLOBAL); | ||
1543 | } else | ||
1544 | seq_printf(s, ",%s", OCFS2_HB_NONE); | ||
1497 | 1545 | ||
1498 | if (opts & OCFS2_MOUNT_NOINTR) | 1546 | if (opts & OCFS2_MOUNT_NOINTR) |
1499 | seq_printf(s, ",nointr"); | 1547 | seq_printf(s, ",nointr"); |
@@ -1536,6 +1584,11 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1536 | if (opts & OCFS2_MOUNT_GRPQUOTA) | 1584 | if (opts & OCFS2_MOUNT_GRPQUOTA) |
1537 | seq_printf(s, ",grpquota"); | 1585 | seq_printf(s, ",grpquota"); |
1538 | 1586 | ||
1587 | if (opts & OCFS2_MOUNT_COHERENCY_BUFFERED) | ||
1588 | seq_printf(s, ",coherency=buffered"); | ||
1589 | else | ||
1590 | seq_printf(s, ",coherency=full"); | ||
1591 | |||
1539 | if (opts & OCFS2_MOUNT_NOUSERXATTR) | 1592 | if (opts & OCFS2_MOUNT_NOUSERXATTR) |
1540 | seq_printf(s, ",nouser_xattr"); | 1593 | seq_printf(s, ",nouser_xattr"); |
1541 | else | 1594 | else |
@@ -1640,13 +1693,9 @@ static void ocfs2_put_super(struct super_block *sb) | |||
1640 | { | 1693 | { |
1641 | mlog_entry("(0x%p)\n", sb); | 1694 | mlog_entry("(0x%p)\n", sb); |
1642 | 1695 | ||
1643 | lock_kernel(); | ||
1644 | |||
1645 | ocfs2_sync_blockdev(sb); | 1696 | ocfs2_sync_blockdev(sb); |
1646 | ocfs2_dismount_volume(sb, 0); | 1697 | ocfs2_dismount_volume(sb, 0); |
1647 | 1698 | ||
1648 | unlock_kernel(); | ||
1649 | |||
1650 | mlog_exit_void(); | 1699 | mlog_exit_void(); |
1651 | } | 1700 | } |
1652 | 1701 | ||
@@ -1990,6 +2039,36 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu | |||
1990 | return 0; | 2039 | return 0; |
1991 | } | 2040 | } |
1992 | 2041 | ||
2042 | /* Make sure entire volume is addressable by our journal. Requires | ||
2043 | osb_clusters_at_boot to be valid and for the journal to have been | ||
2044 | initialized by ocfs2_journal_init(). */ | ||
2045 | static int ocfs2_journal_addressable(struct ocfs2_super *osb) | ||
2046 | { | ||
2047 | int status = 0; | ||
2048 | u64 max_block = | ||
2049 | ocfs2_clusters_to_blocks(osb->sb, | ||
2050 | osb->osb_clusters_at_boot) - 1; | ||
2051 | |||
2052 | /* 32-bit block number is always OK. */ | ||
2053 | if (max_block <= (u32)~0ULL) | ||
2054 | goto out; | ||
2055 | |||
2056 | /* Volume is "huge", so see if our journal is new enough to | ||
2057 | support it. */ | ||
2058 | if (!(OCFS2_HAS_COMPAT_FEATURE(osb->sb, | ||
2059 | OCFS2_FEATURE_COMPAT_JBD2_SB) && | ||
2060 | jbd2_journal_check_used_features(osb->journal->j_journal, 0, 0, | ||
2061 | JBD2_FEATURE_INCOMPAT_64BIT))) { | ||
2062 | mlog(ML_ERROR, "The journal cannot address the entire volume. " | ||
2063 | "Enable the 'block64' journal option with tunefs.ocfs2"); | ||
2064 | status = -EFBIG; | ||
2065 | goto out; | ||
2066 | } | ||
2067 | |||
2068 | out: | ||
2069 | return status; | ||
2070 | } | ||
2071 | |||
1993 | static int ocfs2_initialize_super(struct super_block *sb, | 2072 | static int ocfs2_initialize_super(struct super_block *sb, |
1994 | struct buffer_head *bh, | 2073 | struct buffer_head *bh, |
1995 | int sector_size, | 2074 | int sector_size, |
@@ -2002,6 +2081,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2002 | struct ocfs2_journal *journal; | 2081 | struct ocfs2_journal *journal; |
2003 | __le32 uuid_net_key; | 2082 | __le32 uuid_net_key; |
2004 | struct ocfs2_super *osb; | 2083 | struct ocfs2_super *osb; |
2084 | u64 total_blocks; | ||
2005 | 2085 | ||
2006 | mlog_entry_void(); | 2086 | mlog_entry_void(); |
2007 | 2087 | ||
@@ -2060,6 +2140,15 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2060 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", | 2140 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", |
2061 | MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); | 2141 | MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); |
2062 | 2142 | ||
2143 | osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); | ||
2144 | if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) { | ||
2145 | mlog(ML_ERROR, "Invalid number of node slots (%u)\n", | ||
2146 | osb->max_slots); | ||
2147 | status = -EINVAL; | ||
2148 | goto bail; | ||
2149 | } | ||
2150 | mlog(0, "max_slots for this device: %u\n", osb->max_slots); | ||
2151 | |||
2063 | ocfs2_orphan_scan_init(osb); | 2152 | ocfs2_orphan_scan_init(osb); |
2064 | 2153 | ||
2065 | status = ocfs2_recovery_init(osb); | 2154 | status = ocfs2_recovery_init(osb); |
@@ -2098,15 +2187,6 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2098 | goto bail; | 2187 | goto bail; |
2099 | } | 2188 | } |
2100 | 2189 | ||
2101 | osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); | ||
2102 | if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) { | ||
2103 | mlog(ML_ERROR, "Invalid number of node slots (%u)\n", | ||
2104 | osb->max_slots); | ||
2105 | status = -EINVAL; | ||
2106 | goto bail; | ||
2107 | } | ||
2108 | mlog(0, "max_slots for this device: %u\n", osb->max_slots); | ||
2109 | |||
2110 | osb->slot_recovery_generations = | 2190 | osb->slot_recovery_generations = |
2111 | kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations), | 2191 | kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations), |
2112 | GFP_KERNEL); | 2192 | GFP_KERNEL); |
@@ -2149,7 +2229,9 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2149 | goto bail; | 2229 | goto bail; |
2150 | } | 2230 | } |
2151 | 2231 | ||
2152 | if (ocfs2_userspace_stack(osb)) { | 2232 | if (ocfs2_clusterinfo_valid(osb)) { |
2233 | osb->osb_stackflags = | ||
2234 | OCFS2_RAW_SB(di)->s_cluster_info.ci_stackflags; | ||
2153 | memcpy(osb->osb_cluster_stack, | 2235 | memcpy(osb->osb_cluster_stack, |
2154 | OCFS2_RAW_SB(di)->s_cluster_info.ci_stack, | 2236 | OCFS2_RAW_SB(di)->s_cluster_info.ci_stack, |
2155 | OCFS2_STACK_LABEL_LEN); | 2237 | OCFS2_STACK_LABEL_LEN); |
@@ -2214,11 +2296,15 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2214 | goto bail; | 2296 | goto bail; |
2215 | } | 2297 | } |
2216 | 2298 | ||
2217 | if (ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters) - 1) | 2299 | total_blocks = ocfs2_clusters_to_blocks(osb->sb, |
2218 | > (u32)~0UL) { | 2300 | le32_to_cpu(di->i_clusters)); |
2219 | mlog(ML_ERROR, "Volume might try to write to blocks beyond " | 2301 | |
2220 | "what jbd can address in 32 bits.\n"); | 2302 | status = generic_check_addressable(osb->sb->s_blocksize_bits, |
2221 | status = -EINVAL; | 2303 | total_blocks); |
2304 | if (status) { | ||
2305 | mlog(ML_ERROR, "Volume too large " | ||
2306 | "to mount safely on this system"); | ||
2307 | status = -EFBIG; | ||
2222 | goto bail; | 2308 | goto bail; |
2223 | } | 2309 | } |
2224 | 2310 | ||
@@ -2380,6 +2466,12 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) | |||
2380 | goto finally; | 2466 | goto finally; |
2381 | } | 2467 | } |
2382 | 2468 | ||
2469 | /* Now that journal has been initialized, check to make sure | ||
2470 | entire volume is addressable. */ | ||
2471 | status = ocfs2_journal_addressable(osb); | ||
2472 | if (status) | ||
2473 | goto finally; | ||
2474 | |||
2383 | /* If the journal was unmounted cleanly then we don't want to | 2475 | /* If the journal was unmounted cleanly then we don't want to |
2384 | * recover anything. Otherwise, journal_load will do that | 2476 | * recover anything. Otherwise, journal_load will do that |
2385 | * dirty work for us :) */ | 2477 | * dirty work for us :) */ |