diff options
38 files changed, 1279 insertions, 997 deletions
diff --git a/fs/Makefile b/fs/Makefile index f79cf4043e60..79f522575cba 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -63,10 +63,11 @@ obj-$(CONFIG_DLM) += dlm/ | |||
| 63 | # Do not add any filesystems before this line | 63 | # Do not add any filesystems before this line |
| 64 | obj-$(CONFIG_FSCACHE) += fscache/ | 64 | obj-$(CONFIG_FSCACHE) += fscache/ |
| 65 | obj-$(CONFIG_REISERFS_FS) += reiserfs/ | 65 | obj-$(CONFIG_REISERFS_FS) += reiserfs/ |
| 66 | obj-$(CONFIG_EXT2_FS) += ext2/ | ||
| 67 | # We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 | ||
| 68 | # unless explicitly requested by rootfstype | ||
| 69 | obj-$(CONFIG_EXT4_FS) += ext4/ | 66 | obj-$(CONFIG_EXT4_FS) += ext4/ |
| 67 | # We place ext4 before ext2 so that clean ext3 root fs's do NOT mount using the | ||
| 68 | # ext2 driver, which doesn't know about journalling! Explicitly request ext2 | ||
| 69 | # by giving the rootfstype= parameter. | ||
| 70 | obj-$(CONFIG_EXT2_FS) += ext2/ | ||
| 70 | obj-$(CONFIG_JBD2) += jbd2/ | 71 | obj-$(CONFIG_JBD2) += jbd2/ |
| 71 | obj-$(CONFIG_CRAMFS) += cramfs/ | 72 | obj-$(CONFIG_CRAMFS) += cramfs/ |
| 72 | obj-$(CONFIG_SQUASHFS) += squashfs/ | 73 | obj-$(CONFIG_SQUASHFS) += squashfs/ |
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index 75285ea9aa05..f52cf54f0cbc 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile | |||
| @@ -8,7 +8,7 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \ | |||
| 8 | ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ | 8 | ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ |
| 9 | ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ | 9 | ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ |
| 10 | mmp.o indirect.o extents_status.o xattr.o xattr_user.o \ | 10 | mmp.o indirect.o extents_status.o xattr.o xattr_user.o \ |
| 11 | xattr_trusted.o inline.o readpage.o | 11 | xattr_trusted.o inline.o readpage.o sysfs.o |
| 12 | 12 | ||
| 13 | ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o | 13 | ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o |
| 14 | ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o | 14 | ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index cd6ea29be645..ec0668a60678 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -191,6 +191,7 @@ static int ext4_init_block_bitmap(struct super_block *sb, | |||
| 191 | /* If checksum is bad mark all blocks used to prevent allocation | 191 | /* If checksum is bad mark all blocks used to prevent allocation |
| 192 | * essentially implementing a per-group read-only flag. */ | 192 | * essentially implementing a per-group read-only flag. */ |
| 193 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { | 193 | if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { |
| 194 | ext4_error(sb, "Checksum bad for group %u", block_group); | ||
| 194 | grp = ext4_get_group_info(sb, block_group); | 195 | grp = ext4_get_group_info(sb, block_group); |
| 195 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | 196 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) |
| 196 | percpu_counter_sub(&sbi->s_freeclusters_counter, | 197 | percpu_counter_sub(&sbi->s_freeclusters_counter, |
| @@ -203,7 +204,7 @@ static int ext4_init_block_bitmap(struct super_block *sb, | |||
| 203 | count); | 204 | count); |
| 204 | } | 205 | } |
| 205 | set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); | 206 | set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); |
| 206 | return -EIO; | 207 | return -EFSBADCRC; |
| 207 | } | 208 | } |
| 208 | memset(bh->b_data, 0, sb->s_blocksize); | 209 | memset(bh->b_data, 0, sb->s_blocksize); |
| 209 | 210 | ||
| @@ -213,7 +214,7 @@ static int ext4_init_block_bitmap(struct super_block *sb, | |||
| 213 | 214 | ||
| 214 | start = ext4_group_first_block_no(sb, block_group); | 215 | start = ext4_group_first_block_no(sb, block_group); |
| 215 | 216 | ||
| 216 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 217 | if (ext4_has_feature_flex_bg(sb)) |
| 217 | flex_bg = 1; | 218 | flex_bg = 1; |
| 218 | 219 | ||
| 219 | /* Set bits for block and inode bitmaps, and inode table */ | 220 | /* Set bits for block and inode bitmaps, and inode table */ |
| @@ -322,7 +323,7 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, | |||
| 322 | ext4_fsblk_t blk; | 323 | ext4_fsblk_t blk; |
| 323 | ext4_fsblk_t group_first_block; | 324 | ext4_fsblk_t group_first_block; |
| 324 | 325 | ||
| 325 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { | 326 | if (ext4_has_feature_flex_bg(sb)) { |
| 326 | /* with FLEX_BG, the inode/block bitmaps and itable | 327 | /* with FLEX_BG, the inode/block bitmaps and itable |
| 327 | * blocks may not be in the group at all | 328 | * blocks may not be in the group at all |
| 328 | * so the bitmap validation will be skipped for those groups | 329 | * so the bitmap validation will be skipped for those groups |
| @@ -360,42 +361,45 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, | |||
| 360 | return 0; | 361 | return 0; |
| 361 | } | 362 | } |
| 362 | 363 | ||
| 363 | static void ext4_validate_block_bitmap(struct super_block *sb, | 364 | static int ext4_validate_block_bitmap(struct super_block *sb, |
| 364 | struct ext4_group_desc *desc, | 365 | struct ext4_group_desc *desc, |
| 365 | ext4_group_t block_group, | 366 | ext4_group_t block_group, |
| 366 | struct buffer_head *bh) | 367 | struct buffer_head *bh) |
| 367 | { | 368 | { |
| 368 | ext4_fsblk_t blk; | 369 | ext4_fsblk_t blk; |
| 369 | struct ext4_group_info *grp = ext4_get_group_info(sb, block_group); | 370 | struct ext4_group_info *grp = ext4_get_group_info(sb, block_group); |
| 370 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 371 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 371 | 372 | ||
| 372 | if (buffer_verified(bh) || EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | 373 | if (buffer_verified(bh)) |
| 373 | return; | 374 | return 0; |
| 375 | if (EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | ||
| 376 | return -EFSCORRUPTED; | ||
| 374 | 377 | ||
| 375 | ext4_lock_group(sb, block_group); | 378 | ext4_lock_group(sb, block_group); |
| 376 | blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); | 379 | if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, |
| 377 | if (unlikely(blk != 0)) { | 380 | desc, bh))) { |
| 378 | ext4_unlock_group(sb, block_group); | 381 | ext4_unlock_group(sb, block_group); |
| 379 | ext4_error(sb, "bg %u: block %llu: invalid block bitmap", | 382 | ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); |
| 380 | block_group, blk); | ||
| 381 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | 383 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) |
| 382 | percpu_counter_sub(&sbi->s_freeclusters_counter, | 384 | percpu_counter_sub(&sbi->s_freeclusters_counter, |
| 383 | grp->bb_free); | 385 | grp->bb_free); |
| 384 | set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); | 386 | set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); |
| 385 | return; | 387 | return -EFSBADCRC; |
| 386 | } | 388 | } |
| 387 | if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, | 389 | blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); |
| 388 | desc, bh))) { | 390 | if (unlikely(blk != 0)) { |
| 389 | ext4_unlock_group(sb, block_group); | 391 | ext4_unlock_group(sb, block_group); |
| 390 | ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); | 392 | ext4_error(sb, "bg %u: block %llu: invalid block bitmap", |
| 393 | block_group, blk); | ||
| 391 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) | 394 | if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) |
| 392 | percpu_counter_sub(&sbi->s_freeclusters_counter, | 395 | percpu_counter_sub(&sbi->s_freeclusters_counter, |
| 393 | grp->bb_free); | 396 | grp->bb_free); |
| 394 | set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); | 397 | set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); |
| 395 | return; | 398 | return -EFSCORRUPTED; |
| 396 | } | 399 | } |
| 397 | set_buffer_verified(bh); | 400 | set_buffer_verified(bh); |
| 398 | ext4_unlock_group(sb, block_group); | 401 | ext4_unlock_group(sb, block_group); |
| 402 | return 0; | ||
| 399 | } | 403 | } |
| 400 | 404 | ||
| 401 | /** | 405 | /** |
| @@ -414,17 +418,18 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
| 414 | struct ext4_group_desc *desc; | 418 | struct ext4_group_desc *desc; |
| 415 | struct buffer_head *bh; | 419 | struct buffer_head *bh; |
| 416 | ext4_fsblk_t bitmap_blk; | 420 | ext4_fsblk_t bitmap_blk; |
| 421 | int err; | ||
| 417 | 422 | ||
| 418 | desc = ext4_get_group_desc(sb, block_group, NULL); | 423 | desc = ext4_get_group_desc(sb, block_group, NULL); |
| 419 | if (!desc) | 424 | if (!desc) |
| 420 | return NULL; | 425 | return ERR_PTR(-EFSCORRUPTED); |
| 421 | bitmap_blk = ext4_block_bitmap(sb, desc); | 426 | bitmap_blk = ext4_block_bitmap(sb, desc); |
| 422 | bh = sb_getblk(sb, bitmap_blk); | 427 | bh = sb_getblk(sb, bitmap_blk); |
| 423 | if (unlikely(!bh)) { | 428 | if (unlikely(!bh)) { |
| 424 | ext4_error(sb, "Cannot get buffer for block bitmap - " | 429 | ext4_error(sb, "Cannot get buffer for block bitmap - " |
| 425 | "block_group = %u, block_bitmap = %llu", | 430 | "block_group = %u, block_bitmap = %llu", |
| 426 | block_group, bitmap_blk); | 431 | block_group, bitmap_blk); |
| 427 | return NULL; | 432 | return ERR_PTR(-ENOMEM); |
| 428 | } | 433 | } |
| 429 | 434 | ||
| 430 | if (bitmap_uptodate(bh)) | 435 | if (bitmap_uptodate(bh)) |
| @@ -437,7 +442,6 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
| 437 | } | 442 | } |
| 438 | ext4_lock_group(sb, block_group); | 443 | ext4_lock_group(sb, block_group); |
| 439 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 444 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
| 440 | int err; | ||
| 441 | 445 | ||
| 442 | err = ext4_init_block_bitmap(sb, bh, block_group, desc); | 446 | err = ext4_init_block_bitmap(sb, bh, block_group, desc); |
| 443 | set_bitmap_uptodate(bh); | 447 | set_bitmap_uptodate(bh); |
| @@ -445,7 +449,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
| 445 | ext4_unlock_group(sb, block_group); | 449 | ext4_unlock_group(sb, block_group); |
| 446 | unlock_buffer(bh); | 450 | unlock_buffer(bh); |
| 447 | if (err) | 451 | if (err) |
| 448 | ext4_error(sb, "Checksum bad for grp %u", block_group); | 452 | goto out; |
| 449 | goto verify; | 453 | goto verify; |
| 450 | } | 454 | } |
| 451 | ext4_unlock_group(sb, block_group); | 455 | ext4_unlock_group(sb, block_group); |
| @@ -468,11 +472,13 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
| 468 | submit_bh(READ | REQ_META | REQ_PRIO, bh); | 472 | submit_bh(READ | REQ_META | REQ_PRIO, bh); |
| 469 | return bh; | 473 | return bh; |
| 470 | verify: | 474 | verify: |
| 471 | ext4_validate_block_bitmap(sb, desc, block_group, bh); | 475 | err = ext4_validate_block_bitmap(sb, desc, block_group, bh); |
| 472 | if (buffer_verified(bh)) | 476 | if (err) |
| 473 | return bh; | 477 | goto out; |
| 478 | return bh; | ||
| 479 | out: | ||
| 474 | put_bh(bh); | 480 | put_bh(bh); |
| 475 | return NULL; | 481 | return ERR_PTR(err); |
| 476 | } | 482 | } |
| 477 | 483 | ||
| 478 | /* Returns 0 on success, 1 on error */ | 484 | /* Returns 0 on success, 1 on error */ |
| @@ -485,32 +491,32 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group, | |||
| 485 | return 0; | 491 | return 0; |
| 486 | desc = ext4_get_group_desc(sb, block_group, NULL); | 492 | desc = ext4_get_group_desc(sb, block_group, NULL); |
| 487 | if (!desc) | 493 | if (!desc) |
| 488 | return 1; | 494 | return -EFSCORRUPTED; |
| 489 | wait_on_buffer(bh); | 495 | wait_on_buffer(bh); |
| 490 | if (!buffer_uptodate(bh)) { | 496 | if (!buffer_uptodate(bh)) { |
| 491 | ext4_error(sb, "Cannot read block bitmap - " | 497 | ext4_error(sb, "Cannot read block bitmap - " |
| 492 | "block_group = %u, block_bitmap = %llu", | 498 | "block_group = %u, block_bitmap = %llu", |
| 493 | block_group, (unsigned long long) bh->b_blocknr); | 499 | block_group, (unsigned long long) bh->b_blocknr); |
| 494 | return 1; | 500 | return -EIO; |
| 495 | } | 501 | } |
| 496 | clear_buffer_new(bh); | 502 | clear_buffer_new(bh); |
| 497 | /* Panic or remount fs read-only if block bitmap is invalid */ | 503 | /* Panic or remount fs read-only if block bitmap is invalid */ |
| 498 | ext4_validate_block_bitmap(sb, desc, block_group, bh); | 504 | return ext4_validate_block_bitmap(sb, desc, block_group, bh); |
| 499 | /* ...but check for error just in case errors=continue. */ | ||
| 500 | return !buffer_verified(bh); | ||
| 501 | } | 505 | } |
| 502 | 506 | ||
| 503 | struct buffer_head * | 507 | struct buffer_head * |
| 504 | ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) | 508 | ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) |
| 505 | { | 509 | { |
| 506 | struct buffer_head *bh; | 510 | struct buffer_head *bh; |
| 511 | int err; | ||
| 507 | 512 | ||
| 508 | bh = ext4_read_block_bitmap_nowait(sb, block_group); | 513 | bh = ext4_read_block_bitmap_nowait(sb, block_group); |
| 509 | if (!bh) | 514 | if (IS_ERR(bh)) |
| 510 | return NULL; | 515 | return bh; |
| 511 | if (ext4_wait_block_bitmap(sb, block_group, bh)) { | 516 | err = ext4_wait_block_bitmap(sb, block_group, bh); |
| 517 | if (err) { | ||
| 512 | put_bh(bh); | 518 | put_bh(bh); |
| 513 | return NULL; | 519 | return ERR_PTR(err); |
| 514 | } | 520 | } |
| 515 | return bh; | 521 | return bh; |
| 516 | } | 522 | } |
| @@ -681,8 +687,10 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) | |||
| 681 | desc_count += ext4_free_group_clusters(sb, gdp); | 687 | desc_count += ext4_free_group_clusters(sb, gdp); |
| 682 | brelse(bitmap_bh); | 688 | brelse(bitmap_bh); |
| 683 | bitmap_bh = ext4_read_block_bitmap(sb, i); | 689 | bitmap_bh = ext4_read_block_bitmap(sb, i); |
| 684 | if (bitmap_bh == NULL) | 690 | if (IS_ERR(bitmap_bh)) { |
| 691 | bitmap_bh = NULL; | ||
| 685 | continue; | 692 | continue; |
| 693 | } | ||
| 686 | 694 | ||
| 687 | x = ext4_count_free(bitmap_bh->b_data, | 695 | x = ext4_count_free(bitmap_bh->b_data, |
| 688 | EXT4_CLUSTERS_PER_GROUP(sb) / 8); | 696 | EXT4_CLUSTERS_PER_GROUP(sb) / 8); |
| @@ -740,14 +748,13 @@ int ext4_bg_has_super(struct super_block *sb, ext4_group_t group) | |||
| 740 | 748 | ||
| 741 | if (group == 0) | 749 | if (group == 0) |
| 742 | return 1; | 750 | return 1; |
| 743 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_SPARSE_SUPER2)) { | 751 | if (ext4_has_feature_sparse_super2(sb)) { |
| 744 | if (group == le32_to_cpu(es->s_backup_bgs[0]) || | 752 | if (group == le32_to_cpu(es->s_backup_bgs[0]) || |
| 745 | group == le32_to_cpu(es->s_backup_bgs[1])) | 753 | group == le32_to_cpu(es->s_backup_bgs[1])) |
| 746 | return 1; | 754 | return 1; |
| 747 | return 0; | 755 | return 0; |
| 748 | } | 756 | } |
| 749 | if ((group <= 1) || !EXT4_HAS_RO_COMPAT_FEATURE(sb, | 757 | if ((group <= 1) || !ext4_has_feature_sparse_super(sb)) |
| 750 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) | ||
| 751 | return 1; | 758 | return 1; |
| 752 | if (!(group & 1)) | 759 | if (!(group & 1)) |
| 753 | return 0; | 760 | return 0; |
| @@ -776,7 +783,7 @@ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, | |||
| 776 | if (!ext4_bg_has_super(sb, group)) | 783 | if (!ext4_bg_has_super(sb, group)) |
| 777 | return 0; | 784 | return 0; |
| 778 | 785 | ||
| 779 | if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) | 786 | if (ext4_has_feature_meta_bg(sb)) |
| 780 | return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); | 787 | return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); |
| 781 | else | 788 | else |
| 782 | return EXT4_SB(sb)->s_gdb_count; | 789 | return EXT4_SB(sb)->s_gdb_count; |
| @@ -797,8 +804,7 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group) | |||
| 797 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); | 804 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); |
| 798 | unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); | 805 | unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); |
| 799 | 806 | ||
| 800 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) || | 807 | if (!ext4_has_feature_meta_bg(sb) || metagroup < first_meta_bg) |
| 801 | metagroup < first_meta_bg) | ||
| 802 | return ext4_bg_num_gdb_nometa(sb, group); | 808 | return ext4_bg_num_gdb_nometa(sb, group); |
| 803 | 809 | ||
| 804 | return ext4_bg_num_gdb_meta(sb,group); | 810 | return ext4_bg_num_gdb_meta(sb,group); |
| @@ -818,7 +824,7 @@ static unsigned ext4_num_base_meta_clusters(struct super_block *sb, | |||
| 818 | /* Check for superblock and gdt backups in this group */ | 824 | /* Check for superblock and gdt backups in this group */ |
| 819 | num = ext4_bg_has_super(sb, block_group); | 825 | num = ext4_bg_has_super(sb, block_group); |
| 820 | 826 | ||
| 821 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) || | 827 | if (!ext4_has_feature_meta_bg(sb) || |
| 822 | block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) * | 828 | block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) * |
| 823 | sbi->s_desc_per_block) { | 829 | sbi->s_desc_per_block) { |
| 824 | if (num) { | 830 | if (num) { |
diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 3522340c7a99..02ddec6d8a7d 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c | |||
| @@ -234,7 +234,7 @@ int ext4_check_blockref(const char *function, unsigned int line, | |||
| 234 | es->s_last_error_block = cpu_to_le64(blk); | 234 | es->s_last_error_block = cpu_to_le64(blk); |
| 235 | ext4_error_inode(inode, function, line, blk, | 235 | ext4_error_inode(inode, function, line, blk, |
| 236 | "invalid block"); | 236 | "invalid block"); |
| 237 | return -EIO; | 237 | return -EFSCORRUPTED; |
| 238 | } | 238 | } |
| 239 | } | 239 | } |
| 240 | return 0; | 240 | return 0; |
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index 45731558138c..af06830bfc00 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c | |||
| @@ -253,8 +253,7 @@ typedef enum { | |||
| 253 | EXT4_ENCRYPT, | 253 | EXT4_ENCRYPT, |
| 254 | } ext4_direction_t; | 254 | } ext4_direction_t; |
| 255 | 255 | ||
| 256 | static int ext4_page_crypto(struct ext4_crypto_ctx *ctx, | 256 | static int ext4_page_crypto(struct inode *inode, |
| 257 | struct inode *inode, | ||
| 258 | ext4_direction_t rw, | 257 | ext4_direction_t rw, |
| 259 | pgoff_t index, | 258 | pgoff_t index, |
| 260 | struct page *src_page, | 259 | struct page *src_page, |
| @@ -296,7 +295,6 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx, | |||
| 296 | else | 295 | else |
| 297 | res = crypto_ablkcipher_encrypt(req); | 296 | res = crypto_ablkcipher_encrypt(req); |
| 298 | if (res == -EINPROGRESS || res == -EBUSY) { | 297 | if (res == -EINPROGRESS || res == -EBUSY) { |
| 299 | BUG_ON(req->base.data != &ecr); | ||
| 300 | wait_for_completion(&ecr.completion); | 298 | wait_for_completion(&ecr.completion); |
| 301 | res = ecr.res; | 299 | res = ecr.res; |
| 302 | } | 300 | } |
| @@ -353,7 +351,7 @@ struct page *ext4_encrypt(struct inode *inode, | |||
| 353 | if (IS_ERR(ciphertext_page)) | 351 | if (IS_ERR(ciphertext_page)) |
| 354 | goto errout; | 352 | goto errout; |
| 355 | ctx->w.control_page = plaintext_page; | 353 | ctx->w.control_page = plaintext_page; |
| 356 | err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, plaintext_page->index, | 354 | err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index, |
| 357 | plaintext_page, ciphertext_page); | 355 | plaintext_page, ciphertext_page); |
| 358 | if (err) { | 356 | if (err) { |
| 359 | ciphertext_page = ERR_PTR(err); | 357 | ciphertext_page = ERR_PTR(err); |
| @@ -378,31 +376,14 @@ struct page *ext4_encrypt(struct inode *inode, | |||
| 378 | * | 376 | * |
| 379 | * Return: Zero on success, non-zero otherwise. | 377 | * Return: Zero on success, non-zero otherwise. |
| 380 | */ | 378 | */ |
| 381 | int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page) | 379 | int ext4_decrypt(struct page *page) |
| 382 | { | 380 | { |
| 383 | BUG_ON(!PageLocked(page)); | 381 | BUG_ON(!PageLocked(page)); |
| 384 | 382 | ||
| 385 | return ext4_page_crypto(ctx, page->mapping->host, | 383 | return ext4_page_crypto(page->mapping->host, |
| 386 | EXT4_DECRYPT, page->index, page, page); | 384 | EXT4_DECRYPT, page->index, page, page); |
| 387 | } | 385 | } |
| 388 | 386 | ||
| 389 | /* | ||
| 390 | * Convenience function which takes care of allocating and | ||
| 391 | * deallocating the encryption context | ||
| 392 | */ | ||
| 393 | int ext4_decrypt_one(struct inode *inode, struct page *page) | ||
| 394 | { | ||
| 395 | int ret; | ||
| 396 | |||
| 397 | struct ext4_crypto_ctx *ctx = ext4_get_crypto_ctx(inode); | ||
| 398 | |||
| 399 | if (IS_ERR(ctx)) | ||
| 400 | return PTR_ERR(ctx); | ||
| 401 | ret = ext4_decrypt(ctx, page); | ||
| 402 | ext4_release_crypto_ctx(ctx); | ||
| 403 | return ret; | ||
| 404 | } | ||
| 405 | |||
| 406 | int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) | 387 | int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) |
| 407 | { | 388 | { |
| 408 | struct ext4_crypto_ctx *ctx; | 389 | struct ext4_crypto_ctx *ctx; |
| @@ -411,7 +392,13 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) | |||
| 411 | ext4_lblk_t lblk = ex->ee_block; | 392 | ext4_lblk_t lblk = ex->ee_block; |
| 412 | ext4_fsblk_t pblk = ext4_ext_pblock(ex); | 393 | ext4_fsblk_t pblk = ext4_ext_pblock(ex); |
| 413 | unsigned int len = ext4_ext_get_actual_len(ex); | 394 | unsigned int len = ext4_ext_get_actual_len(ex); |
| 414 | int err = 0; | 395 | int ret, err = 0; |
| 396 | |||
| 397 | #if 0 | ||
| 398 | ext4_msg(inode->i_sb, KERN_CRIT, | ||
| 399 | "ext4_encrypted_zeroout ino %lu lblk %u len %u", | ||
| 400 | (unsigned long) inode->i_ino, lblk, len); | ||
| 401 | #endif | ||
| 415 | 402 | ||
| 416 | BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE); | 403 | BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE); |
| 417 | 404 | ||
| @@ -426,7 +413,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) | |||
| 426 | } | 413 | } |
| 427 | 414 | ||
| 428 | while (len--) { | 415 | while (len--) { |
| 429 | err = ext4_page_crypto(ctx, inode, EXT4_ENCRYPT, lblk, | 416 | err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk, |
| 430 | ZERO_PAGE(0), ciphertext_page); | 417 | ZERO_PAGE(0), ciphertext_page); |
| 431 | if (err) | 418 | if (err) |
| 432 | goto errout; | 419 | goto errout; |
| @@ -437,17 +424,26 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) | |||
| 437 | goto errout; | 424 | goto errout; |
| 438 | } | 425 | } |
| 439 | bio->bi_bdev = inode->i_sb->s_bdev; | 426 | bio->bi_bdev = inode->i_sb->s_bdev; |
| 440 | bio->bi_iter.bi_sector = pblk; | 427 | bio->bi_iter.bi_sector = |
| 441 | err = bio_add_page(bio, ciphertext_page, | 428 | pblk << (inode->i_sb->s_blocksize_bits - 9); |
| 429 | ret = bio_add_page(bio, ciphertext_page, | ||
| 442 | inode->i_sb->s_blocksize, 0); | 430 | inode->i_sb->s_blocksize, 0); |
| 443 | if (err) { | 431 | if (ret != inode->i_sb->s_blocksize) { |
| 432 | /* should never happen! */ | ||
| 433 | ext4_msg(inode->i_sb, KERN_ERR, | ||
| 434 | "bio_add_page failed: %d", ret); | ||
| 435 | WARN_ON(1); | ||
| 444 | bio_put(bio); | 436 | bio_put(bio); |
| 437 | err = -EIO; | ||
| 445 | goto errout; | 438 | goto errout; |
| 446 | } | 439 | } |
| 447 | err = submit_bio_wait(WRITE, bio); | 440 | err = submit_bio_wait(WRITE, bio); |
| 441 | if ((err == 0) && bio->bi_error) | ||
| 442 | err = -EIO; | ||
| 448 | bio_put(bio); | 443 | bio_put(bio); |
| 449 | if (err) | 444 | if (err) |
| 450 | goto errout; | 445 | goto errout; |
| 446 | lblk++; pblk++; | ||
| 451 | } | 447 | } |
| 452 | err = 0; | 448 | err = 0; |
| 453 | errout: | 449 | errout: |
diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index 847f919c84d9..2fbef8a14760 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c | |||
| @@ -120,7 +120,6 @@ static int ext4_fname_encrypt(struct inode *inode, | |||
| 120 | ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); | 120 | ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); |
| 121 | res = crypto_ablkcipher_encrypt(req); | 121 | res = crypto_ablkcipher_encrypt(req); |
| 122 | if (res == -EINPROGRESS || res == -EBUSY) { | 122 | if (res == -EINPROGRESS || res == -EBUSY) { |
| 123 | BUG_ON(req->base.data != &ecr); | ||
| 124 | wait_for_completion(&ecr.completion); | 123 | wait_for_completion(&ecr.completion); |
| 125 | res = ecr.res; | 124 | res = ecr.res; |
| 126 | } | 125 | } |
| @@ -182,7 +181,6 @@ static int ext4_fname_decrypt(struct inode *inode, | |||
| 182 | ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); | 181 | ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); |
| 183 | res = crypto_ablkcipher_decrypt(req); | 182 | res = crypto_ablkcipher_decrypt(req); |
| 184 | if (res == -EINPROGRESS || res == -EBUSY) { | 183 | if (res == -EINPROGRESS || res == -EBUSY) { |
| 185 | BUG_ON(req->base.data != &ecr); | ||
| 186 | wait_for_completion(&ecr.completion); | 184 | wait_for_completion(&ecr.completion); |
| 187 | res = ecr.res; | 185 | res = ecr.res; |
| 188 | } | 186 | } |
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c index 5c52c79dea46..c5882b36e558 100644 --- a/fs/ext4/crypto_key.c +++ b/fs/ext4/crypto_key.c | |||
| @@ -71,7 +71,6 @@ static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE], | |||
| 71 | EXT4_AES_256_XTS_KEY_SIZE, NULL); | 71 | EXT4_AES_256_XTS_KEY_SIZE, NULL); |
| 72 | res = crypto_ablkcipher_encrypt(req); | 72 | res = crypto_ablkcipher_encrypt(req); |
| 73 | if (res == -EINPROGRESS || res == -EBUSY) { | 73 | if (res == -EINPROGRESS || res == -EBUSY) { |
| 74 | BUG_ON(req->base.data != &ecr); | ||
| 75 | wait_for_completion(&ecr.completion); | 74 | wait_for_completion(&ecr.completion); |
| 76 | res = ecr.res; | 75 | res = ecr.res; |
| 77 | } | 76 | } |
| @@ -208,7 +207,12 @@ retry: | |||
| 208 | goto out; | 207 | goto out; |
| 209 | } | 208 | } |
| 210 | crypt_info->ci_keyring_key = keyring_key; | 209 | crypt_info->ci_keyring_key = keyring_key; |
| 211 | BUG_ON(keyring_key->type != &key_type_logon); | 210 | if (keyring_key->type != &key_type_logon) { |
| 211 | printk_once(KERN_WARNING | ||
| 212 | "ext4: key type must be logon\n"); | ||
| 213 | res = -ENOKEY; | ||
| 214 | goto out; | ||
| 215 | } | ||
| 212 | ukp = user_key_payload(keyring_key); | 216 | ukp = user_key_payload(keyring_key); |
| 213 | if (ukp->datalen != sizeof(struct ext4_encryption_key)) { | 217 | if (ukp->datalen != sizeof(struct ext4_encryption_key)) { |
| 214 | res = -EINVAL; | 218 | res = -EINVAL; |
| @@ -217,7 +221,13 @@ retry: | |||
| 217 | master_key = (struct ext4_encryption_key *)ukp->data; | 221 | master_key = (struct ext4_encryption_key *)ukp->data; |
| 218 | BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE != | 222 | BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE != |
| 219 | EXT4_KEY_DERIVATION_NONCE_SIZE); | 223 | EXT4_KEY_DERIVATION_NONCE_SIZE); |
| 220 | BUG_ON(master_key->size != EXT4_AES_256_XTS_KEY_SIZE); | 224 | if (master_key->size != EXT4_AES_256_XTS_KEY_SIZE) { |
| 225 | printk_once(KERN_WARNING | ||
| 226 | "ext4: key size incorrect: %d\n", | ||
| 227 | master_key->size); | ||
| 228 | res = -ENOKEY; | ||
| 229 | goto out; | ||
| 230 | } | ||
| 221 | res = ext4_derive_key_aes(ctx.nonce, master_key->raw, | 231 | res = ext4_derive_key_aes(ctx.nonce, master_key->raw, |
| 222 | raw_key); | 232 | raw_key); |
| 223 | if (res) | 233 | if (res) |
diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c index a640ec2c4b13..ad050698143f 100644 --- a/fs/ext4/crypto_policy.c +++ b/fs/ext4/crypto_policy.c | |||
| @@ -150,7 +150,8 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent, | |||
| 150 | 150 | ||
| 151 | if ((parent == NULL) || (child == NULL)) { | 151 | if ((parent == NULL) || (child == NULL)) { |
| 152 | pr_err("parent %p child %p\n", parent, child); | 152 | pr_err("parent %p child %p\n", parent, child); |
| 153 | BUG_ON(1); | 153 | WARN_ON(1); /* Should never happen */ |
| 154 | return 0; | ||
| 154 | } | 155 | } |
| 155 | /* no restrictions if the parent directory is not encrypted */ | 156 | /* no restrictions if the parent directory is not encrypted */ |
| 156 | if (!ext4_encrypted_inode(parent)) | 157 | if (!ext4_encrypted_inode(parent)) |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index f9e14911918c..1d1bca74f844 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
| @@ -40,8 +40,7 @@ static int is_dx_dir(struct inode *inode) | |||
| 40 | { | 40 | { |
| 41 | struct super_block *sb = inode->i_sb; | 41 | struct super_block *sb = inode->i_sb; |
| 42 | 42 | ||
| 43 | if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb, | 43 | if (ext4_has_feature_dir_index(inode->i_sb) && |
| 44 | EXT4_FEATURE_COMPAT_DIR_INDEX) && | ||
| 45 | ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) || | 44 | ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) || |
| 46 | ((inode->i_size >> sb->s_blocksize_bits) == 1) || | 45 | ((inode->i_size >> sb->s_blocksize_bits) == 1) || |
| 47 | ext4_has_inline_data(inode))) | 46 | ext4_has_inline_data(inode))) |
| @@ -621,14 +620,14 @@ int ext4_check_all_de(struct inode *dir, struct buffer_head *bh, void *buf, | |||
| 621 | while ((char *) de < top) { | 620 | while ((char *) de < top) { |
| 622 | if (ext4_check_dir_entry(dir, NULL, de, bh, | 621 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
| 623 | buf, buf_size, offset)) | 622 | buf, buf_size, offset)) |
| 624 | return -EIO; | 623 | return -EFSCORRUPTED; |
| 625 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 624 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
| 626 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); | 625 | rlen = ext4_rec_len_from_disk(de->rec_len, buf_size); |
| 627 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); | 626 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); |
| 628 | offset += rlen; | 627 | offset += rlen; |
| 629 | } | 628 | } |
| 630 | if ((char *) de > top) | 629 | if ((char *) de > top) |
| 631 | return -EIO; | 630 | return -EFSCORRUPTED; |
| 632 | 631 | ||
| 633 | return 0; | 632 | return 0; |
| 634 | } | 633 | } |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index fd1f28be5296..750063f7a50c 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -374,6 +374,7 @@ struct flex_groups { | |||
| 374 | #define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */ | 374 | #define EXT4_EA_INODE_FL 0x00200000 /* Inode used for large EA */ |
| 375 | #define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */ | 375 | #define EXT4_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */ |
| 376 | #define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */ | 376 | #define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */ |
| 377 | #define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ | ||
| 377 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ | 378 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ |
| 378 | 379 | ||
| 379 | #define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */ | 380 | #define EXT4_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */ |
| @@ -431,6 +432,7 @@ enum { | |||
| 431 | EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */ | 432 | EXT4_INODE_EA_INODE = 21, /* Inode used for large EA */ |
| 432 | EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */ | 433 | EXT4_INODE_EOFBLOCKS = 22, /* Blocks allocated beyond EOF */ |
| 433 | EXT4_INODE_INLINE_DATA = 28, /* Data in inode. */ | 434 | EXT4_INODE_INLINE_DATA = 28, /* Data in inode. */ |
| 435 | EXT4_INODE_PROJINHERIT = 29, /* Create with parents projid */ | ||
| 434 | EXT4_INODE_RESERVED = 31, /* reserved for ext4 lib */ | 436 | EXT4_INODE_RESERVED = 31, /* reserved for ext4 lib */ |
| 435 | }; | 437 | }; |
| 436 | 438 | ||
| @@ -475,6 +477,7 @@ static inline void ext4_check_flag_values(void) | |||
| 475 | CHECK_FLAG_VALUE(EA_INODE); | 477 | CHECK_FLAG_VALUE(EA_INODE); |
| 476 | CHECK_FLAG_VALUE(EOFBLOCKS); | 478 | CHECK_FLAG_VALUE(EOFBLOCKS); |
| 477 | CHECK_FLAG_VALUE(INLINE_DATA); | 479 | CHECK_FLAG_VALUE(INLINE_DATA); |
| 480 | CHECK_FLAG_VALUE(PROJINHERIT); | ||
| 478 | CHECK_FLAG_VALUE(RESERVED); | 481 | CHECK_FLAG_VALUE(RESERVED); |
| 479 | } | 482 | } |
| 480 | 483 | ||
| @@ -692,6 +695,7 @@ struct ext4_inode { | |||
| 692 | __le32 i_crtime; /* File Creation time */ | 695 | __le32 i_crtime; /* File Creation time */ |
| 693 | __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ | 696 | __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ |
| 694 | __le32 i_version_hi; /* high 32 bits for 64-bit version */ | 697 | __le32 i_version_hi; /* high 32 bits for 64-bit version */ |
| 698 | __le32 i_projid; /* Project ID */ | ||
| 695 | }; | 699 | }; |
| 696 | 700 | ||
| 697 | struct move_extent { | 701 | struct move_extent { |
| @@ -1019,6 +1023,9 @@ struct ext4_inode_info { | |||
| 1019 | #define EXT4_MOUNT2_HURD_COMPAT 0x00000004 /* Support HURD-castrated | 1023 | #define EXT4_MOUNT2_HURD_COMPAT 0x00000004 /* Support HURD-castrated |
| 1020 | file systems */ | 1024 | file systems */ |
| 1021 | 1025 | ||
| 1026 | #define EXT4_MOUNT2_EXPLICIT_JOURNAL_CHECKSUM 0x00000008 /* User explicitly | ||
| 1027 | specified journal checksum */ | ||
| 1028 | |||
| 1022 | #define clear_opt(sb, opt) EXT4_SB(sb)->s_mount_opt &= \ | 1029 | #define clear_opt(sb, opt) EXT4_SB(sb)->s_mount_opt &= \ |
| 1023 | ~EXT4_MOUNT_##opt | 1030 | ~EXT4_MOUNT_##opt |
| 1024 | #define set_opt(sb, opt) EXT4_SB(sb)->s_mount_opt |= \ | 1031 | #define set_opt(sb, opt) EXT4_SB(sb)->s_mount_opt |= \ |
| @@ -1179,7 +1186,9 @@ struct ext4_super_block { | |||
| 1179 | __u8 s_encrypt_algos[4]; /* Encryption algorithms in use */ | 1186 | __u8 s_encrypt_algos[4]; /* Encryption algorithms in use */ |
| 1180 | __u8 s_encrypt_pw_salt[16]; /* Salt used for string2key algorithm */ | 1187 | __u8 s_encrypt_pw_salt[16]; /* Salt used for string2key algorithm */ |
| 1181 | __le32 s_lpf_ino; /* Location of the lost+found inode */ | 1188 | __le32 s_lpf_ino; /* Location of the lost+found inode */ |
| 1182 | __le32 s_reserved[100]; /* Padding to the end of the block */ | 1189 | __le32 s_prj_quota_inum; /* inode for tracking project quota */ |
| 1190 | __le32 s_checksum_seed; /* crc32c(uuid) if csum_seed set */ | ||
| 1191 | __le32 s_reserved[98]; /* Padding to the end of the block */ | ||
| 1183 | __le32 s_checksum; /* crc32c(superblock) */ | 1192 | __le32 s_checksum; /* crc32c(superblock) */ |
| 1184 | }; | 1193 | }; |
| 1185 | 1194 | ||
| @@ -1522,6 +1531,7 @@ static inline int ext4_encrypted_inode(struct inode *inode) | |||
| 1522 | * Feature set definitions | 1531 | * Feature set definitions |
| 1523 | */ | 1532 | */ |
| 1524 | 1533 | ||
| 1534 | /* Use the ext4_{has,set,clear}_feature_* helpers; these will be removed */ | ||
| 1525 | #define EXT4_HAS_COMPAT_FEATURE(sb,mask) \ | 1535 | #define EXT4_HAS_COMPAT_FEATURE(sb,mask) \ |
| 1526 | ((EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask)) != 0) | 1536 | ((EXT4_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask)) != 0) |
| 1527 | #define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask) \ | 1537 | #define EXT4_HAS_RO_COMPAT_FEATURE(sb,mask) \ |
| @@ -1566,6 +1576,7 @@ static inline int ext4_encrypted_inode(struct inode *inode) | |||
| 1566 | */ | 1576 | */ |
| 1567 | #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 | 1577 | #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 |
| 1568 | #define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000 | 1578 | #define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000 |
| 1579 | #define EXT4_FEATURE_RO_COMPAT_PROJECT 0x2000 | ||
| 1569 | 1580 | ||
| 1570 | #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 | 1581 | #define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 |
| 1571 | #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 | 1582 | #define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 |
| @@ -1578,11 +1589,99 @@ static inline int ext4_encrypted_inode(struct inode *inode) | |||
| 1578 | #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 | 1589 | #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 |
| 1579 | #define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */ | 1590 | #define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */ |
| 1580 | #define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */ | 1591 | #define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */ |
| 1581 | #define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */ | 1592 | #define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 |
| 1582 | #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ | 1593 | #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ |
| 1583 | #define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ | 1594 | #define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ |
| 1584 | #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 | 1595 | #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 |
| 1585 | 1596 | ||
| 1597 | #define EXT4_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||
| 1598 | static inline bool ext4_has_feature_##name(struct super_block *sb) \ | ||
| 1599 | { \ | ||
| 1600 | return ((EXT4_SB(sb)->s_es->s_feature_compat & \ | ||
| 1601 | cpu_to_le32(EXT4_FEATURE_COMPAT_##flagname)) != 0); \ | ||
| 1602 | } \ | ||
| 1603 | static inline void ext4_set_feature_##name(struct super_block *sb) \ | ||
| 1604 | { \ | ||
| 1605 | EXT4_SB(sb)->s_es->s_feature_compat |= \ | ||
| 1606 | cpu_to_le32(EXT4_FEATURE_COMPAT_##flagname); \ | ||
| 1607 | } \ | ||
| 1608 | static inline void ext4_clear_feature_##name(struct super_block *sb) \ | ||
| 1609 | { \ | ||
| 1610 | EXT4_SB(sb)->s_es->s_feature_compat &= \ | ||
| 1611 | ~cpu_to_le32(EXT4_FEATURE_COMPAT_##flagname); \ | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | #define EXT4_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||
| 1615 | static inline bool ext4_has_feature_##name(struct super_block *sb) \ | ||
| 1616 | { \ | ||
| 1617 | return ((EXT4_SB(sb)->s_es->s_feature_ro_compat & \ | ||
| 1618 | cpu_to_le32(EXT4_FEATURE_RO_COMPAT_##flagname)) != 0); \ | ||
| 1619 | } \ | ||
| 1620 | static inline void ext4_set_feature_##name(struct super_block *sb) \ | ||
| 1621 | { \ | ||
| 1622 | EXT4_SB(sb)->s_es->s_feature_ro_compat |= \ | ||
| 1623 | cpu_to_le32(EXT4_FEATURE_RO_COMPAT_##flagname); \ | ||
| 1624 | } \ | ||
| 1625 | static inline void ext4_clear_feature_##name(struct super_block *sb) \ | ||
| 1626 | { \ | ||
| 1627 | EXT4_SB(sb)->s_es->s_feature_ro_compat &= \ | ||
| 1628 | ~cpu_to_le32(EXT4_FEATURE_RO_COMPAT_##flagname); \ | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | #define EXT4_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||
| 1632 | static inline bool ext4_has_feature_##name(struct super_block *sb) \ | ||
| 1633 | { \ | ||
| 1634 | return ((EXT4_SB(sb)->s_es->s_feature_incompat & \ | ||
| 1635 | cpu_to_le32(EXT4_FEATURE_INCOMPAT_##flagname)) != 0); \ | ||
| 1636 | } \ | ||
| 1637 | static inline void ext4_set_feature_##name(struct super_block *sb) \ | ||
| 1638 | { \ | ||
| 1639 | EXT4_SB(sb)->s_es->s_feature_incompat |= \ | ||
| 1640 | cpu_to_le32(EXT4_FEATURE_INCOMPAT_##flagname); \ | ||
| 1641 | } \ | ||
| 1642 | static inline void ext4_clear_feature_##name(struct super_block *sb) \ | ||
| 1643 | { \ | ||
| 1644 | EXT4_SB(sb)->s_es->s_feature_incompat &= \ | ||
| 1645 | ~cpu_to_le32(EXT4_FEATURE_INCOMPAT_##flagname); \ | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | EXT4_FEATURE_COMPAT_FUNCS(dir_prealloc, DIR_PREALLOC) | ||
| 1649 | EXT4_FEATURE_COMPAT_FUNCS(imagic_inodes, IMAGIC_INODES) | ||
| 1650 | EXT4_FEATURE_COMPAT_FUNCS(journal, HAS_JOURNAL) | ||
| 1651 | EXT4_FEATURE_COMPAT_FUNCS(xattr, EXT_ATTR) | ||
| 1652 | EXT4_FEATURE_COMPAT_FUNCS(resize_inode, RESIZE_INODE) | ||
| 1653 | EXT4_FEATURE_COMPAT_FUNCS(dir_index, DIR_INDEX) | ||
| 1654 | EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, SPARSE_SUPER2) | ||
| 1655 | |||
| 1656 | EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, SPARSE_SUPER) | ||
| 1657 | EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, LARGE_FILE) | ||
| 1658 | EXT4_FEATURE_RO_COMPAT_FUNCS(btree_dir, BTREE_DIR) | ||
| 1659 | EXT4_FEATURE_RO_COMPAT_FUNCS(huge_file, HUGE_FILE) | ||
| 1660 | EXT4_FEATURE_RO_COMPAT_FUNCS(gdt_csum, GDT_CSUM) | ||
| 1661 | EXT4_FEATURE_RO_COMPAT_FUNCS(dir_nlink, DIR_NLINK) | ||
| 1662 | EXT4_FEATURE_RO_COMPAT_FUNCS(extra_isize, EXTRA_ISIZE) | ||
| 1663 | EXT4_FEATURE_RO_COMPAT_FUNCS(quota, QUOTA) | ||
| 1664 | EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc, BIGALLOC) | ||
| 1665 | EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum, METADATA_CSUM) | ||
| 1666 | EXT4_FEATURE_RO_COMPAT_FUNCS(readonly, READONLY) | ||
| 1667 | EXT4_FEATURE_RO_COMPAT_FUNCS(project, PROJECT) | ||
| 1668 | |||
| 1669 | EXT4_FEATURE_INCOMPAT_FUNCS(compression, COMPRESSION) | ||
| 1670 | EXT4_FEATURE_INCOMPAT_FUNCS(filetype, FILETYPE) | ||
| 1671 | EXT4_FEATURE_INCOMPAT_FUNCS(journal_needs_recovery, RECOVER) | ||
| 1672 | EXT4_FEATURE_INCOMPAT_FUNCS(journal_dev, JOURNAL_DEV) | ||
| 1673 | EXT4_FEATURE_INCOMPAT_FUNCS(meta_bg, META_BG) | ||
| 1674 | EXT4_FEATURE_INCOMPAT_FUNCS(extents, EXTENTS) | ||
| 1675 | EXT4_FEATURE_INCOMPAT_FUNCS(64bit, 64BIT) | ||
| 1676 | EXT4_FEATURE_INCOMPAT_FUNCS(mmp, MMP) | ||
| 1677 | EXT4_FEATURE_INCOMPAT_FUNCS(flex_bg, FLEX_BG) | ||
| 1678 | EXT4_FEATURE_INCOMPAT_FUNCS(ea_inode, EA_INODE) | ||
| 1679 | EXT4_FEATURE_INCOMPAT_FUNCS(dirdata, DIRDATA) | ||
| 1680 | EXT4_FEATURE_INCOMPAT_FUNCS(csum_seed, CSUM_SEED) | ||
| 1681 | EXT4_FEATURE_INCOMPAT_FUNCS(largedir, LARGEDIR) | ||
| 1682 | EXT4_FEATURE_INCOMPAT_FUNCS(inline_data, INLINE_DATA) | ||
| 1683 | EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT) | ||
| 1684 | |||
| 1586 | #define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR | 1685 | #define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR |
| 1587 | #define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ | 1686 | #define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ |
| 1588 | EXT4_FEATURE_INCOMPAT_META_BG) | 1687 | EXT4_FEATURE_INCOMPAT_META_BG) |
| @@ -1598,7 +1697,7 @@ static inline int ext4_encrypted_inode(struct inode *inode) | |||
| 1598 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ | 1697 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ |
| 1599 | EXT4_FEATURE_RO_COMPAT_BTREE_DIR) | 1698 | EXT4_FEATURE_RO_COMPAT_BTREE_DIR) |
| 1600 | 1699 | ||
| 1601 | #define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR | 1700 | #define EXT4_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR |
| 1602 | #define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ | 1701 | #define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ |
| 1603 | EXT4_FEATURE_INCOMPAT_RECOVER| \ | 1702 | EXT4_FEATURE_INCOMPAT_RECOVER| \ |
| 1604 | EXT4_FEATURE_INCOMPAT_META_BG| \ | 1703 | EXT4_FEATURE_INCOMPAT_META_BG| \ |
| @@ -1607,7 +1706,8 @@ static inline int ext4_encrypted_inode(struct inode *inode) | |||
| 1607 | EXT4_FEATURE_INCOMPAT_FLEX_BG| \ | 1706 | EXT4_FEATURE_INCOMPAT_FLEX_BG| \ |
| 1608 | EXT4_FEATURE_INCOMPAT_MMP | \ | 1707 | EXT4_FEATURE_INCOMPAT_MMP | \ |
| 1609 | EXT4_FEATURE_INCOMPAT_INLINE_DATA | \ | 1708 | EXT4_FEATURE_INCOMPAT_INLINE_DATA | \ |
| 1610 | EXT4_FEATURE_INCOMPAT_ENCRYPT) | 1709 | EXT4_FEATURE_INCOMPAT_ENCRYPT | \ |
| 1710 | EXT4_FEATURE_INCOMPAT_CSUM_SEED) | ||
| 1611 | #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ | 1711 | #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ |
| 1612 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ | 1712 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ |
| 1613 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ | 1713 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ |
| @@ -1619,6 +1719,40 @@ static inline int ext4_encrypted_inode(struct inode *inode) | |||
| 1619 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ | 1719 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ |
| 1620 | EXT4_FEATURE_RO_COMPAT_QUOTA) | 1720 | EXT4_FEATURE_RO_COMPAT_QUOTA) |
| 1621 | 1721 | ||
| 1722 | #define EXTN_FEATURE_FUNCS(ver) \ | ||
| 1723 | static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \ | ||
| 1724 | { \ | ||
| 1725 | return ((EXT4_SB(sb)->s_es->s_feature_compat & \ | ||
| 1726 | cpu_to_le32(~EXT##ver##_FEATURE_COMPAT_SUPP)) != 0); \ | ||
| 1727 | } \ | ||
| 1728 | static inline bool ext4_has_unknown_ext##ver##_ro_compat_features(struct super_block *sb) \ | ||
| 1729 | { \ | ||
| 1730 | return ((EXT4_SB(sb)->s_es->s_feature_ro_compat & \ | ||
| 1731 | cpu_to_le32(~EXT##ver##_FEATURE_RO_COMPAT_SUPP)) != 0); \ | ||
| 1732 | } \ | ||
| 1733 | static inline bool ext4_has_unknown_ext##ver##_incompat_features(struct super_block *sb) \ | ||
| 1734 | { \ | ||
| 1735 | return ((EXT4_SB(sb)->s_es->s_feature_incompat & \ | ||
| 1736 | cpu_to_le32(~EXT##ver##_FEATURE_INCOMPAT_SUPP)) != 0); \ | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | EXTN_FEATURE_FUNCS(2) | ||
| 1740 | EXTN_FEATURE_FUNCS(3) | ||
| 1741 | EXTN_FEATURE_FUNCS(4) | ||
| 1742 | |||
| 1743 | static inline bool ext4_has_compat_features(struct super_block *sb) | ||
| 1744 | { | ||
| 1745 | return (EXT4_SB(sb)->s_es->s_feature_compat != 0); | ||
| 1746 | } | ||
| 1747 | static inline bool ext4_has_ro_compat_features(struct super_block *sb) | ||
| 1748 | { | ||
| 1749 | return (EXT4_SB(sb)->s_es->s_feature_ro_compat != 0); | ||
| 1750 | } | ||
| 1751 | static inline bool ext4_has_incompat_features(struct super_block *sb) | ||
| 1752 | { | ||
| 1753 | return (EXT4_SB(sb)->s_es->s_feature_incompat != 0); | ||
| 1754 | } | ||
| 1755 | |||
| 1622 | /* | 1756 | /* |
| 1623 | * Default values for user and/or group using reserved blocks | 1757 | * Default values for user and/or group using reserved blocks |
| 1624 | */ | 1758 | */ |
| @@ -1769,8 +1903,7 @@ static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize) | |||
| 1769 | * (c) Daniel Phillips, 2001 | 1903 | * (c) Daniel Phillips, 2001 |
| 1770 | */ | 1904 | */ |
| 1771 | 1905 | ||
| 1772 | #define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \ | 1906 | #define is_dx(dir) (ext4_has_feature_dir_index((dir)->i_sb) && \ |
| 1773 | EXT4_FEATURE_COMPAT_DIR_INDEX) && \ | ||
| 1774 | ext4_test_inode_flag((dir), EXT4_INODE_INDEX)) | 1907 | ext4_test_inode_flag((dir), EXT4_INODE_INDEX)) |
| 1775 | #define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX) | 1908 | #define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX) |
| 1776 | #define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) | 1909 | #define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) |
| @@ -2063,8 +2196,7 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx); | |||
| 2063 | void ext4_restore_control_page(struct page *data_page); | 2196 | void ext4_restore_control_page(struct page *data_page); |
| 2064 | struct page *ext4_encrypt(struct inode *inode, | 2197 | struct page *ext4_encrypt(struct inode *inode, |
| 2065 | struct page *plaintext_page); | 2198 | struct page *plaintext_page); |
| 2066 | int ext4_decrypt(struct ext4_crypto_ctx *ctx, struct page *page); | 2199 | int ext4_decrypt(struct page *page); |
| 2067 | int ext4_decrypt_one(struct inode *inode, struct page *page); | ||
| 2068 | int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex); | 2200 | int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex); |
| 2069 | 2201 | ||
| 2070 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | 2202 | #ifdef CONFIG_EXT4_FS_ENCRYPTION |
| @@ -2072,7 +2204,7 @@ int ext4_init_crypto(void); | |||
| 2072 | void ext4_exit_crypto(void); | 2204 | void ext4_exit_crypto(void); |
| 2073 | static inline int ext4_sb_has_crypto(struct super_block *sb) | 2205 | static inline int ext4_sb_has_crypto(struct super_block *sb) |
| 2074 | { | 2206 | { |
| 2075 | return EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT); | 2207 | return ext4_has_feature_encrypt(sb); |
| 2076 | } | 2208 | } |
| 2077 | #else | 2209 | #else |
| 2078 | static inline int ext4_init_crypto(void) { return 0; } | 2210 | static inline int ext4_init_crypto(void) { return 0; } |
| @@ -2193,8 +2325,7 @@ int ext4_insert_dentry(struct inode *dir, | |||
| 2193 | struct ext4_filename *fname); | 2325 | struct ext4_filename *fname); |
| 2194 | static inline void ext4_update_dx_flag(struct inode *inode) | 2326 | static inline void ext4_update_dx_flag(struct inode *inode) |
| 2195 | { | 2327 | { |
| 2196 | if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb, | 2328 | if (!ext4_has_feature_dir_index(inode->i_sb)) |
| 2197 | EXT4_FEATURE_COMPAT_DIR_INDEX)) | ||
| 2198 | ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); | 2329 | ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); |
| 2199 | } | 2330 | } |
| 2200 | static unsigned char ext4_filetype_table[] = { | 2331 | static unsigned char ext4_filetype_table[] = { |
| @@ -2203,8 +2334,7 @@ static unsigned char ext4_filetype_table[] = { | |||
| 2203 | 2334 | ||
| 2204 | static inline unsigned char get_dtype(struct super_block *sb, int filetype) | 2335 | static inline unsigned char get_dtype(struct super_block *sb, int filetype) |
| 2205 | { | 2336 | { |
| 2206 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FILETYPE) || | 2337 | if (!ext4_has_feature_filetype(sb) || filetype >= EXT4_FT_MAX) |
| 2207 | (filetype >= EXT4_FT_MAX)) | ||
| 2208 | return DT_UNKNOWN; | 2338 | return DT_UNKNOWN; |
| 2209 | 2339 | ||
| 2210 | return ext4_filetype_table[filetype]; | 2340 | return ext4_filetype_table[filetype]; |
| @@ -2245,6 +2375,7 @@ extern int ext4_init_inode_table(struct super_block *sb, | |||
| 2245 | extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate); | 2375 | extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate); |
| 2246 | 2376 | ||
| 2247 | /* mballoc.c */ | 2377 | /* mballoc.c */ |
| 2378 | extern const struct file_operations ext4_seq_mb_groups_fops; | ||
| 2248 | extern long ext4_mb_stats; | 2379 | extern long ext4_mb_stats; |
| 2249 | extern long ext4_mb_max_to_scan; | 2380 | extern long ext4_mb_max_to_scan; |
| 2250 | extern int ext4_mb_init(struct super_block *); | 2381 | extern int ext4_mb_init(struct super_block *); |
| @@ -2372,6 +2503,7 @@ extern int ext4_group_extend(struct super_block *sb, | |||
| 2372 | extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); | 2503 | extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); |
| 2373 | 2504 | ||
| 2374 | /* super.c */ | 2505 | /* super.c */ |
| 2506 | extern int ext4_seq_options_show(struct seq_file *seq, void *offset); | ||
| 2375 | extern int ext4_calculate_overhead(struct super_block *sb); | 2507 | extern int ext4_calculate_overhead(struct super_block *sb); |
| 2376 | extern void ext4_superblock_csum_set(struct super_block *sb); | 2508 | extern void ext4_superblock_csum_set(struct super_block *sb); |
| 2377 | extern void *ext4_kvmalloc(size_t size, gfp_t flags); | 2509 | extern void *ext4_kvmalloc(size_t size, gfp_t flags); |
| @@ -2534,15 +2666,13 @@ extern int ext4_register_li_request(struct super_block *sb, | |||
| 2534 | 2666 | ||
| 2535 | static inline int ext4_has_group_desc_csum(struct super_block *sb) | 2667 | static inline int ext4_has_group_desc_csum(struct super_block *sb) |
| 2536 | { | 2668 | { |
| 2537 | return EXT4_HAS_RO_COMPAT_FEATURE(sb, | 2669 | return ext4_has_feature_gdt_csum(sb) || |
| 2538 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM) || | 2670 | EXT4_SB(sb)->s_chksum_driver != NULL; |
| 2539 | (EXT4_SB(sb)->s_chksum_driver != NULL); | ||
| 2540 | } | 2671 | } |
| 2541 | 2672 | ||
| 2542 | static inline int ext4_has_metadata_csum(struct super_block *sb) | 2673 | static inline int ext4_has_metadata_csum(struct super_block *sb) |
| 2543 | { | 2674 | { |
| 2544 | WARN_ON_ONCE(EXT4_HAS_RO_COMPAT_FEATURE(sb, | 2675 | WARN_ON_ONCE(ext4_has_feature_metadata_csum(sb) && |
| 2545 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && | ||
| 2546 | !EXT4_SB(sb)->s_chksum_driver); | 2676 | !EXT4_SB(sb)->s_chksum_driver); |
| 2547 | 2677 | ||
| 2548 | return (EXT4_SB(sb)->s_chksum_driver != NULL); | 2678 | return (EXT4_SB(sb)->s_chksum_driver != NULL); |
| @@ -2889,7 +3019,7 @@ static unsigned char ext4_type_by_mode[S_IFMT >> S_SHIFT] = { | |||
| 2889 | static inline void ext4_set_de_type(struct super_block *sb, | 3019 | static inline void ext4_set_de_type(struct super_block *sb, |
| 2890 | struct ext4_dir_entry_2 *de, | 3020 | struct ext4_dir_entry_2 *de, |
| 2891 | umode_t mode) { | 3021 | umode_t mode) { |
| 2892 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FILETYPE)) | 3022 | if (ext4_has_feature_filetype(sb)) |
| 2893 | de->file_type = ext4_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; | 3023 | de->file_type = ext4_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; |
| 2894 | } | 3024 | } |
| 2895 | 3025 | ||
| @@ -2903,6 +3033,12 @@ extern const struct inode_operations ext4_encrypted_symlink_inode_operations; | |||
| 2903 | extern const struct inode_operations ext4_symlink_inode_operations; | 3033 | extern const struct inode_operations ext4_symlink_inode_operations; |
| 2904 | extern const struct inode_operations ext4_fast_symlink_inode_operations; | 3034 | extern const struct inode_operations ext4_fast_symlink_inode_operations; |
| 2905 | 3035 | ||
| 3036 | /* sysfs.c */ | ||
| 3037 | extern int ext4_register_sysfs(struct super_block *sb); | ||
| 3038 | extern void ext4_unregister_sysfs(struct super_block *sb); | ||
| 3039 | extern int __init ext4_init_sysfs(void); | ||
| 3040 | extern void ext4_exit_sysfs(void); | ||
| 3041 | |||
| 2906 | /* block_validity */ | 3042 | /* block_validity */ |
| 2907 | extern void ext4_release_system_zone(struct super_block *sb); | 3043 | extern void ext4_release_system_zone(struct super_block *sb); |
| 2908 | extern int ext4_setup_system_zone(struct super_block *sb); | 3044 | extern int ext4_setup_system_zone(struct super_block *sb); |
| @@ -3049,4 +3185,7 @@ extern void ext4_resize_end(struct super_block *sb); | |||
| 3049 | 3185 | ||
| 3050 | #endif /* __KERNEL__ */ | 3186 | #endif /* __KERNEL__ */ |
| 3051 | 3187 | ||
| 3188 | #define EFSBADCRC EBADMSG /* Bad CRC detected */ | ||
| 3189 | #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ | ||
| 3190 | |||
| 3052 | #endif /* _EXT4_H */ | 3191 | #endif /* _EXT4_H */ |
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index d41843181818..e770c1ee4613 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
| @@ -88,13 +88,13 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) | |||
| 88 | return 0; | 88 | return 0; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | err = handle->h_err; | ||
| 91 | if (!handle->h_transaction) { | 92 | if (!handle->h_transaction) { |
| 92 | err = jbd2_journal_stop(handle); | 93 | rc = jbd2_journal_stop(handle); |
| 93 | return handle->h_err ? handle->h_err : err; | 94 | return err ? err : rc; |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | sb = handle->h_transaction->t_journal->j_private; | 97 | sb = handle->h_transaction->t_journal->j_private; |
| 97 | err = handle->h_err; | ||
| 98 | rc = jbd2_journal_stop(handle); | 98 | rc = jbd2_journal_stop(handle); |
| 99 | 99 | ||
| 100 | if (!err) | 100 | if (!err) |
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index 9c5b49fb281e..5f5846211095 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
| @@ -34,8 +34,7 @@ | |||
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | #define EXT4_SINGLEDATA_TRANS_BLOCKS(sb) \ | 36 | #define EXT4_SINGLEDATA_TRANS_BLOCKS(sb) \ |
| 37 | (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS) \ | 37 | (ext4_has_feature_extents(sb) ? 20U : 8U) |
| 38 | ? 20U : 8U) | ||
| 39 | 38 | ||
| 40 | /* Extended attribute operations touch at most two data buffers, | 39 | /* Extended attribute operations touch at most two data buffers, |
| 41 | * two bitmap buffers, and two group summaries, in addition to the inode | 40 | * two bitmap buffers, and two group summaries, in addition to the inode |
| @@ -84,17 +83,16 @@ | |||
| 84 | /* Amount of blocks needed for quota update - we know that the structure was | 83 | /* Amount of blocks needed for quota update - we know that the structure was |
| 85 | * allocated so we need to update only data block */ | 84 | * allocated so we need to update only data block */ |
| 86 | #define EXT4_QUOTA_TRANS_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ | 85 | #define EXT4_QUOTA_TRANS_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ |
| 87 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\ | 86 | ext4_has_feature_quota(sb)) ? 1 : 0) |
| 88 | 1 : 0) | ||
| 89 | /* Amount of blocks needed for quota insert/delete - we do some block writes | 87 | /* Amount of blocks needed for quota insert/delete - we do some block writes |
| 90 | * but inode, sb and group updates are done only once */ | 88 | * but inode, sb and group updates are done only once */ |
| 91 | #define EXT4_QUOTA_INIT_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ | 89 | #define EXT4_QUOTA_INIT_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ |
| 92 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\ | 90 | ext4_has_feature_quota(sb)) ?\ |
| 93 | (DQUOT_INIT_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\ | 91 | (DQUOT_INIT_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\ |
| 94 | +3+DQUOT_INIT_REWRITE) : 0) | 92 | +3+DQUOT_INIT_REWRITE) : 0) |
| 95 | 93 | ||
| 96 | #define EXT4_QUOTA_DEL_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ | 94 | #define EXT4_QUOTA_DEL_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ |
| 97 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\ | 95 | ext4_has_feature_quota(sb)) ?\ |
| 98 | (DQUOT_DEL_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\ | 96 | (DQUOT_DEL_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\ |
| 99 | +3+DQUOT_DEL_REWRITE) : 0) | 97 | +3+DQUOT_DEL_REWRITE) : 0) |
| 100 | #else | 98 | #else |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2553aa8b608d..3a6197a2e270 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -442,7 +442,7 @@ static int __ext4_ext_check(const char *function, unsigned int line, | |||
| 442 | int depth, ext4_fsblk_t pblk) | 442 | int depth, ext4_fsblk_t pblk) |
| 443 | { | 443 | { |
| 444 | const char *error_msg; | 444 | const char *error_msg; |
| 445 | int max = 0; | 445 | int max = 0, err = -EFSCORRUPTED; |
| 446 | 446 | ||
| 447 | if (unlikely(eh->eh_magic != EXT4_EXT_MAGIC)) { | 447 | if (unlikely(eh->eh_magic != EXT4_EXT_MAGIC)) { |
| 448 | error_msg = "invalid magic"; | 448 | error_msg = "invalid magic"; |
| @@ -473,6 +473,7 @@ static int __ext4_ext_check(const char *function, unsigned int line, | |||
| 473 | if (ext_depth(inode) != depth && | 473 | if (ext_depth(inode) != depth && |
| 474 | !ext4_extent_block_csum_verify(inode, eh)) { | 474 | !ext4_extent_block_csum_verify(inode, eh)) { |
| 475 | error_msg = "extent tree corrupted"; | 475 | error_msg = "extent tree corrupted"; |
| 476 | err = -EFSBADCRC; | ||
| 476 | goto corrupted; | 477 | goto corrupted; |
| 477 | } | 478 | } |
| 478 | return 0; | 479 | return 0; |
| @@ -485,7 +486,7 @@ corrupted: | |||
| 485 | le16_to_cpu(eh->eh_magic), | 486 | le16_to_cpu(eh->eh_magic), |
| 486 | le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max), | 487 | le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max), |
| 487 | max, le16_to_cpu(eh->eh_depth), depth); | 488 | max, le16_to_cpu(eh->eh_depth), depth); |
| 488 | return -EIO; | 489 | return err; |
| 489 | } | 490 | } |
| 490 | 491 | ||
| 491 | #define ext4_ext_check(inode, eh, depth, pblk) \ | 492 | #define ext4_ext_check(inode, eh, depth, pblk) \ |
| @@ -910,7 +911,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, | |||
| 910 | put_bh(bh); | 911 | put_bh(bh); |
| 911 | EXT4_ERROR_INODE(inode, | 912 | EXT4_ERROR_INODE(inode, |
| 912 | "ppos %d > depth %d", ppos, depth); | 913 | "ppos %d > depth %d", ppos, depth); |
| 913 | ret = -EIO; | 914 | ret = -EFSCORRUPTED; |
| 914 | goto err; | 915 | goto err; |
| 915 | } | 916 | } |
| 916 | path[ppos].p_bh = bh; | 917 | path[ppos].p_bh = bh; |
| @@ -959,7 +960,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
| 959 | EXT4_ERROR_INODE(inode, | 960 | EXT4_ERROR_INODE(inode, |
| 960 | "logical %d == ei_block %d!", | 961 | "logical %d == ei_block %d!", |
| 961 | logical, le32_to_cpu(curp->p_idx->ei_block)); | 962 | logical, le32_to_cpu(curp->p_idx->ei_block)); |
| 962 | return -EIO; | 963 | return -EFSCORRUPTED; |
| 963 | } | 964 | } |
| 964 | 965 | ||
| 965 | if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries) | 966 | if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries) |
| @@ -968,7 +969,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
| 968 | "eh_entries %d >= eh_max %d!", | 969 | "eh_entries %d >= eh_max %d!", |
| 969 | le16_to_cpu(curp->p_hdr->eh_entries), | 970 | le16_to_cpu(curp->p_hdr->eh_entries), |
| 970 | le16_to_cpu(curp->p_hdr->eh_max)); | 971 | le16_to_cpu(curp->p_hdr->eh_max)); |
| 971 | return -EIO; | 972 | return -EFSCORRUPTED; |
| 972 | } | 973 | } |
| 973 | 974 | ||
| 974 | if (logical > le32_to_cpu(curp->p_idx->ei_block)) { | 975 | if (logical > le32_to_cpu(curp->p_idx->ei_block)) { |
| @@ -992,7 +993,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
| 992 | 993 | ||
| 993 | if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) { | 994 | if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) { |
| 994 | EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!"); | 995 | EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!"); |
| 995 | return -EIO; | 996 | return -EFSCORRUPTED; |
| 996 | } | 997 | } |
| 997 | 998 | ||
| 998 | ix->ei_block = cpu_to_le32(logical); | 999 | ix->ei_block = cpu_to_le32(logical); |
| @@ -1001,7 +1002,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
| 1001 | 1002 | ||
| 1002 | if (unlikely(ix > EXT_LAST_INDEX(curp->p_hdr))) { | 1003 | if (unlikely(ix > EXT_LAST_INDEX(curp->p_hdr))) { |
| 1003 | EXT4_ERROR_INODE(inode, "ix > EXT_LAST_INDEX!"); | 1004 | EXT4_ERROR_INODE(inode, "ix > EXT_LAST_INDEX!"); |
| 1004 | return -EIO; | 1005 | return -EFSCORRUPTED; |
| 1005 | } | 1006 | } |
| 1006 | 1007 | ||
| 1007 | err = ext4_ext_dirty(handle, inode, curp); | 1008 | err = ext4_ext_dirty(handle, inode, curp); |
| @@ -1042,7 +1043,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1042 | * border from split point */ | 1043 | * border from split point */ |
| 1043 | if (unlikely(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr))) { | 1044 | if (unlikely(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr))) { |
| 1044 | EXT4_ERROR_INODE(inode, "p_ext > EXT_MAX_EXTENT!"); | 1045 | EXT4_ERROR_INODE(inode, "p_ext > EXT_MAX_EXTENT!"); |
| 1045 | return -EIO; | 1046 | return -EFSCORRUPTED; |
| 1046 | } | 1047 | } |
| 1047 | if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) { | 1048 | if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) { |
| 1048 | border = path[depth].p_ext[1].ee_block; | 1049 | border = path[depth].p_ext[1].ee_block; |
| @@ -1086,7 +1087,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1086 | newblock = ablocks[--a]; | 1087 | newblock = ablocks[--a]; |
| 1087 | if (unlikely(newblock == 0)) { | 1088 | if (unlikely(newblock == 0)) { |
| 1088 | EXT4_ERROR_INODE(inode, "newblock == 0!"); | 1089 | EXT4_ERROR_INODE(inode, "newblock == 0!"); |
| 1089 | err = -EIO; | 1090 | err = -EFSCORRUPTED; |
| 1090 | goto cleanup; | 1091 | goto cleanup; |
| 1091 | } | 1092 | } |
| 1092 | bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); | 1093 | bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); |
| @@ -1112,7 +1113,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1112 | EXT4_ERROR_INODE(inode, "eh_entries %d != eh_max %d!", | 1113 | EXT4_ERROR_INODE(inode, "eh_entries %d != eh_max %d!", |
| 1113 | path[depth].p_hdr->eh_entries, | 1114 | path[depth].p_hdr->eh_entries, |
| 1114 | path[depth].p_hdr->eh_max); | 1115 | path[depth].p_hdr->eh_max); |
| 1115 | err = -EIO; | 1116 | err = -EFSCORRUPTED; |
| 1116 | goto cleanup; | 1117 | goto cleanup; |
| 1117 | } | 1118 | } |
| 1118 | /* start copy from next extent */ | 1119 | /* start copy from next extent */ |
| @@ -1151,7 +1152,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1151 | k = depth - at - 1; | 1152 | k = depth - at - 1; |
| 1152 | if (unlikely(k < 0)) { | 1153 | if (unlikely(k < 0)) { |
| 1153 | EXT4_ERROR_INODE(inode, "k %d < 0!", k); | 1154 | EXT4_ERROR_INODE(inode, "k %d < 0!", k); |
| 1154 | err = -EIO; | 1155 | err = -EFSCORRUPTED; |
| 1155 | goto cleanup; | 1156 | goto cleanup; |
| 1156 | } | 1157 | } |
| 1157 | if (k) | 1158 | if (k) |
| @@ -1191,7 +1192,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1191 | EXT4_ERROR_INODE(inode, | 1192 | EXT4_ERROR_INODE(inode, |
| 1192 | "EXT_MAX_INDEX != EXT_LAST_INDEX ee_block %d!", | 1193 | "EXT_MAX_INDEX != EXT_LAST_INDEX ee_block %d!", |
| 1193 | le32_to_cpu(path[i].p_ext->ee_block)); | 1194 | le32_to_cpu(path[i].p_ext->ee_block)); |
| 1194 | err = -EIO; | 1195 | err = -EFSCORRUPTED; |
| 1195 | goto cleanup; | 1196 | goto cleanup; |
| 1196 | } | 1197 | } |
| 1197 | /* start copy indexes */ | 1198 | /* start copy indexes */ |
| @@ -1425,7 +1426,7 @@ static int ext4_ext_search_left(struct inode *inode, | |||
| 1425 | 1426 | ||
| 1426 | if (unlikely(path == NULL)) { | 1427 | if (unlikely(path == NULL)) { |
| 1427 | EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical); | 1428 | EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical); |
| 1428 | return -EIO; | 1429 | return -EFSCORRUPTED; |
| 1429 | } | 1430 | } |
| 1430 | depth = path->p_depth; | 1431 | depth = path->p_depth; |
| 1431 | *phys = 0; | 1432 | *phys = 0; |
| @@ -1444,7 +1445,7 @@ static int ext4_ext_search_left(struct inode *inode, | |||
| 1444 | EXT4_ERROR_INODE(inode, | 1445 | EXT4_ERROR_INODE(inode, |
| 1445 | "EXT_FIRST_EXTENT != ex *logical %d ee_block %d!", | 1446 | "EXT_FIRST_EXTENT != ex *logical %d ee_block %d!", |
| 1446 | *logical, le32_to_cpu(ex->ee_block)); | 1447 | *logical, le32_to_cpu(ex->ee_block)); |
| 1447 | return -EIO; | 1448 | return -EFSCORRUPTED; |
| 1448 | } | 1449 | } |
| 1449 | while (--depth >= 0) { | 1450 | while (--depth >= 0) { |
| 1450 | ix = path[depth].p_idx; | 1451 | ix = path[depth].p_idx; |
| @@ -1455,7 +1456,7 @@ static int ext4_ext_search_left(struct inode *inode, | |||
| 1455 | EXT_FIRST_INDEX(path[depth].p_hdr) != NULL ? | 1456 | EXT_FIRST_INDEX(path[depth].p_hdr) != NULL ? |
| 1456 | le32_to_cpu(EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block) : 0, | 1457 | le32_to_cpu(EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block) : 0, |
| 1457 | depth); | 1458 | depth); |
| 1458 | return -EIO; | 1459 | return -EFSCORRUPTED; |
| 1459 | } | 1460 | } |
| 1460 | } | 1461 | } |
| 1461 | return 0; | 1462 | return 0; |
| @@ -1465,7 +1466,7 @@ static int ext4_ext_search_left(struct inode *inode, | |||
| 1465 | EXT4_ERROR_INODE(inode, | 1466 | EXT4_ERROR_INODE(inode, |
| 1466 | "logical %d < ee_block %d + ee_len %d!", | 1467 | "logical %d < ee_block %d + ee_len %d!", |
| 1467 | *logical, le32_to_cpu(ex->ee_block), ee_len); | 1468 | *logical, le32_to_cpu(ex->ee_block), ee_len); |
| 1468 | return -EIO; | 1469 | return -EFSCORRUPTED; |
| 1469 | } | 1470 | } |
| 1470 | 1471 | ||
| 1471 | *logical = le32_to_cpu(ex->ee_block) + ee_len - 1; | 1472 | *logical = le32_to_cpu(ex->ee_block) + ee_len - 1; |
| @@ -1495,7 +1496,7 @@ static int ext4_ext_search_right(struct inode *inode, | |||
| 1495 | 1496 | ||
| 1496 | if (unlikely(path == NULL)) { | 1497 | if (unlikely(path == NULL)) { |
| 1497 | EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical); | 1498 | EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical); |
| 1498 | return -EIO; | 1499 | return -EFSCORRUPTED; |
| 1499 | } | 1500 | } |
| 1500 | depth = path->p_depth; | 1501 | depth = path->p_depth; |
| 1501 | *phys = 0; | 1502 | *phys = 0; |
| @@ -1514,7 +1515,7 @@ static int ext4_ext_search_right(struct inode *inode, | |||
| 1514 | EXT4_ERROR_INODE(inode, | 1515 | EXT4_ERROR_INODE(inode, |
| 1515 | "first_extent(path[%d].p_hdr) != ex", | 1516 | "first_extent(path[%d].p_hdr) != ex", |
| 1516 | depth); | 1517 | depth); |
| 1517 | return -EIO; | 1518 | return -EFSCORRUPTED; |
| 1518 | } | 1519 | } |
| 1519 | while (--depth >= 0) { | 1520 | while (--depth >= 0) { |
| 1520 | ix = path[depth].p_idx; | 1521 | ix = path[depth].p_idx; |
| @@ -1522,7 +1523,7 @@ static int ext4_ext_search_right(struct inode *inode, | |||
| 1522 | EXT4_ERROR_INODE(inode, | 1523 | EXT4_ERROR_INODE(inode, |
| 1523 | "ix != EXT_FIRST_INDEX *logical %d!", | 1524 | "ix != EXT_FIRST_INDEX *logical %d!", |
| 1524 | *logical); | 1525 | *logical); |
| 1525 | return -EIO; | 1526 | return -EFSCORRUPTED; |
| 1526 | } | 1527 | } |
| 1527 | } | 1528 | } |
| 1528 | goto found_extent; | 1529 | goto found_extent; |
| @@ -1532,7 +1533,7 @@ static int ext4_ext_search_right(struct inode *inode, | |||
| 1532 | EXT4_ERROR_INODE(inode, | 1533 | EXT4_ERROR_INODE(inode, |
| 1533 | "logical %d < ee_block %d + ee_len %d!", | 1534 | "logical %d < ee_block %d + ee_len %d!", |
| 1534 | *logical, le32_to_cpu(ex->ee_block), ee_len); | 1535 | *logical, le32_to_cpu(ex->ee_block), ee_len); |
| 1535 | return -EIO; | 1536 | return -EFSCORRUPTED; |
| 1536 | } | 1537 | } |
| 1537 | 1538 | ||
| 1538 | if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) { | 1539 | if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) { |
| @@ -1670,7 +1671,7 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode, | |||
| 1670 | if (unlikely(ex == NULL || eh == NULL)) { | 1671 | if (unlikely(ex == NULL || eh == NULL)) { |
| 1671 | EXT4_ERROR_INODE(inode, | 1672 | EXT4_ERROR_INODE(inode, |
| 1672 | "ex %p == NULL or eh %p == NULL", ex, eh); | 1673 | "ex %p == NULL or eh %p == NULL", ex, eh); |
| 1673 | return -EIO; | 1674 | return -EFSCORRUPTED; |
| 1674 | } | 1675 | } |
| 1675 | 1676 | ||
| 1676 | if (depth == 0) { | 1677 | if (depth == 0) { |
| @@ -1938,14 +1939,14 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
| 1938 | mb_flags |= EXT4_MB_DELALLOC_RESERVED; | 1939 | mb_flags |= EXT4_MB_DELALLOC_RESERVED; |
| 1939 | if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { | 1940 | if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { |
| 1940 | EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); | 1941 | EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); |
| 1941 | return -EIO; | 1942 | return -EFSCORRUPTED; |
| 1942 | } | 1943 | } |
| 1943 | depth = ext_depth(inode); | 1944 | depth = ext_depth(inode); |
| 1944 | ex = path[depth].p_ext; | 1945 | ex = path[depth].p_ext; |
| 1945 | eh = path[depth].p_hdr; | 1946 | eh = path[depth].p_hdr; |
| 1946 | if (unlikely(path[depth].p_hdr == NULL)) { | 1947 | if (unlikely(path[depth].p_hdr == NULL)) { |
| 1947 | EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); | 1948 | EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); |
| 1948 | return -EIO; | 1949 | return -EFSCORRUPTED; |
| 1949 | } | 1950 | } |
| 1950 | 1951 | ||
| 1951 | /* try to insert block into found extent and return */ | 1952 | /* try to insert block into found extent and return */ |
| @@ -2172,7 +2173,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode, | |||
| 2172 | if (unlikely(path[depth].p_hdr == NULL)) { | 2173 | if (unlikely(path[depth].p_hdr == NULL)) { |
| 2173 | up_read(&EXT4_I(inode)->i_data_sem); | 2174 | up_read(&EXT4_I(inode)->i_data_sem); |
| 2174 | EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); | 2175 | EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); |
| 2175 | err = -EIO; | 2176 | err = -EFSCORRUPTED; |
| 2176 | break; | 2177 | break; |
| 2177 | } | 2178 | } |
| 2178 | ex = path[depth].p_ext; | 2179 | ex = path[depth].p_ext; |
| @@ -2241,7 +2242,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode, | |||
| 2241 | 2242 | ||
| 2242 | if (unlikely(es.es_len == 0)) { | 2243 | if (unlikely(es.es_len == 0)) { |
| 2243 | EXT4_ERROR_INODE(inode, "es.es_len == 0"); | 2244 | EXT4_ERROR_INODE(inode, "es.es_len == 0"); |
| 2244 | err = -EIO; | 2245 | err = -EFSCORRUPTED; |
| 2245 | break; | 2246 | break; |
| 2246 | } | 2247 | } |
| 2247 | 2248 | ||
| @@ -2264,7 +2265,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode, | |||
| 2264 | "next extent == %u, next " | 2265 | "next extent == %u, next " |
| 2265 | "delalloc extent = %u", | 2266 | "delalloc extent = %u", |
| 2266 | next, next_del); | 2267 | next, next_del); |
| 2267 | err = -EIO; | 2268 | err = -EFSCORRUPTED; |
| 2268 | break; | 2269 | break; |
| 2269 | } | 2270 | } |
| 2270 | } | 2271 | } |
| @@ -2363,7 +2364,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
| 2363 | leaf = ext4_idx_pblock(path->p_idx); | 2364 | leaf = ext4_idx_pblock(path->p_idx); |
| 2364 | if (unlikely(path->p_hdr->eh_entries == 0)) { | 2365 | if (unlikely(path->p_hdr->eh_entries == 0)) { |
| 2365 | EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); | 2366 | EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); |
| 2366 | return -EIO; | 2367 | return -EFSCORRUPTED; |
| 2367 | } | 2368 | } |
| 2368 | err = ext4_ext_get_access(handle, inode, path); | 2369 | err = ext4_ext_get_access(handle, inode, path); |
| 2369 | if (err) | 2370 | if (err) |
| @@ -2612,7 +2613,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2612 | eh = path[depth].p_hdr; | 2613 | eh = path[depth].p_hdr; |
| 2613 | if (unlikely(path[depth].p_hdr == NULL)) { | 2614 | if (unlikely(path[depth].p_hdr == NULL)) { |
| 2614 | EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); | 2615 | EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth); |
| 2615 | return -EIO; | 2616 | return -EFSCORRUPTED; |
| 2616 | } | 2617 | } |
| 2617 | /* find where to start removing */ | 2618 | /* find where to start removing */ |
| 2618 | ex = path[depth].p_ext; | 2619 | ex = path[depth].p_ext; |
| @@ -2666,7 +2667,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2666 | "on extent %u:%u", | 2667 | "on extent %u:%u", |
| 2667 | start, end, ex_ee_block, | 2668 | start, end, ex_ee_block, |
| 2668 | ex_ee_block + ex_ee_len - 1); | 2669 | ex_ee_block + ex_ee_len - 1); |
| 2669 | err = -EIO; | 2670 | err = -EFSCORRUPTED; |
| 2670 | goto out; | 2671 | goto out; |
| 2671 | } else if (a != ex_ee_block) { | 2672 | } else if (a != ex_ee_block) { |
| 2672 | /* remove tail of the extent */ | 2673 | /* remove tail of the extent */ |
| @@ -2841,7 +2842,7 @@ again: | |||
| 2841 | EXT4_ERROR_INODE(inode, | 2842 | EXT4_ERROR_INODE(inode, |
| 2842 | "path[%d].p_hdr == NULL", | 2843 | "path[%d].p_hdr == NULL", |
| 2843 | depth); | 2844 | depth); |
| 2844 | err = -EIO; | 2845 | err = -EFSCORRUPTED; |
| 2845 | } | 2846 | } |
| 2846 | goto out; | 2847 | goto out; |
| 2847 | } | 2848 | } |
| @@ -2920,7 +2921,7 @@ again: | |||
| 2920 | i = 0; | 2921 | i = 0; |
| 2921 | 2922 | ||
| 2922 | if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) { | 2923 | if (ext4_ext_check(inode, path[0].p_hdr, depth, 0)) { |
| 2923 | err = -EIO; | 2924 | err = -EFSCORRUPTED; |
| 2924 | goto out; | 2925 | goto out; |
| 2925 | } | 2926 | } |
| 2926 | } | 2927 | } |
| @@ -2978,7 +2979,7 @@ again: | |||
| 2978 | * Should be a no-op if we did IO above. */ | 2979 | * Should be a no-op if we did IO above. */ |
| 2979 | cond_resched(); | 2980 | cond_resched(); |
| 2980 | if (WARN_ON(i + 1 > depth)) { | 2981 | if (WARN_ON(i + 1 > depth)) { |
| 2981 | err = -EIO; | 2982 | err = -EFSCORRUPTED; |
| 2982 | break; | 2983 | break; |
| 2983 | } | 2984 | } |
| 2984 | path[i + 1].p_bh = bh; | 2985 | path[i + 1].p_bh = bh; |
| @@ -3054,7 +3055,7 @@ void ext4_ext_init(struct super_block *sb) | |||
| 3054 | * possible initialization would be here | 3055 | * possible initialization would be here |
| 3055 | */ | 3056 | */ |
| 3056 | 3057 | ||
| 3057 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { | 3058 | if (ext4_has_feature_extents(sb)) { |
| 3058 | #if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS) | 3059 | #if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS) |
| 3059 | printk(KERN_INFO "EXT4-fs: file extents enabled" | 3060 | printk(KERN_INFO "EXT4-fs: file extents enabled" |
| 3060 | #ifdef AGGRESSIVE_TEST | 3061 | #ifdef AGGRESSIVE_TEST |
| @@ -3081,7 +3082,7 @@ void ext4_ext_init(struct super_block *sb) | |||
| 3081 | */ | 3082 | */ |
| 3082 | void ext4_ext_release(struct super_block *sb) | 3083 | void ext4_ext_release(struct super_block *sb) |
| 3083 | { | 3084 | { |
| 3084 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) | 3085 | if (!ext4_has_feature_extents(sb)) |
| 3085 | return; | 3086 | return; |
| 3086 | 3087 | ||
| 3087 | #ifdef EXTENTS_STATS | 3088 | #ifdef EXTENTS_STATS |
| @@ -3345,7 +3346,7 @@ static int ext4_split_extent(handle_t *handle, | |||
| 3345 | if (!ex) { | 3346 | if (!ex) { |
| 3346 | EXT4_ERROR_INODE(inode, "unexpected hole at %lu", | 3347 | EXT4_ERROR_INODE(inode, "unexpected hole at %lu", |
| 3347 | (unsigned long) map->m_lblk); | 3348 | (unsigned long) map->m_lblk); |
| 3348 | return -EIO; | 3349 | return -EFSCORRUPTED; |
| 3349 | } | 3350 | } |
| 3350 | unwritten = ext4_ext_is_unwritten(ex); | 3351 | unwritten = ext4_ext_is_unwritten(ex); |
| 3351 | split_flag1 = 0; | 3352 | split_flag1 = 0; |
| @@ -3558,6 +3559,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
| 3558 | max_zeroout = sbi->s_extent_max_zeroout_kb >> | 3559 | max_zeroout = sbi->s_extent_max_zeroout_kb >> |
| 3559 | (inode->i_sb->s_blocksize_bits - 10); | 3560 | (inode->i_sb->s_blocksize_bits - 10); |
| 3560 | 3561 | ||
| 3562 | if (ext4_encrypted_inode(inode)) | ||
| 3563 | max_zeroout = 0; | ||
| 3564 | |||
| 3561 | /* If extent is less than s_max_zeroout_kb, zeroout directly */ | 3565 | /* If extent is less than s_max_zeroout_kb, zeroout directly */ |
| 3562 | if (max_zeroout && (ee_len <= max_zeroout)) { | 3566 | if (max_zeroout && (ee_len <= max_zeroout)) { |
| 3563 | err = ext4_ext_zeroout(inode, ex); | 3567 | err = ext4_ext_zeroout(inode, ex); |
| @@ -3970,7 +3974,7 @@ convert_initialized_extent(handle_t *handle, struct inode *inode, | |||
| 3970 | if (!ex) { | 3974 | if (!ex) { |
| 3971 | EXT4_ERROR_INODE(inode, "unexpected hole at %lu", | 3975 | EXT4_ERROR_INODE(inode, "unexpected hole at %lu", |
| 3972 | (unsigned long) map->m_lblk); | 3976 | (unsigned long) map->m_lblk); |
| 3973 | return -EIO; | 3977 | return -EFSCORRUPTED; |
| 3974 | } | 3978 | } |
| 3975 | } | 3979 | } |
| 3976 | 3980 | ||
| @@ -4308,7 +4312,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
| 4308 | "lblock: %lu, depth: %d pblock %lld", | 4312 | "lblock: %lu, depth: %d pblock %lld", |
| 4309 | (unsigned long) map->m_lblk, depth, | 4313 | (unsigned long) map->m_lblk, depth, |
| 4310 | path[depth].p_block); | 4314 | path[depth].p_block); |
| 4311 | err = -EIO; | 4315 | err = -EFSCORRUPTED; |
| 4312 | goto out2; | 4316 | goto out2; |
| 4313 | } | 4317 | } |
| 4314 | 4318 | ||
| @@ -5271,7 +5275,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, | |||
| 5271 | if (depth == path->p_depth) { | 5275 | if (depth == path->p_depth) { |
| 5272 | ex_start = path[depth].p_ext; | 5276 | ex_start = path[depth].p_ext; |
| 5273 | if (!ex_start) | 5277 | if (!ex_start) |
| 5274 | return -EIO; | 5278 | return -EFSCORRUPTED; |
| 5275 | 5279 | ||
| 5276 | ex_last = EXT_LAST_EXTENT(path[depth].p_hdr); | 5280 | ex_last = EXT_LAST_EXTENT(path[depth].p_hdr); |
| 5277 | 5281 | ||
| @@ -5411,7 +5415,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, | |||
| 5411 | if (!extent) { | 5415 | if (!extent) { |
| 5412 | EXT4_ERROR_INODE(inode, "unexpected hole at %lu", | 5416 | EXT4_ERROR_INODE(inode, "unexpected hole at %lu", |
| 5413 | (unsigned long) *iterator); | 5417 | (unsigned long) *iterator); |
| 5414 | return -EIO; | 5418 | return -EFSCORRUPTED; |
| 5415 | } | 5419 | } |
| 5416 | if (SHIFT == SHIFT_LEFT && *iterator > | 5420 | if (SHIFT == SHIFT_LEFT && *iterator > |
| 5417 | le32_to_cpu(extent->ee_block)) { | 5421 | le32_to_cpu(extent->ee_block)) { |
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 26724aeece73..ac748b3af1c1 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c | |||
| @@ -1089,20 +1089,9 @@ static unsigned long ext4_es_scan(struct shrinker *shrink, | |||
| 1089 | return nr_shrunk; | 1089 | return nr_shrunk; |
| 1090 | } | 1090 | } |
| 1091 | 1091 | ||
| 1092 | static void *ext4_es_seq_shrinker_info_start(struct seq_file *seq, loff_t *pos) | 1092 | int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v) |
| 1093 | { | 1093 | { |
| 1094 | return *pos ? NULL : SEQ_START_TOKEN; | 1094 | struct ext4_sb_info *sbi = EXT4_SB((struct super_block *) seq->private); |
| 1095 | } | ||
| 1096 | |||
| 1097 | static void * | ||
| 1098 | ext4_es_seq_shrinker_info_next(struct seq_file *seq, void *v, loff_t *pos) | ||
| 1099 | { | ||
| 1100 | return NULL; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | static int ext4_es_seq_shrinker_info_show(struct seq_file *seq, void *v) | ||
| 1104 | { | ||
| 1105 | struct ext4_sb_info *sbi = seq->private; | ||
| 1106 | struct ext4_es_stats *es_stats = &sbi->s_es_stats; | 1095 | struct ext4_es_stats *es_stats = &sbi->s_es_stats; |
| 1107 | struct ext4_inode_info *ei, *max = NULL; | 1096 | struct ext4_inode_info *ei, *max = NULL; |
| 1108 | unsigned int inode_cnt = 0; | 1097 | unsigned int inode_cnt = 0; |
| @@ -1143,45 +1132,6 @@ static int ext4_es_seq_shrinker_info_show(struct seq_file *seq, void *v) | |||
| 1143 | return 0; | 1132 | return 0; |
| 1144 | } | 1133 | } |
| 1145 | 1134 | ||
| 1146 | static void ext4_es_seq_shrinker_info_stop(struct seq_file *seq, void *v) | ||
| 1147 | { | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | static const struct seq_operations ext4_es_seq_shrinker_info_ops = { | ||
| 1151 | .start = ext4_es_seq_shrinker_info_start, | ||
| 1152 | .next = ext4_es_seq_shrinker_info_next, | ||
| 1153 | .stop = ext4_es_seq_shrinker_info_stop, | ||
| 1154 | .show = ext4_es_seq_shrinker_info_show, | ||
| 1155 | }; | ||
| 1156 | |||
| 1157 | static int | ||
| 1158 | ext4_es_seq_shrinker_info_open(struct inode *inode, struct file *file) | ||
| 1159 | { | ||
| 1160 | int ret; | ||
| 1161 | |||
| 1162 | ret = seq_open(file, &ext4_es_seq_shrinker_info_ops); | ||
| 1163 | if (!ret) { | ||
| 1164 | struct seq_file *m = file->private_data; | ||
| 1165 | m->private = PDE_DATA(inode); | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | return ret; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | static int | ||
| 1172 | ext4_es_seq_shrinker_info_release(struct inode *inode, struct file *file) | ||
| 1173 | { | ||
| 1174 | return seq_release(inode, file); | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | static const struct file_operations ext4_es_seq_shrinker_info_fops = { | ||
| 1178 | .owner = THIS_MODULE, | ||
| 1179 | .open = ext4_es_seq_shrinker_info_open, | ||
| 1180 | .read = seq_read, | ||
| 1181 | .llseek = seq_lseek, | ||
| 1182 | .release = ext4_es_seq_shrinker_info_release, | ||
| 1183 | }; | ||
| 1184 | |||
| 1185 | int ext4_es_register_shrinker(struct ext4_sb_info *sbi) | 1135 | int ext4_es_register_shrinker(struct ext4_sb_info *sbi) |
| 1186 | { | 1136 | { |
| 1187 | int err; | 1137 | int err; |
| @@ -1210,10 +1160,6 @@ int ext4_es_register_shrinker(struct ext4_sb_info *sbi) | |||
| 1210 | if (err) | 1160 | if (err) |
| 1211 | goto err2; | 1161 | goto err2; |
| 1212 | 1162 | ||
| 1213 | if (sbi->s_proc) | ||
| 1214 | proc_create_data("es_shrinker_info", S_IRUGO, sbi->s_proc, | ||
| 1215 | &ext4_es_seq_shrinker_info_fops, sbi); | ||
| 1216 | |||
| 1217 | return 0; | 1163 | return 0; |
| 1218 | 1164 | ||
| 1219 | err2: | 1165 | err2: |
| @@ -1225,8 +1171,6 @@ err1: | |||
| 1225 | 1171 | ||
| 1226 | void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi) | 1172 | void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi) |
| 1227 | { | 1173 | { |
| 1228 | if (sbi->s_proc) | ||
| 1229 | remove_proc_entry("es_shrinker_info", sbi->s_proc); | ||
| 1230 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt); | 1174 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt); |
| 1231 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt); | 1175 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt); |
| 1232 | unregister_shrinker(&sbi->s_es_shrinker); | 1176 | unregister_shrinker(&sbi->s_es_shrinker); |
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h index 691b52613ce4..f7aa24f4642d 100644 --- a/fs/ext4/extents_status.h +++ b/fs/ext4/extents_status.h | |||
| @@ -172,4 +172,6 @@ static inline void ext4_es_store_pblock_status(struct extent_status *es, | |||
| 172 | extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi); | 172 | extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi); |
| 173 | extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); | 173 | extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); |
| 174 | 174 | ||
| 175 | extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v); | ||
| 176 | |||
| 175 | #endif /* _EXT4_EXTENTS_STATUS_H */ | 177 | #endif /* _EXT4_EXTENTS_STATUS_H */ |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 619bfc1fda8c..1b8024d26f65 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -64,7 +64,7 @@ void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap) | |||
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | /* Initializes an uninitialized inode bitmap */ | 66 | /* Initializes an uninitialized inode bitmap */ |
| 67 | static unsigned ext4_init_inode_bitmap(struct super_block *sb, | 67 | static int ext4_init_inode_bitmap(struct super_block *sb, |
| 68 | struct buffer_head *bh, | 68 | struct buffer_head *bh, |
| 69 | ext4_group_t block_group, | 69 | ext4_group_t block_group, |
| 70 | struct ext4_group_desc *gdp) | 70 | struct ext4_group_desc *gdp) |
| @@ -89,7 +89,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb, | |||
| 89 | count); | 89 | count); |
| 90 | } | 90 | } |
| 91 | set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); | 91 | set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); |
| 92 | return 0; | 92 | return -EFSBADCRC; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); | 95 | memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); |
| @@ -99,7 +99,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb, | |||
| 99 | EXT4_INODES_PER_GROUP(sb) / 8); | 99 | EXT4_INODES_PER_GROUP(sb) / 8); |
| 100 | ext4_group_desc_csum_set(sb, block_group, gdp); | 100 | ext4_group_desc_csum_set(sb, block_group, gdp); |
| 101 | 101 | ||
| 102 | return EXT4_INODES_PER_GROUP(sb); | 102 | return 0; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate) | 105 | void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate) |
| @@ -112,6 +112,42 @@ void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate) | |||
| 112 | put_bh(bh); | 112 | put_bh(bh); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | static int ext4_validate_inode_bitmap(struct super_block *sb, | ||
| 116 | struct ext4_group_desc *desc, | ||
| 117 | ext4_group_t block_group, | ||
| 118 | struct buffer_head *bh) | ||
| 119 | { | ||
| 120 | ext4_fsblk_t blk; | ||
| 121 | struct ext4_group_info *grp = ext4_get_group_info(sb, block_group); | ||
| 122 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 123 | |||
| 124 | if (buffer_verified(bh)) | ||
| 125 | return 0; | ||
| 126 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) | ||
| 127 | return -EFSCORRUPTED; | ||
| 128 | |||
| 129 | ext4_lock_group(sb, block_group); | ||
| 130 | blk = ext4_inode_bitmap(sb, desc); | ||
| 131 | if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh, | ||
| 132 | EXT4_INODES_PER_GROUP(sb) / 8)) { | ||
| 133 | ext4_unlock_group(sb, block_group); | ||
| 134 | ext4_error(sb, "Corrupt inode bitmap - block_group = %u, " | ||
| 135 | "inode_bitmap = %llu", block_group, blk); | ||
| 136 | grp = ext4_get_group_info(sb, block_group); | ||
| 137 | if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { | ||
| 138 | int count; | ||
| 139 | count = ext4_free_inodes_count(sb, desc); | ||
| 140 | percpu_counter_sub(&sbi->s_freeinodes_counter, | ||
| 141 | count); | ||
| 142 | } | ||
| 143 | set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); | ||
| 144 | return -EFSBADCRC; | ||
| 145 | } | ||
| 146 | set_buffer_verified(bh); | ||
| 147 | ext4_unlock_group(sb, block_group); | ||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 115 | /* | 151 | /* |
| 116 | * Read the inode allocation bitmap for a given block_group, reading | 152 | * Read the inode allocation bitmap for a given block_group, reading |
| 117 | * into the specified slot in the superblock's bitmap cache. | 153 | * into the specified slot in the superblock's bitmap cache. |
| @@ -124,12 +160,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
| 124 | struct ext4_group_desc *desc; | 160 | struct ext4_group_desc *desc; |
| 125 | struct buffer_head *bh = NULL; | 161 | struct buffer_head *bh = NULL; |
| 126 | ext4_fsblk_t bitmap_blk; | 162 | ext4_fsblk_t bitmap_blk; |
| 127 | struct ext4_group_info *grp; | 163 | int err; |
| 128 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 129 | 164 | ||
| 130 | desc = ext4_get_group_desc(sb, block_group, NULL); | 165 | desc = ext4_get_group_desc(sb, block_group, NULL); |
| 131 | if (!desc) | 166 | if (!desc) |
| 132 | return NULL; | 167 | return ERR_PTR(-EFSCORRUPTED); |
| 133 | 168 | ||
| 134 | bitmap_blk = ext4_inode_bitmap(sb, desc); | 169 | bitmap_blk = ext4_inode_bitmap(sb, desc); |
| 135 | bh = sb_getblk(sb, bitmap_blk); | 170 | bh = sb_getblk(sb, bitmap_blk); |
| @@ -137,7 +172,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
| 137 | ext4_error(sb, "Cannot read inode bitmap - " | 172 | ext4_error(sb, "Cannot read inode bitmap - " |
| 138 | "block_group = %u, inode_bitmap = %llu", | 173 | "block_group = %u, inode_bitmap = %llu", |
| 139 | block_group, bitmap_blk); | 174 | block_group, bitmap_blk); |
| 140 | return NULL; | 175 | return ERR_PTR(-EIO); |
| 141 | } | 176 | } |
| 142 | if (bitmap_uptodate(bh)) | 177 | if (bitmap_uptodate(bh)) |
| 143 | goto verify; | 178 | goto verify; |
| @@ -150,12 +185,14 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
| 150 | 185 | ||
| 151 | ext4_lock_group(sb, block_group); | 186 | ext4_lock_group(sb, block_group); |
| 152 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { | 187 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { |
| 153 | ext4_init_inode_bitmap(sb, bh, block_group, desc); | 188 | err = ext4_init_inode_bitmap(sb, bh, block_group, desc); |
| 154 | set_bitmap_uptodate(bh); | 189 | set_bitmap_uptodate(bh); |
| 155 | set_buffer_uptodate(bh); | 190 | set_buffer_uptodate(bh); |
| 156 | set_buffer_verified(bh); | 191 | set_buffer_verified(bh); |
| 157 | ext4_unlock_group(sb, block_group); | 192 | ext4_unlock_group(sb, block_group); |
| 158 | unlock_buffer(bh); | 193 | unlock_buffer(bh); |
| 194 | if (err) | ||
| 195 | goto out; | ||
| 159 | return bh; | 196 | return bh; |
| 160 | } | 197 | } |
| 161 | ext4_unlock_group(sb, block_group); | 198 | ext4_unlock_group(sb, block_group); |
| @@ -182,31 +219,17 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
| 182 | ext4_error(sb, "Cannot read inode bitmap - " | 219 | ext4_error(sb, "Cannot read inode bitmap - " |
| 183 | "block_group = %u, inode_bitmap = %llu", | 220 | "block_group = %u, inode_bitmap = %llu", |
| 184 | block_group, bitmap_blk); | 221 | block_group, bitmap_blk); |
| 185 | return NULL; | 222 | return ERR_PTR(-EIO); |
| 186 | } | 223 | } |
| 187 | 224 | ||
| 188 | verify: | 225 | verify: |
| 189 | ext4_lock_group(sb, block_group); | 226 | err = ext4_validate_inode_bitmap(sb, desc, block_group, bh); |
| 190 | if (!buffer_verified(bh) && | 227 | if (err) |
| 191 | !ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh, | 228 | goto out; |
| 192 | EXT4_INODES_PER_GROUP(sb) / 8)) { | ||
| 193 | ext4_unlock_group(sb, block_group); | ||
| 194 | put_bh(bh); | ||
| 195 | ext4_error(sb, "Corrupt inode bitmap - block_group = %u, " | ||
| 196 | "inode_bitmap = %llu", block_group, bitmap_blk); | ||
| 197 | grp = ext4_get_group_info(sb, block_group); | ||
| 198 | if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { | ||
| 199 | int count; | ||
| 200 | count = ext4_free_inodes_count(sb, desc); | ||
| 201 | percpu_counter_sub(&sbi->s_freeinodes_counter, | ||
| 202 | count); | ||
| 203 | } | ||
| 204 | set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); | ||
| 205 | return NULL; | ||
| 206 | } | ||
| 207 | ext4_unlock_group(sb, block_group); | ||
| 208 | set_buffer_verified(bh); | ||
| 209 | return bh; | 229 | return bh; |
| 230 | out: | ||
| 231 | put_bh(bh); | ||
| 232 | return ERR_PTR(err); | ||
| 210 | } | 233 | } |
| 211 | 234 | ||
| 212 | /* | 235 | /* |
| @@ -286,8 +309,15 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) | |||
| 286 | bitmap_bh = ext4_read_inode_bitmap(sb, block_group); | 309 | bitmap_bh = ext4_read_inode_bitmap(sb, block_group); |
| 287 | /* Don't bother if the inode bitmap is corrupt. */ | 310 | /* Don't bother if the inode bitmap is corrupt. */ |
| 288 | grp = ext4_get_group_info(sb, block_group); | 311 | grp = ext4_get_group_info(sb, block_group); |
| 289 | if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || !bitmap_bh) | 312 | if (IS_ERR(bitmap_bh)) { |
| 313 | fatal = PTR_ERR(bitmap_bh); | ||
| 314 | bitmap_bh = NULL; | ||
| 315 | goto error_return; | ||
| 316 | } | ||
| 317 | if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp))) { | ||
| 318 | fatal = -EFSCORRUPTED; | ||
| 290 | goto error_return; | 319 | goto error_return; |
| 320 | } | ||
| 291 | 321 | ||
| 292 | BUFFER_TRACE(bitmap_bh, "get_write_access"); | 322 | BUFFER_TRACE(bitmap_bh, "get_write_access"); |
| 293 | fatal = ext4_journal_get_write_access(handle, bitmap_bh); | 323 | fatal = ext4_journal_get_write_access(handle, bitmap_bh); |
| @@ -826,7 +856,9 @@ got_group: | |||
| 826 | brelse(inode_bitmap_bh); | 856 | brelse(inode_bitmap_bh); |
| 827 | inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); | 857 | inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); |
| 828 | /* Skip groups with suspicious inode tables */ | 858 | /* Skip groups with suspicious inode tables */ |
| 829 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || !inode_bitmap_bh) { | 859 | if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || |
| 860 | IS_ERR(inode_bitmap_bh)) { | ||
| 861 | inode_bitmap_bh = NULL; | ||
| 830 | if (++group == ngroups) | 862 | if (++group == ngroups) |
| 831 | group = 0; | 863 | group = 0; |
| 832 | continue; | 864 | continue; |
| @@ -902,8 +934,8 @@ got: | |||
| 902 | struct buffer_head *block_bitmap_bh; | 934 | struct buffer_head *block_bitmap_bh; |
| 903 | 935 | ||
| 904 | block_bitmap_bh = ext4_read_block_bitmap(sb, group); | 936 | block_bitmap_bh = ext4_read_block_bitmap(sb, group); |
| 905 | if (!block_bitmap_bh) { | 937 | if (IS_ERR(block_bitmap_bh)) { |
| 906 | err = -EIO; | 938 | err = PTR_ERR(block_bitmap_bh); |
| 907 | goto out; | 939 | goto out; |
| 908 | } | 940 | } |
| 909 | BUFFER_TRACE(block_bitmap_bh, "get block bitmap access"); | 941 | BUFFER_TRACE(block_bitmap_bh, "get block bitmap access"); |
| @@ -1045,7 +1077,7 @@ got: | |||
| 1045 | 1077 | ||
| 1046 | ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize; | 1078 | ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize; |
| 1047 | ei->i_inline_off = 0; | 1079 | ei->i_inline_off = 0; |
| 1048 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_INLINE_DATA)) | 1080 | if (ext4_has_feature_inline_data(sb)) |
| 1049 | ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); | 1081 | ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); |
| 1050 | ret = inode; | 1082 | ret = inode; |
| 1051 | err = dquot_alloc_inode(inode); | 1083 | err = dquot_alloc_inode(inode); |
| @@ -1060,7 +1092,7 @@ got: | |||
| 1060 | if (err) | 1092 | if (err) |
| 1061 | goto fail_free_drop; | 1093 | goto fail_free_drop; |
| 1062 | 1094 | ||
| 1063 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { | 1095 | if (ext4_has_feature_extents(sb)) { |
| 1064 | /* set extent flag only for directory, file and normal symlink*/ | 1096 | /* set extent flag only for directory, file and normal symlink*/ |
| 1065 | if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { | 1097 | if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { |
| 1066 | ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); | 1098 | ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); |
| @@ -1116,14 +1148,17 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) | |||
| 1116 | /* Error cases - e2fsck has already cleaned up for us */ | 1148 | /* Error cases - e2fsck has already cleaned up for us */ |
| 1117 | if (ino > max_ino) { | 1149 | if (ino > max_ino) { |
| 1118 | ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino); | 1150 | ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino); |
| 1151 | err = -EFSCORRUPTED; | ||
| 1119 | goto error; | 1152 | goto error; |
| 1120 | } | 1153 | } |
| 1121 | 1154 | ||
| 1122 | block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); | 1155 | block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); |
| 1123 | bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); | 1156 | bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); |
| 1124 | bitmap_bh = ext4_read_inode_bitmap(sb, block_group); | 1157 | bitmap_bh = ext4_read_inode_bitmap(sb, block_group); |
| 1125 | if (!bitmap_bh) { | 1158 | if (IS_ERR(bitmap_bh)) { |
| 1126 | ext4_warning(sb, "inode bitmap error for orphan %lu", ino); | 1159 | err = PTR_ERR(bitmap_bh); |
| 1160 | ext4_warning(sb, "inode bitmap error %ld for orphan %lu", | ||
| 1161 | ino, err); | ||
| 1127 | goto error; | 1162 | goto error; |
| 1128 | } | 1163 | } |
| 1129 | 1164 | ||
| @@ -1198,8 +1233,10 @@ unsigned long ext4_count_free_inodes(struct super_block *sb) | |||
| 1198 | desc_count += ext4_free_inodes_count(sb, gdp); | 1233 | desc_count += ext4_free_inodes_count(sb, gdp); |
| 1199 | brelse(bitmap_bh); | 1234 | brelse(bitmap_bh); |
| 1200 | bitmap_bh = ext4_read_inode_bitmap(sb, i); | 1235 | bitmap_bh = ext4_read_inode_bitmap(sb, i); |
| 1201 | if (!bitmap_bh) | 1236 | if (IS_ERR(bitmap_bh)) { |
| 1237 | bitmap_bh = NULL; | ||
| 1202 | continue; | 1238 | continue; |
| 1239 | } | ||
| 1203 | 1240 | ||
| 1204 | x = ext4_count_free(bitmap_bh->b_data, | 1241 | x = ext4_count_free(bitmap_bh->b_data, |
| 1205 | EXT4_INODES_PER_GROUP(sb) / 8); | 1242 | EXT4_INODES_PER_GROUP(sb) / 8); |
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 2468261748b2..355ef9c36c87 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
| @@ -562,11 +562,10 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, | |||
| 562 | /* | 562 | /* |
| 563 | * Okay, we need to do block allocation. | 563 | * Okay, we need to do block allocation. |
| 564 | */ | 564 | */ |
| 565 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 565 | if (ext4_has_feature_bigalloc(inode->i_sb)) { |
| 566 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
| 567 | EXT4_ERROR_INODE(inode, "Can't allocate blocks for " | 566 | EXT4_ERROR_INODE(inode, "Can't allocate blocks for " |
| 568 | "non-extent mapped inodes with bigalloc"); | 567 | "non-extent mapped inodes with bigalloc"); |
| 569 | return -EUCLEAN; | 568 | return -EFSCORRUPTED; |
| 570 | } | 569 | } |
| 571 | 570 | ||
| 572 | /* Set up for the direct block allocation */ | 571 | /* Set up for the direct block allocation */ |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index cd944a7a99cd..d884989cc83d 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
| @@ -434,8 +434,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle, | |||
| 434 | memset((void *)ext4_raw_inode(&is.iloc)->i_block, | 434 | memset((void *)ext4_raw_inode(&is.iloc)->i_block, |
| 435 | 0, EXT4_MIN_INLINE_DATA_SIZE); | 435 | 0, EXT4_MIN_INLINE_DATA_SIZE); |
| 436 | 436 | ||
| 437 | if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, | 437 | if (ext4_has_feature_extents(inode->i_sb)) { |
| 438 | EXT4_FEATURE_INCOMPAT_EXTENTS)) { | ||
| 439 | if (S_ISDIR(inode->i_mode) || | 438 | if (S_ISDIR(inode->i_mode) || |
| 440 | S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { | 439 | S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { |
| 441 | ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); | 440 | ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 612fbcf76b5c..e8d620a484f6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -378,7 +378,7 @@ static int __check_block_validity(struct inode *inode, const char *func, | |||
| 378 | "lblock %lu mapped to illegal pblock " | 378 | "lblock %lu mapped to illegal pblock " |
| 379 | "(length %d)", (unsigned long) map->m_lblk, | 379 | "(length %d)", (unsigned long) map->m_lblk, |
| 380 | map->m_len); | 380 | map->m_len); |
| 381 | return -EIO; | 381 | return -EFSCORRUPTED; |
| 382 | } | 382 | } |
| 383 | return 0; | 383 | return 0; |
| 384 | } | 384 | } |
| @@ -480,7 +480,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
| 480 | 480 | ||
| 481 | /* We can handle the block number less than EXT_MAX_BLOCKS */ | 481 | /* We can handle the block number less than EXT_MAX_BLOCKS */ |
| 482 | if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS)) | 482 | if (unlikely(map->m_lblk >= EXT_MAX_BLOCKS)) |
| 483 | return -EIO; | 483 | return -EFSCORRUPTED; |
| 484 | 484 | ||
| 485 | /* Lookup extent status tree firstly */ | 485 | /* Lookup extent status tree firstly */ |
| 486 | if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) { | 486 | if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) { |
| @@ -965,7 +965,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, | |||
| 965 | if (unlikely(err)) | 965 | if (unlikely(err)) |
| 966 | page_zero_new_buffers(page, from, to); | 966 | page_zero_new_buffers(page, from, to); |
| 967 | else if (decrypt) | 967 | else if (decrypt) |
| 968 | err = ext4_decrypt_one(inode, page); | 968 | err = ext4_decrypt(page); |
| 969 | return err; | 969 | return err; |
| 970 | } | 970 | } |
| 971 | #endif | 971 | #endif |
| @@ -1181,6 +1181,38 @@ errout: | |||
| 1181 | return ret ? ret : copied; | 1181 | return ret ? ret : copied; |
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | /* | ||
| 1185 | * This is a private version of page_zero_new_buffers() which doesn't | ||
| 1186 | * set the buffer to be dirty, since in data=journalled mode we need | ||
| 1187 | * to call ext4_handle_dirty_metadata() instead. | ||
| 1188 | */ | ||
| 1189 | static void zero_new_buffers(struct page *page, unsigned from, unsigned to) | ||
| 1190 | { | ||
| 1191 | unsigned int block_start = 0, block_end; | ||
| 1192 | struct buffer_head *head, *bh; | ||
| 1193 | |||
| 1194 | bh = head = page_buffers(page); | ||
| 1195 | do { | ||
| 1196 | block_end = block_start + bh->b_size; | ||
| 1197 | if (buffer_new(bh)) { | ||
| 1198 | if (block_end > from && block_start < to) { | ||
| 1199 | if (!PageUptodate(page)) { | ||
| 1200 | unsigned start, size; | ||
| 1201 | |||
| 1202 | start = max(from, block_start); | ||
| 1203 | size = min(to, block_end) - start; | ||
| 1204 | |||
| 1205 | zero_user(page, start, size); | ||
| 1206 | set_buffer_uptodate(bh); | ||
| 1207 | } | ||
| 1208 | clear_buffer_new(bh); | ||
| 1209 | } | ||
| 1210 | } | ||
| 1211 | block_start = block_end; | ||
| 1212 | bh = bh->b_this_page; | ||
| 1213 | } while (bh != head); | ||
| 1214 | } | ||
| 1215 | |||
| 1184 | static int ext4_journalled_write_end(struct file *file, | 1216 | static int ext4_journalled_write_end(struct file *file, |
| 1185 | struct address_space *mapping, | 1217 | struct address_space *mapping, |
| 1186 | loff_t pos, unsigned len, unsigned copied, | 1218 | loff_t pos, unsigned len, unsigned copied, |
| @@ -1207,7 +1239,7 @@ static int ext4_journalled_write_end(struct file *file, | |||
| 1207 | if (copied < len) { | 1239 | if (copied < len) { |
| 1208 | if (!PageUptodate(page)) | 1240 | if (!PageUptodate(page)) |
| 1209 | copied = 0; | 1241 | copied = 0; |
| 1210 | page_zero_new_buffers(page, from+copied, to); | 1242 | zero_new_buffers(page, from+copied, to); |
| 1211 | } | 1243 | } |
| 1212 | 1244 | ||
| 1213 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, | 1245 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, |
| @@ -1815,11 +1847,22 @@ static int ext4_writepage(struct page *page, | |||
| 1815 | * the page. But we may reach here when we do a journal commit via | 1847 | * the page. But we may reach here when we do a journal commit via |
| 1816 | * journal_submit_inode_data_buffers() and in that case we must write | 1848 | * journal_submit_inode_data_buffers() and in that case we must write |
| 1817 | * allocated buffers to achieve data=ordered mode guarantees. | 1849 | * allocated buffers to achieve data=ordered mode guarantees. |
| 1850 | * | ||
| 1851 | * Also, if there is only one buffer per page (the fs block | ||
| 1852 | * size == the page size), if one buffer needs block | ||
| 1853 | * allocation or needs to modify the extent tree to clear the | ||
| 1854 | * unwritten flag, we know that the page can't be written at | ||
| 1855 | * all, so we might as well refuse the write immediately. | ||
| 1856 | * Unfortunately if the block size != page size, we can't as | ||
| 1857 | * easily detect this case using ext4_walk_page_buffers(), but | ||
| 1858 | * for the extremely common case, this is an optimization that | ||
| 1859 | * skips a useless round trip through ext4_bio_write_page(). | ||
| 1818 | */ | 1860 | */ |
| 1819 | if (ext4_walk_page_buffers(NULL, page_bufs, 0, len, NULL, | 1861 | if (ext4_walk_page_buffers(NULL, page_bufs, 0, len, NULL, |
| 1820 | ext4_bh_delay_or_unwritten)) { | 1862 | ext4_bh_delay_or_unwritten)) { |
| 1821 | redirty_page_for_writepage(wbc, page); | 1863 | redirty_page_for_writepage(wbc, page); |
| 1822 | if (current->flags & PF_MEMALLOC) { | 1864 | if ((current->flags & PF_MEMALLOC) || |
| 1865 | (inode->i_sb->s_blocksize == PAGE_CACHE_SIZE)) { | ||
| 1823 | /* | 1866 | /* |
| 1824 | * For memory cleaning there's no point in writing only | 1867 | * For memory cleaning there's no point in writing only |
| 1825 | * some buffers. So just bail out. Warn if we came here | 1868 | * some buffers. So just bail out. Warn if we came here |
| @@ -2599,8 +2642,7 @@ static int ext4_nonda_switch(struct super_block *sb) | |||
| 2599 | /* We always reserve for an inode update; the superblock could be there too */ | 2642 | /* We always reserve for an inode update; the superblock could be there too */ |
| 2600 | static int ext4_da_write_credits(struct inode *inode, loff_t pos, unsigned len) | 2643 | static int ext4_da_write_credits(struct inode *inode, loff_t pos, unsigned len) |
| 2601 | { | 2644 | { |
| 2602 | if (likely(EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 2645 | if (likely(ext4_has_feature_large_file(inode->i_sb))) |
| 2603 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE))) | ||
| 2604 | return 1; | 2646 | return 1; |
| 2605 | 2647 | ||
| 2606 | if (pos + len <= 0x7fffffffULL) | 2648 | if (pos + len <= 0x7fffffffULL) |
| @@ -3393,7 +3435,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, | |||
| 3393 | /* We expect the key to be set. */ | 3435 | /* We expect the key to be set. */ |
| 3394 | BUG_ON(!ext4_has_encryption_key(inode)); | 3436 | BUG_ON(!ext4_has_encryption_key(inode)); |
| 3395 | BUG_ON(blocksize != PAGE_CACHE_SIZE); | 3437 | BUG_ON(blocksize != PAGE_CACHE_SIZE); |
| 3396 | WARN_ON_ONCE(ext4_decrypt_one(inode, page)); | 3438 | WARN_ON_ONCE(ext4_decrypt(page)); |
| 3397 | } | 3439 | } |
| 3398 | } | 3440 | } |
| 3399 | if (ext4_should_journal_data(inode)) { | 3441 | if (ext4_should_journal_data(inode)) { |
| @@ -3820,7 +3862,7 @@ static int __ext4_get_inode_loc(struct inode *inode, | |||
| 3820 | 3862 | ||
| 3821 | iloc->bh = NULL; | 3863 | iloc->bh = NULL; |
| 3822 | if (!ext4_valid_inum(sb, inode->i_ino)) | 3864 | if (!ext4_valid_inum(sb, inode->i_ino)) |
| 3823 | return -EIO; | 3865 | return -EFSCORRUPTED; |
| 3824 | 3866 | ||
| 3825 | iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); | 3867 | iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); |
| 3826 | gdp = ext4_get_group_desc(sb, iloc->block_group, NULL); | 3868 | gdp = ext4_get_group_desc(sb, iloc->block_group, NULL); |
| @@ -4006,8 +4048,7 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | |||
| 4006 | struct inode *inode = &(ei->vfs_inode); | 4048 | struct inode *inode = &(ei->vfs_inode); |
| 4007 | struct super_block *sb = inode->i_sb; | 4049 | struct super_block *sb = inode->i_sb; |
| 4008 | 4050 | ||
| 4009 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 4051 | if (ext4_has_feature_huge_file(sb)) { |
| 4010 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | ||
| 4011 | /* we are using combined 48 bit field */ | 4052 | /* we are using combined 48 bit field */ |
| 4012 | i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | | 4053 | i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | |
| 4013 | le32_to_cpu(raw_inode->i_blocks_lo); | 4054 | le32_to_cpu(raw_inode->i_blocks_lo); |
| @@ -4068,7 +4109,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 4068 | EXT4_ERROR_INODE(inode, "bad extra_isize (%u != %u)", | 4109 | EXT4_ERROR_INODE(inode, "bad extra_isize (%u != %u)", |
| 4069 | EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize, | 4110 | EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize, |
| 4070 | EXT4_INODE_SIZE(inode->i_sb)); | 4111 | EXT4_INODE_SIZE(inode->i_sb)); |
| 4071 | ret = -EIO; | 4112 | ret = -EFSCORRUPTED; |
| 4072 | goto bad_inode; | 4113 | goto bad_inode; |
| 4073 | } | 4114 | } |
| 4074 | } else | 4115 | } else |
| @@ -4088,7 +4129,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 4088 | 4129 | ||
| 4089 | if (!ext4_inode_csum_verify(inode, raw_inode, ei)) { | 4130 | if (!ext4_inode_csum_verify(inode, raw_inode, ei)) { |
| 4090 | EXT4_ERROR_INODE(inode, "checksum invalid"); | 4131 | EXT4_ERROR_INODE(inode, "checksum invalid"); |
| 4091 | ret = -EIO; | 4132 | ret = -EFSBADCRC; |
| 4092 | goto bad_inode; | 4133 | goto bad_inode; |
| 4093 | } | 4134 | } |
| 4094 | 4135 | ||
| @@ -4130,7 +4171,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 4130 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); | 4171 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); |
| 4131 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); | 4172 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); |
| 4132 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); | 4173 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); |
| 4133 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) | 4174 | if (ext4_has_feature_64bit(sb)) |
| 4134 | ei->i_file_acl |= | 4175 | ei->i_file_acl |= |
| 4135 | ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; | 4176 | ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; |
| 4136 | inode->i_size = ext4_isize(raw_inode); | 4177 | inode->i_size = ext4_isize(raw_inode); |
| @@ -4203,7 +4244,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 4203 | !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) { | 4244 | !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) { |
| 4204 | EXT4_ERROR_INODE(inode, "bad extended attribute block %llu", | 4245 | EXT4_ERROR_INODE(inode, "bad extended attribute block %llu", |
| 4205 | ei->i_file_acl); | 4246 | ei->i_file_acl); |
| 4206 | ret = -EIO; | 4247 | ret = -EFSCORRUPTED; |
| 4207 | goto bad_inode; | 4248 | goto bad_inode; |
| 4208 | } else if (!ext4_has_inline_data(inode)) { | 4249 | } else if (!ext4_has_inline_data(inode)) { |
| 4209 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { | 4250 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { |
| @@ -4254,7 +4295,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 4254 | } else if (ino == EXT4_BOOT_LOADER_INO) { | 4295 | } else if (ino == EXT4_BOOT_LOADER_INO) { |
| 4255 | make_bad_inode(inode); | 4296 | make_bad_inode(inode); |
| 4256 | } else { | 4297 | } else { |
| 4257 | ret = -EIO; | 4298 | ret = -EFSCORRUPTED; |
| 4258 | EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode); | 4299 | EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode); |
| 4259 | goto bad_inode; | 4300 | goto bad_inode; |
| 4260 | } | 4301 | } |
| @@ -4272,7 +4313,7 @@ bad_inode: | |||
| 4272 | struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino) | 4313 | struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino) |
| 4273 | { | 4314 | { |
| 4274 | if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) | 4315 | if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) |
| 4275 | return ERR_PTR(-EIO); | 4316 | return ERR_PTR(-EFSCORRUPTED); |
| 4276 | return ext4_iget(sb, ino); | 4317 | return ext4_iget(sb, ino); |
| 4277 | } | 4318 | } |
| 4278 | 4319 | ||
| @@ -4294,7 +4335,7 @@ static int ext4_inode_blocks_set(handle_t *handle, | |||
| 4294 | ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); | 4335 | ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE); |
| 4295 | return 0; | 4336 | return 0; |
| 4296 | } | 4337 | } |
| 4297 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) | 4338 | if (!ext4_has_feature_huge_file(sb)) |
| 4298 | return -EFBIG; | 4339 | return -EFBIG; |
| 4299 | 4340 | ||
| 4300 | if (i_blocks <= 0xffffffffffffULL) { | 4341 | if (i_blocks <= 0xffffffffffffULL) { |
| @@ -4455,8 +4496,7 @@ static int ext4_do_update_inode(handle_t *handle, | |||
| 4455 | need_datasync = 1; | 4496 | need_datasync = 1; |
| 4456 | } | 4497 | } |
| 4457 | if (ei->i_disksize > 0x7fffffffULL) { | 4498 | if (ei->i_disksize > 0x7fffffffULL) { |
| 4458 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | 4499 | if (!ext4_has_feature_large_file(sb) || |
| 4459 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE) || | ||
| 4460 | EXT4_SB(sb)->s_es->s_rev_level == | 4500 | EXT4_SB(sb)->s_es->s_rev_level == |
| 4461 | cpu_to_le32(EXT4_GOOD_OLD_REV)) | 4501 | cpu_to_le32(EXT4_GOOD_OLD_REV)) |
| 4462 | set_large_file = 1; | 4502 | set_large_file = 1; |
| @@ -4505,8 +4545,7 @@ static int ext4_do_update_inode(handle_t *handle, | |||
| 4505 | if (err) | 4545 | if (err) |
| 4506 | goto out_brelse; | 4546 | goto out_brelse; |
| 4507 | ext4_update_dynamic_rev(sb); | 4547 | ext4_update_dynamic_rev(sb); |
| 4508 | EXT4_SET_RO_COMPAT_FEATURE(sb, | 4548 | ext4_set_feature_large_file(sb); |
| 4509 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE); | ||
| 4510 | ext4_handle_sync(handle); | 4549 | ext4_handle_sync(handle); |
| 4511 | err = ext4_handle_dirty_super(handle, sb); | 4550 | err = ext4_handle_dirty_super(handle, sb); |
| 4512 | } | 4551 | } |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 1346cfa355d0..5e872fd40e5e 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -145,8 +145,7 @@ static long swap_inode_boot_loader(struct super_block *sb, | |||
| 145 | inode_bl->i_version = 1; | 145 | inode_bl->i_version = 1; |
| 146 | i_size_write(inode_bl, 0); | 146 | i_size_write(inode_bl, 0); |
| 147 | inode_bl->i_mode = S_IFREG; | 147 | inode_bl->i_mode = S_IFREG; |
| 148 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | 148 | if (ext4_has_feature_extents(sb)) { |
| 149 | EXT4_FEATURE_INCOMPAT_EXTENTS)) { | ||
| 150 | ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); | 149 | ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); |
| 151 | ext4_ext_tree_init(handle, inode_bl); | 150 | ext4_ext_tree_init(handle, inode_bl); |
| 152 | } else | 151 | } else |
| @@ -383,8 +382,7 @@ setversion_out: | |||
| 383 | goto group_extend_out; | 382 | goto group_extend_out; |
| 384 | } | 383 | } |
| 385 | 384 | ||
| 386 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 385 | if (ext4_has_feature_bigalloc(sb)) { |
| 387 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
| 388 | ext4_msg(sb, KERN_ERR, | 386 | ext4_msg(sb, KERN_ERR, |
| 389 | "Online resizing not supported with bigalloc"); | 387 | "Online resizing not supported with bigalloc"); |
| 390 | err = -EOPNOTSUPP; | 388 | err = -EOPNOTSUPP; |
| @@ -432,8 +430,7 @@ group_extend_out: | |||
| 432 | goto mext_out; | 430 | goto mext_out; |
| 433 | } | 431 | } |
| 434 | 432 | ||
| 435 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 433 | if (ext4_has_feature_bigalloc(sb)) { |
| 436 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
| 437 | ext4_msg(sb, KERN_ERR, | 434 | ext4_msg(sb, KERN_ERR, |
| 438 | "Online defrag not supported with bigalloc"); | 435 | "Online defrag not supported with bigalloc"); |
| 439 | err = -EOPNOTSUPP; | 436 | err = -EOPNOTSUPP; |
| @@ -470,8 +467,7 @@ mext_out: | |||
| 470 | goto group_add_out; | 467 | goto group_add_out; |
| 471 | } | 468 | } |
| 472 | 469 | ||
| 473 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 470 | if (ext4_has_feature_bigalloc(sb)) { |
| 474 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
| 475 | ext4_msg(sb, KERN_ERR, | 471 | ext4_msg(sb, KERN_ERR, |
| 476 | "Online resizing not supported with bigalloc"); | 472 | "Online resizing not supported with bigalloc"); |
| 477 | err = -EOPNOTSUPP; | 473 | err = -EOPNOTSUPP; |
| @@ -553,8 +549,7 @@ group_add_out: | |||
| 553 | int err = 0, err2 = 0; | 549 | int err = 0, err2 = 0; |
| 554 | ext4_group_t o_group = EXT4_SB(sb)->s_groups_count; | 550 | ext4_group_t o_group = EXT4_SB(sb)->s_groups_count; |
| 555 | 551 | ||
| 556 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 552 | if (ext4_has_feature_bigalloc(sb)) { |
| 557 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
| 558 | ext4_msg(sb, KERN_ERR, | 553 | ext4_msg(sb, KERN_ERR, |
| 559 | "Online resizing not (yet) supported with bigalloc"); | 554 | "Online resizing not (yet) supported with bigalloc"); |
| 560 | return -EOPNOTSUPP; | 555 | return -EOPNOTSUPP; |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 34b610ea5030..b4b3c1f91814 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -874,8 +874,10 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
| 874 | bh[i] = NULL; | 874 | bh[i] = NULL; |
| 875 | continue; | 875 | continue; |
| 876 | } | 876 | } |
| 877 | if (!(bh[i] = ext4_read_block_bitmap_nowait(sb, group))) { | 877 | bh[i] = ext4_read_block_bitmap_nowait(sb, group); |
| 878 | err = -ENOMEM; | 878 | if (IS_ERR(bh[i])) { |
| 879 | err = PTR_ERR(bh[i]); | ||
| 880 | bh[i] = NULL; | ||
| 879 | goto out; | 881 | goto out; |
| 880 | } | 882 | } |
| 881 | mb_debug(1, "read bitmap for group %u\n", group); | 883 | mb_debug(1, "read bitmap for group %u\n", group); |
| @@ -883,8 +885,13 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
| 883 | 885 | ||
| 884 | /* wait for I/O completion */ | 886 | /* wait for I/O completion */ |
| 885 | for (i = 0, group = first_group; i < groups_per_page; i++, group++) { | 887 | for (i = 0, group = first_group; i < groups_per_page; i++, group++) { |
| 886 | if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i])) | 888 | int err2; |
| 887 | err = -EIO; | 889 | |
| 890 | if (!bh[i]) | ||
| 891 | continue; | ||
| 892 | err2 = ext4_wait_block_bitmap(sb, group, bh[i]); | ||
| 893 | if (!err) | ||
| 894 | err = err2; | ||
| 888 | } | 895 | } |
| 889 | 896 | ||
| 890 | first_block = page->index * blocks_per_page; | 897 | first_block = page->index * blocks_per_page; |
| @@ -2333,7 +2340,7 @@ static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file) | |||
| 2333 | 2340 | ||
| 2334 | } | 2341 | } |
| 2335 | 2342 | ||
| 2336 | static const struct file_operations ext4_mb_seq_groups_fops = { | 2343 | const struct file_operations ext4_seq_mb_groups_fops = { |
| 2337 | .owner = THIS_MODULE, | 2344 | .owner = THIS_MODULE, |
| 2338 | .open = ext4_mb_seq_groups_open, | 2345 | .open = ext4_mb_seq_groups_open, |
| 2339 | .read = seq_read, | 2346 | .read = seq_read, |
| @@ -2447,7 +2454,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, | |||
| 2447 | kmalloc(sb->s_blocksize, GFP_NOFS); | 2454 | kmalloc(sb->s_blocksize, GFP_NOFS); |
| 2448 | BUG_ON(meta_group_info[i]->bb_bitmap == NULL); | 2455 | BUG_ON(meta_group_info[i]->bb_bitmap == NULL); |
| 2449 | bh = ext4_read_block_bitmap(sb, group); | 2456 | bh = ext4_read_block_bitmap(sb, group); |
| 2450 | BUG_ON(bh == NULL); | 2457 | BUG_ON(IS_ERR_OR_NULL(bh)); |
| 2451 | memcpy(meta_group_info[i]->bb_bitmap, bh->b_data, | 2458 | memcpy(meta_group_info[i]->bb_bitmap, bh->b_data, |
| 2452 | sb->s_blocksize); | 2459 | sb->s_blocksize); |
| 2453 | put_bh(bh); | 2460 | put_bh(bh); |
| @@ -2661,10 +2668,6 @@ int ext4_mb_init(struct super_block *sb) | |||
| 2661 | if (ret != 0) | 2668 | if (ret != 0) |
| 2662 | goto out_free_locality_groups; | 2669 | goto out_free_locality_groups; |
| 2663 | 2670 | ||
| 2664 | if (sbi->s_proc) | ||
| 2665 | proc_create_data("mb_groups", S_IRUGO, sbi->s_proc, | ||
| 2666 | &ext4_mb_seq_groups_fops, sb); | ||
| 2667 | |||
| 2668 | return 0; | 2671 | return 0; |
| 2669 | 2672 | ||
| 2670 | out_free_locality_groups: | 2673 | out_free_locality_groups: |
| @@ -2705,9 +2708,6 @@ int ext4_mb_release(struct super_block *sb) | |||
| 2705 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 2708 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 2706 | struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); | 2709 | struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); |
| 2707 | 2710 | ||
| 2708 | if (sbi->s_proc) | ||
| 2709 | remove_proc_entry("mb_groups", sbi->s_proc); | ||
| 2710 | |||
| 2711 | if (sbi->s_group_info) { | 2711 | if (sbi->s_group_info) { |
| 2712 | for (i = 0; i < ngroups; i++) { | 2712 | for (i = 0; i < ngroups; i++) { |
| 2713 | grinfo = ext4_get_group_info(sb, i); | 2713 | grinfo = ext4_get_group_info(sb, i); |
| @@ -2896,10 +2896,12 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
| 2896 | sb = ac->ac_sb; | 2896 | sb = ac->ac_sb; |
| 2897 | sbi = EXT4_SB(sb); | 2897 | sbi = EXT4_SB(sb); |
| 2898 | 2898 | ||
| 2899 | err = -EIO; | ||
| 2900 | bitmap_bh = ext4_read_block_bitmap(sb, ac->ac_b_ex.fe_group); | 2899 | bitmap_bh = ext4_read_block_bitmap(sb, ac->ac_b_ex.fe_group); |
| 2901 | if (!bitmap_bh) | 2900 | if (IS_ERR(bitmap_bh)) { |
| 2901 | err = PTR_ERR(bitmap_bh); | ||
| 2902 | bitmap_bh = NULL; | ||
| 2902 | goto out_err; | 2903 | goto out_err; |
| 2904 | } | ||
| 2903 | 2905 | ||
| 2904 | BUFFER_TRACE(bitmap_bh, "getting write access"); | 2906 | BUFFER_TRACE(bitmap_bh, "getting write access"); |
| 2905 | err = ext4_journal_get_write_access(handle, bitmap_bh); | 2907 | err = ext4_journal_get_write_access(handle, bitmap_bh); |
| @@ -3331,8 +3333,8 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block, | |||
| 3331 | atomic_inc(&pa->pa_count); | 3333 | atomic_inc(&pa->pa_count); |
| 3332 | return pa; | 3334 | return pa; |
| 3333 | } | 3335 | } |
| 3334 | cur_distance = abs(goal_block - cpa->pa_pstart); | 3336 | cur_distance = abs64(goal_block - cpa->pa_pstart); |
| 3335 | new_distance = abs(goal_block - pa->pa_pstart); | 3337 | new_distance = abs64(goal_block - pa->pa_pstart); |
| 3336 | 3338 | ||
| 3337 | if (cur_distance <= new_distance) | 3339 | if (cur_distance <= new_distance) |
| 3338 | return cpa; | 3340 | return cpa; |
| @@ -3843,8 +3845,10 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, | |||
| 3843 | return 0; | 3845 | return 0; |
| 3844 | 3846 | ||
| 3845 | bitmap_bh = ext4_read_block_bitmap(sb, group); | 3847 | bitmap_bh = ext4_read_block_bitmap(sb, group); |
| 3846 | if (bitmap_bh == NULL) { | 3848 | if (IS_ERR(bitmap_bh)) { |
| 3847 | ext4_error(sb, "Error reading block bitmap for %u", group); | 3849 | err = PTR_ERR(bitmap_bh); |
| 3850 | ext4_error(sb, "Error %d reading block bitmap for %u", | ||
| 3851 | err, group); | ||
| 3848 | return 0; | 3852 | return 0; |
| 3849 | } | 3853 | } |
| 3850 | 3854 | ||
| @@ -4015,9 +4019,10 @@ repeat: | |||
| 4015 | } | 4019 | } |
| 4016 | 4020 | ||
| 4017 | bitmap_bh = ext4_read_block_bitmap(sb, group); | 4021 | bitmap_bh = ext4_read_block_bitmap(sb, group); |
| 4018 | if (bitmap_bh == NULL) { | 4022 | if (IS_ERR(bitmap_bh)) { |
| 4019 | ext4_error(sb, "Error reading block bitmap for %u", | 4023 | err = PTR_ERR(bitmap_bh); |
| 4020 | group); | 4024 | ext4_error(sb, "Error %d reading block bitmap for %u", |
| 4025 | err, group); | ||
| 4021 | ext4_mb_unload_buddy(&e4b); | 4026 | ext4_mb_unload_buddy(&e4b); |
| 4022 | continue; | 4027 | continue; |
| 4023 | } | 4028 | } |
| @@ -4682,22 +4687,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
| 4682 | ext4_debug("freeing block %llu\n", block); | 4687 | ext4_debug("freeing block %llu\n", block); |
| 4683 | trace_ext4_free_blocks(inode, block, count, flags); | 4688 | trace_ext4_free_blocks(inode, block, count, flags); |
| 4684 | 4689 | ||
| 4685 | if (flags & EXT4_FREE_BLOCKS_FORGET) { | 4690 | if (bh && (flags & EXT4_FREE_BLOCKS_FORGET)) { |
| 4686 | struct buffer_head *tbh = bh; | 4691 | BUG_ON(count > 1); |
| 4687 | int i; | ||
| 4688 | |||
| 4689 | BUG_ON(bh && (count > 1)); | ||
| 4690 | 4692 | ||
| 4691 | for (i = 0; i < count; i++) { | 4693 | ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, |
| 4692 | cond_resched(); | 4694 | inode, bh, block); |
| 4693 | if (!bh) | ||
| 4694 | tbh = sb_find_get_block(inode->i_sb, | ||
| 4695 | block + i); | ||
| 4696 | if (!tbh) | ||
| 4697 | continue; | ||
| 4698 | ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, | ||
| 4699 | inode, tbh, block + i); | ||
| 4700 | } | ||
| 4701 | } | 4695 | } |
| 4702 | 4696 | ||
| 4703 | /* | 4697 | /* |
| @@ -4742,6 +4736,19 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
| 4742 | count += sbi->s_cluster_ratio - overflow; | 4736 | count += sbi->s_cluster_ratio - overflow; |
| 4743 | } | 4737 | } |
| 4744 | 4738 | ||
| 4739 | if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) { | ||
| 4740 | int i; | ||
| 4741 | |||
| 4742 | for (i = 0; i < count; i++) { | ||
| 4743 | cond_resched(); | ||
| 4744 | bh = sb_find_get_block(inode->i_sb, block + i); | ||
| 4745 | if (!bh) | ||
| 4746 | continue; | ||
| 4747 | ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, | ||
| 4748 | inode, bh, block + i); | ||
| 4749 | } | ||
| 4750 | } | ||
| 4751 | |||
| 4745 | do_more: | 4752 | do_more: |
| 4746 | overflow = 0; | 4753 | overflow = 0; |
| 4747 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); | 4754 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); |
| @@ -4761,8 +4768,9 @@ do_more: | |||
| 4761 | } | 4768 | } |
| 4762 | count_clusters = EXT4_NUM_B2C(sbi, count); | 4769 | count_clusters = EXT4_NUM_B2C(sbi, count); |
| 4763 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); | 4770 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); |
| 4764 | if (!bitmap_bh) { | 4771 | if (IS_ERR(bitmap_bh)) { |
| 4765 | err = -EIO; | 4772 | err = PTR_ERR(bitmap_bh); |
| 4773 | bitmap_bh = NULL; | ||
| 4766 | goto error_return; | 4774 | goto error_return; |
| 4767 | } | 4775 | } |
| 4768 | gdp = ext4_get_group_desc(sb, block_group, &gd_bh); | 4776 | gdp = ext4_get_group_desc(sb, block_group, &gd_bh); |
| @@ -4931,8 +4939,9 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, | |||
| 4931 | } | 4939 | } |
| 4932 | 4940 | ||
| 4933 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); | 4941 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); |
| 4934 | if (!bitmap_bh) { | 4942 | if (IS_ERR(bitmap_bh)) { |
| 4935 | err = -EIO; | 4943 | err = PTR_ERR(bitmap_bh); |
| 4944 | bitmap_bh = NULL; | ||
| 4936 | goto error_return; | 4945 | goto error_return; |
| 4937 | } | 4946 | } |
| 4938 | 4947 | ||
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index 6163ad21cb0e..a4651894cc33 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
| @@ -448,8 +448,7 @@ int ext4_ext_migrate(struct inode *inode) | |||
| 448 | * If the filesystem does not support extents, or the inode | 448 | * If the filesystem does not support extents, or the inode |
| 449 | * already is extent-based, error out. | 449 | * already is extent-based, error out. |
| 450 | */ | 450 | */ |
| 451 | if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, | 451 | if (!ext4_has_feature_extents(inode->i_sb) || |
| 452 | EXT4_FEATURE_INCOMPAT_EXTENTS) || | ||
| 453 | (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 452 | (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
| 454 | return -EINVAL; | 453 | return -EINVAL; |
| 455 | 454 | ||
| @@ -625,13 +624,11 @@ int ext4_ind_migrate(struct inode *inode) | |||
| 625 | handle_t *handle; | 624 | handle_t *handle; |
| 626 | int ret; | 625 | int ret; |
| 627 | 626 | ||
| 628 | if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, | 627 | if (!ext4_has_feature_extents(inode->i_sb) || |
| 629 | EXT4_FEATURE_INCOMPAT_EXTENTS) || | ||
| 630 | (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 628 | (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
| 631 | return -EINVAL; | 629 | return -EINVAL; |
| 632 | 630 | ||
| 633 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | 631 | if (ext4_has_feature_bigalloc(inode->i_sb)) |
| 634 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) | ||
| 635 | return -EOPNOTSUPP; | 632 | return -EOPNOTSUPP; |
| 636 | 633 | ||
| 637 | /* | 634 | /* |
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index 6eb1a619890c..0a512aa81bf7 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c | |||
| @@ -98,10 +98,12 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | mmp = (struct mmp_struct *)((*bh)->b_data); | 100 | mmp = (struct mmp_struct *)((*bh)->b_data); |
| 101 | if (le32_to_cpu(mmp->mmp_magic) == EXT4_MMP_MAGIC && | 101 | if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) |
| 102 | ext4_mmp_csum_verify(sb, mmp)) | 102 | ret = -EFSCORRUPTED; |
| 103 | else if (!ext4_mmp_csum_verify(sb, mmp)) | ||
| 104 | ret = -EFSBADCRC; | ||
| 105 | else | ||
| 103 | return 0; | 106 | return 0; |
| 104 | ret = -EINVAL; | ||
| 105 | 107 | ||
| 106 | warn_exit: | 108 | warn_exit: |
| 107 | ext4_warning(sb, "Error %d while reading MMP block %llu", | 109 | ext4_warning(sb, "Error %d while reading MMP block %llu", |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 9f61e7679a6d..19ce34525a59 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -109,7 +109,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, | |||
| 109 | if (!bh) { | 109 | if (!bh) { |
| 110 | ext4_error_inode(inode, func, line, block, | 110 | ext4_error_inode(inode, func, line, block, |
| 111 | "Directory hole found"); | 111 | "Directory hole found"); |
| 112 | return ERR_PTR(-EIO); | 112 | return ERR_PTR(-EFSCORRUPTED); |
| 113 | } | 113 | } |
| 114 | dirent = (struct ext4_dir_entry *) bh->b_data; | 114 | dirent = (struct ext4_dir_entry *) bh->b_data; |
| 115 | /* Determine whether or not we have an index block */ | 115 | /* Determine whether or not we have an index block */ |
| @@ -124,7 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, | |||
| 124 | if (!is_dx_block && type == INDEX) { | 124 | if (!is_dx_block && type == INDEX) { |
| 125 | ext4_error_inode(inode, func, line, block, | 125 | ext4_error_inode(inode, func, line, block, |
| 126 | "directory leaf block found instead of index block"); | 126 | "directory leaf block found instead of index block"); |
| 127 | return ERR_PTR(-EIO); | 127 | return ERR_PTR(-EFSCORRUPTED); |
| 128 | } | 128 | } |
| 129 | if (!ext4_has_metadata_csum(inode->i_sb) || | 129 | if (!ext4_has_metadata_csum(inode->i_sb) || |
| 130 | buffer_verified(bh)) | 130 | buffer_verified(bh)) |
| @@ -142,7 +142,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, | |||
| 142 | ext4_error_inode(inode, func, line, block, | 142 | ext4_error_inode(inode, func, line, block, |
| 143 | "Directory index failed checksum"); | 143 | "Directory index failed checksum"); |
| 144 | brelse(bh); | 144 | brelse(bh); |
| 145 | return ERR_PTR(-EIO); | 145 | return ERR_PTR(-EFSBADCRC); |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | if (!is_dx_block) { | 148 | if (!is_dx_block) { |
| @@ -152,7 +152,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, | |||
| 152 | ext4_error_inode(inode, func, line, block, | 152 | ext4_error_inode(inode, func, line, block, |
| 153 | "Directory block failed checksum"); | 153 | "Directory block failed checksum"); |
| 154 | brelse(bh); | 154 | brelse(bh); |
| 155 | return ERR_PTR(-EIO); | 155 | return ERR_PTR(-EFSBADCRC); |
| 156 | } | 156 | } |
| 157 | } | 157 | } |
| 158 | return bh; | 158 | return bh; |
| @@ -1570,19 +1570,19 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi | |||
| 1570 | brelse(bh); | 1570 | brelse(bh); |
| 1571 | if (!ext4_valid_inum(dir->i_sb, ino)) { | 1571 | if (!ext4_valid_inum(dir->i_sb, ino)) { |
| 1572 | EXT4_ERROR_INODE(dir, "bad inode number: %u", ino); | 1572 | EXT4_ERROR_INODE(dir, "bad inode number: %u", ino); |
| 1573 | return ERR_PTR(-EIO); | 1573 | return ERR_PTR(-EFSCORRUPTED); |
| 1574 | } | 1574 | } |
| 1575 | if (unlikely(ino == dir->i_ino)) { | 1575 | if (unlikely(ino == dir->i_ino)) { |
| 1576 | EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir", | 1576 | EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir", |
| 1577 | dentry); | 1577 | dentry); |
| 1578 | return ERR_PTR(-EIO); | 1578 | return ERR_PTR(-EFSCORRUPTED); |
| 1579 | } | 1579 | } |
| 1580 | inode = ext4_iget_normal(dir->i_sb, ino); | 1580 | inode = ext4_iget_normal(dir->i_sb, ino); |
| 1581 | if (inode == ERR_PTR(-ESTALE)) { | 1581 | if (inode == ERR_PTR(-ESTALE)) { |
| 1582 | EXT4_ERROR_INODE(dir, | 1582 | EXT4_ERROR_INODE(dir, |
| 1583 | "deleted inode referenced: %u", | 1583 | "deleted inode referenced: %u", |
| 1584 | ino); | 1584 | ino); |
| 1585 | return ERR_PTR(-EIO); | 1585 | return ERR_PTR(-EFSCORRUPTED); |
| 1586 | } | 1586 | } |
| 1587 | if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && | 1587 | if (!IS_ERR(inode) && ext4_encrypted_inode(dir) && |
| 1588 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 1588 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
| @@ -1619,7 +1619,7 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
| 1619 | if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) { | 1619 | if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) { |
| 1620 | EXT4_ERROR_INODE(d_inode(child), | 1620 | EXT4_ERROR_INODE(d_inode(child), |
| 1621 | "bad parent inode number: %u", ino); | 1621 | "bad parent inode number: %u", ino); |
| 1622 | return ERR_PTR(-EIO); | 1622 | return ERR_PTR(-EFSCORRUPTED); |
| 1623 | } | 1623 | } |
| 1624 | 1624 | ||
| 1625 | return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino)); | 1625 | return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino)); |
| @@ -1807,7 +1807,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode, | |||
| 1807 | while ((char *) de <= top) { | 1807 | while ((char *) de <= top) { |
| 1808 | if (ext4_check_dir_entry(dir, NULL, de, bh, | 1808 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
| 1809 | buf, buf_size, offset)) { | 1809 | buf, buf_size, offset)) { |
| 1810 | res = -EIO; | 1810 | res = -EFSCORRUPTED; |
| 1811 | goto return_result; | 1811 | goto return_result; |
| 1812 | } | 1812 | } |
| 1813 | /* Provide crypto context and crypto buffer to ext4 match */ | 1813 | /* Provide crypto context and crypto buffer to ext4 match */ |
| @@ -1967,7 +1967,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname, | |||
| 1967 | if ((char *) de >= (((char *) root) + blocksize)) { | 1967 | if ((char *) de >= (((char *) root) + blocksize)) { |
| 1968 | EXT4_ERROR_INODE(dir, "invalid rec_len for '..'"); | 1968 | EXT4_ERROR_INODE(dir, "invalid rec_len for '..'"); |
| 1969 | brelse(bh); | 1969 | brelse(bh); |
| 1970 | return -EIO; | 1970 | return -EFSCORRUPTED; |
| 1971 | } | 1971 | } |
| 1972 | len = ((char *) root) + (blocksize - csum_size) - (char *) de; | 1972 | len = ((char *) root) + (blocksize - csum_size) - (char *) de; |
| 1973 | 1973 | ||
| @@ -2118,7 +2118,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, | |||
| 2118 | goto out; | 2118 | goto out; |
| 2119 | 2119 | ||
| 2120 | if (blocks == 1 && !dx_fallback && | 2120 | if (blocks == 1 && !dx_fallback && |
| 2121 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { | 2121 | ext4_has_feature_dir_index(sb)) { |
| 2122 | retval = make_indexed_dir(handle, &fname, dentry, | 2122 | retval = make_indexed_dir(handle, &fname, dentry, |
| 2123 | inode, bh); | 2123 | inode, bh); |
| 2124 | bh = NULL; /* make_indexed_dir releases bh */ | 2124 | bh = NULL; /* make_indexed_dir releases bh */ |
| @@ -2315,7 +2315,7 @@ int ext4_generic_delete_entry(handle_t *handle, | |||
| 2315 | while (i < buf_size - csum_size) { | 2315 | while (i < buf_size - csum_size) { |
| 2316 | if (ext4_check_dir_entry(dir, NULL, de, bh, | 2316 | if (ext4_check_dir_entry(dir, NULL, de, bh, |
| 2317 | bh->b_data, bh->b_size, i)) | 2317 | bh->b_data, bh->b_size, i)) |
| 2318 | return -EIO; | 2318 | return -EFSCORRUPTED; |
| 2319 | if (de == de_del) { | 2319 | if (de == de_del) { |
| 2320 | if (pde) | 2320 | if (pde) |
| 2321 | pde->rec_len = ext4_rec_len_to_disk( | 2321 | pde->rec_len = ext4_rec_len_to_disk( |
| @@ -2388,8 +2388,7 @@ static void ext4_inc_count(handle_t *handle, struct inode *inode) | |||
| 2388 | /* limit is 16-bit i_links_count */ | 2388 | /* limit is 16-bit i_links_count */ |
| 2389 | if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) { | 2389 | if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) { |
| 2390 | set_nlink(inode, 1); | 2390 | set_nlink(inode, 1); |
| 2391 | EXT4_SET_RO_COMPAT_FEATURE(inode->i_sb, | 2391 | ext4_set_feature_dir_nlink(inode->i_sb); |
| 2392 | EXT4_FEATURE_RO_COMPAT_DIR_NLINK); | ||
| 2393 | } | 2392 | } |
| 2394 | } | 2393 | } |
| 2395 | } | 2394 | } |
| @@ -2469,9 +2468,6 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry, | |||
| 2469 | struct inode *inode; | 2468 | struct inode *inode; |
| 2470 | int err, credits, retries = 0; | 2469 | int err, credits, retries = 0; |
| 2471 | 2470 | ||
| 2472 | if (!new_valid_dev(rdev)) | ||
| 2473 | return -EINVAL; | ||
| 2474 | |||
| 2475 | err = dquot_initialize(dir); | 2471 | err = dquot_initialize(dir); |
| 2476 | if (err) | 2472 | if (err) |
| 2477 | return err; | 2473 | return err; |
| @@ -2934,7 +2930,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 2934 | 2930 | ||
| 2935 | inode = d_inode(dentry); | 2931 | inode = d_inode(dentry); |
| 2936 | 2932 | ||
| 2937 | retval = -EIO; | 2933 | retval = -EFSCORRUPTED; |
| 2938 | if (le32_to_cpu(de->inode) != inode->i_ino) | 2934 | if (le32_to_cpu(de->inode) != inode->i_ino) |
| 2939 | goto end_rmdir; | 2935 | goto end_rmdir; |
| 2940 | 2936 | ||
| @@ -3008,7 +3004,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) | |||
| 3008 | 3004 | ||
| 3009 | inode = d_inode(dentry); | 3005 | inode = d_inode(dentry); |
| 3010 | 3006 | ||
| 3011 | retval = -EIO; | 3007 | retval = -EFSCORRUPTED; |
| 3012 | if (le32_to_cpu(de->inode) != inode->i_ino) | 3008 | if (le32_to_cpu(de->inode) != inode->i_ino) |
| 3013 | goto end_unlink; | 3009 | goto end_unlink; |
| 3014 | 3010 | ||
| @@ -3310,7 +3306,7 @@ static int ext4_rename_dir_prepare(handle_t *handle, struct ext4_renament *ent) | |||
| 3310 | if (!ent->dir_bh) | 3306 | if (!ent->dir_bh) |
| 3311 | return retval; | 3307 | return retval; |
| 3312 | if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino) | 3308 | if (le32_to_cpu(ent->parent_de->inode) != ent->dir->i_ino) |
| 3313 | return -EIO; | 3309 | return -EFSCORRUPTED; |
| 3314 | BUFFER_TRACE(ent->dir_bh, "get_write_access"); | 3310 | BUFFER_TRACE(ent->dir_bh, "get_write_access"); |
| 3315 | return ext4_journal_get_write_access(handle, ent->dir_bh); | 3311 | return ext4_journal_get_write_access(handle, ent->dir_bh); |
| 3316 | } | 3312 | } |
| @@ -3352,8 +3348,7 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent, | |||
| 3352 | if (retval) | 3348 | if (retval) |
| 3353 | return retval; | 3349 | return retval; |
| 3354 | ent->de->inode = cpu_to_le32(ino); | 3350 | ent->de->inode = cpu_to_le32(ino); |
| 3355 | if (EXT4_HAS_INCOMPAT_FEATURE(ent->dir->i_sb, | 3351 | if (ext4_has_feature_filetype(ent->dir->i_sb)) |
| 3356 | EXT4_FEATURE_INCOMPAT_FILETYPE)) | ||
| 3357 | ent->de->file_type = file_type; | 3352 | ent->de->file_type = file_type; |
| 3358 | ent->dir->i_version++; | 3353 | ent->dir->i_version++; |
| 3359 | ent->dir->i_ctime = ent->dir->i_mtime = | 3354 | ent->dir->i_ctime = ent->dir->i_mtime = |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 84ba4d2b3a35..17fbe3882b8e 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
| @@ -425,6 +425,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
| 425 | struct buffer_head *bh, *head; | 425 | struct buffer_head *bh, *head; |
| 426 | int ret = 0; | 426 | int ret = 0; |
| 427 | int nr_submitted = 0; | 427 | int nr_submitted = 0; |
| 428 | int nr_to_submit = 0; | ||
| 428 | 429 | ||
| 429 | blocksize = 1 << inode->i_blkbits; | 430 | blocksize = 1 << inode->i_blkbits; |
| 430 | 431 | ||
| @@ -477,11 +478,13 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
| 477 | unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); | 478 | unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); |
| 478 | } | 479 | } |
| 479 | set_buffer_async_write(bh); | 480 | set_buffer_async_write(bh); |
| 481 | nr_to_submit++; | ||
| 480 | } while ((bh = bh->b_this_page) != head); | 482 | } while ((bh = bh->b_this_page) != head); |
| 481 | 483 | ||
| 482 | bh = head = page_buffers(page); | 484 | bh = head = page_buffers(page); |
| 483 | 485 | ||
| 484 | if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) { | 486 | if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) && |
| 487 | nr_to_submit) { | ||
| 485 | data_page = ext4_encrypt(inode, page); | 488 | data_page = ext4_encrypt(inode, page); |
| 486 | if (IS_ERR(data_page)) { | 489 | if (IS_ERR(data_page)) { |
| 487 | ret = PTR_ERR(data_page); | 490 | ret = PTR_ERR(data_page); |
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 560af0437704..d94af71a4e7f 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c | |||
| @@ -62,7 +62,7 @@ static void completion_pages(struct work_struct *work) | |||
| 62 | bio_for_each_segment_all(bv, bio, i) { | 62 | bio_for_each_segment_all(bv, bio, i) { |
| 63 | struct page *page = bv->bv_page; | 63 | struct page *page = bv->bv_page; |
| 64 | 64 | ||
| 65 | int ret = ext4_decrypt(ctx, page); | 65 | int ret = ext4_decrypt(page); |
| 66 | if (ret) { | 66 | if (ret) { |
| 67 | WARN_ON_ONCE(1); | 67 | WARN_ON_ONCE(1); |
| 68 | SetPageError(page); | 68 | SetPageError(page); |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index cf0c472047e3..ad62d7acc315 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -490,7 +490,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb, | |||
| 490 | group_data[0].group != sbi->s_groups_count); | 490 | group_data[0].group != sbi->s_groups_count); |
| 491 | 491 | ||
| 492 | reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks); | 492 | reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks); |
| 493 | meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); | 493 | meta_bg = ext4_has_feature_meta_bg(sb); |
| 494 | 494 | ||
| 495 | /* This transaction may be extended/restarted along the way */ | 495 | /* This transaction may be extended/restarted along the way */ |
| 496 | handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, EXT4_MAX_TRANS_DATA); | 496 | handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, EXT4_MAX_TRANS_DATA); |
| @@ -680,8 +680,7 @@ static unsigned ext4_list_backups(struct super_block *sb, unsigned *three, | |||
| 680 | int mult = 3; | 680 | int mult = 3; |
| 681 | unsigned ret; | 681 | unsigned ret; |
| 682 | 682 | ||
| 683 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | 683 | if (!ext4_has_feature_sparse_super(sb)) { |
| 684 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) { | ||
| 685 | ret = *min; | 684 | ret = *min; |
| 686 | *min += 1; | 685 | *min += 1; |
| 687 | return ret; | 686 | return ret; |
| @@ -1040,7 +1039,7 @@ exit_free: | |||
| 1040 | * do not copy the full number of backups at this time. The resize | 1039 | * do not copy the full number of backups at this time. The resize |
| 1041 | * which changed s_groups_count will backup again. | 1040 | * which changed s_groups_count will backup again. |
| 1042 | */ | 1041 | */ |
| 1043 | static void update_backups(struct super_block *sb, int blk_off, char *data, | 1042 | static void update_backups(struct super_block *sb, sector_t blk_off, char *data, |
| 1044 | int size, int meta_bg) | 1043 | int size, int meta_bg) |
| 1045 | { | 1044 | { |
| 1046 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 1045 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| @@ -1065,7 +1064,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data, | |||
| 1065 | group = ext4_list_backups(sb, &three, &five, &seven); | 1064 | group = ext4_list_backups(sb, &three, &five, &seven); |
| 1066 | last = sbi->s_groups_count; | 1065 | last = sbi->s_groups_count; |
| 1067 | } else { | 1066 | } else { |
| 1068 | group = ext4_meta_bg_first_group(sb, group) + 1; | 1067 | group = ext4_get_group_number(sb, blk_off) + 1; |
| 1069 | last = (ext4_group_t)(group + EXT4_DESC_PER_BLOCK(sb) - 2); | 1068 | last = (ext4_group_t)(group + EXT4_DESC_PER_BLOCK(sb) - 2); |
| 1070 | } | 1069 | } |
| 1071 | 1070 | ||
| @@ -1158,7 +1157,7 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb, | |||
| 1158 | int i, gdb_off, gdb_num, err = 0; | 1157 | int i, gdb_off, gdb_num, err = 0; |
| 1159 | int meta_bg; | 1158 | int meta_bg; |
| 1160 | 1159 | ||
| 1161 | meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); | 1160 | meta_bg = ext4_has_feature_meta_bg(sb); |
| 1162 | for (i = 0; i < count; i++, group++) { | 1161 | for (i = 0; i < count; i++, group++) { |
| 1163 | int reserved_gdb = ext4_bg_has_super(sb, group) ? | 1162 | int reserved_gdb = ext4_bg_has_super(sb, group) ? |
| 1164 | le16_to_cpu(es->s_reserved_gdt_blocks) : 0; | 1163 | le16_to_cpu(es->s_reserved_gdt_blocks) : 0; |
| @@ -1381,9 +1380,7 @@ static void ext4_update_super(struct super_block *sb, | |||
| 1381 | 1380 | ||
| 1382 | ext4_debug("free blocks count %llu", | 1381 | ext4_debug("free blocks count %llu", |
| 1383 | percpu_counter_read(&sbi->s_freeclusters_counter)); | 1382 | percpu_counter_read(&sbi->s_freeclusters_counter)); |
| 1384 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | 1383 | if (ext4_has_feature_flex_bg(sb) && sbi->s_log_groups_per_flex) { |
| 1385 | EXT4_FEATURE_INCOMPAT_FLEX_BG) && | ||
| 1386 | sbi->s_log_groups_per_flex) { | ||
| 1387 | ext4_group_t flex_group; | 1384 | ext4_group_t flex_group; |
| 1388 | flex_group = ext4_flex_group(sbi, group_data[0].group); | 1385 | flex_group = ext4_flex_group(sbi, group_data[0].group); |
| 1389 | atomic64_add(EXT4_NUM_B2C(sbi, free_blocks), | 1386 | atomic64_add(EXT4_NUM_B2C(sbi, free_blocks), |
| @@ -1476,8 +1473,7 @@ exit_journal: | |||
| 1476 | int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); | 1473 | int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); |
| 1477 | int gdb_num_end = ((group + flex_gd->count - 1) / | 1474 | int gdb_num_end = ((group + flex_gd->count - 1) / |
| 1478 | EXT4_DESC_PER_BLOCK(sb)); | 1475 | EXT4_DESC_PER_BLOCK(sb)); |
| 1479 | int meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, | 1476 | int meta_bg = ext4_has_feature_meta_bg(sb); |
| 1480 | EXT4_FEATURE_INCOMPAT_META_BG); | ||
| 1481 | sector_t old_gdb = 0; | 1477 | sector_t old_gdb = 0; |
| 1482 | 1478 | ||
| 1483 | update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, | 1479 | update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, |
| @@ -1585,8 +1581,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
| 1585 | 1581 | ||
| 1586 | gdb_off = input->group % EXT4_DESC_PER_BLOCK(sb); | 1582 | gdb_off = input->group % EXT4_DESC_PER_BLOCK(sb); |
| 1587 | 1583 | ||
| 1588 | if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb, | 1584 | if (gdb_off == 0 && !ext4_has_feature_sparse_super(sb)) { |
| 1589 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) { | ||
| 1590 | ext4_warning(sb, "Can't resize non-sparse filesystem further"); | 1585 | ext4_warning(sb, "Can't resize non-sparse filesystem further"); |
| 1591 | return -EPERM; | 1586 | return -EPERM; |
| 1592 | } | 1587 | } |
| @@ -1604,9 +1599,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
| 1604 | } | 1599 | } |
| 1605 | 1600 | ||
| 1606 | if (reserved_gdb || gdb_off == 0) { | 1601 | if (reserved_gdb || gdb_off == 0) { |
| 1607 | if (!EXT4_HAS_COMPAT_FEATURE(sb, | 1602 | if (ext4_has_feature_resize_inode(sb) || |
| 1608 | EXT4_FEATURE_COMPAT_RESIZE_INODE) | 1603 | !le16_to_cpu(es->s_reserved_gdt_blocks)) { |
| 1609 | || !le16_to_cpu(es->s_reserved_gdt_blocks)) { | ||
| 1610 | ext4_warning(sb, | 1604 | ext4_warning(sb, |
| 1611 | "No reserved GDT blocks, can't resize"); | 1605 | "No reserved GDT blocks, can't resize"); |
| 1612 | return -EPERM; | 1606 | return -EPERM; |
| @@ -1825,8 +1819,8 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode) | |||
| 1825 | if (err) | 1819 | if (err) |
| 1826 | goto errout; | 1820 | goto errout; |
| 1827 | 1821 | ||
| 1828 | EXT4_CLEAR_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE); | 1822 | ext4_clear_feature_resize_inode(sb); |
| 1829 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); | 1823 | ext4_set_feature_meta_bg(sb); |
| 1830 | sbi->s_es->s_first_meta_bg = | 1824 | sbi->s_es->s_first_meta_bg = |
| 1831 | cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count)); | 1825 | cpu_to_le32(num_desc_blocks(sb, sbi->s_groups_count)); |
| 1832 | 1826 | ||
| @@ -1918,9 +1912,9 @@ retry: | |||
| 1918 | n_desc_blocks = num_desc_blocks(sb, n_group + 1); | 1912 | n_desc_blocks = num_desc_blocks(sb, n_group + 1); |
| 1919 | o_desc_blocks = num_desc_blocks(sb, sbi->s_groups_count); | 1913 | o_desc_blocks = num_desc_blocks(sb, sbi->s_groups_count); |
| 1920 | 1914 | ||
| 1921 | meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG); | 1915 | meta_bg = ext4_has_feature_meta_bg(sb); |
| 1922 | 1916 | ||
| 1923 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) { | 1917 | if (ext4_has_feature_resize_inode(sb)) { |
| 1924 | if (meta_bg) { | 1918 | if (meta_bg) { |
| 1925 | ext4_error(sb, "resize_inode and meta_bg enabled " | 1919 | ext4_error(sb, "resize_inode and meta_bg enabled " |
| 1926 | "simultaneously"); | 1920 | "simultaneously"); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a63c7b0a10cf..04d0f1b33409 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/namei.h> | 34 | #include <linux/namei.h> |
| 35 | #include <linux/quotaops.h> | 35 | #include <linux/quotaops.h> |
| 36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
| 37 | #include <linux/proc_fs.h> | ||
| 38 | #include <linux/ctype.h> | 37 | #include <linux/ctype.h> |
| 39 | #include <linux/log2.h> | 38 | #include <linux/log2.h> |
| 40 | #include <linux/crc16.h> | 39 | #include <linux/crc16.h> |
| @@ -54,11 +53,8 @@ | |||
| 54 | #define CREATE_TRACE_POINTS | 53 | #define CREATE_TRACE_POINTS |
| 55 | #include <trace/events/ext4.h> | 54 | #include <trace/events/ext4.h> |
| 56 | 55 | ||
| 57 | static struct proc_dir_entry *ext4_proc_root; | ||
| 58 | static struct kset *ext4_kset; | ||
| 59 | static struct ext4_lazy_init *ext4_li_info; | 56 | static struct ext4_lazy_init *ext4_li_info; |
| 60 | static struct mutex ext4_li_mtx; | 57 | static struct mutex ext4_li_mtx; |
| 61 | static struct ext4_features *ext4_feat; | ||
| 62 | static int ext4_mballoc_ready; | 58 | static int ext4_mballoc_ready; |
| 63 | static struct ratelimit_state ext4_mount_msg_ratelimit; | 59 | static struct ratelimit_state ext4_mount_msg_ratelimit; |
| 64 | 60 | ||
| @@ -83,7 +79,6 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly); | |||
| 83 | static void ext4_destroy_lazyinit_thread(void); | 79 | static void ext4_destroy_lazyinit_thread(void); |
| 84 | static void ext4_unregister_li_request(struct super_block *sb); | 80 | static void ext4_unregister_li_request(struct super_block *sb); |
| 85 | static void ext4_clear_request_list(void); | 81 | static void ext4_clear_request_list(void); |
| 86 | static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t); | ||
| 87 | 82 | ||
| 88 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) | 83 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) |
| 89 | static struct file_system_type ext2_fs_type = { | 84 | static struct file_system_type ext2_fs_type = { |
| @@ -115,8 +110,7 @@ MODULE_ALIAS("ext3"); | |||
| 115 | static int ext4_verify_csum_type(struct super_block *sb, | 110 | static int ext4_verify_csum_type(struct super_block *sb, |
| 116 | struct ext4_super_block *es) | 111 | struct ext4_super_block *es) |
| 117 | { | 112 | { |
| 118 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | 113 | if (!ext4_has_feature_metadata_csum(sb)) |
| 119 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | ||
| 120 | return 1; | 114 | return 1; |
| 121 | 115 | ||
| 122 | return es->s_checksum_type == EXT4_CRC32C_CHKSUM; | 116 | return es->s_checksum_type == EXT4_CRC32C_CHKSUM; |
| @@ -394,9 +388,13 @@ static void ext4_handle_error(struct super_block *sb) | |||
| 394 | smp_wmb(); | 388 | smp_wmb(); |
| 395 | sb->s_flags |= MS_RDONLY; | 389 | sb->s_flags |= MS_RDONLY; |
| 396 | } | 390 | } |
| 397 | if (test_opt(sb, ERRORS_PANIC)) | 391 | if (test_opt(sb, ERRORS_PANIC)) { |
| 392 | if (EXT4_SB(sb)->s_journal && | ||
| 393 | !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) | ||
| 394 | return; | ||
| 398 | panic("EXT4-fs (device %s): panic forced after error\n", | 395 | panic("EXT4-fs (device %s): panic forced after error\n", |
| 399 | sb->s_id); | 396 | sb->s_id); |
| 397 | } | ||
| 400 | } | 398 | } |
| 401 | 399 | ||
| 402 | #define ext4_error_ratelimit(sb) \ | 400 | #define ext4_error_ratelimit(sb) \ |
| @@ -495,6 +493,12 @@ const char *ext4_decode_error(struct super_block *sb, int errno, | |||
| 495 | char *errstr = NULL; | 493 | char *errstr = NULL; |
| 496 | 494 | ||
| 497 | switch (errno) { | 495 | switch (errno) { |
| 496 | case -EFSCORRUPTED: | ||
| 497 | errstr = "Corrupt filesystem"; | ||
| 498 | break; | ||
| 499 | case -EFSBADCRC: | ||
| 500 | errstr = "Filesystem failed CRC"; | ||
| 501 | break; | ||
| 498 | case -EIO: | 502 | case -EIO: |
| 499 | errstr = "IO failure"; | 503 | errstr = "IO failure"; |
| 500 | break; | 504 | break; |
| @@ -585,8 +589,12 @@ void __ext4_abort(struct super_block *sb, const char *function, | |||
| 585 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); | 589 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); |
| 586 | save_error_info(sb, function, line); | 590 | save_error_info(sb, function, line); |
| 587 | } | 591 | } |
| 588 | if (test_opt(sb, ERRORS_PANIC)) | 592 | if (test_opt(sb, ERRORS_PANIC)) { |
| 593 | if (EXT4_SB(sb)->s_journal && | ||
| 594 | !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) | ||
| 595 | return; | ||
| 589 | panic("EXT4-fs panic from previous error\n"); | 596 | panic("EXT4-fs panic from previous error\n"); |
| 597 | } | ||
| 590 | } | 598 | } |
| 591 | 599 | ||
| 592 | void __ext4_msg(struct super_block *sb, | 600 | void __ext4_msg(struct super_block *sb, |
| @@ -800,6 +808,7 @@ static void ext4_put_super(struct super_block *sb) | |||
| 800 | ext4_abort(sb, "Couldn't clean up the journal"); | 808 | ext4_abort(sb, "Couldn't clean up the journal"); |
| 801 | } | 809 | } |
| 802 | 810 | ||
| 811 | ext4_unregister_sysfs(sb); | ||
| 803 | ext4_es_unregister_shrinker(sbi); | 812 | ext4_es_unregister_shrinker(sbi); |
| 804 | del_timer_sync(&sbi->s_err_report); | 813 | del_timer_sync(&sbi->s_err_report); |
| 805 | ext4_release_system_zone(sb); | 814 | ext4_release_system_zone(sb); |
| @@ -808,18 +817,12 @@ static void ext4_put_super(struct super_block *sb) | |||
| 808 | ext4_xattr_put_super(sb); | 817 | ext4_xattr_put_super(sb); |
| 809 | 818 | ||
| 810 | if (!(sb->s_flags & MS_RDONLY)) { | 819 | if (!(sb->s_flags & MS_RDONLY)) { |
| 811 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 820 | ext4_clear_feature_journal_needs_recovery(sb); |
| 812 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 821 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| 813 | } | 822 | } |
| 814 | if (!(sb->s_flags & MS_RDONLY)) | 823 | if (!(sb->s_flags & MS_RDONLY)) |
| 815 | ext4_commit_super(sb, 1); | 824 | ext4_commit_super(sb, 1); |
| 816 | 825 | ||
| 817 | if (sbi->s_proc) { | ||
| 818 | remove_proc_entry("options", sbi->s_proc); | ||
| 819 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
| 820 | } | ||
| 821 | kobject_del(&sbi->s_kobj); | ||
| 822 | |||
| 823 | for (i = 0; i < sbi->s_gdb_count; i++) | 826 | for (i = 0; i < sbi->s_gdb_count; i++) |
| 824 | brelse(sbi->s_group_desc[i]); | 827 | brelse(sbi->s_group_desc[i]); |
| 825 | kvfree(sbi->s_group_desc); | 828 | kvfree(sbi->s_group_desc); |
| @@ -1288,7 +1291,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) | |||
| 1288 | "quota options when quota turned on"); | 1291 | "quota options when quota turned on"); |
| 1289 | return -1; | 1292 | return -1; |
| 1290 | } | 1293 | } |
| 1291 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) { | 1294 | if (ext4_has_feature_quota(sb)) { |
| 1292 | ext4_msg(sb, KERN_ERR, "Cannot set journaled quota options " | 1295 | ext4_msg(sb, KERN_ERR, "Cannot set journaled quota options " |
| 1293 | "when QUOTA feature is enabled"); | 1296 | "when QUOTA feature is enabled"); |
| 1294 | return -1; | 1297 | return -1; |
| @@ -1381,10 +1384,10 @@ static const struct mount_opts { | |||
| 1381 | {Opt_nojournal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, | 1384 | {Opt_nojournal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, |
| 1382 | MOPT_EXT4_ONLY | MOPT_CLEAR}, | 1385 | MOPT_EXT4_ONLY | MOPT_CLEAR}, |
| 1383 | {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, | 1386 | {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, |
| 1384 | MOPT_EXT4_ONLY | MOPT_SET}, | 1387 | MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT}, |
| 1385 | {Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT | | 1388 | {Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT | |
| 1386 | EXT4_MOUNT_JOURNAL_CHECKSUM), | 1389 | EXT4_MOUNT_JOURNAL_CHECKSUM), |
| 1387 | MOPT_EXT4_ONLY | MOPT_SET}, | 1390 | MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT}, |
| 1388 | {Opt_noload, EXT4_MOUNT_NOLOAD, MOPT_NO_EXT2 | MOPT_SET}, | 1391 | {Opt_noload, EXT4_MOUNT_NOLOAD, MOPT_NO_EXT2 | MOPT_SET}, |
| 1389 | {Opt_err_panic, EXT4_MOUNT_ERRORS_PANIC, MOPT_SET | MOPT_CLEAR_ERR}, | 1392 | {Opt_err_panic, EXT4_MOUNT_ERRORS_PANIC, MOPT_SET | MOPT_CLEAR_ERR}, |
| 1390 | {Opt_err_ro, EXT4_MOUNT_ERRORS_RO, MOPT_SET | MOPT_CLEAR_ERR}, | 1393 | {Opt_err_ro, EXT4_MOUNT_ERRORS_RO, MOPT_SET | MOPT_CLEAR_ERR}, |
| @@ -1513,8 +1516,14 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
| 1513 | return -1; | 1516 | return -1; |
| 1514 | if (args->from && (m->flags & MOPT_GTE0) && (arg < 0)) | 1517 | if (args->from && (m->flags & MOPT_GTE0) && (arg < 0)) |
| 1515 | return -1; | 1518 | return -1; |
| 1516 | if (m->flags & MOPT_EXPLICIT) | 1519 | if (m->flags & MOPT_EXPLICIT) { |
| 1517 | set_opt2(sb, EXPLICIT_DELALLOC); | 1520 | if (m->mount_opt & EXT4_MOUNT_DELALLOC) { |
| 1521 | set_opt2(sb, EXPLICIT_DELALLOC); | ||
| 1522 | } else if (m->mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) { | ||
| 1523 | set_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM); | ||
| 1524 | } else | ||
| 1525 | return -1; | ||
| 1526 | } | ||
| 1518 | if (m->flags & MOPT_CLEAR_ERR) | 1527 | if (m->flags & MOPT_CLEAR_ERR) |
| 1519 | clear_opt(sb, ERRORS_MASK); | 1528 | clear_opt(sb, ERRORS_MASK); |
| 1520 | if (token == Opt_noquota && sb_any_quota_loaded(sb)) { | 1529 | if (token == Opt_noquota && sb_any_quota_loaded(sb)) { |
| @@ -1647,8 +1656,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
| 1647 | "quota options when quota turned on"); | 1656 | "quota options when quota turned on"); |
| 1648 | return -1; | 1657 | return -1; |
| 1649 | } | 1658 | } |
| 1650 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 1659 | if (ext4_has_feature_quota(sb)) { |
| 1651 | EXT4_FEATURE_RO_COMPAT_QUOTA)) { | ||
| 1652 | ext4_msg(sb, KERN_ERR, | 1660 | ext4_msg(sb, KERN_ERR, |
| 1653 | "Cannot set journaled quota options " | 1661 | "Cannot set journaled quota options " |
| 1654 | "when QUOTA feature is enabled"); | 1662 | "when QUOTA feature is enabled"); |
| @@ -1707,7 +1715,7 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1707 | return 0; | 1715 | return 0; |
| 1708 | } | 1716 | } |
| 1709 | #ifdef CONFIG_QUOTA | 1717 | #ifdef CONFIG_QUOTA |
| 1710 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && | 1718 | if (ext4_has_feature_quota(sb) && |
| 1711 | (test_opt(sb, USRQUOTA) || test_opt(sb, GRPQUOTA))) { | 1719 | (test_opt(sb, USRQUOTA) || test_opt(sb, GRPQUOTA))) { |
| 1712 | ext4_msg(sb, KERN_ERR, "Cannot set quota options when QUOTA " | 1720 | ext4_msg(sb, KERN_ERR, "Cannot set quota options when QUOTA " |
| 1713 | "feature is enabled"); | 1721 | "feature is enabled"); |
| @@ -1880,7 +1888,7 @@ static int ext4_show_options(struct seq_file *seq, struct dentry *root) | |||
| 1880 | return _ext4_show_options(seq, root->d_sb, 0); | 1888 | return _ext4_show_options(seq, root->d_sb, 0); |
| 1881 | } | 1889 | } |
| 1882 | 1890 | ||
| 1883 | static int options_seq_show(struct seq_file *seq, void *offset) | 1891 | int ext4_seq_options_show(struct seq_file *seq, void *offset) |
| 1884 | { | 1892 | { |
| 1885 | struct super_block *sb = seq->private; | 1893 | struct super_block *sb = seq->private; |
| 1886 | int rc; | 1894 | int rc; |
| @@ -1891,19 +1899,6 @@ static int options_seq_show(struct seq_file *seq, void *offset) | |||
| 1891 | return rc; | 1899 | return rc; |
| 1892 | } | 1900 | } |
| 1893 | 1901 | ||
| 1894 | static int options_open_fs(struct inode *inode, struct file *file) | ||
| 1895 | { | ||
| 1896 | return single_open(file, options_seq_show, PDE_DATA(inode)); | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | static const struct file_operations ext4_seq_options_fops = { | ||
| 1900 | .owner = THIS_MODULE, | ||
| 1901 | .open = options_open_fs, | ||
| 1902 | .read = seq_read, | ||
| 1903 | .llseek = seq_lseek, | ||
| 1904 | .release = single_release, | ||
| 1905 | }; | ||
| 1906 | |||
| 1907 | static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | 1902 | static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, |
| 1908 | int read_only) | 1903 | int read_only) |
| 1909 | { | 1904 | { |
| @@ -1944,7 +1939,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | |||
| 1944 | es->s_mtime = cpu_to_le32(get_seconds()); | 1939 | es->s_mtime = cpu_to_le32(get_seconds()); |
| 1945 | ext4_update_dynamic_rev(sb); | 1940 | ext4_update_dynamic_rev(sb); |
| 1946 | if (sbi->s_journal) | 1941 | if (sbi->s_journal) |
| 1947 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 1942 | ext4_set_feature_journal_needs_recovery(sb); |
| 1948 | 1943 | ||
| 1949 | ext4_commit_super(sb, 1); | 1944 | ext4_commit_super(sb, 1); |
| 1950 | done: | 1945 | done: |
| @@ -2027,12 +2022,13 @@ failed: | |||
| 2027 | return 0; | 2022 | return 0; |
| 2028 | } | 2023 | } |
| 2029 | 2024 | ||
| 2030 | static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, | 2025 | static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group, |
| 2031 | struct ext4_group_desc *gdp) | 2026 | struct ext4_group_desc *gdp) |
| 2032 | { | 2027 | { |
| 2033 | int offset; | 2028 | int offset; |
| 2034 | __u16 crc = 0; | 2029 | __u16 crc = 0; |
| 2035 | __le32 le_group = cpu_to_le32(block_group); | 2030 | __le32 le_group = cpu_to_le32(block_group); |
| 2031 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 2036 | 2032 | ||
| 2037 | if (ext4_has_metadata_csum(sbi->s_sb)) { | 2033 | if (ext4_has_metadata_csum(sbi->s_sb)) { |
| 2038 | /* Use new metadata_csum algorithm */ | 2034 | /* Use new metadata_csum algorithm */ |
| @@ -2052,8 +2048,7 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, | |||
| 2052 | } | 2048 | } |
| 2053 | 2049 | ||
| 2054 | /* old crc16 code */ | 2050 | /* old crc16 code */ |
| 2055 | if (!(sbi->s_es->s_feature_ro_compat & | 2051 | if (!ext4_has_feature_gdt_csum(sb)) |
| 2056 | cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) | ||
| 2057 | return 0; | 2052 | return 0; |
| 2058 | 2053 | ||
| 2059 | offset = offsetof(struct ext4_group_desc, bg_checksum); | 2054 | offset = offsetof(struct ext4_group_desc, bg_checksum); |
| @@ -2063,8 +2058,7 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, | |||
| 2063 | crc = crc16(crc, (__u8 *)gdp, offset); | 2058 | crc = crc16(crc, (__u8 *)gdp, offset); |
| 2064 | offset += sizeof(gdp->bg_checksum); /* skip checksum */ | 2059 | offset += sizeof(gdp->bg_checksum); /* skip checksum */ |
| 2065 | /* for checksum of struct ext4_group_desc do the rest...*/ | 2060 | /* for checksum of struct ext4_group_desc do the rest...*/ |
| 2066 | if ((sbi->s_es->s_feature_incompat & | 2061 | if (ext4_has_feature_64bit(sb) && |
| 2067 | cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) && | ||
| 2068 | offset < le16_to_cpu(sbi->s_es->s_desc_size)) | 2062 | offset < le16_to_cpu(sbi->s_es->s_desc_size)) |
| 2069 | crc = crc16(crc, (__u8 *)gdp + offset, | 2063 | crc = crc16(crc, (__u8 *)gdp + offset, |
| 2070 | le16_to_cpu(sbi->s_es->s_desc_size) - | 2064 | le16_to_cpu(sbi->s_es->s_desc_size) - |
| @@ -2078,8 +2072,7 @@ int ext4_group_desc_csum_verify(struct super_block *sb, __u32 block_group, | |||
| 2078 | struct ext4_group_desc *gdp) | 2072 | struct ext4_group_desc *gdp) |
| 2079 | { | 2073 | { |
| 2080 | if (ext4_has_group_desc_csum(sb) && | 2074 | if (ext4_has_group_desc_csum(sb) && |
| 2081 | (gdp->bg_checksum != ext4_group_desc_csum(EXT4_SB(sb), | 2075 | (gdp->bg_checksum != ext4_group_desc_csum(sb, block_group, gdp))) |
| 2082 | block_group, gdp))) | ||
| 2083 | return 0; | 2076 | return 0; |
| 2084 | 2077 | ||
| 2085 | return 1; | 2078 | return 1; |
| @@ -2090,7 +2083,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group, | |||
| 2090 | { | 2083 | { |
| 2091 | if (!ext4_has_group_desc_csum(sb)) | 2084 | if (!ext4_has_group_desc_csum(sb)) |
| 2092 | return; | 2085 | return; |
| 2093 | gdp->bg_checksum = ext4_group_desc_csum(EXT4_SB(sb), block_group, gdp); | 2086 | gdp->bg_checksum = ext4_group_desc_csum(sb, block_group, gdp); |
| 2094 | } | 2087 | } |
| 2095 | 2088 | ||
| 2096 | /* Called at mount-time, super-block is locked */ | 2089 | /* Called at mount-time, super-block is locked */ |
| @@ -2106,7 +2099,7 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
| 2106 | int flexbg_flag = 0; | 2099 | int flexbg_flag = 0; |
| 2107 | ext4_group_t i, grp = sbi->s_groups_count; | 2100 | ext4_group_t i, grp = sbi->s_groups_count; |
| 2108 | 2101 | ||
| 2109 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 2102 | if (ext4_has_feature_flex_bg(sb)) |
| 2110 | flexbg_flag = 1; | 2103 | flexbg_flag = 1; |
| 2111 | 2104 | ||
| 2112 | ext4_debug("Checking group descriptors"); | 2105 | ext4_debug("Checking group descriptors"); |
| @@ -2150,7 +2143,7 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
| 2150 | if (!ext4_group_desc_csum_verify(sb, i, gdp)) { | 2143 | if (!ext4_group_desc_csum_verify(sb, i, gdp)) { |
| 2151 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | 2144 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " |
| 2152 | "Checksum for group %u failed (%u!=%u)", | 2145 | "Checksum for group %u failed (%u!=%u)", |
| 2153 | i, le16_to_cpu(ext4_group_desc_csum(sbi, i, | 2146 | i, le16_to_cpu(ext4_group_desc_csum(sb, i, |
| 2154 | gdp)), le16_to_cpu(gdp->bg_checksum)); | 2147 | gdp)), le16_to_cpu(gdp->bg_checksum)); |
| 2155 | if (!(sb->s_flags & MS_RDONLY)) { | 2148 | if (!(sb->s_flags & MS_RDONLY)) { |
| 2156 | ext4_unlock_group(sb, i); | 2149 | ext4_unlock_group(sb, i); |
| @@ -2413,8 +2406,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb, | |||
| 2413 | 2406 | ||
| 2414 | first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); | 2407 | first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); |
| 2415 | 2408 | ||
| 2416 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) || | 2409 | if (!ext4_has_feature_meta_bg(sb) || nr < first_meta_bg) |
| 2417 | nr < first_meta_bg) | ||
| 2418 | return logical_sb_block + nr + 1; | 2410 | return logical_sb_block + nr + 1; |
| 2419 | bg = sbi->s_desc_per_block * nr; | 2411 | bg = sbi->s_desc_per_block * nr; |
| 2420 | if (ext4_bg_has_super(sb, bg)) | 2412 | if (ext4_bg_has_super(sb, bg)) |
| @@ -2470,335 +2462,6 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi) | |||
| 2470 | return ret; | 2462 | return ret; |
| 2471 | } | 2463 | } |
| 2472 | 2464 | ||
| 2473 | /* sysfs supprt */ | ||
| 2474 | |||
| 2475 | struct ext4_attr { | ||
| 2476 | struct attribute attr; | ||
| 2477 | ssize_t (*show)(struct ext4_attr *, struct ext4_sb_info *, char *); | ||
| 2478 | ssize_t (*store)(struct ext4_attr *, struct ext4_sb_info *, | ||
| 2479 | const char *, size_t); | ||
| 2480 | union { | ||
| 2481 | int offset; | ||
| 2482 | int deprecated_val; | ||
| 2483 | } u; | ||
| 2484 | }; | ||
| 2485 | |||
| 2486 | static int parse_strtoull(const char *buf, | ||
| 2487 | unsigned long long max, unsigned long long *value) | ||
| 2488 | { | ||
| 2489 | int ret; | ||
| 2490 | |||
| 2491 | ret = kstrtoull(skip_spaces(buf), 0, value); | ||
| 2492 | if (!ret && *value > max) | ||
| 2493 | ret = -EINVAL; | ||
| 2494 | return ret; | ||
| 2495 | } | ||
| 2496 | |||
| 2497 | static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a, | ||
| 2498 | struct ext4_sb_info *sbi, | ||
| 2499 | char *buf) | ||
| 2500 | { | ||
| 2501 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 2502 | (s64) EXT4_C2B(sbi, | ||
| 2503 | percpu_counter_sum(&sbi->s_dirtyclusters_counter))); | ||
| 2504 | } | ||
| 2505 | |||
| 2506 | static ssize_t session_write_kbytes_show(struct ext4_attr *a, | ||
| 2507 | struct ext4_sb_info *sbi, char *buf) | ||
| 2508 | { | ||
| 2509 | struct super_block *sb = sbi->s_buddy_cache->i_sb; | ||
| 2510 | |||
| 2511 | if (!sb->s_bdev->bd_part) | ||
| 2512 | return snprintf(buf, PAGE_SIZE, "0\n"); | ||
| 2513 | return snprintf(buf, PAGE_SIZE, "%lu\n", | ||
| 2514 | (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | ||
| 2515 | sbi->s_sectors_written_start) >> 1); | ||
| 2516 | } | ||
| 2517 | |||
| 2518 | static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, | ||
| 2519 | struct ext4_sb_info *sbi, char *buf) | ||
| 2520 | { | ||
| 2521 | struct super_block *sb = sbi->s_buddy_cache->i_sb; | ||
| 2522 | |||
| 2523 | if (!sb->s_bdev->bd_part) | ||
| 2524 | return snprintf(buf, PAGE_SIZE, "0\n"); | ||
| 2525 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 2526 | (unsigned long long)(sbi->s_kbytes_written + | ||
| 2527 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | ||
| 2528 | EXT4_SB(sb)->s_sectors_written_start) >> 1))); | ||
| 2529 | } | ||
| 2530 | |||
| 2531 | static ssize_t inode_readahead_blks_store(struct ext4_attr *a, | ||
| 2532 | struct ext4_sb_info *sbi, | ||
| 2533 | const char *buf, size_t count) | ||
| 2534 | { | ||
| 2535 | unsigned long t; | ||
| 2536 | int ret; | ||
| 2537 | |||
| 2538 | ret = kstrtoul(skip_spaces(buf), 0, &t); | ||
| 2539 | if (ret) | ||
| 2540 | return ret; | ||
| 2541 | |||
| 2542 | if (t && (!is_power_of_2(t) || t > 0x40000000)) | ||
| 2543 | return -EINVAL; | ||
| 2544 | |||
| 2545 | sbi->s_inode_readahead_blks = t; | ||
| 2546 | return count; | ||
| 2547 | } | ||
| 2548 | |||
| 2549 | static ssize_t sbi_ui_show(struct ext4_attr *a, | ||
| 2550 | struct ext4_sb_info *sbi, char *buf) | ||
| 2551 | { | ||
| 2552 | unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); | ||
| 2553 | |||
| 2554 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); | ||
| 2555 | } | ||
| 2556 | |||
| 2557 | static ssize_t sbi_ui_store(struct ext4_attr *a, | ||
| 2558 | struct ext4_sb_info *sbi, | ||
| 2559 | const char *buf, size_t count) | ||
| 2560 | { | ||
| 2561 | unsigned int *ui = (unsigned int *) (((char *) sbi) + a->u.offset); | ||
| 2562 | unsigned long t; | ||
| 2563 | int ret; | ||
| 2564 | |||
| 2565 | ret = kstrtoul(skip_spaces(buf), 0, &t); | ||
| 2566 | if (ret) | ||
| 2567 | return ret; | ||
| 2568 | *ui = t; | ||
| 2569 | return count; | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | static ssize_t es_ui_show(struct ext4_attr *a, | ||
| 2573 | struct ext4_sb_info *sbi, char *buf) | ||
| 2574 | { | ||
| 2575 | |||
| 2576 | unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) + | ||
| 2577 | a->u.offset); | ||
| 2578 | |||
| 2579 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | static ssize_t reserved_clusters_show(struct ext4_attr *a, | ||
| 2583 | struct ext4_sb_info *sbi, char *buf) | ||
| 2584 | { | ||
| 2585 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 2586 | (unsigned long long) atomic64_read(&sbi->s_resv_clusters)); | ||
| 2587 | } | ||
| 2588 | |||
| 2589 | static ssize_t reserved_clusters_store(struct ext4_attr *a, | ||
| 2590 | struct ext4_sb_info *sbi, | ||
| 2591 | const char *buf, size_t count) | ||
| 2592 | { | ||
| 2593 | unsigned long long val; | ||
| 2594 | int ret; | ||
| 2595 | |||
| 2596 | if (parse_strtoull(buf, -1ULL, &val)) | ||
| 2597 | return -EINVAL; | ||
| 2598 | ret = ext4_reserve_clusters(sbi, val); | ||
| 2599 | |||
| 2600 | return ret ? ret : count; | ||
| 2601 | } | ||
| 2602 | |||
| 2603 | static ssize_t trigger_test_error(struct ext4_attr *a, | ||
| 2604 | struct ext4_sb_info *sbi, | ||
| 2605 | const char *buf, size_t count) | ||
| 2606 | { | ||
| 2607 | int len = count; | ||
| 2608 | |||
| 2609 | if (!capable(CAP_SYS_ADMIN)) | ||
| 2610 | return -EPERM; | ||
| 2611 | |||
| 2612 | if (len && buf[len-1] == '\n') | ||
| 2613 | len--; | ||
| 2614 | |||
| 2615 | if (len) | ||
| 2616 | ext4_error(sbi->s_sb, "%.*s", len, buf); | ||
| 2617 | return count; | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | static ssize_t sbi_deprecated_show(struct ext4_attr *a, | ||
| 2621 | struct ext4_sb_info *sbi, char *buf) | ||
| 2622 | { | ||
| 2623 | return snprintf(buf, PAGE_SIZE, "%d\n", a->u.deprecated_val); | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | #define EXT4_ATTR_OFFSET(_name,_mode,_show,_store,_elname) \ | ||
| 2627 | static struct ext4_attr ext4_attr_##_name = { \ | ||
| 2628 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 2629 | .show = _show, \ | ||
| 2630 | .store = _store, \ | ||
| 2631 | .u = { \ | ||
| 2632 | .offset = offsetof(struct ext4_sb_info, _elname),\ | ||
| 2633 | }, \ | ||
| 2634 | } | ||
| 2635 | |||
| 2636 | #define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname) \ | ||
| 2637 | static struct ext4_attr ext4_attr_##_name = { \ | ||
| 2638 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 2639 | .show = _show, \ | ||
| 2640 | .store = _store, \ | ||
| 2641 | .u = { \ | ||
| 2642 | .offset = offsetof(struct ext4_super_block, _elname), \ | ||
| 2643 | }, \ | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | #define EXT4_ATTR(name, mode, show, store) \ | ||
| 2647 | static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) | ||
| 2648 | |||
| 2649 | #define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL) | ||
| 2650 | #define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL) | ||
| 2651 | #define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store) | ||
| 2652 | |||
| 2653 | #define EXT4_RO_ATTR_ES_UI(name, elname) \ | ||
| 2654 | EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname) | ||
| 2655 | #define EXT4_RW_ATTR_SBI_UI(name, elname) \ | ||
| 2656 | EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname) | ||
| 2657 | |||
| 2658 | #define ATTR_LIST(name) &ext4_attr_##name.attr | ||
| 2659 | #define EXT4_DEPRECATED_ATTR(_name, _val) \ | ||
| 2660 | static struct ext4_attr ext4_attr_##_name = { \ | ||
| 2661 | .attr = {.name = __stringify(_name), .mode = 0444 }, \ | ||
| 2662 | .show = sbi_deprecated_show, \ | ||
| 2663 | .u = { \ | ||
| 2664 | .deprecated_val = _val, \ | ||
| 2665 | }, \ | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | EXT4_RO_ATTR(delayed_allocation_blocks); | ||
| 2669 | EXT4_RO_ATTR(session_write_kbytes); | ||
| 2670 | EXT4_RO_ATTR(lifetime_write_kbytes); | ||
| 2671 | EXT4_RW_ATTR(reserved_clusters); | ||
| 2672 | EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, | ||
| 2673 | inode_readahead_blks_store, s_inode_readahead_blks); | ||
| 2674 | EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); | ||
| 2675 | EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); | ||
| 2676 | EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); | ||
| 2677 | EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); | ||
| 2678 | EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); | ||
| 2679 | EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); | ||
| 2680 | EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); | ||
| 2681 | EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128); | ||
| 2682 | EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb); | ||
| 2683 | EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error); | ||
| 2684 | EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); | ||
| 2685 | EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); | ||
| 2686 | EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); | ||
| 2687 | EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); | ||
| 2688 | EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); | ||
| 2689 | EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); | ||
| 2690 | EXT4_RO_ATTR_ES_UI(errors_count, s_error_count); | ||
| 2691 | EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time); | ||
| 2692 | EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time); | ||
| 2693 | |||
| 2694 | static struct attribute *ext4_attrs[] = { | ||
| 2695 | ATTR_LIST(delayed_allocation_blocks), | ||
| 2696 | ATTR_LIST(session_write_kbytes), | ||
| 2697 | ATTR_LIST(lifetime_write_kbytes), | ||
| 2698 | ATTR_LIST(reserved_clusters), | ||
| 2699 | ATTR_LIST(inode_readahead_blks), | ||
| 2700 | ATTR_LIST(inode_goal), | ||
| 2701 | ATTR_LIST(mb_stats), | ||
| 2702 | ATTR_LIST(mb_max_to_scan), | ||
| 2703 | ATTR_LIST(mb_min_to_scan), | ||
| 2704 | ATTR_LIST(mb_order2_req), | ||
| 2705 | ATTR_LIST(mb_stream_req), | ||
| 2706 | ATTR_LIST(mb_group_prealloc), | ||
| 2707 | ATTR_LIST(max_writeback_mb_bump), | ||
| 2708 | ATTR_LIST(extent_max_zeroout_kb), | ||
| 2709 | ATTR_LIST(trigger_fs_error), | ||
| 2710 | ATTR_LIST(err_ratelimit_interval_ms), | ||
| 2711 | ATTR_LIST(err_ratelimit_burst), | ||
| 2712 | ATTR_LIST(warning_ratelimit_interval_ms), | ||
| 2713 | ATTR_LIST(warning_ratelimit_burst), | ||
| 2714 | ATTR_LIST(msg_ratelimit_interval_ms), | ||
| 2715 | ATTR_LIST(msg_ratelimit_burst), | ||
| 2716 | ATTR_LIST(errors_count), | ||
| 2717 | ATTR_LIST(first_error_time), | ||
| 2718 | ATTR_LIST(last_error_time), | ||
| 2719 | NULL, | ||
| 2720 | }; | ||
| 2721 | |||
| 2722 | /* Features this copy of ext4 supports */ | ||
| 2723 | EXT4_INFO_ATTR(lazy_itable_init); | ||
| 2724 | EXT4_INFO_ATTR(batched_discard); | ||
| 2725 | EXT4_INFO_ATTR(meta_bg_resize); | ||
| 2726 | EXT4_INFO_ATTR(encryption); | ||
| 2727 | |||
| 2728 | static struct attribute *ext4_feat_attrs[] = { | ||
| 2729 | ATTR_LIST(lazy_itable_init), | ||
| 2730 | ATTR_LIST(batched_discard), | ||
| 2731 | ATTR_LIST(meta_bg_resize), | ||
| 2732 | ATTR_LIST(encryption), | ||
| 2733 | NULL, | ||
| 2734 | }; | ||
| 2735 | |||
| 2736 | static ssize_t ext4_attr_show(struct kobject *kobj, | ||
| 2737 | struct attribute *attr, char *buf) | ||
| 2738 | { | ||
| 2739 | struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, | ||
| 2740 | s_kobj); | ||
| 2741 | struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); | ||
| 2742 | |||
| 2743 | return a->show ? a->show(a, sbi, buf) : 0; | ||
| 2744 | } | ||
| 2745 | |||
| 2746 | static ssize_t ext4_attr_store(struct kobject *kobj, | ||
| 2747 | struct attribute *attr, | ||
| 2748 | const char *buf, size_t len) | ||
| 2749 | { | ||
| 2750 | struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, | ||
| 2751 | s_kobj); | ||
| 2752 | struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); | ||
| 2753 | |||
| 2754 | return a->store ? a->store(a, sbi, buf, len) : 0; | ||
| 2755 | } | ||
| 2756 | |||
| 2757 | static void ext4_sb_release(struct kobject *kobj) | ||
| 2758 | { | ||
| 2759 | struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, | ||
| 2760 | s_kobj); | ||
| 2761 | complete(&sbi->s_kobj_unregister); | ||
| 2762 | } | ||
| 2763 | |||
| 2764 | static const struct sysfs_ops ext4_attr_ops = { | ||
| 2765 | .show = ext4_attr_show, | ||
| 2766 | .store = ext4_attr_store, | ||
| 2767 | }; | ||
| 2768 | |||
| 2769 | static struct kobj_type ext4_ktype = { | ||
| 2770 | .default_attrs = ext4_attrs, | ||
| 2771 | .sysfs_ops = &ext4_attr_ops, | ||
| 2772 | .release = ext4_sb_release, | ||
| 2773 | }; | ||
| 2774 | |||
| 2775 | static void ext4_feat_release(struct kobject *kobj) | ||
| 2776 | { | ||
| 2777 | complete(&ext4_feat->f_kobj_unregister); | ||
| 2778 | } | ||
| 2779 | |||
| 2780 | static ssize_t ext4_feat_show(struct kobject *kobj, | ||
| 2781 | struct attribute *attr, char *buf) | ||
| 2782 | { | ||
| 2783 | return snprintf(buf, PAGE_SIZE, "supported\n"); | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | /* | ||
| 2787 | * We can not use ext4_attr_show/store because it relies on the kobject | ||
| 2788 | * being embedded in the ext4_sb_info structure which is definitely not | ||
| 2789 | * true in this case. | ||
| 2790 | */ | ||
| 2791 | static const struct sysfs_ops ext4_feat_ops = { | ||
| 2792 | .show = ext4_feat_show, | ||
| 2793 | .store = NULL, | ||
| 2794 | }; | ||
| 2795 | |||
| 2796 | static struct kobj_type ext4_feat_ktype = { | ||
| 2797 | .default_attrs = ext4_feat_attrs, | ||
| 2798 | .sysfs_ops = &ext4_feat_ops, | ||
| 2799 | .release = ext4_feat_release, | ||
| 2800 | }; | ||
| 2801 | |||
| 2802 | /* | 2465 | /* |
| 2803 | * Check whether this filesystem can be mounted based on | 2466 | * Check whether this filesystem can be mounted based on |
| 2804 | * the features present and the RDONLY/RDWR mount requested. | 2467 | * the features present and the RDONLY/RDWR mount requested. |
| @@ -2807,7 +2470,7 @@ static struct kobj_type ext4_feat_ktype = { | |||
| 2807 | */ | 2470 | */ |
| 2808 | static int ext4_feature_set_ok(struct super_block *sb, int readonly) | 2471 | static int ext4_feature_set_ok(struct super_block *sb, int readonly) |
| 2809 | { | 2472 | { |
| 2810 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP)) { | 2473 | if (ext4_has_unknown_ext4_incompat_features(sb)) { |
| 2811 | ext4_msg(sb, KERN_ERR, | 2474 | ext4_msg(sb, KERN_ERR, |
| 2812 | "Couldn't mount because of " | 2475 | "Couldn't mount because of " |
| 2813 | "unsupported optional features (%x)", | 2476 | "unsupported optional features (%x)", |
| @@ -2819,14 +2482,14 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
| 2819 | if (readonly) | 2482 | if (readonly) |
| 2820 | return 1; | 2483 | return 1; |
| 2821 | 2484 | ||
| 2822 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_READONLY)) { | 2485 | if (ext4_has_feature_readonly(sb)) { |
| 2823 | ext4_msg(sb, KERN_INFO, "filesystem is read-only"); | 2486 | ext4_msg(sb, KERN_INFO, "filesystem is read-only"); |
| 2824 | sb->s_flags |= MS_RDONLY; | 2487 | sb->s_flags |= MS_RDONLY; |
| 2825 | return 1; | 2488 | return 1; |
| 2826 | } | 2489 | } |
| 2827 | 2490 | ||
| 2828 | /* Check that feature set is OK for a read-write mount */ | 2491 | /* Check that feature set is OK for a read-write mount */ |
| 2829 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP)) { | 2492 | if (ext4_has_unknown_ext4_ro_compat_features(sb)) { |
| 2830 | ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of " | 2493 | ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of " |
| 2831 | "unsupported optional features (%x)", | 2494 | "unsupported optional features (%x)", |
| 2832 | (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) & | 2495 | (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) & |
| @@ -2837,7 +2500,7 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
| 2837 | * Large file size enabled file system can only be mounted | 2500 | * Large file size enabled file system can only be mounted |
| 2838 | * read-write on 32-bit systems if kernel is built with CONFIG_LBDAF | 2501 | * read-write on 32-bit systems if kernel is built with CONFIG_LBDAF |
| 2839 | */ | 2502 | */ |
| 2840 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | 2503 | if (ext4_has_feature_huge_file(sb)) { |
| 2841 | if (sizeof(blkcnt_t) < sizeof(u64)) { | 2504 | if (sizeof(blkcnt_t) < sizeof(u64)) { |
| 2842 | ext4_msg(sb, KERN_ERR, "Filesystem with huge files " | 2505 | ext4_msg(sb, KERN_ERR, "Filesystem with huge files " |
| 2843 | "cannot be mounted RDWR without " | 2506 | "cannot be mounted RDWR without " |
| @@ -2845,8 +2508,7 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
| 2845 | return 0; | 2508 | return 0; |
| 2846 | } | 2509 | } |
| 2847 | } | 2510 | } |
| 2848 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC) && | 2511 | if (ext4_has_feature_bigalloc(sb) && !ext4_has_feature_extents(sb)) { |
| 2849 | !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { | ||
| 2850 | ext4_msg(sb, KERN_ERR, | 2512 | ext4_msg(sb, KERN_ERR, |
| 2851 | "Can't support bigalloc feature without " | 2513 | "Can't support bigalloc feature without " |
| 2852 | "extents feature\n"); | 2514 | "extents feature\n"); |
| @@ -2854,8 +2516,7 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
| 2854 | } | 2516 | } |
| 2855 | 2517 | ||
| 2856 | #ifndef CONFIG_QUOTA | 2518 | #ifndef CONFIG_QUOTA |
| 2857 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && | 2519 | if (ext4_has_feature_quota(sb) && !readonly) { |
| 2858 | !readonly) { | ||
| 2859 | ext4_msg(sb, KERN_ERR, | 2520 | ext4_msg(sb, KERN_ERR, |
| 2860 | "Filesystem with quota feature cannot be mounted RDWR " | 2521 | "Filesystem with quota feature cannot be mounted RDWR " |
| 2861 | "without CONFIG_QUOTA"); | 2522 | "without CONFIG_QUOTA"); |
| @@ -3312,7 +2973,7 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp, | |||
| 3312 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); | 2973 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); |
| 3313 | int s, j, count = 0; | 2974 | int s, j, count = 0; |
| 3314 | 2975 | ||
| 3315 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) | 2976 | if (!ext4_has_feature_bigalloc(sb)) |
| 3316 | return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + | 2977 | return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + |
| 3317 | sbi->s_itb_per_group + 2); | 2978 | sbi->s_itb_per_group + 2); |
| 3318 | 2979 | ||
| @@ -3403,10 +3064,10 @@ int ext4_calculate_overhead(struct super_block *sb) | |||
| 3403 | return 0; | 3064 | return 0; |
| 3404 | } | 3065 | } |
| 3405 | 3066 | ||
| 3406 | 3067 | static void ext4_set_resv_clusters(struct super_block *sb) | |
| 3407 | static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb) | ||
| 3408 | { | 3068 | { |
| 3409 | ext4_fsblk_t resv_clusters; | 3069 | ext4_fsblk_t resv_clusters; |
| 3070 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 3410 | 3071 | ||
| 3411 | /* | 3072 | /* |
| 3412 | * There's no need to reserve anything when we aren't using extents. | 3073 | * There's no need to reserve anything when we aren't using extents. |
| @@ -3414,8 +3075,8 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb) | |||
| 3414 | * hole punching doesn't need new metadata... This is needed especially | 3075 | * hole punching doesn't need new metadata... This is needed especially |
| 3415 | * to keep ext2/3 backward compatibility. | 3076 | * to keep ext2/3 backward compatibility. |
| 3416 | */ | 3077 | */ |
| 3417 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) | 3078 | if (!ext4_has_feature_extents(sb)) |
| 3418 | return 0; | 3079 | return; |
| 3419 | /* | 3080 | /* |
| 3420 | * By default we reserve 2% or 4096 clusters, whichever is smaller. | 3081 | * By default we reserve 2% or 4096 clusters, whichever is smaller. |
| 3421 | * This should cover the situations where we can not afford to run | 3082 | * This should cover the situations where we can not afford to run |
| @@ -3424,26 +3085,13 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb) | |||
| 3424 | * allocation would require 1, or 2 blocks, higher numbers are | 3085 | * allocation would require 1, or 2 blocks, higher numbers are |
| 3425 | * very rare. | 3086 | * very rare. |
| 3426 | */ | 3087 | */ |
| 3427 | resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >> | 3088 | resv_clusters = (ext4_blocks_count(sbi->s_es) >> |
| 3428 | EXT4_SB(sb)->s_cluster_bits; | 3089 | sbi->s_cluster_bits); |
| 3429 | 3090 | ||
| 3430 | do_div(resv_clusters, 50); | 3091 | do_div(resv_clusters, 50); |
| 3431 | resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096); | 3092 | resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096); |
| 3432 | 3093 | ||
| 3433 | return resv_clusters; | 3094 | atomic64_set(&sbi->s_resv_clusters, resv_clusters); |
| 3434 | } | ||
| 3435 | |||
| 3436 | |||
| 3437 | static int ext4_reserve_clusters(struct ext4_sb_info *sbi, ext4_fsblk_t count) | ||
| 3438 | { | ||
| 3439 | ext4_fsblk_t clusters = ext4_blocks_count(sbi->s_es) >> | ||
| 3440 | sbi->s_cluster_bits; | ||
| 3441 | |||
| 3442 | if (count >= clusters) | ||
| 3443 | return -EINVAL; | ||
| 3444 | |||
| 3445 | atomic64_set(&sbi->s_resv_clusters, count); | ||
| 3446 | return 0; | ||
| 3447 | } | 3095 | } |
| 3448 | 3096 | ||
| 3449 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) | 3097 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) |
| @@ -3526,9 +3174,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3526 | sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written); | 3174 | sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written); |
| 3527 | 3175 | ||
| 3528 | /* Warn if metadata_csum and gdt_csum are both set. */ | 3176 | /* Warn if metadata_csum and gdt_csum are both set. */ |
| 3529 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3177 | if (ext4_has_feature_metadata_csum(sb) && |
| 3530 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && | 3178 | ext4_has_feature_gdt_csum(sb)) |
| 3531 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | ||
| 3532 | ext4_warning(sb, "metadata_csum and uninit_bg are " | 3179 | ext4_warning(sb, "metadata_csum and uninit_bg are " |
| 3533 | "redundant flags; please run fsck."); | 3180 | "redundant flags; please run fsck."); |
| 3534 | 3181 | ||
| @@ -3541,8 +3188,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3541 | } | 3188 | } |
| 3542 | 3189 | ||
| 3543 | /* Load the checksum driver */ | 3190 | /* Load the checksum driver */ |
| 3544 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3191 | if (ext4_has_feature_metadata_csum(sb)) { |
| 3545 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { | ||
| 3546 | sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); | 3192 | sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); |
| 3547 | if (IS_ERR(sbi->s_chksum_driver)) { | 3193 | if (IS_ERR(sbi->s_chksum_driver)) { |
| 3548 | ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver."); | 3194 | ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver."); |
| @@ -3557,11 +3203,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3557 | ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with " | 3203 | ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with " |
| 3558 | "invalid superblock checksum. Run e2fsck?"); | 3204 | "invalid superblock checksum. Run e2fsck?"); |
| 3559 | silent = 1; | 3205 | silent = 1; |
| 3206 | ret = -EFSBADCRC; | ||
| 3560 | goto cantfind_ext4; | 3207 | goto cantfind_ext4; |
| 3561 | } | 3208 | } |
| 3562 | 3209 | ||
| 3563 | /* Precompute checksum seed for all metadata */ | 3210 | /* Precompute checksum seed for all metadata */ |
| 3564 | if (ext4_has_metadata_csum(sb)) | 3211 | if (ext4_has_feature_csum_seed(sb)) |
| 3212 | sbi->s_csum_seed = le32_to_cpu(es->s_checksum_seed); | ||
| 3213 | else if (ext4_has_metadata_csum(sb)) | ||
| 3565 | sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid, | 3214 | sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid, |
| 3566 | sizeof(es->s_uuid)); | 3215 | sizeof(es->s_uuid)); |
| 3567 | 3216 | ||
| @@ -3664,17 +3313,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3664 | (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); | 3313 | (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); |
| 3665 | 3314 | ||
| 3666 | if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV && | 3315 | if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV && |
| 3667 | (EXT4_HAS_COMPAT_FEATURE(sb, ~0U) || | 3316 | (ext4_has_compat_features(sb) || |
| 3668 | EXT4_HAS_RO_COMPAT_FEATURE(sb, ~0U) || | 3317 | ext4_has_ro_compat_features(sb) || |
| 3669 | EXT4_HAS_INCOMPAT_FEATURE(sb, ~0U))) | 3318 | ext4_has_incompat_features(sb))) |
| 3670 | ext4_msg(sb, KERN_WARNING, | 3319 | ext4_msg(sb, KERN_WARNING, |
| 3671 | "feature flags set on rev 0 fs, " | 3320 | "feature flags set on rev 0 fs, " |
| 3672 | "running e2fsck is recommended"); | 3321 | "running e2fsck is recommended"); |
| 3673 | 3322 | ||
| 3674 | if (es->s_creator_os == cpu_to_le32(EXT4_OS_HURD)) { | 3323 | if (es->s_creator_os == cpu_to_le32(EXT4_OS_HURD)) { |
| 3675 | set_opt2(sb, HURD_COMPAT); | 3324 | set_opt2(sb, HURD_COMPAT); |
| 3676 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | 3325 | if (ext4_has_feature_64bit(sb)) { |
| 3677 | EXT4_FEATURE_INCOMPAT_64BIT)) { | ||
| 3678 | ext4_msg(sb, KERN_ERR, | 3326 | ext4_msg(sb, KERN_ERR, |
| 3679 | "The Hurd can't support 64-bit file systems"); | 3327 | "The Hurd can't support 64-bit file systems"); |
| 3680 | goto failed_mount; | 3328 | goto failed_mount; |
| @@ -3732,8 +3380,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3732 | } | 3380 | } |
| 3733 | } | 3381 | } |
| 3734 | 3382 | ||
| 3735 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) && | 3383 | if (ext4_has_feature_encrypt(sb) && es->s_encryption_level) { |
| 3736 | es->s_encryption_level) { | ||
| 3737 | ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d", | 3384 | ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d", |
| 3738 | es->s_encryption_level); | 3385 | es->s_encryption_level); |
| 3739 | goto failed_mount; | 3386 | goto failed_mount; |
| @@ -3765,8 +3412,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3765 | } | 3412 | } |
| 3766 | } | 3413 | } |
| 3767 | 3414 | ||
| 3768 | has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3415 | has_huge_files = ext4_has_feature_huge_file(sb); |
| 3769 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE); | ||
| 3770 | sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits, | 3416 | sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits, |
| 3771 | has_huge_files); | 3417 | has_huge_files); |
| 3772 | sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files); | 3418 | sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files); |
| @@ -3790,7 +3436,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3790 | } | 3436 | } |
| 3791 | 3437 | ||
| 3792 | sbi->s_desc_size = le16_to_cpu(es->s_desc_size); | 3438 | sbi->s_desc_size = le16_to_cpu(es->s_desc_size); |
| 3793 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) { | 3439 | if (ext4_has_feature_64bit(sb)) { |
| 3794 | if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT || | 3440 | if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT || |
| 3795 | sbi->s_desc_size > EXT4_MAX_DESC_SIZE || | 3441 | sbi->s_desc_size > EXT4_MAX_DESC_SIZE || |
| 3796 | !is_power_of_2(sbi->s_desc_size)) { | 3442 | !is_power_of_2(sbi->s_desc_size)) { |
| @@ -3821,7 +3467,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3821 | for (i = 0; i < 4; i++) | 3467 | for (i = 0; i < 4; i++) |
| 3822 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); | 3468 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); |
| 3823 | sbi->s_def_hash_version = es->s_def_hash_version; | 3469 | sbi->s_def_hash_version = es->s_def_hash_version; |
| 3824 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { | 3470 | if (ext4_has_feature_dir_index(sb)) { |
| 3825 | i = le32_to_cpu(es->s_flags); | 3471 | i = le32_to_cpu(es->s_flags); |
| 3826 | if (i & EXT2_FLAGS_UNSIGNED_HASH) | 3472 | if (i & EXT2_FLAGS_UNSIGNED_HASH) |
| 3827 | sbi->s_hash_unsigned = 3; | 3473 | sbi->s_hash_unsigned = 3; |
| @@ -3841,8 +3487,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3841 | 3487 | ||
| 3842 | /* Handle clustersize */ | 3488 | /* Handle clustersize */ |
| 3843 | clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size); | 3489 | clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size); |
| 3844 | has_bigalloc = EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3490 | has_bigalloc = ext4_has_feature_bigalloc(sb); |
| 3845 | EXT4_FEATURE_RO_COMPAT_BIGALLOC); | ||
| 3846 | if (has_bigalloc) { | 3491 | if (has_bigalloc) { |
| 3847 | if (clustersize < blocksize) { | 3492 | if (clustersize < blocksize) { |
| 3848 | ext4_msg(sb, KERN_ERR, | 3493 | ext4_msg(sb, KERN_ERR, |
| @@ -3961,13 +3606,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3961 | goto failed_mount; | 3606 | goto failed_mount; |
| 3962 | } | 3607 | } |
| 3963 | 3608 | ||
| 3964 | if (ext4_proc_root) | ||
| 3965 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | ||
| 3966 | |||
| 3967 | if (sbi->s_proc) | ||
| 3968 | proc_create_data("options", S_IRUGO, sbi->s_proc, | ||
| 3969 | &ext4_seq_options_fops, sb); | ||
| 3970 | |||
| 3971 | bgl_lock_init(sbi->s_blockgroup_lock); | 3609 | bgl_lock_init(sbi->s_blockgroup_lock); |
| 3972 | 3610 | ||
| 3973 | for (i = 0; i < db_count; i++) { | 3611 | for (i = 0; i < db_count; i++) { |
| @@ -3982,6 +3620,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3982 | } | 3620 | } |
| 3983 | if (!ext4_check_descriptors(sb, &first_not_zeroed)) { | 3621 | if (!ext4_check_descriptors(sb, &first_not_zeroed)) { |
| 3984 | ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); | 3622 | ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); |
| 3623 | ret = -EFSCORRUPTED; | ||
| 3985 | goto failed_mount2; | 3624 | goto failed_mount2; |
| 3986 | } | 3625 | } |
| 3987 | 3626 | ||
| @@ -4007,7 +3646,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 4007 | sb->s_xattr = ext4_xattr_handlers; | 3646 | sb->s_xattr = ext4_xattr_handlers; |
| 4008 | #ifdef CONFIG_QUOTA | 3647 | #ifdef CONFIG_QUOTA |
| 4009 | sb->dq_op = &ext4_quota_operations; | 3648 | sb->dq_op = &ext4_quota_operations; |
| 4010 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) | 3649 | if (ext4_has_feature_quota(sb)) |
| 4011 | sb->s_qcop = &dquot_quotactl_sysfile_ops; | 3650 | sb->s_qcop = &dquot_quotactl_sysfile_ops; |
| 4012 | else | 3651 | else |
| 4013 | sb->s_qcop = &ext4_qctl_operations; | 3652 | sb->s_qcop = &ext4_qctl_operations; |
| @@ -4021,11 +3660,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 4021 | sb->s_root = NULL; | 3660 | sb->s_root = NULL; |
| 4022 | 3661 | ||
| 4023 | needs_recovery = (es->s_last_orphan != 0 || | 3662 | needs_recovery = (es->s_last_orphan != 0 || |
| 4024 | EXT4_HAS_INCOMPAT_FEATURE(sb, | 3663 | ext4_has_feature_journal_needs_recovery(sb)); |
| 4025 | EXT4_FEATURE_INCOMPAT_RECOVER)); | ||
| 4026 | 3664 | ||
| 4027 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) && | 3665 | if (ext4_has_feature_mmp(sb) && !(sb->s_flags & MS_RDONLY)) |
| 4028 | !(sb->s_flags & MS_RDONLY)) | ||
| 4029 | if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) | 3666 | if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) |
| 4030 | goto failed_mount3a; | 3667 | goto failed_mount3a; |
| 4031 | 3668 | ||
| @@ -4033,23 +3670,47 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 4033 | * The first inode we look at is the journal inode. Don't try | 3670 | * The first inode we look at is the journal inode. Don't try |
| 4034 | * root first: it may be modified in the journal! | 3671 | * root first: it may be modified in the journal! |
| 4035 | */ | 3672 | */ |
| 4036 | if (!test_opt(sb, NOLOAD) && | 3673 | if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) { |
| 4037 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { | ||
| 4038 | if (ext4_load_journal(sb, es, journal_devnum)) | 3674 | if (ext4_load_journal(sb, es, journal_devnum)) |
| 4039 | goto failed_mount3a; | 3675 | goto failed_mount3a; |
| 4040 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && | 3676 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && |
| 4041 | EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { | 3677 | ext4_has_feature_journal_needs_recovery(sb)) { |
| 4042 | ext4_msg(sb, KERN_ERR, "required journal recovery " | 3678 | ext4_msg(sb, KERN_ERR, "required journal recovery " |
| 4043 | "suppressed and not mounted read-only"); | 3679 | "suppressed and not mounted read-only"); |
| 4044 | goto failed_mount_wq; | 3680 | goto failed_mount_wq; |
| 4045 | } else { | 3681 | } else { |
| 3682 | /* Nojournal mode, all journal mount options are illegal */ | ||
| 3683 | if (test_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM)) { | ||
| 3684 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 3685 | "journal_checksum, fs mounted w/o journal"); | ||
| 3686 | goto failed_mount_wq; | ||
| 3687 | } | ||
| 3688 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { | ||
| 3689 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 3690 | "journal_async_commit, fs mounted w/o journal"); | ||
| 3691 | goto failed_mount_wq; | ||
| 3692 | } | ||
| 3693 | if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) { | ||
| 3694 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 3695 | "commit=%lu, fs mounted w/o journal", | ||
| 3696 | sbi->s_commit_interval / HZ); | ||
| 3697 | goto failed_mount_wq; | ||
| 3698 | } | ||
| 3699 | if (EXT4_MOUNT_DATA_FLAGS & | ||
| 3700 | (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) { | ||
| 3701 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 3702 | "data=, fs mounted w/o journal"); | ||
| 3703 | goto failed_mount_wq; | ||
| 3704 | } | ||
| 3705 | sbi->s_def_mount_opt &= EXT4_MOUNT_JOURNAL_CHECKSUM; | ||
| 3706 | clear_opt(sb, JOURNAL_CHECKSUM); | ||
| 4046 | clear_opt(sb, DATA_FLAGS); | 3707 | clear_opt(sb, DATA_FLAGS); |
| 4047 | sbi->s_journal = NULL; | 3708 | sbi->s_journal = NULL; |
| 4048 | needs_recovery = 0; | 3709 | needs_recovery = 0; |
| 4049 | goto no_journal; | 3710 | goto no_journal; |
| 4050 | } | 3711 | } |
| 4051 | 3712 | ||
| 4052 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT) && | 3713 | if (ext4_has_feature_64bit(sb) && |
| 4053 | !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0, | 3714 | !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0, |
| 4054 | JBD2_FEATURE_INCOMPAT_64BIT)) { | 3715 | JBD2_FEATURE_INCOMPAT_64BIT)) { |
| 4055 | ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature"); | 3716 | ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature"); |
| @@ -4101,18 +3762,16 @@ no_journal: | |||
| 4101 | } | 3762 | } |
| 4102 | } | 3763 | } |
| 4103 | 3764 | ||
| 4104 | if ((DUMMY_ENCRYPTION_ENABLED(sbi) || | 3765 | if ((DUMMY_ENCRYPTION_ENABLED(sbi) || ext4_has_feature_encrypt(sb)) && |
| 4105 | EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) && | ||
| 4106 | (blocksize != PAGE_CACHE_SIZE)) { | 3766 | (blocksize != PAGE_CACHE_SIZE)) { |
| 4107 | ext4_msg(sb, KERN_ERR, | 3767 | ext4_msg(sb, KERN_ERR, |
| 4108 | "Unsupported blocksize for fs encryption"); | 3768 | "Unsupported blocksize for fs encryption"); |
| 4109 | goto failed_mount_wq; | 3769 | goto failed_mount_wq; |
| 4110 | } | 3770 | } |
| 4111 | 3771 | ||
| 4112 | if (DUMMY_ENCRYPTION_ENABLED(sbi) && | 3772 | if (DUMMY_ENCRYPTION_ENABLED(sbi) && !(sb->s_flags & MS_RDONLY) && |
| 4113 | !(sb->s_flags & MS_RDONLY) && | 3773 | !ext4_has_feature_encrypt(sb)) { |
| 4114 | !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) { | 3774 | ext4_set_feature_encrypt(sb); |
| 4115 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT); | ||
| 4116 | ext4_commit_super(sb, 1); | 3775 | ext4_commit_super(sb, 1); |
| 4117 | } | 3776 | } |
| 4118 | 3777 | ||
| @@ -4171,8 +3830,7 @@ no_journal: | |||
| 4171 | if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { | 3830 | if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { |
| 4172 | sbi->s_want_extra_isize = sizeof(struct ext4_inode) - | 3831 | sbi->s_want_extra_isize = sizeof(struct ext4_inode) - |
| 4173 | EXT4_GOOD_OLD_INODE_SIZE; | 3832 | EXT4_GOOD_OLD_INODE_SIZE; |
| 4174 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3833 | if (ext4_has_feature_extra_isize(sb)) { |
| 4175 | EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)) { | ||
| 4176 | if (sbi->s_want_extra_isize < | 3834 | if (sbi->s_want_extra_isize < |
| 4177 | le16_to_cpu(es->s_want_extra_isize)) | 3835 | le16_to_cpu(es->s_want_extra_isize)) |
| 4178 | sbi->s_want_extra_isize = | 3836 | sbi->s_want_extra_isize = |
| @@ -4192,12 +3850,7 @@ no_journal: | |||
| 4192 | "available"); | 3850 | "available"); |
| 4193 | } | 3851 | } |
| 4194 | 3852 | ||
| 4195 | err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb)); | 3853 | ext4_set_resv_clusters(sb); |
| 4196 | if (err) { | ||
| 4197 | ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for " | ||
| 4198 | "reserved pool", ext4_calculate_resv_clusters(sb)); | ||
| 4199 | goto failed_mount4a; | ||
| 4200 | } | ||
| 4201 | 3854 | ||
| 4202 | err = ext4_setup_system_zone(sb); | 3855 | err = ext4_setup_system_zone(sb); |
| 4203 | if (err) { | 3856 | if (err) { |
| @@ -4236,7 +3889,7 @@ no_journal: | |||
| 4236 | goto failed_mount6; | 3889 | goto failed_mount6; |
| 4237 | } | 3890 | } |
| 4238 | 3891 | ||
| 4239 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 3892 | if (ext4_has_feature_flex_bg(sb)) |
| 4240 | if (!ext4_fill_flex_info(sb)) { | 3893 | if (!ext4_fill_flex_info(sb)) { |
| 4241 | ext4_msg(sb, KERN_ERR, | 3894 | ext4_msg(sb, KERN_ERR, |
| 4242 | "unable to initialize " | 3895 | "unable to initialize " |
| @@ -4248,17 +3901,13 @@ no_journal: | |||
| 4248 | if (err) | 3901 | if (err) |
| 4249 | goto failed_mount6; | 3902 | goto failed_mount6; |
| 4250 | 3903 | ||
| 4251 | sbi->s_kobj.kset = ext4_kset; | 3904 | err = ext4_register_sysfs(sb); |
| 4252 | init_completion(&sbi->s_kobj_unregister); | ||
| 4253 | err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL, | ||
| 4254 | "%s", sb->s_id); | ||
| 4255 | if (err) | 3905 | if (err) |
| 4256 | goto failed_mount7; | 3906 | goto failed_mount7; |
| 4257 | 3907 | ||
| 4258 | #ifdef CONFIG_QUOTA | 3908 | #ifdef CONFIG_QUOTA |
| 4259 | /* Enable quota usage during mount. */ | 3909 | /* Enable quota usage during mount. */ |
| 4260 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && | 3910 | if (ext4_has_feature_quota(sb) && !(sb->s_flags & MS_RDONLY)) { |
| 4261 | !(sb->s_flags & MS_RDONLY)) { | ||
| 4262 | err = ext4_enable_quotas(sb); | 3911 | err = ext4_enable_quotas(sb); |
| 4263 | if (err) | 3912 | if (err) |
| 4264 | goto failed_mount8; | 3913 | goto failed_mount8; |
| @@ -4313,7 +3962,7 @@ cantfind_ext4: | |||
| 4313 | 3962 | ||
| 4314 | #ifdef CONFIG_QUOTA | 3963 | #ifdef CONFIG_QUOTA |
| 4315 | failed_mount8: | 3964 | failed_mount8: |
| 4316 | kobject_del(&sbi->s_kobj); | 3965 | ext4_unregister_sysfs(sb); |
| 4317 | #endif | 3966 | #endif |
| 4318 | failed_mount7: | 3967 | failed_mount7: |
| 4319 | ext4_unregister_li_request(sb); | 3968 | ext4_unregister_li_request(sb); |
| @@ -4353,10 +4002,6 @@ failed_mount2: | |||
| 4353 | failed_mount: | 4002 | failed_mount: |
| 4354 | if (sbi->s_chksum_driver) | 4003 | if (sbi->s_chksum_driver) |
| 4355 | crypto_free_shash(sbi->s_chksum_driver); | 4004 | crypto_free_shash(sbi->s_chksum_driver); |
| 4356 | if (sbi->s_proc) { | ||
| 4357 | remove_proc_entry("options", sbi->s_proc); | ||
| 4358 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
| 4359 | } | ||
| 4360 | #ifdef CONFIG_QUOTA | 4005 | #ifdef CONFIG_QUOTA |
| 4361 | for (i = 0; i < EXT4_MAXQUOTAS; i++) | 4006 | for (i = 0; i < EXT4_MAXQUOTAS; i++) |
| 4362 | kfree(sbi->s_qf_names[i]); | 4007 | kfree(sbi->s_qf_names[i]); |
| @@ -4403,7 +4048,7 @@ static journal_t *ext4_get_journal(struct super_block *sb, | |||
| 4403 | struct inode *journal_inode; | 4048 | struct inode *journal_inode; |
| 4404 | journal_t *journal; | 4049 | journal_t *journal; |
| 4405 | 4050 | ||
| 4406 | BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); | 4051 | BUG_ON(!ext4_has_feature_journal(sb)); |
| 4407 | 4052 | ||
| 4408 | /* First, test for the existence of a valid inode on disk. Bad | 4053 | /* First, test for the existence of a valid inode on disk. Bad |
| 4409 | * things happen if we iget() an unused inode, as the subsequent | 4054 | * things happen if we iget() an unused inode, as the subsequent |
| @@ -4453,7 +4098,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb, | |||
| 4453 | struct ext4_super_block *es; | 4098 | struct ext4_super_block *es; |
| 4454 | struct block_device *bdev; | 4099 | struct block_device *bdev; |
| 4455 | 4100 | ||
| 4456 | BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); | 4101 | BUG_ON(!ext4_has_feature_journal(sb)); |
| 4457 | 4102 | ||
| 4458 | bdev = ext4_blkdev_get(j_dev, sb); | 4103 | bdev = ext4_blkdev_get(j_dev, sb); |
| 4459 | if (bdev == NULL) | 4104 | if (bdev == NULL) |
| @@ -4545,7 +4190,7 @@ static int ext4_load_journal(struct super_block *sb, | |||
| 4545 | int err = 0; | 4190 | int err = 0; |
| 4546 | int really_read_only; | 4191 | int really_read_only; |
| 4547 | 4192 | ||
| 4548 | BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); | 4193 | BUG_ON(!ext4_has_feature_journal(sb)); |
| 4549 | 4194 | ||
| 4550 | if (journal_devnum && | 4195 | if (journal_devnum && |
| 4551 | journal_devnum != le32_to_cpu(es->s_journal_dev)) { | 4196 | journal_devnum != le32_to_cpu(es->s_journal_dev)) { |
| @@ -4562,7 +4207,7 @@ static int ext4_load_journal(struct super_block *sb, | |||
| 4562 | * crash? For recovery, we need to check in advance whether we | 4207 | * crash? For recovery, we need to check in advance whether we |
| 4563 | * can get read-write access to the device. | 4208 | * can get read-write access to the device. |
| 4564 | */ | 4209 | */ |
| 4565 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { | 4210 | if (ext4_has_feature_journal_needs_recovery(sb)) { |
| 4566 | if (sb->s_flags & MS_RDONLY) { | 4211 | if (sb->s_flags & MS_RDONLY) { |
| 4567 | ext4_msg(sb, KERN_INFO, "INFO: recovery " | 4212 | ext4_msg(sb, KERN_INFO, "INFO: recovery " |
| 4568 | "required on readonly filesystem"); | 4213 | "required on readonly filesystem"); |
| @@ -4593,7 +4238,7 @@ static int ext4_load_journal(struct super_block *sb, | |||
| 4593 | if (!(journal->j_flags & JBD2_BARRIER)) | 4238 | if (!(journal->j_flags & JBD2_BARRIER)) |
| 4594 | ext4_msg(sb, KERN_INFO, "barriers disabled"); | 4239 | ext4_msg(sb, KERN_INFO, "barriers disabled"); |
| 4595 | 4240 | ||
| 4596 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) | 4241 | if (!ext4_has_feature_journal_needs_recovery(sb)) |
| 4597 | err = jbd2_journal_wipe(journal, !really_read_only); | 4242 | err = jbd2_journal_wipe(journal, !really_read_only); |
| 4598 | if (!err) { | 4243 | if (!err) { |
| 4599 | char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL); | 4244 | char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL); |
| @@ -4707,7 +4352,7 @@ static void ext4_mark_recovery_complete(struct super_block *sb, | |||
| 4707 | { | 4352 | { |
| 4708 | journal_t *journal = EXT4_SB(sb)->s_journal; | 4353 | journal_t *journal = EXT4_SB(sb)->s_journal; |
| 4709 | 4354 | ||
| 4710 | if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { | 4355 | if (!ext4_has_feature_journal(sb)) { |
| 4711 | BUG_ON(journal != NULL); | 4356 | BUG_ON(journal != NULL); |
| 4712 | return; | 4357 | return; |
| 4713 | } | 4358 | } |
| @@ -4715,9 +4360,9 @@ static void ext4_mark_recovery_complete(struct super_block *sb, | |||
| 4715 | if (jbd2_journal_flush(journal) < 0) | 4360 | if (jbd2_journal_flush(journal) < 0) |
| 4716 | goto out; | 4361 | goto out; |
| 4717 | 4362 | ||
| 4718 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && | 4363 | if (ext4_has_feature_journal_needs_recovery(sb) && |
| 4719 | sb->s_flags & MS_RDONLY) { | 4364 | sb->s_flags & MS_RDONLY) { |
| 4720 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 4365 | ext4_clear_feature_journal_needs_recovery(sb); |
| 4721 | ext4_commit_super(sb, 1); | 4366 | ext4_commit_super(sb, 1); |
| 4722 | } | 4367 | } |
| 4723 | 4368 | ||
| @@ -4737,7 +4382,7 @@ static void ext4_clear_journal_err(struct super_block *sb, | |||
| 4737 | int j_errno; | 4382 | int j_errno; |
| 4738 | const char *errstr; | 4383 | const char *errstr; |
| 4739 | 4384 | ||
| 4740 | BUG_ON(!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)); | 4385 | BUG_ON(!ext4_has_feature_journal(sb)); |
| 4741 | 4386 | ||
| 4742 | journal = EXT4_SB(sb)->s_journal; | 4387 | journal = EXT4_SB(sb)->s_journal; |
| 4743 | 4388 | ||
| @@ -4852,7 +4497,7 @@ static int ext4_freeze(struct super_block *sb) | |||
| 4852 | goto out; | 4497 | goto out; |
| 4853 | 4498 | ||
| 4854 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 4499 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
| 4855 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 4500 | ext4_clear_feature_journal_needs_recovery(sb); |
| 4856 | } | 4501 | } |
| 4857 | 4502 | ||
| 4858 | error = ext4_commit_super(sb, 1); | 4503 | error = ext4_commit_super(sb, 1); |
| @@ -4874,7 +4519,7 @@ static int ext4_unfreeze(struct super_block *sb) | |||
| 4874 | 4519 | ||
| 4875 | if (EXT4_SB(sb)->s_journal) { | 4520 | if (EXT4_SB(sb)->s_journal) { |
| 4876 | /* Reset the needs_recovery flag before the fs is unlocked. */ | 4521 | /* Reset the needs_recovery flag before the fs is unlocked. */ |
| 4877 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 4522 | ext4_set_feature_journal_needs_recovery(sb); |
| 4878 | } | 4523 | } |
| 4879 | 4524 | ||
| 4880 | ext4_commit_super(sb, 1); | 4525 | ext4_commit_super(sb, 1); |
| @@ -5027,8 +4672,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 5027 | ext4_mark_recovery_complete(sb, es); | 4672 | ext4_mark_recovery_complete(sb, es); |
| 5028 | } else { | 4673 | } else { |
| 5029 | /* Make sure we can mount this feature set readwrite */ | 4674 | /* Make sure we can mount this feature set readwrite */ |
| 5030 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 4675 | if (ext4_has_feature_readonly(sb) || |
| 5031 | EXT4_FEATURE_RO_COMPAT_READONLY) || | ||
| 5032 | !ext4_feature_set_ok(sb, 0)) { | 4676 | !ext4_feature_set_ok(sb, 0)) { |
| 5033 | err = -EROFS; | 4677 | err = -EROFS; |
| 5034 | goto restore_opts; | 4678 | goto restore_opts; |
| @@ -5044,9 +4688,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 5044 | if (!ext4_group_desc_csum_verify(sb, g, gdp)) { | 4688 | if (!ext4_group_desc_csum_verify(sb, g, gdp)) { |
| 5045 | ext4_msg(sb, KERN_ERR, | 4689 | ext4_msg(sb, KERN_ERR, |
| 5046 | "ext4_remount: Checksum for group %u failed (%u!=%u)", | 4690 | "ext4_remount: Checksum for group %u failed (%u!=%u)", |
| 5047 | g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)), | 4691 | g, le16_to_cpu(ext4_group_desc_csum(sb, g, gdp)), |
| 5048 | le16_to_cpu(gdp->bg_checksum)); | 4692 | le16_to_cpu(gdp->bg_checksum)); |
| 5049 | err = -EINVAL; | 4693 | err = -EFSBADCRC; |
| 5050 | goto restore_opts; | 4694 | goto restore_opts; |
| 5051 | } | 4695 | } |
| 5052 | } | 4696 | } |
| @@ -5076,8 +4720,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 5076 | sbi->s_mount_state = le16_to_cpu(es->s_state); | 4720 | sbi->s_mount_state = le16_to_cpu(es->s_state); |
| 5077 | if (!ext4_setup_super(sb, es, 0)) | 4721 | if (!ext4_setup_super(sb, es, 0)) |
| 5078 | sb->s_flags &= ~MS_RDONLY; | 4722 | sb->s_flags &= ~MS_RDONLY; |
| 5079 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | 4723 | if (ext4_has_feature_mmp(sb)) |
| 5080 | EXT4_FEATURE_INCOMPAT_MMP)) | ||
| 5081 | if (ext4_multi_mount_protect(sb, | 4724 | if (ext4_multi_mount_protect(sb, |
| 5082 | le64_to_cpu(es->s_mmp_block))) { | 4725 | le64_to_cpu(es->s_mmp_block))) { |
| 5083 | err = -EROFS; | 4726 | err = -EROFS; |
| @@ -5110,8 +4753,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 5110 | if (enable_quota) { | 4753 | if (enable_quota) { |
| 5111 | if (sb_any_quota_suspended(sb)) | 4754 | if (sb_any_quota_suspended(sb)) |
| 5112 | dquot_resume(sb, -1); | 4755 | dquot_resume(sb, -1); |
| 5113 | else if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 4756 | else if (ext4_has_feature_quota(sb)) { |
| 5114 | EXT4_FEATURE_RO_COMPAT_QUOTA)) { | ||
| 5115 | err = ext4_enable_quotas(sb); | 4757 | err = ext4_enable_quotas(sb); |
| 5116 | if (err) | 4758 | if (err) |
| 5117 | goto restore_opts; | 4759 | goto restore_opts; |
| @@ -5255,7 +4897,7 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot) | |||
| 5255 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 4897 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 5256 | 4898 | ||
| 5257 | /* Are we journaling quotas? */ | 4899 | /* Are we journaling quotas? */ |
| 5258 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) || | 4900 | if (ext4_has_feature_quota(sb) || |
| 5259 | sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { | 4901 | sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { |
| 5260 | dquot_mark_dquot_dirty(dquot); | 4902 | dquot_mark_dquot_dirty(dquot); |
| 5261 | return ext4_write_dquot(dquot); | 4903 | return ext4_write_dquot(dquot); |
| @@ -5343,7 +4985,7 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id, | |||
| 5343 | le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) | 4985 | le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) |
| 5344 | }; | 4986 | }; |
| 5345 | 4987 | ||
| 5346 | BUG_ON(!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)); | 4988 | BUG_ON(!ext4_has_feature_quota(sb)); |
| 5347 | 4989 | ||
| 5348 | if (!qf_inums[type]) | 4990 | if (!qf_inums[type]) |
| 5349 | return -EPERM; | 4991 | return -EPERM; |
| @@ -5537,11 +5179,11 @@ static inline void unregister_as_ext2(void) | |||
| 5537 | 5179 | ||
| 5538 | static inline int ext2_feature_set_ok(struct super_block *sb) | 5180 | static inline int ext2_feature_set_ok(struct super_block *sb) |
| 5539 | { | 5181 | { |
| 5540 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP)) | 5182 | if (ext4_has_unknown_ext2_incompat_features(sb)) |
| 5541 | return 0; | 5183 | return 0; |
| 5542 | if (sb->s_flags & MS_RDONLY) | 5184 | if (sb->s_flags & MS_RDONLY) |
| 5543 | return 1; | 5185 | return 1; |
| 5544 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP)) | 5186 | if (ext4_has_unknown_ext2_ro_compat_features(sb)) |
| 5545 | return 0; | 5187 | return 0; |
| 5546 | return 1; | 5188 | return 1; |
| 5547 | } | 5189 | } |
| @@ -5566,13 +5208,13 @@ static inline void unregister_as_ext3(void) | |||
| 5566 | 5208 | ||
| 5567 | static inline int ext3_feature_set_ok(struct super_block *sb) | 5209 | static inline int ext3_feature_set_ok(struct super_block *sb) |
| 5568 | { | 5210 | { |
| 5569 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP)) | 5211 | if (ext4_has_unknown_ext3_incompat_features(sb)) |
| 5570 | return 0; | 5212 | return 0; |
| 5571 | if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) | 5213 | if (!ext4_has_feature_journal(sb)) |
| 5572 | return 0; | 5214 | return 0; |
| 5573 | if (sb->s_flags & MS_RDONLY) | 5215 | if (sb->s_flags & MS_RDONLY) |
| 5574 | return 1; | 5216 | return 1; |
| 5575 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) | 5217 | if (ext4_has_unknown_ext3_ro_compat_features(sb)) |
| 5576 | return 0; | 5218 | return 0; |
| 5577 | return 1; | 5219 | return 1; |
| 5578 | } | 5220 | } |
| @@ -5586,37 +5228,6 @@ static struct file_system_type ext4_fs_type = { | |||
| 5586 | }; | 5228 | }; |
| 5587 | MODULE_ALIAS_FS("ext4"); | 5229 | MODULE_ALIAS_FS("ext4"); |
| 5588 | 5230 | ||
| 5589 | static int __init ext4_init_feat_adverts(void) | ||
| 5590 | { | ||
| 5591 | struct ext4_features *ef; | ||
| 5592 | int ret = -ENOMEM; | ||
| 5593 | |||
| 5594 | ef = kzalloc(sizeof(struct ext4_features), GFP_KERNEL); | ||
| 5595 | if (!ef) | ||
| 5596 | goto out; | ||
| 5597 | |||
| 5598 | ef->f_kobj.kset = ext4_kset; | ||
| 5599 | init_completion(&ef->f_kobj_unregister); | ||
| 5600 | ret = kobject_init_and_add(&ef->f_kobj, &ext4_feat_ktype, NULL, | ||
| 5601 | "features"); | ||
| 5602 | if (ret) { | ||
| 5603 | kfree(ef); | ||
| 5604 | goto out; | ||
| 5605 | } | ||
| 5606 | |||
| 5607 | ext4_feat = ef; | ||
| 5608 | ret = 0; | ||
| 5609 | out: | ||
| 5610 | return ret; | ||
| 5611 | } | ||
| 5612 | |||
| 5613 | static void ext4_exit_feat_adverts(void) | ||
| 5614 | { | ||
| 5615 | kobject_put(&ext4_feat->f_kobj); | ||
| 5616 | wait_for_completion(&ext4_feat->f_kobj_unregister); | ||
| 5617 | kfree(ext4_feat); | ||
| 5618 | } | ||
| 5619 | |||
| 5620 | /* Shared across all ext4 file systems */ | 5231 | /* Shared across all ext4 file systems */ |
| 5621 | wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; | 5232 | wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ]; |
| 5622 | struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; | 5233 | struct mutex ext4__aio_mutex[EXT4_WQ_HASH_SZ]; |
| @@ -5643,21 +5254,15 @@ static int __init ext4_init_fs(void) | |||
| 5643 | 5254 | ||
| 5644 | err = ext4_init_pageio(); | 5255 | err = ext4_init_pageio(); |
| 5645 | if (err) | 5256 | if (err) |
| 5646 | goto out7; | 5257 | goto out5; |
| 5647 | 5258 | ||
| 5648 | err = ext4_init_system_zone(); | 5259 | err = ext4_init_system_zone(); |
| 5649 | if (err) | 5260 | if (err) |
| 5650 | goto out6; | 5261 | goto out4; |
| 5651 | ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); | ||
| 5652 | if (!ext4_kset) { | ||
| 5653 | err = -ENOMEM; | ||
| 5654 | goto out5; | ||
| 5655 | } | ||
| 5656 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); | ||
| 5657 | 5262 | ||
| 5658 | err = ext4_init_feat_adverts(); | 5263 | err = ext4_init_sysfs(); |
| 5659 | if (err) | 5264 | if (err) |
| 5660 | goto out4; | 5265 | goto out3; |
| 5661 | 5266 | ||
| 5662 | err = ext4_init_mballoc(); | 5267 | err = ext4_init_mballoc(); |
| 5663 | if (err) | 5268 | if (err) |
| @@ -5682,16 +5287,12 @@ out1: | |||
| 5682 | ext4_mballoc_ready = 0; | 5287 | ext4_mballoc_ready = 0; |
| 5683 | ext4_exit_mballoc(); | 5288 | ext4_exit_mballoc(); |
| 5684 | out2: | 5289 | out2: |
| 5685 | ext4_exit_feat_adverts(); | 5290 | ext4_exit_sysfs(); |
| 5686 | out4: | 5291 | out3: |
| 5687 | if (ext4_proc_root) | ||
| 5688 | remove_proc_entry("fs/ext4", NULL); | ||
| 5689 | kset_unregister(ext4_kset); | ||
| 5690 | out5: | ||
| 5691 | ext4_exit_system_zone(); | 5292 | ext4_exit_system_zone(); |
| 5692 | out6: | 5293 | out4: |
| 5693 | ext4_exit_pageio(); | 5294 | ext4_exit_pageio(); |
| 5694 | out7: | 5295 | out5: |
| 5695 | ext4_exit_es(); | 5296 | ext4_exit_es(); |
| 5696 | 5297 | ||
| 5697 | return err; | 5298 | return err; |
| @@ -5706,9 +5307,7 @@ static void __exit ext4_exit_fs(void) | |||
| 5706 | unregister_filesystem(&ext4_fs_type); | 5307 | unregister_filesystem(&ext4_fs_type); |
| 5707 | destroy_inodecache(); | 5308 | destroy_inodecache(); |
| 5708 | ext4_exit_mballoc(); | 5309 | ext4_exit_mballoc(); |
| 5709 | ext4_exit_feat_adverts(); | 5310 | ext4_exit_sysfs(); |
| 5710 | remove_proc_entry("fs/ext4", NULL); | ||
| 5711 | kset_unregister(ext4_kset); | ||
| 5712 | ext4_exit_system_zone(); | 5311 | ext4_exit_system_zone(); |
| 5713 | ext4_exit_pageio(); | 5312 | ext4_exit_pageio(); |
| 5714 | ext4_exit_es(); | 5313 | ext4_exit_es(); |
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index c677f2c1044b..abe2401ce405 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c | |||
| @@ -57,7 +57,7 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook | |||
| 57 | sizeof(struct ext4_encrypted_symlink_data) - 1) > | 57 | sizeof(struct ext4_encrypted_symlink_data) - 1) > |
| 58 | max_size) { | 58 | max_size) { |
| 59 | /* Symlink data on the disk is corrupted */ | 59 | /* Symlink data on the disk is corrupted */ |
| 60 | res = -EIO; | 60 | res = -EFSCORRUPTED; |
| 61 | goto errout; | 61 | goto errout; |
| 62 | } | 62 | } |
| 63 | plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ? | 63 | plen = (cstr.len < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2) ? |
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c new file mode 100644 index 000000000000..1b57c72f4a00 --- /dev/null +++ b/fs/ext4/sysfs.c | |||
| @@ -0,0 +1,448 @@ | |||
| 1 | /* | ||
| 2 | * linux/fs/ext4/sysfs.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
| 5 | * Remy Card (card@masi.ibp.fr) | ||
| 6 | * Theodore Ts'o (tytso@mit.edu) | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/time.h> | ||
| 11 | #include <linux/fs.h> | ||
| 12 | #include <linux/seq_file.h> | ||
| 13 | #include <linux/proc_fs.h> | ||
| 14 | |||
| 15 | #include "ext4.h" | ||
| 16 | #include "ext4_jbd2.h" | ||
| 17 | |||
| 18 | typedef enum { | ||
| 19 | attr_noop, | ||
| 20 | attr_delayed_allocation_blocks, | ||
| 21 | attr_session_write_kbytes, | ||
| 22 | attr_lifetime_write_kbytes, | ||
| 23 | attr_reserved_clusters, | ||
| 24 | attr_inode_readahead, | ||
| 25 | attr_trigger_test_error, | ||
| 26 | attr_feature, | ||
| 27 | attr_pointer_ui, | ||
| 28 | attr_pointer_atomic, | ||
| 29 | } attr_id_t; | ||
| 30 | |||
| 31 | typedef enum { | ||
| 32 | ptr_explicit, | ||
| 33 | ptr_ext4_sb_info_offset, | ||
| 34 | ptr_ext4_super_block_offset, | ||
| 35 | } attr_ptr_t; | ||
| 36 | |||
| 37 | static const char *proc_dirname = "fs/ext4"; | ||
| 38 | static struct proc_dir_entry *ext4_proc_root; | ||
| 39 | |||
| 40 | struct ext4_attr { | ||
| 41 | struct attribute attr; | ||
| 42 | short attr_id; | ||
| 43 | short attr_ptr; | ||
| 44 | union { | ||
| 45 | int offset; | ||
| 46 | void *explicit_ptr; | ||
| 47 | } u; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static ssize_t session_write_kbytes_show(struct ext4_attr *a, | ||
| 51 | struct ext4_sb_info *sbi, char *buf) | ||
| 52 | { | ||
| 53 | struct super_block *sb = sbi->s_buddy_cache->i_sb; | ||
| 54 | |||
| 55 | if (!sb->s_bdev->bd_part) | ||
| 56 | return snprintf(buf, PAGE_SIZE, "0\n"); | ||
| 57 | return snprintf(buf, PAGE_SIZE, "%lu\n", | ||
| 58 | (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | ||
| 59 | sbi->s_sectors_written_start) >> 1); | ||
| 60 | } | ||
| 61 | |||
| 62 | static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, | ||
| 63 | struct ext4_sb_info *sbi, char *buf) | ||
| 64 | { | ||
| 65 | struct super_block *sb = sbi->s_buddy_cache->i_sb; | ||
| 66 | |||
| 67 | if (!sb->s_bdev->bd_part) | ||
| 68 | return snprintf(buf, PAGE_SIZE, "0\n"); | ||
| 69 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 70 | (unsigned long long)(sbi->s_kbytes_written + | ||
| 71 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | ||
| 72 | EXT4_SB(sb)->s_sectors_written_start) >> 1))); | ||
| 73 | } | ||
| 74 | |||
| 75 | static ssize_t inode_readahead_blks_store(struct ext4_attr *a, | ||
| 76 | struct ext4_sb_info *sbi, | ||
| 77 | const char *buf, size_t count) | ||
| 78 | { | ||
| 79 | unsigned long t; | ||
| 80 | int ret; | ||
| 81 | |||
| 82 | ret = kstrtoul(skip_spaces(buf), 0, &t); | ||
| 83 | if (ret) | ||
| 84 | return ret; | ||
| 85 | |||
| 86 | if (t && (!is_power_of_2(t) || t > 0x40000000)) | ||
| 87 | return -EINVAL; | ||
| 88 | |||
| 89 | sbi->s_inode_readahead_blks = t; | ||
| 90 | return count; | ||
| 91 | } | ||
| 92 | |||
| 93 | static ssize_t reserved_clusters_store(struct ext4_attr *a, | ||
| 94 | struct ext4_sb_info *sbi, | ||
| 95 | const char *buf, size_t count) | ||
| 96 | { | ||
| 97 | unsigned long long val; | ||
| 98 | ext4_fsblk_t clusters = (ext4_blocks_count(sbi->s_es) >> | ||
| 99 | sbi->s_cluster_bits); | ||
| 100 | int ret; | ||
| 101 | |||
| 102 | ret = kstrtoull(skip_spaces(buf), 0, &val); | ||
| 103 | if (!ret || val >= clusters) | ||
| 104 | return -EINVAL; | ||
| 105 | |||
| 106 | atomic64_set(&sbi->s_resv_clusters, val); | ||
| 107 | return count; | ||
| 108 | } | ||
| 109 | |||
| 110 | static ssize_t trigger_test_error(struct ext4_attr *a, | ||
| 111 | struct ext4_sb_info *sbi, | ||
| 112 | const char *buf, size_t count) | ||
| 113 | { | ||
| 114 | int len = count; | ||
| 115 | |||
| 116 | if (!capable(CAP_SYS_ADMIN)) | ||
| 117 | return -EPERM; | ||
| 118 | |||
| 119 | if (len && buf[len-1] == '\n') | ||
| 120 | len--; | ||
| 121 | |||
| 122 | if (len) | ||
| 123 | ext4_error(sbi->s_sb, "%.*s", len, buf); | ||
| 124 | return count; | ||
| 125 | } | ||
| 126 | |||
| 127 | #define EXT4_ATTR(_name,_mode,_id) \ | ||
| 128 | static struct ext4_attr ext4_attr_##_name = { \ | ||
| 129 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 130 | .attr_id = attr_##_id, \ | ||
| 131 | } | ||
| 132 | |||
| 133 | #define EXT4_ATTR_FUNC(_name,_mode) EXT4_ATTR(_name,_mode,_name) | ||
| 134 | |||
| 135 | #define EXT4_ATTR_FEATURE(_name) EXT4_ATTR(_name, 0444, feature) | ||
| 136 | |||
| 137 | #define EXT4_ATTR_OFFSET(_name,_mode,_id,_struct,_elname) \ | ||
| 138 | static struct ext4_attr ext4_attr_##_name = { \ | ||
| 139 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 140 | .attr_id = attr_##_id, \ | ||
| 141 | .attr_ptr = ptr_##_struct##_offset, \ | ||
| 142 | .u = { \ | ||
| 143 | .offset = offsetof(struct _struct, _elname),\ | ||
| 144 | }, \ | ||
| 145 | } | ||
| 146 | |||
| 147 | #define EXT4_RO_ATTR_ES_UI(_name,_elname) \ | ||
| 148 | EXT4_ATTR_OFFSET(_name, 0444, pointer_ui, ext4_super_block, _elname) | ||
| 149 | |||
| 150 | #define EXT4_RW_ATTR_SBI_UI(_name,_elname) \ | ||
| 151 | EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname) | ||
| 152 | |||
| 153 | #define EXT4_ATTR_PTR(_name,_mode,_id,_ptr) \ | ||
| 154 | static struct ext4_attr ext4_attr_##_name = { \ | ||
| 155 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | ||
| 156 | .attr_id = attr_##_id, \ | ||
| 157 | .attr_ptr = ptr_explicit, \ | ||
| 158 | .u = { \ | ||
| 159 | .explicit_ptr = _ptr, \ | ||
| 160 | }, \ | ||
| 161 | } | ||
| 162 | |||
| 163 | #define ATTR_LIST(name) &ext4_attr_##name.attr | ||
| 164 | |||
| 165 | EXT4_ATTR_FUNC(delayed_allocation_blocks, 0444); | ||
| 166 | EXT4_ATTR_FUNC(session_write_kbytes, 0444); | ||
| 167 | EXT4_ATTR_FUNC(lifetime_write_kbytes, 0444); | ||
| 168 | EXT4_ATTR_FUNC(reserved_clusters, 0644); | ||
| 169 | |||
| 170 | EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead, | ||
| 171 | ext4_sb_info, s_inode_readahead_blks); | ||
| 172 | EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); | ||
| 173 | EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats); | ||
| 174 | EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan); | ||
| 175 | EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); | ||
| 176 | EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); | ||
| 177 | EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); | ||
| 178 | EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); | ||
| 179 | EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb); | ||
| 180 | EXT4_ATTR(trigger_fs_error, 0200, trigger_test_error); | ||
| 181 | EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); | ||
| 182 | EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); | ||
| 183 | EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); | ||
| 184 | EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); | ||
| 185 | EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); | ||
| 186 | EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); | ||
| 187 | EXT4_RO_ATTR_ES_UI(errors_count, s_error_count); | ||
| 188 | EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time); | ||
| 189 | EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time); | ||
| 190 | |||
| 191 | static unsigned int old_bump_val = 128; | ||
| 192 | EXT4_ATTR_PTR(max_writeback_mb_bump, 0444, pointer_ui, &old_bump_val); | ||
| 193 | |||
| 194 | static struct attribute *ext4_attrs[] = { | ||
| 195 | ATTR_LIST(delayed_allocation_blocks), | ||
| 196 | ATTR_LIST(session_write_kbytes), | ||
| 197 | ATTR_LIST(lifetime_write_kbytes), | ||
| 198 | ATTR_LIST(reserved_clusters), | ||
| 199 | ATTR_LIST(inode_readahead_blks), | ||
| 200 | ATTR_LIST(inode_goal), | ||
| 201 | ATTR_LIST(mb_stats), | ||
| 202 | ATTR_LIST(mb_max_to_scan), | ||
| 203 | ATTR_LIST(mb_min_to_scan), | ||
| 204 | ATTR_LIST(mb_order2_req), | ||
| 205 | ATTR_LIST(mb_stream_req), | ||
| 206 | ATTR_LIST(mb_group_prealloc), | ||
| 207 | ATTR_LIST(max_writeback_mb_bump), | ||
| 208 | ATTR_LIST(extent_max_zeroout_kb), | ||
| 209 | ATTR_LIST(trigger_fs_error), | ||
| 210 | ATTR_LIST(err_ratelimit_interval_ms), | ||
| 211 | ATTR_LIST(err_ratelimit_burst), | ||
| 212 | ATTR_LIST(warning_ratelimit_interval_ms), | ||
| 213 | ATTR_LIST(warning_ratelimit_burst), | ||
| 214 | ATTR_LIST(msg_ratelimit_interval_ms), | ||
| 215 | ATTR_LIST(msg_ratelimit_burst), | ||
| 216 | ATTR_LIST(errors_count), | ||
| 217 | ATTR_LIST(first_error_time), | ||
| 218 | ATTR_LIST(last_error_time), | ||
| 219 | NULL, | ||
| 220 | }; | ||
| 221 | |||
| 222 | /* Features this copy of ext4 supports */ | ||
| 223 | EXT4_ATTR_FEATURE(lazy_itable_init); | ||
| 224 | EXT4_ATTR_FEATURE(batched_discard); | ||
| 225 | EXT4_ATTR_FEATURE(meta_bg_resize); | ||
| 226 | EXT4_ATTR_FEATURE(encryption); | ||
| 227 | EXT4_ATTR_FEATURE(metadata_csum_seed); | ||
| 228 | |||
| 229 | static struct attribute *ext4_feat_attrs[] = { | ||
| 230 | ATTR_LIST(lazy_itable_init), | ||
| 231 | ATTR_LIST(batched_discard), | ||
| 232 | ATTR_LIST(meta_bg_resize), | ||
| 233 | ATTR_LIST(encryption), | ||
| 234 | ATTR_LIST(metadata_csum_seed), | ||
| 235 | NULL, | ||
| 236 | }; | ||
| 237 | |||
| 238 | static void *calc_ptr(struct ext4_attr *a, struct ext4_sb_info *sbi) | ||
| 239 | { | ||
| 240 | switch (a->attr_ptr) { | ||
| 241 | case ptr_explicit: | ||
| 242 | return a->u.explicit_ptr; | ||
| 243 | case ptr_ext4_sb_info_offset: | ||
| 244 | return (void *) (((char *) sbi) + a->u.offset); | ||
| 245 | case ptr_ext4_super_block_offset: | ||
| 246 | return (void *) (((char *) sbi->s_es) + a->u.offset); | ||
| 247 | } | ||
| 248 | return NULL; | ||
| 249 | } | ||
| 250 | |||
| 251 | static ssize_t ext4_attr_show(struct kobject *kobj, | ||
| 252 | struct attribute *attr, char *buf) | ||
| 253 | { | ||
| 254 | struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, | ||
| 255 | s_kobj); | ||
| 256 | struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); | ||
| 257 | void *ptr = calc_ptr(a, sbi); | ||
| 258 | |||
| 259 | switch (a->attr_id) { | ||
| 260 | case attr_delayed_allocation_blocks: | ||
| 261 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 262 | (s64) EXT4_C2B(sbi, | ||
| 263 | percpu_counter_sum(&sbi->s_dirtyclusters_counter))); | ||
| 264 | case attr_session_write_kbytes: | ||
| 265 | return session_write_kbytes_show(a, sbi, buf); | ||
| 266 | case attr_lifetime_write_kbytes: | ||
| 267 | return lifetime_write_kbytes_show(a, sbi, buf); | ||
| 268 | case attr_reserved_clusters: | ||
| 269 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 270 | (unsigned long long) | ||
| 271 | atomic64_read(&sbi->s_resv_clusters)); | ||
| 272 | case attr_inode_readahead: | ||
| 273 | case attr_pointer_ui: | ||
| 274 | if (!ptr) | ||
| 275 | return 0; | ||
| 276 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
| 277 | *((unsigned int *) ptr)); | ||
| 278 | case attr_pointer_atomic: | ||
| 279 | if (!ptr) | ||
| 280 | return 0; | ||
| 281 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
| 282 | atomic_read((atomic_t *) ptr)); | ||
| 283 | case attr_feature: | ||
| 284 | return snprintf(buf, PAGE_SIZE, "supported\n"); | ||
| 285 | } | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static ssize_t ext4_attr_store(struct kobject *kobj, | ||
| 291 | struct attribute *attr, | ||
| 292 | const char *buf, size_t len) | ||
| 293 | { | ||
| 294 | struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, | ||
| 295 | s_kobj); | ||
| 296 | struct ext4_attr *a = container_of(attr, struct ext4_attr, attr); | ||
| 297 | void *ptr = calc_ptr(a, sbi); | ||
| 298 | unsigned long t; | ||
| 299 | int ret; | ||
| 300 | |||
| 301 | switch (a->attr_id) { | ||
| 302 | case attr_reserved_clusters: | ||
| 303 | return reserved_clusters_store(a, sbi, buf, len); | ||
| 304 | case attr_pointer_ui: | ||
| 305 | if (!ptr) | ||
| 306 | return 0; | ||
| 307 | ret = kstrtoul(skip_spaces(buf), 0, &t); | ||
| 308 | if (ret) | ||
| 309 | return ret; | ||
| 310 | *((unsigned int *) ptr) = t; | ||
| 311 | return len; | ||
| 312 | case attr_inode_readahead: | ||
| 313 | return inode_readahead_blks_store(a, sbi, buf, len); | ||
| 314 | case attr_trigger_test_error: | ||
| 315 | return trigger_test_error(a, sbi, buf, len); | ||
| 316 | } | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | static void ext4_sb_release(struct kobject *kobj) | ||
| 321 | { | ||
| 322 | struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info, | ||
| 323 | s_kobj); | ||
| 324 | complete(&sbi->s_kobj_unregister); | ||
| 325 | } | ||
| 326 | |||
| 327 | static const struct sysfs_ops ext4_attr_ops = { | ||
| 328 | .show = ext4_attr_show, | ||
| 329 | .store = ext4_attr_store, | ||
| 330 | }; | ||
| 331 | |||
| 332 | static struct kobj_type ext4_sb_ktype = { | ||
| 333 | .default_attrs = ext4_attrs, | ||
| 334 | .sysfs_ops = &ext4_attr_ops, | ||
| 335 | .release = ext4_sb_release, | ||
| 336 | }; | ||
| 337 | |||
| 338 | static struct kobj_type ext4_ktype = { | ||
| 339 | .sysfs_ops = &ext4_attr_ops, | ||
| 340 | }; | ||
| 341 | |||
| 342 | static struct kset ext4_kset = { | ||
| 343 | .kobj = {.ktype = &ext4_ktype}, | ||
| 344 | }; | ||
| 345 | |||
| 346 | static struct kobj_type ext4_feat_ktype = { | ||
| 347 | .default_attrs = ext4_feat_attrs, | ||
| 348 | .sysfs_ops = &ext4_attr_ops, | ||
| 349 | }; | ||
| 350 | |||
| 351 | static struct kobject ext4_feat = { | ||
| 352 | .kset = &ext4_kset, | ||
| 353 | }; | ||
| 354 | |||
| 355 | #define PROC_FILE_SHOW_DEFN(name) \ | ||
| 356 | static int name##_open(struct inode *inode, struct file *file) \ | ||
| 357 | { \ | ||
| 358 | return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \ | ||
| 359 | } \ | ||
| 360 | \ | ||
| 361 | const struct file_operations ext4_seq_##name##_fops = { \ | ||
| 362 | .owner = THIS_MODULE, \ | ||
| 363 | .open = name##_open, \ | ||
| 364 | .read = seq_read, \ | ||
| 365 | .llseek = seq_lseek, \ | ||
| 366 | .release = single_release, \ | ||
| 367 | } | ||
| 368 | |||
| 369 | #define PROC_FILE_LIST(name) \ | ||
| 370 | { __stringify(name), &ext4_seq_##name##_fops } | ||
| 371 | |||
| 372 | PROC_FILE_SHOW_DEFN(es_shrinker_info); | ||
| 373 | PROC_FILE_SHOW_DEFN(options); | ||
| 374 | |||
| 375 | static struct ext4_proc_files { | ||
| 376 | const char *name; | ||
| 377 | const struct file_operations *fops; | ||
| 378 | } proc_files[] = { | ||
| 379 | PROC_FILE_LIST(options), | ||
| 380 | PROC_FILE_LIST(es_shrinker_info), | ||
| 381 | PROC_FILE_LIST(mb_groups), | ||
| 382 | { NULL, NULL }, | ||
| 383 | }; | ||
| 384 | |||
| 385 | int ext4_register_sysfs(struct super_block *sb) | ||
| 386 | { | ||
| 387 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 388 | struct ext4_proc_files *p; | ||
| 389 | int err; | ||
| 390 | |||
| 391 | sbi->s_kobj.kset = &ext4_kset; | ||
| 392 | init_completion(&sbi->s_kobj_unregister); | ||
| 393 | err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL, | ||
| 394 | "%s", sb->s_id); | ||
| 395 | if (err) | ||
| 396 | return err; | ||
| 397 | |||
| 398 | if (ext4_proc_root) | ||
| 399 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | ||
| 400 | |||
| 401 | if (sbi->s_proc) { | ||
| 402 | for (p = proc_files; p->name; p++) | ||
| 403 | proc_create_data(p->name, S_IRUGO, sbi->s_proc, | ||
| 404 | p->fops, sb); | ||
| 405 | } | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | void ext4_unregister_sysfs(struct super_block *sb) | ||
| 410 | { | ||
| 411 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 412 | struct ext4_proc_files *p; | ||
| 413 | |||
| 414 | if (sbi->s_proc) { | ||
| 415 | for (p = proc_files; p->name; p++) | ||
| 416 | remove_proc_entry(p->name, sbi->s_proc); | ||
| 417 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
| 418 | } | ||
| 419 | kobject_del(&sbi->s_kobj); | ||
| 420 | } | ||
| 421 | |||
| 422 | int __init ext4_init_sysfs(void) | ||
| 423 | { | ||
| 424 | int ret; | ||
| 425 | |||
| 426 | kobject_set_name(&ext4_kset.kobj, "ext4"); | ||
| 427 | ext4_kset.kobj.parent = fs_kobj; | ||
| 428 | ret = kset_register(&ext4_kset); | ||
| 429 | if (ret) | ||
| 430 | return ret; | ||
| 431 | |||
| 432 | ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype, | ||
| 433 | NULL, "features"); | ||
| 434 | if (ret) | ||
| 435 | kset_unregister(&ext4_kset); | ||
| 436 | else | ||
| 437 | ext4_proc_root = proc_mkdir(proc_dirname, NULL); | ||
| 438 | return ret; | ||
| 439 | } | ||
| 440 | |||
| 441 | void ext4_exit_sysfs(void) | ||
| 442 | { | ||
| 443 | kobject_put(&ext4_feat); | ||
| 444 | kset_unregister(&ext4_kset); | ||
| 445 | remove_proc_entry(proc_dirname, NULL); | ||
| 446 | ext4_proc_root = NULL; | ||
| 447 | } | ||
| 448 | |||
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 16e28c08d1e8..984448c6f5f0 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
| @@ -195,7 +195,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, | |||
| 195 | while (!IS_LAST_ENTRY(e)) { | 195 | while (!IS_LAST_ENTRY(e)) { |
| 196 | struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); | 196 | struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); |
| 197 | if ((void *)next >= end) | 197 | if ((void *)next >= end) |
| 198 | return -EIO; | 198 | return -EFSCORRUPTED; |
| 199 | e = next; | 199 | e = next; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| @@ -205,7 +205,7 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, | |||
| 205 | (void *)e + sizeof(__u32) || | 205 | (void *)e + sizeof(__u32) || |
| 206 | value_start + le16_to_cpu(entry->e_value_offs) + | 206 | value_start + le16_to_cpu(entry->e_value_offs) + |
| 207 | le32_to_cpu(entry->e_value_size) > end)) | 207 | le32_to_cpu(entry->e_value_size) > end)) |
| 208 | return -EIO; | 208 | return -EFSCORRUPTED; |
| 209 | entry = EXT4_XATTR_NEXT(entry); | 209 | entry = EXT4_XATTR_NEXT(entry); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| @@ -222,9 +222,9 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) | |||
| 222 | 222 | ||
| 223 | if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || | 223 | if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || |
| 224 | BHDR(bh)->h_blocks != cpu_to_le32(1)) | 224 | BHDR(bh)->h_blocks != cpu_to_le32(1)) |
| 225 | return -EIO; | 225 | return -EFSCORRUPTED; |
| 226 | if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) | 226 | if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) |
| 227 | return -EIO; | 227 | return -EFSBADCRC; |
| 228 | error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, | 228 | error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, |
| 229 | bh->b_data); | 229 | bh->b_data); |
| 230 | if (!error) | 230 | if (!error) |
| @@ -239,7 +239,7 @@ ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) | |||
| 239 | 239 | ||
| 240 | if (entry->e_value_block != 0 || value_size > size || | 240 | if (entry->e_value_block != 0 || value_size > size || |
| 241 | le16_to_cpu(entry->e_value_offs) + value_size > size) | 241 | le16_to_cpu(entry->e_value_offs) + value_size > size) |
| 242 | return -EIO; | 242 | return -EFSCORRUPTED; |
| 243 | return 0; | 243 | return 0; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| @@ -266,7 +266,7 @@ ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index, | |||
| 266 | } | 266 | } |
| 267 | *pentry = entry; | 267 | *pentry = entry; |
| 268 | if (!cmp && ext4_xattr_check_entry(entry, size)) | 268 | if (!cmp && ext4_xattr_check_entry(entry, size)) |
| 269 | return -EIO; | 269 | return -EFSCORRUPTED; |
| 270 | return cmp ? -ENODATA : 0; | 270 | return cmp ? -ENODATA : 0; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| @@ -297,13 +297,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, | |||
| 297 | bad_block: | 297 | bad_block: |
| 298 | EXT4_ERROR_INODE(inode, "bad block %llu", | 298 | EXT4_ERROR_INODE(inode, "bad block %llu", |
| 299 | EXT4_I(inode)->i_file_acl); | 299 | EXT4_I(inode)->i_file_acl); |
| 300 | error = -EIO; | 300 | error = -EFSCORRUPTED; |
| 301 | goto cleanup; | 301 | goto cleanup; |
| 302 | } | 302 | } |
| 303 | ext4_xattr_cache_insert(ext4_mb_cache, bh); | 303 | ext4_xattr_cache_insert(ext4_mb_cache, bh); |
| 304 | entry = BFIRST(bh); | 304 | entry = BFIRST(bh); |
| 305 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); | 305 | error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); |
| 306 | if (error == -EIO) | 306 | if (error == -EFSCORRUPTED) |
| 307 | goto bad_block; | 307 | goto bad_block; |
| 308 | if (error) | 308 | if (error) |
| 309 | goto cleanup; | 309 | goto cleanup; |
| @@ -445,7 +445,7 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
| 445 | if (ext4_xattr_check_block(inode, bh)) { | 445 | if (ext4_xattr_check_block(inode, bh)) { |
| 446 | EXT4_ERROR_INODE(inode, "bad block %llu", | 446 | EXT4_ERROR_INODE(inode, "bad block %llu", |
| 447 | EXT4_I(inode)->i_file_acl); | 447 | EXT4_I(inode)->i_file_acl); |
| 448 | error = -EIO; | 448 | error = -EFSCORRUPTED; |
| 449 | goto cleanup; | 449 | goto cleanup; |
| 450 | } | 450 | } |
| 451 | ext4_xattr_cache_insert(ext4_mb_cache, bh); | 451 | ext4_xattr_cache_insert(ext4_mb_cache, bh); |
| @@ -525,12 +525,12 @@ errout: | |||
| 525 | static void ext4_xattr_update_super_block(handle_t *handle, | 525 | static void ext4_xattr_update_super_block(handle_t *handle, |
| 526 | struct super_block *sb) | 526 | struct super_block *sb) |
| 527 | { | 527 | { |
| 528 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR)) | 528 | if (ext4_has_feature_xattr(sb)) |
| 529 | return; | 529 | return; |
| 530 | 530 | ||
| 531 | BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access"); | 531 | BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access"); |
| 532 | if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { | 532 | if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { |
| 533 | EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR); | 533 | ext4_set_feature_xattr(sb); |
| 534 | ext4_handle_dirty_super(handle, sb); | 534 | ext4_handle_dirty_super(handle, sb); |
| 535 | } | 535 | } |
| 536 | } | 536 | } |
| @@ -751,7 +751,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i, | |||
| 751 | if (ext4_xattr_check_block(inode, bs->bh)) { | 751 | if (ext4_xattr_check_block(inode, bs->bh)) { |
| 752 | EXT4_ERROR_INODE(inode, "bad block %llu", | 752 | EXT4_ERROR_INODE(inode, "bad block %llu", |
| 753 | EXT4_I(inode)->i_file_acl); | 753 | EXT4_I(inode)->i_file_acl); |
| 754 | error = -EIO; | 754 | error = -EFSCORRUPTED; |
| 755 | goto cleanup; | 755 | goto cleanup; |
| 756 | } | 756 | } |
| 757 | /* Find the named attribute. */ | 757 | /* Find the named attribute. */ |
| @@ -811,7 +811,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
| 811 | bs->bh); | 811 | bs->bh); |
| 812 | } | 812 | } |
| 813 | unlock_buffer(bs->bh); | 813 | unlock_buffer(bs->bh); |
| 814 | if (error == -EIO) | 814 | if (error == -EFSCORRUPTED) |
| 815 | goto bad_block; | 815 | goto bad_block; |
| 816 | if (!error) | 816 | if (!error) |
| 817 | error = ext4_handle_dirty_xattr_block(handle, | 817 | error = ext4_handle_dirty_xattr_block(handle, |
| @@ -855,7 +855,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, | |||
| 855 | } | 855 | } |
| 856 | 856 | ||
| 857 | error = ext4_xattr_set_entry(i, s); | 857 | error = ext4_xattr_set_entry(i, s); |
| 858 | if (error == -EIO) | 858 | if (error == -EFSCORRUPTED) |
| 859 | goto bad_block; | 859 | goto bad_block; |
| 860 | if (error) | 860 | if (error) |
| 861 | goto cleanup; | 861 | goto cleanup; |
| @@ -1314,7 +1314,7 @@ retry: | |||
| 1314 | if (ext4_xattr_check_block(inode, bh)) { | 1314 | if (ext4_xattr_check_block(inode, bh)) { |
| 1315 | EXT4_ERROR_INODE(inode, "bad block %llu", | 1315 | EXT4_ERROR_INODE(inode, "bad block %llu", |
| 1316 | EXT4_I(inode)->i_file_acl); | 1316 | EXT4_I(inode)->i_file_acl); |
| 1317 | error = -EIO; | 1317 | error = -EFSCORRUPTED; |
| 1318 | goto cleanup; | 1318 | goto cleanup; |
| 1319 | } | 1319 | } |
| 1320 | base = BHDR(bh); | 1320 | base = BHDR(bh); |
| @@ -1579,7 +1579,7 @@ ext4_xattr_cmp(struct ext4_xattr_header *header1, | |||
| 1579 | memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) | 1579 | memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) |
| 1580 | return 1; | 1580 | return 1; |
| 1581 | if (entry1->e_value_block != 0 || entry2->e_value_block != 0) | 1581 | if (entry1->e_value_block != 0 || entry2->e_value_block != 0) |
| 1582 | return -EIO; | 1582 | return -EFSCORRUPTED; |
| 1583 | if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), | 1583 | if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), |
| 1584 | (char *)header2 + le16_to_cpu(entry2->e_value_offs), | 1584 | (char *)header2 + le16_to_cpu(entry2->e_value_offs), |
| 1585 | le32_to_cpu(entry1->e_value_size))) | 1585 | le32_to_cpu(entry1->e_value_size))) |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 8c44654ce274..684996c8a3a4 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
| @@ -427,7 +427,6 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) | |||
| 427 | struct journal_head *last_jh; | 427 | struct journal_head *last_jh; |
| 428 | struct journal_head *next_jh = jh; | 428 | struct journal_head *next_jh = jh; |
| 429 | int ret; | 429 | int ret; |
| 430 | int freed = 0; | ||
| 431 | 430 | ||
| 432 | if (!jh) | 431 | if (!jh) |
| 433 | return 0; | 432 | return 0; |
| @@ -441,10 +440,9 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) | |||
| 441 | else | 440 | else |
| 442 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; | 441 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; |
| 443 | if (!ret) | 442 | if (!ret) |
| 444 | return freed; | 443 | return 0; |
| 445 | if (ret == 2) | 444 | if (ret == 2) |
| 446 | return 1; | 445 | return 1; |
| 447 | freed = 1; | ||
| 448 | /* | 446 | /* |
| 449 | * This function only frees up some memory | 447 | * This function only frees up some memory |
| 450 | * if possible so we dont have an obligation | 448 | * if possible so we dont have an obligation |
| @@ -452,10 +450,10 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy) | |||
| 452 | * requested: | 450 | * requested: |
| 453 | */ | 451 | */ |
| 454 | if (need_resched()) | 452 | if (need_resched()) |
| 455 | return freed; | 453 | return 0; |
| 456 | } while (jh != last_jh); | 454 | } while (jh != last_jh); |
| 457 | 455 | ||
| 458 | return freed; | 456 | return 0; |
| 459 | } | 457 | } |
| 460 | 458 | ||
| 461 | /* | 459 | /* |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 362e5f614450..36345fefa3ff 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -142,8 +142,7 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 142 | tmp->h_commit_sec = cpu_to_be64(now.tv_sec); | 142 | tmp->h_commit_sec = cpu_to_be64(now.tv_sec); |
| 143 | tmp->h_commit_nsec = cpu_to_be32(now.tv_nsec); | 143 | tmp->h_commit_nsec = cpu_to_be32(now.tv_nsec); |
| 144 | 144 | ||
| 145 | if (JBD2_HAS_COMPAT_FEATURE(journal, | 145 | if (jbd2_has_feature_checksum(journal)) { |
| 146 | JBD2_FEATURE_COMPAT_CHECKSUM)) { | ||
| 147 | tmp->h_chksum_type = JBD2_CRC32_CHKSUM; | 146 | tmp->h_chksum_type = JBD2_CRC32_CHKSUM; |
| 148 | tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; | 147 | tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; |
| 149 | tmp->h_chksum[0] = cpu_to_be32(crc32_sum); | 148 | tmp->h_chksum[0] = cpu_to_be32(crc32_sum); |
| @@ -157,8 +156,7 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 157 | bh->b_end_io = journal_end_buffer_io_sync; | 156 | bh->b_end_io = journal_end_buffer_io_sync; |
| 158 | 157 | ||
| 159 | if (journal->j_flags & JBD2_BARRIER && | 158 | if (journal->j_flags & JBD2_BARRIER && |
| 160 | !JBD2_HAS_INCOMPAT_FEATURE(journal, | 159 | !jbd2_has_feature_async_commit(journal)) |
| 161 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) | ||
| 162 | ret = submit_bh(WRITE_SYNC | WRITE_FLUSH_FUA, bh); | 160 | ret = submit_bh(WRITE_SYNC | WRITE_FLUSH_FUA, bh); |
| 163 | else | 161 | else |
| 164 | ret = submit_bh(WRITE_SYNC, bh); | 162 | ret = submit_bh(WRITE_SYNC, bh); |
| @@ -317,7 +315,7 @@ static void write_tag_block(journal_t *j, journal_block_tag_t *tag, | |||
| 317 | unsigned long long block) | 315 | unsigned long long block) |
| 318 | { | 316 | { |
| 319 | tag->t_blocknr = cpu_to_be32(block & (u32)~0); | 317 | tag->t_blocknr = cpu_to_be32(block & (u32)~0); |
| 320 | if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_64BIT)) | 318 | if (jbd2_has_feature_64bit(j)) |
| 321 | tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); | 319 | tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); |
| 322 | } | 320 | } |
| 323 | 321 | ||
| @@ -356,7 +354,7 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, | |||
| 356 | bh->b_size); | 354 | bh->b_size); |
| 357 | kunmap_atomic(addr); | 355 | kunmap_atomic(addr); |
| 358 | 356 | ||
| 359 | if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) | 357 | if (jbd2_has_feature_csum3(j)) |
| 360 | tag3->t_checksum = cpu_to_be32(csum32); | 358 | tag3->t_checksum = cpu_to_be32(csum32); |
| 361 | else | 359 | else |
| 362 | tag->t_checksum = cpu_to_be16(csum32); | 360 | tag->t_checksum = cpu_to_be16(csum32); |
| @@ -730,8 +728,7 @@ start_journal_io: | |||
| 730 | /* | 728 | /* |
| 731 | * Compute checksum. | 729 | * Compute checksum. |
| 732 | */ | 730 | */ |
| 733 | if (JBD2_HAS_COMPAT_FEATURE(journal, | 731 | if (jbd2_has_feature_checksum(journal)) { |
| 734 | JBD2_FEATURE_COMPAT_CHECKSUM)) { | ||
| 735 | crc32_sum = | 732 | crc32_sum = |
| 736 | jbd2_checksum_data(crc32_sum, bh); | 733 | jbd2_checksum_data(crc32_sum, bh); |
| 737 | } | 734 | } |
| @@ -797,8 +794,7 @@ start_journal_io: | |||
| 797 | blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); | 794 | blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); |
| 798 | 795 | ||
| 799 | /* Done it all: now write the commit record asynchronously. */ | 796 | /* Done it all: now write the commit record asynchronously. */ |
| 800 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 797 | if (jbd2_has_feature_async_commit(journal)) { |
| 801 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | ||
| 802 | err = journal_submit_commit_record(journal, commit_transaction, | 798 | err = journal_submit_commit_record(journal, commit_transaction, |
| 803 | &cbh, crc32_sum); | 799 | &cbh, crc32_sum); |
| 804 | if (err) | 800 | if (err) |
| @@ -889,8 +885,7 @@ start_journal_io: | |||
| 889 | commit_transaction->t_state = T_COMMIT_JFLUSH; | 885 | commit_transaction->t_state = T_COMMIT_JFLUSH; |
| 890 | write_unlock(&journal->j_state_lock); | 886 | write_unlock(&journal->j_state_lock); |
| 891 | 887 | ||
| 892 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 888 | if (!jbd2_has_feature_async_commit(journal)) { |
| 893 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | ||
| 894 | err = journal_submit_commit_record(journal, commit_transaction, | 889 | err = journal_submit_commit_record(journal, commit_transaction, |
| 895 | &cbh, crc32_sum); | 890 | &cbh, crc32_sum); |
| 896 | if (err) | 891 | if (err) |
| @@ -898,8 +893,7 @@ start_journal_io: | |||
| 898 | } | 893 | } |
| 899 | if (cbh) | 894 | if (cbh) |
| 900 | err = journal_wait_on_commit_record(journal, cbh); | 895 | err = journal_wait_on_commit_record(journal, cbh); |
| 901 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 896 | if (jbd2_has_feature_async_commit(journal) && |
| 902 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && | ||
| 903 | journal->j_flags & JBD2_BARRIER) { | 897 | journal->j_flags & JBD2_BARRIER) { |
| 904 | blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); | 898 | blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); |
| 905 | } | 899 | } |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 8270fe9e3641..81e622681c82 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -124,7 +124,7 @@ EXPORT_SYMBOL(__jbd2_debug); | |||
| 124 | /* Checksumming functions */ | 124 | /* Checksumming functions */ |
| 125 | static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) | 125 | static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) |
| 126 | { | 126 | { |
| 127 | if (!jbd2_journal_has_csum_v2or3(j)) | 127 | if (!jbd2_journal_has_csum_v2or3_feature(j)) |
| 128 | return 1; | 128 | return 1; |
| 129 | 129 | ||
| 130 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; | 130 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; |
| @@ -1523,16 +1523,16 @@ static int journal_get_superblock(journal_t *journal) | |||
| 1523 | goto out; | 1523 | goto out; |
| 1524 | } | 1524 | } |
| 1525 | 1525 | ||
| 1526 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) && | 1526 | if (jbd2_has_feature_csum2(journal) && |
| 1527 | JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) { | 1527 | jbd2_has_feature_csum3(journal)) { |
| 1528 | /* Can't have checksum v2 and v3 at the same time! */ | 1528 | /* Can't have checksum v2 and v3 at the same time! */ |
| 1529 | printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 " | 1529 | printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 " |
| 1530 | "at the same time!\n"); | 1530 | "at the same time!\n"); |
| 1531 | goto out; | 1531 | goto out; |
| 1532 | } | 1532 | } |
| 1533 | 1533 | ||
| 1534 | if (jbd2_journal_has_csum_v2or3(journal) && | 1534 | if (jbd2_journal_has_csum_v2or3_feature(journal) && |
| 1535 | JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) { | 1535 | jbd2_has_feature_checksum(journal)) { |
| 1536 | /* Can't have checksum v1 and v2 on at the same time! */ | 1536 | /* Can't have checksum v1 and v2 on at the same time! */ |
| 1537 | printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2/3 " | 1537 | printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2/3 " |
| 1538 | "at the same time!\n"); | 1538 | "at the same time!\n"); |
| @@ -1545,7 +1545,7 @@ static int journal_get_superblock(journal_t *journal) | |||
| 1545 | } | 1545 | } |
| 1546 | 1546 | ||
| 1547 | /* Load the checksum driver */ | 1547 | /* Load the checksum driver */ |
| 1548 | if (jbd2_journal_has_csum_v2or3(journal)) { | 1548 | if (jbd2_journal_has_csum_v2or3_feature(journal)) { |
| 1549 | journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); | 1549 | journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); |
| 1550 | if (IS_ERR(journal->j_chksum_driver)) { | 1550 | if (IS_ERR(journal->j_chksum_driver)) { |
| 1551 | printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); | 1551 | printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); |
| @@ -1558,6 +1558,7 @@ static int journal_get_superblock(journal_t *journal) | |||
| 1558 | /* Check superblock checksum */ | 1558 | /* Check superblock checksum */ |
| 1559 | if (!jbd2_superblock_csum_verify(journal, sb)) { | 1559 | if (!jbd2_superblock_csum_verify(journal, sb)) { |
| 1560 | printk(KERN_ERR "JBD2: journal checksum error\n"); | 1560 | printk(KERN_ERR "JBD2: journal checksum error\n"); |
| 1561 | err = -EFSBADCRC; | ||
| 1561 | goto out; | 1562 | goto out; |
| 1562 | } | 1563 | } |
| 1563 | 1564 | ||
| @@ -1649,7 +1650,7 @@ int jbd2_journal_load(journal_t *journal) | |||
| 1649 | printk(KERN_ERR "JBD2: journal transaction %u on %s " | 1650 | printk(KERN_ERR "JBD2: journal transaction %u on %s " |
| 1650 | "is corrupt.\n", journal->j_failed_commit, | 1651 | "is corrupt.\n", journal->j_failed_commit, |
| 1651 | journal->j_devname); | 1652 | journal->j_devname); |
| 1652 | return -EIO; | 1653 | return -EFSCORRUPTED; |
| 1653 | } | 1654 | } |
| 1654 | 1655 | ||
| 1655 | /* OK, we've finished with the dynamic journal bits: | 1656 | /* OK, we've finished with the dynamic journal bits: |
| @@ -2071,8 +2072,12 @@ static void __journal_abort_soft (journal_t *journal, int errno) | |||
| 2071 | 2072 | ||
| 2072 | __jbd2_journal_abort_hard(journal); | 2073 | __jbd2_journal_abort_hard(journal); |
| 2073 | 2074 | ||
| 2074 | if (errno) | 2075 | if (errno) { |
| 2075 | jbd2_journal_update_sb_errno(journal); | 2076 | jbd2_journal_update_sb_errno(journal); |
| 2077 | write_lock(&journal->j_state_lock); | ||
| 2078 | journal->j_flags |= JBD2_REC_ERR; | ||
| 2079 | write_unlock(&journal->j_state_lock); | ||
| 2080 | } | ||
| 2076 | } | 2081 | } |
| 2077 | 2082 | ||
| 2078 | /** | 2083 | /** |
| @@ -2197,15 +2202,15 @@ size_t journal_tag_bytes(journal_t *journal) | |||
| 2197 | { | 2202 | { |
| 2198 | size_t sz; | 2203 | size_t sz; |
| 2199 | 2204 | ||
| 2200 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) | 2205 | if (jbd2_has_feature_csum3(journal)) |
| 2201 | return sizeof(journal_block_tag3_t); | 2206 | return sizeof(journal_block_tag3_t); |
| 2202 | 2207 | ||
| 2203 | sz = sizeof(journal_block_tag_t); | 2208 | sz = sizeof(journal_block_tag_t); |
| 2204 | 2209 | ||
| 2205 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 2210 | if (jbd2_has_feature_csum2(journal)) |
| 2206 | sz += sizeof(__u16); | 2211 | sz += sizeof(__u16); |
| 2207 | 2212 | ||
| 2208 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 2213 | if (jbd2_has_feature_64bit(journal)) |
| 2209 | return sz; | 2214 | return sz; |
| 2210 | else | 2215 | else |
| 2211 | return sz - sizeof(__u32); | 2216 | return sz - sizeof(__u32); |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index a9079d035ae5..7f277e49fe88 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
| @@ -140,7 +140,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal, | |||
| 140 | 140 | ||
| 141 | if (offset >= journal->j_maxlen) { | 141 | if (offset >= journal->j_maxlen) { |
| 142 | printk(KERN_ERR "JBD2: corrupted journal superblock\n"); | 142 | printk(KERN_ERR "JBD2: corrupted journal superblock\n"); |
| 143 | return -EIO; | 143 | return -EFSCORRUPTED; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | err = jbd2_journal_bmap(journal, offset, &blocknr); | 146 | err = jbd2_journal_bmap(journal, offset, &blocknr); |
| @@ -342,7 +342,7 @@ static inline unsigned long long read_tag_block(journal_t *journal, | |||
| 342 | journal_block_tag_t *tag) | 342 | journal_block_tag_t *tag) |
| 343 | { | 343 | { |
| 344 | unsigned long long block = be32_to_cpu(tag->t_blocknr); | 344 | unsigned long long block = be32_to_cpu(tag->t_blocknr); |
| 345 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 345 | if (jbd2_has_feature_64bit(journal)) |
| 346 | block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; | 346 | block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; |
| 347 | return block; | 347 | return block; |
| 348 | } | 348 | } |
| @@ -411,7 +411,7 @@ static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, | |||
| 411 | csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); | 411 | csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); |
| 412 | csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); | 412 | csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); |
| 413 | 413 | ||
| 414 | if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) | 414 | if (jbd2_has_feature_csum3(j)) |
| 415 | return tag3->t_checksum == cpu_to_be32(csum32); | 415 | return tag3->t_checksum == cpu_to_be32(csum32); |
| 416 | else | 416 | else |
| 417 | return tag->t_checksum == cpu_to_be16(csum32); | 417 | return tag->t_checksum == cpu_to_be16(csum32); |
| @@ -527,7 +527,7 @@ static int do_one_pass(journal_t *journal, | |||
| 527 | printk(KERN_ERR "JBD2: Invalid checksum " | 527 | printk(KERN_ERR "JBD2: Invalid checksum " |
| 528 | "recovering block %lu in log\n", | 528 | "recovering block %lu in log\n", |
| 529 | next_log_block); | 529 | next_log_block); |
| 530 | err = -EIO; | 530 | err = -EFSBADCRC; |
| 531 | brelse(bh); | 531 | brelse(bh); |
| 532 | goto failed; | 532 | goto failed; |
| 533 | } | 533 | } |
| @@ -538,8 +538,7 @@ static int do_one_pass(journal_t *journal, | |||
| 538 | * just skip over the blocks it describes. */ | 538 | * just skip over the blocks it describes. */ |
| 539 | if (pass != PASS_REPLAY) { | 539 | if (pass != PASS_REPLAY) { |
| 540 | if (pass == PASS_SCAN && | 540 | if (pass == PASS_SCAN && |
| 541 | JBD2_HAS_COMPAT_FEATURE(journal, | 541 | jbd2_has_feature_checksum(journal) && |
| 542 | JBD2_FEATURE_COMPAT_CHECKSUM) && | ||
| 543 | !info->end_transaction) { | 542 | !info->end_transaction) { |
| 544 | if (calc_chksums(journal, bh, | 543 | if (calc_chksums(journal, bh, |
| 545 | &next_log_block, | 544 | &next_log_block, |
| @@ -602,7 +601,7 @@ static int do_one_pass(journal_t *journal, | |||
| 602 | journal, tag, obh->b_data, | 601 | journal, tag, obh->b_data, |
| 603 | be32_to_cpu(tmp->h_sequence))) { | 602 | be32_to_cpu(tmp->h_sequence))) { |
| 604 | brelse(obh); | 603 | brelse(obh); |
| 605 | success = -EIO; | 604 | success = -EFSBADCRC; |
| 606 | printk(KERN_ERR "JBD2: Invalid " | 605 | printk(KERN_ERR "JBD2: Invalid " |
| 607 | "checksum recovering " | 606 | "checksum recovering " |
| 608 | "block %llu in log\n", | 607 | "block %llu in log\n", |
| @@ -694,8 +693,7 @@ static int do_one_pass(journal_t *journal, | |||
| 694 | * much to do other than move on to the next sequence | 693 | * much to do other than move on to the next sequence |
| 695 | * number. */ | 694 | * number. */ |
| 696 | if (pass == PASS_SCAN && | 695 | if (pass == PASS_SCAN && |
| 697 | JBD2_HAS_COMPAT_FEATURE(journal, | 696 | jbd2_has_feature_checksum(journal)) { |
| 698 | JBD2_FEATURE_COMPAT_CHECKSUM)) { | ||
| 699 | int chksum_err, chksum_seen; | 697 | int chksum_err, chksum_seen; |
| 700 | struct commit_header *cbh = | 698 | struct commit_header *cbh = |
| 701 | (struct commit_header *)bh->b_data; | 699 | (struct commit_header *)bh->b_data; |
| @@ -735,8 +733,7 @@ static int do_one_pass(journal_t *journal, | |||
| 735 | if (chksum_err) { | 733 | if (chksum_err) { |
| 736 | info->end_transaction = next_commit_ID; | 734 | info->end_transaction = next_commit_ID; |
| 737 | 735 | ||
| 738 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 736 | if (!jbd2_has_feature_async_commit(journal)) { |
| 739 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){ | ||
| 740 | journal->j_failed_commit = | 737 | journal->j_failed_commit = |
| 741 | next_commit_ID; | 738 | next_commit_ID; |
| 742 | brelse(bh); | 739 | brelse(bh); |
| @@ -750,8 +747,7 @@ static int do_one_pass(journal_t *journal, | |||
| 750 | bh->b_data)) { | 747 | bh->b_data)) { |
| 751 | info->end_transaction = next_commit_ID; | 748 | info->end_transaction = next_commit_ID; |
| 752 | 749 | ||
| 753 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 750 | if (!jbd2_has_feature_async_commit(journal)) { |
| 754 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | ||
| 755 | journal->j_failed_commit = | 751 | journal->j_failed_commit = |
| 756 | next_commit_ID; | 752 | next_commit_ID; |
| 757 | brelse(bh); | 753 | brelse(bh); |
| @@ -851,7 +847,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, | |||
| 851 | rcount = be32_to_cpu(header->r_count); | 847 | rcount = be32_to_cpu(header->r_count); |
| 852 | 848 | ||
| 853 | if (!jbd2_revoke_block_csum_verify(journal, header)) | 849 | if (!jbd2_revoke_block_csum_verify(journal, header)) |
| 854 | return -EINVAL; | 850 | return -EFSBADCRC; |
| 855 | 851 | ||
| 856 | if (jbd2_journal_has_csum_v2or3(journal)) | 852 | if (jbd2_journal_has_csum_v2or3(journal)) |
| 857 | csum_size = sizeof(struct jbd2_journal_revoke_tail); | 853 | csum_size = sizeof(struct jbd2_journal_revoke_tail); |
| @@ -859,7 +855,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, | |||
| 859 | return -EINVAL; | 855 | return -EINVAL; |
| 860 | max = rcount; | 856 | max = rcount; |
| 861 | 857 | ||
| 862 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 858 | if (jbd2_has_feature_64bit(journal)) |
| 863 | record_len = 8; | 859 | record_len = 8; |
| 864 | 860 | ||
| 865 | while (offset + record_len <= max) { | 861 | while (offset + record_len <= max) { |
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 0abf2e7f725b..705ae577882b 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
| @@ -589,7 +589,7 @@ static void write_one_revoke_record(journal_t *journal, | |||
| 589 | if (jbd2_journal_has_csum_v2or3(journal)) | 589 | if (jbd2_journal_has_csum_v2or3(journal)) |
| 590 | csum_size = sizeof(struct jbd2_journal_revoke_tail); | 590 | csum_size = sizeof(struct jbd2_journal_revoke_tail); |
| 591 | 591 | ||
| 592 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 592 | if (jbd2_has_feature_64bit(journal)) |
| 593 | sz = 8; | 593 | sz = 8; |
| 594 | else | 594 | else |
| 595 | sz = 4; | 595 | sz = 4; |
| @@ -619,7 +619,7 @@ static void write_one_revoke_record(journal_t *journal, | |||
| 619 | *descriptorp = descriptor; | 619 | *descriptorp = descriptor; |
| 620 | } | 620 | } |
| 621 | 621 | ||
| 622 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 622 | if (jbd2_has_feature_64bit(journal)) |
| 623 | * ((__be64 *)(&descriptor->b_data[offset])) = | 623 | * ((__be64 *)(&descriptor->b_data[offset])) = |
| 624 | cpu_to_be64(record->blocknr); | 624 | cpu_to_be64(record->blocknr); |
| 625 | else | 625 | else |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index df07e78487d5..65407f6c9120 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
| @@ -278,6 +278,7 @@ typedef struct journal_superblock_s | |||
| 278 | /* 0x0400 */ | 278 | /* 0x0400 */ |
| 279 | } journal_superblock_t; | 279 | } journal_superblock_t; |
| 280 | 280 | ||
| 281 | /* Use the jbd2_{has,set,clear}_feature_* helpers; these will be removed */ | ||
| 281 | #define JBD2_HAS_COMPAT_FEATURE(j,mask) \ | 282 | #define JBD2_HAS_COMPAT_FEATURE(j,mask) \ |
| 282 | ((j)->j_format_version >= 2 && \ | 283 | ((j)->j_format_version >= 2 && \ |
| 283 | ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) | 284 | ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) |
| @@ -288,7 +289,7 @@ typedef struct journal_superblock_s | |||
| 288 | ((j)->j_format_version >= 2 && \ | 289 | ((j)->j_format_version >= 2 && \ |
| 289 | ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) | 290 | ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) |
| 290 | 291 | ||
| 291 | #define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001 | 292 | #define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001 |
| 292 | 293 | ||
| 293 | #define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 | 294 | #define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 |
| 294 | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 | 295 | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 |
| @@ -296,6 +297,8 @@ typedef struct journal_superblock_s | |||
| 296 | #define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 | 297 | #define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 |
| 297 | #define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 | 298 | #define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 |
| 298 | 299 | ||
| 300 | /* See "journal feature predicate functions" below */ | ||
| 301 | |||
| 299 | /* Features known to this kernel version: */ | 302 | /* Features known to this kernel version: */ |
| 300 | #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM | 303 | #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM |
| 301 | #define JBD2_KNOWN_ROCOMPAT_FEATURES 0 | 304 | #define JBD2_KNOWN_ROCOMPAT_FEATURES 0 |
| @@ -1034,6 +1037,69 @@ struct journal_s | |||
| 1034 | __u32 j_csum_seed; | 1037 | __u32 j_csum_seed; |
| 1035 | }; | 1038 | }; |
| 1036 | 1039 | ||
| 1040 | /* journal feature predicate functions */ | ||
| 1041 | #define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||
| 1042 | static inline bool jbd2_has_feature_##name(journal_t *j) \ | ||
| 1043 | { \ | ||
| 1044 | return ((j)->j_format_version >= 2 && \ | ||
| 1045 | ((j)->j_superblock->s_feature_compat & \ | ||
| 1046 | cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname)) != 0); \ | ||
| 1047 | } \ | ||
| 1048 | static inline void jbd2_set_feature_##name(journal_t *j) \ | ||
| 1049 | { \ | ||
| 1050 | (j)->j_superblock->s_feature_compat |= \ | ||
| 1051 | cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ | ||
| 1052 | } \ | ||
| 1053 | static inline void jbd2_clear_feature_##name(journal_t *j) \ | ||
| 1054 | { \ | ||
| 1055 | (j)->j_superblock->s_feature_compat &= \ | ||
| 1056 | ~cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | #define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||
| 1060 | static inline bool jbd2_has_feature_##name(journal_t *j) \ | ||
| 1061 | { \ | ||
| 1062 | return ((j)->j_format_version >= 2 && \ | ||
| 1063 | ((j)->j_superblock->s_feature_ro_compat & \ | ||
| 1064 | cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname)) != 0); \ | ||
| 1065 | } \ | ||
| 1066 | static inline void jbd2_set_feature_##name(journal_t *j) \ | ||
| 1067 | { \ | ||
| 1068 | (j)->j_superblock->s_feature_ro_compat |= \ | ||
| 1069 | cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ | ||
| 1070 | } \ | ||
| 1071 | static inline void jbd2_clear_feature_##name(journal_t *j) \ | ||
| 1072 | { \ | ||
| 1073 | (j)->j_superblock->s_feature_ro_compat &= \ | ||
| 1074 | ~cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | #define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||
| 1078 | static inline bool jbd2_has_feature_##name(journal_t *j) \ | ||
| 1079 | { \ | ||
| 1080 | return ((j)->j_format_version >= 2 && \ | ||
| 1081 | ((j)->j_superblock->s_feature_incompat & \ | ||
| 1082 | cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname)) != 0); \ | ||
| 1083 | } \ | ||
| 1084 | static inline void jbd2_set_feature_##name(journal_t *j) \ | ||
| 1085 | { \ | ||
| 1086 | (j)->j_superblock->s_feature_incompat |= \ | ||
| 1087 | cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ | ||
| 1088 | } \ | ||
| 1089 | static inline void jbd2_clear_feature_##name(journal_t *j) \ | ||
| 1090 | { \ | ||
| 1091 | (j)->j_superblock->s_feature_incompat &= \ | ||
| 1092 | ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | JBD2_FEATURE_COMPAT_FUNCS(checksum, CHECKSUM) | ||
| 1096 | |||
| 1097 | JBD2_FEATURE_INCOMPAT_FUNCS(revoke, REVOKE) | ||
| 1098 | JBD2_FEATURE_INCOMPAT_FUNCS(64bit, 64BIT) | ||
| 1099 | JBD2_FEATURE_INCOMPAT_FUNCS(async_commit, ASYNC_COMMIT) | ||
| 1100 | JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2) | ||
| 1101 | JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3) | ||
| 1102 | |||
| 1037 | /* | 1103 | /* |
| 1038 | * Journal flag definitions | 1104 | * Journal flag definitions |
| 1039 | */ | 1105 | */ |
| @@ -1046,6 +1112,7 @@ struct journal_s | |||
| 1046 | #define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file | 1112 | #define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file |
| 1047 | * data write error in ordered | 1113 | * data write error in ordered |
| 1048 | * mode */ | 1114 | * mode */ |
| 1115 | #define JBD2_REC_ERR 0x080 /* The errno in the sb has been recorded */ | ||
| 1049 | 1116 | ||
| 1050 | /* | 1117 | /* |
| 1051 | * Function declarations for the journaling transaction and buffer | 1118 | * Function declarations for the journaling transaction and buffer |
| @@ -1338,13 +1405,17 @@ static inline int tid_geq(tid_t x, tid_t y) | |||
| 1338 | extern int jbd2_journal_blocks_per_page(struct inode *inode); | 1405 | extern int jbd2_journal_blocks_per_page(struct inode *inode); |
| 1339 | extern size_t journal_tag_bytes(journal_t *journal); | 1406 | extern size_t journal_tag_bytes(journal_t *journal); |
| 1340 | 1407 | ||
| 1408 | static inline bool jbd2_journal_has_csum_v2or3_feature(journal_t *j) | ||
| 1409 | { | ||
| 1410 | return jbd2_has_feature_csum2(j) || jbd2_has_feature_csum3(j); | ||
| 1411 | } | ||
| 1412 | |||
| 1341 | static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) | 1413 | static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) |
| 1342 | { | 1414 | { |
| 1343 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) || | 1415 | WARN_ON_ONCE(jbd2_journal_has_csum_v2or3_feature(journal) && |
| 1344 | JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) | 1416 | journal->j_chksum_driver == NULL); |
| 1345 | return 1; | ||
| 1346 | 1417 | ||
| 1347 | return 0; | 1418 | return journal->j_chksum_driver != NULL; |
| 1348 | } | 1419 | } |
| 1349 | 1420 | ||
| 1350 | /* | 1421 | /* |
| @@ -1444,4 +1515,7 @@ static inline tid_t jbd2_get_latest_transaction(journal_t *journal) | |||
| 1444 | 1515 | ||
| 1445 | #endif /* __KERNEL__ */ | 1516 | #endif /* __KERNEL__ */ |
| 1446 | 1517 | ||
| 1518 | #define EFSBADCRC EBADMSG /* Bad CRC detected */ | ||
| 1519 | #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ | ||
| 1520 | |||
| 1447 | #endif /* _LINUX_JBD2_H */ | 1521 | #endif /* _LINUX_JBD2_H */ |
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 9b964a5920af..f15d980249b5 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h | |||
| @@ -197,6 +197,7 @@ struct inodes_stat_t { | |||
| 197 | #define FS_EXTENT_FL 0x00080000 /* Extents */ | 197 | #define FS_EXTENT_FL 0x00080000 /* Extents */ |
| 198 | #define FS_DIRECTIO_FL 0x00100000 /* Use direct i/o */ | 198 | #define FS_DIRECTIO_FL 0x00100000 /* Use direct i/o */ |
| 199 | #define FS_NOCOW_FL 0x00800000 /* Do not cow file */ | 199 | #define FS_NOCOW_FL 0x00800000 /* Do not cow file */ |
| 200 | #define FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ | ||
| 200 | #define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ | 201 | #define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ |
| 201 | 202 | ||
| 202 | #define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ | 203 | #define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ |
