diff options
Diffstat (limited to 'fs/ocfs2/super.c')
-rw-r--r-- | fs/ocfs2/super.c | 104 |
1 files changed, 87 insertions, 17 deletions
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 4e009ad303a1..a8a0ca44f88f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -178,6 +178,8 @@ enum { | |||
178 | Opt_noacl, | 178 | Opt_noacl, |
179 | Opt_usrquota, | 179 | Opt_usrquota, |
180 | Opt_grpquota, | 180 | Opt_grpquota, |
181 | Opt_coherency_buffered, | ||
182 | Opt_coherency_full, | ||
181 | Opt_resv_level, | 183 | Opt_resv_level, |
182 | Opt_dir_resv_level, | 184 | Opt_dir_resv_level, |
183 | Opt_err, | 185 | Opt_err, |
@@ -207,6 +209,8 @@ static const match_table_t tokens = { | |||
207 | {Opt_noacl, "noacl"}, | 209 | {Opt_noacl, "noacl"}, |
208 | {Opt_usrquota, "usrquota"}, | 210 | {Opt_usrquota, "usrquota"}, |
209 | {Opt_grpquota, "grpquota"}, | 211 | {Opt_grpquota, "grpquota"}, |
212 | {Opt_coherency_buffered, "coherency=buffered"}, | ||
213 | {Opt_coherency_full, "coherency=full"}, | ||
210 | {Opt_resv_level, "resv_level=%u"}, | 214 | {Opt_resv_level, "resv_level=%u"}, |
211 | {Opt_dir_resv_level, "dir_resv_level=%u"}, | 215 | {Opt_dir_resv_level, "dir_resv_level=%u"}, |
212 | {Opt_err, NULL} | 216 | {Opt_err, NULL} |
@@ -516,11 +520,11 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) | |||
516 | 520 | ||
517 | mlog_entry_void(); | 521 | mlog_entry_void(); |
518 | 522 | ||
519 | for (i = 0; i < NUM_SYSTEM_INODES; i++) { | 523 | for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) { |
520 | inode = osb->system_inodes[i]; | 524 | inode = osb->global_system_inodes[i]; |
521 | if (inode) { | 525 | if (inode) { |
522 | iput(inode); | 526 | iput(inode); |
523 | osb->system_inodes[i] = NULL; | 527 | osb->global_system_inodes[i] = NULL; |
524 | } | 528 | } |
525 | } | 529 | } |
526 | 530 | ||
@@ -536,6 +540,20 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) | |||
536 | osb->root_inode = NULL; | 540 | osb->root_inode = NULL; |
537 | } | 541 | } |
538 | 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: | ||
539 | mlog_exit(0); | 557 | mlog_exit(0); |
540 | } | 558 | } |
541 | 559 | ||
@@ -1452,6 +1470,12 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1452 | case Opt_grpquota: | 1470 | case Opt_grpquota: |
1453 | mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; | 1471 | mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA; |
1454 | break; | 1472 | break; |
1473 | case Opt_coherency_buffered: | ||
1474 | mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED; | ||
1475 | break; | ||
1476 | case Opt_coherency_full: | ||
1477 | mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED; | ||
1478 | break; | ||
1455 | case Opt_acl: | 1479 | case Opt_acl: |
1456 | mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; | 1480 | mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL; |
1457 | mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; | 1481 | mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL; |
@@ -1563,6 +1587,11 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1563 | if (opts & OCFS2_MOUNT_GRPQUOTA) | 1587 | if (opts & OCFS2_MOUNT_GRPQUOTA) |
1564 | seq_printf(s, ",grpquota"); | 1588 | seq_printf(s, ",grpquota"); |
1565 | 1589 | ||
1590 | if (opts & OCFS2_MOUNT_COHERENCY_BUFFERED) | ||
1591 | seq_printf(s, ",coherency=buffered"); | ||
1592 | else | ||
1593 | seq_printf(s, ",coherency=full"); | ||
1594 | |||
1566 | if (opts & OCFS2_MOUNT_NOUSERXATTR) | 1595 | if (opts & OCFS2_MOUNT_NOUSERXATTR) |
1567 | seq_printf(s, ",nouser_xattr"); | 1596 | seq_printf(s, ",nouser_xattr"); |
1568 | else | 1597 | else |
@@ -2017,6 +2046,36 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu | |||
2017 | return 0; | 2046 | return 0; |
2018 | } | 2047 | } |
2019 | 2048 | ||
2049 | /* Make sure entire volume is addressable by our journal. Requires | ||
2050 | osb_clusters_at_boot to be valid and for the journal to have been | ||
2051 | initialized by ocfs2_journal_init(). */ | ||
2052 | static int ocfs2_journal_addressable(struct ocfs2_super *osb) | ||
2053 | { | ||
2054 | int status = 0; | ||
2055 | u64 max_block = | ||
2056 | ocfs2_clusters_to_blocks(osb->sb, | ||
2057 | osb->osb_clusters_at_boot) - 1; | ||
2058 | |||
2059 | /* 32-bit block number is always OK. */ | ||
2060 | if (max_block <= (u32)~0ULL) | ||
2061 | goto out; | ||
2062 | |||
2063 | /* Volume is "huge", so see if our journal is new enough to | ||
2064 | support it. */ | ||
2065 | if (!(OCFS2_HAS_COMPAT_FEATURE(osb->sb, | ||
2066 | OCFS2_FEATURE_COMPAT_JBD2_SB) && | ||
2067 | jbd2_journal_check_used_features(osb->journal->j_journal, 0, 0, | ||
2068 | JBD2_FEATURE_INCOMPAT_64BIT))) { | ||
2069 | mlog(ML_ERROR, "The journal cannot address the entire volume. " | ||
2070 | "Enable the 'block64' journal option with tunefs.ocfs2"); | ||
2071 | status = -EFBIG; | ||
2072 | goto out; | ||
2073 | } | ||
2074 | |||
2075 | out: | ||
2076 | return status; | ||
2077 | } | ||
2078 | |||
2020 | static int ocfs2_initialize_super(struct super_block *sb, | 2079 | static int ocfs2_initialize_super(struct super_block *sb, |
2021 | struct buffer_head *bh, | 2080 | struct buffer_head *bh, |
2022 | int sector_size, | 2081 | int sector_size, |
@@ -2029,6 +2088,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2029 | struct ocfs2_journal *journal; | 2088 | struct ocfs2_journal *journal; |
2030 | __le32 uuid_net_key; | 2089 | __le32 uuid_net_key; |
2031 | struct ocfs2_super *osb; | 2090 | struct ocfs2_super *osb; |
2091 | u64 total_blocks; | ||
2032 | 2092 | ||
2033 | mlog_entry_void(); | 2093 | mlog_entry_void(); |
2034 | 2094 | ||
@@ -2087,6 +2147,15 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2087 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", | 2147 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", |
2088 | MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); | 2148 | MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); |
2089 | 2149 | ||
2150 | osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); | ||
2151 | if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) { | ||
2152 | mlog(ML_ERROR, "Invalid number of node slots (%u)\n", | ||
2153 | osb->max_slots); | ||
2154 | status = -EINVAL; | ||
2155 | goto bail; | ||
2156 | } | ||
2157 | mlog(0, "max_slots for this device: %u\n", osb->max_slots); | ||
2158 | |||
2090 | ocfs2_orphan_scan_init(osb); | 2159 | ocfs2_orphan_scan_init(osb); |
2091 | 2160 | ||
2092 | status = ocfs2_recovery_init(osb); | 2161 | status = ocfs2_recovery_init(osb); |
@@ -2125,15 +2194,6 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2125 | goto bail; | 2194 | goto bail; |
2126 | } | 2195 | } |
2127 | 2196 | ||
2128 | osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); | ||
2129 | if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) { | ||
2130 | mlog(ML_ERROR, "Invalid number of node slots (%u)\n", | ||
2131 | osb->max_slots); | ||
2132 | status = -EINVAL; | ||
2133 | goto bail; | ||
2134 | } | ||
2135 | mlog(0, "max_slots for this device: %u\n", osb->max_slots); | ||
2136 | |||
2137 | osb->slot_recovery_generations = | 2197 | osb->slot_recovery_generations = |
2138 | kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations), | 2198 | kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations), |
2139 | GFP_KERNEL); | 2199 | GFP_KERNEL); |
@@ -2243,11 +2303,15 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2243 | goto bail; | 2303 | goto bail; |
2244 | } | 2304 | } |
2245 | 2305 | ||
2246 | if (ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters) - 1) | 2306 | total_blocks = ocfs2_clusters_to_blocks(osb->sb, |
2247 | > (u32)~0UL) { | 2307 | le32_to_cpu(di->i_clusters)); |
2248 | mlog(ML_ERROR, "Volume might try to write to blocks beyond " | 2308 | |
2249 | "what jbd can address in 32 bits.\n"); | 2309 | status = generic_check_addressable(osb->sb->s_blocksize_bits, |
2250 | status = -EINVAL; | 2310 | total_blocks); |
2311 | if (status) { | ||
2312 | mlog(ML_ERROR, "Volume too large " | ||
2313 | "to mount safely on this system"); | ||
2314 | status = -EFBIG; | ||
2251 | goto bail; | 2315 | goto bail; |
2252 | } | 2316 | } |
2253 | 2317 | ||
@@ -2409,6 +2473,12 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) | |||
2409 | goto finally; | 2473 | goto finally; |
2410 | } | 2474 | } |
2411 | 2475 | ||
2476 | /* Now that journal has been initialized, check to make sure | ||
2477 | entire volume is addressable. */ | ||
2478 | status = ocfs2_journal_addressable(osb); | ||
2479 | if (status) | ||
2480 | goto finally; | ||
2481 | |||
2412 | /* If the journal was unmounted cleanly then we don't want to | 2482 | /* If the journal was unmounted cleanly then we don't want to |
2413 | * recover anything. Otherwise, journal_load will do that | 2483 | * recover anything. Otherwise, journal_load will do that |
2414 | * dirty work for us :) */ | 2484 | * dirty work for us :) */ |