[Ocfs2-tools-devel] [PATCH 1/1] Ocfs2-tools: Add quota corruption codes to fswreck.
Tristan
tristan.ye at oracle.com
Tue Sep 29 19:25:58 PDT 2009
Jan, Joel
Patch below sent days ago may need your review:-)
Thanks,
Tristan
Tristan Ye wrote:
> As the quota supports on ocfs2-tools got finished, we therefore
> have to support such quota corruptions in fswreck to make it compatible
> with corresponding codes in fsck.ocfs2. Following five fsck codes will be
> added in fswreck to support new quota corruptions.
>
> QMAGIC_INVALID,
> QTREE_BLK_INVALID,
> DQBLK_INVALID,
> DUP_DQBLK_INVALID,
> DUP_DQBLK_VALID
>
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
> fswreck/Makefile | 5 +-
> fswreck/corrupt.c | 7 +
> fswreck/include/fsck_type.h | 13 ++-
> fswreck/include/main.h | 1 +
> fswreck/include/quota.h | 23 ++++
> fswreck/main.c | 16 ++-
> fswreck/quota.c | 278 +++++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 336 insertions(+), 7 deletions(-)
> create mode 100644 fswreck/include/quota.h
> create mode 100644 fswreck/quota.c
>
> diff --git a/fswreck/Makefile b/fswreck/Makefile
> index d5b4e6c..7e688f9 100644
> --- a/fswreck/Makefile
> +++ b/fswreck/Makefile
> @@ -10,7 +10,7 @@ INCLUDES += $(GLIB_CFLAGS)
>
> UNINST_PROGRAMS = fswreck
>
> -CFILES = main.c corrupt.c chain.c extent.c group.c inode.c local_alloc.c truncate_log.c special.c symlink.c dir.c journal.c
> +CFILES = main.c corrupt.c chain.c extent.c group.c inode.c local_alloc.c truncate_log.c special.c symlink.c dir.c journal.c quota.c
>
> HFILES = \
> include/chain.h \
> @@ -25,7 +25,8 @@ HFILES = \
> include/group.h \
> include/journal.h \
> include/main.h \
> - include/symlink.h
> + include/symlink.h \
> + include/quota.h
>
> DIST_FILES = $(CFILES) $(HFILES)
> DIST_RULES = dist-subdircreate
> diff --git a/fswreck/corrupt.c b/fswreck/corrupt.c
> index e6f2bf3..f0c89cf 100644
> --- a/fswreck/corrupt.c
> +++ b/fswreck/corrupt.c
> @@ -332,6 +332,13 @@ void corrupt_sys_file(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum)
> case JOURNAL_TOO_SMALL:
> func = mess_up_journal;
> break;
> + case QMAGIC_INVALID:
> + case QTREE_BLK_INVALID:
> + case DQBLK_INVALID:
> + case DUP_DQBLK_INVALID:
> + case DUP_DQBLK_VALID:
> + func = mess_up_quota;
> + break;
> default:
> FSWRK_FATAL("Invalid code=%d", type);
> }
> diff --git a/fswreck/include/fsck_type.h b/fswreck/include/fsck_type.h
> index c385383..7f3430f 100644
> --- a/fswreck/include/fsck_type.h
> +++ b/fswreck/include/fsck_type.h
> @@ -129,6 +129,11 @@ enum fsck_type
> JOURNAL_UNKNOWN_FEATURE,
> JOURNAL_MISSING_FEATURE,
> JOURNAL_TOO_SMALL,
> + QMAGIC_INVALID,
> + QTREE_BLK_INVALID,
> + DQBLK_INVALID,
> + DUP_DQBLK_INVALID,
> + DUP_DQBLK_VALID,
> NUM_FSCK_TYPE
> };
>
> @@ -186,9 +191,13 @@ enum fsck_type
> *
> * Special files error: ROOT_NOTDIR, ROOT_DIR_MISSING, LOSTFOUND_MISSING,
> * DIR_DOTDOT
> + *
> * Journal file error: JOURNAL_FILE_INVALID, JOURNAL_UNKNOWN_FEATURE,
> - JOURNAL_MISSING_FEATURE, JOURNAL_TOO_SMALL.
> - *
> + * JOURNAL_MISSING_FEATURE, JOURNAL_TOO_SMALL.
> + *
> + * Quota file error: QMAGIC_INVALID, QTREE_BLK_INVALID, DQBLK_INVALID
> + * DUP_DQBLK_INVALID, DUP_DQBLK_VALID
> + *
> * Link file error: LINK_FAST_DATA, LINK_NULLTERM, LINK_SIZE, LINK_BLOCKS
> *
> * Directory inode error: DIR_ZERO
> diff --git a/fswreck/include/main.h b/fswreck/include/main.h
> index daedc0a..a5f69ea 100644
> --- a/fswreck/include/main.h
> +++ b/fswreck/include/main.h
> @@ -89,5 +89,6 @@
> #include "special.h"
> #include "dir.h"
> #include "journal.h"
> +#include "quota.h"
>
> #endif /* __MAIN_H__ */
> diff --git a/fswreck/include/quota.h b/fswreck/include/quota.h
> new file mode 100644
> index 0000000..e50621b
> --- /dev/null
> +++ b/fswreck/include/quota.h
> @@ -0,0 +1,23 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * quota.h
> + *
> + * Copyright (C) 2004, 2008 Oracle. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#ifndef __QUOTA_H
> +#define __QUOTA_H
> +
> +void mess_up_quota(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum);
> +
> +#endif /* __QUOTA_H */
> diff --git a/fswreck/main.c b/fswreck/main.c
> index 85b0472..0910188 100644
> --- a/fswreck/main.c
> +++ b/fswreck/main.c
> @@ -9,12 +9,12 @@
> * modify it under the terms of the GNU General Public
> * License as published by the Free Software Foundation; either
> * version 2 of the License, or (at your option) any later version.
> - *
> + *
> * This program is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> * General Public License for more details.
> - *
> + *
> * You should have received a copy of the GNU General Public
> * License along with this program; if not, write to the
> * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> @@ -249,6 +249,16 @@ static struct prompt_code prompt_codes[NUM_FSCK_TYPE] = {
> "Corrupt journal file by missing features."),
> define_prompt_code(JOURNAL_TOO_SMALL, corrupt_sys_file,
> "Corrupt journal file as a too small one."),
> + define_prompt_code(QMAGIC_INVALID, corrupt_sys_file,
> + "Corrupt quota system file's header."),
> + define_prompt_code(QTREE_BLK_INVALID, corrupt_sys_file,
> + "Corrupt quota tree block."),
> + define_prompt_code(DQBLK_INVALID, corrupt_sys_file,
> + "Corrupt quota data blok."),
> + define_prompt_code(DUP_DQBLK_INVALID, corrupt_sys_file,
> + "Duplicate a invalid quota limits."),
> + define_prompt_code(DUP_DQBLK_VALID, corrupt_sys_file,
> + "Duplicate a valid quota limits."),
> };
>
> #undef define_prompt_code
> @@ -373,7 +383,7 @@ static int read_options(int argc, char **argv)
> return 1;
> }
>
> - while(1) {
> + while (1) {
> c = getopt(argc, argv, "c:n:");
> if (c == -1)
> break;
> diff --git a/fswreck/quota.c b/fswreck/quota.c
> new file mode 100644
> index 0000000..cee1f26
> --- /dev/null
> +++ b/fswreck/quota.c
> @@ -0,0 +1,278 @@
> +/* -*- mode: c; c-basic-offset: 8; -*-
> + * vim: noexpandtab sw=8 ts=8 sts=0:
> + *
> + * quota.c
> + *
> + * Copyright (C) 2004, 2008 Oracle. All rights reserved.
> + *
> + * Corruptions for quota system file.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#include "main.h"
> +
> +extern char *progname;
> +static int g_actref;
> +
> +/* This file will corrupt quota system file.
> + *
> + * Quota Error: QMAGIC_INVALID, QTREE_BLK_INVALID, DQBLK_INVALID
> + * DUP_DQBLK_INVALID, DUP_DQBLK_VALID
> + *
> + */
> +
> +static char *type2name(int type)
> +{
> + if (type == USRQUOTA)
> + return "user";
> +
> + return "group";
> +}
> +
> +static errcode_t o2fswreck_read_blk(ocfs2_filesys *fs, int type, char *buf,
> + uint32_t blk)
> +{
> + uint32_t got;
> + errcode_t ret;
> +
> + ret = ocfs2_file_read(fs->qinfo[type].qi_inode, buf, fs->fs_blocksize,
> + blk * fs->fs_blocksize, &got);
> + if (ret)
> + return ret;
> + if (got != fs->fs_blocksize)
> + return OCFS2_ET_SHORT_READ;
> +
> + return 0;
> +}
> +
> +static errcode_t o2fswreck_write_blk(ocfs2_filesys *fs, int type, char *buf,
> + uint32_t blk)
> +{
> + errcode_t err;
> + uint32_t written;
> +
> + err = ocfs2_file_write(fs->qinfo[type].qi_inode, buf, fs->fs_blocksize,
> + blk * fs->fs_blocksize, &written);
> + if (err)
> + return err;
> + if (written != fs->fs_blocksize)
> + return OCFS2_ET_SHORT_WRITE;
> +
> + return 0;
> +}
> +
> +
> +static errcode_t o2fswreck_get_data_blk(ocfs2_filesys *fs, int type,
> + uint32_t blk, int depth,
> + char *buf)
> +{
> + errcode_t ret;
> + int epb = (fs->fs_blocksize - OCFS2_QBLK_RESERVED_SPACE) >> 2;
> + int tree_depth = ocfs2_qtree_depth(fs->fs_blocksize);
> + uint32_t *refs = (uint32_t *)buf, actref;
> + int i;
> +
> + ret = o2fswreck_read_blk(fs, type, buf, blk);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + for (i = 0; i < epb; i++) {
> +
> + actref = le32_to_cpu(refs[i]);
> + if (!actref)
> + continue;
> +
> + if (depth + 1 < tree_depth) {
> + ret = o2fswreck_get_data_blk(fs, type, actref,
> + depth + 1,
> + buf + fs->fs_blocksize);
> + } else {
> +
> + ret = o2fswreck_read_blk(fs, type,
> + buf + fs->fs_blocksize,
> + actref);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + g_actref = actref;
> +
> + return 0;
> + }
> +
> + if (ret)
> + goto out;
> + }
> +
> +out:
> + return ret;
> +}
> +
> +
> +void mess_up_quota(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum)
> +{
> + errcode_t ret;
> + int qtype;
> + char *buf;
> + int tree_depth = ocfs2_qtree_depth(fs->fs_blocksize);
> +
> + struct ocfs2_disk_dqheader *header;
> + struct ocfs2_global_disk_dqblk *ddquot;
> +
> + ret = ocfs2_init_fs_quota_info(fs, USRQUOTA);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + ret = ocfs2_init_fs_quota_info(fs, GRPQUOTA);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + ret = ocfs2_malloc_blocks(fs->fs_io,
> + tree_depth + 1,
> + &buf);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + switch (type) {
> + case QMAGIC_INVALID:
> + qtype = USRQUOTA;
> +
> + ret = o2fswreck_read_blk(fs, qtype, buf, 0);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + header = (struct ocfs2_disk_dqheader *)buf;
> +
> + ocfs2_swap_quota_header(header);
> +
> + header->dqh_magic = ~header->dqh_magic;
> +
> + ocfs2_swap_quota_header(header);
> +
> + ret = o2fswreck_write_blk(fs, qtype, buf, 0);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + fprintf(stdout, "QMAGIC_INVALID: "
> + "Corrupt global %s quota file's magic number "
> + "in its header.\n", type2name(qtype));
> + break;
> + case QTREE_BLK_INVALID:
> + qtype = GRPQUOTA;
> +
> + ret = o2fswreck_read_blk(fs, qtype, buf, QT_TREEOFF);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + struct ocfs2_disk_dqtrailer *dqt =
> + ocfs2_block_dqtrailer(fs->fs_blocksize, buf);
> +
> + dqt->dq_check.bc_crc32e = ~dqt->dq_check.bc_crc32e;
> + dqt->dq_check.bc_ecc = ~dqt->dq_check.bc_ecc;
> +
> + ret = o2fswreck_write_blk(fs, qtype, buf, QT_TREEOFF);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + fprintf(stdout, "QTREE_BLK_INVALID: "
> + "Corrupt global %s quota tree block.\n",
> + type2name(qtype));
> + break;
> + case DQBLK_INVALID:
> + qtype = USRQUOTA;
> +
> + ret = o2fswreck_get_data_blk(fs, qtype, QT_TREEOFF, 0, buf);
> +
> + ddquot = (struct ocfs2_global_disk_dqblk *)(buf +
> + fs->fs_blocksize * tree_depth +
> + sizeof(struct qt_disk_dqdbheader));
> +
> + ocfs2_swap_quota_global_dqblk(ddquot);
> +
> + ddquot->dqb_id = getuid();
> +
> + ddquot->dqb_isoftlimit += 1;
> + ddquot->dqb_ihardlimit += 2;
> + ddquot->dqb_bsoftlimit += 3;
> + ddquot->dqb_bhardlimit += 4;
> +
> + ocfs2_swap_quota_global_dqblk(ddquot);
> +
> + ret = o2fswreck_write_blk(fs, qtype,
> + buf + fs->fs_blocksize * tree_depth,
> + g_actref);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + fprintf(stdout, "DQBLK_INVALID: "
> + "Corrupt global %s quota data block.\n",
> + type2name(qtype));
> +
> + break;
> + case DUP_DQBLK_INVALID:
> + qtype = GRPQUOTA;
> +
> + ret = o2fswreck_get_data_blk(fs, qtype, QT_TREEOFF, 0, buf);
> +
> + ddquot = (struct ocfs2_global_disk_dqblk *)(buf +
> + fs->fs_blocksize * tree_depth +
> + sizeof(struct qt_disk_dqdbheader));
> +
> + ddquot[1].dqb_id = ddquot[0].dqb_id;
> +
> + ddquot[1].dqb_isoftlimit += 1;
> + ddquot[1].dqb_ihardlimit += 2;
> + ddquot[1].dqb_bsoftlimit += 3;
> + ddquot[1].dqb_bhardlimit += 4;
> +
> + ret = o2fswreck_write_blk(fs, qtype,
> + buf + fs->fs_blocksize * tree_depth,
> + g_actref);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + fprintf(stdout, "DUP_DQBLK_INVALID: "
> + "Duplicate %s quota data block with a invalid entry.\n",
> + type2name(qtype));
> +
> + break;
> + case DUP_DQBLK_VALID:
> + qtype = GRPQUOTA;
> +
> + ret = o2fswreck_get_data_blk(fs, qtype, QT_TREEOFF, 0, buf);
> +
> + ddquot = (struct ocfs2_global_disk_dqblk *)(buf +
> + fs->fs_blocksize * tree_depth +
> + sizeof(struct qt_disk_dqdbheader));
> +
> + ddquot[1].dqb_id = ddquot[0].dqb_id;
> + ddquot[1].dqb_isoftlimit = ddquot[0].dqb_isoftlimit;
> + ddquot[1].dqb_ihardlimit = ddquot[0].dqb_isoftlimit;
> + ddquot[1].dqb_bsoftlimit = ddquot[0].dqb_isoftlimit;
> + ddquot[1].dqb_bhardlimit = ddquot[0].dqb_isoftlimit;
> +
> + ret = o2fswreck_write_blk(fs, qtype,
> + buf + fs->fs_blocksize * tree_depth,
> + g_actref);
> + if (ret)
> + FSWRK_COM_FATAL(progname, ret);
> +
> + fprintf(stdout, "DUP_DQBLK_INVALID: "
> + "Duplicate %s quota data block with a valid entry.\n",
> + type2name(qtype));
> +
> + break;
> + default:
> + FSWRK_FATAL("Invalid type[%d]\n", type);
> + }
> +
> + if (buf)
> + ocfs2_free(&buf);
> +}
>
More information about the Ocfs2-tools-devel
mailing list