cluster: RHEL510 - libgfs2: Fix null pointer dereference in linked_leaf_search
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=c77cd8fe7f7...
Commit: c77cd8fe7f7cd7b96106fde4ea6a411208f3a6e5
Parent: b2d1e993d3688ccae39a1680615c425953662861
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jan 12 15:31:18 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
libgfs2: Fix null pointer dereference in linked_leaf_search
Fix a null pointer dereference by checking the value of the bh set by
get_first_leaf(). Looking down the call tree the bh is set to NULL when
__bread fails to allocate memory so we can use errno as the return value
here.
rhbz#877150
---
gfs2/fsck/lost_n_found.c | 3 +--
gfs2/libgfs2/fs_ops.c | 2 ++
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index c0de5d5..b2ad2d3 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -124,8 +124,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
lf_dip = createi(sdp->md.rooti, "lost+found",
S_IFDIR | 0700, 0);
if (lf_dip == NULL) {
- log_crit(_("Error %d creating lost+found: %s\n"),
- errno);
+ log_crit(_("Error %d creating lost+found\n"), errno);
exit(FSCK_ERROR);
}
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 4e23b4a..1c20e61 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -1433,6 +1433,8 @@ static int linked_leaf_search(struct gfs2_inode *dip, const char *filename,
error = get_first_leaf(dip, lindex, &bh_next);
if (error)
return error;
+ if (bh_next == NULL)
+ return errno;
/* Find the entry */
do{
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Add return code checks and initializations
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=b2d1e993d36...
Commit: b2d1e993d3688ccae39a1680615c425953662861
Parent: f6e426b5aa22692e414192d5aa70e4ef15db1c18
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jan 12 15:29:17 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Add return code checks and initializations
This patch fixes several problems detected by the coverity
tool whereby variables could be accessed without being
initialized, and where return codes should be checked and
were not.
rhbz#877150
---
gfs2/fsck/fs_recovery.c | 9 ++++
gfs2/fsck/initialize.c | 99 ++++++++++++++++++++++++++++++++++++++-------
gfs2/fsck/lost_n_found.c | 16 ++++++-
gfs2/fsck/pass1.c | 17 ++++++--
gfs2/fsck/pass2.c | 19 +++++++--
gfs2/fsck/pass3.c | 10 ++++-
gfs2/fsck/pass5.c | 17 ++++++--
gfs2/libgfs2/fs_ops.c | 45 +++++++++++++-------
gfs2/libgfs2/libgfs2.h | 2 +-
9 files changed, 184 insertions(+), 50 deletions(-)
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 61c3b9d..214aa18 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -139,6 +139,10 @@ static int buf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
(unsigned long long)blkno, (unsigned long long)blkno,
start);
bh_ip = bget(sdp, blkno);
+ if (!bh_ip) {
+ log_err(_("Out of memory when replaying journals.\n"));
+ return FSCK_ERROR;
+ }
memcpy(bh_ip->b_data, bh_log->b_data, sdp->bsize);
check_magic = ((struct gfs2_meta_header *)
@@ -245,6 +249,10 @@ static int databuf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
(unsigned long long)blkno, (unsigned long long)blkno,
start);
bh_ip = bget(sdp, blkno);
+ if (!bh_ip) {
+ log_err(_("Out of memory when replaying journals.\n"));
+ return FSCK_ERROR;
+ }
memcpy(bh_ip->b_data, bh_log->b_data, sdp->bsize);
/* Unescape */
@@ -369,6 +377,7 @@ static int fix_journal_seq_no(struct gfs2_inode *ip)
uint32_t extlen;
struct gfs2_buffer_head *bh;
+ memset(&lh, 0, sizeof(lh));
for (blk = 0; blk < jd_blocks; blk++) {
error = get_log_header(ip, blk, &lh);
if (error == 1) /* if not a log header */
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index df955eb..75f81f5 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -340,6 +340,7 @@ static int rebuild_master(struct gfs2_sbd *sdp)
{
struct gfs2_inum inum;
struct gfs2_buffer_head *bh;
+ int err = 0;
log_err(_("The system master directory seems to be destroyed.\n"));
if (!query(_("Okay to rebuild it? (y/n)"))) {
@@ -356,59 +357,109 @@ static int rebuild_master(struct gfs2_sbd *sdp)
if (fix_md.jiinode) {
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = fix_md.jiinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "jindex", 6, &inum,
- IF2DT(S_IFDIR | 0700));
+ err = dir_add(sdp->master_dir, "jindex", 6, &inum,
+ IF2DT(S_IFDIR | 0700));
+ if (err) {
+ log_crit(_("Error %d adding jindex directory\n"), errno);
+ exit(FSCK_ERROR);
+ }
sdp->master_dir->i_di.di_nlink++;
} else {
- build_jindex(sdp);
+ err = build_jindex(sdp);
+ if (err) {
+ log_crit(_("Error %d building jindex\n"), err);
+ exit(FSCK_ERROR);
+ }
}
if (fix_md.pinode) {
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = fix_md.pinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "per_node", 8, &inum,
+ err = dir_add(sdp->master_dir, "per_node", 8, &inum,
IF2DT(S_IFDIR | 0700));
+ if (err) {
+ log_crit(_("Error %d adding per_node directory\n"),
+ errno);
+ exit(FSCK_ERROR);
+ }
sdp->master_dir->i_di.di_nlink++;
} else {
- build_per_node(sdp);
+ err = build_per_node(sdp);
+ if (err) {
+ log_crit(_("Error %d building per_node directory\n"),
+ err);
+ exit(FSCK_ERROR);
+ }
}
if (fix_md.inum) {
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = fix_md.inum->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "inum", 4, &inum,
+ err = dir_add(sdp->master_dir, "inum", 4, &inum,
IF2DT(S_IFREG | 0600));
+ if (err) {
+ log_crit(_("Error %d adding inum inode\n"), errno);
+ exit(FSCK_ERROR);
+ }
} else {
- build_inum(sdp);
+ err = build_inum(sdp);
+ if (err) {
+ log_crit(_("Error %d building inum inode\n"), err);
+ exit(FSCK_ERROR);
+ }
gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
}
if (fix_md.statfs) {
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = fix_md.statfs->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "statfs", 6, &inum,
- IF2DT(S_IFREG | 0600));
+ err = dir_add(sdp->master_dir, "statfs", 6, &inum,
+ IF2DT(S_IFREG | 0600));
+ if (err) {
+ log_crit(_("Error %d adding statfs inode\n"), errno);
+ exit(FSCK_ERROR);
+ }
} else {
- build_statfs(sdp);
+ err = build_statfs(sdp);
+ if (err) {
+ log_crit(_("Error %d building statfs inode\n"), err);
+ exit(FSCK_ERROR);
+ }
gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
}
if (fix_md.riinode) {
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = fix_md.riinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "rindex", 6, &inum,
+ err = dir_add(sdp->master_dir, "rindex", 6, &inum,
IF2DT(S_IFREG | 0600));
+ if (err) {
+ log_crit(_("Error %d adding rindex inode\n"), errno);
+ exit(FSCK_ERROR);
+ }
} else {
- build_rindex(sdp);
+ err = build_rindex(sdp);
+ if (err) {
+ log_crit(_("Error %d building rindex inode\n"), err);
+ exit(FSCK_ERROR);
+ }
}
if (fix_md.qinode) {
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = fix_md.qinode->i_di.di_num.no_addr;
- dir_add(sdp->master_dir, "quota", 5, &inum,
+ err = dir_add(sdp->master_dir, "quota", 5, &inum,
IF2DT(S_IFREG | 0600));
+ if (err) {
+ log_crit(_("Error %d adding quota inode\n"), errno);
+ exit(FSCK_ERROR);
+ }
} else {
- build_quota(sdp);
+ err = build_quota(sdp);
+ if (err) {
+ log_crit(_("Error %d building quota inode\n"), err);
+ exit(FSCK_ERROR);
+ }
}
log_err(_("Master directory rebuilt.\n"));
@@ -590,6 +641,16 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
goto fail;
}
}
+ /* Read inum entry into buffer */
+ err = gfs2_readi(sdp->md.inum, &inumbuf, 0,
+ sdp->md.inum->i_di.di_size);
+ if (err != sdp->md.inum->i_di.di_size) {
+ log_crit(_("Error %d reading system inum inode. "
+ "Aborting.\n"), err);
+ goto fail;
+ }
+ /* call gfs2_inum_range_in() to retrieve range */
+ sdp->md.next_inum = be64_to_cpu(inumbuf);
}
/* Read inum entry into buffer */
gfs2_readi(sdp->md.inum, &inumbuf, 0,
@@ -622,8 +683,14 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
if (sdp->md.statfs->i_di.di_size) {
buf = malloc(sdp->md.statfs->i_di.di_size);
if (buf) {
- gfs2_readi(sdp->md.statfs, buf, 0,
- sdp->md.statfs->i_di.di_size);
+ err = gfs2_readi(sdp->md.statfs, buf, 0,
+ sdp->md.statfs->i_di.di_size);
+ if (err != sdp->md.statfs->i_di.di_size) {
+ log_crit(_("Error %d reading statfs file. "
+ "Aborting.\n"), err);
+ free(buf);
+ goto fail;
+ }
/* call gfs2_inum_range_in() to retrieve range */
gfs2_statfs_change_in(&sc, buf);
free(buf);
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index afdeefc..c0de5d5 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -33,6 +33,7 @@ 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"),
@@ -89,7 +90,12 @@ static void add_dotdot(struct gfs2_inode *ip)
log_warn( _("add_inode_to_lf: Unable to remove "
"\"..\" directory entry.\n"));
- dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR);
+ 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(FSCK_ERROR);
+ }
}
/* add_inode_to_lf - Add dir entry to lost+found for the inode
@@ -107,6 +113,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
uint64_t lf_blocks;
struct gfs2_sbd *sdp = ip->i_sbd;
struct dir_info *di;
+ int err = 0;
uint32_t mode;
if (!lf_dip) {
@@ -207,8 +214,13 @@ int add_inode_to_lf(struct gfs2_inode *ip){
break;
}
- dir_add(lf_dip, tmp_name, strlen(tmp_name), &(ip->i_di.di_num),
+ err = dir_add(lf_dip, tmp_name, strlen(tmp_name), &(ip->i_di.di_num),
inode_type);
+ if (err) {
+ log_crit(_("Error adding directory %s: %s\n"),
+ tmp_name, strerror(errno));
+ exit(FSCK_ERROR);
+ }
/* If the lf directory had new blocks added we have to mark them
properly in the bitmap so they're not freed. */
if (lf_dip->i_di.di_blocks != lf_blocks)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index c241960..8bda4b8 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1315,7 +1315,7 @@ static int check_system_inode(struct gfs2_sbd *sdp,
{
uint64_t iblock = 0;
struct dir_status ds = {0};
- int error;
+ int error, err = 0;
log_info( _("Checking system inode '%s'\n"), filename);
if (*sysinode) {
@@ -1387,12 +1387,19 @@ static int check_system_inode(struct gfs2_sbd *sdp,
sysdir_fxns.private = &bc;
if ((*sysinode)->i_di.di_flags & GFS2_DIF_EXHASH)
check_metatree(*sysinode, &sysdir_fxns);
- else
- check_linear_dir(*sysinode, (*sysinode)->i_bh,
- &sysdir_fxns);
+ else {
+ err = check_linear_dir(*sysinode, (*sysinode)->i_bh,
+ &sysdir_fxns);
+ /* If we encountered an error in our directory check
+ we should still call handle_ip, but return the
+ error later. */
+ if (err)
+ log_err(_("Error found in %s while checking "
+ "directory entries.\n"), filename);
+ }
}
error = handle_ip(sdp, *sysinode);
- return error;
+ return error ? error : err;
}
static int build_a_journal(struct gfs2_sbd *sdp)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 33eb2d4..e89640b 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -18,6 +18,7 @@
#include <inttypes.h>
#include <sys/stat.h>
#include <libintl.h>
+#include <errno.h>
#define _(String) gettext(String)
#include "libgfs2.h"
@@ -679,8 +680,13 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
}
memcpy(filename, tmp_name, filename_len);
log_warn( _("Adding '.' entry\n"));
- dir_add(sysinode, filename, filename_len,
- &(sysinode->i_di.di_num), DT_DIR);
+ error = dir_add(sysinode, filename, filename_len,
+ &(sysinode->i_di.di_num), DT_DIR);
+ if (error) {
+ log_err(_("Error adding directory %s: %s\n"),
+ filename, strerror(errno));
+ return -errno;
+ }
if (cur_blks != sysinode->i_di.di_blocks)
reprocess_inode(sysinode, dirname);
/* This system inode is linked to itself via '.' */
@@ -883,8 +889,13 @@ int pass2(struct gfs2_sbd *sdp)
memcpy(filename, tmp_name, filename_len);
cur_blks = ip->i_di.di_blocks;
- dir_add(ip, filename, filename_len,
- &(ip->i_di.di_num), DT_DIR);
+ error = dir_add(ip, filename, filename_len,
+ &(ip->i_di.di_num), DT_DIR);
+ if (error) {
+ log_err(_("Error adding directory %s: %s\n"),
+ filename, strerror(errno));
+ return -errno;
+ }
if (cur_blks != ip->i_di.di_blocks) {
char dirname[80];
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index db59191..ebf4800 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -17,6 +17,7 @@
#include <string.h>
#include <dirent.h>
#include <libintl.h>
+#include <errno.h>
#define _(String) gettext(String)
#include "libgfs2.h"
@@ -31,7 +32,7 @@ static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
uint64_t olddotdot, uint64_t block)
{
char *filename;
- int filename_len;
+ int filename_len, err;
struct gfs2_inode *ip, *pip;
uint64_t cur_blks;
@@ -65,7 +66,12 @@ static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
else
decr_link_count(olddotdot, block, _("old \"..\""));
cur_blks = ip->i_di.di_blocks;
- dir_add(ip, filename, filename_len, &pip->i_di.di_num, DT_DIR);
+ err = dir_add(ip, filename, filename_len, &pip->i_di.di_num, DT_DIR);
+ if (err) {
+ log_err(_("Error adding directory %s: %s\n"),
+ filename, strerror(errno));
+ exit(FSCK_ERROR);
+ }
if (cur_blks != ip->i_di.di_blocks) {
char dirname[80];
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index fc2eb80..f2d23cd 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -65,7 +65,8 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
{
unsigned char *byte, *end;
unsigned int bit;
- unsigned char rg_status, block_status;
+ unsigned char rg_status;
+ int block_status;
uint8_t q;
uint64_t block;
@@ -80,10 +81,17 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
warm_fuzzy_stuff(block);
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return 0;
+
q = block_type(block);
block_status = convert_mark(q, count);
+ if (block_status < 0) {
+ log_err( _("Invalid status for block %llu (0x%llx).\n"),
+ (unsigned long long)block,
+ (unsigned long long)block);
+ return block_status;
+ }
/* If one node opens a file and another node deletes it, we
may be left with a block that appears to be "unlinked" in
the bitmap, but nothing links to it. This is a valid case
@@ -161,9 +169,10 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
bits = &rgp->bits[i];
/* 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);
+ if (check_block_status(sdp, rgp->bh[i]->b_data +
+ bits->bi_offset, bits->bi_len,
+ &rg_block, rgp->ri.ri_data0, count))
+ return;
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return;
}
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 0691956..4e23b4a 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -711,6 +711,11 @@ int gfs2_dirent_next(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
return 0;
}
+/**
+ * Allocate a gfs2 dirent
+ * Returns 0 on success, with *dent_out pointing to the new dirent,
+ * or -1 on failure, with errno set
+ */
static int dirent_alloc(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
int name_len, struct gfs2_dirent **dent_out)
{
@@ -778,7 +783,8 @@ static int dirent_alloc(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
}
} while (gfs2_dirent_next(dip, bh, &dent) == 0);
- return -ENOSPC;
+ errno = ENOSPC;
+ return -1;
}
void dirent2_del(struct gfs2_inode *dip, struct gfs2_buffer_head *bh,
@@ -997,8 +1003,6 @@ int gfs2_get_leaf(struct gfs2_inode *dip, uint64_t leaf_no,
int error = 0;
*bhp = bread(dip->i_sbd, leaf_no);
- if (error)
- return error;
error = gfs2_check_meta(*bhp, GFS2_METATYPE_LF);
if(error)
brelse(*bhp);
@@ -1046,7 +1050,7 @@ static int get_next_leaf(struct gfs2_inode *dip,struct gfs2_buffer_head *bh_in,
return 0;
}
-static void dir_e_add(struct gfs2_inode *dip, const char *filename, int len,
+static int dir_e_add(struct gfs2_inode *dip, const char *filename, int len,
struct gfs2_inum *inum, unsigned int type)
{
struct gfs2_buffer_head *bh, *nbh;
@@ -1055,6 +1059,7 @@ static void dir_e_add(struct gfs2_inode *dip, const char *filename, int len,
uint32_t lindex;
uint32_t hash;
uint64_t leaf_no, bn;
+ int err = 0;
hash = gfs2_disk_hash(filename, len);
restart:
@@ -1103,8 +1108,9 @@ restart:
nleaf->lf_depth = leaf->lf_depth;
nleaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
- if (dirent_alloc(dip, nbh, len, &dent))
- die("dir_split_leaf (3)\n");
+ err = dirent_alloc(dip, nbh, len, &dent);
+ if (err)
+ return err;
dip->i_di.di_blocks++;
bmodified(dip->i_bh);
bmodified(bh);
@@ -1124,7 +1130,7 @@ restart:
bmodified(bh);
brelse(bh);
- return;
+ return err;
}
}
@@ -1191,15 +1197,16 @@ static void dir_make_exhash(struct gfs2_inode *dip)
bwrite(dip->i_bh);
}
-static void dir_l_add(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inum *inum, unsigned int type)
+static int dir_l_add(struct gfs2_inode *dip, const char *filename, int len,
+ struct gfs2_inum *inum, unsigned int type)
{
struct gfs2_dirent *dent;
+ int err = 0;
if (dirent_alloc(dip, dip->i_bh, len, &dent)) {
dir_make_exhash(dip);
- dir_e_add(dip, filename, len, inum, type);
- return;
+ err = dir_e_add(dip, filename, len, inum, type);
+ return err;
}
gfs2_inum_out(inum, (char *)&dent->de_inum);
@@ -1208,15 +1215,18 @@ static void dir_l_add(struct gfs2_inode *dip, const char *filename, int len,
dent->de_type = cpu_to_be16(type);
memcpy((char *)(dent + 1), filename, len);
bmodified(dip->i_bh);
+ return err;
}
-void dir_add(struct gfs2_inode *dip, const char *filename, int len,
- struct gfs2_inum *inum, unsigned int type)
+int dir_add(struct gfs2_inode *dip, const char *filename, int len,
+ struct gfs2_inum *inum, unsigned int type)
{
+ int err = 0;
if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
- dir_e_add(dip, filename, len, inum, type);
+ err = dir_e_add(dip, filename, len, inum, type);
else
- dir_l_add(dip, filename, len, inum, type);
+ err = dir_l_add(dip, filename, len, inum, type);
+ return err;
}
struct gfs2_buffer_head *
@@ -1290,6 +1300,7 @@ struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename,
struct gfs2_inum inum;
struct gfs2_buffer_head *bh;
struct gfs2_inode *ip;
+ int err = 0;
gfs2_lookupi(dip, filename, strlen(filename), &ip);
if (!ip) {
@@ -1298,7 +1309,9 @@ struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename,
inum.no_formal_ino = sdp->md.next_inum++;
inum.no_addr = bn;
- dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode));
+ err = dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode));
+ if (err)
+ return NULL;
if(S_ISDIR(mode)) {
bmodified(dip->i_bh);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 2c2bce5..87c65c6 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -380,7 +380,7 @@ extern int dir_search(struct gfs2_inode *dip, const char *filename, int len,
unsigned int *type, struct gfs2_inum *inum);
extern int gfs2_lookupi(struct gfs2_inode *dip, const char *filename, int len,
struct gfs2_inode **ipp);
-extern void dir_add(struct gfs2_inode *dip, const char *filename, int len,
+extern int dir_add(struct gfs2_inode *dip, const char *filename, int len,
struct gfs2_inum *inum, unsigned int type);
extern int gfs2_dirent_del(struct gfs2_inode *dip, const char *filename,
int filename_len);
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Fix memory leak in initialize.c
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=f6e426b5aa2...
Commit: f6e426b5aa22692e414192d5aa70e4ef15db1c18
Parent: 0059c9378ae6cfa28742f96065ade198d8807787
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jan 12 14:31:45 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Fix memory leak in initialize.c
This patch fixes a memory leak whereby dinodes were not being freed
under certain conditions.
rhbz#877150
---
gfs2/fsck/initialize.c | 25 ++++++++++++++++---------
1 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 0e798ef..df955eb 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -770,7 +770,7 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
ip = inode_read(sdp, di->di_num.no_addr);
if (di->di_num.no_formal_ino == 3) {
if (fix_md.jiinode || is_journal_copy(ip, bh))
- return;
+ goto out_discard_ip;
log_warn(_("Found system jindex file at: 0x%llx\n"),
di->di_num.no_addr);
fix_md.jiinode = ip;
@@ -779,8 +779,10 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
jindex: master */
gfs2_lookupi(ip, "jindex", 6, &child_ip);
if (child_ip) {
- if (fix_md.jiinode || is_journal_copy(ip, bh))
- return;
+ if (fix_md.jiinode || is_journal_copy(ip, bh)) {
+ inode_put(&child_ip);
+ goto out_discard_ip;
+ }
fix_md.jiinode = child_ip;
sdp->sd_sb.sb_master_dir.no_addr = di->di_num.no_addr;
log_warn(_("Found system master directory at: "
@@ -792,8 +794,9 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
has a statfs_change: per_node, and its .. will be master. */
gfs2_lookupi(ip, "statfs_change0", 14, &child_ip);
if (child_ip) {
+ inode_put(&child_ip);
if (fix_md.pinode || is_journal_copy(ip, bh))
- return;
+ goto out_discard_ip;
log_warn(_("Found system per_node directory at: "
"0x%llx\n"), ip->i_di.di_num.no_addr);
fix_md.pinode = ip;
@@ -809,22 +812,22 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
}
log_debug(_("Unknown system directory at block 0x%llx\n"),
di->di_num.no_addr);
- inode_put(&ip);
+ goto out_discard_ip;
} else if (di->di_size == 8) {
if (fix_md.inum || is_journal_copy(ip, bh))
- return;
+ goto out_discard_ip;
fix_md.inum = ip;
log_warn(_("Found system inum file at: 0x%llx\n"),
di->di_num.no_addr);
} else if (di->di_size == 24) {
if (fix_md.statfs || is_journal_copy(ip, bh))
- return;
+ goto out_discard_ip;
fix_md.statfs = ip;
log_warn(_("Found system statfs file at: 0x%llx\n"),
di->di_num.no_addr);
} else if ((di->di_size % 96) == 0) {
if (fix_md.riinode || is_journal_copy(ip, bh))
- return;
+ goto out_discard_ip;
fix_md.riinode = ip;
log_warn(_("Found system rindex file at: 0x%llx\n"),
di->di_num.no_addr);
@@ -832,11 +835,15 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
di->di_num.no_formal_ino >= 12 &&
di->di_num.no_formal_ino <= 100) {
if (is_journal_copy(ip, bh))
- return;
+ goto out_discard_ip;
fix_md.qinode = ip;
log_warn(_("Found system quota file at: 0x%llx\n"),
di->di_num.no_addr);
}
+ return;
+
+out_discard_ip:
+ inode_put(&ip);
}
/**
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Don't use strerror for libgfs2 errors
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=0059c9378ae...
Commit: 0059c9378ae6cfa28742f96065ade198d8807787
Parent: aa125b9443ab370b9bcfedafe1b0a69e1804f4b3
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jan 12 14:29:19 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Don't use strerror for libgfs2 errors
This patch removes the calls to strerror from initialize.c.
The errors returned by libgfs2 currently don't conform to system
errors. For example, they can return positive or negative numbers.
Therefore, strerror could segfault or give nonsense messages.
I hate numeric error messages as much as the next guy, but using
strerror won't work until we systematically go through libgfs2 and
make all the return codes conform to the rules strerror lives by.
rhbz#877150
---
gfs2/fsck/initialize.c | 32 +++++++++++++++++++++++---------
gfs2/fsck/lost_n_found.c | 7 +++++++
2 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index fc4fdec..0e798ef 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -452,8 +452,8 @@ static void lookup_per_node(struct gfs2_sbd *sdp, int allow_rebuild)
err = build_per_node(sdp);
if (err) {
- log_crit(_("Error rebuilding per_node directory: %s\n"),
- strerror(err));
+ log_crit(_("Error %d rebuilding per_node directory\n"),
+ err);
exit(FSCK_ERROR);
}
}
@@ -570,9 +570,25 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
gfs2_lookupi(sdp->master_dir, "inum", 4,
&sdp->md.inum);
if (!sdp->md.inum) {
- log_crit("System inum inode was not rebuilt. "
- "Aborting.\n");
- goto fail;
+ if (!query( _("The gfs2 system inum inode is missing. "
+ "Okay to rebuild it? (y/n) "))) {
+ log_err( _("fsck.gfs2 cannot continue without "
+ "a valid inum file; aborting.\n"));
+ goto fail;
+ }
+ err = build_inum(sdp);
+ if (err) {
+ log_crit(_("Error %d rebuilding inum inode\n"),
+ err);
+ exit(FSCK_ERROR);
+ }
+ gfs2_lookupi(sdp->master_dir, "inum", 4,
+ &sdp->md.inum);
+ if (!sdp->md.inum) {
+ log_crit("System inum inode was not rebuilt. "
+ "Aborting.\n");
+ goto fail;
+ }
}
}
/* Read inum entry into buffer */
@@ -591,8 +607,7 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
}
err = build_statfs(sdp);
if (err) {
- log_crit(_("Error rebuilding statfs inode: %s\n"),
- strerror(err));
+ log_crit(_("Error %d rebuilding statfs inode\n"), err);
exit(FSCK_ERROR);
}
gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
@@ -625,8 +640,7 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
}
err = build_quota(sdp);
if (err) {
- log_crit(_("Error rebuilding quota inode: %s\n"),
- strerror(err));
+ log_crit(_("Error %d rebuilding quota inode\n"), err);
exit(FSCK_ERROR);
}
gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index f02fb5a..afdeefc 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -19,6 +19,7 @@
#include <unistd.h>
#include <dirent.h>
#include <libintl.h>
+#include <errno.h>
#define _(String) gettext(String)
#include "fsck.h"
@@ -115,6 +116,12 @@ int add_inode_to_lf(struct gfs2_inode *ip){
lf_dip = createi(sdp->md.rooti, "lost+found",
S_IFDIR | 0700, 0);
+ if (lf_dip == NULL) {
+ log_crit(_("Error %d creating lost+found: %s\n"),
+ errno);
+ exit(FSCK_ERROR);
+ }
+
/* 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
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Fix initialization error return codes
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=aa125b9443a...
Commit: aa125b9443ab370b9bcfedafe1b0a69e1804f4b3
Parent: 071287645c85a40797d2658d4e0f6cc3a65cf93f
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jan 12 14:18:13 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Fix initialization error return codes
In initialize.c there are several places where it can exit with an error.
These places return with -1 where they should return the standard fsck
error FSCK_ERROR.
rhbz#877150
---
gfs2/fsck/initialize.c | 85 +++++++++++++++++++++++++++++++++++------------
1 files changed, 63 insertions(+), 22 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 537cae5..fc4fdec 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -454,13 +454,13 @@ static void lookup_per_node(struct gfs2_sbd *sdp, int allow_rebuild)
if (err) {
log_crit(_("Error rebuilding per_node directory: %s\n"),
strerror(err));
- exit(-1);
+ exit(FSCK_ERROR);
}
}
gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
if (!sdp->md.pinode) {
log_err( _("Unable to rebuild per_node; aborting.\n"));
- exit(-1);
+ exit(FSCK_ERROR);
}
}
@@ -555,24 +555,52 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
/* Look for "inum" entry in master dinode */
gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
if (!sdp->md.inum) {
- if (query( _("The gfs2 system inum inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_inum(sdp);
+ if (!query( _("The gfs2 system inum inode is missing. "
+ "Okay to rebuild it? (y/n) "))) {
+ log_err( _("fsck.gfs2 cannot continue without "
+ "a valid inum file; aborting.\n"));
+ goto fail;
+ }
+ err = build_inum(sdp);
+ if (err) {
+ log_crit(_("Error rebuilding inum inode: %s\n"),
+ strerror(err));
+ exit(FSCK_ERROR);
+ }
+ gfs2_lookupi(sdp->master_dir, "inum", 4,
+ &sdp->md.inum);
+ if (!sdp->md.inum) {
+ log_crit("System inum inode was not rebuilt. "
+ "Aborting.\n");
+ goto fail;
+ }
}
/* Read inum entry into buffer */
- gfs2_readi(sdp->md.inum, &inumbuf, 0, sdp->md.inum->i_di.di_size);
+ gfs2_readi(sdp->md.inum, &inumbuf, 0,
+ sdp->md.inum->i_di.di_size);
/* call gfs2_inum_range_in() to retrieve range */
sdp->md.next_inum = be64_to_cpu(inumbuf);
gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
if (!sdp->md.statfs) {
- if (query( _("The gfs2 system statfs inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_statfs(sdp);
- else {
- log_err( _("fsck.gfs2 cannot continue without a "
- "valid statfs file; aborting.\n"));
- return FSCK_ERROR;
+ if (!query( _("The gfs2 system statfs inode is missing. "
+ "Okay to rebuild it? (y/n) "))) {
+ log_err( _("fsck.gfs2 cannot continue without a valid "
+ "statfs file; aborting.\n"));
+ goto fail;
+ }
+ err = build_statfs(sdp);
+ if (err) {
+ log_crit(_("Error rebuilding statfs inode: %s\n"),
+ strerror(err));
+ exit(FSCK_ERROR);
+ }
+ gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
+ if (!sdp->md.statfs) {
+ log_err( _("Rebuild of statfs system file failed."));
+ log_err( _("fsck.gfs2 cannot continue without "
+ "a valid statfs file; aborting.\n"));
+ goto fail;
}
do_init_statfs(sdp);
}
@@ -589,9 +617,24 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
if (!sdp->md.qinode) {
- if (query( _("The gfs2 system quota inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_quota(sdp);
+ if (!query( _("The gfs2 system quota inode is missing. "
+ "Okay to rebuild it? (y/n) "))) {
+ log_crit("System quota inode was not "
+ "rebuilt. Aborting.\n");
+ goto fail;
+ }
+ err = build_quota(sdp);
+ if (err) {
+ log_crit(_("Error rebuilding quota inode: %s\n"),
+ strerror(err));
+ exit(FSCK_ERROR);
+ }
+ gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
+ if (!sdp->md.qinode) {
+ log_crit("Unable to rebuild system quota file "
+ "inode. Aborting.\n");
+ goto fail;
+ }
}
/* Try to lookup the per_node inode. If it was missing, it is now
@@ -1079,6 +1122,8 @@ static int sb_repair(struct gfs2_sbd *sdp)
*/
static int fill_super_block(struct gfs2_sbd *sdp)
{
+ int ret;
+
sync();
/********************************************************************
@@ -1100,12 +1145,8 @@ static int fill_super_block(struct gfs2_sbd *sdp)
}
compute_constants(sdp);
- if (read_sb(sdp) < 0) {
- /* First, check for a gfs1 (not gfs2) file system */
- if (sdp->sd_sb.sb_header.mh_magic == GFS2_MAGIC &&
- sdp->sd_sb.sb_header.mh_type == GFS2_METATYPE_SB)
- return -1; /* This is gfs1, don't try to repair */
- /* It's not a "sane" gfs1 fs so try to repair it */
+ ret = read_sb(sdp);
+ if (ret < 0) {
if (sb_repair(sdp) != 0)
return -1; /* unrepairable, so exit */
/* Now that we've tried to repair it, re-read it. */
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Rearrange block types to group all inode types
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=071287645c8...
Commit: 071287645c85a40797d2658d4e0f6cc3a65cf93f
Parent: 979447cfad1f18bbcf617511ae40742903690fdf
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jan 12 13:55:59 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Rearrange block types to group all inode types
This patch rearranges the declares in util.h such that all the inode
types are grouped together. There's a place in fsck.gfs2 that checks
whether a block is an inode by checking the range of block types.
But that's only valid if they are all grouped together. Since a
previous patch put GFS journaled data blocks in the range, they could
mistakenly pass that test and be treated as an inode for that test.
I never saw an error resulting from this mistake, but I'm fixing it
anyway.
rhbz#877150
Conflicts:
gfs2/fsck/util.h
---
gfs2/fsck/util.h | 20 +++++++++++---------
1 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
index 86bda82..e4bee0a 100644
--- a/gfs2/fsck/util.h
+++ b/gfs2/fsck/util.h
@@ -52,16 +52,18 @@ enum gfs2_mark_block {
gfs2_block_free = (0x0),
gfs2_block_used = (0x1),
gfs2_indir_blk = (0x2),
+ /* These are inode block types (only): */
gfs2_inode_dir = (0x3),
gfs2_inode_file = (0x4),
gfs2_inode_lnk = (0x5),
- gfs2_inode_device = (0x6),
+ gfs2_inode_device = (0x6), /* char or block device */
+ gfs2_inode_fifo = (0x7),
+ gfs2_inode_sock = (0x8),
+ gfs2_inode_invalid = (0x9),
- gfs2_inode_fifo = (0x8),
- gfs2_inode_sock = (0x9),
-
- gfs2_inode_invalid = (0xa),
+ /* misc block types: */
+ gfs2_jdata = (0xa), /* gfs journaled data blocks */
gfs2_meta_inval = (0xb),
gfs2_leaf_blk = (0xc),
@@ -81,11 +83,11 @@ static const inline char *block_type_string(uint8_t q)
"symlink",
"device",
- "",
"fifo",
"socket",
-
"invalid inode",
+
+ "journaled data",
"invalid meta",
"dir leaf",
"",
@@ -110,11 +112,11 @@ static inline int blockmap_to_bitmap(enum gfs2_mark_block m)
GFS2_BLKST_DINODE, /* symlink */
GFS2_BLKST_DINODE, /* block or char device */
- GFS2_BLKST_USED, /* journaled data */
GFS2_BLKST_DINODE, /* fifo */
GFS2_BLKST_DINODE, /* socket */
-
GFS2_BLKST_FREE, /* invalid inode */
+
+ GFS2_BLKST_USED, /* journaled data */
GFS2_BLKST_FREE, /* invalid meta */
GFS2_BLKST_USED, /* dir leaf */
GFS2_BLKST_UNLINKED, /* GFS unlinked metadata */
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Journals not properly checked
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=979447cfad1...
Commit: 979447cfad1f18bbcf617511ae40742903690fdf
Parent: d873d2a33c42baa8063c6975e430756c9fbbb1e2
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 6 17:19:25 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Journals not properly checked
The coverity tool found a problem with the previous set of patches that
led me to discover a problem with how journals were being processed
under the new code. The problem was that the journal index was read
in after journal replay. But journal replay relies upon information
in the jindex. This patch rearranges the initializeation sequence
of fsck.gfs2 so that the journal index and rindex are read in and
processed prior to journal recovery.
rhbz#877150
---
gfs2/fsck/fs_recovery.c | 12 ----
gfs2/fsck/initialize.c | 164 ++++++++++++++++++++++++++++++++---------------
2 files changed, 112 insertions(+), 64 deletions(-)
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 94113ca..61c3b9d 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -584,14 +584,6 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
*clean_journals = 0;
sdp->jsize = GFS2_DEFAULT_JSIZE;
- /* Get master dinode */
- gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
-
- /* read in the journal index data */
- if (ji_update(sdp)){
- log_err( _("Unable to read in jindex inode.\n"));
- return -1;
- }
for(i = 0; i < sdp->md.journals; i++) {
if (!sdp->md.journal[i]) {
@@ -620,11 +612,7 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
}
*clean_journals += clean;
}
- inode_put(&sdp->md.journal[i]);
}
- inode_put(&sdp->md.jiinode);
- free(sdp->md.journal);
- sdp->md.journal = NULL;
/* Sync the buffers to disk so we get a fresh start. */
fsync(sdp->device_fd);
return error;
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 8ab5f48..537cae5 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -465,18 +465,13 @@ static void lookup_per_node(struct gfs2_sbd *sdp, int allow_rebuild)
}
/**
- * init_system_inodes
- *
- * Returns: 0 on success, -1 on failure
+ * fetch_rgrps - fetch the resource groups from disk, and check their integrity
*/
-static int init_system_inodes(struct gfs2_sbd *sdp)
+static int fetch_rgrps(struct gfs2_sbd *sdp)
{
- uint64_t inumbuf;
- char *buf;
- struct gfs2_statfs_change sc;
- int rgcount, sane = 1;
enum rgindex_trust_level trust_lvl;
- uint64_t addl_mem_needed;
+ int rgcount, sane = 1;
+
const char *level_desc[] = {
_("Checking if all rgrp and rindex values are good"),
_("Checking if rindex values may be easily repaired"),
@@ -491,42 +486,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
_("Too many rgrp misses: rgrps must be unevenly spaced"),
_("Too much damage found: we cannot rebuild this rindex"),
};
-
- /*******************************************************************
- ****************** Initialize important inodes ******************
- *******************************************************************/
-
- log_info( _("Initializing special inodes...\n"));
-
- /* Get root dinode */
- sdp->md.rooti = inode_read(sdp, sdp->sd_sb.sb_root_dir.no_addr);
-
- gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
- if (!sdp->md.riinode) {
- if (query( _("The gfs2 system rindex inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_rindex(sdp);
- }
-
- /*******************************************************************
- ****************** Fill in journal information ******************
- *******************************************************************/
-
- /* rgrepair requires the journals be read in in order to distinguish
- "real" rgrps from rgrps that are just copies left in journals. */
- gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
- if (!sdp->md.jiinode) {
- if (query( _("The gfs2 system jindex inode is missing. "
- "Okay to rebuild it? (y/n) ")))
- build_jindex(sdp);
- }
-
- /* read in the ji data */
- if (ji_update(sdp)){
- log_err( _("Unable to read in jindex inode.\n"));
- return -1;
- }
-
/*******************************************************************
******** Validate and read in resource group information ********
*******************************************************************/
@@ -561,6 +520,34 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
log_info( _("%u resource groups found.\n"), rgcount);
check_rgrps_integrity(sdp);
+ return 0;
+}
+
+/**
+ * init_system_inodes
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int init_system_inodes(struct gfs2_sbd *sdp)
+{
+ uint64_t inumbuf = 0;
+ char *buf;
+ struct gfs2_statfs_change sc;
+ uint64_t addl_mem_needed;
+ int err;
+
+ /*******************************************************************
+ ****************** Initialize important inodes ******************
+ *******************************************************************/
+
+ log_info( _("Initializing special inodes...\n"));
+
+ /* Get root dinode */
+ sdp->md.rooti = inode_read(sdp, sdp->sd_sb.sb_root_dir.no_addr);
+
+ err = fetch_rgrps(sdp);
+ if (err)
+ return err;
/*******************************************************************
***************** Initialize more system inodes *****************
@@ -1125,7 +1112,75 @@ static int fill_super_block(struct gfs2_sbd *sdp)
if (read_sb(sdp) < 0)
return -1;
}
+ return 0;
+}
+/**
+ * init_rindex - read in the rindex file
+ */
+static int init_rindex(struct gfs2_sbd *sdp)
+{
+ int err;
+
+ gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
+
+ if (sdp->md.riinode)
+ return 0;
+
+ if (!query( _("The gfs2 system rindex inode is missing. "
+ "Okay to rebuild it? (y/n) "))) {
+ log_crit(_("Error: Cannot proceed without a valid rindex.\n"));
+ return -1;
+ }
+ if ((err = build_rindex(sdp))) {
+ log_crit(_("Error %d rebuilding rindex\n"), err);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * init_jindex - read in the rindex file
+ */
+static int init_jindex(struct gfs2_sbd *sdp)
+{
+ /*******************************************************************
+ ****************** Fill in journal information ******************
+ *******************************************************************/
+
+ /* rgrepair requires the journals be read in in order to distinguish
+ "real" rgrps from rgrps that are just copies left in journals. */
+ gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
+
+ if (!sdp->md.jiinode) {
+ int err;
+
+ if (!query( _("The gfs2 system jindex inode is missing. "
+ "Okay to rebuild it? (y/n) "))) {
+ log_crit(_("Error: cannot proceed without a valid "
+ "jindex file.\n"));
+ return -1;
+ }
+ /* In order to rebuild jindex, we need some valid
+ rgrps in memory. Temporarily read those in. */
+ err = fetch_rgrps(sdp);
+ if (err)
+ return err;
+
+ err = build_jindex(sdp);
+ /* Free rgrps read in earlier (re-read them later) */
+ gfs2_rgrp_free(&sdp->rglist);
+ if (err) {
+ log_crit(_("Error %d rebuilding jindex\n"), err);
+ return err;
+ }
+ }
+
+ /* read in the ji data */
+ if (ji_update(sdp)){
+ log_err( _("Unable to read in jindex inode.\n"));
+ return -1;
+ }
return 0;
}
@@ -1211,7 +1266,17 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
our journals to be there before we can replay them. */
lookup_per_node(sdp, 0);
- /* verify various things */
+ /* We need rindex first in case jindex is missing and needs to read
+ in the rgrps before rebuilding it. */
+ if (init_rindex(sdp))
+ return FSCK_ERROR;
+
+ /* We need to read in jindex in order to replay the journals */
+ if (init_jindex(sdp))
+ return FSCK_ERROR;
+
+ /* If GFS, rebuild the journals. If GFS2, replay them. We don't have
+ the smarts to replay GFS1 journals (neither did gfs_fsck). */
if (replay_journals(sdp, preen, force_check, &clean_journals)) {
if (!opts.no && preen_is_safe(sdp, preen, force_check))
@@ -1239,7 +1304,7 @@ mount_fail:
return FSCK_USAGE;
}
-static void destroy_sdp(struct gfs2_sbd *sdp)
+void destroy(struct gfs2_sbd *sdp)
{
if (!opts.no) {
if (block_mounters(sdp, 0)) {
@@ -1261,8 +1326,3 @@ static void destroy_sdp(struct gfs2_sbd *sdp)
"caches.\n"));
}
}
-
-void destroy(struct gfs2_sbd *sdp)
-{
- destroy_sdp(sdp);
-}
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Fix memory leaks
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=d873d2a33c4...
Commit: d873d2a33c42baa8063c6975e430756c9fbbb1e2
Parent: f150dda8961cf6b535da786eb6e9aa5a75a7349f
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 6 16:30:30 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:00 2013 -0700
fsck.gfs2: Fix memory leaks
This patch fixes some memory leaks in fsck.gfs2 that I discovered
by using valgrind.
rhbz#877150
---
gfs2/fsck/fs_recovery.c | 2 ++
gfs2/fsck/initialize.c | 16 ++++++++++------
gfs2/fsck/main.c | 2 ++
gfs2/fsck/metawalk.c | 10 ++++++++--
gfs2/fsck/pass1.c | 6 +++++-
5 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 8a4ff13..94113ca 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -623,6 +623,8 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
inode_put(&sdp->md.journal[i]);
}
inode_put(&sdp->md.jiinode);
+ free(sdp->md.journal);
+ sdp->md.journal = NULL;
/* Sync the buffers to disk so we get a fresh start. */
fsync(sdp->device_fd);
return error;
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 150c586..8ab5f48 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -589,12 +589,16 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
}
do_init_statfs(sdp);
}
- buf = malloc(sdp->md.statfs->i_di.di_size);
- // FIXME: handle failed malloc
- gfs2_readi(sdp->md.statfs, buf, 0, sdp->md.statfs->i_di.di_size);
- /* call gfs2_inum_range_in() to retrieve range */
- gfs2_statfs_change_in(&sc, buf);
- free(buf);
+ if (sdp->md.statfs->i_di.di_size) {
+ buf = malloc(sdp->md.statfs->i_di.di_size);
+ if (buf) {
+ gfs2_readi(sdp->md.statfs, buf, 0,
+ sdp->md.statfs->i_di.di_size);
+ /* call gfs2_inum_range_in() to retrieve range */
+ gfs2_statfs_change_in(&sc, buf);
+ free(buf);
+ }
+ }
gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
if (!sdp->md.qinode) {
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 62852af..4e556f1 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -355,6 +355,8 @@ int main(int argc, char **argv)
inode_put(&sdp->md.statfs);
for (j = 0; j < sdp->md.journals; j++)
inode_put(&sdp->md.journal[j]);
+ free(sdp->md.journal);
+ sdp->md.journal = NULL;
inode_put(&sdp->md.jiinode);
inode_put(&sdp->md.riinode);
inode_put(&sdp->md.qinode);
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index a580867..31ceca9 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1145,8 +1145,10 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
for (ptr = (uint64_t *)(bh->b_data + head_size);
(char *)ptr < (bh->b_data + ip->i_sbd->bsize);
ptr++) {
- if (skip_this_pass || fsck_abort)
+ if (skip_this_pass || fsck_abort) {
+ free_metalist(ip, mlp);
return FSCK_OK;
+ }
nbh = NULL;
if (!*ptr)
@@ -1258,6 +1260,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
error = build_and_check_metalist(ip, &metalist[0], pass);
if (error) {
stack;
+ free_metalist(ip, &metalist[0]);
return error;
}
@@ -1294,8 +1297,10 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
last_reported_fblock = -10000000;
while (error >= 0 && !osi_list_empty(list)) {
- if (fsck_abort)
+ if (fsck_abort) {
+ free_metalist(ip, &metalist[0]);
return 0;
+ }
bh = osi_list_entry(list->next, struct gfs2_buffer_head,
b_altlist);
@@ -1345,6 +1350,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
(unsigned long long)ip->i_di.di_num.no_addr);
fflush(stdout);
}
+ free_metalist(ip, &metalist[0]);
return error;
}
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 79fd216..c241960 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -434,6 +434,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
fsck_blockmap_set(ip, block, _("bad indirect"),
gfs2_meta_inval);
brelse(nbh);
+ nbh = NULL;
return 1;
}
brelse(nbh);
@@ -443,8 +444,11 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
bc->indir_count++;
if (found_dup) {
- if (nbh)
+ if (nbh) {
brelse(nbh);
+ nbh = NULL;
+ *bh = NULL;
+ }
return 1; /* don't process the metadata again */
} else
fsck_blockmap_set(ip, block, _("indirect"),
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: Speed up rangecheck functions
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=f150dda8961...
Commit: f150dda8961cf6b535da786eb6e9aa5a75a7349f
Parent: 0c93cdb7378757e954d635e114e37a62a888b17e
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 6 14:21:35 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:00 2013 -0700
fsck.gfs2: Speed up rangecheck functions
This patch speeds up the block rangecheck functions by passing
the block type in as an integer rather than a translated string
constant. The translation functions were a bit costly.
rhbz#877150
---
gfs2/fsck/pass1.c | 26 ++++++++++++++------------
1 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 62cc96e..79fd216 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1040,9 +1040,14 @@ static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
* duplicate (for example) until we know if the pointers in general can
* be trusted. Thus it needs to be in a separate loop.
*/
+enum b_types { btype_meta, btype_leaf, btype_data, btype_ieattr, btype_eattr};
+const char *btypes[5] = {
+ "metadata", "leaf", "data", "indirect extended attribute",
+ "extended attribute" };
+
static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh,
- const char *btype, void *private)
+ struct gfs2_buffer_head **bh, enum b_types btype,
+ void *private)
{
long *bad_pointers = (long *)private;
uint8_t q;
@@ -1051,7 +1056,7 @@ static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
(*bad_pointers)++;
log_info( _("Bad %s block pointer (invalid or out of range "
"#%ld) found in inode %lld (0x%llx).\n"),
- btype, *bad_pointers,
+ btypes[btype], *bad_pointers,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
if ((*bad_pointers) <= BAD_POINTER_TOLERANCE)
@@ -1065,7 +1070,7 @@ static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
(*bad_pointers)++;
log_info( _("Duplicated %s block pointer (violation %ld, block"
" %lld (0x%llx)) found in inode %lld (0x%llx).\n"),
- btype, *bad_pointers,
+ btypes[btype], *bad_pointers,
(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);
@@ -1081,36 +1086,33 @@ static int rangecheck_metadata(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, int h,
void *private)
{
- return rangecheck_block(ip, block, bh, _("metadata"), private);
+ return rangecheck_block(ip, block, bh, btype_meta, private);
}
static int rangecheck_leaf(struct gfs2_inode *ip, uint64_t block,
void *private)
{
- return rangecheck_block(ip, block, NULL, _("leaf"), private);
+ return rangecheck_block(ip, block, NULL, btype_leaf, private);
}
static int rangecheck_data(struct gfs2_inode *ip, uint64_t block,
void *private)
{
- return rangecheck_block(ip, block, NULL, _("data"), private);
+ return rangecheck_block(ip, block, NULL, btype_data, private);
}
static int rangecheck_eattr_indir(struct gfs2_inode *ip, uint64_t block,
uint64_t parent,
struct gfs2_buffer_head **bh, void *private)
{
- return rangecheck_block(ip, block, NULL,
- _("indirect extended attribute"),
- private);
+ return rangecheck_block(ip, block, NULL, btype_ieattr, private);
}
static int rangecheck_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
uint64_t parent, struct gfs2_buffer_head **bh,
void *private)
{
- return rangecheck_block(ip, block, NULL, _("extended attribute"),
- private);
+ return rangecheck_block(ip, block, NULL, btype_eattr, private);
}
struct metawalk_fxns rangecheck_fxns = {
11 years, 1 month
cluster: RHEL510 - fsck.gfs2: pass1c counts percentage backward
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=0c93cdb7378...
Commit: 0c93cdb7378757e954d635e114e37a62a888b17e
Parent: 68922b8444c39c78a79b9f62062e60adfaa5f1ea
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 6 14:20:26 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:00 2013 -0700
fsck.gfs2: pass1c counts percentage backward
In testing I noticed that pass1c, which checks all extended
attributes, counted percent-complete backwards. It's better to
count forward because disk block seeks will be more efficient.
This patch changes the special_list functions of block_list to
add items as "prev" so that they're processed in block order.
rhbz#877150
---
gfs2/libgfs2/block_list.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c
index a7e28f3..06384a1 100644
--- a/gfs2/libgfs2/block_list.c
+++ b/gfs2/libgfs2/block_list.c
@@ -54,7 +54,7 @@ void gfs2_special_add(struct special_blocks *blocklist, uint64_t block)
if (b) {
memset(b, 0, sizeof(*b));
b->block = block;
- osi_list_add(&b->list, &blocklist->list);
+ osi_list_add_prev(&b->list, &blocklist->list);
}
}
11 years, 1 month