xen: map foreign pages for shared rings by updating the PTEs directly
[pandora-kernel.git] / fs / gfs2 / rgrp.c
index 88d5b75..96bd6d7 100644 (file)
@@ -329,17 +329,16 @@ static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
 
 struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk)
 {
-       struct rb_node **newn, *parent = NULL;
+       struct rb_node **newn;
+       struct gfs2_rgrpd *cur;
 
        spin_lock(&sdp->sd_rindex_spin);
        newn = &sdp->sd_rindex_tree.rb_node;
        while (*newn) {
-               struct gfs2_rgrpd *cur = rb_entry(*newn, struct gfs2_rgrpd,
-                                                 rd_node);
-               parent = *newn;
+               cur = rb_entry(*newn, struct gfs2_rgrpd, rd_node);
                if (blk < cur->rd_addr)
                        newn = &((*newn)->rb_left);
-               else if (blk > cur->rd_data0 + cur->rd_data)
+               else if (blk >= cur->rd_data0 + cur->rd_data)
                        newn = &((*newn)->rb_right);
                else {
                        spin_unlock(&sdp->sd_rindex_spin);
@@ -882,24 +881,21 @@ struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip)
 /**
  * try_rgrp_fit - See if a given reservation will fit in a given RG
  * @rgd: the RG data
- * @al: the struct gfs2_alloc structure describing the reservation
+ * @ip: the inode
  *
  * If there's room for the requested blocks to be allocated from the RG:
- *   Sets the $al_rgd field in @al.
  *
  * Returns: 1 on success (it fits), 0 on failure (it doesn't fit)
  */
 
-static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
+static int try_rgrp_fit(const struct gfs2_rgrpd *rgd, const struct gfs2_inode *ip)
 {
+       const struct gfs2_alloc *al = ip->i_alloc;
+
        if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR))
                return 0;
-
-       if (rgd->rd_free_clone >= al->al_requested) {
-               al->al_rgd = rgd;
+       if (rgd->rd_free_clone >= al->al_requested)
                return 1;
-       }
-
        return 0;
 }
 
@@ -985,7 +981,10 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
        int error, rg_locked;
        int loops = 0;
 
-       rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal);
+       if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal))
+               rgd = begin = ip->i_rgd;
+       else
+               rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal);
 
        if (rgd == NULL)
                return -EBADSLT;
@@ -1002,8 +1001,10 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
                }
                switch (error) {
                case 0:
-                       if (try_rgrp_fit(rgd, al))
+                       if (try_rgrp_fit(rgd, ip)) {
+                               ip->i_rgd = rgd;
                                return 0;
+                       }
                        if (rgd->rd_flags & GFS2_RDF_CHECK)
                                try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
                        if (!rg_locked)
@@ -1014,7 +1015,6 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
                        if (rgd == begin)
                                loops++;
                        break;
-
                default:
                        return error;
                }
@@ -1024,14 +1024,13 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
 }
 
 /**
- * gfs2_inplace_reserve_i - Reserve space in the filesystem
+ * gfs2_inplace_reserve - Reserve space in the filesystem
  * @ip: the inode to reserve space for
  *
  * Returns: errno
  */
 
-int gfs2_inplace_reserve_i(struct gfs2_inode *ip,
-                          char *file, unsigned int line)
+int gfs2_inplace_reserve(struct gfs2_inode *ip)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = ip->i_alloc;
@@ -1042,30 +1041,22 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip,
        if (gfs2_assert_warn(sdp, al->al_requested))
                return -EINVAL;
 
-try_again:
        do {
                error = get_local_rgrp(ip, &last_unlinked);
-               /* If there is no space, flushing the log may release some */
-               if (error) {
-                       if (ip == GFS2_I(sdp->sd_rindex) &&
-                           !sdp->sd_rindex_uptodate) {
-                               error = gfs2_ri_update(ip);
-                               if (error)
-                                       return error;
-                               goto try_again;
-                       }
-                       gfs2_log_flush(sdp, NULL);
+               if (error != -ENOSPC)
+                       break;
+               /* Check that fs hasn't grown if writing to rindex */
+               if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) {
+                       error = gfs2_ri_update(ip);
+                       if (error)
+                               break;
+                       continue;
                }
-       } while (error && tries++ < 3);
-
-       if (error)
-               return error;
+               /* Flushing the log may release space */
+               gfs2_log_flush(sdp, NULL);
+       } while (tries++ < 3);
 
-       /* no error, so we have the rgrp set in the inode's allocation. */
-       al->al_file = file;
-       al->al_line = line;
-
-       return 0;
+       return error;
 }
 
 /**
@@ -1077,16 +1068,8 @@ try_again:
 
 void gfs2_inplace_release(struct gfs2_inode *ip)
 {
-       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_alloc *al = ip->i_alloc;
 
-       if (gfs2_assert_warn(sdp, al->al_alloced <= al->al_requested) == -1)
-               fs_warn(sdp, "al_alloced = %u, al_requested = %u "
-                            "al_file = %s, al_line = %u\n",
-                            al->al_alloced, al->al_requested, al->al_file,
-                            al->al_line);
-
-       al->al_rgd = NULL;
        if (al->al_rgd_gh.gh_gl)
                gfs2_glock_dq_uninit(&al->al_rgd_gh);
 }
@@ -1339,7 +1322,7 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
        if (al == NULL)
                return -ECANCELED;
 
-       rgd = al->al_rgd;
+       rgd = ip->i_rgd;
 
        if (rgrp_contains_block(rgd, ip->i_goal))
                goal = ip->i_goal - rgd->rd_data0;
@@ -1354,7 +1337,7 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
 
        rgd->rd_last_alloc = blk;
        block = rgd->rd_data0 + blk;
-       ip->i_goal = block;
+       ip->i_goal = block + *n - 1;
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error == 0) {
                struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
@@ -1398,7 +1381,7 @@ int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_alloc *al = dip->i_alloc;
-       struct gfs2_rgrpd *rgd = al->al_rgd;
+       struct gfs2_rgrpd *rgd = dip->i_rgd;
        u32 blk;
        u64 block;
        unsigned int n = 1;
@@ -1568,7 +1551,7 @@ fail:
 
 /**
  * gfs2_rlist_add - add a RG to a list of RGs
- * @sdp: the filesystem
+ * @ip: the inode
  * @rlist: the list of resource groups
  * @block: the block
  *
@@ -1578,9 +1561,10 @@ fail:
  *
  */
 
-void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
+void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,
                    u64 block)
 {
+       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_rgrpd *rgd;
        struct gfs2_rgrpd **tmp;
        unsigned int new_space;
@@ -1589,12 +1573,15 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
        if (gfs2_assert_warn(sdp, !rlist->rl_ghs))
                return;
 
-       rgd = gfs2_blk2rgrpd(sdp, block);
+       if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, block))
+               rgd = ip->i_rgd;
+       else
+               rgd = gfs2_blk2rgrpd(sdp, block);
        if (!rgd) {
-               if (gfs2_consist(sdp))
-                       fs_err(sdp, "block = %llu\n", (unsigned long long)block);
+               fs_err(sdp, "rlist_add: no rgrp for block %llu\n", (unsigned long long)block);
                return;
        }
+       ip->i_rgd = rgd;
 
        for (x = 0; x < rlist->rl_rgrps; x++)
                if (rlist->rl_rgd[x] == rgd)