gfs2-utils: master - fsck.gfs2: fsck.gfs2: Duplicate ref processing for leaf blocks
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 6759a08320875da052809758fa94381d813cc456
Parent: 18bd4a7ac30b392a71acb12cb1eb9092480c9908
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 09:33:08 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Duplicate ref processing for leaf blocks
This patch adds checks for duplicate block references to the leaf block
processing.
rhbz#675723
---
gfs2/fsck/pass1.c | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index e39d9d2..b891a68 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -336,7 +336,27 @@ static int check_num_ptrs(struct gfs2_inode *ip, uint64_t leafno,
static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
{
struct block_count *bc = (struct block_count *) private;
+ uint8_t q;
+ /* Note if we've gotten this far, the block has already passed the
+ check in metawalk: gfs2_check_meta(lbh, GFS2_METATYPE_LF).
+ So we know it's a leaf block. */
+ q = block_type(block);
+ if (q != gfs2_block_free) {
+ log_err( _("Found duplicate block %llu (0x%llx) referenced "
+ "as a directory leaf in dinode "
+ "%llu (0x%llx) - was marked %d (%s)\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, q,
+ block_type_string(q));
+ add_duplicate_ref(ip, block, ref_as_meta, 0, INODE_VALID);
+ if (q == gfs2_leaf_blk) /* If the previous reference also saw
+ this as a leaf, it was already
+ checked, so don't check again. */
+ return -EEXIST;
+ }
fsck_blockmap_set(ip, block, _("directory leaf"), gfs2_leaf_blk);
bc->indir_count++;
return 0;
12 years, 8 months
gfs2-utils: master - fsck.gfs2: fsck.gfs2: Move check_num_ptrs from metawalk to pass1
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 18bd4a7ac30b392a71acb12cb1eb9092480c9908
Parent: 07cadb6dbca0618635b25fd9ff9f03118bfe2f90
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Aug 9 09:23:05 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Move check_num_ptrs from metawalk to pass1
This patch moves function check_num_ptrs from metawalk.c to pass1.c
and also its helper function fix_leaf_pointers. This function checks
that the number of pointers in a leaf block is a factor of 2, and sane.
This should only happen once, when leaf blocks are initially checked.
Previously it was wasting a lot of time doing this check from every pass.
rhbz#675723
---
gfs2/fsck/metawalk.c | 129 +++-------------------------------------------
gfs2/fsck/metawalk.h | 3 +
gfs2/fsck/pass1.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 148 insertions(+), 124 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 9abec79..622f9d7 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -463,123 +463,6 @@ static void warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no,
*leaf_no = old_leaf;
}
-/*
- * fix_leaf_pointers - fix a directory dinode that has a number of pointers
- * that is not a multiple of 2.
- * dip - the directory inode having the problem
- * lindex - the index of the leaf right after the problem (need to back up)
- * cur_numleafs - current (incorrect) number of instances of the leaf block
- * correct_numleafs - the correct number instances of the leaf block
- */
-static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
- int cur_numleafs, int correct_numleafs)
-{
- int count;
- char *ptrbuf;
- int start_lindex = *lindex - cur_numleafs; /* start of bad ptrs */
- int tot_num_ptrs = (1 << dip->i_di.di_depth) - start_lindex;
- int bufsize = tot_num_ptrs * sizeof(uint64_t);
- int off_by = cur_numleafs - correct_numleafs;
-
- ptrbuf = malloc(bufsize);
- if (!ptrbuf) {
- log_err( _("Error: Cannot allocate memory to fix the leaf "
- "pointers.\n"));
- return -1;
- }
- /* Read all the pointers, starting with the first bad one */
- count = gfs2_readi(dip, ptrbuf, start_lindex * sizeof(uint64_t),
- bufsize);
- if (count != bufsize) {
- log_err( _("Error: bad read while fixing leaf pointers.\n"));
- free(ptrbuf);
- return -1;
- }
-
- bufsize -= off_by * sizeof(uint64_t); /* We need to write fewer */
- /* Write the same pointers, but offset them so they fit within the
- smaller factor of 2. So if we have 12 pointers, write out only
- the last 8 of them. If we have 7, write the last 4, etc.
- We need to write these starting at the current lindex and adjust
- lindex accordingly. */
- count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
- start_lindex * sizeof(uint64_t), bufsize);
- if (count != bufsize) {
- log_err( _("Error: bad read while fixing leaf pointers.\n"));
- free(ptrbuf);
- return -1;
- }
- /* Now zero out the hole left at the end */
- memset(ptrbuf, 0, off_by * sizeof(uint64_t));
- gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
- bufsize, off_by * sizeof(uint64_t));
- free(ptrbuf);
- *lindex -= off_by; /* adjust leaf index to account for the change */
- return 0;
-}
-
-/* check_num_ptrs - check a previously processed leaf's pointer count */
-static int check_num_ptrs(struct gfs2_inode *ip, uint64_t old_leaf,
- int *ref_count, int *exp_count, int *lindex,
- struct gfs2_leaf *oldleaf)
-{
- int factor = 0, divisor = *ref_count, multiple = 1, error = 0;
- struct gfs2_buffer_head *lbh;
-
- /* Check to see if the number of pointers we found is a power of 2.
- It needs to be and if it's not we need to fix it.*/
- while (divisor > 1) {
- factor++;
- divisor /= 2;
- multiple = multiple << 1;
- }
- if (*ref_count != multiple) {
- log_err( _("Directory #%llu (0x%llx) has an "
- "invalid number of pointers to "
- "leaf #%llu (0x%llx)\n\tFound: %u, "
- "which is not a factor of 2.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)old_leaf,
- (unsigned long long)old_leaf, *ref_count);
- if (!query( _("Attempt to fix it? (y/n) "))) {
- log_err( _("Directory inode was not fixed.\n"));
- return 1;
- }
- error = fix_leaf_pointers(ip, lindex, *ref_count, multiple);
- if (error)
- return error;
- *ref_count = multiple;
- log_err( _("Directory inode was fixed.\n"));
- }
- /* Check to see if the counted number of leaf pointers is what we
- expect. */
- if (*ref_count != *exp_count) {
- log_err( _("Directory #%llu (0x%llx) has an "
- "incorrect number of pointers to "
- "leaf #%llu (0x%llx)\n\tFound: "
- "%u, Expected: %u\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)old_leaf,
- (unsigned long long)old_leaf, *ref_count, *exp_count);
- if (!query( _("Attempt to fix it? (y/n) "))) {
- log_err( _("Directory leaf was not fixed.\n"));
- return 1;
- }
- lbh = bread(ip->i_sbd, old_leaf);
- gfs2_leaf_in(oldleaf, lbh);
- log_err( _("Leaf depth was %d, changed to %d\n"),
- oldleaf->lf_depth, ip->i_di.di_depth - factor);
- oldleaf->lf_depth = ip->i_di.di_depth - factor;
- gfs2_leaf_out(oldleaf, lbh);
- brelse(lbh);
- *exp_count = *ref_count;
- log_err( _("Directory leaf was fixed.\n"));
- }
- return 0;
-}
-
/* Checks exhash directory entries */
static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
{
@@ -638,10 +521,14 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
}
do {
- if (!valid_block(ip->i_sbd, old_leaf) == 0) {
- error = check_num_ptrs(ip, old_leaf,
- &ref_count, &exp_count,
- &lindex, &oldleaf);
+ if (fsck_abort)
+ return 0;
+ if (pass->check_num_ptrs &&
+ valid_block(ip->i_sbd, old_leaf)) {
+ error = pass->check_num_ptrs(ip, old_leaf,
+ &ref_count,
+ &lindex,
+ &oldleaf);
if (error)
return error;
}
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index d705726..7a8ae4c 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -89,6 +89,9 @@ struct metawalk_fxns {
int (*finish_eattr_indir) (struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private);
void (*big_file_msg) (struct gfs2_inode *ip, uint64_t blks_checked);
+ int (*check_num_ptrs) (struct gfs2_inode *ip, uint64_t leafno,
+ int *ref_count, int *lindex,
+ struct gfs2_leaf *leaf);
};
#endif /* _METAWALK_H */
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 2b04227..e39d9d2 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -34,7 +34,7 @@ struct block_count {
uint64_t ea_count;
};
-static int leaf(struct gfs2_inode *ip, uint64_t block, void *private);
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private);
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h, void *private);
static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
@@ -59,6 +59,8 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
+static int check_num_ptrs(struct gfs2_inode *ip, uint64_t leafno,
+ int *ref_count, int *lindex, struct gfs2_leaf *leaf);
static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private);
static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block,
@@ -79,7 +81,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip);
struct metawalk_fxns pass1_fxns = {
.private = NULL,
- .check_leaf = leaf,
+ .check_leaf = check_leaf,
.check_metalist = check_metalist,
.check_data = check_data,
.check_eattr_indir = check_eattr_indir,
@@ -89,6 +91,7 @@ struct metawalk_fxns pass1_fxns = {
.check_eattr_extentry = check_extended_leaf_eattr,
.finish_eattr_indir = finish_eattr_indir,
.big_file_msg = big_file_comfort,
+ .check_num_ptrs = check_num_ptrs,
};
struct metawalk_fxns undo_fxns = {
@@ -199,7 +202,138 @@ struct metawalk_fxns sysdir_fxns = {
.check_dentry = resuscitate_dentry,
};
-static int leaf(struct gfs2_inode *ip, uint64_t block, void *private)
+/*
+ * fix_leaf_pointers - fix a directory dinode that has a number of pointers
+ * that is not a multiple of 2.
+ * dip - the directory inode having the problem
+ * lindex - the index of the leaf right after the problem (need to back up)
+ * cur_numleafs - current (incorrect) number of instances of the leaf block
+ * correct_numleafs - the correct number instances of the leaf block
+ */
+static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
+ int cur_numleafs, int correct_numleafs)
+{
+ int count;
+ char *ptrbuf;
+ int start_lindex = *lindex - cur_numleafs; /* start of bad ptrs */
+ int tot_num_ptrs = (1 << dip->i_di.di_depth) - start_lindex;
+ int bufsize = tot_num_ptrs * sizeof(uint64_t);
+ int off_by = cur_numleafs - correct_numleafs;
+
+ ptrbuf = malloc(bufsize);
+ if (!ptrbuf) {
+ log_err( _("Error: Cannot allocate memory to fix the leaf "
+ "pointers.\n"));
+ return -1;
+ }
+ /* Read all the pointers, starting with the first bad one */
+ count = gfs2_readi(dip, ptrbuf, start_lindex * sizeof(uint64_t),
+ bufsize);
+ if (count != bufsize) {
+ log_err( _("Error: bad read while fixing leaf pointers.\n"));
+ free(ptrbuf);
+ return -1;
+ }
+
+ bufsize -= off_by * sizeof(uint64_t); /* We need to write fewer */
+ /* Write the same pointers, but offset them so they fit within the
+ smaller factor of 2. So if we have 12 pointers, write out only
+ the last 8 of them. If we have 7, write the last 4, etc.
+ We need to write these starting at the current lindex and adjust
+ lindex accordingly. */
+ count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
+ start_lindex * sizeof(uint64_t), bufsize);
+ if (count != bufsize) {
+ log_err( _("Error: bad read while fixing leaf pointers.\n"));
+ free(ptrbuf);
+ return -1;
+ }
+ /* Now zero out the hole left at the end */
+ memset(ptrbuf, 0, off_by * sizeof(uint64_t));
+ gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
+ bufsize, off_by * sizeof(uint64_t));
+ free(ptrbuf);
+ *lindex -= off_by; /* adjust leaf index to account for the change */
+ return 0;
+}
+
+/**
+ * check_num_ptrs - check a previously processed leaf's pointer count in the
+ * hash table.
+ *
+ * The number of pointers in a directory hash table that point to any given
+ * leaf block should always be a factor of two. The difference between the
+ * leaf block's depth and the dinode's di_depth gives us the factor.
+ * This function makes sure the leaf follows the rules properly.
+ *
+ * ip - pointer to the in-core inode structure
+ * leafno - the leaf number we're operating on
+ * ref_count - the number of pointers to this leaf we actually counted.
+ * exp_count - the number of pointers to this leaf we expect based on
+ * ip depth minus leaf depth.
+ * lindex - leaf index number
+ * leaf - the leaf structure for the leaf block to check
+ */
+static int check_num_ptrs(struct gfs2_inode *ip, uint64_t leafno,
+ int *ref_count, int *lindex, struct gfs2_leaf *leaf)
+{
+ int factor = 0, divisor = *ref_count, multiple = 1, error = 0;
+ struct gfs2_buffer_head *lbh;
+ int exp_count;
+
+ /* Check to see if the number of pointers we found is a power of 2.
+ It needs to be and if it's not we need to fix it.*/
+ while (divisor > 1) {
+ factor++;
+ divisor /= 2;
+ multiple = multiple << 1;
+ }
+ if (*ref_count != multiple) {
+ log_err( _("Directory #%llu (0x%llx) has an invalid number of "
+ "pointers to leaf #%llu (0x%llx)\n\tFound: %u, "
+ "which is not a factor of 2.\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)leafno,
+ (unsigned long long)leafno, *ref_count);
+ if (!query( _("Attempt to fix it? (y/n) "))) {
+ log_err( _("Directory inode was not fixed.\n"));
+ return 1;
+ }
+ error = fix_leaf_pointers(ip, lindex, *ref_count, multiple);
+ if (error)
+ return error;
+ *ref_count = multiple;
+ log_err( _("Directory inode was fixed.\n"));
+ }
+ /* Check to see if the counted number of leaf pointers is what we
+ expect based on the leaf depth. */
+ exp_count = (1 << (ip->i_di.di_depth - leaf->lf_depth));
+ if (*ref_count != exp_count) {
+ log_err( _("Directory #%llu (0x%llx) has an incorrect number "
+ "of pointers to leaf #%llu (0x%llx)\n\tFound: "
+ "%u, Expected: %u\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)leafno,
+ (unsigned long long)leafno, *ref_count, exp_count);
+ if (!query( _("Attempt to fix it? (y/n) "))) {
+ log_err( _("Directory leaf was not fixed.\n"));
+ return 1;
+ }
+ lbh = bread(ip->i_sbd, leafno);
+ gfs2_leaf_in(leaf, lbh);
+ log_err( _("Leaf depth was %d, changed to %d\n"),
+ leaf->lf_depth, ip->i_di.di_depth - factor);
+ leaf->lf_depth = ip->i_di.di_depth - factor;
+ gfs2_leaf_out(leaf, lbh);
+ brelse(lbh);
+ log_err( _("Directory leaf was fixed.\n"));
+ }
+ return 0;
+}
+
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
{
struct block_count *bc = (struct block_count *) private;
12 years, 8 months
gfs2-utils: master - fsck.gfs2: fsck.gfs2: Find and clear duplicate leaf blocks refs
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 07cadb6dbca0618635b25fd9ff9f03118bfe2f90
Parent: f4ddd034d629e628a2cde4aba86d0c7c20e9800a
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 16:44:47 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Find and clear duplicate leaf blocks refs
Duplicate references that were in leaf blocks were never found nor
cleared. This patch adds that capability.
rhbz#675723
---
gfs2/fsck/pass1b.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 9497c78..7c6ae3d 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -28,6 +28,7 @@ struct dup_handler {
int ref_count;
};
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private);
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h, void *private);
static int check_data(struct gfs2_inode *ip, uint64_t block, void *private);
@@ -53,7 +54,7 @@ static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
struct metawalk_fxns find_refs = {
.private = NULL,
- .check_leaf = NULL,
+ .check_leaf = check_leaf,
.check_metalist = check_metalist,
.check_data = check_data,
.check_eattr_indir = check_eattr_indir,
@@ -75,6 +76,11 @@ struct metawalk_fxns find_dirents = {
.check_eattr_extentry = NULL,
};
+static int check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
+{
+ return add_duplicate_ref(ip, block, ref_as_meta, 1, INODE_VALID);
+}
+
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h, void *private)
{
@@ -253,6 +259,11 @@ static int clear_dup_data(struct gfs2_inode *ip, uint64_t block, void *private)
return clear_dup_metalist(ip, block, NULL, 0, private);
}
+static int clear_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
+{
+ return clear_dup_metalist(ip, block, NULL, 0, private);
+}
+
static int clear_dup_eattr_indir(struct gfs2_inode *ip, uint64_t block,
uint64_t parent, struct gfs2_buffer_head **bh,
void *private)
@@ -395,7 +406,7 @@ static int clear_a_reference(struct gfs2_sbd *sdp, struct duptree *b,
osi_list_t *tmp, *x;
struct metawalk_fxns clear_dup_fxns = {
.private = NULL,
- .check_leaf = NULL,
+ .check_leaf = clear_leaf,
.check_metalist = clear_dup_metalist,
.check_data = clear_dup_data,
.check_eattr_indir = clear_dup_eattr_indir,
12 years, 8 months
gfs2-utils: master - fsck.gfs2: fsck.gfs2: Don't stop invalidating blocks on invalid
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: f4ddd034d629e628a2cde4aba86d0c7c20e9800a
Parent: 2a55d5be6be747d8f0e73b9fa3dc13f6328977db
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 16:20:14 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Don't stop invalidating blocks on invalid
When fsck found a duplicate reference to a block it invalidated the dinode's
metadata. But if it encountered an invalid block, for example, out of range,
the invalidating would stop. If we encounter a block that isn't valid, we
obviously can't invalidate it. However, if we return an error, all future
invalidating will stop for that dinode. That's wrong because we need it to
continue to invalidate the other valid blocks. If we don't do this, block
references that follow the bad one that are also referenced elsewhere
(duplicates) won't be flagged as such. As a result, they'll be freed when
this corrupt dinode is deleted, despite being used by another dinode as a
valid block. This patch makes it return a good return code so the invalidating
continues.
rhbz#675723
---
gfs2/fsck/pass1.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index b9aa165..2b04227 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -827,8 +827,15 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block,
{
uint8_t q;
- if (!valid_block(ip->i_sbd, block) != 0)
- return -EFAULT;
+ /* If the block isn't valid, we obviously can't invalidate it.
+ * However, if we return an error, invalidating will stop, and
+ * we want it to continue to invalidate the valid blocks. If we
+ * don't do this, block references that follow that are also
+ * referenced elsewhere (duplicates) won't be flagged as such,
+ * and as a result, they'll be freed when this dinode is deleted,
+ * despite being used by another dinode as a valid block. */
+ if (!valid_block(ip->i_sbd, block))
+ return 0;
q = block_type(block);
if (q != gfs2_block_free) {
12 years, 8 months
gfs2-utils: master - libgfs2: libgfs2: Use __FUNCTION__ rather than __FILE__
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 2a55d5be6be747d8f0e73b9fa3dc13f6328977db
Parent: fc1166c02e0361b500e2ecc8a71c0da2a16bc27d
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 16:11:48 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
libgfs2: libgfs2: Use __FUNCTION__ rather than __FILE__
This patch changes the debug output of gfs2-utils to use __FUNCTION__
rather than __FILE__. The output file is much smaller. Digging through
a 6.5GB output is better and faster than a 9GB output file.
rhbz#675723
---
gfs2/fsck/metawalk.c | 13 +++----------
gfs2/fsck/metawalk.h | 2 +-
gfs2/libgfs2/libgfs2.h | 2 +-
3 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 6bdea5a..9abec79 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -100,17 +100,10 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
int error;
if (print_level >= MSG_DEBUG) {
- const char *p;
-
- p = strrchr(caller, '/');
- if (p)
- p++;
- else
- p = caller;
/* I'm circumventing the log levels here on purpose to make the
output easier to debug. */
if (ip->i_di.di_num.no_addr == bblock) {
- print_fsck_log(MSG_DEBUG, p, fline,
+ print_fsck_log(MSG_DEBUG, caller, fline,
_("%s inode found at block %lld "
"(0x%llx): marking as '%s'\n"),
btype, (unsigned long long)
@@ -119,7 +112,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
ip->i_di.di_num.no_addr,
block_type_string(mark));
} else if (mark == gfs2_bad_block || mark == gfs2_meta_inval) {
- print_fsck_log(MSG_DEBUG, p, fline,
+ print_fsck_log(MSG_DEBUG, caller, fline,
_("inode %lld (0x%llx) references "
"%s block %lld (0x%llx): "
"marking as '%s'\n"),
@@ -131,7 +124,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
(unsigned long long)bblock,
block_type_string(mark));
} else {
- print_fsck_log(MSG_DEBUG, p, fline,
+ print_fsck_log(MSG_DEBUG, caller, fline,
_("inode %lld (0x%llx) references "
"%s block %lld (0x%llx): "
"marking as '%s'\n"),
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index c15d7b7..d705726 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -39,7 +39,7 @@ extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp,
#define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0)
#define fsck_blockmap_set(ip, b, bt, m) _fsck_blockmap_set(ip, b, bt, m, \
- __FILE__, __LINE__)
+ __FUNCTION__, __LINE__)
/* metawalk_fxns: function pointers to check various parts of the fs
*
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 140a7a0..f8f55b1 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -697,7 +697,7 @@ extern int print_level;
#define MSG_NULL 1
#define print_log(priority, format...) \
- do { print_fsck_log(priority, __FILE__, __LINE__, ## format); } while(0)
+ do { print_fsck_log(priority, __FUNCTION__, __LINE__, ## format); } while(0)
#define log_debug(format...) \
do { if(print_level >= MSG_DEBUG) print_log(MSG_DEBUG, format); } while(0)
12 years, 8 months
gfs2-utils: master - fsck.gfs2: fsck.gfs2: Refactor add_dotdot function in lost+found
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: fc1166c02e0361b500e2ecc8a71c0da2a16bc27d
Parent: 72da15f9d14524957bd731722cd59201d502b24a
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 15:44:19 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Refactor add_dotdot function in lost+found
This function factors out a section of code from function add_inode_to_lf.
This makes it easier to read and gives it the ability to print better
messages regarding where the block was previously linked.
rhbz#675723
---
gfs2/fsck/lost_n_found.c | 125 ++++++++++++++++++++++++++--------------------
1 files changed, 70 insertions(+), 55 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index b6f02b9..7ce5db5 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -17,6 +17,75 @@
#include "metawalk.h"
#include "util.h"
+static void add_dotdot(struct gfs2_inode *ip)
+{
+ struct dir_info *di;
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ int err;
+
+ log_info( _("Adding .. entry to directory %llu (0x%llx) pointing back "
+ "to lost+found\n"),
+ (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 && !valid_block(sdp, 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);
+ decr_link_count(di->dotdot_parent, ip->i_di.di_num.no_addr,
+ _(".. unlinked, moving to lost+found"));
+ dip = fsck_load_inode(sdp, di->dotdot_parent);
+ if (dip->i_di.di_nlink > 0) {
+ dip->i_di.di_nlink--;
+ set_di_nlink(dip); /* keep inode tree in sync */
+ log_debug(_("Decrementing its links to %d\n"),
+ dip->i_di.di_nlink);
+ bmodified(dip->i_bh);
+ } else if (!dip->i_di.di_nlink) {
+ log_debug(_("Its link count is zero.\n"));
+ } else {
+ log_debug(_("Its link count is %d! Changing "
+ "it to 0.\n"), dip->i_di.di_nlink);
+ dip->i_di.di_nlink = 0;
+ set_di_nlink(dip); /* keep inode tree in sync */
+ bmodified(dip->i_bh);
+ }
+ fsck_inode_put(&dip);
+ di = NULL;
+ } else {
+ if (di)
+ log_debug(_("Couldn't find a valid \"..\" entry "
+ "for orphan directory %lld (0x%llx): "
+ "'..' = 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);
+ 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"));
+
+ err = dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR);
+ if (err) {
+ log_crit(_("Error adding .. directory: %s\n"),
+ strerror(errno));
+ exit(-1);
+ }
+}
+
/* add_inode_to_lf - Add dir entry to lost+found for the inode
* @ip: inode to add to lost + found
*
@@ -95,61 +164,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
switch(ip->i_di.di_mode & S_IFMT){
case S_IFDIR:
- log_info( _("Adding .. entry pointing to lost+found for "
- "directory %llu (0x%llx)\n"),
- (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 && !valid_block(sdp, 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);
- decr_link_count(di->dotdot_parent,
- ip->i_di.di_num.no_addr,
- _(".. unlinked, moving to lost+found"));
- dip = fsck_load_inode(sdp, di->dotdot_parent);
- if (dip->i_di.di_nlink > 0) {
- dip->i_di.di_nlink--;
- set_di_nlink(dip); /* keep inode tree in sync */
- log_debug(_("Decrementing its links to %d\n"),
- dip->i_di.di_nlink);
- bmodified(dip->i_bh);
- } else if (!dip->i_di.di_nlink) {
- log_debug(_("Its link count is zero.\n"));
- } else {
- log_debug(_("Its link count is %d! "
- "Changing it to 0.\n"),
- dip->i_di.di_nlink);
- dip->i_di.di_nlink = 0;
- set_di_nlink(dip); /* keep inode tree in sync */
- 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"));
-
- err = dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR);
- if (err) {
- log_crit(_("Error adding .. directory: %s\n"),
- strerror(errno));
- exit(-1);
- }
-
+ add_dotdot(ip);
sprintf(tmp_name, "lost_dir_%llu",
(unsigned long long)ip->i_di.di_num.no_addr);
inode_type = DT_DIR;
12 years, 8 months
gfs2-utils: master - fsck.gfs2: fsck.gfs2: Ask to reclaim unlinked meta per-rgrp only
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 72da15f9d14524957bd731722cd59201d502b24a
Parent: 1e178e7efd900508bd82e72f584b5acf83691b66
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 15:16:01 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Ask to reclaim unlinked meta per-rgrp only
Before this patch, fsck.gfs2 would ask for every unlinked metadata bit
whether you wanted to reclaim it as free space. This patch makes it
ask only once per resource group, and reports which resource group
so that the user doesn't think it's stuck in an infinite loop.
rhbz#675723
---
gfs2/fsck/initialize.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 18d13cc..c0e83a7 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -195,7 +195,7 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
int *this_rg_bad)
{
uint32_t rg_free, rg_reclaimed;
- int rgb, x, y, off, bytes_to_check, total_bytes_to_check;
+ int rgb, x, y, off, bytes_to_check, total_bytes_to_check, asked = 0;
unsigned int state;
rg_free = rg_reclaimed = 0;
@@ -234,9 +234,17 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
}
/* GFS2_BLKST_UNLINKED */
*this_rg_bad = 1;
- if (!(*fixit)) {
- if (query(_("Okay to reclaim unlinked "
- "inodes? (y/n)")))
+ if (!asked) {
+ char msg[256];
+
+ asked = 1;
+ sprintf(msg,
+ _("Okay to reclaim unlinked "
+ "inodes in resource group "
+ "%lld (0x%llx)? (y/n)"),
+ (unsigned long long)rgd->ri.ri_addr,
+ (unsigned long long)rgd->ri.ri_addr);
+ if (query("%s", msg))
*fixit = 1;
}
if (!(*fixit))
12 years, 8 months
gfs2-utils: master - dirent_repair needs to mark the buffer as modified
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 1e178e7efd900508bd82e72f584b5acf83691b66
Parent: 3997b83236a388c22d37be67c0b015bbf3d3a5c5
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 14:47:49 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
dirent_repair needs to mark the buffer as modified
This patch adds a call to bmodified to function dirent_repair. Without
setting the modified bit, directory repairs may be forgotten and never
written back to disk, leaving the damage in place.
rhbz#675723
---
gfs2/fsck/metawalk.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index a4d7d3e..6bdea5a 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -266,6 +266,7 @@ static int dirent_repair(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
de->de_rec_len = GFS2_DIRENT_SIZE(de->de_name_len);
}
gfs2_dirent_out(de, (char *)dent);
+ bmodified(bh);
return 0;
}
12 years, 8 months
gfs2-utils: master - fsck.gfs2: get rid of triple negative logic
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 3997b83236a388c22d37be67c0b015bbf3d3a5c5
Parent: 536823ad0bc31840a79a02bdd8482cba248b5a51
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 14:44:46 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: get rid of triple negative logic
This patch changes the logic of the code from being triple-negative
to single-negative so it won't twist your brain into knots.
rhbz#675723
---
gfs2/fsck/metawalk.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index f2cd938..a4d7d3e 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -930,7 +930,7 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
uint8_t q;
struct duptree *d;
- if (!valid_block(ip->i_sbd, block) != 0)
+ if (!valid_block(ip->i_sbd, block))
return -EFAULT;
q = block_type(block);
12 years, 8 months
gfs2-utils: master - fsck.gfs2: fsck.gfs2: Make dir entry count 32 bits
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 536823ad0bc31840a79a02bdd8482cba248b5a51
Parent: 6bee78a1e1e0e759339da5a01d42b1c8c4260d73
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Aug 8 14:38:19 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon Aug 29 12:53:02 2011 -0500
fsck.gfs2: fsck.gfs2: Make dir entry count 32 bits
When counting directory links, fsck.gfs2 was using a 16-bit integer.
Therefore, if a directory had more than 65535 links, it would wrap to
zero and the counts would be damaged by fsck.gfs2. Subsequent runs would
not find the corruption, but it was there nonetheless. You would
encounter it if you tried to delete enough entries to cause the count
to become negative.
rhbz#675723
---
gfs2/fsck/fsck.h | 6 +++---
gfs2/fsck/metawalk.c | 8 ++++----
gfs2/fsck/metawalk.h | 2 +-
gfs2/fsck/pass1.c | 2 +-
gfs2/fsck/pass1b.c | 4 ++--
gfs2/fsck/pass2.c | 2 +-
6 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 6353dfc..0fed06b 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -29,9 +29,9 @@ struct inode_info
{
struct osi_node node;
uint64_t inode;
- uint16_t di_nlink; /* the number of links the inode
- * thinks it has */
- uint16_t counted_links; /* the number of links we've found */
+ uint32_t di_nlink; /* the number of links the inode
+ * thinks it has */
+ uint32_t counted_links; /* the number of links we've found */
};
struct dir_info
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index ea1774a..f2cd938 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -300,7 +300,7 @@ static void dirblk_truncate(struct gfs2_inode *ip, struct gfs2_dirent *fixb,
* -1 - error occurred
*/
static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
- int type, uint16_t *count, struct metawalk_fxns *pass)
+ int type, uint32_t *count, struct metawalk_fxns *pass)
{
struct gfs2_dirent *dent;
struct gfs2_dirent de, *prev;
@@ -596,7 +596,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;
- uint16_t count;
+ uint32_t count;
int ref_count = 0, exp_count = 0;
/* Find the first valid leaf pointer in range and use it as our "old"
@@ -1373,7 +1373,7 @@ int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
struct metawalk_fxns *pass)
{
int error = 0;
- uint16_t count = 0;
+ uint32_t count = 0;
error = check_entries(ip, bh, DIR_LINEAR, &count, pass);
if (error < 0) {
@@ -1406,7 +1406,7 @@ int check_dir(struct gfs2_sbd *sdp, uint64_t block, struct metawalk_fxns *pass)
static int remove_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct gfs2_dirent *prev_de,
struct gfs2_buffer_head *bh,
- char *filename, uint16_t *count, void *private)
+ char *filename, uint32_t *count, void *private)
{
/* the metawalk_fxn's private field must be set to the dentry
* block we want to clear */
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index ea023b6..c15d7b7 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -74,7 +74,7 @@ struct metawalk_fxns {
int (*check_dentry) (struct gfs2_inode *ip, struct gfs2_dirent *de,
struct gfs2_dirent *prev,
struct gfs2_buffer_head *bh,
- char *filename, uint16_t *count, void *private);
+ char *filename, uint32_t *count, void *private);
int (*check_eattr_entry) (struct gfs2_inode *ip,
struct gfs2_buffer_head *leaf_bh,
struct gfs2_ea_header *ea_hdr,
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 1bd8464..b9aa165 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -147,7 +147,7 @@ static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t block,
static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct gfs2_dirent *prev_de,
struct gfs2_buffer_head *bh, char *filename,
- uint16_t *count, void *priv)
+ uint32_t *count, void *priv)
{
struct gfs2_sbd *sdp = ip->i_sbd;
struct gfs2_dirent dentry, *de;
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index bbf33d2..9497c78 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -49,7 +49,7 @@ static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
void *private);
static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
struct gfs2_dirent *prev, struct gfs2_buffer_head *bh,
- char *filename, uint16_t *count, void *priv);
+ char *filename, uint32_t *count, void *priv);
struct metawalk_fxns find_refs = {
.private = NULL,
@@ -168,7 +168,7 @@ static int check_dir_dup_ref(struct gfs2_inode *ip, struct gfs2_dirent *de,
static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
struct gfs2_dirent *prev,
struct gfs2_buffer_head *bh, char *filename,
- uint16_t *count, void *priv)
+ uint32_t *count, void *priv)
{
struct osi_node *n, *next = NULL;
osi_list_t *tmp2;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 614c963..1143a15 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -175,7 +175,7 @@ struct metawalk_fxns pass2_fxns_delete = {
static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct gfs2_dirent *prev_de,
struct gfs2_buffer_head *bh, char *filename,
- uint16_t *count, void *priv)
+ uint32_t *count, void *priv)
{
struct gfs2_sbd *sdp = ip->i_sbd;
uint8_t q;
12 years, 8 months