[Ocfs2-tools-devel] [PATCH 1/1] Ocfs2-tools: Add quota corruption codes to fswreck.
Tristan
tristan.ye at oracle.com
Thu Oct 8 20:15:32 PDT 2009
Jan Kara wrote:
> Hi Tristan,
>
> On Wed 30-09-09 10:25:58, Tristan wrote:
>
>> Patch below sent days ago may need your review:-)
>>
> Thanks for a reminder.
>
>
>> 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();
>>>
> I suppose you want to use some random UID here. Maybe using 0xffffffff
> might be better because it's most probably invalid.
> Also it might be useful to have another test which would corrupt a header
> of data block (qt_disk_dqdbheader).
>
Good point!
I'll use -10 for a invalid UID as joel suggested.
>
>>> +
>>> + 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;
>>>
> DQBLK_INVALID error of fsck happens when there is a duplicate dquot in an
> invalid block - i.e. you have to also corrupt header of the block or so.
>
>
Thank you for pointing this out:-)
>>> +
>>> + 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);
>>> +}
>>>
>>>
> Honza
>
More information about the Ocfs2-tools-devel
mailing list