From: Andrew Price <anprice@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [gfs2-utils PATCH 7/7] fsck.gfs2: Detect and fix duplicate references in hash tables
Date: Tue, 16 Jul 2013 17:52:34 +0100 [thread overview]
Message-ID: <51E57A52.8030103@redhat.com> (raw)
In-Reply-To: <67014263a531655f54e1b40b0058a93c42790e01.1373979296.git.rpeterso@redhat.com>
Hi Bob,
A couple of comments below...
On 16/07/13 13:56, Bob Peterson wrote:
> This patch checks directory hash tables for multiple occurrences
> of the same leaf block. When duplicates are encountered, it checks
> to see which reference is appropriate for the hash table location
> based on the leaf block's hash value. The appropriate reference is
> kept and all duplicates are replaced by newly created leaf blocks.
>
> rhbz#984085
> ---
> gfs2/fsck/pass2.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 108 insertions(+)
>
> diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
> index a40a4a7..9f3e5c1 100644
> --- a/gfs2/fsck/pass2.c
> +++ b/gfs2/fsck/pass2.c
> @@ -1278,6 +1278,110 @@ static int fix_hashtable(struct gfs2_inode *ip, uint64_t *tbl, unsigned hsize,
> return changes;
> }
>
> +/* check_hash_tbl_dups - check for the same leaf in multiple places */
> +static int check_hash_tbl_dups(struct gfs2_inode *ip, uint64_t *tbl,
> + unsigned hsize, int lindex, int len)
> +{
> + int l, len2;
> + uint64_t leafblk, leaf_no;
> + struct gfs2_buffer_head *lbh;
> + struct gfs2_leaf leaf;
> + struct gfs2_dirent dentry, *de;
> + int hash_index; /* index into the hash table based on the hash */
> +
> + leafblk = be64_to_cpu(tbl[lindex]);
> + for (l = 0; l < hsize; l++) {
> + if (l == lindex) { /* skip the valid reference */
> + l += len - 1;
> + continue;
> + }
> + if (be64_to_cpu(tbl[l]) != leafblk)
> + continue;
> +
> + for (len2 = 0; l + len2 < hsize; len2++) {
> + if (l + len2 == lindex)
> + break;
> + if (be64_to_cpu(tbl[l + len2]) != leafblk)
> + break;
> + }
> + log_err(_("Dinode %llu (0x%llx) has duplicate leaf pointers "
> + "to block %llu (0x%llx) at offsets %u (0x%x) "
> + "(for 0x%x) and %u (0x%x) (for 0x%x)\n"),
> + (unsigned long long)ip->i_di.di_num.no_addr,
> + (unsigned long long)ip->i_di.di_num.no_addr,
> + (unsigned long long)leafblk,
> + (unsigned long long)leafblk, lindex, lindex, len,
> + l, l, len2);
> +
> + /* See which set of references is valid: the one passed in
> + or the duplicate we found. */
> + memset(&leaf, 0, sizeof(leaf));
> + leaf_no = leafblk;
> + if (!valid_block(ip->i_sbd, leaf_no)) /* Checked later */
> + continue;
> +
> + lbh = bread(ip->i_sbd, leafblk);
> + if (gfs2_check_meta(lbh, GFS2_METATYPE_LF)) { /* Chked later */
> + brelse(lbh);
> + continue;
> + }
> +
> + memset(&dentry, 0, sizeof(struct gfs2_dirent));
> + de = (struct gfs2_dirent *)(lbh->b_data +
> + sizeof(struct gfs2_leaf));
> + gfs2_dirent_in(&dentry, (char *)de);
> + hash_index = hash_table_index(dentry.de_hash, ip);
> + brelse(lbh);
Unconditionally releasing lbh here ...
> + /* check the duplicate ref first */
> + if (hash_index < l || hash_index > l + len2) {
> + log_err(_("This leaf block has hash index %d, which "
> + "is out of bounds for lindex (%d - %d)\n"),
> + hash_index, l, l + len2);
> + if (!query( _("Fix the hash table? (y/n) "))) {
> + log_err(_("Hash table not fixed.\n"));
> + brelse(lbh);
so shouldn't need to here...
> + return 0;
> + }
> + /* Adjust the ondisk block count. The original value
> + may have been correct without the duplicates but
> + pass1 would have counted them and adjusted the
> + count to include them. So we must subtract them. */
> + ip->i_di.di_blocks--;
> + bmodified(ip->i_bh);
> + pad_with_leafblks(ip, tbl, l, len2);
> + } else {
> + log_debug(_("Hash index 0x%x is the proper "
> + "reference to leaf 0x%llx.\n"),
> + l, (unsigned long long)leafblk);
> + }
> + /* Check the original ref: both references might be bad.
> + If both were bad, just return and if we encounter it
> + again, we'll treat it as new. If the original ref is not
> + bad, keep looking for (and fixing) other instances. */
> + if (hash_index < lindex || hash_index > lindex + len) {
> + log_err(_("This leaf block has hash index %d, which "
> + "is out of bounds for lindex (%d - %d).\n"),
> + hash_index, lindex, lindex + len);
> + if (!query( _("Fix the hash table? (y/n) "))) {
> + log_err(_("Hash table not fixed.\n"));
> + brelse(lbh);
and here.
The rest looks good to me.
Cheers,
Andy
> + return 0;
> + }
> + ip->i_di.di_blocks--;
> + bmodified(ip->i_bh);
> + pad_with_leafblks(ip, tbl, lindex, len);
> + /* At this point we know both copies are bad, so we
> + return to start fresh */
> + return -EFAULT;
> + } else {
> + log_debug(_("Hash index 0x%x is the proper "
> + "reference to leaf 0x%llx.\n"),
> + lindex, (unsigned long long)leafblk);
> + }
> + }
> + return 0;
> +}
> +
> /* check_hash_tbl - check that the hash table is sane
> *
> * We've got to make sure the hash table is sane. Each leaf needs to
> @@ -1372,6 +1476,10 @@ static int check_hash_tbl(struct gfs2_inode *ip, uint64_t *tbl,
> lindex += proper_len;
> continue;
> }
> +
> + if (check_hash_tbl_dups(ip, tbl, hsize, lindex, len))
> + continue;
> +
> /* Make sure they call on proper leaf-split boundaries. This
> is the calculation used by the kernel, and dir_split_leaf */
> proper_start = (lindex & ~(proper_len - 1));
>
next prev parent reply other threads:[~2013-07-16 16:52 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-16 12:56 [Cluster-devel] [gfs2-utils PATCH 1/7] fsck.gfs2: Fix reference to uninitialized variable Bob Peterson
2013-07-16 12:56 ` [Cluster-devel] [gfs2-utils PATCH 2/7] fsck.gfs2: fix some log messages Bob Peterson
2013-07-16 12:56 ` [Cluster-devel] [gfs2-utils PATCH 3/7] fsck.gfs2: Fix directory link on relocated directory dirents Bob Peterson
2013-07-16 12:56 ` [Cluster-devel] [gfs2-utils PATCH 4/7] fsck.gfs2: Fix infinite loop in pass1b caused by duplicates in hash table Bob Peterson
2013-07-16 12:56 ` [Cluster-devel] [gfs2-utils PATCH 5/7] fsck.gfs2: don't check newly created lost+found in pass2 Bob Peterson
2013-07-16 16:52 ` Andrew Price
2013-07-16 17:14 ` Bob Peterson
2013-07-16 12:56 ` [Cluster-devel] [gfs2-utils PATCH 6/7] fsck.gfs2: avoid negative number in leaf depth Bob Peterson
2013-07-16 12:56 ` [Cluster-devel] [gfs2-utils PATCH 7/7] fsck.gfs2: Detect and fix duplicate references in hash tables Bob Peterson
2013-07-16 16:52 ` Andrew Price [this message]
2013-07-16 17:16 ` Bob Peterson
2013-07-17 5:30 ` [Cluster-devel] [gfs2-utils PATCH 1/7] fsck.gfs2: Fix reference to uninitialized variable Fabio M. Di Nitto
2013-07-17 7:53 ` Steven Whitehouse
2013-07-17 11:51 ` [Cluster-devel] [PATCH] fsck.gfs2: Don't rely on cluster.conf when rebuilding sb Andrew Price
2013-07-17 11:52 ` Steven Whitehouse
2013-07-17 12:27 ` Bob Peterson
2013-07-17 18:13 ` Fabio M. Di Nitto
2013-07-17 18:26 ` Bob Peterson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51E57A52.8030103@redhat.com \
--to=anprice@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.