commit 7c8cb8d5d6d1e08c5f83eef844ceff89a6567d64 Author: Bob Peterson <bob@ganesha.peterson> Date: Fri Jan 22 09:01:15 2010 -0600 fsck.gfs2: link.c should log why it's making a change for debugging This patch helps in debugging directory link problems by logging the dinode and the reason why the directory link count is being incremented or decremented. rhbz#455300 diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c index b6870c8..a39db33 100644 --- a/gfs2/fsck/link.c +++ b/gfs2/fsck/link.c @@ -40,21 +40,28 @@ int set_link_count(uint64_t inode_no, uint32_t count) return 0; } -int increment_link(struct gfs2_sbd *sbp, uint64_t inode_no) +int increment_link(uint64_t inode_no, uint64_t referenced_from, + const char *why) { struct inode_info *ii = NULL; ii = inodetree_find(inode_no); /* If the list has entries, look for one that matches * inode_no */ - if(ii) { + if (ii) { ii->counted_links++; - log_debug( _("Incremented counted links to %u for %"PRIu64" (0x%" - PRIx64 ")\n"), ii->counted_links, inode_no, inode_no); + log_debug( _("Directory %lld (0x%llx) incremented counted " + "links to %u for %"PRIu64" (0x%" PRIx64 ") " + "via %s\n"), + (unsigned long long)referenced_from, + (unsigned long long)referenced_from, + ii->counted_links, inode_no, inode_no, why); return 0; } - log_debug( _("No match found when incrementing link for %" PRIu64 - " (0x%" PRIx64 ")!\n"), inode_no, inode_no); + log_debug( _("Ref: %lld (0x%llx) No match found when incrementing " + "link for %" PRIu64 " (0x%" PRIx64 ")!\n"), + (unsigned long long)referenced_from, + (unsigned long long)referenced_from, inode_no, inode_no); /* If no match was found, add a new entry and set its * counted links to 1 */ ii = inodetree_insert(inode_no); @@ -65,16 +72,24 @@ int increment_link(struct gfs2_sbd *sbp, uint64_t inode_no) return 0; } -int decrement_link(struct gfs2_sbd *sbp, uint64_t inode_no) +int decrement_link(uint64_t inode_no, uint64_t referenced_from, + const char *why) { struct inode_info *ii = NULL; ii = inodetree_find(inode_no); /* If the list has entries, look for one that matches * inode_no */ - log_err( _("Decrementing %"PRIu64" (0x%" PRIx64 ")\n"), inode_no, inode_no); + log_err( _("Decrementing %"PRIu64" (0x%" PRIx64 ") to %d\n"), + inode_no, inode_no, ii->counted_links); if(ii) { ii->counted_links--; + log_debug( _("Directory %lld (0x%llx) decremented counted " + "links to %u for %"PRIu64" (0x%" PRIx64 ") " + "via %s\n"), + (unsigned long long)referenced_from, + (unsigned long long)referenced_from, + ii->counted_links, inode_no, inode_no, why); return 0; } log_debug( _("No match found when decrementing link for %" PRIu64 diff --git a/gfs2/fsck/link.h b/gfs2/fsck/link.h index 0509255..c43cda3 100644 --- a/gfs2/fsck/link.h +++ b/gfs2/fsck/link.h @@ -16,7 +16,9 @@ #define _LINK_H int set_link_count(uint64_t inode_no, uint32_t count); -int increment_link(struct gfs2_sbd *sbp, uint64_t inode_no); -int decrement_link(struct gfs2_sbd *sbp, uint64_t inode_no); +int increment_link(uint64_t inode_no, uint64_t referenced_from, + const char *why); +int decrement_link(uint64_t inode_no, uint64_t referenced_from, + const char *why); #endif /* _LINK_H */ diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c index 05318f0..90354d9 100644 --- a/gfs2/fsck/lost_n_found.c +++ b/gfs2/fsck/lost_n_found.c @@ -59,10 +59,16 @@ int add_inode_to_lf(struct gfs2_inode *ip){ * this */ gfs2_blockmap_set(bl, lf_dip->i_di.di_num.no_addr, gfs2_inode_dir); - increment_link(ip->i_sbd, - ip->i_sbd->md.rooti->i_di.di_num.no_addr); - increment_link(ip->i_sbd, lf_dip->i_di.di_num.no_addr); - increment_link(ip->i_sbd, lf_dip->i_di.di_num.no_addr); + /* root inode links to lost+found */ + increment_link(ip->i_sbd->md.rooti->i_di.di_num.no_addr, + lf_dip->i_di.di_num.no_addr, _("root")); + /* lost+found link for '.' from itself */ + increment_link(lf_dip->i_di.di_num.no_addr, + lf_dip->i_di.di_num.no_addr, "\".\""); + /* lost+found link for '..' back to root */ + increment_link(lf_dip->i_di.di_num.no_addr, + ip->i_sbd->md.rooti->i_di.di_num.no_addr, + "\"..\""); } } if(ip->i_di.di_num.no_addr == lf_dip->i_di.di_num.no_addr) { @@ -117,9 +123,13 @@ int add_inode_to_lf(struct gfs2_inode *ip){ dir_add(lf_dip, tmp_name, strlen(tmp_name), &(ip->i_di.di_num), inode_type); - increment_link(ip->i_sbd, ip->i_di.di_num.no_addr); + /* This inode is linked from lost+found */ + increment_link(ip->i_di.di_num.no_addr, lf_dip->i_di.di_num.no_addr, + _("from lost+found")); + /* If it's a directory, lost+found is back-linked to it via .. */ if(S_ISDIR(ip->i_di.di_mode)) - increment_link(ip->i_sbd, lf_dip->i_di.di_num.no_addr); + increment_link(lf_dip->i_di.di_num.no_addr, + ip->i_di.di_mode, _("to lost+found")); log_notice( _("Added inode #%llu to lost+found dir\n"), (unsigned long long)ip->i_di.di_num.no_addr); diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 7c8a71c..36f2f6b 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -390,7 +390,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* FIXME: Should we continue on here * and check the rest of the '.' * entry? */ - increment_link(sbp, entryblock); + increment_link(entryblock, + ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; return 0; @@ -425,7 +427,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, log_err( _("Invalid '.' reference remains\n")); /* Not setting ds->dotdir here since * this '.' entry is invalid */ - increment_link(sbp, entryblock); + increment_link(entryblock, + ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; return 0; @@ -433,7 +437,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } ds->dotdir = 1; - increment_link(sbp, entryblock); + increment_link(entryblock, ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; @@ -460,7 +465,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* FIXME: Should we continue on here * and check the rest of the '..' * entry? */ - increment_link(sbp, entryblock); + increment_link(entryblock, + ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; return 0; @@ -483,7 +490,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, return 1; } else { log_err( _("Bad '..' directory entry remains\n")); - increment_link(sbp, entryblock); + increment_link(entryblock, + ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; return 0; @@ -500,7 +509,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } ds->dotdotdir = 1; - increment_link(sbp, entryblock); + increment_link(entryblock, ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; return 0; @@ -509,7 +519,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* After this point we're only concerned with directories */ if(q != gfs2_inode_dir) { log_debug( _("Found non-dir inode dentry\n")); - increment_link(sbp, entryblock); + increment_link(entryblock, ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; return 0; @@ -537,7 +548,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, stack; return -1; } - increment_link(sbp, entryblock); + increment_link(entryblock, ip->i_di.di_num.no_addr, + _("valid reference")); (*count)++; ds->entry_count++; /* End of checks */ @@ -614,8 +626,10 @@ int check_system_dir(struct gfs2_inode *sysinode, const char *dirname, log_warn( _("Adding '.' entry\n")); dir_add(sysinode, filename, filename_len, &(sysinode->i_di.di_num), DT_DIR); - increment_link(sysinode->i_sbd, - sysinode->i_di.di_num.no_addr); + /* This system inode is linked to itself via '.' */ + increment_link(sysinode->i_di.di_num.no_addr, + sysinode->i_di.di_num.no_addr, + "sysinode \".\""); ds.entry_count++; free(filename); } else @@ -794,8 +808,10 @@ int pass2(struct gfs2_sbd *sbp) dir_add(ip, filename, filename_len, &(ip->i_di.di_num), DT_DIR); - increment_link(ip->i_sbd, - ip->i_di.di_num.no_addr); + /* directory links to itself via '.' */ + increment_link(ip->i_di.di_num.no_addr, + ip->i_di.di_num.no_addr, + _("\". (itself)\"")); ds.entry_count++; free(filename); log_err( _("The directory was fixed.\n")); diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c index fa66f29..719a665 100644 --- a/gfs2/fsck/pass3.c +++ b/gfs2/fsck/pass3.c @@ -62,9 +62,9 @@ static int attach_dotdot_to(struct gfs2_sbd *sbp, uint64_t newdotdot, if(gfs2_dirent_del(ip, filename, filename_len)) log_warn( _("Unable to remove \"..\" directory entry.\n")); else - decrement_link(sbp, olddotdot); + decrement_link(olddotdot, block, _("old \"..\"")); dir_add(ip, filename, filename_len, &pip->i_di.di_num, DT_DIR); - increment_link(sbp, newdotdot); + increment_link(newdotdot, block, _("new \"..\"")); bmodified(ip->i_bh); fsck_inode_put(&ip); fsck_inode_put(&pip);