This is an automated email from the git hooks/post-receive script.
andyp pushed a commit to branch andyp-removeexit
in repository gfs2-utils.
commit a142c7c583718eb5ba8bbe9aefd9ff1c26b1ff85
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Wed Jan 11 11:24:42 2023 +0000
Add error checking to lgfs2_dir_split_leaf()
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/fsck/pass2.c | 6 +++++-
gfs2/libgfs2/fs_ops.c | 42 +++++++++++++++++++++++++-----------------
gfs2/libgfs2/libgfs2.h | 4 ++--
3 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index a0681ba8..6792f795 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -1399,7 +1399,11 @@ static int fix_hashtable(struct fsck_cx *cx, struct lgfs2_inode
*ip, __be64 *tbl
"0x%x.\n"), factor, len, proper_start);
changes++;
new_leaf_blk = find_free_blk(ip->i_sbd);
- lgfs2_dir_split_leaf(ip, lindex, leafblk, lbh);
+ if (lgfs2_dir_split_leaf(ip, lindex, leafblk, lbh)) {
+ log_crit(_("Failed to split directory leaf block at 0x%"PRIx64":
%s\n"),
+ ip->i_num.in_addr, strerror(errno));
+ exit(1);
+ }
/* re-read the leaf to pick up lgfs2_dir_split_leaf's changes */
lgfs2_leaf_in(&leaf, lbh->b_data);
*proper_len = 1 << (ip->i_depth - leaf.lf_depth);
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 66809014..2798bdde 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -894,8 +894,12 @@ int lgfs2_get_leaf_ptr(struct lgfs2_inode *dip, const uint32_t
lindex, uint64_t
return 0;
}
-void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start, uint64_t leaf_no,
- struct lgfs2_buffer_head *obh)
+/**
+ * Split a directory leaf.
+ * Returns 0 on success and non-zero with errno set on failure.
+ */
+int lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start, uint64_t leaf_no,
+ struct lgfs2_buffer_head *obh)
{
struct lgfs2_buffer_head *nbh;
struct gfs2_leaf *nleaf, *oleaf;
@@ -908,8 +912,10 @@ void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
uint64_t leaf
int x, moved = 0;
int count;
- if (lgfs2_meta_alloc(dip, &bn))
- exit(1);
+ if (lgfs2_meta_alloc(dip, &bn)) {
+ errno = EIO;
+ return -1;
+ }
nbh = lgfs2_bget(dip->i_sbd, bn);
{
struct gfs2_meta_header mh = {
@@ -932,10 +938,9 @@ void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
uint64_t leaf
half_len = len >> 1;
lp = calloc(1, half_len * sizeof(__be64));
- if (lp == NULL) {
- fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
- exit(-1);
- }
+ if (lp == NULL)
+ return -1;
+
for (x = 0; x < half_len; x++)
lp[x] = cpu_to_be64(bn);
@@ -946,8 +951,8 @@ void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
uint64_t leaf
count = lgfs2_writei(dip, (char *)lp, start * sizeof(uint64_t),
half_len * sizeof(uint64_t));
if (count != half_len * sizeof(uint64_t)) {
- fprintf(stderr, "lgfs2_dir_split_leaf (2)\n");
- exit(1);
+ errno = EINVAL;
+ return -1;
}
free(lp);
@@ -968,8 +973,8 @@ void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
uint64_t leaf
name_len = be16_to_cpu(dent->de_name_len);
if (dirent_alloc(dip, nbh, name_len, &new)) {
- fprintf(stderr, "lgfs2_dir_split_leaf (3)\n");
- exit(1);
+ errno = ENOSPC;
+ return -1;
}
new->de_inum = dent->de_inum;
@@ -994,8 +999,8 @@ void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
uint64_t leaf
if (!moved) {
if (dirent_alloc(dip, nbh, 0, &new)) {
- fprintf(stderr, "lgfs2_dir_split_leaf (4)\n");
- exit(1);
+ errno = ENOSPC;
+ return -1;
}
new->de_inum.no_formal_ino = 0;
/* Don't count the sentinel dirent as an entry */
@@ -1013,6 +1018,7 @@ void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
uint64_t leaf
lgfs2_bmodified(obh); /* Need to do this in case nothing was moved */
lgfs2_bmodified(nbh);
lgfs2_brelse(nbh);
+ return 0;
}
static void dir_double_exhash(struct lgfs2_inode *dip)
@@ -1155,7 +1161,7 @@ static int dir_e_add(struct lgfs2_inode *dip, const char *filename,
int len,
hash = lgfs2_disk_hash(filename, len);
restart:
- /* Have to kludge because (hash >> 32) gives hash for some reason. */
+ /* (hash >> 32) is undefined behaviour */
if (dip->i_depth)
lindex = hash >> (32 - dip->i_depth);
else
@@ -1176,8 +1182,10 @@ restart:
if (be16_to_cpu(leaf->lf_depth) < dip->i_depth) {
llen = 1 << (dip->i_depth -
be16_to_cpu(leaf->lf_depth));
- lgfs2_dir_split_leaf(dip, lindex & ~(llen - 1),
- leaf_no, bh);
+ if (lgfs2_dir_split_leaf(dip, lindex & ~(llen - 1), leaf_no, bh)) {
+ lgfs2_brelse(bh);
+ return -1;
+ }
lgfs2_brelse(bh);
goto restart;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 493961a8..7186126d 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -531,8 +531,8 @@ extern int lgfs2_dirent_del(struct lgfs2_inode *dip, const char
*filename, int n
extern int lgfs2_block_map(struct lgfs2_inode *ip, uint64_t lblock, int *new, uint64_t
*dblock,
uint32_t *extlen, int prealloc)
__attribute__((warn_unused_result));
extern int lgfs2_get_leaf_ptr(struct lgfs2_inode *dip, uint32_t index, uint64_t *ptr)
__attribute__((warn_unused_result));
-extern void lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start,
- uint64_t leaf_no, struct lgfs2_buffer_head *obh);
+extern int lgfs2_dir_split_leaf(struct lgfs2_inode *dip, uint32_t start, uint64_t
leaf_no,
+ struct lgfs2_buffer_head *obh)
__attribute__((warn_unused_result));
extern void lgfs2_free_block(struct lgfs2_sbd *sdp, uint64_t block);
extern int lgfs2_freedi(struct lgfs2_sbd *sdp, uint64_t block);
extern int lgfs2_get_leaf(struct lgfs2_inode *dip, uint64_t leaf_no,
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.