[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Cluster-devel] [gfs2-utils PATCH] fsck.gfs2: Check and repair per_node contents such as quota_changeX



Hi,


Sounds good, but I wonder do we really need to continue doing anything
with the inum range files, now that nothing uses them. Maybe worth
looking to see how we can drop those eventually,

Steve.

On Thu, 2013-09-05 at 11:25 -0400, Bob Peterson wrote:
> Hi,
> 
> This patch gives fsck.gfs2 the ability to check the system files that
> are in the per_node directory: All the inum_rangeX, statfs_changeX
> and quota_changeX files. If they're found to be corrupt, they are
> deleted and rebuilt.
> 
> Regards,
> 
> Bob Peterson
> Red Hat File Systems
> 
> Signed-off-by: Bob Peterson <rpeterso redhat com> 
> ---
> diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
> index 727cc18..26f7d48 100644
> --- a/gfs2/fsck/pass2.c
> +++ b/gfs2/fsck/pass2.c
> @@ -1595,6 +1595,116 @@ struct metawalk_fxns pass2_fxns = {
>  	.repair_leaf = pass2_repair_leaf,
>  };
>  
> +static int check_metalist_qc(struct gfs2_inode *ip, uint64_t block,
> +			     struct gfs2_buffer_head **bh, int h,
> +			     int *is_valid, int *was_duplicate, void *private)
> +{
> +	*was_duplicate = 0;
> +	*is_valid = 1;
> +	*bh = bread(ip->i_sbd, block);
> +	return meta_is_good;
> +}
> +
> +static int check_data_qc(struct gfs2_inode *ip, uint64_t metablock,
> +			 uint64_t block, void *private)
> +{
> +	struct gfs2_buffer_head *bh;
> +
> +	/* At this point, basic data block checks have already been done,
> +	   so we only need to make sure they're QC blocks. */
> +	if (!valid_block(ip->i_sbd, block))
> +		return -1;
> +
> +	bh = bread(ip->i_sbd, block);
> +	if (gfs2_check_meta(bh, GFS2_METATYPE_QC) != 0) {
> +		log_crit(_("Error: quota_change block at %lld (0x%llx) is "
> +			   "the wrong metadata type.\n"),
> +			 (unsigned long long)block, (unsigned long long)block);
> +		brelse(bh);
> +		return -1;
> +	}
> +	brelse(bh);
> +	return 0;
> +}
> +
> +struct metawalk_fxns quota_change_fxns = {
> +	.check_metalist = check_metalist_qc,
> +	.check_data = check_data_qc,
> +};
> +
> +/* check_pernode_for - verify a file within the system per_node directory
> + * @x - index number X
> + * @per_node - pointer to the per_node inode
> + * @fn - system file name
> + * @filelen - the file length the system file needs to be
> + * @multiple - the file length must be a multiple (versus the exact value)
> + * @pass - a metawalk function for checking the data blocks (if any)
> + * @builder - a rebuild function for the file
> + *
> + * Returns: 0 if all went well, else error. */
> +static int check_pernode_for(int x, struct gfs2_inode *pernode, const char *fn,
> +			     unsigned long long filelen, int multiple,
> +			     struct metawalk_fxns *pass,
> +			     int builder(struct gfs2_inode *per_node,
> +					 unsigned int j))
> +{
> +	struct gfs2_inode *ip;
> +	int error, valid_size = 1;
> +
> +	log_debug(_("Checking system file %s\n"), fn);
> +	error = gfs2_lookupi(pernode, fn, strlen(fn), &ip);
> +	if (error) {
> +		log_err(_("System file %s is missing.\n"), fn);
> +		if (!query( _("Rebuild the system file? (y/n) ")))
> +			return 0;
> +		goto build_it;
> +	}
> +	if (!ip->i_di.di_size)
> +		valid_size = 0;
> +	else if (!multiple && ip->i_di.di_size != filelen)
> +		valid_size = 0;
> +	else if (multiple && (ip->i_di.di_size % filelen))
> +		valid_size = 0;
> +	if (!valid_size) {
> +		log_err(_("System file %s has an invalid size. Is %llu, "
> +			  "should be %llu.\n"), fn, ip->i_di.di_size, filelen);
> +		if (!query( _("Rebuild the system file? (y/n) ")))
> +			goto out_good;
> +		fsck_inode_put(&ip);
> +		goto build_it;
> +	}
> +	if (pass) {
> +		error = check_metatree(ip, pass);
> +		if (!error)
> +			goto out_good;
> +		log_err(_("System file %s has bad contents.\n"), fn);
> +		if (!query( _("Delete and rebuild the system file? (y/n) ")))
> +			goto out_good;
> +		check_metatree(ip, &pass2_fxns_delete);
> +		fsck_inode_put(&ip);
> +		gfs2_dirent_del(pernode, fn, strlen(fn));
> +		goto build_it;
> +	}
> +out_good:
> +	fsck_inode_put(&ip);
> +	return 0;
> +
> +build_it:
> +	if (builder(pernode, x)) {
> +		log_err(_("Error building %s\n"), fn);
> +		return -1;
> +	}
> +	error = gfs2_lookupi(pernode, fn, strlen(fn), &ip);
> +	if (error) {
> +		log_err(_("Error rebuilding %s.\n"), fn);
> +		return -1;
> +	}
> +	fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, fn, gfs2_inode_file);
> +	reprocess_inode(ip, fn);
> +	log_err(_("System file %s rebuilt.\n"), fn);
> +	goto out_good;
> +}
> +
>  /* Check system directory inode                                           */
>  /* Should work for all system directories: root, master, jindex, per_node */
>  static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
> @@ -1707,7 +1817,26 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
>  				sysinode->i_di.di_num.no_addr);
>  		}
>  	}
> -	return 0;
> +	error = 0;
> +	if (sysinode == sysinode->i_sbd->md.pinode) {
> +		int j;
> +		char fn[64];
> +
> +		/* Make sure all the per_node files are there, and valid */
> +		for (j = 0; j < sysinode->i_sbd->md.journals; j++) {
> +			sprintf(fn, "inum_range%d", j);
> +			error += check_pernode_for(j, sysinode, fn, 16, 0,
> +						   NULL, build_inum_range);
> +			sprintf(fn, "statfs_change%d", j);
> +			error += check_pernode_for(j, sysinode, fn, 24, 0,
> +						   NULL, build_statfs_change);
> +			sprintf(fn, "quota_change%d", j);
> +			error += check_pernode_for(j, sysinode, fn, 1048576, 1,
> +						   &quota_change_fxns,
> +						   build_quota_change);
> +		}
> +	}
> +	return error;
>  }
>  
>  /**
> diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
> index 1548cf3..f864a08 100644
> --- a/gfs2/libgfs2/libgfs2.h
> +++ b/gfs2/libgfs2/libgfs2.h
> @@ -770,6 +770,10 @@ extern int do_init_statfs(struct gfs2_sbd *sdp);
>  extern int gfs2_check_meta(struct gfs2_buffer_head *bh, int type);
>  extern unsigned lgfs2_bm_scan(struct rgrp_tree *rgd, unsigned idx,
>  			      uint64_t *buf, uint8_t state);
> +extern int build_inum_range(struct gfs2_inode *per_node, unsigned int j);
> +extern int build_statfs_change(struct gfs2_inode *per_node, unsigned int j);
> +extern int build_quota_change(struct gfs2_inode *per_node, unsigned int j);
> +
>  /* super.c */
>  extern int check_sb(struct gfs2_sb *sb);
>  extern int read_sb(struct gfs2_sbd *sdp);
> diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
> index 2a8c6f7..e888f1e 100644
> --- a/gfs2/libgfs2/structures.c
> +++ b/gfs2/libgfs2/structures.c
> @@ -180,7 +180,7 @@ int build_jindex(struct gfs2_sbd *sdp)
>  	return 0;
>  }
>  
> -static int build_inum_range(struct gfs2_inode *per_node, unsigned int j)
> +int build_inum_range(struct gfs2_inode *per_node, unsigned int j)
>  {
>  	struct gfs2_sbd *sdp = per_node->i_sbd;
>  	char name[256];
> @@ -204,7 +204,7 @@ static int build_inum_range(struct gfs2_inode *per_node, unsigned int j)
>  	return 0;
>  }
>  
> -static int build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
> +int build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
>  {
>  	struct gfs2_sbd *sdp = per_node->i_sbd;
>  	char name[256];
> @@ -228,7 +228,7 @@ static int build_statfs_change(struct gfs2_inode *per_node, unsigned int j)
>  	return 0;
>  }
>  
> -static int build_quota_change(struct gfs2_inode *per_node, unsigned int j)
> +int build_quota_change(struct gfs2_inode *per_node, unsigned int j)
>  {
>  	struct gfs2_sbd *sdp = per_node->i_sbd;
>  	struct gfs2_meta_header mh;
> diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
> index eb97c40..f87734a 100644
> --- a/gfs2/libgfs2/super.c
> +++ b/gfs2/libgfs2/super.c
> @@ -119,6 +119,7 @@ int read_sb(struct gfs2_sbd *sdp)
>  	sdp->sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->bsize;
>  	sdp->sd_blocks_per_bitmap = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header))
>  	                             * GFS2_NBBY;
> +	sdp->qcsize = GFS2_DEFAULT_QCSIZE;
>  
>  	return 0;
>  }
> 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]