| .. | .. |
|---|
| 13 | 13 | #include <linux/blkdev.h> |
|---|
| 14 | 14 | #include <linux/backing-dev.h> |
|---|
| 15 | 15 | #include <linux/random.h> |
|---|
| 16 | +#include <linux/log2.h> |
|---|
| 16 | 17 | #include <linux/crc32.h> |
|---|
| 17 | 18 | #include "nilfs.h" |
|---|
| 18 | 19 | #include "segment.h" |
|---|
| .. | .. |
|---|
| 86 | 87 | { |
|---|
| 87 | 88 | might_sleep(); |
|---|
| 88 | 89 | if (nilfs_init(nilfs)) { |
|---|
| 89 | | - nilfs_sysfs_delete_device_group(nilfs); |
|---|
| 90 | 90 | brelse(nilfs->ns_sbh[0]); |
|---|
| 91 | 91 | brelse(nilfs->ns_sbh[1]); |
|---|
| 92 | 92 | } |
|---|
| .. | .. |
|---|
| 193 | 193 | } |
|---|
| 194 | 194 | |
|---|
| 195 | 195 | /** |
|---|
| 196 | + * nilfs_get_blocksize - get block size from raw superblock data |
|---|
| 197 | + * @sb: super block instance |
|---|
| 198 | + * @sbp: superblock raw data buffer |
|---|
| 199 | + * @blocksize: place to store block size |
|---|
| 200 | + * |
|---|
| 201 | + * nilfs_get_blocksize() calculates the block size from the block size |
|---|
| 202 | + * exponent information written in @sbp and stores it in @blocksize, |
|---|
| 203 | + * or aborts with an error message if it's too large. |
|---|
| 204 | + * |
|---|
| 205 | + * Return Value: On success, 0 is returned. If the block size is too |
|---|
| 206 | + * large, -EINVAL is returned. |
|---|
| 207 | + */ |
|---|
| 208 | +static int nilfs_get_blocksize(struct super_block *sb, |
|---|
| 209 | + struct nilfs_super_block *sbp, int *blocksize) |
|---|
| 210 | +{ |
|---|
| 211 | + unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); |
|---|
| 212 | + |
|---|
| 213 | + if (unlikely(shift_bits > |
|---|
| 214 | + ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS)) { |
|---|
| 215 | + nilfs_err(sb, "too large filesystem blocksize: 2 ^ %u KiB", |
|---|
| 216 | + shift_bits); |
|---|
| 217 | + return -EINVAL; |
|---|
| 218 | + } |
|---|
| 219 | + *blocksize = BLOCK_SIZE << shift_bits; |
|---|
| 220 | + return 0; |
|---|
| 221 | +} |
|---|
| 222 | + |
|---|
| 223 | +/** |
|---|
| 196 | 224 | * load_nilfs - load and recover the nilfs |
|---|
| 197 | 225 | * @nilfs: the_nilfs structure to be released |
|---|
| 198 | 226 | * @sb: super block isntance used to recover past segment |
|---|
| .. | .. |
|---|
| 245 | 273 | nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); |
|---|
| 246 | 274 | |
|---|
| 247 | 275 | /* verify consistency between two super blocks */ |
|---|
| 248 | | - blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); |
|---|
| 276 | + err = nilfs_get_blocksize(sb, sbp[0], &blocksize); |
|---|
| 277 | + if (err) |
|---|
| 278 | + goto scan_error; |
|---|
| 279 | + |
|---|
| 249 | 280 | if (blocksize != nilfs->ns_blocksize) { |
|---|
| 250 | 281 | nilfs_warn(sb, |
|---|
| 251 | 282 | "blocksize differs between two super blocks (%d != %d)", |
|---|
| 252 | 283 | blocksize, nilfs->ns_blocksize); |
|---|
| 284 | + err = -EINVAL; |
|---|
| 253 | 285 | goto scan_error; |
|---|
| 254 | 286 | } |
|---|
| 255 | 287 | |
|---|
| .. | .. |
|---|
| 271 | 303 | nilfs_err(sb, "error %d while loading super root", err); |
|---|
| 272 | 304 | goto failed; |
|---|
| 273 | 305 | } |
|---|
| 306 | + |
|---|
| 307 | + err = nilfs_sysfs_create_device_group(sb); |
|---|
| 308 | + if (unlikely(err)) |
|---|
| 309 | + goto sysfs_error; |
|---|
| 274 | 310 | |
|---|
| 275 | 311 | if (valid_fs) |
|---|
| 276 | 312 | goto skip_recovery; |
|---|
| .. | .. |
|---|
| 333 | 369 | goto failed; |
|---|
| 334 | 370 | |
|---|
| 335 | 371 | failed_unload: |
|---|
| 372 | + nilfs_sysfs_delete_device_group(nilfs); |
|---|
| 373 | + |
|---|
| 374 | + sysfs_error: |
|---|
| 336 | 375 | iput(nilfs->ns_cpfile); |
|---|
| 337 | 376 | iput(nilfs->ns_sufile); |
|---|
| 338 | 377 | iput(nilfs->ns_dat); |
|---|
| .. | .. |
|---|
| 366 | 405 | 100)); |
|---|
| 367 | 406 | } |
|---|
| 368 | 407 | |
|---|
| 408 | +/** |
|---|
| 409 | + * nilfs_max_segment_count - calculate the maximum number of segments |
|---|
| 410 | + * @nilfs: nilfs object |
|---|
| 411 | + */ |
|---|
| 412 | +static u64 nilfs_max_segment_count(struct the_nilfs *nilfs) |
|---|
| 413 | +{ |
|---|
| 414 | + u64 max_count = U64_MAX; |
|---|
| 415 | + |
|---|
| 416 | + do_div(max_count, nilfs->ns_blocks_per_segment); |
|---|
| 417 | + return min_t(u64, max_count, ULONG_MAX); |
|---|
| 418 | +} |
|---|
| 419 | + |
|---|
| 369 | 420 | void nilfs_set_nsegments(struct the_nilfs *nilfs, unsigned long nsegs) |
|---|
| 370 | 421 | { |
|---|
| 371 | 422 | nilfs->ns_nsegments = nsegs; |
|---|
| .. | .. |
|---|
| 375 | 426 | static int nilfs_store_disk_layout(struct the_nilfs *nilfs, |
|---|
| 376 | 427 | struct nilfs_super_block *sbp) |
|---|
| 377 | 428 | { |
|---|
| 429 | + u64 nsegments, nblocks; |
|---|
| 430 | + |
|---|
| 378 | 431 | if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) { |
|---|
| 379 | 432 | nilfs_err(nilfs->ns_sb, |
|---|
| 380 | 433 | "unsupported revision (superblock rev.=%d.%d, current rev.=%d.%d). Please check the version of mkfs.nilfs(2).", |
|---|
| .. | .. |
|---|
| 418 | 471 | return -EINVAL; |
|---|
| 419 | 472 | } |
|---|
| 420 | 473 | |
|---|
| 421 | | - nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments)); |
|---|
| 474 | + nsegments = le64_to_cpu(sbp->s_nsegments); |
|---|
| 475 | + if (nsegments > nilfs_max_segment_count(nilfs)) { |
|---|
| 476 | + nilfs_err(nilfs->ns_sb, |
|---|
| 477 | + "segment count %llu exceeds upper limit (%llu segments)", |
|---|
| 478 | + (unsigned long long)nsegments, |
|---|
| 479 | + (unsigned long long)nilfs_max_segment_count(nilfs)); |
|---|
| 480 | + return -EINVAL; |
|---|
| 481 | + } |
|---|
| 482 | + |
|---|
| 483 | + nblocks = (u64)i_size_read(nilfs->ns_sb->s_bdev->bd_inode) >> |
|---|
| 484 | + nilfs->ns_sb->s_blocksize_bits; |
|---|
| 485 | + if (nblocks) { |
|---|
| 486 | + u64 min_block_count = nsegments * nilfs->ns_blocks_per_segment; |
|---|
| 487 | + /* |
|---|
| 488 | + * To avoid failing to mount early device images without a |
|---|
| 489 | + * second superblock, exclude that block count from the |
|---|
| 490 | + * "min_block_count" calculation. |
|---|
| 491 | + */ |
|---|
| 492 | + |
|---|
| 493 | + if (nblocks < min_block_count) { |
|---|
| 494 | + nilfs_err(nilfs->ns_sb, |
|---|
| 495 | + "total number of segment blocks %llu exceeds device size (%llu blocks)", |
|---|
| 496 | + (unsigned long long)min_block_count, |
|---|
| 497 | + (unsigned long long)nblocks); |
|---|
| 498 | + return -EINVAL; |
|---|
| 499 | + } |
|---|
| 500 | + } |
|---|
| 501 | + |
|---|
| 502 | + nilfs_set_nsegments(nilfs, nsegments); |
|---|
| 422 | 503 | nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed); |
|---|
| 423 | 504 | return 0; |
|---|
| 424 | 505 | } |
|---|
| .. | .. |
|---|
| 443 | 524 | return crc == le32_to_cpu(sbp->s_sum); |
|---|
| 444 | 525 | } |
|---|
| 445 | 526 | |
|---|
| 446 | | -static int nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) |
|---|
| 527 | +/** |
|---|
| 528 | + * nilfs_sb2_bad_offset - check the location of the second superblock |
|---|
| 529 | + * @sbp: superblock raw data buffer |
|---|
| 530 | + * @offset: byte offset of second superblock calculated from device size |
|---|
| 531 | + * |
|---|
| 532 | + * nilfs_sb2_bad_offset() checks if the position on the second |
|---|
| 533 | + * superblock is valid or not based on the filesystem parameters |
|---|
| 534 | + * stored in @sbp. If @offset points to a location within the segment |
|---|
| 535 | + * area, or if the parameters themselves are not normal, it is |
|---|
| 536 | + * determined to be invalid. |
|---|
| 537 | + * |
|---|
| 538 | + * Return Value: true if invalid, false if valid. |
|---|
| 539 | + */ |
|---|
| 540 | +static bool nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) |
|---|
| 447 | 541 | { |
|---|
| 448 | | - return offset < ((le64_to_cpu(sbp->s_nsegments) * |
|---|
| 449 | | - le32_to_cpu(sbp->s_blocks_per_segment)) << |
|---|
| 450 | | - (le32_to_cpu(sbp->s_log_block_size) + 10)); |
|---|
| 542 | + unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); |
|---|
| 543 | + u32 blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); |
|---|
| 544 | + u64 nsegments = le64_to_cpu(sbp->s_nsegments); |
|---|
| 545 | + u64 index; |
|---|
| 546 | + |
|---|
| 547 | + if (blocks_per_segment < NILFS_SEG_MIN_BLOCKS || |
|---|
| 548 | + shift_bits > ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS) |
|---|
| 549 | + return true; |
|---|
| 550 | + |
|---|
| 551 | + index = offset >> (shift_bits + BLOCK_SIZE_BITS); |
|---|
| 552 | + do_div(index, blocks_per_segment); |
|---|
| 553 | + return index < nsegments; |
|---|
| 451 | 554 | } |
|---|
| 452 | 555 | |
|---|
| 453 | 556 | static void nilfs_release_super_block(struct the_nilfs *nilfs) |
|---|
| .. | .. |
|---|
| 489 | 592 | { |
|---|
| 490 | 593 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
|---|
| 491 | 594 | struct buffer_head **sbh = nilfs->ns_sbh; |
|---|
| 492 | | - u64 sb2off = NILFS_SB2_OFFSET_BYTES(nilfs->ns_bdev->bd_inode->i_size); |
|---|
| 595 | + u64 sb2off, devsize = nilfs->ns_bdev->bd_inode->i_size; |
|---|
| 493 | 596 | int valid[2], swp = 0; |
|---|
| 597 | + |
|---|
| 598 | + if (devsize < NILFS_SEG_MIN_BLOCKS * NILFS_MIN_BLOCK_SIZE + 4096) { |
|---|
| 599 | + nilfs_err(sb, "device size too small"); |
|---|
| 600 | + return -EINVAL; |
|---|
| 601 | + } |
|---|
| 602 | + sb2off = NILFS_SB2_OFFSET_BYTES(devsize); |
|---|
| 494 | 603 | |
|---|
| 495 | 604 | sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize, |
|---|
| 496 | 605 | &sbh[0]); |
|---|
| .. | .. |
|---|
| 586 | 695 | if (err) |
|---|
| 587 | 696 | goto failed_sbh; |
|---|
| 588 | 697 | |
|---|
| 589 | | - blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
|---|
| 590 | | - if (blocksize < NILFS_MIN_BLOCK_SIZE || |
|---|
| 591 | | - blocksize > NILFS_MAX_BLOCK_SIZE) { |
|---|
| 698 | + err = nilfs_get_blocksize(sb, sbp, &blocksize); |
|---|
| 699 | + if (err) |
|---|
| 700 | + goto failed_sbh; |
|---|
| 701 | + |
|---|
| 702 | + if (blocksize < NILFS_MIN_BLOCK_SIZE) { |
|---|
| 592 | 703 | nilfs_err(sb, |
|---|
| 593 | 704 | "couldn't mount because of unsupported filesystem blocksize %d", |
|---|
| 594 | 705 | blocksize); |
|---|
| .. | .. |
|---|
| 631 | 742 | nilfs->ns_mount_state = le16_to_cpu(sbp->s_state); |
|---|
| 632 | 743 | |
|---|
| 633 | 744 | err = nilfs_store_log_cursor(nilfs, sbp); |
|---|
| 634 | | - if (err) |
|---|
| 635 | | - goto failed_sbh; |
|---|
| 636 | | - |
|---|
| 637 | | - err = nilfs_sysfs_create_device_group(sb); |
|---|
| 638 | 745 | if (err) |
|---|
| 639 | 746 | goto failed_sbh; |
|---|
| 640 | 747 | |
|---|