.. | .. |
---|
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 | |
---|