diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 43c92b1685cb..10e8c6b7ca08 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -334,7 +334,7 @@ static void save_error_info(struct super_block *sb, const char *func, | |||
| 334 | static int block_device_ejected(struct super_block *sb) | 334 | static int block_device_ejected(struct super_block *sb) |
| 335 | { | 335 | { |
| 336 | struct inode *bd_inode = sb->s_bdev->bd_inode; | 336 | struct inode *bd_inode = sb->s_bdev->bd_inode; |
| 337 | struct backing_dev_info *bdi = bd_inode->i_mapping->backing_dev_info; | 337 | struct backing_dev_info *bdi = inode_to_bdi(bd_inode); |
| 338 | 338 | ||
| 339 | return bdi->dev == NULL; | 339 | return bdi->dev == NULL; |
| 340 | } | 340 | } |
| @@ -1046,10 +1046,7 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot); | |||
| 1046 | static int ext4_write_info(struct super_block *sb, int type); | 1046 | static int ext4_write_info(struct super_block *sb, int type); |
| 1047 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, | 1047 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, |
| 1048 | struct path *path); | 1048 | struct path *path); |
| 1049 | static int ext4_quota_on_sysfile(struct super_block *sb, int type, | ||
| 1050 | int format_id); | ||
| 1051 | static int ext4_quota_off(struct super_block *sb, int type); | 1049 | static int ext4_quota_off(struct super_block *sb, int type); |
| 1052 | static int ext4_quota_off_sysfile(struct super_block *sb, int type); | ||
| 1053 | static int ext4_quota_on_mount(struct super_block *sb, int type); | 1050 | static int ext4_quota_on_mount(struct super_block *sb, int type); |
| 1054 | static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, | 1051 | static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, |
| 1055 | size_t len, loff_t off); | 1052 | size_t len, loff_t off); |
| @@ -1084,16 +1081,6 @@ static const struct quotactl_ops ext4_qctl_operations = { | |||
| 1084 | .get_dqblk = dquot_get_dqblk, | 1081 | .get_dqblk = dquot_get_dqblk, |
| 1085 | .set_dqblk = dquot_set_dqblk | 1082 | .set_dqblk = dquot_set_dqblk |
| 1086 | }; | 1083 | }; |
| 1087 | |||
| 1088 | static const struct quotactl_ops ext4_qctl_sysfile_operations = { | ||
| 1089 | .quota_on_meta = ext4_quota_on_sysfile, | ||
| 1090 | .quota_off = ext4_quota_off_sysfile, | ||
| 1091 | .quota_sync = dquot_quota_sync, | ||
| 1092 | .get_info = dquot_get_dqinfo, | ||
| 1093 | .set_info = dquot_set_dqinfo, | ||
| 1094 | .get_dqblk = dquot_get_dqblk, | ||
| 1095 | .set_dqblk = dquot_set_dqblk | ||
| 1096 | }; | ||
| 1097 | #endif | 1084 | #endif |
| 1098 | 1085 | ||
| 1099 | static const struct super_operations ext4_sops = { | 1086 | static const struct super_operations ext4_sops = { |
| @@ -1137,7 +1124,7 @@ enum { | |||
| 1137 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 1124 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
| 1138 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, | 1125 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, |
| 1139 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, | 1126 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, |
| 1140 | Opt_usrquota, Opt_grpquota, Opt_i_version, | 1127 | Opt_usrquota, Opt_grpquota, Opt_i_version, Opt_dax, |
| 1141 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, | 1128 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, |
| 1142 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, | 1129 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, |
| 1143 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1130 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
| @@ -1200,6 +1187,7 @@ static const match_table_t tokens = { | |||
| 1200 | {Opt_barrier, "barrier"}, | 1187 | {Opt_barrier, "barrier"}, |
| 1201 | {Opt_nobarrier, "nobarrier"}, | 1188 | {Opt_nobarrier, "nobarrier"}, |
| 1202 | {Opt_i_version, "i_version"}, | 1189 | {Opt_i_version, "i_version"}, |
| 1190 | {Opt_dax, "dax"}, | ||
| 1203 | {Opt_stripe, "stripe=%u"}, | 1191 | {Opt_stripe, "stripe=%u"}, |
| 1204 | {Opt_delalloc, "delalloc"}, | 1192 | {Opt_delalloc, "delalloc"}, |
| 1205 | {Opt_nodelalloc, "nodelalloc"}, | 1193 | {Opt_nodelalloc, "nodelalloc"}, |
| @@ -1384,6 +1372,7 @@ static const struct mount_opts { | |||
| 1384 | {Opt_min_batch_time, 0, MOPT_GTE0}, | 1372 | {Opt_min_batch_time, 0, MOPT_GTE0}, |
| 1385 | {Opt_inode_readahead_blks, 0, MOPT_GTE0}, | 1373 | {Opt_inode_readahead_blks, 0, MOPT_GTE0}, |
| 1386 | {Opt_init_itable, 0, MOPT_GTE0}, | 1374 | {Opt_init_itable, 0, MOPT_GTE0}, |
| 1375 | {Opt_dax, EXT4_MOUNT_DAX, MOPT_SET}, | ||
| 1387 | {Opt_stripe, 0, MOPT_GTE0}, | 1376 | {Opt_stripe, 0, MOPT_GTE0}, |
| 1388 | {Opt_resuid, 0, MOPT_GTE0}, | 1377 | {Opt_resuid, 0, MOPT_GTE0}, |
| 1389 | {Opt_resgid, 0, MOPT_GTE0}, | 1378 | {Opt_resgid, 0, MOPT_GTE0}, |
| @@ -1620,6 +1609,11 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
| 1620 | } | 1609 | } |
| 1621 | sbi->s_jquota_fmt = m->mount_opt; | 1610 | sbi->s_jquota_fmt = m->mount_opt; |
| 1622 | #endif | 1611 | #endif |
| 1612 | #ifndef CONFIG_FS_DAX | ||
| 1613 | } else if (token == Opt_dax) { | ||
| 1614 | ext4_msg(sb, KERN_INFO, "dax option not supported"); | ||
| 1615 | return -1; | ||
| 1616 | #endif | ||
| 1623 | } else { | 1617 | } else { |
| 1624 | if (!args->from) | 1618 | if (!args->from) |
| 1625 | arg = 1; | 1619 | arg = 1; |
| @@ -3482,7 +3476,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3482 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3476 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, |
| 3483 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && | 3477 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && |
| 3484 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | 3478 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) |
| 3485 | ext4_warning(sb, KERN_INFO "metadata_csum and uninit_bg are " | 3479 | ext4_warning(sb, "metadata_csum and uninit_bg are " |
| 3486 | "redundant flags; please run fsck."); | 3480 | "redundant flags; please run fsck."); |
| 3487 | 3481 | ||
| 3488 | /* Check for a known checksum algorithm */ | 3482 | /* Check for a known checksum algorithm */ |
| @@ -3602,6 +3596,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3602 | "both data=journal and dioread_nolock"); | 3596 | "both data=journal and dioread_nolock"); |
| 3603 | goto failed_mount; | 3597 | goto failed_mount; |
| 3604 | } | 3598 | } |
| 3599 | if (test_opt(sb, DAX)) { | ||
| 3600 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 3601 | "both data=journal and dax"); | ||
| 3602 | goto failed_mount; | ||
| 3603 | } | ||
| 3605 | if (test_opt(sb, DELALLOC)) | 3604 | if (test_opt(sb, DELALLOC)) |
| 3606 | clear_opt(sb, DELALLOC); | 3605 | clear_opt(sb, DELALLOC); |
| 3607 | } | 3606 | } |
| @@ -3665,6 +3664,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3665 | goto failed_mount; | 3664 | goto failed_mount; |
| 3666 | } | 3665 | } |
| 3667 | 3666 | ||
| 3667 | if (sbi->s_mount_opt & EXT4_MOUNT_DAX) { | ||
| 3668 | if (blocksize != PAGE_SIZE) { | ||
| 3669 | ext4_msg(sb, KERN_ERR, | ||
| 3670 | "error: unsupported blocksize for dax"); | ||
| 3671 | goto failed_mount; | ||
| 3672 | } | ||
| 3673 | if (!sb->s_bdev->bd_disk->fops->direct_access) { | ||
| 3674 | ext4_msg(sb, KERN_ERR, | ||
| 3675 | "error: device does not support dax"); | ||
| 3676 | goto failed_mount; | ||
| 3677 | } | ||
| 3678 | } | ||
| 3679 | |||
| 3668 | if (sb->s_blocksize != blocksize) { | 3680 | if (sb->s_blocksize != blocksize) { |
| 3669 | /* Validate the filesystem blocksize */ | 3681 | /* Validate the filesystem blocksize */ |
| 3670 | if (!sb_set_blocksize(sb, blocksize)) { | 3682 | if (!sb_set_blocksize(sb, blocksize)) { |
| @@ -3935,7 +3947,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3935 | #ifdef CONFIG_QUOTA | 3947 | #ifdef CONFIG_QUOTA |
| 3936 | sb->dq_op = &ext4_quota_operations; | 3948 | sb->dq_op = &ext4_quota_operations; |
| 3937 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) | 3949 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) |
| 3938 | sb->s_qcop = &ext4_qctl_sysfile_operations; | 3950 | sb->s_qcop = &dquot_quotactl_sysfile_ops; |
| 3939 | else | 3951 | else |
| 3940 | sb->s_qcop = &ext4_qctl_operations; | 3952 | sb->s_qcop = &ext4_qctl_operations; |
| 3941 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; | 3953 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; |
| @@ -4882,6 +4894,18 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 4882 | err = -EINVAL; | 4894 | err = -EINVAL; |
| 4883 | goto restore_opts; | 4895 | goto restore_opts; |
| 4884 | } | 4896 | } |
| 4897 | if (test_opt(sb, DAX)) { | ||
| 4898 | ext4_msg(sb, KERN_ERR, "can't mount with " | ||
| 4899 | "both data=journal and dax"); | ||
| 4900 | err = -EINVAL; | ||
| 4901 | goto restore_opts; | ||
| 4902 | } | ||
| 4903 | } | ||
| 4904 | |||
| 4905 | if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX) { | ||
| 4906 | ext4_msg(sb, KERN_WARNING, "warning: refusing change of " | ||
| 4907 | "dax flag with busy inodes while remounting"); | ||
| 4908 | sbi->s_mount_opt ^= EXT4_MOUNT_DAX; | ||
| 4885 | } | 4909 | } |
| 4886 | 4910 | ||
| 4887 | if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) | 4911 | if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) |
| @@ -5288,21 +5312,6 @@ static int ext4_enable_quotas(struct super_block *sb) | |||
| 5288 | return 0; | 5312 | return 0; |
| 5289 | } | 5313 | } |
| 5290 | 5314 | ||
| 5291 | /* | ||
| 5292 | * quota_on function that is used when QUOTA feature is set. | ||
| 5293 | */ | ||
| 5294 | static int ext4_quota_on_sysfile(struct super_block *sb, int type, | ||
| 5295 | int format_id) | ||
| 5296 | { | ||
| 5297 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) | ||
| 5298 | return -EINVAL; | ||
| 5299 | |||
| 5300 | /* | ||
| 5301 | * USAGE was enabled at mount time. Only need to enable LIMITS now. | ||
| 5302 | */ | ||
| 5303 | return ext4_quota_enable(sb, type, format_id, DQUOT_LIMITS_ENABLED); | ||
| 5304 | } | ||
| 5305 | |||
| 5306 | static int ext4_quota_off(struct super_block *sb, int type) | 5315 | static int ext4_quota_off(struct super_block *sb, int type) |
| 5307 | { | 5316 | { |
| 5308 | struct inode *inode = sb_dqopt(sb)->files[type]; | 5317 | struct inode *inode = sb_dqopt(sb)->files[type]; |
| @@ -5329,18 +5338,6 @@ out: | |||
| 5329 | return dquot_quota_off(sb, type); | 5338 | return dquot_quota_off(sb, type); |
| 5330 | } | 5339 | } |
| 5331 | 5340 | ||
| 5332 | /* | ||
| 5333 | * quota_off function that is used when QUOTA feature is set. | ||
| 5334 | */ | ||
| 5335 | static int ext4_quota_off_sysfile(struct super_block *sb, int type) | ||
| 5336 | { | ||
| 5337 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) | ||
| 5338 | return -EINVAL; | ||
| 5339 | |||
| 5340 | /* Disable only the limits. */ | ||
| 5341 | return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED); | ||
| 5342 | } | ||
| 5343 | |||
| 5344 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 5341 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
| 5345 | * acquiring the locks... As quota files are never truncated and quota code | 5342 | * acquiring the locks... As quota files are never truncated and quota code |
| 5346 | * itself serializes the operations (and no one else should touch the files) | 5343 | * itself serializes the operations (and no one else should touch the files) |
