* [PATCH] ext4: make quota as first class supported feature
@ 2011-12-10 0:08 Aditya Kali
0 siblings, 0 replies; 6+ messages in thread
From: Aditya Kali @ 2011-12-10 0:08 UTC (permalink / raw)
To: adilger, tytso, dmonakhov, jack, johann, linux-ext4; +Cc: Aditya Kali
This patch is an attempt towards supporting quotas as first class
feature in ext4. It is based on the proposal at:
https://ext4.wiki.kernel.org/index.php/Design_For_1st_Class_Quota_in_Ext4
This patch introduces a new feature - EXT4_FEATURE_RO_COMPAT_QUOTA which, when
turned on, enables quota accounting at mount time iteself. Also, the
quota inodes are stored in two additional superblock fields.
Some changes introduced by this patch that should be pointed out are:
1) Two new ext4-superblock fields - s_usr_quota_inum and s_grp_quota_inum
for storing the quota inodes in use.
2) Default quota inodes are: inode#3 for tracking userquota and inode#4 for
tracking group quota. The superblock fields can be set to use other inodes
as well.
3) If the QUOTA feature and corresponding quota inodes are set in superblock,
the quota usage tracking is turned on at mount time. On 'quotaon' ioctl, the
quota limits enforcement is turned on. 'quotaoff' ioctl turns off only the
limits enforcement in this case.
4) When QUOTA feature is in use, the quota mount options 'quota', 'usrquota',
'grpquota' are ignored by the kernel.
5) mke2fs or tune2fs can be used to set the QUOTA feature and initialize quota
inodes. The default reserved inodes will not be visible to user as
regular files.
6) The quota-tools will need to be modified to support hidden quota files on
ext4. E2fsprogs will also include support for creating and fixing quota
files.
7) Support is only for the new V2 quota file format.
Signed-off-by: Aditya Kali <adityakali@google.com>
---
fs/ext4/ext4.h | 5 ++-
fs/ext4/ext4_jbd2.h | 18 +++++--
fs/ext4/super.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 149 insertions(+), 9 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 5b0e26a..747e600 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1269,6 +1269,8 @@ static inline struct timespec ext4_current_time(struct inode *inode)
static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
{
return ino == EXT4_ROOT_INO ||
+ ino == EXT4_USR_QUOTA_INO ||
+ ino == EXT4_GRP_QUOTA_INO ||
ino == EXT4_JOURNAL_INO ||
ino == EXT4_RESIZE_INO ||
(ino >= EXT4_FIRST_INO(sb) &&
@@ -1440,7 +1442,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
- EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC | \
+ EXT4_FEATURE_RO_COMPAT_QUOTA)
/*
* 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 5802fa1..45de190 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -87,14 +87,20 @@
#ifdef CONFIG_QUOTA
/* Amount of blocks needed for quota update - we know that the structure was
* allocated so we need to update only data block */
-#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0)
+#define EXT4_QUOTA_TRANS_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
+ EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
+ 1 : 0)
/* Amount of blocks needed for quota insert/delete - we do some block writes
* but inode, sb and group updates are done only once */
-#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
- (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
-
-#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
- (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)
+#define EXT4_QUOTA_INIT_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
+ EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
+ (DQUOT_INIT_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\
+ +3+DQUOT_INIT_REWRITE) : 0)
+
+#define EXT4_QUOTA_DEL_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\
+ EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\
+ (DQUOT_DEL_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\
+ +3+DQUOT_DEL_REWRITE) : 0)
#else
#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
#define EXT4_QUOTA_INIT_BLOCKS(sb) 0
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 3858767..4ba21ab 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1239,12 +1239,18 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot);
static int ext4_write_info(struct super_block *sb, int type);
static int ext4_quota_on(struct super_block *sb, int type, int format_id,
struct path *path);
+static int ext4_quota_on_sysfile(struct super_block *sb, int type,
+ int format_id);
static int ext4_quota_off(struct super_block *sb, int type);
+static int ext4_quota_off_sysfile(struct super_block *sb, int type);
static int ext4_quota_on_mount(struct super_block *sb, int type);
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
size_t len, loff_t off);
static ssize_t ext4_quota_write(struct super_block *sb, int type,
const char *data, size_t len, loff_t off);
+static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+ unsigned int flags);
+static int ext4_enable_quotas(struct super_block *sb);
static const struct dquot_operations ext4_quota_operations = {
.get_reserved_space = ext4_get_reserved_space,
@@ -1266,6 +1272,16 @@ static const struct quotactl_ops ext4_qctl_operations = {
.get_dqblk = dquot_get_dqblk,
.set_dqblk = dquot_set_dqblk
};
+
+static const struct quotactl_ops ext4_qctl_sysfile_operations = {
+ .quota_on_meta = ext4_quota_on_sysfile,
+ .quota_off = ext4_quota_off_sysfile,
+ .quota_sync = dquot_quota_sync,
+ .get_info = dquot_get_dqinfo,
+ .set_info = dquot_set_dqinfo,
+ .get_dqblk = dquot_get_dqblk,
+ .set_dqblk = dquot_set_dqblk
+};
#endif
static const struct super_operations ext4_sops = {
@@ -2713,6 +2729,16 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
"extents feature\n");
return 0;
}
+
+#ifndef CONFIG_QUOTA
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) &&
+ !readonly) {
+ ext4_msg(sb, KERN_ERR,
+ "Filesystem with quota feature cannot be mounted RDWR "
+ "without CONFIG_QUOTA");
+ return 0;
+ }
+#endif /* CONFIG_QUOTA */
return 1;
}
@@ -3610,6 +3636,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
sb->s_qcop = &ext4_qctl_operations;
sb->dq_op = &ext4_quota_operations;
+
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+ /* Use qctl operations for hidden quota files. */
+ sb->s_qcop = &ext4_qctl_sysfile_operations;
+ }
#endif
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
@@ -3815,6 +3846,16 @@ no_journal:
} else
descr = "out journal";
+#ifdef CONFIG_QUOTA
+ /* Enable quota usage during mount. */
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) &&
+ !(sb->s_flags & MS_RDONLY)) {
+ ret = ext4_enable_quotas(sb);
+ if (ret)
+ goto failed_mount7;
+ }
+#endif /* CONFIG_QUOTA */
+
ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
"Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
*sbi->s_es->s_mount_opts ? "; " : "", orig_data);
@@ -4554,8 +4595,18 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
kfree(old_opts.s_qf_names[i]);
#endif
unlock_super(sb);
- if (enable_quota)
- dquot_resume(sb, -1);
+ if (enable_quota) {
+ if (sb_any_quota_suspended(sb))
+ dquot_resume(sb, -1);
+ else if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+ EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+ err = ext4_enable_quotas(sb);
+ if (err) {
+ lock_super(sb);
+ goto restore_opts;
+ }
+ }
+ }
ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
kfree(orig_data);
@@ -4814,6 +4865,74 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
return dquot_quota_on(sb, type, format_id, path);
}
+static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+ unsigned int flags)
+{
+ int err;
+ struct inode *qf_inode;
+ unsigned long qf_inums[MAXQUOTAS] = {
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
+ };
+
+ BUG_ON(!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA));
+
+ if (!qf_inums[type])
+ return -EPERM;
+
+ qf_inode = ext4_iget(sb, qf_inums[type]);
+ if (IS_ERR(qf_inode)) {
+ ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]);
+ return PTR_ERR(qf_inode);
+ }
+
+ err = dquot_enable(qf_inode, type, format_id, flags);
+ iput(qf_inode);
+
+ return err;
+}
+
+/* Enable usage tracking for all quota types. */
+static int ext4_enable_quotas(struct super_block *sb)
+{
+ int type, err = 0;
+ unsigned long qf_inums[MAXQUOTAS] = {
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
+ le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
+ };
+
+ sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
+ for (type = 0; type < MAXQUOTAS; type++) {
+ if (qf_inums[type]) {
+ err = ext4_quota_enable(sb, type, QFMT_VFS_V1,
+ DQUOT_USAGE_ENABLED);
+ if (err) {
+ ext4_warning(sb,
+ "Failed to enable quota (type=%d) "
+ "tracking. Please run e2fsck to fix.",
+ type);
+ return err;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * quota_on function that is used when QUOTA feature is set.
+ */
+static int ext4_quota_on_sysfile(struct super_block *sb, int type,
+ int format_id)
+{
+ if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
+ return -EINVAL;
+
+ /*
+ * USAGE was enabled at mount time. Only need to enable LIMITS now.
+ */
+ return ext4_quota_enable(sb, type, format_id, DQUOT_LIMITS_ENABLED);
+}
+
static int ext4_quota_off(struct super_block *sb, int type)
{
struct inode *inode = sb_dqopt(sb)->files[type];
@@ -4840,6 +4959,18 @@ out:
return dquot_quota_off(sb, type);
}
+/*
+ * quota_off function that is used when QUOTA feature is set.
+ */
+static int ext4_quota_off_sysfile(struct super_block *sb, int type)
+{
+ if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
+ return -EINVAL;
+
+ /* Disable only the limits. */
+ return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
+}
+
/* Read data from quotafile - avoid pagecache and such because we cannot afford
* acquiring the locks... As quota files are never truncated and quota code
* itself serializes the operations (and no one else should touch the files)
--
1.7.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH] ext4: make quota as first class supported feature
@ 2011-07-20 18:40 Aditya Kali
[not found] ` <561996F3-BC30-4E1A-B405-0A13A966E45A@dilger.ca>
2011-08-01 14:00 ` Ted Ts'o
0 siblings, 2 replies; 6+ messages in thread
From: Aditya Kali @ 2011-07-20 18:40 UTC (permalink / raw)
To: linux-ext4; +Cc: Aditya Kali
This patch is an attempt towards supporting quotas as first class
feature in ext4. It is based on the proposal at:
https://ext4.wiki.kernel.org/index.php/Design_For_1st_Class_Quota_in_Ext4
This patch introduces a new feature - EXT4_FEATURE_RO_COMPAT_QUOTA which, when
turned on, enables quota accounting at mount time iteself. Also, the
quota inodes are stored in two additional superblock fields.
Some changes introduced by this patch that should be pointed out are:
1) Two new ext4-superblock fields - s_usr_quota_inum and s_grp_quota_inum
for storing the quota inodes in use.
2) Quotas are turned on at mount time irrespective of the quota mount options.
Thus the mount options 'quota', 'usrquota' and 'grpquota' are completely
ignored.
3) Default quota inodes are: inode#3 for tracking userquota and inode#4 for
tracking group quota. The superblock fields can be set to use other inodes
as well.
4) mke2fs or tune2fs will initialize these inodes when quota feature is
being set. The default reserved inodes will not be visible to user as
regular files.
5) Once quotas are turned on, they cannot be turned off while the FS is
mounted. This is because we do not want to let the quota get inconsistent.
6) Since the quota inodes are hidden, some of the utilities from quota-tools
will no longer work correctly. Instead, e2fsprogs will include support for
fixing the quota files.
7) Support is only for QFMT_VFS_V1 quota file format.
Signed-off-by: Aditya Kali <adityakali@google.com>
---
fs/ext4/ext4.h | 10 ++++++-
fs/ext4/super.c | 67 ++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 1921392..256fdd8 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1062,7 +1062,9 @@ struct ext4_super_block {
__u8 s_last_error_func[32]; /* function where the error happened */
#define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
__u8 s_mount_opts[64];
- __le32 s_reserved[112]; /* Padding to the end of the block */
+ __le32 s_usr_quota_inum; /* inode for tracking user quota */
+ __le32 s_grp_quota_inum; /* inode for tracking group quota */
+ __le32 s_reserved[110]; /* Padding to the end of the block */
};
#define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
@@ -1138,6 +1140,7 @@ struct ext4_sb_info {
#ifdef CONFIG_QUOTA
char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
int s_jquota_fmt; /* Format of quota to use */
+ unsigned long s_qf_inums[MAXQUOTAS]; /* Quota file inodes */
#endif
unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
struct rb_root system_blks;
@@ -1234,6 +1237,8 @@ static inline struct timespec ext4_current_time(struct inode *inode)
static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
{
return ino == EXT4_ROOT_INO ||
+ ino == EXT4_USR_QUOTA_INO ||
+ ino == EXT4_GRP_QUOTA_INO ||
ino == EXT4_JOURNAL_INO ||
ino == EXT4_RESIZE_INO ||
(ino >= EXT4_FIRST_INO(sb) &&
@@ -1394,7 +1399,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
- EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE| \
+ EXT4_FEATURE_RO_COMPAT_QUOTA)
/*
* Default values for user and/or group using reserved blocks
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 9ea71aa..dd6590d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1196,8 +1196,7 @@ static int ext4_acquire_dquot(struct dquot *dquot);
static int ext4_release_dquot(struct dquot *dquot);
static int ext4_mark_dquot_dirty(struct dquot *dquot);
static int ext4_write_info(struct super_block *sb, int type);
-static int ext4_quota_on(struct super_block *sb, int type, int format_id,
- struct path *path);
+static int ext4_quota_on(struct super_block *sb, int type, int format_id);
static int ext4_quota_off(struct super_block *sb, int type);
static int ext4_quota_on_mount(struct super_block *sb, int type);
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
@@ -1217,7 +1216,7 @@ static const struct dquot_operations ext4_quota_operations = {
};
static const struct quotactl_ops ext4_qctl_operations = {
- .quota_on = ext4_quota_on,
+ .quota_on_meta = ext4_quota_on,
.quota_off = ext4_quota_off,
.quota_sync = dquot_quota_sync,
.get_info = dquot_get_dqinfo,
@@ -3486,6 +3485,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
#ifdef CONFIG_QUOTA
sb->s_qcop = &ext4_qctl_operations;
sb->dq_op = &ext4_quota_operations;
+
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+ sbi->s_qf_inums[USRQUOTA] = es->s_usr_quota_inum;
+ sbi->s_qf_inums[GRPQUOTA] = es->s_grp_quota_inum;
+ }
#endif
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
@@ -3713,8 +3717,19 @@ no_journal:
} else
descr = "out journal";
- ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
- "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
+#ifdef CONFIG_QUOTA
+ /* Enable quotas during mount. */
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) &&
+ !(sb->s_flags & MS_RDONLY)) {
+ ext4_quota_on(sb, USRQUOTA, QFMT_VFS_V1);
+ ext4_quota_on(sb, GRPQUOTA, QFMT_VFS_V1);
+ }
+#endif /* CONFIG_QUOTA */
+
+ ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. quota=%s. "
+ "Opts: %s%s%s", descr,
+ sb_any_quota_loaded(sb) ? "on" : "off",
+ sbi->s_es->s_mount_opts,
*sbi->s_es->s_mount_opts ? "; " : "", orig_data);
if (es->s_error_count)
@@ -4078,6 +4093,12 @@ static int ext4_commit_super(struct super_block *sb, int sync)
es->s_free_inodes_count =
cpu_to_le32(percpu_counter_sum_positive(
&EXT4_SB(sb)->s_freeinodes_counter));
+#ifdef CONFIG_QUOTA
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+ es->s_usr_quota_inum = EXT4_SB(sb)->s_qf_inums[USRQUOTA];
+ es->s_grp_quota_inum = EXT4_SB(sb)->s_qf_inums[GRPQUOTA];
+ }
+#endif
sb->s_dirt = 0;
BUFFER_TRACE(sbh, "marking dirty");
mark_buffer_dirty(sbh);
@@ -4658,24 +4679,22 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
/*
* Standard function to be called on quota_on
*/
-static int ext4_quota_on(struct super_block *sb, int type, int format_id,
- struct path *path)
+static int ext4_quota_on(struct super_block *sb, int type, int format_id)
{
int err;
+ struct inode *qf_inode;
- if (!test_opt(sb, QUOTA))
+ if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) ||
+ !EXT4_SB(sb)->s_qf_inums[type])
return -EINVAL;
- /* Quotafile not on the same filesystem? */
- if (path->mnt->mnt_sb != sb)
- return -EXDEV;
- /* Journaling quota? */
- if (EXT4_SB(sb)->s_qf_names[type]) {
- /* Quotafile not in fs root? */
- if (path->dentry->d_parent != sb->s_root)
- ext4_msg(sb, KERN_WARNING,
- "Quota file not on filesystem root. "
- "Journaled quota will not work");
+ if (!EXT4_SB(sb)->s_qf_inums[type])
+ return -EINVAL;
+
+ qf_inode = ext4_iget(sb, EXT4_SB(sb)->s_qf_inums[type]);
+ if (IS_ERR(qf_inode)) {
+ EXT4_SB(sb)->s_qf_inums[type] = 0;
+ return PTR_ERR(qf_inode);
}
/*
@@ -4683,7 +4702,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
* all updates to the file when we bypass pagecache...
*/
if (EXT4_SB(sb)->s_journal &&
- ext4_should_journal_data(path->dentry->d_inode)) {
+ ext4_should_journal_data(qf_inode)) {
/*
* We don't need to lock updates but journal_flush() could
* otherwise be livelocked...
@@ -4695,7 +4714,11 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
return err;
}
- return dquot_quota_on(sb, type, format_id, path);
+ err = dquot_enable(qf_inode, type, format_id,
+ DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+ iput(qf_inode);
+
+ return err;
}
static int ext4_quota_off(struct super_block *sb, int type)
@@ -4703,6 +4726,10 @@ static int ext4_quota_off(struct super_block *sb, int type)
struct inode *inode = sb_dqopt(sb)->files[type];
handle_t *handle;
+ /* Do not allow turning quotas off. */
+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
+ return -EINVAL;
+
/* Force all delayed allocation blocks to be allocated.
* Caller already holds s_umount sem */
if (test_opt(sb, DELALLOC))
--
1.7.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
[parent not found: <561996F3-BC30-4E1A-B405-0A13A966E45A@dilger.ca>]
* Re: [PATCH] ext4: make quota as first class supported feature
[not found] ` <561996F3-BC30-4E1A-B405-0A13A966E45A@dilger.ca>
@ 2011-07-21 17:24 ` Aditya Kali
0 siblings, 0 replies; 6+ messages in thread
From: Aditya Kali @ 2011-07-21 17:24 UTC (permalink / raw)
To: Andreas Dilger; +Cc: linux-ext4@vger.kernel.org, Johann Lombardi
On Thu, Jul 21, 2011 at 12:02 AM, Andreas Dilger <adilger@dilger.ca> wrote:
> Why support V1 quota, when it has known limits on some of the usage, instead
> of using V2 quotas that are added to ext3/4 already? The Kconfig comment
> for V1 begins:
> This quota format was (is) used by kernels earlier than 2.4.22.
> It would make much more sense to start with V2 for a new feature like this.
>
QFMT_VFS_V1 is actually the format ID of V2 quota format itself. This
is whats in fs/quota/quota_v2.c:
313 static struct quota_format_type v2r1_quota_format = {
314 .qf_fmt_id = QFMT_VFS_V1,
315 .qf_ops = &v2_format_ops,
316 .qf_owner = THIS_MODULE
317 };
So this patch does support the V2 format.
> static const struct quotactl_ops ext4_qctl_operations = {
> - .quota_on = ext4_quota_on,
> + .quota_on_meta = ext4_quota_on,
> .quota_off = ext4_quota_off,
> .quota_sync = dquot_quota_sync,
> .get_info = dquot_get_dqinfo,
> @@ -4658,24 +4679,22 @@ static int ext4_quota_on_mount(struct super_block
> *sb, int type)
> /*
> * Standard function to be called on quota_on
> */
> -static int ext4_quota_on(struct super_block *sb, int type, int format_id,
> - struct path *path)
> +static int ext4_quota_on(struct super_block *sb, int type, int format_id)
> {
> int err;
> + struct inode *qf_inode;
>
> - if (!test_opt(sb, QUOTA))
> + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) ||
> + !EXT4_SB(sb)->s_qf_inums[type])
> return -EINVAL;
>
I also wanted to get input on this change to ext4_quota_on. With this
change, its not possible to use quotas at all without the 'quota'
feature flag set, which might break the current userspace. Do we want
to keep supporting current approach (where quotas can be turned on
with user specified files) as well? This change kinda forces users to
update userspace tools (e2fsprogs & quota-tools) as well.
Thanks,
-Aditya
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ext4: make quota as first class supported feature
2011-07-20 18:40 Aditya Kali
[not found] ` <561996F3-BC30-4E1A-B405-0A13A966E45A@dilger.ca>
@ 2011-08-01 14:00 ` Ted Ts'o
2011-08-01 16:44 ` Ted Ts'o
1 sibling, 1 reply; 6+ messages in thread
From: Ted Ts'o @ 2011-08-01 14:00 UTC (permalink / raw)
To: Aditya Kali; +Cc: linux-ext4
On Wed, Jul 20, 2011 at 11:40:18AM -0700, Aditya Kali wrote:
> This patch is an attempt towards supporting quotas as first class
> feature in ext4. It is based on the proposal at:
> https://ext4.wiki.kernel.org/index.php/Design_For_1st_Class_Quota_in_Ext4
> ...
>
> Signed-off-by: Aditya Kali <adityakali@google.com>
Thanks, added to the ext4 tree.
- Ted
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ext4: make quota as first class supported feature
2011-08-01 14:00 ` Ted Ts'o
@ 2011-08-01 16:44 ` Ted Ts'o
[not found] ` <CAGr1F2F5Je=LFVm0Z9N3+ThstvEf5XiWPYMqjemri6F5aHossQ@mail.gmail.com>
0 siblings, 1 reply; 6+ messages in thread
From: Ted Ts'o @ 2011-08-01 16:44 UTC (permalink / raw)
To: Aditya Kali; +Cc: linux-ext4
[-- Attachment #1: Type: text/plain, Size: 1497 bytes --]
On Mon, Aug 01, 2011 at 10:00:34AM -0400, Ted Ts'o wrote:
> On Wed, Jul 20, 2011 at 11:40:18AM -0700, Aditya Kali wrote:
> > This patch is an attempt towards supporting quotas as first class
> > feature in ext4. It is based on the proposal at:
> > https://ext4.wiki.kernel.org/index.php/Design_For_1st_Class_Quota_in_Ext4
> > ...
> >
> > Signed-off-by: Aditya Kali <adityakali@google.com>
>
> Thanks, added to the ext4 tree.
Hmm, this caused a bunch of quota test failures that shouldn't be
happening....
Ran: 001 002 005 006 007 011 013 014 053 069 070 074 075 076 077 088 089 100 105 112 113 123 124 125 126 127 128 129 130 131 132 133 135 141 169 184 193 198 204 207 208 209 210 211 212 213 214 215 219 221 223 224 225 226 228 230 231 232 233 234 235 236 237 239 240 243
Failures: 219 230 231 232 233 235
It looks like the backwards compatibility with traditional quota
setups isn't quite working correctly:
230 21s ... - output mismatch (see 230.out.bad)
--- 230.out 2011-07-21 19:27:10.000000000 -0400
+++ 230.out.bad 2011-08-01 10:46:59.470964400 -0400
@@ -7,14 +7,10 @@
Write 900k...
Rewrite 1001k...
Write 1000k...
-pwrite64: Disk quota exceeded
Write 4096...
-pwrite64: Disk quota exceeded
Touch 3+4
Touch 5+6
-touch: cannot touch `SCRATCH_MNT/file6': Disk quota exceeded
Touch 5
-touch: cannot touch `SCRATCH_MNT/file5': Disk quota exceeded
...
I may end up putting this off until the next merge window, unless we
can fix this quickly.
- Ted
[-- Attachment #2: xfstests-quota.log.gz --]
[-- Type: application/octet-stream, Size: 57516 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-12-10 0:08 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-10 0:08 [PATCH] ext4: make quota as first class supported feature Aditya Kali
-- strict thread matches above, loose matches on Subject: below --
2011-07-20 18:40 Aditya Kali
[not found] ` <561996F3-BC30-4E1A-B405-0A13A966E45A@dilger.ca>
2011-07-21 17:24 ` Aditya Kali
2011-08-01 14:00 ` Ted Ts'o
2011-08-01 16:44 ` Ted Ts'o
[not found] ` <CAGr1F2F5Je=LFVm0Z9N3+ThstvEf5XiWPYMqjemri6F5aHossQ@mail.gmail.com>
2011-08-05 17:32 ` Aditya Kali
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).