]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/gfs2/bmap.c
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
[karo-tx-linux.git] / fs / gfs2 / bmap.c
index 9d3a0c26df286b19fe069afebab173369fc4c11f..41d494d7970918644f338411d2fc523c89a641e1 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
+#include <linux/blkdev.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/crc32.h>
 
@@ -268,6 +269,30 @@ static inline __be64 *metapointer(unsigned int height, const struct metapath *mp
        return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
 }
 
+static void gfs2_metapath_ra(struct gfs2_glock *gl,
+                            const struct buffer_head *bh, const __be64 *pos)
+{
+       struct buffer_head *rabh;
+       const __be64 *endp = (const __be64 *)(bh->b_data + bh->b_size);
+       const __be64 *t;
+
+       for (t = pos; t < endp; t++) {
+               if (!*t)
+                       continue;
+
+               rabh = gfs2_getbuf(gl, be64_to_cpu(*t), CREATE);
+               if (trylock_buffer(rabh)) {
+                       if (!buffer_uptodate(rabh)) {
+                               rabh->b_end_io = end_buffer_read_sync;
+                               submit_bh(READA | REQ_META, rabh);
+                               continue;
+                       }
+                       unlock_buffer(rabh);
+               }
+               brelse(rabh);
+       }
+}
+
 /**
  * lookup_metapath - Walk the metadata tree to a specific point
  * @ip: The inode
@@ -427,12 +452,14 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct super_block *sb = sdp->sd_vfs;
        struct buffer_head *dibh = mp->mp_bh[0];
        u64 bn, dblock = 0;
        unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
        unsigned dblks = 0;
        unsigned ptrs_per_blk;
        const unsigned end_of_metadata = height - 1;
+       int ret;
        int eob = 0;
        enum alloc_state state;
        __be64 *ptr;
@@ -535,6 +562,15 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
                        dblock = bn;
                        while (n-- > 0)
                                *ptr++ = cpu_to_be64(bn++);
+                       if (buffer_zeronew(bh_map)) {
+                               ret = sb_issue_zeroout(sb, dblock, dblks,
+                                                      GFP_NOFS);
+                               if (ret) {
+                                       fs_err(sdp,
+                                              "Failed to zero data buffers\n");
+                                       clear_buffer_zeronew(bh_map);
+                               }
+                       }
                        break;
                }
        } while ((state != ALLOC_DATA) || !dblock);
@@ -724,7 +760,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
                        blen++;
                else {
                        if (bstart)
-                               gfs2_rlist_add(sdp, &rlist, bstart);
+                               gfs2_rlist_add(ip, &rlist, bstart);
 
                        bstart = bn;
                        blen = 1;
@@ -732,7 +768,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
        }
 
        if (bstart)
-               gfs2_rlist_add(sdp, &rlist, bstart);
+               gfs2_rlist_add(ip, &rlist, bstart);
        else
                goto out; /* Nothing to do */
 
@@ -859,7 +895,10 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
        if (error)
                goto out;
 
-       if (height < ip->i_height - 1)
+       if (height < ip->i_height - 1) {
+
+               gfs2_metapath_ra(ip->i_gl, bh, top);
+
                for (; top < bottom; top++, first = 0) {
                        if (!*top)
                                continue;
@@ -871,7 +910,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
                        if (error)
                                break;
                }
-
+       }
 out:
        brelse(bh);
        return error;