Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=b46... Commit: b46c19c385f182f950c6df56bafd3db15459c48e Parent: 5df69b1d9f020df9e97629240196596c330567fa Author: Bob Peterson bob@ganesha.peterson AuthorDate: Fri Jan 22 15:07:19 2010 -0600 Committer: Bob Peterson rpeterso@redhat.com CommitterDate: Tue Jan 26 14:39:31 2010 -0600
lost+found link count and connections were not properly managed
When the lost+found directory was created, function createi in libgfs2 incremented the di_nlink link count for the root directory, but fsck.gfs2 did not increment the nlink value in the hash table. As a result, pass4 doesn't find and fix the discrepancy. Subsequent runs of fsck.gfs2 detect the problem, though. This patch adjusts for the new link and keeps everything sane.
In a similar fashion, if the dinode being moved to lost+found happens to be a directory, the links were not properly adjusted for that directory's ".." dentry. This patch also takes care of that so the links don't get off.
rhbz#455300 --- gfs2/fsck/lost_n_found.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c index ea7b370..6d26096 100644 --- a/gfs2/fsck/lost_n_found.c +++ b/gfs2/fsck/lost_n_found.c @@ -27,6 +27,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){ char tmp_name[256]; __be32 inode_type; + struct dir_info *di;
if(!lf_dip) { uint8_t q; @@ -35,6 +36,13 @@ int add_inode_to_lf(struct gfs2_inode *ip){
lf_dip = createi(ip->i_sbd->md.rooti, "lost+found", S_IFDIR | 0700, 0); + /* createi will have incremented the di_nlink link count for + the root directory. We must increment the nlink value + in the hash table to keep them in sync so that pass4 can + detect and fix any discrepancies. */ + set_link_count(ip->i_sbd->sd_sb.sb_root_dir.no_addr, + ip->i_sbd->md.rooti->i_di.di_nlink); + q = block_type(lf_dip->i_di.di_num.no_addr); if(q != gfs2_inode_dir) { /* This is a new lost+found directory, so set its @@ -59,6 +67,15 @@ int add_inode_to_lf(struct gfs2_inode *ip){ ip->i_sbd->md.rooti->i_di.di_num.no_addr, ""..""); } + log_info( _("lost+found directory is dinode %lld (0x%llx)\n"), + (unsigned long long)lf_dip->i_di.di_num.no_addr, + (unsigned long long)lf_dip->i_di.di_num.no_addr); + di = dirtree_find(lf_dip->i_di.di_num.no_addr); + if (di) { + log_info( _("Marking lost+found inode connected\n")); + di->checked = 1; + di = NULL; + } } if(ip->i_di.di_num.no_addr == lf_dip->i_di.di_num.no_addr) { log_err( _("Trying to add lost+found to itself...skipping")); @@ -71,6 +88,33 @@ int add_inode_to_lf(struct gfs2_inode *ip){ (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr);
+ /* If there's a pre-existing .. directory entry, we have to + back out the links. */ + di = dirtree_find(ip->i_di.di_num.no_addr); + if (di && gfs2_check_range(ip->i_sbd, di->dotdot_parent) == 0){ + struct gfs2_inode *dip; + + log_debug(_("Directory %lld (0x%llx) already had a " + "".." link to %lld (0x%llx).\n"), + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)di->dotdot_parent, + (unsigned long long)di->dotdot_parent); + decrement_link(di->dotdot_parent, + ip->i_di.di_num.no_addr, + _(".. unlinked, moving to lost+found")); + dip = fsck_load_inode(ip->i_sbd, di->dotdot_parent); + dip->i_di.di_nlink--; + log_debug(_("Decrementing its links to %d\n"), + dip->i_di.di_nlink); + bmodified(dip->i_bh); + fsck_inode_put(&dip); + di = NULL; + } else + log_debug(_("Couldn't find a valid ".." entry " + "for orphan directory %lld (0x%llx)\n"), + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr); if(gfs2_dirent_del(ip, "..", 2)) log_warn( _("add_inode_to_lf: Unable to remove " "".." directory entry.\n"));
cluster-commits@lists.stg.fedorahosted.org