[GFS2] Finally get ref counting correct
Steven Whitehouse [Fri, 7 Apr 2006 20:28:07 +0000 (16:28 -0400)]
The last patch missed some other instances of incorrect ref counting,
this fixes all of those too.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>

fs/gfs2/dir.c
fs/gfs2/log.c

index 316eed6..100672d 100644 (file)
@@ -776,9 +776,9 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
                                goto got_dent;
                        leaf = (struct gfs2_leaf *)bh->b_data;
                        ln = be64_to_cpu(leaf->lf_next);
-                       brelse(bh);
                        if (!ln)
                                break;
+                       brelse(bh);
                        error = get_leaf(ip, ln, &bh);
                } while(!error);
 
@@ -789,9 +789,11 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
        if (error)
                return ERR_PTR(error);
        dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, scan, name, NULL);
-       brelse(bh);
-
 got_dent:
+       if (unlikely(IS_ERR(dent))) {
+               brelse(bh);
+               bh = NULL;
+       }
        *pbh = bh;
        return dent;
 }
@@ -1475,6 +1477,7 @@ int gfs2_dir_search(struct inode *dir, const struct qstr *name,
                brelse(bh);
                return 0;
        }
+       brelse(bh);
        return -ENOENT;
 }
 
@@ -1616,6 +1619,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
           previous entry otherwise */
        dent = gfs2_dirent_search(dip->i_vnode, name, gfs2_dirent_prev, &bh);
        if (!dent) {
+               brelse(bh);
                gfs2_consist_inode(dip);
                return -EIO;
        }
@@ -1636,8 +1640,8 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
                if (!entries)
                        gfs2_consist_inode(dip);
                leaf->lf_entries = cpu_to_be16(--entries);
-               brelse(bh);
        }
+       brelse(bh);
 
        error = gfs2_meta_inode_buffer(dip, &bh);
        if (error)
@@ -1676,6 +1680,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
 
        dent = gfs2_dirent_search(dip->i_vnode, filename, gfs2_dirent_find, &bh);
        if (!dent) {
+               brelse(bh);
                gfs2_consist_inode(dip);
                return -EIO;
        }
@@ -1955,8 +1960,10 @@ int gfs2_diradd_alloc_required(struct inode *inode,
        struct buffer_head *bh;
 
        dent = gfs2_dirent_search(inode, name, gfs2_dirent_find_space, &bh);
-       if (!dent)
+       if (!dent) {
+               brelse(bh);
                return 1;
+       }
        if (IS_ERR(dent))
                return PTR_ERR(dent);
        brelse(bh);
index cadfef1..0b26d6a 100644 (file)
@@ -196,7 +196,6 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
 
 void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
 {
-       up_read(&sdp->sd_log_flush_lock);
 
        gfs2_log_lock(sdp);
        sdp->sd_log_blks_free += blks;
@@ -204,6 +203,7 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
        gfs2_assert_withdraw(sdp,
                             sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
        gfs2_log_unlock(sdp);
+       up_read(&sdp->sd_log_flush_lock);
 }
 
 static uint64_t log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)