aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ext4.h5
-rw-r--r--fs/ext4/ext4_jbd2.h18
-rw-r--r--fs/ext4/super.c137
3 files changed, 150 insertions, 10 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 4a49f8225d0..1610e808ebe 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1315,6 +1315,8 @@ static inline struct timespec ext4_current_time(struct inode *inode)
1315static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) 1315static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
1316{ 1316{
1317 return ino == EXT4_ROOT_INO || 1317 return ino == EXT4_ROOT_INO ||
1318 ino == EXT4_USR_QUOTA_INO ||
1319 ino == EXT4_GRP_QUOTA_INO ||
1318 ino == EXT4_JOURNAL_INO || 1320 ino == EXT4_JOURNAL_INO ||
1319 ino == EXT4_RESIZE_INO || 1321 ino == EXT4_RESIZE_INO ||
1320 (ino >= EXT4_FIRST_INO(sb) && 1322 (ino >= EXT4_FIRST_INO(sb) &&
@@ -1497,7 +1499,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
1497 EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\ 1499 EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
1498 EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\ 1500 EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
1499 EXT4_FEATURE_RO_COMPAT_BIGALLOC |\ 1501 EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
1500 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) 1502 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
1503 EXT4_FEATURE_RO_COMPAT_QUOTA)
1501 1504
1502/* 1505/*
1503 * Default values for user and/or group using reserved blocks 1506 * Default values for user and/or group using reserved blocks
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index f440e8f1841..1393c830411 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -87,14 +87,20 @@
87#ifdef CONFIG_QUOTA 87#ifdef CONFIG_QUOTA
88/* Amount of blocks needed for quota update - we know that the structure was 88/* Amount of blocks needed for quota update - we know that the structure was
89 * allocated so we need to update only data block */ 89 * allocated so we need to update only data block */
90#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0) 90#define EXT4_QUOTA_TRANS_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
91 EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
92 1 : 0)
91/* Amount of blocks needed for quota insert/delete - we do some block writes 93/* Amount of blocks needed for quota insert/delete - we do some block writes
92 * but inode, sb and group updates are done only once */ 94 * but inode, sb and group updates are done only once */
93#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ 95#define EXT4_QUOTA_INIT_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
94 (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0) 96 EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
95 97 (DQUOT_INIT_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\
96#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\ 98 +3+DQUOT_INIT_REWRITE) : 0)
97 (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0) 99
100#define EXT4_QUOTA_DEL_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
101 EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
102 (DQUOT_DEL_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\
103 +3+DQUOT_DEL_REWRITE) : 0)
98#else 104#else
99#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0 105#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
100#define EXT4_QUOTA_INIT_BLOCKS(sb) 0 106#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 78b7ede2efa..bebf8e5bf08 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1137,12 +1137,18 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot);
1137static int ext4_write_info(struct super_block *sb, int type); 1137static int ext4_write_info(struct super_block *sb, int type);
1138static int ext4_quota_on(struct super_block *sb, int type, int format_id, 1138static int ext4_quota_on(struct super_block *sb, int type, int format_id,
1139 struct path *path); 1139 struct path *path);
1140static int ext4_quota_on_sysfile(struct super_block *sb, int type,
1141 int format_id);
1140static int ext4_quota_off(struct super_block *sb, int type); 1142static int ext4_quota_off(struct super_block *sb, int type);
1143static int ext4_quota_off_sysfile(struct super_block *sb, int type);
1141static int ext4_quota_on_mount(struct super_block *sb, int type); 1144static int ext4_quota_on_mount(struct super_block *sb, int type);
1142static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, 1145static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
1143 size_t len, loff_t off); 1146 size_t len, loff_t off);
1144static ssize_t ext4_quota_write(struct super_block *sb, int type, 1147static ssize_t ext4_quota_write(struct super_block *sb, int type,
1145 const char *data, size_t len, loff_t off); 1148 const char *data, size_t len, loff_t off);
1149static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
1150 unsigned int flags);
1151static int ext4_enable_quotas(struct super_block *sb);
1146 1152
1147static const struct dquot_operations ext4_quota_operations = { 1153static const struct dquot_operations ext4_quota_operations = {
1148 .get_reserved_space = ext4_get_reserved_space, 1154 .get_reserved_space = ext4_get_reserved_space,
@@ -1164,6 +1170,16 @@ static const struct quotactl_ops ext4_qctl_operations = {
1164 .get_dqblk = dquot_get_dqblk, 1170 .get_dqblk = dquot_get_dqblk,
1165 .set_dqblk = dquot_set_dqblk 1171 .set_dqblk = dquot_set_dqblk
1166}; 1172};
1173
1174static const struct quotactl_ops ext4_qctl_sysfile_operations = {
1175 .quota_on_meta = ext4_quota_on_sysfile,
1176 .quota_off = ext4_quota_off_sysfile,
1177 .quota_sync = dquot_quota_sync,
1178 .get_info = dquot_get_dqinfo,
1179 .set_info = dquot_set_dqinfo,
1180 .get_dqblk = dquot_get_dqblk,
1181 .set_dqblk = dquot_set_dqblk
1182};
1167#endif 1183#endif
1168 1184
1169static const struct super_operations ext4_sops = { 1185static const struct super_operations ext4_sops = {
@@ -2661,6 +2677,16 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
2661 "extents feature\n"); 2677 "extents feature\n");
2662 return 0; 2678 return 0;
2663 } 2679 }
2680
2681#ifndef CONFIG_QUOTA
2682 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) &&
2683 !readonly) {
2684 ext4_msg(sb, KERN_ERR,
2685 "Filesystem with quota feature cannot be mounted RDWR "
2686 "without CONFIG_QUOTA");
2687 return 0;
2688 }
2689#endif /* CONFIG_QUOTA */
2664 return 1; 2690 return 1;
2665} 2691}
2666 2692
@@ -3748,6 +3774,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3748#ifdef CONFIG_QUOTA 3774#ifdef CONFIG_QUOTA
3749 sb->s_qcop = &ext4_qctl_operations; 3775 sb->s_qcop = &ext4_qctl_operations;
3750 sb->dq_op = &ext4_quota_operations; 3776 sb->dq_op = &ext4_quota_operations;
3777
3778 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) {
3779 /* Use qctl operations for hidden quota files. */
3780 sb->s_qcop = &ext4_qctl_sysfile_operations;
3781 }
3751#endif 3782#endif
3752 memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); 3783 memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
3753 3784
@@ -3960,6 +3991,16 @@ no_journal:
3960 } else 3991 } else
3961 descr = "out journal"; 3992 descr = "out journal";
3962 3993
3994#ifdef CONFIG_QUOTA
3995 /* Enable quota usage during mount. */
3996 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) &&
3997 !(sb->s_flags & MS_RDONLY)) {
3998 ret = ext4_enable_quotas(sb);
3999 if (ret)
4000 goto failed_mount7;
4001 }
4002#endif /* CONFIG_QUOTA */
4003
3963 ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " 4004 ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
3964 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts, 4005 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
3965 *sbi->s_es->s_mount_opts ? "; " : "", orig_data); 4006 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
@@ -4682,16 +4723,26 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4682 if (sbi->s_journal == NULL) 4723 if (sbi->s_journal == NULL)
4683 ext4_commit_super(sb, 1); 4724 ext4_commit_super(sb, 1);
4684 4725
4726 unlock_super(sb);
4685#ifdef CONFIG_QUOTA 4727#ifdef CONFIG_QUOTA
4686 /* Release old quota file names */ 4728 /* Release old quota file names */
4687 for (i = 0; i < MAXQUOTAS; i++) 4729 for (i = 0; i < MAXQUOTAS; i++)
4688 if (old_opts.s_qf_names[i] && 4730 if (old_opts.s_qf_names[i] &&
4689 old_opts.s_qf_names[i] != sbi->s_qf_names[i]) 4731 old_opts.s_qf_names[i] != sbi->s_qf_names[i])
4690 kfree(old_opts.s_qf_names[i]); 4732 kfree(old_opts.s_qf_names[i]);
4733 if (enable_quota) {
4734 if (sb_any_quota_suspended(sb))
4735 dquot_resume(sb, -1);
4736 else if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
4737 EXT4_FEATURE_RO_COMPAT_QUOTA)) {
4738 err = ext4_enable_quotas(sb);
4739 if (err) {
4740 lock_super(sb);
4741 goto restore_opts;
4742 }
4743 }
4744 }
4691#endif 4745#endif
4692 unlock_super(sb);
4693 if (enable_quota)
4694 dquot_resume(sb, -1);
4695 4746
4696 ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data); 4747 ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
4697 kfree(orig_data); 4748 kfree(orig_data);
@@ -4904,6 +4955,74 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
4904 return dquot_quota_on(sb, type, format_id, path); 4955 return dquot_quota_on(sb, type, format_id, path);
4905} 4956}
4906 4957
4958static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
4959 unsigned int flags)
4960{
4961 int err;
4962 struct inode *qf_inode;
4963 unsigned long qf_inums[MAXQUOTAS] = {
4964 le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
4965 le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
4966 };
4967
4968 BUG_ON(!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA));
4969
4970 if (!qf_inums[type])
4971 return -EPERM;
4972
4973 qf_inode = ext4_iget(sb, qf_inums[type]);
4974 if (IS_ERR(qf_inode)) {
4975 ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]);
4976 return PTR_ERR(qf_inode);
4977 }
4978
4979 err = dquot_enable(qf_inode, type, format_id, flags);
4980 iput(qf_inode);
4981
4982 return err;
4983}
4984
4985/* Enable usage tracking for all quota types. */
4986static int ext4_enable_quotas(struct super_block *sb)
4987{
4988 int type, err = 0;
4989 unsigned long qf_inums[MAXQUOTAS] = {
4990 le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
4991 le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
4992 };
4993
4994 sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
4995 for (type = 0; type < MAXQUOTAS; type++) {
4996 if (qf_inums[type]) {
4997 err = ext4_quota_enable(sb, type, QFMT_VFS_V1,
4998 DQUOT_USAGE_ENABLED);
4999 if (err) {
5000 ext4_warning(sb,
5001 "Failed to enable quota (type=%d) "
5002 "tracking. Please run e2fsck to fix.",
5003 type);
5004 return err;
5005 }
5006 }
5007 }
5008 return 0;
5009}
5010
5011/*
5012 * quota_on function that is used when QUOTA feature is set.
5013 */
5014static int ext4_quota_on_sysfile(struct super_block *sb, int type,
5015 int format_id)
5016{
5017 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
5018 return -EINVAL;
5019
5020 /*
5021 * USAGE was enabled at mount time. Only need to enable LIMITS now.
5022 */
5023 return ext4_quota_enable(sb, type, format_id, DQUOT_LIMITS_ENABLED);
5024}
5025
4907static int ext4_quota_off(struct super_block *sb, int type) 5026static int ext4_quota_off(struct super_block *sb, int type)
4908{ 5027{
4909 struct inode *inode = sb_dqopt(sb)->files[type]; 5028 struct inode *inode = sb_dqopt(sb)->files[type];
@@ -4930,6 +5049,18 @@ out:
4930 return dquot_quota_off(sb, type); 5049 return dquot_quota_off(sb, type);
4931} 5050}
4932 5051
5052/*
5053 * quota_off function that is used when QUOTA feature is set.
5054 */
5055static int ext4_quota_off_sysfile(struct super_block *sb, int type)
5056{
5057 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
5058 return -EINVAL;
5059
5060 /* Disable only the limits. */
5061 return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
5062}
5063
4933/* Read data from quotafile - avoid pagecache and such because we cannot afford 5064/* Read data from quotafile - avoid pagecache and such because we cannot afford
4934 * acquiring the locks... As quota files are never truncated and quota code 5065 * acquiring the locks... As quota files are never truncated and quota code
4935 * itself serializes the operations (and no one else should touch the files) 5066 * itself serializes the operations (and no one else should touch the files)