quota: support storing the quota file handles in the quota context

This makes memory management easier because when the quota context is
released, all of the quota file handles get released automatically.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Aditya Kali <adityakali@google.com>
maint-test
Theodore Ts'o 2014-05-10 23:19:12 -04:00
parent d37178bb87
commit cbc1280dc7
3 changed files with 66 additions and 21 deletions

View File

@ -183,7 +183,7 @@ errcode_t quota_write_inode(quota_ctx_t qctx, int qtype)
}
write_dquots(dict, h);
retval = quota_file_close(h);
retval = quota_file_close(qctx, h);
if (retval < 0) {
log_err("Cannot finish IO on new quotafile: %s",
strerror(errno));
@ -251,9 +251,10 @@ static void quota_dnode_free(dnode_t *node,
*/
errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype)
{
int i, err = 0;
errcode_t err;
dict_t *dict;
quota_ctx_t ctx;
int i;
err = ext2fs_get_mem(sizeof(struct quota_ctx), &ctx);
if (err) {
@ -263,6 +264,7 @@ 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))
continue;
err = ext2fs_get_mem(sizeof(dict_t), &dict);
@ -283,6 +285,7 @@ errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs, int qtype)
void quota_release_context(quota_ctx_t *qctx)
{
errcode_t err;
dict_t *dict;
int i;
quota_ctx_t ctx;
@ -298,6 +301,14 @@ void quota_release_context(quota_ctx_t *qctx)
dict_free_nodes(dict);
free(dict);
}
if (ctx->quota_file[i]) {
err = quota_file_close(ctx, ctx->quota_file[i]);
if (err) {
log_err("Cannot close quotafile: %s",
strerror(errno));
ext2fs_free_mem(&ctx->quota_file[i]);
}
}
}
*qctx = NULL;
free(ctx);
@ -541,7 +552,7 @@ errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, int type)
return err;
}
err = quota_file_open(qh, qctx->fs, qf_ino, type, -1, 0);
err = quota_file_open(qctx, qh, qf_ino, type, -1, 0);
if (err) {
log_err("Open quota file failed");
goto out;
@ -549,7 +560,7 @@ errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, int type)
quota_read_all_dquots(qh, qctx, 1);
err = quota_file_close(qh);
err = quota_file_close(qctx, qh);
if (err) {
log_err("Cannot finish IO on new quotafile: %s",
strerror(errno));
@ -575,15 +586,12 @@ errcode_t quota_compare_and_update(quota_ctx_t qctx, int qtype,
struct dquot *dq;
dnode_t *n;
dict_t *dict = qctx->quota_dict[qtype];
ext2_ino_t qf_ino;
errcode_t err = 0;
if (!dict)
goto out;
qf_ino = qtype == USRQUOTA ? fs->super->s_usr_quota_inum :
fs->super->s_grp_quota_inum;
err = quota_file_open(&qh, fs, qf_ino, qtype, -1, 0);
err = quota_file_open(qctx, &qh, 0, qtype, -1, 0);
if (err) {
log_err("Open quota file failed");
goto out;
@ -612,7 +620,7 @@ errcode_t quota_compare_and_update(quota_ctx_t qctx, int qtype,
*usage_inconsistent = scan_data.usage_is_inconsistent;
out_close_qh:
err = quota_file_close(&qh);
err = quota_file_close(qctx, &qh);
if (err) {
log_err("Cannot close quotafile: %s", error_message(errno));
if (qh.qh_qf.e2_file)

View File

@ -197,11 +197,16 @@ static unsigned int quota_read_nomount(struct quota_file *qf,
/*
* Detect quota format and initialize quota IO
*/
errcode_t quota_file_open(struct quota_handle *h, ext2_filsys fs,
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_filsys fs = qctx->fs;
ext2_file_t e2_file;
errcode_t err;
int allocated_handle = 0;
if (type >= MAXQUOTAS)
return EINVAL;
if (fmt == -1)
fmt = QFMT_VFS_V1;
@ -210,18 +215,42 @@ errcode_t quota_file_open(struct quota_handle *h, ext2_filsys fs,
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;
}
log_debug("Opening quota ino=%lu, type=%d", qf_ino, type);
err = ext2fs_file_open(fs, qf_ino, flags, &e2_file);
if (err) {
log_err("ext2fs_file_open failed: %s", error_message(err));
return err;
}
h->qh_qf.e2_file = e2_file;
if (!h) {
if (qctx->quota_file[type]) {
h = qctx->quota_file[type];
if (((flags & EXT2_FILE_WRITE) == 0) ||
(h->qh_file_flags & EXT2_FILE_WRITE))
return 0;
(void) quota_file_close(qctx, h);
}
err = ext2fs_get_mem(sizeof(struct quota_handle), &h);
if (err) {
log_err("Unable to allocate quota handle");
return err;
}
allocated_handle = 1;
}
h->qh_qf.e2_file = e2_file;
h->qh_qf.fs = fs;
h->qh_qf.ino = qf_ino;
h->e2fs_write = quota_write_nomount;
h->e2fs_read = quota_read_nomount;
h->qh_file_flags = flags;
h->qh_io_flags = 0;
h->qh_type = type;
h->qh_fmt = fmt;
@ -231,17 +260,22 @@ errcode_t quota_file_open(struct quota_handle *h, ext2_filsys fs,
if (h->qh_ops->check_file &&
(h->qh_ops->check_file(h, type, fmt) == 0)) {
log_err("qh_ops->check_file failed");
ext2fs_file_close(e2_file);
return -1;
goto errout;
}
if (h->qh_ops->init_io && (h->qh_ops->init_io(h) < 0)) {
log_err("qh_ops->init_io failed");
ext2fs_file_close(e2_file);
return -1;
goto errout;
}
if (allocated_handle)
qctx->quota_file[type] = h;
return 0;
errout:
ext2fs_file_close(e2_file);
if (allocated_handle)
ext2fs_free_mem(&h);
return -1;
}
static errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino)
@ -307,12 +341,12 @@ errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, in
goto out_err;
}
h->qh_qf.ino = qf_inum;
h->qh_file_flags = EXT2_FILE_WRITE | EXT2_FILE_CREATE;
h->e2fs_write = quota_write_nomount;
h->e2fs_read = quota_read_nomount;
log_debug("Creating quota ino=%lu, type=%d", qf_inum, type);
err = ext2fs_file_open(fs, qf_inum,
EXT2_FILE_WRITE | EXT2_FILE_CREATE, &e2_file);
err = ext2fs_file_open(fs, qf_inum, h->qh_file_flags, &e2_file);
if (err) {
log_err("ext2fs_file_open failed: %d", err);
goto out_err;
@ -345,7 +379,7 @@ out_err:
/*
* Close quotafile and release handle
*/
errcode_t quota_file_close(struct quota_handle *h)
errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h)
{
if (h->qh_io_flags & IOFL_INFODIRTY) {
if (h->qh_ops->write_info && h->qh_ops->write_info(h) < 0)
@ -366,7 +400,8 @@ errcode_t quota_file_close(struct quota_handle *h)
ext2fs_file_set_size2(h->qh_qf.e2_file, new_size);
ext2fs_file_close(h->qh_qf.e2_file);
}
if (qctx->quota_file[h->qh_type] == h)
ext2fs_free_mem(&qctx->quota_file[h->qh_type]);
return 0;
}

View File

@ -53,6 +53,7 @@ typedef struct quota_ctx *quota_ctx_t;
struct quota_ctx {
ext2_filsys fs;
dict_t *quota_dict[MAXQUOTAS];
struct quota_handle *quota_file[MAXQUOTAS];
};
/*
@ -105,6 +106,7 @@ struct quota_file {
struct quota_handle {
int qh_type; /* Type of quotafile */
int qh_fmt; /* Quotafile format */
int qh_file_flags;
int qh_io_flags; /* IO flags for file */
struct quota_file qh_qf;
unsigned int (*e2fs_read)(struct quota_file *qf, ext2_loff_t offset,
@ -171,7 +173,7 @@ 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(struct quota_handle *h, ext2_filsys fs,
errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
ext2_ino_t qf_ino, int type, int fmt, int flags);
@ -180,7 +182,7 @@ errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs,
int type, int fmt);
/* Close quotafile */
errcode_t quota_file_close(struct quota_handle *h);
errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h);
/* Get empty quota structure */
struct dquot *get_empty_dquot(void);