[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