Previously init_dinode() always allocated the bh with bget() which meant
less control over memory allocation higher up. This patch changes the
signature of init_dinode to accept a bh pointer and only allocates a new
bh if it is NULL. Also adds error checking to init_dinode()'s callers.

Signed-off-by: Andrew Price <anpr...@redhat.com>
---
 gfs2/convert/gfs2_convert.c |  7 +++++--
 gfs2/fsck/initialize.c      | 12 ++++++++----
 gfs2/libgfs2/fs_ops.c       | 42 ++++++++++++++++++++++++------------------
 gfs2/libgfs2/libgfs2.h      |  6 ++----
 gfs2/libgfs2/structures.c   | 13 +++++++++----
 5 files changed, 48 insertions(+), 32 deletions(-)

diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 61ed320..19a9839 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1389,7 +1389,7 @@ static int fix_cdpn_symlinks(struct gfs2_sbd *sbp, 
osi_list_t *cdpn_to_fix)
        osi_list_foreach_safe(tmp, cdpn_to_fix, x) {
                struct gfs2_inum fix, dir;
                struct inode_dir_block *l_fix;
-               struct gfs2_buffer_head *bh;
+               struct gfs2_buffer_head *bh = NULL;
                struct gfs2_inode *fix_inode;
                uint64_t eablk;
 
@@ -1411,7 +1411,10 @@ static int fix_cdpn_symlinks(struct gfs2_sbd *sbp, 
osi_list_t *cdpn_to_fix)
                }
 
                /* initialize the symlink inode to be a directory */
