cluster: RHEL6 - libgfs2: Mark buffer modified adding a new GFS1 block
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: acee2940261ea454b8f82fcc55827a3e97ad0049
Parent: 08b9756cb840be6174af0eb962b17a048316d154
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Aug 10 10:25:19 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
libgfs2: Mark buffer modified adding a new GFS1 block
When adding new blocks to the file system for GFS1, function
gfs1_lookup_block was not marking the buffer and dinode buffer
as modified like gfs2_lookup_block does. This patch fixes that.
rhbz#675723
---
gfs2/libgfs2/gfs1.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c
index 2bdf57f..59eaa8d 100644
--- a/gfs2/libgfs2/gfs1.c
+++ b/gfs2/libgfs2/gfs1.c
@@ -54,7 +54,9 @@ void gfs1_lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
*block = meta_alloc(ip);
*ptr = cpu_to_be64(*block);
+ bmodified(bh);
ip->i_di.di_blocks++;
+ bmodified(ip->i_bh);
*new = 1;
}
12 years, 4 months
cluster: RHEL6 - libgfs2: eliminate gfs1_readi in favor of gfs2_readi
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 08b9756cb840be6174af0eb962b17a048316d154
Parent: 0bb789dbabb6ada3d29dd476c520428d8c116c42
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Aug 10 10:21:00 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
libgfs2: eliminate gfs1_readi in favor of gfs2_readi
This patch eliminates function gfs1_readi because it's nearly
identical to gfs2_readi. The gfs1-specific bits have been made
generic in gfs2_readi based on the sdp->gfs1 setting.
rhbz#675723
---
gfs2/edit/extended.c | 8 +----
gfs2/libgfs2/fs_ops.c | 21 ++++++++++----
gfs2/libgfs2/gfs1.c | 68 +-----------------------------------------------
gfs2/libgfs2/libgfs2.h | 2 -
gfs2/libgfs2/super.c | 5 ---
5 files changed, 18 insertions(+), 86 deletions(-)
diff --git a/gfs2/edit/extended.c b/gfs2/edit/extended.c
index 366dfc6..6326ec3 100644
--- a/gfs2/edit/extended.c
+++ b/gfs2/edit/extended.c
@@ -515,12 +515,8 @@ static int parse_rindex(struct gfs2_inode *dip, int print_rindex)
roff = print_entry_ndx * sizeof(struct gfs2_rindex);
- if (sbd.gfs1)
- error = gfs1_readi(dip, (void *)&rbuf, roff,
- sizeof(struct gfs2_rindex));
- else
- error = gfs2_readi(dip, (void *)&rbuf, roff,
- sizeof(struct gfs2_rindex));
+ error = gfs2_readi(dip, (void *)&rbuf, roff,
+ sizeof(struct gfs2_rindex));
if (!error) /* end of file */
break;
gfs2_rindex_in(&ri, rbuf);
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 3d57b97..6ffee9d 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -508,6 +508,7 @@ int gfs2_readi(struct gfs2_inode *ip, void *buf,
unsigned int amount;
int not_new = 0;
int isdir = !!(S_ISDIR(ip->i_di.di_mode));
+ int journaled = ip->i_di.di_flags & GFS2_DIF_JDATA;
int copied = 0;
if (offset >= ip->i_di.di_size)
@@ -519,7 +520,7 @@ int gfs2_readi(struct gfs2_inode *ip, void *buf,
if (!size)
return 0;
- if (isdir) {
+ if ((sdp->gfs1 && journaled) || (!sdp->gfs1 && isdir)) {
lblock = offset;
o = lblock % sdp->sd_jbsize;
lblock /= sdp->sd_jbsize;
@@ -530,7 +531,7 @@ int gfs2_readi(struct gfs2_inode *ip, void *buf,
if (inode_is_stuffed(ip))
o += sizeof(struct gfs2_dinode);
- else if (isdir)
+ else if ((sdp->gfs1 && journaled) || (!sdp->gfs1 && isdir))
o += sizeof(struct gfs2_meta_header);
while (copied < size) {
@@ -538,9 +539,14 @@ int gfs2_readi(struct gfs2_inode *ip, void *buf,
if (amount > sdp->bsize - o)
amount = sdp->bsize - o;
- if (!extlen)
- block_map(ip, lblock, ¬_new, &dblock, &extlen,
- FALSE);
+ if (!extlen) {
+ if (sdp->gfs1)
+ gfs1_block_map(ip, lblock, ¬_new, &dblock,
+ &extlen, FALSE);
+ else
+ block_map(ip, lblock, ¬_new, &dblock,
+ &extlen, FALSE);
+ }
if (dblock) {
if (dblock == ip->i_di.di_num.no_addr)
@@ -559,7 +565,10 @@ int gfs2_readi(struct gfs2_inode *ip, void *buf,
copied += amount;
lblock++;
- o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
+ if (sdp->gfs1)
+ o = (journaled) ? sizeof(struct gfs2_meta_header) : 0;
+ else
+ o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
}
return copied;
diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c
index 5018334..2bdf57f 100644
--- a/gfs2/libgfs2/gfs1.c
+++ b/gfs2/libgfs2/gfs1.c
@@ -154,72 +154,6 @@ void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
free(mp);
}
-int gfs1_readi(struct gfs2_inode *ip, void *bufin,
- uint64_t offset, unsigned int size)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- struct gfs2_buffer_head *bh;
- uint64_t lblock, dblock = 0;
- uint32_t extlen = 0;
- unsigned int amount;
- int not_new = 0;
- int journaled = fs_is_jdata(ip);
- int copied = 0;
- char *buf = bufin;
-
- if (offset >= ip->i_di.di_size)
- return 0;
-
- if ((offset + size) > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
-
- if (!size)
- return 0;
-
- if (journaled) {
- lblock = offset / sdp->sd_jbsize;
- offset %= sdp->sd_jbsize;
- } else {
- lblock = offset >> sdp->sd_sb.sb_bsize_shift;
- offset &= sdp->sd_sb.sb_bsize - 1;
- }
-
- if (!ip->i_di.di_height) /* stuffed */
- offset += sizeof(struct gfs_dinode);
- else if (journaled)
- offset += sizeof(struct gfs2_meta_header);
-
- while (copied < size) {
- amount = size - copied;
- if (amount > sdp->bsize - offset)
- amount = sdp->bsize - offset;
-
- if (!extlen)
- gfs1_block_map(ip, lblock, ¬_new, &dblock,
- &extlen, FALSE);
-
- if (dblock) {
- bh = bread(sdp, dblock);
- dblock++;
- extlen--;
- } else
- bh = NULL;
-
-
- if (bh) {
- memcpy(buf+copied, bh->b_data + offset, amount);
- brelse(bh);
- } else
- memset(buf+copied, 0, amount);
- copied += amount;
- lblock++;
-
- offset = (journaled) ? sizeof(struct gfs2_meta_header) : 0;
- }
-
- return copied;
-}
-
/**
* gfs1_rindex_read - read in the rg index file
* Stolen from libgfs2/super.c, but modified to handle gfs1.
@@ -244,7 +178,7 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
if (fd > 0)
error = read(fd, &buf, sizeof(struct gfs2_rindex));
else
- error = gfs1_readi(sdp->md.riinode, (char *)&buf,
+ error = gfs2_readi(sdp->md.riinode, (char *)&buf,
(rg * sizeof(struct gfs2_rindex)),
sizeof(struct gfs2_rindex));
if (!error)
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 9bae01b..cc71bd3 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -665,8 +665,6 @@ extern void gfs1_lookup_block(struct gfs2_inode *ip,
int create, int *new, uint64_t *block);
extern void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new,
uint64_t *dblock, uint32_t *extlen, int prealloc);
-extern int gfs1_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
- unsigned int size);
extern int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1);
extern int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet);
extern struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp,
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index d902ba2..0fac740 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -158,11 +158,6 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
for (rg = 0; ; rg++) {
if (fd > 0)
error = read(fd, &buf, sizeof(struct gfs2_rindex));
- else if (sdp->gfs1)
- error = gfs1_readi(sdp->md.riinode,
- (char *)&buf.bufgfs1,
- rg * sizeof(struct gfs2_rindex),
- sizeof(struct gfs2_rindex));
else
error = gfs2_readi(sdp->md.riinode,
(char *)&buf.bufgfs2,
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: don't free prev rgrp list repairing rgrps
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 0bb789dbabb6ada3d29dd476c520428d8c116c42
Parent: debfd10488695bc940bbb1cd88b2dc79e74064b3
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 15:51:34 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
fsck.gfs2: don't free prev rgrp list repairing rgrps
In cases where fsck.gfs2 is trying to repair damaged resource groups or
rindex, it tries several levels of repair. Some of those levels build a
list of expected resource groups and check them against the actual ones,
and the previous list is freed before the next level is attempted.
However, in the case of minor damage, such as one bitmap block that was
overwritten, we can often repair the damage by reading in the resource
groups at the first level, then at the second level of repair (called
"ye_of_little_faith") use those values to compare against. This patch
allows the second level of repair to use the first level's list.
rhbz#675723
---
gfs2/fsck/rgrepair.c | 17 +++++++++++++----
1 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
index 52cc529..c01aaa6 100644
--- a/gfs2/fsck/rgrepair.c
+++ b/gfs2/fsck/rgrepair.c
@@ -780,12 +780,12 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
osi_list_t *exp, *act; /* expected, actual */
struct gfs2_rindex buf;
- /* Free previous incarnations in memory, if any. */
- gfs2_rgrp_free(&sdp->rglist);
-
if (trust_lvl == blind_faith)
return 0;
- else if (trust_lvl == ye_of_little_faith) { /* if rindex seems sane */
+ if (trust_lvl == ye_of_little_faith) { /* if rindex seems sane */
+ /* Don't free previous incarnations in memory, if any.
+ * We need them to copy in the next function:
+ * gfs2_rgrp_free(&sdp->rglist); */
if (!(*sane)) {
log_err(_("The rindex file does not meet our "
"expectations.\n"));
@@ -798,6 +798,9 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
return error;
}
} else if (trust_lvl == open_minded) { /* If we can't trust RG index */
+ /* Free previous incarnations in memory, if any. */
+ gfs2_rgrp_free(&sdp->rglist);
+
/* Calculate our own RG index for comparison */
error = gfs2_rindex_calculate(sdp, &expected_rglist,
&calc_rg_count);
@@ -807,6 +810,9 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
}
}
else if (trust_lvl == distrust) { /* If we can't trust RG index */
+ /* Free previous incarnations in memory, if any. */
+ gfs2_rgrp_free(&sdp->rglist);
+
error = gfs2_rindex_rebuild(sdp, &expected_rglist,
&calc_rg_count, 0);
if (error) {
@@ -817,6 +823,9 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
sdp->rgrps = calc_rg_count;
}
else if (trust_lvl == indignation) { /* If we can't trust anything */
+ /* Free previous incarnations in memory, if any. */
+ gfs2_rgrp_free(&sdp->rglist);
+
error = gfs2_rindex_rebuild(sdp, &expected_rglist,
&calc_rg_count, 1);
if (error) {
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: Add find_remove_dup, free_block_if_notdup
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: debfd10488695bc940bbb1cd88b2dc79e74064b3
Parent: 32e3d16a69e12b19134557fde710d22d0560a356
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 15:29:35 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
fsck.gfs2: Add find_remove_dup, free_block_if_notdup
This patch adds a couple new functions to util.c: find_remove_dup
and free_block_if_notdup. This is a centralized function that
is used to remove a duplicate reference. Each reference needs to be
removed to determine when all duplicate references have been resolved.
The object is to get down to one reference, so we can set the proper
type based on the remaining reference. However, if the very last
reference is deleted as well, the block may be freed.
These functions present one consistent way to do all this rather than
before when the it wasn't very consistent and various bitmap
inaccuracies were sometimes left in the file system.
rhbz#675723
---
gfs2/fsck/metawalk.c | 64 ++++++++++++++++++++++++-------
gfs2/fsck/metawalk.h | 4 ++
gfs2/fsck/pass1.c | 34 +----------------
gfs2/fsck/util.c | 101 ++++++++++++++++++++++++++-----------------------
gfs2/fsck/util.h | 4 ++
5 files changed, 113 insertions(+), 94 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index a5de1c8..b25b40d 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -823,6 +823,54 @@ int delete_block(struct gfs2_inode *ip, uint64_t block,
}
/**
+ * find_remove_dup - find out if this is a duplicate ref. If so, remove it.
+ * Returns: 0 if not a duplicate reference, 1 if it is.
+ */
+int find_remove_dup(struct gfs2_inode *ip, uint64_t block, const char *btype)
+{
+ struct duptree *d;
+ struct inode_with_dups *id;
+
+ d = dupfind(block);
+ if (!d)
+ return 0;
+
+ /* remove the inode reference id structure for this reference. */
+ id = find_dup_ref_inode(d, ip);
+ if (!id)
+ return 0;
+
+ dup_listent_delete(id);
+ log_err( _("Removing duplicate status of block %llu (0x%llx) "
+ "referenced as %s by dinode %llu (0x%llx)\n"),
+ (unsigned long long)block, (unsigned long long)block,
+ btype, (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ d->refs--; /* one less reference */
+ if (d->refs == 1) {
+ log_info( _("This leaves only one reference: it's "
+ "no longer a duplicate.\n"));
+ dup_delete(d); /* not duplicate now */
+ } else
+ log_info( _("%d block reference(s) remain.\n"),
+ d->refs);
+ return 1; /* but the original ref still exists so do not free it. */
+}
+
+/**
+ * free_block_if_notdup - free blocks associated with an inode, but if it's a
+ * duplicate, just remove that designation instead.
+ * Returns: 0 if the block was freed, 1 if a duplicate reference was removed
+ */
+int free_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
+ const char *btype)
+{
+ if (!find_remove_dup(ip, block, btype))
+ fsck_blockmap_set(ip, block, btype, gfs2_block_free);
+ return 0;
+}
+
+/**
* delete_block_if_notdup - delete blocks associated with an inode
*
* Ignore blocks that are already marked free.
@@ -834,7 +882,6 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
const char *btype, void *private)
{
uint8_t q;
- struct duptree *d;
if (!valid_block(ip->i_sbd, block))
return -EFAULT;
@@ -849,20 +896,7 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
(unsigned long long)ip->i_di.di_num.no_addr);
return 0;
}
- d = dupfind(block);
- if (d) {
- log_info( _("Removing duplicate reference %d "
- "to block %lld (0x%llx).\n"), d->refs,
- (unsigned long long)block,
- (unsigned long long)block);
- d->refs--; /* one less reference */
- if (d->refs == 1) /* If down to the last reference */
- dup_delete(d); /* not duplicate now */
- return 1; /* but the original ref still exists
- so return (do not free it). */
- }
- fsck_blockmap_set(ip, block, btype, gfs2_block_free);
- return 0;
+ return free_block_if_notdup(ip, block, btype);
}
/**
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index 7a8ae4c..719bbd9 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -35,6 +35,10 @@ extern void reprocess_inode(struct gfs2_inode *ip, const char *desc);
extern struct duptree *dupfind(uint64_t block);
extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp,
uint64_t block);
+extern int find_remove_dup(struct gfs2_inode *ip, uint64_t block,
+ const char *btype);
+extern int free_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
+ const char *btype);
#define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index f5ec37a..64220f0 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -438,7 +438,6 @@ static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h,
void *private)
{
- struct duptree *d;
int found_dup = 0, iblk_type;
struct gfs2_buffer_head *nbh;
struct block_count *bc = (struct block_count *)private;
@@ -455,20 +454,7 @@ static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
else
iblk_type = GFS2_METATYPE_IN;
- d = dupfind(block);
- if (d) {
- log_err( _("Reversing duplicate status of block %llu (0x%llx) "
- "referenced as metadata in indirect block for "
- "dinode %llu (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- d->refs--; /* one less reference */
- if (d->refs == 1)
- dup_delete(d);
- found_dup = 1;
- }
+ found_dup = find_remove_dup(ip, block, _("Metadata"));
nbh = bread(ip->i_sbd, block);
if (gfs2_check_meta(nbh, iblk_type)) {
@@ -548,7 +534,6 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
static int undo_check_data(struct gfs2_inode *ip, uint64_t block,
void *private)
{
- struct duptree *d;
struct block_count *bc = (struct block_count *) private;
if (!valid_block(ip->i_sbd, block)) {
@@ -560,23 +545,8 @@ static int undo_check_data(struct gfs2_inode *ip, uint64_t block,
gfs2_block_free);
return 1;
}
- d = dupfind(block);
- if (d) {
- log_err( _("Reversing duplicate status of block %llu (0x%llx) "
- "referenced as data by dinode %llu (0x%llx)\n"),
- (unsigned long long)block,
- (unsigned long long)block,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- d->refs--; /* one less reference */
- if (d->refs == 1)
- dup_delete(d);
- bc->data_count--;
- return 1;
- }
- fsck_blockmap_set(ip, block, _("data"), gfs2_block_free);
bc->data_count--;
- return 0;
+ return free_block_if_notdup(ip, block, _("data"));
}
static int remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc)
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index 9930624..569f25a 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -185,6 +185,30 @@ static struct duptree *gfs2_dup_set(uint64_t dblock, int create)
return data;
}
+/**
+ * find_dup_ref_inode - find a duplicate reference inode entry for an inode
+ */
+struct inode_with_dups *find_dup_ref_inode(struct duptree *dt,
+ struct gfs2_inode *ip)
+{
+ osi_list_t *ref;
+ struct inode_with_dups *id;
+
+ osi_list_foreach(ref, &dt->ref_invinode_list) {
+ id = osi_list_entry(ref, struct inode_with_dups, list);
+
+ if (id->block_no == ip->i_di.di_num.no_addr)
+ return id;
+ }
+ osi_list_foreach(ref, &dt->ref_inode_list) {
+ id = osi_list_entry(ref, struct inode_with_dups, list);
+
+ if (id->block_no == ip->i_di.di_num.no_addr)
+ return id;
+ }
+ return NULL;
+}
+
/*
* add_duplicate_ref - Add a duplicate reference to the duplicates tree list
* A new element of the tree will be created as needed
@@ -193,15 +217,19 @@ static struct duptree *gfs2_dup_set(uint64_t dblock, int create)
* So we need to recreate the duplicate reference structure if it's not there.
* Later, in pass1b, it has to go back through the file system
* and figure out those original references in order to resolve them.
+ *
+ * first - if 1, we're being called from pass1b, in which case we're trying
+ * to find the first reference to this block. If 0, we're being
+ * called from pass1, which is the second reference, which determined
+ * it was a duplicate..
*/
int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
enum dup_ref_type reftype, int first, int inode_valid)
{
- osi_list_t *ref;
- struct inode_with_dups *id, *found_id;
+ struct inode_with_dups *id;
struct duptree *dt;
- if (!valid_block(ip->i_sbd, block) != 0)
+ if (!valid_block(ip->i_sbd, block))
return 0;
/* If this is not the first reference (i.e. all calls from pass1) we
need to create the duplicate reference. If this is pass1b, we want
@@ -221,65 +249,42 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
reference, we don't want to increment the reference count because
it's already accounted for. */
if (first) {
- if (!dt->first_ref_found) {
- dt->first_ref_found = 1;
- dups_found_first++; /* We found another first ref. */
- }
+ dt->first_ref_found = 1;
+ dups_found_first++; /* We found another first ref. */
} else {
dt->refs++;
}
- /* Check for a previous reference to this duplicate on the "invalid
- inode" reference list. */
- found_id = NULL;
- osi_list_foreach(ref, &dt->ref_invinode_list) {
- id = osi_list_entry(ref, struct inode_with_dups, list);
-
- if (id->block_no == ip->i_di.di_num.no_addr) {
- found_id = id;
- break;
- }
- }
- if (found_id == NULL) {
- osi_list_foreach(ref, &dt->ref_inode_list) {
- id = osi_list_entry(ref, struct inode_with_dups, list);
-
- if (id->block_no == ip->i_di.di_num.no_addr) {
- found_id = id;
- break;
- }
- }
- }
- if (found_id == NULL) {
+ /* Check for a previous reference to this duplicate */
+ id = find_dup_ref_inode(dt, ip);
+ if (id == NULL) {
/* Check for the inode on the invalid inode reference list. */
uint8_t q;
- if (!(found_id = malloc(sizeof(*found_id)))) {
+ if (!(id = malloc(sizeof(*id)))) {
log_crit( _("Unable to allocate "
"inode_with_dups structure\n"));
return -1;
}
- if (!(memset(found_id, 0, sizeof(*found_id)))) {
+ if (!(memset(id, 0, sizeof(*id)))) {
log_crit( _("Unable to zero inode_with_dups "
"structure\n"));
return -1;
}
- found_id->block_no = ip->i_di.di_num.no_addr;
+ id->block_no = ip->i_di.di_num.no_addr;
q = block_type(ip->i_di.di_num.no_addr);
/* If it's an invalid dinode, put it first on the invalid
inode reference list otherwise put it on the normal list. */
if (!inode_valid || q == gfs2_inode_invalid)
- osi_list_add_prev(&found_id->list,
- &dt->ref_invinode_list);
+ osi_list_add_prev(&id->list, &dt->ref_invinode_list);
else
- osi_list_add_prev(&found_id->list,
- &dt->ref_inode_list);
+ osi_list_add_prev(&id->list, &dt->ref_inode_list);
}
- found_id->reftypecount[reftype]++;
- found_id->dup_count++;
+ id->reftypecount[reftype]++;
+ id->dup_count++;
log_info( _("Found %d reference(s) to block %llu"
" (0x%llx) as %s in inode #%llu (0x%llx)\n"),
- found_id->dup_count, (unsigned long long)block,
+ id->dup_count, (unsigned long long)block,
(unsigned long long)block, reftypes[reftype],
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
@@ -343,6 +348,14 @@ struct dir_info *dirtree_find(uint64_t block)
return NULL;
}
+void dup_listent_delete(struct inode_with_dups *id)
+{
+ if (id->name)
+ free(id->name);
+ osi_list_del(&id->list);
+ free(id);
+}
+
void dup_delete(struct duptree *b)
{
struct inode_with_dups *id;
@@ -351,18 +364,12 @@ void dup_delete(struct duptree *b)
while (!osi_list_empty(&b->ref_invinode_list)) {
tmp = (&b->ref_invinode_list)->next;
id = osi_list_entry(tmp, struct inode_with_dups, list);
- if (id->name)
- free(id->name);
- osi_list_del(&id->list);
- free(id);
+ dup_listent_delete(id);
}
while (!osi_list_empty(&b->ref_inode_list)) {
tmp = (&b->ref_inode_list)->next;
id = osi_list_entry(tmp, struct inode_with_dups, list);
- if (id->name)
- free(id->name);
- osi_list_del(&id->list);
- free(id);
+ dup_listent_delete(id);
}
osi_erase(&b->node, &dup_blocks);
free(b);
diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
index d2c81db..56b83fe 100644
--- a/gfs2/fsck/util.h
+++ b/gfs2/fsck/util.h
@@ -15,6 +15,10 @@ void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked);
void warm_fuzzy_stuff(uint64_t block);
int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
enum dup_ref_type reftype, int first, int inode_valid);
+extern struct inode_with_dups *find_dup_ref_inode(struct duptree *dt,
+ struct gfs2_inode *ip);
+extern void dup_listent_delete(struct inode_with_dups *id);
+
extern const char *reftypes[3];
static inline uint8_t block_type(uint64_t bblock)
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: Don't use old_leaf if it was a duplicate
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 32e3d16a69e12b19134557fde710d22d0560a356
Parent: d44048a47efe1784bdcb3da3b995fc77259bebb7
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 14:22:12 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
fsck.gfs2: Don't use old_leaf if it was a duplicate
In function check_leaf_blks fsck.gfs2 keeps track of the current leaf
and the previous leaf. It can only check the number of pointers is
correct for the old leaf after it finds a new leaf block. However,
it was getting confused if the old leaf was a duplicate reference.
If the old leaf was a duplicate referenced by a different dinode, we
can't check the number of pointers because the number of pointers may
be for that other dinode's reference, not this one. The other dinode
referencing this leaf block may have the correct depth and this one
may not. This patch adds an extra check for the old leaf block being
a duplicate before checking the number of pointers.
rhbz#675723
---
gfs2/fsck/metawalk.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 9b68de8..a5de1c8 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -603,7 +603,7 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
struct gfs2_buffer_head *lbh;
int lindex;
struct gfs2_sbd *sdp = ip->i_sbd;
- int ref_count = 0;
+ int ref_count = 0, old_was_dup;
/* Find the first valid leaf pointer in range and use it as our "old"
leaf. That way, bad blocks at the beginning will be overwritten
@@ -631,7 +631,8 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
}
old_leaf = -1;
memset(&oldleaf, 0, sizeof(oldleaf));
- for(lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
+ old_was_dup = 0;
+ for (lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
if (fsck_abort)
break;
gfs2_get_leaf_nr(ip, lindex, &leaf_no);
@@ -650,7 +651,11 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
do {
if (fsck_abort)
return 0;
- if (pass->check_num_ptrs &&
+ /* If the old leaf was a duplicate referenced by a
+ previous dinode, we can't check the number of
+ pointers because the number of pointers may be for
+ that other dinode's reference, not this one. */
+ if (pass->check_num_ptrs && !old_was_dup &&
valid_block(ip->i_sbd, old_leaf)) {
error = pass->check_num_ptrs(ip, old_leaf,
&ref_count,
@@ -662,6 +667,7 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
error = check_leaf(ip, lindex, pass, &ref_count,
&leaf_no, old_leaf, &bad_leaf,
first_ok_leaf, &leaf, &oldleaf);
+ old_was_dup = (error == -EEXIST);
old_leaf = leaf_no;
memcpy(&oldleaf, &leaf, sizeof(oldleaf));
if (!leaf.lf_next || error)
12 years, 4 months
cluster: RHEL6 - fsck.gfs2: misc cosmetic changes
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: d44048a47efe1784bdcb3da3b995fc77259bebb7
Parent: 0f369e0d0cbb8245485321f8a5077f95d29c59e5
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 14:07:21 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
fsck.gfs2: misc cosmetic changes
This patch is just cosmetic changes. It cleans up comments and code
but there should be no logic changes.
rhbz#675723
---
gfs2/fsck/metawalk.c | 17 +++++++----------
gfs2/fsck/pass1.c | 8 ++++----
gfs2/fsck/pass1b.c | 9 +++++----
gfs2/fsck/pass2.c | 2 +-
gfs2/fsck/pass5.c | 10 ++++++----
5 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 92973ae..9b68de8 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -453,15 +453,14 @@ static int warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
}
if (*leaf_no == *bad_leaf ||
(okay_to_fix = query( _("Attempt to patch around it? (y/n) ")))) {
- if (!valid_block(ip->i_sbd, old_leaf) == 0)
+ if (valid_block(ip->i_sbd, old_leaf))
gfs2_put_leaf_nr(ip, pindex, old_leaf);
else
gfs2_put_leaf_nr(ip, pindex, first_ok_leaf);
log_err( _("Directory Inode %llu (0x%llx) repaired.\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
- }
- else
+ } else
log_err( _("Bad leaf left in place.\n"));
*bad_leaf = *leaf_no;
*leaf_no = old_leaf;
@@ -610,9 +609,9 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
leaf. That way, bad blocks at the beginning will be overwritten
with the first valid leaf. */
first_ok_leaf = leaf_no = -1;
- for(lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
+ for (lindex = 0; lindex < (1 << ip->i_di.di_depth); lindex++) {
gfs2_get_leaf_nr(ip, lindex, &leaf_no);
- if (!valid_block(ip->i_sbd, leaf_no) == 0) {
+ if (valid_block(ip->i_sbd, leaf_no)) {
lbh = bread(sdp, leaf_no);
/* Make sure it's really a valid leaf block. */
if (gfs2_check_meta(lbh, GFS2_METATYPE_LF) == 0) {
@@ -638,11 +637,9 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
gfs2_get_leaf_nr(ip, lindex, &leaf_no);
/* GFS has multiple indirect pointers to the same leaf
- * until those extra pointers are needed, so skip the
- * dups */
+ * until those extra pointers are needed, so skip the dups */
if (leaf_no == bad_leaf) {
- gfs2_put_leaf_nr(ip, lindex, old_leaf); /* fill w/old
- leaf info */
+ gfs2_put_leaf_nr(ip, lindex, old_leaf);
ref_count++;
continue;
} else if (old_leaf == leaf_no) {
@@ -812,7 +809,7 @@ int delete_block(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, const char *btype,
void *private)
{
- if (!valid_block(ip->i_sbd, block) == 0) {
+ if (valid_block(ip->i_sbd, block)) {
fsck_blockmap_set(ip, block, btype, gfs2_block_free);
return 0;
}
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 7077272..f5ec37a 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -371,7 +371,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
*bh = NULL;
- if (!valid_block(ip->i_sbd, block)){ /* blk outside of FS */
+ if (!valid_block(ip->i_sbd, block)) { /* blk outside of FS */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
_("itself"), gfs2_bad_block);
log_debug( _("Bad indirect block (invalid/out of range) "
@@ -445,7 +445,7 @@ static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
*bh = NULL;
- if (!valid_block(ip->i_sbd, block)){ /* blk outside of FS */
+ if (!valid_block(ip->i_sbd, block)) { /* blk outside of FS */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
_("itself"), gfs2_block_free);
return 1;
@@ -866,7 +866,7 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
struct gfs2_buffer_head *bh = NULL;
int error;
- if (!valid_block(sdp, el_blk)){
+ if (!valid_block(sdp, el_blk)) {
log_err( _("Inode #%llu (0x%llx): Extended Attribute block "
"%llu (0x%llx) has an extended leaf block #%llu "
"(0x%llx) that is invalid or out of range.\n"),
@@ -1058,7 +1058,7 @@ static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
long *bad_pointers = (long *)private;
uint8_t q;
- if (!valid_block(ip->i_sbd, block) != 0) {
+ if (!valid_block(ip->i_sbd, block)) {
(*bad_pointers)++;
log_info( _("Bad %s block pointer (invalid or out of range "
"#%ld) found in inode %lld (0x%llx).\n"),
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 259eb7a..67b8d14 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -209,7 +209,7 @@ static int clear_dup_metalist(struct gfs2_inode *ip, uint64_t block,
struct dup_handler *dh = (struct dup_handler *) private;
struct duptree *d;
- if (!valid_block(ip->i_sbd, block) != 0)
+ if (!valid_block(ip->i_sbd, block))
return 0;
/* This gets tricky. We're traversing a metadata tree trying to
@@ -625,9 +625,10 @@ int pass1b(struct gfs2_sbd *sdp)
/* Rescan the fs looking for pointers to blocks that are in
* the duplicate block map */
log_info( _("Scanning filesystem for inodes containing duplicate blocks...\n"));
- log_debug( _("Filesystem has %"PRIu64" (0x%" PRIx64 ") blocks total\n"),
- last_fs_block, last_fs_block);
- for(i = 0; i < last_fs_block; i++) {
+ log_debug( _("Filesystem has %llu (0x%llx) blocks total\n"),
+ (unsigned long long)last_fs_block,
+ (unsigned long long)last_fs_block);
+ for (i = 0; i < last_fs_block; i++) {
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
goto out;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 5fe5454..7f32903 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -767,7 +767,7 @@ int pass2(struct gfs2_sbd *sdp)
return FSCK_OK;
log_info( _("Checking directory inodes.\n"));
/* Grab each directory inode, and run checks on it */
- for(dirblk = 0; dirblk < last_fs_block; dirblk++) {
+ for (dirblk = 0; dirblk < last_fs_block; dirblk++) {
warm_fuzzy_stuff(dirblk);
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return FSCK_OK;
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index b71b2b6..814f202 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -43,13 +43,14 @@ static int convert_mark(uint8_t q, uint32_t *count)
default:
log_err( _("Invalid block type %d found\n"), q);
- return -1;
}
return -1;
}
-static int check_block_status(struct gfs2_sbd *sdp, char *buffer, unsigned int buflen,
- uint64_t *rg_block, uint64_t rg_data, uint32_t *count)
+
+static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
+ unsigned int buflen, uint64_t *rg_block,
+ uint64_t rg_data, uint32_t *count)
{
unsigned char *byte, *end;
unsigned int bit;
@@ -150,7 +151,8 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
/* update the bitmaps */
check_block_status(sdp, rgp->bh[i]->b_data + bits->bi_offset,
- bits->bi_len, &rg_block, rgp->ri.ri_data0, count);
+ bits->bi_len, &rg_block, rgp->ri.ri_data0,
+ count);
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return;
}
12 years, 4 months
cluster: RHEL6 - fsck.gfs2 pass3: Refactor mark_and_return_parent
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 0f369e0d0cbb8245485321f8a5077f95d29c59e5
Parent: 43c29f0c0477427ccf065642a355045ebb95f4bb
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 13:27:01 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:27 2012 -0600
fsck.gfs2 pass3: Refactor mark_and_return_parent
This patch refactors pass3 function "mark_and_return_parent". Before
it was so complex and indented you could hardly interpret it. Now you
can actually follow the logic.
rhbz#675723
---
gfs2/fsck/pass3.c | 162 ++++++++++++++++++++++++++---------------------------
1 files changed, 79 insertions(+), 83 deletions(-)
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index 580c662..b904814 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -73,102 +73,98 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
{
struct dir_info *pdi;
uint8_t q_dotdot, q_treewalk;
+ int error = 0;
di->checked = 1;
if (!di->treewalk_parent)
return NULL;
- if (di->dotdot_parent != di->treewalk_parent) {
- log_warn( _("Directory '..' and treewalk connections disagree for inode %llu"
- " (0x%llx)\n"), (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
- log_notice( _("'..' has %llu (0x%llx), treewalk has %llu"
- " (0x%llx)\n"),
- (unsigned long long)di->dotdot_parent,
- (unsigned long long)di->dotdot_parent,
- (unsigned long long)di->treewalk_parent,
- (unsigned long long)di->treewalk_parent);
+ if (di->dotdot_parent == di->treewalk_parent) {
q_dotdot = block_type(di->dotdot_parent);
- q_treewalk = block_type(di->treewalk_parent);
- /* if the dotdot entry isn't a directory, but the
- * treewalk is, treewalk is correct - if the treewalk
- * entry isn't a directory, but the dotdot is, dotdot
- * is correct - if both are directories, which do we
- * choose? if neither are directories, we have a
- * problem - need to move this directory into lost+found
- */
if (q_dotdot != gfs2_inode_dir) {
- if (q_treewalk != gfs2_inode_dir) {
- log_err( _("Orphaned directory, move to lost+found\n"));
- return NULL;
- }
- else {
- log_warn( _("Treewalk parent is correct,"
- " fixing dotdot -> %llu (0x%llx)\n"),
- (unsigned long long)di->treewalk_parent,
- (unsigned long long)di->treewalk_parent);
- attach_dotdot_to(sdp, di->treewalk_parent,
- di->dotdot_parent, di->dinode);
- di->dotdot_parent = di->treewalk_parent;
- }
- } else {
- if (q_treewalk != gfs2_inode_dir) {
- int error = 0;
- log_warn( _(".. parent is valid, but treewalk"
- "is bad - reattaching to lost+found"));
-
- /* FIXME: add a dinode for this entry instead? */
-
- if (query( _("Remove directory entry for bad"
- " inode %llu (0x%llx) in %llu"
- " (0x%llx)? (y/n)"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode,
- (unsigned long long)di->treewalk_parent,
- (unsigned long long)di->treewalk_parent)) {
- error = remove_dentry_from_dir(sdp, di->treewalk_parent,
- di->dinode);
- if (error < 0) {
- stack;
- return NULL;
- }
- if (error > 0) {
- log_warn( _("Unable to find dentry for block %llu"
- " (0x%llx) in %llu (0x%llx)\n"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode,
- (unsigned long long)di->treewalk_parent,
- (unsigned long long)di->treewalk_parent);
- }
- log_warn( _("Directory entry removed\n"));
- } else {
- log_err( _("Directory entry to invalid inode remains\n"));
- }
- log_info( _("Marking directory unlinked\n"));
-
- return NULL;
- }
- else {
- log_err( _("Both .. and treewalk parents are "
- "directories, going with treewalk "
- "for now...\n"));
- attach_dotdot_to(sdp, di->treewalk_parent,
- di->dotdot_parent,
- di->dinode);
- di->dotdot_parent = di->treewalk_parent;
- }
+ log_err( _("Orphaned directory at block %llu (0x%llx) "
+ "moved to lost+found\n"),
+ (unsigned long long)di->dinode,
+ (unsigned long long)di->dinode);
+ return NULL;
}
+ goto out;
}
- else {
- q_dotdot = block_type(di->dotdot_parent);
- if (q_dotdot != gfs2_inode_dir) {
- log_err( _("Orphaned directory at block %llu (0x%llx) moved to lost+found\n"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
+
+ log_warn( _("Directory '..' and treewalk connections disagree for "
+ "inode %llu (0x%llx)\n"), (unsigned long long)di->dinode,
+ (unsigned long long)di->dinode);
+ log_notice( _("'..' has %llu (0x%llx), treewalk has %llu (0x%llx)\n"),
+ (unsigned long long)di->dotdot_parent,
+ (unsigned long long)di->dotdot_parent,
+ (unsigned long long)di->treewalk_parent,
+ (unsigned long long)di->treewalk_parent);
+ q_dotdot = block_type(di->dotdot_parent);
+ q_treewalk = block_type(di->treewalk_parent);
+ /* if the dotdot entry isn't a directory, but the
+ * treewalk is, treewalk is correct - if the treewalk
+ * entry isn't a directory, but the dotdot is, dotdot
+ * is correct - if both are directories, which do we
+ * choose? if neither are directories, we have a
+ * problem - need to move this directory into lost+found
+ */
+ if (q_dotdot != gfs2_inode_dir) {
+ if (q_treewalk != gfs2_inode_dir) {
+ log_err( _("Orphaned directory, move to "
+ "lost+found\n"));
return NULL;
+ } else {
+ log_warn( _("Treewalk parent is correct, fixing "
+ "dotdot -> %llu (0x%llx)\n"),
+ (unsigned long long)di->treewalk_parent,
+ (unsigned long long)di->treewalk_parent);
+ attach_dotdot_to(sdp, di->treewalk_parent,
+ di->dotdot_parent, di->dinode);
+ di->dotdot_parent = di->treewalk_parent;
}
+ goto out;
+ }
+ if (q_treewalk == gfs2_inode_dir) {
+ log_err( _("Both .. and treewalk parents are directories, "
+ "going with treewalk...\n"));
+ attach_dotdot_to(sdp, di->treewalk_parent,
+ di->dotdot_parent, di->dinode);
+ di->dotdot_parent = di->treewalk_parent;
+ goto out;
}
+ log_warn( _(".. parent is valid, but treewalk is bad - reattaching to "
+ "lost+found"));
+
+ /* FIXME: add a dinode for this entry instead? */
+
+ if (!query( _("Remove directory entry for bad inode %llu (0x%llx) in "
+ "%llu (0x%llx)? (y/n)"),
+ (unsigned long long)di->dinode,
+ (unsigned long long)di->dinode,
+ (unsigned long long)di->treewalk_parent,
+ (unsigned long long)di->treewalk_parent)) {
+ log_err( _("Directory entry to invalid inode remains\n"));
+ return NULL;
+ }
+ error = remove_dentry_from_dir(sdp, di->treewalk_parent, di->dinode);
+ if (error < 0) {
+ stack;
+ return NULL;
+ }
+ if (error > 0)
+ log_warn( _("Unable to find dentry for block %llu"
+ " (0x%llx) in %llu (0x%llx)\n"),
+ (unsigned long long)di->dinode,
+ (unsigned long long)di->dinode,
+ (unsigned long long)di->treewalk_parent,
+ (unsigned long long)di->treewalk_parent);
+ log_warn( _("Directory entry removed\n"));
+ log_info( _("Marking directory unlinked\n"));
+
+ return NULL;
+
+out:
pdi = dirtree_find(di->dotdot_parent);
return pdi;
12 years, 4 months
cluster: RHEL6 - fsck.gfs2 pass2: Don't delete invalid inode metadata
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 43c29f0c0477427ccf065642a355045ebb95f4bb
Parent: 37a84a1d83dfb5b71cbf41cf5411caab8311e87a
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 13:01:05 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2 pass2: Don't delete invalid inode metadata
In pass2, all metadata was deleted for inodes that were marked either
"bad" or "invalid" but that is wrong, and here is why:
Blocks marked "invalid" were invalidated due to duplicate block references.
Pass1b should have already taken care of deleting their metadata, so in pass2
we only need to delete the directory entries pointing to them. We delete the
metadata in pass1b because we need to eliminate the inode referencing the
duplicate-referenced block from the list of candidates to keep. So we have a
delete-as-we-go policy. Blocks marked "bad" need to have their entire
metadata tree deleted.
rhbz#675723
---
gfs2/fsck/pass2.c | 30 ++++++++++++++++++++++--------
1 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index bcd9355..5fe5454 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -315,6 +315,18 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
q = block_type(entryblock);
/* Get the status of the directory inode */
+ /**
+ * 1. Blocks marked "invalid" were invalidated due to duplicate
+ * block references. Pass1b should have already taken care of deleting
+ * their metadata, so here we only need to delete the directory entries
+ * pointing to them. We delete the metadata in pass1b because we need
+ * to eliminate the inode referencing the duplicate-referenced block
+ * from the list of candidates to keep. So we have a delete-as-we-go
+ * policy.
+ *
+ * 2. Blocks marked "bad" need to have their entire
+ * metadata tree deleted.
+ */
if (q == gfs2_inode_invalid || q == gfs2_bad_block) {
/* This entry's inode has bad blocks in it */
@@ -329,14 +341,16 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
goto dentry_is_valid;
}
- if (ip->i_di.di_num.no_addr == entryblock)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sdp, entryblock);
- check_inode_eattr(entry_ip, &pass2_fxns_delete);
- check_metatree(entry_ip, &pass2_fxns_delete);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
+ if (q == gfs2_bad_block) {
+ if (ip->i_di.di_num.no_addr == entryblock)
+ entry_ip = ip;
+ else
+ entry_ip = fsck_load_inode(sdp, entryblock);
+ check_inode_eattr(entry_ip, &pass2_fxns_delete);
+ check_metatree(entry_ip, &pass2_fxns_delete);
+ if (entry_ip != ip)
+ fsck_inode_put(&entry_ip);
+ }
fsck_blockmap_set(ip, entryblock,
_("bad directory entry"), gfs2_block_free);
log_err( _("Inode %lld (0x%llx) was deleted.\n"),
12 years, 4 months
cluster: RHEL6 - fsck.gfs2 pass2: Delete extended attributes with inode
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 37a84a1d83dfb5b71cbf41cf5411caab8311e87a
Parent: eeaa054a33190440487bace78683cae8b8744910
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 12:48:36 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs2 pass2: Delete extended attributes with inode
When pass2 decided to delete a bad/corrupt dinode from disk, it was
not deleting extended attributes associated with that dinode. Oops.
This patch corrects the situation and allows it to delete them.
rhbz#675723
---
gfs2/fsck/pass2.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index b31d293..bcd9355 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -158,6 +158,59 @@ static int check_file_type(uint8_t de_type, uint8_t blk_type)
return 0;
}
+static int delete_eattr_entry (struct gfs2_inode *ip,
+ struct gfs2_buffer_head *leaf_bh,
+ struct gfs2_ea_header *ea_hdr,
+ struct gfs2_ea_header *ea_hdr_prev,
+ void *private)
+{
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ char ea_name[256];
+
+ if (!ea_hdr->ea_name_len){
+ /* Skip this entry for now */
+ return 1;
+ }
+
+ memset(ea_name, 0, sizeof(ea_name));
+ strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
+ ea_hdr->ea_name_len);
+
+ if (!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
+ ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
+ /* Skip invalid entry */
+ return 1;
+ }
+
+ if (ea_hdr->ea_num_ptrs){
+ uint32_t avail_size;
+ int max_ptrs;
+
+ avail_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header);
+ max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len) + avail_size - 1) /
+ avail_size;
+
+ if (max_ptrs > ea_hdr->ea_num_ptrs)
+ return 1;
+ else {
+ log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"),
+ max_ptrs, ea_hdr->ea_num_ptrs);
+ }
+ }
+ return 0;
+}
+
+static int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
+ struct gfs2_buffer_head *leaf_bh,
+ struct gfs2_ea_header *ea_hdr,
+ struct gfs2_ea_header *ea_hdr_prev,
+ void *private)
+{
+ uint64_t block = be64_to_cpu(*ea_data_ptr);
+
+ return delete_metadata(ip, block, NULL, 0, private);
+}
+
struct metawalk_fxns pass2_fxns_delete = {
.private = NULL,
.check_metalist = delete_metadata,
@@ -165,6 +218,8 @@ struct metawalk_fxns pass2_fxns_delete = {
.check_leaf = delete_leaf,
.check_eattr_indir = delete_eattr_indir,
.check_eattr_leaf = delete_eattr_leaf,
+ .check_eattr_entry = delete_eattr_entry,
+ .check_eattr_extentry = delete_eattr_extentry,
};
/* FIXME: should maybe refactor this a bit - but need to deal with
12 years, 4 months
cluster: RHEL6 - fsck.gfs pass2: Refactor function set_dotdot_dir
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: eeaa054a33190440487bace78683cae8b8744910
Parent: 94431db3595d647c196e2b518065ddc2b02cae38
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 12:45:18 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Jan 20 08:26:26 2012 -0600
fsck.gfs pass2: Refactor function set_dotdot_dir
This patch refactors function set_dotdot_dir to make it more readable.
rhbz#675723
---
gfs2/fsck/pass2.c | 46 ++++++++++++++++++++++++++--------------------
1 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 0424241..b31d293 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -57,34 +57,40 @@ static int set_parent_dir(struct gfs2_sbd *sdp, uint64_t childblock,
/* Set's the child's '..' directory inode number in dir_info structure */
static int set_dotdot_dir(struct gfs2_sbd *sdp, uint64_t childblock,
- uint64_t parentblock)
+ uint64_t parentblock)
{
struct dir_info *di;
di = dirtree_find(childblock);
- if (di) {
- if (di->dinode == childblock) {
- /* Special case for root inode because we set
- * it earlier */
- if (di->dotdot_parent && sdp->md.rooti->i_di.di_num.no_addr
- != di->dinode) {
- /* This should never happen */
- log_crit( _("Dotdot parent already set for"
- " block %"PRIu64" (0x%" PRIx64 ") -> %" PRIu64
- " (0x%" PRIx64 ")\n"), childblock, childblock,
- di->dotdot_parent, di->dotdot_parent);
- return -1;
- }
- di->dotdot_parent = parentblock;
- }
- } else {
+ if (!di) {
log_err( _("Unable to find block %"PRIu64" (0x%" PRIx64
- ") in dir_info list\n"), childblock, childblock);
+ ") in dir_info tree\n"), childblock, childblock);
return -1;
}
-
+ if (di->dinode != childblock) {
+ log_debug("'..' doesn't point to what we found: childblock "
+ "0x%llx != dinode 0x%llx\n",
+ (unsigned long long)childblock,
+ (unsigned long long)di->dinode);
+ return -1;
+ }
+ /* Special case for root inode because we set it earlier */
+ if (di->dotdot_parent &&
+ sdp->md.rooti->i_di.di_num.no_addr != di->dinode) {
+ /* This should never happen */
+ log_crit( _("Dotdot parent already set for block %llu (0x%llx)"
+ "-> %llu (0x%llx)\n"),
+ (unsigned long long)childblock,
+ (unsigned long long)childblock,
+ (unsigned long long)di->dotdot_parent,
+ (unsigned long long)di->dotdot_parent);
+ return -1;
+ }
+ log_debug("Setting '..' for directory block 0x%llx to parent 0x%llx\n",
+ (unsigned long long)childblock,
+ (unsigned long long)parentblock);
+ di->dotdot_parent = parentblock;
return 0;
-
}
static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
12 years, 4 months