mirror of
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
synced 2024-11-24 02:25:03 +08:00
Clean up codes for adding new quota type
Project quota related fields are reserved in Linux kernel. As a preparation for it, this patch cleans up quota codes of e2fsprogs so as to make it easier to add new quota type(s). Signed-off-by: Li Xi <lixi@ddn.com> Signed-off-by: Wang Shilong <wshilong@ddn.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
0f26747167
commit
2d2d799c72
@ -42,7 +42,7 @@ static int load_quota_ctx(char *progname)
|
||||
if (current_qctx)
|
||||
return 0;
|
||||
|
||||
retval = quota_init_context(¤t_qctx, current_fs, -1);
|
||||
retval = quota_init_context(¤t_qctx, current_fs, QUOTA_ALL_BIT);
|
||||
if (retval) {
|
||||
com_err(current_fs->device_name, retval,
|
||||
"while trying to load quota information");
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "debugfs.h"
|
||||
#include "uuid/uuid.h"
|
||||
#include "e2p/e2p.h"
|
||||
#include "support/quotaio.h"
|
||||
|
||||
static struct ext2_super_block set_sb;
|
||||
static struct ext2_inode_large set_inode;
|
||||
|
@ -954,6 +954,41 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the passed ino is one of the used superblock quota inodes.
|
||||
*
|
||||
* Before the quota inodes were journaled, older superblock quota inodes
|
||||
* were just regular files in the filesystem and not reserved inodes. This
|
||||
* checks if the passed ino is one of the s_*_quota_inum superblock fields,
|
||||
* which may not always be the same as the EXT4_*_QUOTA_INO fields.
|
||||
*/
|
||||
static int quota_inum_is_super(struct ext2_super_block *sb, ext2_ino_t ino)
|
||||
{
|
||||
enum quota_type qtype;
|
||||
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++)
|
||||
if (*quota_sb_inump(sb, qtype) == ino)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the passed ino is one of the reserved quota inodes.
|
||||
* This checks if the inode number is one of the reserved EXT4_*_QUOTA_INO
|
||||
* inodes. These inodes may or may not be in use by the quota feature.
|
||||
*/
|
||||
static int quota_inum_is_reserved(ext2_filsys fs, ext2_ino_t ino)
|
||||
{
|
||||
enum quota_type qtype;
|
||||
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++)
|
||||
if (quota_type2inum(qtype, fs->super) == ino)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void e2fsck_pass1(e2fsck_t ctx)
|
||||
{
|
||||
int i;
|
||||
@ -1502,12 +1537,10 @@ void e2fsck_pass1(e2fsck_t ctx)
|
||||
inode_size, "pass1");
|
||||
failed_csum = 0;
|
||||
}
|
||||
} else if ((ino == EXT4_USR_QUOTA_INO) ||
|
||||
(ino == EXT4_GRP_QUOTA_INO)) {
|
||||
} else if (quota_inum_is_reserved(fs, ino)) {
|
||||
ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
|
||||
if (ext2fs_has_feature_quota(fs->super) &&
|
||||
((fs->super->s_usr_quota_inum == ino) ||
|
||||
(fs->super->s_grp_quota_inum == ino))) {
|
||||
quota_inum_is_super(fs->super, ino)) {
|
||||
if (!LINUX_S_ISREG(inode->i_mode) &&
|
||||
fix_problem(ctx, PR_1_QUOTA_BAD_MODE,
|
||||
&pctx)) {
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "problem.h"
|
||||
|
||||
static void move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino,
|
||||
ext2_ino_t to_ino, int qtype)
|
||||
ext2_ino_t to_ino, enum quota_type qtype)
|
||||
{
|
||||
struct ext2_inode inode;
|
||||
errcode_t retval;
|
||||
@ -61,6 +61,8 @@ void e2fsck_hide_quota(e2fsck_t ctx)
|
||||
struct ext2_super_block *sb = ctx->fs->super;
|
||||
struct problem_context pctx;
|
||||
ext2_filsys fs = ctx->fs;
|
||||
enum quota_type qtype;
|
||||
ext2_ino_t quota_ino;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
|
||||
@ -68,22 +70,14 @@ void e2fsck_hide_quota(e2fsck_t ctx)
|
||||
!ext2fs_has_feature_quota(sb))
|
||||
return;
|
||||
|
||||
pctx.ino = sb->s_usr_quota_inum;
|
||||
if (sb->s_usr_quota_inum &&
|
||||
(sb->s_usr_quota_inum != EXT4_USR_QUOTA_INO) &&
|
||||
fix_problem(ctx, PR_0_HIDE_QUOTA, &pctx)) {
|
||||
move_quota_inode(fs, sb->s_usr_quota_inum, EXT4_USR_QUOTA_INO,
|
||||
USRQUOTA);
|
||||
sb->s_usr_quota_inum = EXT4_USR_QUOTA_INO;
|
||||
}
|
||||
|
||||
pctx.ino = sb->s_grp_quota_inum;
|
||||
if (sb->s_grp_quota_inum &&
|
||||
(sb->s_grp_quota_inum != EXT4_GRP_QUOTA_INO) &&
|
||||
fix_problem(ctx, PR_0_HIDE_QUOTA, &pctx)) {
|
||||
move_quota_inode(fs, sb->s_grp_quota_inum, EXT4_GRP_QUOTA_INO,
|
||||
GRPQUOTA);
|
||||
sb->s_grp_quota_inum = EXT4_GRP_QUOTA_INO;
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
pctx.ino = *quota_sb_inump(sb, qtype);
|
||||
quota_ino = quota_type2inum(qtype, fs->super);
|
||||
if (pctx.ino && (pctx.ino != quota_ino) &&
|
||||
fix_problem(ctx, PR_0_HIDE_QUOTA, &pctx)) {
|
||||
move_quota_inode(fs, pctx.ino, quota_ino, qtype);
|
||||
*quota_sb_inump(sb, qtype) = quota_ino;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1338,7 +1338,8 @@ int main (int argc, char *argv[])
|
||||
int old_bitmaps;
|
||||
__u32 features[3];
|
||||
char *cp;
|
||||
int qtype = -99; /* quota type */
|
||||
unsigned int qtype_bits = 0;
|
||||
enum quota_type qtype;
|
||||
|
||||
clear_problem_context(&pctx);
|
||||
sigcatcher_setup();
|
||||
@ -1778,13 +1779,12 @@ print_unsupp_features:
|
||||
|
||||
if (ext2fs_has_feature_quota(sb)) {
|
||||
/* Quotas were enabled. Do quota accounting during fsck. */
|
||||
if ((sb->s_usr_quota_inum && sb->s_grp_quota_inum) ||
|
||||
(!sb->s_usr_quota_inum && !sb->s_grp_quota_inum))
|
||||
qtype = -1;
|
||||
else
|
||||
qtype = sb->s_usr_quota_inum ? USRQUOTA : GRPQUOTA;
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
if (*quota_sb_inump(sb, qtype) != 0)
|
||||
qtype_bits |= 1 << qtype;
|
||||
}
|
||||
|
||||
quota_init_context(&ctx->qctx, ctx->fs, qtype);
|
||||
quota_init_context(&ctx->qctx, ctx->fs, qtype_bits);
|
||||
}
|
||||
|
||||
run_result = e2fsck_run(ctx);
|
||||
@ -1826,18 +1826,18 @@ no_journal:
|
||||
ctx->device_name : ctx->filesystem_name);
|
||||
exit_value |= FSCK_CANCELED;
|
||||
} else if (ctx->qctx && !ctx->invalid_bitmaps) {
|
||||
int i, needs_writeout;
|
||||
int needs_writeout;
|
||||
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
if (qtype != -1 && qtype != i)
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
if (((1 << qtype) & qtype_bits) == 0)
|
||||
continue;
|
||||
needs_writeout = 0;
|
||||
pctx.num = i;
|
||||
retval = quota_compare_and_update(ctx->qctx, i,
|
||||
pctx.num = qtype;
|
||||
retval = quota_compare_and_update(ctx->qctx, qtype,
|
||||
&needs_writeout);
|
||||
if ((retval || needs_writeout) &&
|
||||
fix_problem(ctx, PR_6_UPDATE_QUOTAS, &pctx))
|
||||
quota_write_inode(ctx->qctx, i);
|
||||
quota_write_inode(ctx->qctx, 1 << qtype);
|
||||
}
|
||||
quota_release_context(&ctx->qctx);
|
||||
}
|
||||
|
27
lib/e2p/ls.c
27
lib/e2p/ls.c
@ -23,6 +23,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "e2p.h"
|
||||
#include "support/quotaio.h"
|
||||
|
||||
static void print_user (unsigned short uid, FILE *f)
|
||||
{
|
||||
@ -206,11 +207,25 @@ static const char *checksum_type(__u8 type)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *quota_prefix[MAXQUOTAS] = {
|
||||
[USRQUOTA] = "User quota inode:",
|
||||
[GRPQUOTA] = "Group quota inode:",
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert type of quota to written representation
|
||||
*/
|
||||
static const char *quota_type2prefix(enum quota_type qtype)
|
||||
{
|
||||
return quota_prefix[qtype];
|
||||
}
|
||||
|
||||
void list_super2(struct ext2_super_block * sb, FILE *f)
|
||||
{
|
||||
int inode_blocks_per_group;
|
||||
char buf[80], *str;
|
||||
time_t tm;
|
||||
enum quota_type qtype;
|
||||
|
||||
inode_blocks_per_group = (((sb->s_inodes_per_group *
|
||||
EXT2_INODE_SIZE(sb)) +
|
||||
@ -434,12 +449,12 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
|
||||
fprintf(f, "MMP update interval: %u\n",
|
||||
sb->s_mmp_update_interval);
|
||||
}
|
||||
if (sb->s_usr_quota_inum)
|
||||
fprintf(f, "User quota inode: %u\n",
|
||||
sb->s_usr_quota_inum);
|
||||
if (sb->s_grp_quota_inum)
|
||||
fprintf(f, "Group quota inode: %u\n",
|
||||
sb->s_grp_quota_inum);
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
if (*quota_sb_inump(sb, qtype) != 0)
|
||||
fprintf(f, "%-26s%u\n",
|
||||
quota_type2prefix(qtype),
|
||||
*quota_sb_inump(sb, qtype));
|
||||
}
|
||||
|
||||
if (ext2fs_has_feature_metadata_csum(sb)) {
|
||||
fprintf(f, "Checksum type: %s\n",
|
||||
|
@ -67,7 +67,7 @@ static void print_dquot(const char *desc EXT2FS_ATTR((unused)),
|
||||
* Returns 0 if not able to find the quota file, otherwise returns its
|
||||
* inode number.
|
||||
*/
|
||||
int quota_file_exists(ext2_filsys fs, int qtype)
|
||||
int quota_file_exists(ext2_filsys fs, enum quota_type qtype)
|
||||
{
|
||||
char qf_name[256];
|
||||
errcode_t ret;
|
||||
@ -89,12 +89,11 @@ int quota_file_exists(ext2_filsys fs, int qtype)
|
||||
/*
|
||||
* Set the value for reserved quota inode number field in superblock.
|
||||
*/
|
||||
void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, int qtype)
|
||||
void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype)
|
||||
{
|
||||
ext2_ino_t *inump;
|
||||
|
||||
inump = (qtype == USRQUOTA) ? &fs->super->s_usr_quota_inum :
|
||||
&fs->super->s_grp_quota_inum;
|
||||
inump = quota_sb_inump(fs->super, qtype);
|
||||
|
||||
log_debug("setting quota ino in superblock: ino=%u, type=%d", ino,
|
||||
qtype);
|
||||
@ -102,7 +101,7 @@ void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, int qtype)
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
}
|
||||
|
||||
errcode_t quota_remove_inode(ext2_filsys fs, int qtype)
|
||||
errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype)
|
||||
{
|
||||
ext2_ino_t qf_ino;
|
||||
errcode_t retval;
|
||||
@ -112,8 +111,7 @@ errcode_t quota_remove_inode(ext2_filsys fs, int qtype)
|
||||
log_err("Couldn't read bitmaps: %s", error_message(retval));
|
||||
return retval;
|
||||
}
|
||||
qf_ino = (qtype == USRQUOTA) ? fs->super->s_usr_quota_inum :
|
||||
fs->super->s_grp_quota_inum;
|
||||
qf_ino = *quota_sb_inump(fs->super, qtype);
|
||||
quota_set_sb_inum(fs, 0, qtype);
|
||||
/* Truncate the inode only if its a reserved one. */
|
||||
if (qf_ino < EXT2_FIRST_INODE(fs->super))
|
||||
@ -145,9 +143,10 @@ static void write_dquots(dict_t *dict, struct quota_handle *qh)
|
||||
}
|
||||
}
|
||||
|
||||
errcode_t quota_write_inode(quota_ctx_t qctx, int qtype)
|
||||
errcode_t quota_write_inode(quota_ctx_t qctx, unsigned int qtype_bits)
|
||||
{
|
||||
int retval = 0, i;
|
||||
int retval = 0;
|
||||
enum quota_type qtype;
|
||||
dict_t *dict;
|
||||
ext2_filsys fs;
|
||||
struct quota_handle *h = NULL;
|
||||
@ -170,15 +169,15 @@ errcode_t quota_write_inode(quota_ctx_t qctx, int qtype)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
if ((qtype != -1) && (i != qtype))
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
if (((1 << qtype) & qtype_bits) == 0)
|
||||
continue;
|
||||
|
||||
dict = qctx->quota_dict[i];
|
||||
dict = qctx->quota_dict[qtype];
|
||||
if (!dict)
|
||||
continue;
|
||||
|
||||
retval = quota_file_create(h, fs, i, fmt);
|
||||
retval = quota_file_create(h, fs, qtype, fmt);
|
||||
if (retval < 0) {
|
||||
log_err("Cannot initialize io on quotafile");
|
||||
continue;
|
||||
@ -196,7 +195,7 @@ errcode_t quota_write_inode(quota_ctx_t qctx, int qtype)
|
||||
}
|
||||
|
||||
/* Set quota inode numbers in superblock. */
|
||||
quota_set_sb_inum(fs, h->qh_qf.ino, i);
|
||||
quota_set_sb_inum(fs, h->qh_qf.ino, qtype);
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
ext2fs_mark_bb_dirty(fs);
|
||||
fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
|
||||
@ -232,11 +231,18 @@ static int dict_uint_cmp(const void *a, const void *b)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline qid_t get_qid(struct ext2_inode *inode, int qtype)
|
||||
static inline qid_t get_qid(struct ext2_inode *inode, enum quota_type qtype)
|
||||
{
|
||||
if (qtype == USRQUOTA)
|
||||
switch (qtype) {
|
||||
case USRQUOTA:
|
||||
return inode_uid(*inode);
|
||||
return inode_gid(*inode);
|
||||
case GRPQUOTA:
|
||||
return inode_gid(*inode);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void quota_dnode_free(dnode_t *node,
|
||||
@ -251,12 +257,13 @@ static void quota_dnode_free(dnode_t *node,
|
||||
/*
|
||||
* Set up the quota tracking data structures.
|
||||
*/
|
||||
errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype)
|
||||
errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs,
|
||||
unsigned int qtype_bits)
|
||||
{
|
||||
errcode_t err;
|
||||
dict_t *dict;
|
||||
quota_ctx_t ctx;
|
||||
int i;
|
||||
enum quota_type qtype;
|
||||
|
||||
err = ext2fs_get_mem(sizeof(struct quota_ctx), &ctx);
|
||||
if (err) {
|
||||
@ -265,9 +272,9 @@ errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype)
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(struct quota_ctx));
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
ctx->quota_file[i] = NULL;
|
||||
if ((qtype != -1) && (i != qtype))
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
ctx->quota_file[qtype] = NULL;
|
||||
if (((1 << qtype) & qtype_bits) == 0)
|
||||
continue;
|
||||
err = ext2fs_get_mem(sizeof(dict_t), &dict);
|
||||
if (err) {
|
||||
@ -275,7 +282,7 @@ errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype)
|
||||
quota_release_context(&ctx);
|
||||
return err;
|
||||
}
|
||||
ctx->quota_dict[i] = dict;
|
||||
ctx->quota_dict[qtype] = dict;
|
||||
dict_init(dict, DICTCOUNT_T_MAX, dict_uint_cmp);
|
||||
dict_set_allocator(dict, NULL, quota_dnode_free, NULL);
|
||||
}
|
||||
@ -289,26 +296,26 @@ void quota_release_context(quota_ctx_t *qctx)
|
||||
{
|
||||
errcode_t err;
|
||||
dict_t *dict;
|
||||
int i;
|
||||
enum quota_type qtype;
|
||||
quota_ctx_t ctx;
|
||||
|
||||
if (!qctx)
|
||||
return;
|
||||
|
||||
ctx = *qctx;
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
dict = ctx->quota_dict[i];
|
||||
ctx->quota_dict[i] = 0;
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
dict = ctx->quota_dict[qtype];
|
||||
ctx->quota_dict[qtype] = 0;
|
||||
if (dict) {
|
||||
dict_free_nodes(dict);
|
||||
free(dict);
|
||||
}
|
||||
if (ctx->quota_file[i]) {
|
||||
err = quota_file_close(ctx, ctx->quota_file[i]);
|
||||
if (ctx->quota_file[qtype]) {
|
||||
err = quota_file_close(ctx, ctx->quota_file[qtype]);
|
||||
if (err) {
|
||||
log_err("Cannot close quotafile: %s",
|
||||
strerror(errno));
|
||||
ext2fs_free_mem(&ctx->quota_file[i]);
|
||||
ext2fs_free_mem(&ctx->quota_file[qtype]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -346,7 +353,7 @@ void quota_data_add(quota_ctx_t qctx, struct ext2_inode *inode,
|
||||
{
|
||||
struct dquot *dq;
|
||||
dict_t *dict;
|
||||
int i;
|
||||
enum quota_type qtype;
|
||||
|
||||
if (!qctx)
|
||||
return;
|
||||
@ -354,10 +361,10 @@ void quota_data_add(quota_ctx_t qctx, struct ext2_inode *inode,
|
||||
log_debug("ADD_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino,
|
||||
inode_uid(*inode),
|
||||
inode_gid(*inode), space);
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
dict = qctx->quota_dict[i];
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
dict = qctx->quota_dict[qtype];
|
||||
if (dict) {
|
||||
dq = get_dq(dict, get_qid(inode, i));
|
||||
dq = get_dq(dict, get_qid(inode, qtype));
|
||||
if (dq)
|
||||
dq->dq_dqb.dqb_curspace += space;
|
||||
}
|
||||
@ -373,7 +380,7 @@ void quota_data_sub(quota_ctx_t qctx, struct ext2_inode *inode,
|
||||
{
|
||||
struct dquot *dq;
|
||||
dict_t *dict;
|
||||
int i;
|
||||
enum quota_type qtype;
|
||||
|
||||
if (!qctx)
|
||||
return;
|
||||
@ -381,10 +388,10 @@ void quota_data_sub(quota_ctx_t qctx, struct ext2_inode *inode,
|
||||
log_debug("SUB_DATA: Inode: %u, UID/GID: %u/%u, space: %ld", ino,
|
||||
inode_uid(*inode),
|
||||
inode_gid(*inode), space);
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
dict = qctx->quota_dict[i];
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
dict = qctx->quota_dict[qtype];
|
||||
if (dict) {
|
||||
dq = get_dq(dict, get_qid(inode, i));
|
||||
dq = get_dq(dict, get_qid(inode, qtype));
|
||||
dq->dq_dqb.dqb_curspace -= space;
|
||||
}
|
||||
}
|
||||
@ -398,7 +405,7 @@ void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode *inode,
|
||||
{
|
||||
struct dquot *dq;
|
||||
dict_t *dict;
|
||||
int i;
|
||||
enum quota_type qtype;
|
||||
|
||||
if (!qctx)
|
||||
return;
|
||||
@ -406,10 +413,10 @@ void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode *inode,
|
||||
log_debug("ADJ_INODE: Inode: %u, UID/GID: %u/%u, adjust: %d", ino,
|
||||
inode_uid(*inode),
|
||||
inode_gid(*inode), adjust);
|
||||
for (i = 0; i < MAXQUOTAS; i++) {
|
||||
dict = qctx->quota_dict[i];
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
|
||||
dict = qctx->quota_dict[qtype];
|
||||
if (dict) {
|
||||
dq = get_dq(dict, get_qid(inode, i));
|
||||
dq = get_dq(dict, get_qid(inode, qtype));
|
||||
dq->dq_dqb.dqb_curinodes += adjust;
|
||||
}
|
||||
}
|
||||
@ -542,7 +549,8 @@ static errcode_t quota_write_all_dquots(struct quota_handle *qh,
|
||||
/*
|
||||
* Updates the in-memory quota limits from the given quota inode.
|
||||
*/
|
||||
errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, int type)
|
||||
errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino,
|
||||
enum quota_type qtype)
|
||||
{
|
||||
struct quota_handle *qh;
|
||||
errcode_t err;
|
||||
@ -556,7 +564,7 @@ errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, int type)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = quota_file_open(qctx, qh, qf_ino, type, -1, 0);
|
||||
err = quota_file_open(qctx, qh, qf_ino, qtype, -1, 0);
|
||||
if (err) {
|
||||
log_err("Open quota file failed");
|
||||
goto out;
|
||||
@ -581,7 +589,7 @@ out:
|
||||
* on disk and updates the limits in qctx->quota_dict. 'usage_inconsistent' is
|
||||
* set to 1 if the supplied and on-disk quota usage values are not identical.
|
||||
*/
|
||||
errcode_t quota_compare_and_update(quota_ctx_t qctx, int qtype,
|
||||
errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype,
|
||||
int *usage_inconsistent)
|
||||
{
|
||||
struct quota_handle qh;
|
||||
@ -632,3 +640,32 @@ out_close_qh:
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int parse_quota_opts(const char *opts, int (*func)(), void *data)
|
||||
{
|
||||
char *buf, *token, *next, *p;
|
||||
int len;
|
||||
int ret = 0;
|
||||
|
||||
len = strlen(opts);
|
||||
buf = malloc(len + 1);
|
||||
if (!buf) {
|
||||
fprintf(stderr,
|
||||
"Couldn't allocate memory to parse quota options!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
strcpy(buf, opts);
|
||||
for (token = buf; token && *token; token = next) {
|
||||
p = strchr(token, ',');
|
||||
next = 0;
|
||||
if (p) {
|
||||
*p = 0;
|
||||
next = p + 1;
|
||||
}
|
||||
ret = func(token, data);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "quotaio.h"
|
||||
@ -37,15 +38,31 @@ struct disk_dqheader {
|
||||
/**
|
||||
* Convert type of quota to written representation
|
||||
*/
|
||||
const char *type2name(int type)
|
||||
const char *quota_type2name(enum quota_type qtype)
|
||||
{
|
||||
return extensions[type];
|
||||
if (qtype < 0 || qtype >= MAXQUOTAS)
|
||||
return "unknown";
|
||||
return extensions[qtype];
|
||||
}
|
||||
|
||||
ext2_ino_t quota_type2inum(enum quota_type qtype,
|
||||
struct ext2_super_block *sb)
|
||||
{
|
||||
switch (qtype) {
|
||||
case USRQUOTA:
|
||||
return EXT4_USR_QUOTA_INO;
|
||||
case GRPQUOTA:
|
||||
return EXT4_GRP_QUOTA_INO;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a quota file name for given type and format.
|
||||
*/
|
||||
const char *quota_get_qf_name(int type, int fmt, char *buf)
|
||||
const char *quota_get_qf_name(enum quota_type type, int fmt, char *buf)
|
||||
{
|
||||
if (!buf)
|
||||
return NULL;
|
||||
@ -99,11 +116,16 @@ errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino)
|
||||
{
|
||||
struct ext2_inode inode;
|
||||
errcode_t err;
|
||||
enum quota_type qtype;
|
||||
|
||||
if ((err = ext2fs_read_inode(fs, ino, &inode)))
|
||||
return err;
|
||||
|
||||
if ((ino == EXT4_USR_QUOTA_INO) || (ino == EXT4_GRP_QUOTA_INO)) {
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++)
|
||||
if (ino == quota_type2inum(qtype, fs->super))
|
||||
break;
|
||||
|
||||
if (qtype != MAXQUOTAS) {
|
||||
inode.i_dtime = fs->now ? fs->now : time(0);
|
||||
if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
|
||||
return 0;
|
||||
@ -183,14 +205,15 @@ static unsigned int quota_read_nomount(struct quota_file *qf,
|
||||
* Detect quota format and initialize quota IO
|
||||
*/
|
||||
errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
|
||||
ext2_ino_t qf_ino, int type, int fmt, int flags)
|
||||
ext2_ino_t qf_ino, enum quota_type qtype,
|
||||
int fmt, int flags)
|
||||
{
|
||||
ext2_filsys fs = qctx->fs;
|
||||
ext2_file_t e2_file;
|
||||
errcode_t err;
|
||||
int allocated_handle = 0;
|
||||
|
||||
if (type >= MAXQUOTAS)
|
||||
if (qtype >= MAXQUOTAS)
|
||||
return EINVAL;
|
||||
|
||||
if (fmt == -1)
|
||||
@ -200,14 +223,10 @@ errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (qf_ino == 0) {
|
||||
if (type == USRQUOTA)
|
||||
qf_ino = fs->super->s_usr_quota_inum;
|
||||
else
|
||||
qf_ino = fs->super->s_grp_quota_inum;
|
||||
}
|
||||
if (qf_ino == 0)
|
||||
qf_ino = *quota_sb_inump(fs->super, qtype)
|
||||
|
||||
log_debug("Opening quota ino=%lu, type=%d", qf_ino, type);
|
||||
log_debug("Opening quota ino=%lu, type=%d", qf_ino, qtype);
|
||||
err = ext2fs_file_open(fs, qf_ino, flags, &e2_file);
|
||||
if (err) {
|
||||
log_err("ext2fs_file_open failed: %s", error_message(err));
|
||||
@ -215,8 +234,8 @@ errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
|
||||
}
|
||||
|
||||
if (!h) {
|
||||
if (qctx->quota_file[type]) {
|
||||
h = qctx->quota_file[type];
|
||||
if (qctx->quota_file[qtype]) {
|
||||
h = qctx->quota_file[qtype];
|
||||
if (((flags & EXT2_FILE_WRITE) == 0) ||
|
||||
(h->qh_file_flags & EXT2_FILE_WRITE))
|
||||
return 0;
|
||||
@ -237,13 +256,13 @@ errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
|
||||
h->e2fs_read = quota_read_nomount;
|
||||
h->qh_file_flags = flags;
|
||||
h->qh_io_flags = 0;
|
||||
h->qh_type = type;
|
||||
h->qh_type = qtype;
|
||||
h->qh_fmt = fmt;
|
||||
memset(&h->qh_info, 0, sizeof(h->qh_info));
|
||||
h->qh_ops = "afile_ops_2;
|
||||
|
||||
if (h->qh_ops->check_file &&
|
||||
(h->qh_ops->check_file(h, type, fmt) == 0)) {
|
||||
(h->qh_ops->check_file(h, qtype, fmt) == 0)) {
|
||||
log_err("qh_ops->check_file failed");
|
||||
goto errout;
|
||||
}
|
||||
@ -253,7 +272,7 @@ errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
|
||||
goto errout;
|
||||
}
|
||||
if (allocated_handle)
|
||||
qctx->quota_file[type] = h;
|
||||
qctx->quota_file[qtype] = h;
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
@ -298,7 +317,8 @@ static errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino)
|
||||
/*
|
||||
* Create new quotafile of specified format on given filesystem
|
||||
*/
|
||||
errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, int fmt)
|
||||
errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs,
|
||||
enum quota_type qtype, int fmt)
|
||||
{
|
||||
ext2_file_t e2_file;
|
||||
int err;
|
||||
@ -308,11 +328,8 @@ errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, in
|
||||
fmt = QFMT_VFS_V1;
|
||||
|
||||
h->qh_qf.fs = fs;
|
||||
if (type == USRQUOTA)
|
||||
qf_inum = EXT4_USR_QUOTA_INO;
|
||||
else if (type == GRPQUOTA)
|
||||
qf_inum = EXT4_GRP_QUOTA_INO;
|
||||
else
|
||||
qf_inum = quota_type2inum(qtype, fs->super);
|
||||
if (qf_inum == 0)
|
||||
return -1;
|
||||
|
||||
err = ext2fs_read_bitmaps(fs);
|
||||
@ -338,7 +355,7 @@ errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, in
|
||||
h->qh_qf.e2_file = e2_file;
|
||||
|
||||
h->qh_io_flags = 0;
|
||||
h->qh_type = type;
|
||||
h->qh_type = qtype;
|
||||
h->qh_fmt = fmt;
|
||||
memset(&h->qh_info, 0, sizeof(h->qh_info));
|
||||
h->qh_ops = "afile_ops_2;
|
||||
|
@ -10,9 +10,9 @@
|
||||
* {
|
||||
* quota_ctx_t qctx;
|
||||
*
|
||||
* quota_init_context(&qctx, fs, -1);
|
||||
* quota_init_context(&qctx, fs, QUOTA_ALL_BIT);
|
||||
* {
|
||||
* quota_compute_usage(qctx, -1);
|
||||
* quota_compute_usage(qctx, QUOTA_ALL_BIT);
|
||||
* AND/OR
|
||||
* quota_data_add/quota_data_sub/quota_data_inodes();
|
||||
* }
|
||||
@ -43,9 +43,19 @@
|
||||
|
||||
typedef int64_t qsize_t; /* Type in which we store size limitations */
|
||||
|
||||
#define MAXQUOTAS 2
|
||||
#define USRQUOTA 0
|
||||
#define GRPQUOTA 1
|
||||
enum quota_type {
|
||||
USRQUOTA = 0,
|
||||
GRPQUOTA = 1,
|
||||
MAXQUOTAS = 2,
|
||||
};
|
||||
|
||||
#if MAXQUOTAS > 32
|
||||
#error "cannot have more than 32 quota types to fit in qtype_bits"
|
||||
#endif
|
||||
|
||||
#define QUOTA_USR_BIT (1 << USRQUOTA)
|
||||
#define QUOTA_GRP_BIT (1 << GRPQUOTA)
|
||||
#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT)
|
||||
|
||||
typedef struct quota_ctx *quota_ctx_t;
|
||||
struct dict_t;
|
||||
@ -104,7 +114,7 @@ struct quota_file {
|
||||
|
||||
/* Structure for one opened quota file */
|
||||
struct quota_handle {
|
||||
int qh_type; /* Type of quotafile */
|
||||
enum quota_type qh_type; /* Type of quotafile */
|
||||
int qh_fmt; /* Quotafile format */
|
||||
int qh_file_flags;
|
||||
int qh_io_flags; /* IO flags for file */
|
||||
@ -174,12 +184,13 @@ extern struct quotafile_ops quotafile_ops_meta;
|
||||
/* Open existing quotafile of given type (and verify its format) on given
|
||||
* filesystem. */
|
||||
errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
|
||||
ext2_ino_t qf_ino, int type, int fmt, int flags);
|
||||
ext2_ino_t qf_ino, enum quota_type type,
|
||||
int fmt, int flags);
|
||||
|
||||
|
||||
/* Create new quotafile of specified format on given filesystem */
|
||||
errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs,
|
||||
int type, int fmt);
|
||||
enum quota_type qtype, int fmt);
|
||||
|
||||
/* Close quotafile */
|
||||
errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h);
|
||||
@ -189,7 +200,8 @@ struct dquot *get_empty_dquot(void);
|
||||
|
||||
errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino);
|
||||
|
||||
const char *type2name(int type);
|
||||
const char *quota_type2name(enum quota_type qtype);
|
||||
ext2_ino_t quota_type2inum(enum quota_type qtype, struct ext2_super_block *);
|
||||
|
||||
void update_grace_times(struct dquot *q);
|
||||
|
||||
@ -197,27 +209,48 @@ void update_grace_times(struct dquot *q);
|
||||
than maxlen of extensions[] and fmtnames[] (plus 2) found in quotaio.c */
|
||||
#define QUOTA_NAME_LEN 16
|
||||
|
||||
const char *quota_get_qf_name(int type, int fmt, char *buf);
|
||||
const char *quota_get_qf_name(enum quota_type, int fmt, char *buf);
|
||||
|
||||
/* In mkquota.c */
|
||||
errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype);
|
||||
errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs,
|
||||
unsigned int qtype_bits);
|
||||
void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode *inode, ext2_ino_t ino,
|
||||
int adjust);
|
||||
void quota_data_add(quota_ctx_t qctx, struct ext2_inode *inode, ext2_ino_t ino,
|
||||
qsize_t space);
|
||||
void quota_data_sub(quota_ctx_t qctx, struct ext2_inode *inode, ext2_ino_t ino,
|
||||
qsize_t space);
|
||||
errcode_t quota_write_inode(quota_ctx_t qctx, int qtype);
|
||||
errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, int type);
|
||||
errcode_t quota_write_inode(quota_ctx_t qctx, enum quota_type qtype);
|
||||
errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino,
|
||||
enum quota_type type);
|
||||
errcode_t quota_compute_usage(quota_ctx_t qctx);
|
||||
void quota_release_context(quota_ctx_t *qctx);
|
||||
|
||||
errcode_t quota_remove_inode(ext2_filsys fs, int qtype);
|
||||
int quota_file_exists(ext2_filsys fs, int qtype);
|
||||
void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, int qtype);
|
||||
errcode_t quota_compare_and_update(quota_ctx_t qctx, int qtype,
|
||||
errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype);
|
||||
int quota_file_exists(ext2_filsys fs, enum quota_type qtype);
|
||||
void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype);
|
||||
errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype,
|
||||
int *usage_inconsistent);
|
||||
int parse_quota_opts(const char *opts, int (*func)(), void *data);
|
||||
|
||||
/*
|
||||
* Return pointer to reserved inode field in superblock for given quota type.
|
||||
*
|
||||
* This allows the caller to get or set the quota inode by type without the
|
||||
* need for the quota array to be contiguous in the superbock.
|
||||
*/
|
||||
static inline ext2_ino_t *quota_sb_inump(struct ext2_super_block *sb,
|
||||
enum quota_type qtype)
|
||||
{
|
||||
switch (qtype) {
|
||||
case USRQUOTA:
|
||||
return &sb->s_usr_quota_inum;
|
||||
case GRPQUOTA:
|
||||
return &sb->s_grp_quota_inum;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* GUARD_QUOTAIO_H */
|
||||
|
@ -587,7 +587,7 @@ static void check_reference(struct quota_handle *h, unsigned int blk)
|
||||
"Please run e2fsck (8) to fix it.",
|
||||
blk,
|
||||
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks,
|
||||
type2name(h->qh_type));
|
||||
quota_type2name(h->qh_type));
|
||||
}
|
||||
|
||||
static int report_tree(struct dquot *dquot, unsigned int blk, int depth,
|
||||
|
@ -95,7 +95,8 @@ static int lazy_itable_init;
|
||||
static int packed_meta_blocks;
|
||||
static char *bad_blocks_filename = NULL;
|
||||
static __u32 fs_stride;
|
||||
static int quotatype = -1; /* Initialize both user and group quotas by default */
|
||||
/* Initialize usr/grp quotas by default */
|
||||
static unsigned int quotatype_bits = (QUOTA_USR_BIT | QUOTA_GRP_BIT);
|
||||
static __u64 offset;
|
||||
static blk64_t journal_location = ~0LL;
|
||||
static int proceed_delay = -1;
|
||||
@ -770,12 +771,28 @@ static int set_os(struct ext2_super_block *sb, char *os)
|
||||
|
||||
#define PATH_SET "PATH=/sbin"
|
||||
|
||||
static int option_handle_function(char *token, void *data)
|
||||
{
|
||||
if (!strncmp(token, "usr", 3)) {
|
||||
quotatype_bits |= QUOTA_USR_BIT;
|
||||
} else if (!strncmp(token, "grp", 3)) {
|
||||
quotatype_bits |= QUOTA_GRP_BIT;
|
||||
} else {
|
||||
fprintf(stderr, _("Invalid quotatype parameter: %s\n"),
|
||||
token);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void parse_extended_opts(struct ext2_super_block *param,
|
||||
const char *opts)
|
||||
{
|
||||
char *buf, *token, *next, *p, *arg, *badopt = 0;
|
||||
int len;
|
||||
int r_usage = 0;
|
||||
int ret;
|
||||
|
||||
len = strlen(opts);
|
||||
buf = malloc(len+1);
|
||||
@ -1008,14 +1025,9 @@ static void parse_extended_opts(struct ext2_super_block *param,
|
||||
badopt = token;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(arg, "usr", 3)) {
|
||||
quotatype = 0;
|
||||
} else if (!strncmp(arg, "grp", 3)) {
|
||||
quotatype = 1;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
_("Invalid quotatype parameter: %s\n"),
|
||||
arg);
|
||||
ret = parse_quota_opts(arg, option_handle_function,
|
||||
NULL);
|
||||
if (ret) {
|
||||
r_usage++;
|
||||
continue;
|
||||
}
|
||||
@ -2646,9 +2658,9 @@ static int create_quota_inodes(ext2_filsys fs)
|
||||
{
|
||||
quota_ctx_t qctx;
|
||||
|
||||
quota_init_context(&qctx, fs, -1);
|
||||
quota_init_context(&qctx, fs, QUOTA_ALL_BIT);
|
||||
quota_compute_usage(qctx);
|
||||
quota_write_inode(qctx, quotatype);
|
||||
quota_write_inode(qctx, quotatype_bits);
|
||||
quota_release_context(&qctx);
|
||||
|
||||
return 0;
|
||||
|
134
misc/tune2fs.c
134
misc/tune2fs.c
@ -95,7 +95,7 @@ static int stride_set, stripe_width_set;
|
||||
static char *extended_cmd;
|
||||
static unsigned long new_inode_size;
|
||||
static char *ext_mount_opts;
|
||||
static int usrquota, grpquota;
|
||||
static int quota_enable[MAXQUOTAS];
|
||||
static int rewrite_checksums;
|
||||
static int feature_64bit;
|
||||
static int fsck_requested;
|
||||
@ -958,6 +958,7 @@ static int update_feature_set(ext2_filsys fs, char *features)
|
||||
int type_err;
|
||||
unsigned int mask_err;
|
||||
errcode_t err;
|
||||
enum quota_type qtype;
|
||||
|
||||
#define FEATURE_ON(type, mask) (!(old_features[(type)] & (mask)) && \
|
||||
((&sb->s_feature_compat)[(type)] & (mask)))
|
||||
@ -1265,9 +1266,9 @@ mmp_error:
|
||||
*/
|
||||
if (!Q_flag) {
|
||||
Q_flag = 1;
|
||||
/* Enable both user quota and group quota by default */
|
||||
usrquota = QOPT_ENABLE;
|
||||
grpquota = QOPT_ENABLE;
|
||||
/* Enable all quota by default */
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++)
|
||||
quota_enable[qtype] = QOPT_ENABLE;
|
||||
}
|
||||
ext2fs_clear_feature_quota(sb);
|
||||
}
|
||||
@ -1282,9 +1283,9 @@ mmp_error:
|
||||
fputs(_("\nWarning: '^quota' option overrides '-Q'"
|
||||
"arguments.\n"), stderr);
|
||||
Q_flag = 1;
|
||||
/* Disable both user quota and group quota by default */
|
||||
usrquota = QOPT_DISABLE;
|
||||
grpquota = QOPT_DISABLE;
|
||||
/* Disable all quota by default */
|
||||
for (qtype = 0; qtype < MAXQUOTAS; qtype++)
|
||||
quota_enable[qtype] = QOPT_DISABLE;
|
||||
}
|
||||
|
||||
if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {
|
||||
@ -1406,87 +1407,76 @@ static void handle_quota_options(ext2_filsys fs)
|
||||
{
|
||||
quota_ctx_t qctx;
|
||||
ext2_ino_t qf_ino;
|
||||
enum quota_type qtype;
|
||||
int enable = 0;
|
||||
|
||||
if (!usrquota && !grpquota)
|
||||
for (qtype = 0 ; qtype < MAXQUOTAS; qtype++)
|
||||
if (quota_enable[qtype] != 0)
|
||||
break;
|
||||
if (qtype == MAXQUOTAS)
|
||||
/* Nothing to do. */
|
||||
return;
|
||||
|
||||
quota_init_context(&qctx, fs, -1);
|
||||
|
||||
if (usrquota == QOPT_ENABLE || grpquota == QOPT_ENABLE)
|
||||
quota_init_context(&qctx, fs, QUOTA_ALL_BIT);
|
||||
for (qtype = 0 ; qtype < MAXQUOTAS; qtype++) {
|
||||
if (quota_enable[qtype] == QOPT_ENABLE) {
|
||||
enable = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enable)
|
||||
quota_compute_usage(qctx);
|
||||
|
||||
if (usrquota == QOPT_ENABLE && !fs->super->s_usr_quota_inum) {
|
||||
if ((qf_ino = quota_file_exists(fs, USRQUOTA)) > 0)
|
||||
quota_update_limits(qctx, qf_ino, USRQUOTA);
|
||||
quota_write_inode(qctx, USRQUOTA);
|
||||
} else if (usrquota == QOPT_DISABLE) {
|
||||
quota_remove_inode(fs, USRQUOTA);
|
||||
}
|
||||
|
||||
if (grpquota == QOPT_ENABLE && !fs->super->s_grp_quota_inum) {
|
||||
if ((qf_ino = quota_file_exists(fs, GRPQUOTA)) > 0)
|
||||
quota_update_limits(qctx, qf_ino, GRPQUOTA);
|
||||
quota_write_inode(qctx, GRPQUOTA);
|
||||
} else if (grpquota == QOPT_DISABLE) {
|
||||
quota_remove_inode(fs, GRPQUOTA);
|
||||
for (qtype = 0 ; qtype < MAXQUOTAS; qtype++) {
|
||||
if (quota_enable[qtype] == QOPT_ENABLE &&
|
||||
*quota_sb_inump(fs->super, qtype) == 0) {
|
||||
if ((qf_ino = quota_file_exists(fs, qtype)) > 0)
|
||||
quota_update_limits(qctx, qf_ino, qtype);
|
||||
quota_write_inode(qctx, 1 << qtype);
|
||||
} else if (quota_enable[qtype] == QOPT_DISABLE) {
|
||||
quota_remove_inode(fs, qtype);
|
||||
}
|
||||
}
|
||||
|
||||
quota_release_context(&qctx);
|
||||
|
||||
if ((usrquota == QOPT_ENABLE) || (grpquota == QOPT_ENABLE)) {
|
||||
if (enable) {
|
||||
ext2fs_set_feature_quota(fs->super);
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
} else if (!fs->super->s_usr_quota_inum &&
|
||||
!fs->super->s_grp_quota_inum) {
|
||||
ext2fs_clear_feature_quota(fs->super);
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
} else {
|
||||
for (qtype = 0 ; qtype < MAXQUOTAS; qtype++)
|
||||
if (*quota_sb_inump(fs->super, qtype) != 0)
|
||||
break;
|
||||
if (qtype == MAXQUOTAS) {
|
||||
fs->super->s_feature_ro_compat &=
|
||||
~EXT4_FEATURE_RO_COMPAT_QUOTA;
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void parse_quota_opts(const char *opts)
|
||||
static int option_handle_function(char *token, void *data)
|
||||
{
|
||||
char *buf, *token, *next, *p;
|
||||
int len;
|
||||
|
||||
len = strlen(opts);
|
||||
buf = malloc(len+1);
|
||||
if (!buf) {
|
||||
fputs(_("Couldn't allocate memory to parse quota "
|
||||
"options!\n"), stderr);
|
||||
exit(1);
|
||||
if (strncmp(token, "usr", 3) == 0) {
|
||||
quota_enable[USRQUOTA] = QOPT_ENABLE;
|
||||
} else if (strncmp(token, "^usr", 4) == 0) {
|
||||
quota_enable[USRQUOTA] = QOPT_DISABLE;
|
||||
} else if (strncmp(token, "grp", 3) == 0) {
|
||||
quota_enable[GRPQUOTA] = QOPT_ENABLE;
|
||||
} else if (strncmp(token, "^grp", 4) == 0) {
|
||||
quota_enable[GRPQUOTA] = QOPT_DISABLE;
|
||||
} else {
|
||||
fputs(_("\nBad quota options specified.\n\n"
|
||||
"Following valid quota options are available "
|
||||
"(pass by separating with comma):\n"
|
||||
"\t[^]usr[quota]\n"
|
||||
"\t[^]grp[quota]\n"
|
||||
"\n\n"), stderr);
|
||||
return 1;
|
||||
}
|
||||
strcpy(buf, opts);
|
||||
for (token = buf; token && *token; token = next) {
|
||||
p = strchr(token, ',');
|
||||
next = 0;
|
||||
if (p) {
|
||||
*p = 0;
|
||||
next = p+1;
|
||||
}
|
||||
|
||||
if (strcmp(token, "usrquota") == 0) {
|
||||
usrquota = QOPT_ENABLE;
|
||||
} else if (strcmp(token, "^usrquota") == 0) {
|
||||
usrquota = QOPT_DISABLE;
|
||||
} else if (strcmp(token, "grpquota") == 0) {
|
||||
grpquota = QOPT_ENABLE;
|
||||
} else if (strcmp(token, "^grpquota") == 0) {
|
||||
grpquota = QOPT_DISABLE;
|
||||
} else {
|
||||
fputs(_("\nBad quota options specified.\n\n"
|
||||
"Following valid quota options are available "
|
||||
"(pass by separating with comma):\n"
|
||||
"\t[^]usrquota\n"
|
||||
"\t[^]grpquota\n"
|
||||
"\n\n"), stderr);
|
||||
free(buf);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void parse_e2label_options(int argc, char ** argv)
|
||||
@ -1549,6 +1539,7 @@ static void parse_tune2fs_options(int argc, char **argv)
|
||||
char *tmp;
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
int ret;
|
||||
char optstring[100] = "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:T:U:z:Q:";
|
||||
|
||||
open_flag = 0;
|
||||
@ -1709,7 +1700,10 @@ static void parse_tune2fs_options(int argc, char **argv)
|
||||
break;
|
||||
case 'Q':
|
||||
Q_flag = 1;
|
||||
parse_quota_opts(optarg);
|
||||
ret = parse_quota_opts(optarg, option_handle_function,
|
||||
NULL);
|
||||
if (ret)
|
||||
exit(1);
|
||||
open_flag = EXT2_FLAG_RW;
|
||||
break;
|
||||
case 'r':
|
||||
|
Loading…
Reference in New Issue
Block a user