Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: b46c19c385f182f950c6df56bafd3db15459c48e
Parent: 5df69b1d9f020df9e97629240196596c330567fa
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Fri Jan 22 15:07:19 2010 -0600
Committer: Bob Peterson <rpeterso(a)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"));