-               bh = init_dinode(sbp, &fix, S_IFDIR | 0755, 0, &dir);
+               error = init_dinode(sbp, &bh, &fix, S_IFDIR | 0755, 0, &dir);
+               if (error != 0)
+                       return -1;
+
                fix_inode = lgfs2_inode_get(sbp, bh);
                if (fix_inode == NULL)
                        return -1;
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 02ecd3f..4dedec2 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -419,7 +419,7 @@ static void check_rgrps_integrity(struct gfs2_sbd *sdp)
 static int rebuild_master(struct gfs2_sbd *sdp)
 {
        struct gfs2_inum inum;
-       struct gfs2_buffer_head *bh;
+       struct gfs2_buffer_head *bh = NULL;
        int err = 0;
 
        log_err(_("The system master directory seems to be destroyed.\n"));
@@ -430,7 +430,9 @@ static int rebuild_master(struct gfs2_sbd *sdp)
        log_err(_("Trying to rebuild the master directory.\n"));
        inum.no_formal_ino = sdp->md.next_inum++;
        inum.no_addr = sdp->sd_sb.sb_master_dir.no_addr;
-       bh = init_dinode(sdp, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
+       err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, 
&inum);
+       if (err != 0)
+               return -1;
        sdp->master_dir = lgfs2_inode_get(sdp, bh);
        if (sdp->master_dir == NULL) {
                log_crit(_("Error reading master: %s\n"), strerror(errno));
@@ -1210,7 +1212,7 @@ static int sb_repair(struct gfs2_sbd *sdp)
                sdp->md.rooti = lgfs2_inode_read(sdp, possible_root);
                if (!sdp->md.rooti ||
                    sdp->md.rooti->i_di.di_header.mh_magic != GFS2_MAGIC) {
-                       struct gfs2_buffer_head *bh;
+                       struct gfs2_buffer_head *bh = NULL;
 
                        log_err(_("The root dinode block is destroyed.\n"));
                        log_err(_("At this point I recommend "
@@ -1225,7 +1227,9 @@ static int sb_repair(struct gfs2_sbd *sdp)
                        }
                        inum.no_formal_ino = 1;
                        inum.no_addr = possible_root;
-                       bh = init_dinode(sdp, &inum, S_IFDIR | 0755, 0, &inum);
+                       error = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, 
&inum);
+                       if (error != 0)
+                               return -1;
                        brelse(bh);
                }
        }
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index aa95aa8..c8b90ad 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -1273,24 +1273,30 @@ int dir_add(struct gfs2_inode *dip, const char 
*filename, int len,
        return err;
 }
 
-static struct gfs2_buffer_head *__init_dinode(struct gfs2_sbd *sdp,
-                                             struct gfs2_inum *inum,
-                                             unsigned int mode,
-                                             uint32_t flags,
-                                             struct gfs2_inum *parent,
-                                             int gfs1)
+static int __init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, 
struct gfs2_inum *inum,
+                         unsigned int mode, uint32_t flags, struct gfs2_inum 
*parent, int gfs1)
 {
        struct gfs2_buffer_head *bh;
-       struct gfs2_dinode di;
+       struct gfs2_dinode di = {{0}};
        int is_dir;
 
        if (gfs1)
                is_dir = (IF2DT(mode) == GFS_FILE_DIR);
        else
                is_dir = S_ISDIR(mode);
-       bh = bget(sdp, inum->no_addr);
 
-       memset(&di, 0, sizeof(struct gfs2_dinode));
+       errno = EINVAL;
+       if (bhp == NULL)
+               return 1;
+
+       if (*bhp == NULL) {
+               *bhp = bget(sdp, inum->no_addr);
+               if (*bhp == NULL)
+                       return 1;
+       }
+
+       bh = *bhp;
+
        di.di_header.mh_magic = GFS2_MAGIC;
        di.di_header.mh_type = GFS2_METATYPE_DI;
        di.di_header.mh_format = GFS2_FORMAT_DI;
@@ -1340,15 +1346,13 @@ static struct gfs2_buffer_head *__init_dinode(struct 
gfs2_sbd *sdp,
 
        gfs2_dinode_out(&di, bh);
 
-       return bh;
+       return 0;
 }
 
-struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
-                                    struct gfs2_inum *inum,
-                                    unsigned int mode, uint32_t flags,
-                                    struct gfs2_inum *parent)
+int init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, struct 
gfs2_inum *inum,
+                unsigned int mode, uint32_t flags, struct gfs2_inum *parent)
 {
-       return __init_dinode(sdp, inum, mode, flags, parent, 0);
+       return __init_dinode(sdp, bhp, inum, mode, flags, parent, 0);
 }
 
 static struct gfs2_inode *__createi(struct gfs2_inode *dip,
@@ -1358,7 +1362,7 @@ static struct gfs2_inode *__createi(struct gfs2_inode 
*dip,
        struct gfs2_sbd *sdp = dip->i_sbd;
        uint64_t bn;
        struct gfs2_inum inum;
-       struct gfs2_buffer_head *bh;
+       struct gfs2_buffer_head *bh = NULL;
        struct gfs2_inode *ip;
        int err = 0;
        int is_dir;
@@ -1388,8 +1392,10 @@ static struct gfs2_inode *__createi(struct gfs2_inode 
*dip,
                        dip->i_di.di_nlink++;
                }
 
-               bh = __init_dinode(sdp, &inum, mode, flags, &dip->i_di.di_num,
-                                  if_gfs1);
+               err = __init_dinode(sdp, &bh, &inum, mode, flags, 
&dip->i_di.di_num, if_gfs1);
+               if (err != 0)
+                       return NULL;
+
                ip = lgfs2_inode_get(sdp, bh);
                if (ip == NULL)
                        return NULL;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index ed1030c..9b1bdc2 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -462,10 +462,8 @@ extern int __gfs2_writei(struct gfs2_inode *ip, void *buf, 
uint64_t offset,
                         unsigned int size, int resize);
 extern struct gfs2_buffer_head *get_file_buf(struct gfs2_inode *ip,
                                             uint64_t lbn, int prealloc);
-extern struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
-                                           struct gfs2_inum *inum,
-                                           unsigned int mode, uint32_t flags,
-                                           struct gfs2_inum *parent);
+extern int init_dinode(struct gfs2_sbd *sdp, struct gfs2_buffer_head **bhp, 
struct gfs2_inum *inum,
+                       unsigned int mode, uint32_t flags, struct gfs2_inum 
*parent);
 extern struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename,
                                  unsigned int mode, uint32_t flags);
 extern struct gfs2_inode *gfs_createi(struct gfs2_inode *dip,
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index 9d90657..1836255 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -20,7 +20,7 @@ int build_master(struct gfs2_sbd *sdp)
 {
        struct gfs2_inum inum;
        uint64_t bn;
-       struct gfs2_buffer_head *bh;
+       struct gfs2_buffer_head *bh = NULL;
        int err = lgfs2_dinode_alloc(sdp, 1, &bn);
 
        if (err != 0)
@@ -29,7 +29,9 @@ int build_master(struct gfs2_sbd *sdp)
        inum.no_formal_ino = sdp->md.next_inum++;
        inum.no_addr = bn;
 
-       bh = init_dinode(sdp, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
+       err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, 
&inum);
+       if (err != 0)
+               return -1;
 
        sdp->master_dir = lgfs2_inode_get(sdp, bh);
        if (sdp->master_dir == NULL)
@@ -479,7 +481,7 @@ int build_root(struct gfs2_sbd *sdp)
 {
        struct gfs2_inum inum;
        uint64_t bn;
-       struct gfs2_buffer_head *bh;
+       struct gfs2_buffer_head *bh = NULL;
        int err = lgfs2_dinode_alloc(sdp, 1, &bn);
 
        if (err != 0)
@@ -488,7 +490,10 @@ int build_root(struct gfs2_sbd *sdp)
        inum.no_formal_ino = sdp->md.next_inum++;
        inum.no_addr = bn;
 
-       bh = init_dinode(sdp, &inum, S_IFDIR | 0755, 0, &inum);
+       err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, &inum);
+       if (err != 0)
+               return -1;
+
        sdp->md.rooti = lgfs2_inode_get(sdp, bh);
        if (sdp->md.rooti == NULL)
                return -1;
-- 
1.9.3

Reply via email to