| .. | .. |
|---|
| 417 | 417 | #define ext4_get_tstamp(es, tstamp) \ |
|---|
| 418 | 418 | __ext4_get_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi) |
|---|
| 419 | 419 | |
|---|
| 420 | | -static void __save_error_info(struct super_block *sb, int error, |
|---|
| 421 | | - __u32 ino, __u64 block, |
|---|
| 422 | | - const char *func, unsigned int line) |
|---|
| 423 | | -{ |
|---|
| 424 | | - struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
|---|
| 425 | | - int err; |
|---|
| 426 | | - |
|---|
| 427 | | - EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; |
|---|
| 428 | | - if (bdev_read_only(sb->s_bdev)) |
|---|
| 429 | | - return; |
|---|
| 430 | | - es->s_state |= cpu_to_le16(EXT4_ERROR_FS); |
|---|
| 431 | | - ext4_update_tstamp(es, s_last_error_time); |
|---|
| 432 | | - strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); |
|---|
| 433 | | - es->s_last_error_line = cpu_to_le32(line); |
|---|
| 434 | | - es->s_last_error_ino = cpu_to_le32(ino); |
|---|
| 435 | | - es->s_last_error_block = cpu_to_le64(block); |
|---|
| 436 | | - switch (error) { |
|---|
| 437 | | - case EIO: |
|---|
| 438 | | - err = EXT4_ERR_EIO; |
|---|
| 439 | | - break; |
|---|
| 440 | | - case ENOMEM: |
|---|
| 441 | | - err = EXT4_ERR_ENOMEM; |
|---|
| 442 | | - break; |
|---|
| 443 | | - case EFSBADCRC: |
|---|
| 444 | | - err = EXT4_ERR_EFSBADCRC; |
|---|
| 445 | | - break; |
|---|
| 446 | | - case 0: |
|---|
| 447 | | - case EFSCORRUPTED: |
|---|
| 448 | | - err = EXT4_ERR_EFSCORRUPTED; |
|---|
| 449 | | - break; |
|---|
| 450 | | - case ENOSPC: |
|---|
| 451 | | - err = EXT4_ERR_ENOSPC; |
|---|
| 452 | | - break; |
|---|
| 453 | | - case ENOKEY: |
|---|
| 454 | | - err = EXT4_ERR_ENOKEY; |
|---|
| 455 | | - break; |
|---|
| 456 | | - case EROFS: |
|---|
| 457 | | - err = EXT4_ERR_EROFS; |
|---|
| 458 | | - break; |
|---|
| 459 | | - case EFBIG: |
|---|
| 460 | | - err = EXT4_ERR_EFBIG; |
|---|
| 461 | | - break; |
|---|
| 462 | | - case EEXIST: |
|---|
| 463 | | - err = EXT4_ERR_EEXIST; |
|---|
| 464 | | - break; |
|---|
| 465 | | - case ERANGE: |
|---|
| 466 | | - err = EXT4_ERR_ERANGE; |
|---|
| 467 | | - break; |
|---|
| 468 | | - case EOVERFLOW: |
|---|
| 469 | | - err = EXT4_ERR_EOVERFLOW; |
|---|
| 470 | | - break; |
|---|
| 471 | | - case EBUSY: |
|---|
| 472 | | - err = EXT4_ERR_EBUSY; |
|---|
| 473 | | - break; |
|---|
| 474 | | - case ENOTDIR: |
|---|
| 475 | | - err = EXT4_ERR_ENOTDIR; |
|---|
| 476 | | - break; |
|---|
| 477 | | - case ENOTEMPTY: |
|---|
| 478 | | - err = EXT4_ERR_ENOTEMPTY; |
|---|
| 479 | | - break; |
|---|
| 480 | | - case ESHUTDOWN: |
|---|
| 481 | | - err = EXT4_ERR_ESHUTDOWN; |
|---|
| 482 | | - break; |
|---|
| 483 | | - case EFAULT: |
|---|
| 484 | | - err = EXT4_ERR_EFAULT; |
|---|
| 485 | | - break; |
|---|
| 486 | | - default: |
|---|
| 487 | | - err = EXT4_ERR_UNKNOWN; |
|---|
| 488 | | - } |
|---|
| 489 | | - es->s_last_error_errcode = err; |
|---|
| 490 | | - if (!es->s_first_error_time) { |
|---|
| 491 | | - es->s_first_error_time = es->s_last_error_time; |
|---|
| 492 | | - es->s_first_error_time_hi = es->s_last_error_time_hi; |
|---|
| 493 | | - strncpy(es->s_first_error_func, func, |
|---|
| 494 | | - sizeof(es->s_first_error_func)); |
|---|
| 495 | | - es->s_first_error_line = cpu_to_le32(line); |
|---|
| 496 | | - es->s_first_error_ino = es->s_last_error_ino; |
|---|
| 497 | | - es->s_first_error_block = es->s_last_error_block; |
|---|
| 498 | | - es->s_first_error_errcode = es->s_last_error_errcode; |
|---|
| 499 | | - } |
|---|
| 500 | | - /* |
|---|
| 501 | | - * Start the daily error reporting function if it hasn't been |
|---|
| 502 | | - * started already |
|---|
| 503 | | - */ |
|---|
| 504 | | - if (!es->s_error_count) |
|---|
| 505 | | - mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ); |
|---|
| 506 | | - le32_add_cpu(&es->s_error_count, 1); |
|---|
| 507 | | -} |
|---|
| 508 | | - |
|---|
| 509 | | -static void save_error_info(struct super_block *sb, int error, |
|---|
| 510 | | - __u32 ino, __u64 block, |
|---|
| 511 | | - const char *func, unsigned int line) |
|---|
| 512 | | -{ |
|---|
| 513 | | - __save_error_info(sb, error, ino, block, func, line); |
|---|
| 514 | | - if (!bdev_read_only(sb->s_bdev)) |
|---|
| 515 | | - ext4_commit_super(sb, 1); |
|---|
| 516 | | -} |
|---|
| 517 | | - |
|---|
| 518 | 420 | /* |
|---|
| 519 | 421 | * The del_gendisk() function uninitializes the disk-specific data |
|---|
| 520 | 422 | * structures, including the bdi structure, without telling anyone |
|---|
| .. | .. |
|---|
| 641 | 543 | { |
|---|
| 642 | 544 | return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF |
|---|
| 643 | 545 | || system_state == SYSTEM_RESTART; |
|---|
| 546 | +} |
|---|
| 547 | + |
|---|
| 548 | +struct ext4_err_translation { |
|---|
| 549 | + int code; |
|---|
| 550 | + int errno; |
|---|
| 551 | +}; |
|---|
| 552 | + |
|---|
| 553 | +#define EXT4_ERR_TRANSLATE(err) { .code = EXT4_ERR_##err, .errno = err } |
|---|
| 554 | + |
|---|
| 555 | +static struct ext4_err_translation err_translation[] = { |
|---|
| 556 | + EXT4_ERR_TRANSLATE(EIO), |
|---|
| 557 | + EXT4_ERR_TRANSLATE(ENOMEM), |
|---|
| 558 | + EXT4_ERR_TRANSLATE(EFSBADCRC), |
|---|
| 559 | + EXT4_ERR_TRANSLATE(EFSCORRUPTED), |
|---|
| 560 | + EXT4_ERR_TRANSLATE(ENOSPC), |
|---|
| 561 | + EXT4_ERR_TRANSLATE(ENOKEY), |
|---|
| 562 | + EXT4_ERR_TRANSLATE(EROFS), |
|---|
| 563 | + EXT4_ERR_TRANSLATE(EFBIG), |
|---|
| 564 | + EXT4_ERR_TRANSLATE(EEXIST), |
|---|
| 565 | + EXT4_ERR_TRANSLATE(ERANGE), |
|---|
| 566 | + EXT4_ERR_TRANSLATE(EOVERFLOW), |
|---|
| 567 | + EXT4_ERR_TRANSLATE(EBUSY), |
|---|
| 568 | + EXT4_ERR_TRANSLATE(ENOTDIR), |
|---|
| 569 | + EXT4_ERR_TRANSLATE(ENOTEMPTY), |
|---|
| 570 | + EXT4_ERR_TRANSLATE(ESHUTDOWN), |
|---|
| 571 | + EXT4_ERR_TRANSLATE(EFAULT), |
|---|
| 572 | +}; |
|---|
| 573 | + |
|---|
| 574 | +static int ext4_errno_to_code(int errno) |
|---|
| 575 | +{ |
|---|
| 576 | + int i; |
|---|
| 577 | + |
|---|
| 578 | + for (i = 0; i < ARRAY_SIZE(err_translation); i++) |
|---|
| 579 | + if (err_translation[i].errno == errno) |
|---|
| 580 | + return err_translation[i].code; |
|---|
| 581 | + return EXT4_ERR_UNKNOWN; |
|---|
| 582 | +} |
|---|
| 583 | + |
|---|
| 584 | +static void __save_error_info(struct super_block *sb, int error, |
|---|
| 585 | + __u32 ino, __u64 block, |
|---|
| 586 | + const char *func, unsigned int line) |
|---|
| 587 | +{ |
|---|
| 588 | + struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
|---|
| 589 | + |
|---|
| 590 | + EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; |
|---|
| 591 | + if (bdev_read_only(sb->s_bdev)) |
|---|
| 592 | + return; |
|---|
| 593 | + /* We default to EFSCORRUPTED error... */ |
|---|
| 594 | + if (error == 0) |
|---|
| 595 | + error = EFSCORRUPTED; |
|---|
| 596 | + es->s_state |= cpu_to_le16(EXT4_ERROR_FS); |
|---|
| 597 | + ext4_update_tstamp(es, s_last_error_time); |
|---|
| 598 | + strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); |
|---|
| 599 | + es->s_last_error_line = cpu_to_le32(line); |
|---|
| 600 | + es->s_last_error_ino = cpu_to_le32(ino); |
|---|
| 601 | + es->s_last_error_block = cpu_to_le64(block); |
|---|
| 602 | + es->s_last_error_errcode = ext4_errno_to_code(error); |
|---|
| 603 | + if (!es->s_first_error_time) { |
|---|
| 604 | + es->s_first_error_time = es->s_last_error_time; |
|---|
| 605 | + es->s_first_error_time_hi = es->s_last_error_time_hi; |
|---|
| 606 | + strncpy(es->s_first_error_func, func, |
|---|
| 607 | + sizeof(es->s_first_error_func)); |
|---|
| 608 | + es->s_first_error_line = cpu_to_le32(line); |
|---|
| 609 | + es->s_first_error_ino = es->s_last_error_ino; |
|---|
| 610 | + es->s_first_error_block = es->s_last_error_block; |
|---|
| 611 | + es->s_first_error_errcode = es->s_last_error_errcode; |
|---|
| 612 | + } |
|---|
| 613 | + /* |
|---|
| 614 | + * Start the daily error reporting function if it hasn't been |
|---|
| 615 | + * started already |
|---|
| 616 | + */ |
|---|
| 617 | + if (!es->s_error_count) |
|---|
| 618 | + mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ); |
|---|
| 619 | + le32_add_cpu(&es->s_error_count, 1); |
|---|
| 620 | +} |
|---|
| 621 | + |
|---|
| 622 | +static void save_error_info(struct super_block *sb, int error, |
|---|
| 623 | + __u32 ino, __u64 block, |
|---|
| 624 | + const char *func, unsigned int line) |
|---|
| 625 | +{ |
|---|
| 626 | + __save_error_info(sb, error, ino, block, func, line); |
|---|
| 627 | + if (!bdev_read_only(sb->s_bdev)) |
|---|
| 628 | + ext4_commit_super(sb, 1); |
|---|
| 644 | 629 | } |
|---|
| 645 | 630 | |
|---|
| 646 | 631 | /* Deal with the reporting of failure conditions on a filesystem such as |
|---|
| .. | .. |
|---|
| 1026 | 1011 | struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL); |
|---|
| 1027 | 1012 | int ret; |
|---|
| 1028 | 1013 | |
|---|
| 1014 | + if (!grp || !gdp) |
|---|
| 1015 | + return; |
|---|
| 1029 | 1016 | if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT) { |
|---|
| 1030 | 1017 | ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, |
|---|
| 1031 | 1018 | &grp->bb_state); |
|---|
| .. | .. |
|---|
| 1104 | 1091 | struct block_device *bdev; |
|---|
| 1105 | 1092 | bdev = sbi->s_journal_bdev; |
|---|
| 1106 | 1093 | if (bdev) { |
|---|
| 1094 | + /* |
|---|
| 1095 | + * Invalidate the journal device's buffers. We don't want them |
|---|
| 1096 | + * floating about in memory - the physical journal device may |
|---|
| 1097 | + * hotswapped, and it breaks the `ro-after' testing code. |
|---|
| 1098 | + */ |
|---|
| 1099 | + invalidate_bdev(bdev); |
|---|
| 1107 | 1100 | ext4_blkdev_put(bdev); |
|---|
| 1108 | 1101 | sbi->s_journal_bdev = NULL; |
|---|
| 1109 | 1102 | } |
|---|
| .. | .. |
|---|
| 1243 | 1236 | sync_blockdev(sb->s_bdev); |
|---|
| 1244 | 1237 | invalidate_bdev(sb->s_bdev); |
|---|
| 1245 | 1238 | if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) { |
|---|
| 1246 | | - /* |
|---|
| 1247 | | - * Invalidate the journal device's buffers. We don't want them |
|---|
| 1248 | | - * floating about in memory - the physical journal device may |
|---|
| 1249 | | - * hotswapped, and it breaks the `ro-after' testing code. |
|---|
| 1250 | | - */ |
|---|
| 1251 | 1239 | sync_blockdev(sbi->s_journal_bdev); |
|---|
| 1252 | | - invalidate_bdev(sbi->s_journal_bdev); |
|---|
| 1253 | 1240 | ext4_blkdev_remove(sbi); |
|---|
| 1254 | 1241 | } |
|---|
| 1255 | 1242 | |
|---|
| .. | .. |
|---|
| 1294 | 1281 | return NULL; |
|---|
| 1295 | 1282 | |
|---|
| 1296 | 1283 | inode_set_iversion(&ei->vfs_inode, 1); |
|---|
| 1284 | + ei->i_flags = 0; |
|---|
| 1297 | 1285 | spin_lock_init(&ei->i_raw_lock); |
|---|
| 1298 | 1286 | INIT_LIST_HEAD(&ei->i_prealloc_list); |
|---|
| 1299 | 1287 | atomic_set(&ei->i_prealloc_active, 0); |
|---|
| .. | .. |
|---|
| 2845 | 2833 | crc = crc16(crc, (__u8 *)gdp, offset); |
|---|
| 2846 | 2834 | offset += sizeof(gdp->bg_checksum); /* skip checksum */ |
|---|
| 2847 | 2835 | /* for checksum of struct ext4_group_desc do the rest...*/ |
|---|
| 2848 | | - if (ext4_has_feature_64bit(sb) && |
|---|
| 2849 | | - offset < le16_to_cpu(sbi->s_es->s_desc_size)) |
|---|
| 2836 | + if (ext4_has_feature_64bit(sb) && offset < sbi->s_desc_size) |
|---|
| 2850 | 2837 | crc = crc16(crc, (__u8 *)gdp + offset, |
|---|
| 2851 | | - le16_to_cpu(sbi->s_es->s_desc_size) - |
|---|
| 2852 | | - offset); |
|---|
| 2838 | + sbi->s_desc_size - offset); |
|---|
| 2853 | 2839 | |
|---|
| 2854 | 2840 | out: |
|---|
| 2855 | 2841 | return cpu_to_le16(crc); |
|---|
| .. | .. |
|---|
| 4787 | 4773 | needs_recovery = (es->s_last_orphan != 0 || |
|---|
| 4788 | 4774 | ext4_has_feature_journal_needs_recovery(sb)); |
|---|
| 4789 | 4775 | |
|---|
| 4790 | | - if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb)) |
|---|
| 4791 | | - if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) |
|---|
| 4776 | + if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb)) { |
|---|
| 4777 | + err = ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)); |
|---|
| 4778 | + if (err) |
|---|
| 4792 | 4779 | goto failed_mount3a; |
|---|
| 4780 | + } |
|---|
| 4793 | 4781 | |
|---|
| 4794 | 4782 | /* |
|---|
| 4795 | 4783 | * The first inode we look at is the journal inode. Don't try |
|---|
| .. | .. |
|---|
| 4803 | 4791 | ext4_has_feature_journal_needs_recovery(sb)) { |
|---|
| 4804 | 4792 | ext4_msg(sb, KERN_ERR, "required journal recovery " |
|---|
| 4805 | 4793 | "suppressed and not mounted read-only"); |
|---|
| 4806 | | - goto failed_mount_wq; |
|---|
| 4794 | + goto failed_mount3a; |
|---|
| 4807 | 4795 | } else { |
|---|
| 4808 | 4796 | /* Nojournal mode, all journal mount options are illegal */ |
|---|
| 4809 | | - if (test_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM)) { |
|---|
| 4810 | | - ext4_msg(sb, KERN_ERR, "can't mount with " |
|---|
| 4811 | | - "journal_checksum, fs mounted w/o journal"); |
|---|
| 4812 | | - goto failed_mount_wq; |
|---|
| 4813 | | - } |
|---|
| 4814 | 4797 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { |
|---|
| 4815 | 4798 | ext4_msg(sb, KERN_ERR, "can't mount with " |
|---|
| 4816 | 4799 | "journal_async_commit, fs mounted w/o journal"); |
|---|
| 4817 | | - goto failed_mount_wq; |
|---|
| 4800 | + goto failed_mount3a; |
|---|
| 4801 | + } |
|---|
| 4802 | + |
|---|
| 4803 | + if (test_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM)) { |
|---|
| 4804 | + ext4_msg(sb, KERN_ERR, "can't mount with " |
|---|
| 4805 | + "journal_checksum, fs mounted w/o journal"); |
|---|
| 4806 | + goto failed_mount3a; |
|---|
| 4818 | 4807 | } |
|---|
| 4819 | 4808 | if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) { |
|---|
| 4820 | 4809 | ext4_msg(sb, KERN_ERR, "can't mount with " |
|---|
| 4821 | 4810 | "commit=%lu, fs mounted w/o journal", |
|---|
| 4822 | 4811 | sbi->s_commit_interval / HZ); |
|---|
| 4823 | | - goto failed_mount_wq; |
|---|
| 4812 | + goto failed_mount3a; |
|---|
| 4824 | 4813 | } |
|---|
| 4825 | 4814 | if (EXT4_MOUNT_DATA_FLAGS & |
|---|
| 4826 | 4815 | (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) { |
|---|
| 4827 | 4816 | ext4_msg(sb, KERN_ERR, "can't mount with " |
|---|
| 4828 | 4817 | "data=, fs mounted w/o journal"); |
|---|
| 4829 | | - goto failed_mount_wq; |
|---|
| 4818 | + goto failed_mount3a; |
|---|
| 4830 | 4819 | } |
|---|
| 4831 | 4820 | sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM; |
|---|
| 4832 | 4821 | clear_opt(sb, JOURNAL_CHECKSUM); |
|---|
| .. | .. |
|---|
| 5206 | 5195 | brelse(bh); |
|---|
| 5207 | 5196 | ext4_blkdev_remove(sbi); |
|---|
| 5208 | 5197 | out_fail: |
|---|
| 5198 | + invalidate_bdev(sb->s_bdev); |
|---|
| 5209 | 5199 | sb->s_fs_info = NULL; |
|---|
| 5210 | 5200 | kfree(sbi->s_blockgroup_lock); |
|---|
| 5211 | 5201 | out_free_base: |
|---|
| .. | .. |
|---|
| 5265 | 5255 | |
|---|
| 5266 | 5256 | jbd_debug(2, "Journal inode found at %p: %lld bytes\n", |
|---|
| 5267 | 5257 | journal_inode, journal_inode->i_size); |
|---|
| 5268 | | - if (!S_ISREG(journal_inode->i_mode)) { |
|---|
| 5258 | + if (!S_ISREG(journal_inode->i_mode) || IS_ENCRYPTED(journal_inode)) { |
|---|
| 5269 | 5259 | ext4_msg(sb, KERN_ERR, "invalid journal inode"); |
|---|
| 5270 | 5260 | iput(journal_inode); |
|---|
| 5271 | 5261 | return NULL; |
|---|
| .. | .. |
|---|
| 5796 | 5786 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
|---|
| 5797 | 5787 | unsigned long old_sb_flags, vfs_flags; |
|---|
| 5798 | 5788 | struct ext4_mount_options old_opts; |
|---|
| 5799 | | - int enable_quota = 0; |
|---|
| 5800 | 5789 | ext4_group_t g; |
|---|
| 5801 | 5790 | unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; |
|---|
| 5802 | 5791 | int err = 0; |
|---|
| 5803 | 5792 | #ifdef CONFIG_QUOTA |
|---|
| 5793 | + int enable_quota = 0; |
|---|
| 5804 | 5794 | int i, j; |
|---|
| 5805 | 5795 | char *to_free[EXT4_MAXQUOTAS]; |
|---|
| 5806 | 5796 | #endif |
|---|
| .. | .. |
|---|
| 5992 | 5982 | goto restore_opts; |
|---|
| 5993 | 5983 | |
|---|
| 5994 | 5984 | sb->s_flags &= ~SB_RDONLY; |
|---|
| 5995 | | - if (ext4_has_feature_mmp(sb)) |
|---|
| 5996 | | - if (ext4_multi_mount_protect(sb, |
|---|
| 5997 | | - le64_to_cpu(es->s_mmp_block))) { |
|---|
| 5998 | | - err = -EROFS; |
|---|
| 5985 | + if (ext4_has_feature_mmp(sb)) { |
|---|
| 5986 | + err = ext4_multi_mount_protect(sb, |
|---|
| 5987 | + le64_to_cpu(es->s_mmp_block)); |
|---|
| 5988 | + if (err) |
|---|
| 5999 | 5989 | goto restore_opts; |
|---|
| 6000 | | - } |
|---|
| 5990 | + } |
|---|
| 5991 | +#ifdef CONFIG_QUOTA |
|---|
| 6001 | 5992 | enable_quota = 1; |
|---|
| 5993 | +#endif |
|---|
| 6002 | 5994 | } |
|---|
| 6003 | | - } |
|---|
| 6004 | | - |
|---|
| 6005 | | - /* |
|---|
| 6006 | | - * Reinitialize lazy itable initialization thread based on |
|---|
| 6007 | | - * current settings |
|---|
| 6008 | | - */ |
|---|
| 6009 | | - if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE)) |
|---|
| 6010 | | - ext4_unregister_li_request(sb); |
|---|
| 6011 | | - else { |
|---|
| 6012 | | - ext4_group_t first_not_zeroed; |
|---|
| 6013 | | - first_not_zeroed = ext4_has_uninit_itable(sb); |
|---|
| 6014 | | - ext4_register_li_request(sb, first_not_zeroed); |
|---|
| 6015 | 5995 | } |
|---|
| 6016 | 5996 | |
|---|
| 6017 | 5997 | /* |
|---|
| .. | .. |
|---|
| 6032 | 6012 | } |
|---|
| 6033 | 6013 | |
|---|
| 6034 | 6014 | #ifdef CONFIG_QUOTA |
|---|
| 6035 | | - /* Release old quota file names */ |
|---|
| 6036 | | - for (i = 0; i < EXT4_MAXQUOTAS; i++) |
|---|
| 6037 | | - kfree(old_opts.s_qf_names[i]); |
|---|
| 6038 | 6015 | if (enable_quota) { |
|---|
| 6039 | 6016 | if (sb_any_quota_suspended(sb)) |
|---|
| 6040 | 6017 | dquot_resume(sb, -1); |
|---|
| .. | .. |
|---|
| 6044 | 6021 | goto restore_opts; |
|---|
| 6045 | 6022 | } |
|---|
| 6046 | 6023 | } |
|---|
| 6024 | + /* Release old quota file names */ |
|---|
| 6025 | + for (i = 0; i < EXT4_MAXQUOTAS; i++) |
|---|
| 6026 | + kfree(old_opts.s_qf_names[i]); |
|---|
| 6047 | 6027 | #endif |
|---|
| 6048 | 6028 | if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks) |
|---|
| 6049 | 6029 | ext4_release_system_zone(sb); |
|---|
| 6030 | + |
|---|
| 6031 | + /* |
|---|
| 6032 | + * Reinitialize lazy itable initialization thread based on |
|---|
| 6033 | + * current settings |
|---|
| 6034 | + */ |
|---|
| 6035 | + if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE)) |
|---|
| 6036 | + ext4_unregister_li_request(sb); |
|---|
| 6037 | + else { |
|---|
| 6038 | + ext4_group_t first_not_zeroed; |
|---|
| 6039 | + first_not_zeroed = ext4_has_uninit_itable(sb); |
|---|
| 6040 | + ext4_register_li_request(sb, first_not_zeroed); |
|---|
| 6041 | + } |
|---|
| 6050 | 6042 | |
|---|
| 6051 | 6043 | if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb)) |
|---|
| 6052 | 6044 | ext4_stop_mmpd(sbi); |
|---|
| .. | .. |
|---|
| 6063 | 6055 | return 0; |
|---|
| 6064 | 6056 | |
|---|
| 6065 | 6057 | restore_opts: |
|---|
| 6058 | + /* |
|---|
| 6059 | + * If there was a failing r/w to ro transition, we may need to |
|---|
| 6060 | + * re-enable quota |
|---|
| 6061 | + */ |
|---|
| 6062 | + if ((sb->s_flags & SB_RDONLY) && !(old_sb_flags & SB_RDONLY) && |
|---|
| 6063 | + sb_any_quota_suspended(sb)) |
|---|
| 6064 | + dquot_resume(sb, -1); |
|---|
| 6066 | 6065 | sb->s_flags = old_sb_flags; |
|---|
| 6067 | 6066 | sbi->s_mount_opt = old_opts.s_mount_opt; |
|---|
| 6068 | 6067 | sbi->s_mount_opt2 = old_opts.s_mount_opt2; |
|---|
| .. | .. |
|---|
| 6374 | 6373 | return err; |
|---|
| 6375 | 6374 | } |
|---|
| 6376 | 6375 | |
|---|
| 6376 | +static inline bool ext4_check_quota_inum(int type, unsigned long qf_inum) |
|---|
| 6377 | +{ |
|---|
| 6378 | + switch (type) { |
|---|
| 6379 | + case USRQUOTA: |
|---|
| 6380 | + return qf_inum == EXT4_USR_QUOTA_INO; |
|---|
| 6381 | + case GRPQUOTA: |
|---|
| 6382 | + return qf_inum == EXT4_GRP_QUOTA_INO; |
|---|
| 6383 | + case PRJQUOTA: |
|---|
| 6384 | + return qf_inum >= EXT4_GOOD_OLD_FIRST_INO; |
|---|
| 6385 | + default: |
|---|
| 6386 | + BUG(); |
|---|
| 6387 | + } |
|---|
| 6388 | +} |
|---|
| 6389 | + |
|---|
| 6377 | 6390 | static int ext4_quota_enable(struct super_block *sb, int type, int format_id, |
|---|
| 6378 | 6391 | unsigned int flags) |
|---|
| 6379 | 6392 | { |
|---|
| .. | .. |
|---|
| 6390 | 6403 | if (!qf_inums[type]) |
|---|
| 6391 | 6404 | return -EPERM; |
|---|
| 6392 | 6405 | |
|---|
| 6406 | + if (!ext4_check_quota_inum(type, qf_inums[type])) { |
|---|
| 6407 | + ext4_error(sb, "Bad quota inum: %lu, type: %d", |
|---|
| 6408 | + qf_inums[type], type); |
|---|
| 6409 | + return -EUCLEAN; |
|---|
| 6410 | + } |
|---|
| 6411 | + |
|---|
| 6393 | 6412 | qf_inode = ext4_iget(sb, qf_inums[type], EXT4_IGET_SPECIAL); |
|---|
| 6394 | 6413 | if (IS_ERR(qf_inode)) { |
|---|
| 6395 | | - ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]); |
|---|
| 6414 | + ext4_error(sb, "Bad quota inode: %lu, type: %d", |
|---|
| 6415 | + qf_inums[type], type); |
|---|
| 6396 | 6416 | return PTR_ERR(qf_inode); |
|---|
| 6397 | 6417 | } |
|---|
| 6398 | 6418 | |
|---|
| .. | .. |
|---|
| 6431 | 6451 | if (err) { |
|---|
| 6432 | 6452 | ext4_warning(sb, |
|---|
| 6433 | 6453 | "Failed to enable quota tracking " |
|---|
| 6434 | | - "(type=%d, err=%d). Please run " |
|---|
| 6435 | | - "e2fsck to fix.", type, err); |
|---|
| 6454 | + "(type=%d, err=%d, ino=%lu). " |
|---|
| 6455 | + "Please run e2fsck to fix.", type, |
|---|
| 6456 | + err, qf_inums[type]); |
|---|
| 6436 | 6457 | for (type--; type >= 0; type--) { |
|---|
| 6437 | 6458 | struct inode *inode; |
|---|
| 6438 | 6459 | |
|---|