diff options
Diffstat (limited to 'lib/quota/quotaio.c')
-rw-r--r-- | lib/quota/quotaio.c | 127 |
1 files changed, 74 insertions, 53 deletions
diff --git a/lib/quota/quotaio.c b/lib/quota/quotaio.c index 481d5f57..65fccaa9 100644 --- a/lib/quota/quotaio.c +++ b/lib/quota/quotaio.c @@ -11,6 +11,7 @@ #include <string.h> #include <unistd.h> #include <stdlib.h> +#include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> @@ -18,7 +19,7 @@ #include "common.h" #include "quotaio.h" -static const char extensions[MAXQUOTAS + 2][20] = INITQFNAMES; +static const char * const extensions[MAXQUOTAS] = {"user", "group"}; static const char * const basenames[] = { "", /* undefined */ "quota", /* QFMT_VFS_OLD */ @@ -27,18 +28,10 @@ static const char * const basenames[] = { "aquota" /* QFMT_VFS_V1 */ }; -static const char * const fmtnames[] = { - "vfsold", - "vfsv0", - "vfsv1", - "rpc", - "xfs" -}; - /* Header in all newer quotafiles */ struct disk_dqheader { - u_int32_t dqh_magic; - u_int32_t dqh_version; + __u32 dqh_magic; + __u32 dqh_version; } __attribute__ ((packed)); /** @@ -65,7 +58,6 @@ const char *quota_get_qf_name(int type, int fmt, char *buf) const char *quota_get_qf_path(const char *mntpt, int qtype, int fmt, char *path_buf, size_t path_buf_size) { - struct stat qf_stat; char qf_name[QUOTA_NAME_LEN]; if (!mntpt || !path_buf || !path_buf_size) @@ -106,26 +98,12 @@ void update_grace_times(struct dquot *q) } } -static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr, - e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), - blk64_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *private EXT2FS_ATTR((unused))) -{ - blk64_t block; - - block = *blocknr; - ext2fs_block_alloc_stats2(fs, block, -1); - return 0; -} - static int compute_num_blocks_proc(ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), blk64_t ref_block EXT2FS_ATTR((unused)), int ref_offset EXT2FS_ATTR((unused)), void *private) { - blk64_t block; blk64_t *num_blocks = private; *num_blocks += 1; @@ -136,19 +114,22 @@ errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino) { struct ext2_inode inode; errcode_t err; - int i; if ((err = ext2fs_read_inode(fs, ino, &inode))) return err; - inode.i_dtime = fs->now ? fs->now : time(0); - if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) - return 0; - - ext2fs_block_iterate3(fs, ino, BLOCK_FLAG_READ_ONLY, NULL, - release_blocks_proc, NULL); - - memset(&inode, 0, sizeof(struct ext2_inode)); + if ((ino == EXT4_USR_QUOTA_INO) || (ino == EXT4_GRP_QUOTA_INO)) { + inode.i_dtime = fs->now ? fs->now : time(0); + if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) + return 0; + err = ext2fs_punch(fs, ino, &inode, NULL, 0, ~0ULL); + if (err) + return err; + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + memset(&inode, 0, sizeof(struct ext2_inode)); + } else { + inode.i_flags &= ~EXT2_IMMUTABLE_FL; + } err = ext2fs_write_inode(fs, ino, &inode); return err; } @@ -216,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; @@ -229,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; @@ -249,18 +259,23 @@ 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; + log_err("qh_ops->check_file failed"); + 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; + log_err("qh_ops->init_io failed"); + 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) @@ -270,7 +285,7 @@ static errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino) err = ext2fs_read_inode(fs, ino, &inode); if (err) { - log_err("ex2fs_read_inode failed", ""); + log_err("ex2fs_read_inode failed"); return err; } @@ -322,16 +337,16 @@ errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, in err = quota_inode_init_new(fs, qf_inum); if (err) { - log_err("init_new_quota_inode failed", ""); + log_err("init_new_quota_inode failed"); 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 +360,7 @@ errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, in h->qh_ops = "afile_ops_2; if (h->qh_ops->new_io && (h->qh_ops->new_io(h) < 0)) { - log_err("qh_ops->new_io failed", ""); + log_err("qh_ops->new_io failed"); goto out_err1; } @@ -364,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) @@ -375,12 +390,18 @@ errcode_t quota_file_close(struct quota_handle *h) if (h->qh_ops->end_io && h->qh_ops->end_io(h) < 0) return -1; if (h->qh_qf.e2_file) { + __u64 new_size, size; + + new_size = compute_inode_size(h->qh_qf.fs, h->qh_qf.ino); ext2fs_file_flush(h->qh_qf.e2_file); - ext2fs_file_set_size2(h->qh_qf.e2_file, - compute_inode_size(h->qh_qf.fs, h->qh_qf.ino)); + if (ext2fs_file_get_lsize(h->qh_qf.e2_file, &size)) + new_size = 0; + if (size != new_size) + 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; } @@ -392,7 +413,7 @@ struct dquot *get_empty_dquot(void) struct dquot *dquot; if (ext2fs_get_memzero(sizeof(struct dquot), &dquot)) { - log_err("Failed to allocate dquot", ""); + log_err("Failed to allocate dquot"); return NULL; } |