Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/fs/ocfs2/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 196 kB image not shown  

Quelle  alloc.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * alloc.c
 *
 * Extent allocs and frees
 *
 * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
 */


#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/swap.h>
#include <linux/quotaops.h>
#include <linux/blkdev.h>
#include <linux/sched/signal.h>

#include <cluster/masklog.h>

#include "ocfs2.h"

#include "alloc.h"
#include "aops.h"
#include "blockcheck.h"
#include "dlmglue.h"
#include "extent_map.h"
#include "inode.h"
#include "journal.h"
#include "localalloc.h"
#include "suballoc.h"
#include "sysfile.h"
#include "file.h"
#include "super.h"
#include "uptodate.h"
#include "xattr.h"
#include "refcounttree.h"
#include "ocfs2_trace.h"

#include "buffer_head_io.h"

enum ocfs2_contig_type {
 CONTIG_NONE = 0,
 CONTIG_LEFT,
 CONTIG_RIGHT,
 CONTIG_LEFTRIGHT,
};

static enum ocfs2_contig_type
 ocfs2_extent_rec_contig(struct super_block *sb,
    struct ocfs2_extent_rec *ext,
    struct ocfs2_extent_rec *insert_rec);
/*
 * Operations for a specific extent tree type.
 *
 * To implement an on-disk btree (extent tree) type in ocfs2, add
 * an ocfs2_extent_tree_operations structure and the matching
 * ocfs2_init_<thingy>_extent_tree() function.  That's pretty much it
 * for the allocation portion of the extent tree.
 */

struct ocfs2_extent_tree_operations {
 /*
 * last_eb_blk is the block number of the right most leaf extent
 * block.  Most on-disk structures containing an extent tree store
 * this value for fast access.  The ->eo_set_last_eb_blk() and
 * ->eo_get_last_eb_blk() operations access this value.  They are
 *  both required.
 */

 void (*eo_set_last_eb_blk)(struct ocfs2_extent_tree *et,
       u64 blkno);
 u64 (*eo_get_last_eb_blk)(struct ocfs2_extent_tree *et);

 /*
 * The on-disk structure usually keeps track of how many total
 * clusters are stored in this extent tree.  This function updates
 * that value.  new_clusters is the delta, and must be
 * added to the total.  Required.
 */

 void (*eo_update_clusters)(struct ocfs2_extent_tree *et,
       u32 new_clusters);

 /*
 * If this extent tree is supported by an extent map, insert
 * a record into the map.
 */

 void (*eo_extent_map_insert)(struct ocfs2_extent_tree *et,
         struct ocfs2_extent_rec *rec);

 /*
 * If this extent tree is supported by an extent map, truncate the
 * map to clusters,
 */

 void (*eo_extent_map_truncate)(struct ocfs2_extent_tree *et,
           u32 clusters);

 /*
 * If ->eo_insert_check() exists, it is called before rec is
 * inserted into the extent tree.  It is optional.
 */

 int (*eo_insert_check)(struct ocfs2_extent_tree *et,
          struct ocfs2_extent_rec *rec);
 int (*eo_sanity_check)(struct ocfs2_extent_tree *et);

 /*
 * --------------------------------------------------------------
 * The remaining are internal to ocfs2_extent_tree and don't have
 * accessor functions
 */


 /*
 * ->eo_fill_root_el() takes et->et_object and sets et->et_root_el.
 * It is required.
 */

 void (*eo_fill_root_el)(struct ocfs2_extent_tree *et);

 /*
 * ->eo_fill_max_leaf_clusters sets et->et_max_leaf_clusters if
 * it exists.  If it does not, et->et_max_leaf_clusters is set
 * to 0 (unlimited).  Optional.
 */

 void (*eo_fill_max_leaf_clusters)(struct ocfs2_extent_tree *et);

 /*
 * ->eo_extent_contig test whether the 2 ocfs2_extent_rec
 * are contiguous or not. Optional. Don't need to set it if use
 * ocfs2_extent_rec as the tree leaf.
 */

 enum ocfs2_contig_type
  (*eo_extent_contig)(struct ocfs2_extent_tree *et,
        struct ocfs2_extent_rec *ext,
        struct ocfs2_extent_rec *insert_rec);
};


/*
 * Pre-declare ocfs2_dinode_et_ops so we can use it as a sanity check
 * in the methods.
 */

static u64 ocfs2_dinode_get_last_eb_blk(struct ocfs2_extent_tree *et);
static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
      u64 blkno);
static void ocfs2_dinode_update_clusters(struct ocfs2_extent_tree *et,
      u32 clusters);
static void ocfs2_dinode_extent_map_insert(struct ocfs2_extent_tree *et,
        struct ocfs2_extent_rec *rec);
static void ocfs2_dinode_extent_map_truncate(struct ocfs2_extent_tree *et,
          u32 clusters);
static int ocfs2_dinode_insert_check(struct ocfs2_extent_tree *et,
         struct ocfs2_extent_rec *rec);
static int ocfs2_dinode_sanity_check(struct ocfs2_extent_tree *et);
static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et);

static int ocfs2_reuse_blk_from_dealloc(handle_t *handle,
     struct ocfs2_extent_tree *et,
     struct buffer_head **new_eb_bh,
     int blk_wanted, int *blk_given);
static int ocfs2_is_dealloc_empty(struct ocfs2_extent_tree *et);

static const struct ocfs2_extent_tree_operations ocfs2_dinode_et_ops = {
 .eo_set_last_eb_blk = ocfs2_dinode_set_last_eb_blk,
 .eo_get_last_eb_blk = ocfs2_dinode_get_last_eb_blk,
 .eo_update_clusters = ocfs2_dinode_update_clusters,
 .eo_extent_map_insert = ocfs2_dinode_extent_map_insert,
 .eo_extent_map_truncate = ocfs2_dinode_extent_map_truncate,
 .eo_insert_check = ocfs2_dinode_insert_check,
 .eo_sanity_check = ocfs2_dinode_sanity_check,
 .eo_fill_root_el = ocfs2_dinode_fill_root_el,
};

static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
      u64 blkno)
{
 struct ocfs2_dinode *di = et->et_object;

 BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
 di->i_last_eb_blk = cpu_to_le64(blkno);
}

static u64 ocfs2_dinode_get_last_eb_blk(struct ocfs2_extent_tree *et)
{
 struct ocfs2_dinode *di = et->et_object;

 BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
 return le64_to_cpu(di->i_last_eb_blk);
}

static void ocfs2_dinode_update_clusters(struct ocfs2_extent_tree *et,
      u32 clusters)
{
 struct ocfs2_inode_info *oi = cache_info_to_inode(et->et_ci);
 struct ocfs2_dinode *di = et->et_object;

 le32_add_cpu(&di->i_clusters, clusters);
 spin_lock(&oi->ip_lock);
 oi->ip_clusters = le32_to_cpu(di->i_clusters);
 spin_unlock(&oi->ip_lock);
}

static void ocfs2_dinode_extent_map_insert(struct ocfs2_extent_tree *et,
        struct ocfs2_extent_rec *rec)
{
 struct inode *inode = &cache_info_to_inode(et->et_ci)->vfs_inode;

 ocfs2_extent_map_insert_rec(inode, rec);
}

static void ocfs2_dinode_extent_map_truncate(struct ocfs2_extent_tree *et,
          u32 clusters)
{
 struct inode *inode = &cache_info_to_inode(et->et_ci)->vfs_inode;

 ocfs2_extent_map_trunc(inode, clusters);
}

static int ocfs2_dinode_insert_check(struct ocfs2_extent_tree *et,
         struct ocfs2_extent_rec *rec)
{
 struct ocfs2_inode_info *oi = cache_info_to_inode(et->et_ci);
 struct ocfs2_super *osb = OCFS2_SB(oi->vfs_inode.i_sb);

 BUG_ON(oi->ip_dyn_features & OCFS2_INLINE_DATA_FL);
 mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
   (oi->ip_clusters != le32_to_cpu(rec->e_cpos)),
   "Device %s, asking for sparse allocation: inode %llu, "
   "cpos %u, clusters %u\n",
   osb->dev_str,
   (unsigned long long)oi->ip_blkno,
   rec->e_cpos, oi->ip_clusters);

 return 0;
}

static int ocfs2_dinode_sanity_check(struct ocfs2_extent_tree *et)
{
 struct ocfs2_dinode *di = et->et_object;

 BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
 BUG_ON(!OCFS2_IS_VALID_DINODE(di));

 return 0;
}

static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et)
{
 struct ocfs2_dinode *di = et->et_object;

 et->et_root_el = &di->id2.i_list;
}


static void ocfs2_xattr_value_fill_root_el(struct ocfs2_extent_tree *et)
{
 struct ocfs2_xattr_value_buf *vb = et->et_object;

 et->et_root_el = &vb->vb_xv->xr_list;
}

static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
           u64 blkno)
{
 struct ocfs2_xattr_value_buf *vb = et->et_object;

 vb->vb_xv->xr_last_eb_blk = cpu_to_le64(blkno);
}

static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
{
 struct ocfs2_xattr_value_buf *vb = et->et_object;

 return le64_to_cpu(vb->vb_xv->xr_last_eb_blk);
}

static void ocfs2_xattr_value_update_clusters(struct ocfs2_extent_tree *et,
           u32 clusters)
{
 struct ocfs2_xattr_value_buf *vb = et->et_object;

 le32_add_cpu(&vb->vb_xv->xr_clusters, clusters);
}

static const struct ocfs2_extent_tree_operations ocfs2_xattr_value_et_ops = {
 .eo_set_last_eb_blk = ocfs2_xattr_value_set_last_eb_blk,
 .eo_get_last_eb_blk = ocfs2_xattr_value_get_last_eb_blk,
 .eo_update_clusters = ocfs2_xattr_value_update_clusters,
 .eo_fill_root_el = ocfs2_xattr_value_fill_root_el,
};

static void ocfs2_xattr_tree_fill_root_el(struct ocfs2_extent_tree *et)
{
 struct ocfs2_xattr_block *xb = et->et_object;

 et->et_root_el = &xb->xb_attrs.xb_root.xt_list;
}

static void ocfs2_xattr_tree_fill_max_leaf_clusters(struct ocfs2_extent_tree *et)
{
 struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
 et->et_max_leaf_clusters =
  ocfs2_clusters_for_bytes(sb, OCFS2_MAX_XATTR_TREE_LEAF_SIZE);
}

static void ocfs2_xattr_tree_set_last_eb_blk(struct ocfs2_extent_tree *et,
          u64 blkno)
{
 struct ocfs2_xattr_block *xb = et->et_object;
 struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;

 xt->xt_last_eb_blk = cpu_to_le64(blkno);
}

static u64 ocfs2_xattr_tree_get_last_eb_blk(struct ocfs2_extent_tree *et)
{
 struct ocfs2_xattr_block *xb = et->et_object;
 struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;

 return le64_to_cpu(xt->xt_last_eb_blk);
}

static void ocfs2_xattr_tree_update_clusters(struct ocfs2_extent_tree *et,
          u32 clusters)
{
 struct ocfs2_xattr_block *xb = et->et_object;

 le32_add_cpu(&xb->xb_attrs.xb_root.xt_clusters, clusters);
}

static const struct ocfs2_extent_tree_operations ocfs2_xattr_tree_et_ops = {
 .eo_set_last_eb_blk = ocfs2_xattr_tree_set_last_eb_blk,
 .eo_get_last_eb_blk = ocfs2_xattr_tree_get_last_eb_blk,
 .eo_update_clusters = ocfs2_xattr_tree_update_clusters,
 .eo_fill_root_el = ocfs2_xattr_tree_fill_root_el,
 .eo_fill_max_leaf_clusters = ocfs2_xattr_tree_fill_max_leaf_clusters,
};

static void ocfs2_dx_root_set_last_eb_blk(struct ocfs2_extent_tree *et,
       u64 blkno)
{
 struct ocfs2_dx_root_block *dx_root = et->et_object;

 dx_root->dr_last_eb_blk = cpu_to_le64(blkno);
}

static u64 ocfs2_dx_root_get_last_eb_blk(struct ocfs2_extent_tree *et)
{
 struct ocfs2_dx_root_block *dx_root = et->et_object;

 return le64_to_cpu(dx_root->dr_last_eb_blk);
}

static void ocfs2_dx_root_update_clusters(struct ocfs2_extent_tree *et,
       u32 clusters)
{
 struct ocfs2_dx_root_block *dx_root = et->et_object;

 le32_add_cpu(&dx_root->dr_clusters, clusters);
}

static int ocfs2_dx_root_sanity_check(struct ocfs2_extent_tree *et)
{
 struct ocfs2_dx_root_block *dx_root = et->et_object;

 BUG_ON(!OCFS2_IS_VALID_DX_ROOT(dx_root));

 return 0;
}

static void ocfs2_dx_root_fill_root_el(struct ocfs2_extent_tree *et)
{
 struct ocfs2_dx_root_block *dx_root = et->et_object;

 et->et_root_el = &dx_root->dr_list;
}

static const struct ocfs2_extent_tree_operations ocfs2_dx_root_et_ops = {
 .eo_set_last_eb_blk = ocfs2_dx_root_set_last_eb_blk,
 .eo_get_last_eb_blk = ocfs2_dx_root_get_last_eb_blk,
 .eo_update_clusters = ocfs2_dx_root_update_clusters,
 .eo_sanity_check = ocfs2_dx_root_sanity_check,
 .eo_fill_root_el = ocfs2_dx_root_fill_root_el,
};

static void ocfs2_refcount_tree_fill_root_el(struct ocfs2_extent_tree *et)
{
 struct ocfs2_refcount_block *rb = et->et_object;

 et->et_root_el = &rb->rf_list;
}

static void ocfs2_refcount_tree_set_last_eb_blk(struct ocfs2_extent_tree *et,
      u64 blkno)
{
 struct ocfs2_refcount_block *rb = et->et_object;

 rb->rf_last_eb_blk = cpu_to_le64(blkno);
}

static u64 ocfs2_refcount_tree_get_last_eb_blk(struct ocfs2_extent_tree *et)
{
 struct ocfs2_refcount_block *rb = et->et_object;

 return le64_to_cpu(rb->rf_last_eb_blk);
}

static void ocfs2_refcount_tree_update_clusters(struct ocfs2_extent_tree *et,
      u32 clusters)
{
 struct ocfs2_refcount_block *rb = et->et_object;

 le32_add_cpu(&rb->rf_clusters, clusters);
}

static enum ocfs2_contig_type
ocfs2_refcount_tree_extent_contig(struct ocfs2_extent_tree *et,
      struct ocfs2_extent_rec *ext,
      struct ocfs2_extent_rec *insert_rec)
{
 return CONTIG_NONE;
}

static const struct ocfs2_extent_tree_operations ocfs2_refcount_tree_et_ops = {
 .eo_set_last_eb_blk = ocfs2_refcount_tree_set_last_eb_blk,
 .eo_get_last_eb_blk = ocfs2_refcount_tree_get_last_eb_blk,
 .eo_update_clusters = ocfs2_refcount_tree_update_clusters,
 .eo_fill_root_el = ocfs2_refcount_tree_fill_root_el,
 .eo_extent_contig = ocfs2_refcount_tree_extent_contig,
};

static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
         struct ocfs2_caching_info *ci,
         struct buffer_head *bh,
         ocfs2_journal_access_func access,
         void *obj,
         const struct ocfs2_extent_tree_operations *ops)
{
 et->et_ops = ops;
 et->et_root_bh = bh;
 et->et_ci = ci;
 et->et_root_journal_access = access;
 if (!obj)
  obj = (void *)bh->b_data;
 et->et_object = obj;
 et->et_dealloc = NULL;

 et->et_ops->eo_fill_root_el(et);
 if (!et->et_ops->eo_fill_max_leaf_clusters)
  et->et_max_leaf_clusters = 0;
 else
  et->et_ops->eo_fill_max_leaf_clusters(et);
}

void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
       struct ocfs2_caching_info *ci,
       struct buffer_head *bh)
{
 __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_di,
     NULL, &ocfs2_dinode_et_ops);
}

void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
           struct ocfs2_caching_info *ci,
           struct buffer_head *bh)
{
 __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_xb,
     NULL, &ocfs2_xattr_tree_et_ops);
}

void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
     struct ocfs2_caching_info *ci,
     struct ocfs2_xattr_value_buf *vb)
{
 __ocfs2_init_extent_tree(et, ci, vb->vb_bh, vb->vb_access, vb,
     &ocfs2_xattr_value_et_ops);
}

void ocfs2_init_dx_root_extent_tree(struct ocfs2_extent_tree *et,
        struct ocfs2_caching_info *ci,
        struct buffer_head *bh)
{
 __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_dr,
     NULL, &ocfs2_dx_root_et_ops);
}

void ocfs2_init_refcount_extent_tree(struct ocfs2_extent_tree *et,
         struct ocfs2_caching_info *ci,
         struct buffer_head *bh)
{
 __ocfs2_init_extent_tree(et, ci, bh, ocfs2_journal_access_rb,
     NULL, &ocfs2_refcount_tree_et_ops);
}

static inline void ocfs2_et_set_last_eb_blk(struct ocfs2_extent_tree *et,
         u64 new_last_eb_blk)
{
 et->et_ops->eo_set_last_eb_blk(et, new_last_eb_blk);
}

static inline u64 ocfs2_et_get_last_eb_blk(struct ocfs2_extent_tree *et)
{
 return et->et_ops->eo_get_last_eb_blk(et);
}

static inline void ocfs2_et_update_clusters(struct ocfs2_extent_tree *et,
         u32 clusters)
{
 et->et_ops->eo_update_clusters(et, clusters);
}

static inline void ocfs2_et_extent_map_insert(struct ocfs2_extent_tree *et,
           struct ocfs2_extent_rec *rec)
{
 if (et->et_ops->eo_extent_map_insert)
  et->et_ops->eo_extent_map_insert(et, rec);
}

static inline void ocfs2_et_extent_map_truncate(struct ocfs2_extent_tree *et,
      u32 clusters)
{
 if (et->et_ops->eo_extent_map_truncate)
  et->et_ops->eo_extent_map_truncate(et, clusters);
}

static inline int ocfs2_et_root_journal_access(handle_t *handle,
            struct ocfs2_extent_tree *et,
            int type)
{
 return et->et_root_journal_access(handle, et->et_ci, et->et_root_bh,
       type);
}

static inline enum ocfs2_contig_type
 ocfs2_et_extent_contig(struct ocfs2_extent_tree *et,
          struct ocfs2_extent_rec *rec,
          struct ocfs2_extent_rec *insert_rec)
{
 if (et->et_ops->eo_extent_contig)
  return et->et_ops->eo_extent_contig(et, rec, insert_rec);

 return ocfs2_extent_rec_contig(
    ocfs2_metadata_cache_get_super(et->et_ci),
    rec, insert_rec);
}

static inline int ocfs2_et_insert_check(struct ocfs2_extent_tree *et,
     struct ocfs2_extent_rec *rec)
{
 int ret = 0;

 if (et->et_ops->eo_insert_check)
  ret = et->et_ops->eo_insert_check(et, rec);
 return ret;
}

static inline int ocfs2_et_sanity_check(struct ocfs2_extent_tree *et)
{
 int ret = 0;

 if (et->et_ops->eo_sanity_check)
  ret = et->et_ops->eo_sanity_check(et);
 return ret;
}

static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
      struct ocfs2_extent_block *eb);
static void ocfs2_adjust_rightmost_records(handle_t *handle,
        struct ocfs2_extent_tree *et,
        struct ocfs2_path *path,
        struct ocfs2_extent_rec *insert_rec);
/*
 * Reset the actual path elements so that we can reuse the structure
 * to build another path. Generally, this involves freeing the buffer
 * heads.
 */

void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root)
{
 int i, start = 0, depth = 0;
 struct ocfs2_path_item *node;

 if (keep_root)
  start = 1;

 for(i = start; i < path_num_items(path); i++) {
  node = &path->p_node[i];

  brelse(node->bh);
  node->bh = NULL;
  node->el = NULL;
 }

 /*
 * Tree depth may change during truncate, or insert. If we're
 * keeping the root extent list, then make sure that our path
 * structure reflects the proper depth.
 */

 if (keep_root)
  depth = le16_to_cpu(path_root_el(path)->l_tree_depth);
 else
  path_root_access(path) = NULL;

 path->p_tree_depth = depth;
}

void ocfs2_free_path(struct ocfs2_path *path)
{
 if (path) {
  ocfs2_reinit_path(path, 0);
  kfree(path);
 }
}

/*
 * All the elements of src into dest. After this call, src could be freed
 * without affecting dest.
 *
 * Both paths should have the same root. Any non-root elements of dest
 * will be freed.
 */

static void ocfs2_cp_path(struct ocfs2_path *dest, struct ocfs2_path *src)
{
 int i;

 BUG_ON(path_root_bh(dest) != path_root_bh(src));
 BUG_ON(path_root_el(dest) != path_root_el(src));
 BUG_ON(path_root_access(dest) != path_root_access(src));

 ocfs2_reinit_path(dest, 1);

 for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
  dest->p_node[i].bh = src->p_node[i].bh;
  dest->p_node[i].el = src->p_node[i].el;

  if (dest->p_node[i].bh)
   get_bh(dest->p_node[i].bh);
 }
}

/*
 * Make the *dest path the same as src and re-initialize src path to
 * have a root only.
 */

static void ocfs2_mv_path(struct ocfs2_path *dest, struct ocfs2_path *src)
{
 int i;

 BUG_ON(path_root_bh(dest) != path_root_bh(src));
 BUG_ON(path_root_access(dest) != path_root_access(src));

 for(i = 1; i < OCFS2_MAX_PATH_DEPTH; i++) {
  brelse(dest->p_node[i].bh);

  dest->p_node[i].bh = src->p_node[i].bh;
  dest->p_node[i].el = src->p_node[i].el;

  src->p_node[i].bh = NULL;
  src->p_node[i].el = NULL;
 }
}

/*
 * Insert an extent block at given index.
 *
 * This will not take an additional reference on eb_bh.
 */

static inline void ocfs2_path_insert_eb(struct ocfs2_path *path, int index,
     struct buffer_head *eb_bh)
{
 struct ocfs2_extent_block *eb = (struct ocfs2_extent_block *)eb_bh->b_data;

 /*
 * Right now, no root bh is an extent block, so this helps
 * catch code errors with dinode trees. The assertion can be
 * safely removed if we ever need to insert extent block
 * structures at the root.
 */

 BUG_ON(index == 0);

 path->p_node[index].bh = eb_bh;
 path->p_node[index].el = &eb->h_list;
}

static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
      struct ocfs2_extent_list *root_el,
      ocfs2_journal_access_func access)
{
 struct ocfs2_path *path;

 BUG_ON(le16_to_cpu(root_el->l_tree_depth) >= OCFS2_MAX_PATH_DEPTH);

 path = kzalloc(sizeof(*path), GFP_NOFS);
 if (path) {
  path->p_tree_depth = le16_to_cpu(root_el->l_tree_depth);
  get_bh(root_bh);
  path_root_bh(path) = root_bh;
  path_root_el(path) = root_el;
  path_root_access(path) = access;
 }

 return path;
}

struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path)
{
 return ocfs2_new_path(path_root_bh(path), path_root_el(path),
         path_root_access(path));
}

struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et)
{
 return ocfs2_new_path(et->et_root_bh, et->et_root_el,
         et->et_root_journal_access);
}

/*
 * Journal the buffer at depth idx.  All idx>0 are extent_blocks,
 * otherwise it's the root_access function.
 *
 * I don't like the way this function's name looks next to
 * ocfs2_journal_access_path(), but I don't have a better one.
 */

int ocfs2_path_bh_journal_access(handle_t *handle,
     struct ocfs2_caching_info *ci,
     struct ocfs2_path *path,
     int idx)
{
 ocfs2_journal_access_func access = path_root_access(path);

 if (!access)
  access = ocfs2_journal_access;

 if (idx)
  access = ocfs2_journal_access_eb;

 return access(handle, ci, path->p_node[idx].bh,
        OCFS2_JOURNAL_ACCESS_WRITE);
}

/*
 * Convenience function to journal all components in a path.
 */

int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
         handle_t *handle,
         struct ocfs2_path *path)
{
 int i, ret = 0;

 if (!path)
  goto out;

 for(i = 0; i < path_num_items(path); i++) {
  ret = ocfs2_path_bh_journal_access(handle, ci, path, i);
  if (ret < 0) {
   mlog_errno(ret);
   goto out;
  }
 }

out:
 return ret;
}

/*
 * Return the index of the extent record which contains cluster #v_cluster.
 * -1 is returned if it was not found.
 *
 * Should work fine on interior and exterior nodes.
 */

int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster)
{
 int ret = -1;
 int i;
 struct ocfs2_extent_rec *rec;
 u32 rec_end, rec_start, clusters;

 for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
  rec = &el->l_recs[i];

  rec_start = le32_to_cpu(rec->e_cpos);
  clusters = ocfs2_rec_clusters(el, rec);

  rec_end = rec_start + clusters;

  if (v_cluster >= rec_start && v_cluster < rec_end) {
   ret = i;
   break;
  }
 }

 return ret;
}

/*
 * NOTE: ocfs2_block_extent_contig(), ocfs2_extents_adjacent() and
 * ocfs2_extent_rec_contig only work properly against leaf nodes!
 */

static int ocfs2_block_extent_contig(struct super_block *sb,
         struct ocfs2_extent_rec *ext,
         u64 blkno)
{
 u64 blk_end = le64_to_cpu(ext->e_blkno);

 blk_end += ocfs2_clusters_to_blocks(sb,
        le16_to_cpu(ext->e_leaf_clusters));

 return blkno == blk_end;
}

static int ocfs2_extents_adjacent(struct ocfs2_extent_rec *left,
      struct ocfs2_extent_rec *right)
{
 u32 left_range;

 left_range = le32_to_cpu(left->e_cpos) +
  le16_to_cpu(left->e_leaf_clusters);

 return (left_range == le32_to_cpu(right->e_cpos));
}

static enum ocfs2_contig_type
 ocfs2_extent_rec_contig(struct super_block *sb,
    struct ocfs2_extent_rec *ext,
    struct ocfs2_extent_rec *insert_rec)
{
 u64 blkno = le64_to_cpu(insert_rec->e_blkno);

 /*
 * Refuse to coalesce extent records with different flag
 * fields - we don't want to mix unwritten extents with user
 * data.
 */

 if (ext->e_flags != insert_rec->e_flags)
  return CONTIG_NONE;

 if (ocfs2_extents_adjacent(ext, insert_rec) &&
     ocfs2_block_extent_contig(sb, ext, blkno))
   return CONTIG_RIGHT;

 blkno = le64_to_cpu(ext->e_blkno);
 if (ocfs2_extents_adjacent(insert_rec, ext) &&
     ocfs2_block_extent_contig(sb, insert_rec, blkno))
  return CONTIG_LEFT;

 return CONTIG_NONE;
}

/*
 * NOTE: We can have pretty much any combination of contiguousness and
 * appending.
 *
 * The usefulness of APPEND_TAIL is more in that it lets us know that
 * we'll have to update the path to that leaf.
 */

enum ocfs2_append_type {
 APPEND_NONE = 0,
 APPEND_TAIL,
};

enum ocfs2_split_type {
 SPLIT_NONE = 0,
 SPLIT_LEFT,
 SPLIT_RIGHT,
};

struct ocfs2_insert_type {
 enum ocfs2_split_type ins_split;
 enum ocfs2_append_type ins_appending;
 enum ocfs2_contig_type ins_contig;
 int   ins_contig_index;
 int   ins_tree_depth;
};

struct ocfs2_merge_ctxt {
 enum ocfs2_contig_type c_contig_type;
 int   c_has_empty_extent;
 int   c_split_covers_rec;
};

static int ocfs2_validate_extent_block(struct super_block *sb,
           struct buffer_head *bh)
{
 int rc;
 struct ocfs2_extent_block *eb =
  (struct ocfs2_extent_block *)bh->b_data;

 trace_ocfs2_validate_extent_block((unsigned long long)bh->b_blocknr);

 BUG_ON(!buffer_uptodate(bh));

 /*
 * If the ecc fails, we return the error but otherwise
 * leave the filesystem running.  We know any error is
 * local to this block.
 */

 rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &eb->h_check);
 if (rc) {
  mlog(ML_ERROR, "Checksum failed for extent block %llu\n",
       (unsigned long long)bh->b_blocknr);
  return rc;
 }

 /*
 * Errors after here are fatal.
 */


 if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
  rc = ocfs2_error(sb,
     "Extent block #%llu has bad signature %.*s\n",
     (unsigned long long)bh->b_blocknr, 7,
     eb->h_signature);
  goto bail;
 }

 if (le64_to_cpu(eb->h_blkno) != bh->b_blocknr) {
  rc = ocfs2_error(sb,
     "Extent block #%llu has an invalid h_blkno of %llu\n",
     (unsigned long long)bh->b_blocknr,
     (unsigned long long)le64_to_cpu(eb->h_blkno));
  goto bail;
 }

 if (le32_to_cpu(eb->h_fs_generation) != OCFS2_SB(sb)->fs_generation)
  rc = ocfs2_error(sb,
     "Extent block #%llu has an invalid h_fs_generation of #%u\n",
     (unsigned long long)bh->b_blocknr,
     le32_to_cpu(eb->h_fs_generation));
bail:
 return rc;
}

int ocfs2_read_extent_block(struct ocfs2_caching_info *ci, u64 eb_blkno,
       struct buffer_head **bh)
{
 int rc;
 struct buffer_head *tmp = *bh;

 rc = ocfs2_read_block(ci, eb_blkno, &tmp,
         ocfs2_validate_extent_block);

 /* If ocfs2_read_block() got us a new bh, pass it up. */
 if (!rc && !*bh)
  *bh = tmp;

 return rc;
}


/*
 * How many free extents have we got before we need more meta data?
 */

int ocfs2_num_free_extents(struct ocfs2_extent_tree *et)
{
 int retval;
 struct ocfs2_extent_list *el = NULL;
 struct ocfs2_extent_block *eb;
 struct buffer_head *eb_bh = NULL;
 u64 last_eb_blk = 0;

 el = et->et_root_el;
 last_eb_blk = ocfs2_et_get_last_eb_blk(et);

 if (last_eb_blk) {
  retval = ocfs2_read_extent_block(et->et_ci, last_eb_blk,
       &eb_bh);
  if (retval < 0) {
   mlog_errno(retval);
   goto bail;
  }
  eb = (struct ocfs2_extent_block *) eb_bh->b_data;
  el = &eb->h_list;
 }

 if (el->l_tree_depth != 0) {
  retval = ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
    "Owner %llu has leaf extent block %llu with an invalid l_tree_depth of %u\n",
    (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
    (unsigned long long)last_eb_blk,
    le16_to_cpu(el->l_tree_depth));
  goto bail;
 }

 retval = le16_to_cpu(el->l_count) - le16_to_cpu(el->l_next_free_rec);
bail:
 brelse(eb_bh);

 trace_ocfs2_num_free_extents(retval);
 return retval;
}

/* expects array to already be allocated
 *
 * sets h_signature, h_blkno, h_suballoc_bit, h_suballoc_slot, and
 * l_count for you
 */

static int ocfs2_create_new_meta_bhs(handle_t *handle,
         struct ocfs2_extent_tree *et,
         int wanted,
         struct ocfs2_alloc_context *meta_ac,
         struct buffer_head *bhs[])
{
 int count, status, i;
 u16 suballoc_bit_start;
 u32 num_got;
 u64 suballoc_loc, first_blkno;
 struct ocfs2_super *osb =
  OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));
 struct ocfs2_extent_block *eb;

 count = 0;
 while (count < wanted) {
  status = ocfs2_claim_metadata(handle,
           meta_ac,
           wanted - count,
           &suballoc_loc,
           &suballoc_bit_start,
           &num_got,
           &first_blkno);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }

  for(i = count;  i < (num_got + count); i++) {
   bhs[i] = sb_getblk(osb->sb, first_blkno);
   if (bhs[i] == NULL) {
    status = -ENOMEM;
    mlog_errno(status);
    goto bail;
   }
   ocfs2_set_new_buffer_uptodate(et->et_ci, bhs[i]);

   status = ocfs2_journal_access_eb(handle, et->et_ci,
        bhs[i],
        OCFS2_JOURNAL_ACCESS_CREATE);
   if (status < 0) {
    mlog_errno(status);
    goto bail;
   }

   memset(bhs[i]->b_data, 0, osb->sb->s_blocksize);
   eb = (struct ocfs2_extent_block *) bhs[i]->b_data;
   /* Ok, setup the minimal stuff here. */
   strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
   eb->h_blkno = cpu_to_le64(first_blkno);
   eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
   eb->h_suballoc_slot =
    cpu_to_le16(meta_ac->ac_alloc_slot);
   eb->h_suballoc_loc = cpu_to_le64(suballoc_loc);
   eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
   eb->h_list.l_count =
    cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));

   suballoc_bit_start++;
   first_blkno++;

   /* We'll also be dirtied by the caller, so
 * this isn't absolutely necessary. */

   ocfs2_journal_dirty(handle, bhs[i]);
  }

  count += num_got;
 }

 status = 0;
bail:
 if (status < 0) {
  for(i = 0; i < wanted; i++) {
   brelse(bhs[i]);
   bhs[i] = NULL;
  }
 }
 return status;
}

/*
 * Helper function for ocfs2_add_branch() and ocfs2_shift_tree_depth().
 *
 * Returns the sum of the rightmost extent rec logical offset and
 * cluster count.
 *
 * ocfs2_add_branch() uses this to determine what logical cluster
 * value should be populated into the leftmost new branch records.
 *
 * ocfs2_shift_tree_depth() uses this to determine the # clusters
 * value for the new topmost tree record.
 */

static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list  *el)
{
 int i;

 i = le16_to_cpu(el->l_next_free_rec) - 1;

 return le32_to_cpu(el->l_recs[i].e_cpos) +
  ocfs2_rec_clusters(el, &el->l_recs[i]);
}

/*
 * Change range of the branches in the right most path according to the leaf
 * extent block's rightmost record.
 */

static int ocfs2_adjust_rightmost_branch(handle_t *handle,
      struct ocfs2_extent_tree *et)
{
 int status;
 struct ocfs2_path *path = NULL;
 struct ocfs2_extent_list *el;
 struct ocfs2_extent_rec *rec;

 path = ocfs2_new_path_from_et(et);
 if (!path) {
  status = -ENOMEM;
  return status;
 }

 status = ocfs2_find_path(et->et_ci, path, UINT_MAX);
 if (status < 0) {
  mlog_errno(status);
  goto out;
 }

 status = ocfs2_extend_trans(handle, path_num_items(path));
 if (status < 0) {
  mlog_errno(status);
  goto out;
 }

 status = ocfs2_journal_access_path(et->et_ci, handle, path);
 if (status < 0) {
  mlog_errno(status);
  goto out;
 }

 el = path_leaf_el(path);
 rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1];

 ocfs2_adjust_rightmost_records(handle, et, path, rec);

out:
 ocfs2_free_path(path);
 return status;
}

/*
 * Add an entire tree branch to our inode. eb_bh is the extent block
 * to start at, if we don't want to start the branch at the root
 * structure.
 *
 * last_eb_bh is required as we have to update it's next_leaf pointer
 * for the new last extent block.
 *
 * the new branch will be 'empty' in the sense that every block will
 * contain a single record with cluster count == 0.
 */

static int ocfs2_add_branch(handle_t *handle,
       struct ocfs2_extent_tree *et,
       struct buffer_head *eb_bh,
       struct buffer_head **last_eb_bh,
       struct ocfs2_alloc_context *meta_ac)
{
 int status, new_blocks, i, block_given = 0;
 u64 next_blkno, new_last_eb_blk;
 struct buffer_head *bh;
 struct buffer_head **new_eb_bhs = NULL;
 struct ocfs2_extent_block *eb;
 struct ocfs2_extent_list  *eb_el;
 struct ocfs2_extent_list  *el;
 u32 new_cpos, root_end;

 BUG_ON(!last_eb_bh || !*last_eb_bh);

 if (eb_bh) {
  eb = (struct ocfs2_extent_block *) eb_bh->b_data;
  el = &eb->h_list;
 } else
  el = et->et_root_el;

 /* we never add a branch to a leaf. */
 BUG_ON(!el->l_tree_depth);

 new_blocks = le16_to_cpu(el->l_tree_depth);

 eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
 new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
 root_end = ocfs2_sum_rightmost_rec(et->et_root_el);

 /*
 * If there is a gap before the root end and the real end
 * of the rightmost leaf block, we need to remove the gap
 * between new_cpos and root_end first so that the tree
 * is consistent after we add a new branch(it will start
 * from new_cpos).
 */

 if (root_end > new_cpos) {
  trace_ocfs2_adjust_rightmost_branch(
   (unsigned long long)
   ocfs2_metadata_cache_owner(et->et_ci),
   root_end, new_cpos);

  status = ocfs2_adjust_rightmost_branch(handle, et);
  if (status) {
   mlog_errno(status);
   goto bail;
  }
 }

 /* allocate the number of new eb blocks we need */
 new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *),
        GFP_KERNEL);
 if (!new_eb_bhs) {
  status = -ENOMEM;
  mlog_errno(status);
  goto bail;
 }

 /* Firstyly, try to reuse dealloc since we have already estimated how
 * many extent blocks we may use.
 */

 if (!ocfs2_is_dealloc_empty(et)) {
  status = ocfs2_reuse_blk_from_dealloc(handle, et,
            new_eb_bhs, new_blocks,
            &block_given);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }
 }

 BUG_ON(block_given > new_blocks);

 if (block_given < new_blocks) {
  BUG_ON(!meta_ac);
  status = ocfs2_create_new_meta_bhs(handle, et,
         new_blocks - block_given,
         meta_ac,
         &new_eb_bhs[block_given]);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }
 }

 /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
 * linked with the rest of the tree.
 * conversely, new_eb_bhs[0] is the new bottommost leaf.
 *
 * when we leave the loop, new_last_eb_blk will point to the
 * newest leaf, and next_blkno will point to the topmost extent
 * block. */

 next_blkno = new_last_eb_blk = 0;
 for(i = 0; i < new_blocks; i++) {
  bh = new_eb_bhs[i];
  eb = (struct ocfs2_extent_block *) bh->b_data;
  /* ocfs2_create_new_meta_bhs() should create it right! */
  BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));
  eb_el = &eb->h_list;

  status = ocfs2_journal_access_eb(handle, et->et_ci, bh,
       OCFS2_JOURNAL_ACCESS_CREATE);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }

  eb->h_next_leaf_blk = 0;
  eb_el->l_tree_depth = cpu_to_le16(i);
  eb_el->l_next_free_rec = cpu_to_le16(1);
  /*
 * This actually counts as an empty extent as
 * c_clusters == 0
 */

  eb_el->l_recs[0].e_cpos = cpu_to_le32(new_cpos);
  eb_el->l_recs[0].e_blkno = cpu_to_le64(next_blkno);
  /*
 * eb_el isn't always an interior node, but even leaf
 * nodes want a zero'd flags and reserved field so
 * this gets the whole 32 bits regardless of use.
 */

  eb_el->l_recs[0].e_int_clusters = cpu_to_le32(0);
  if (!eb_el->l_tree_depth)
   new_last_eb_blk = le64_to_cpu(eb->h_blkno);

  ocfs2_journal_dirty(handle, bh);
  next_blkno = le64_to_cpu(eb->h_blkno);
 }

 /* This is a bit hairy. We want to update up to three blocks
 * here without leaving any of them in an inconsistent state
 * in case of error. We don't have to worry about
 * journal_dirty erroring as it won't unless we've aborted the
 * handle (in which case we would never be here) so reserving
 * the write with journal_access is all we need to do. */

 status = ocfs2_journal_access_eb(handle, et->et_ci, *last_eb_bh,
      OCFS2_JOURNAL_ACCESS_WRITE);
 if (status < 0) {
  mlog_errno(status);
  goto bail;
 }
 status = ocfs2_et_root_journal_access(handle, et,
           OCFS2_JOURNAL_ACCESS_WRITE);
 if (status < 0) {
  mlog_errno(status);
  goto bail;
 }
 if (eb_bh) {
  status = ocfs2_journal_access_eb(handle, et->et_ci, eb_bh,
       OCFS2_JOURNAL_ACCESS_WRITE);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }
 }

 /* Link the new branch into the rest of the tree (el will
 * either be on the root_bh, or the extent block passed in. */

 i = le16_to_cpu(el->l_next_free_rec);
 el->l_recs[i].e_blkno = cpu_to_le64(next_blkno);
 el->l_recs[i].e_cpos = cpu_to_le32(new_cpos);
 el->l_recs[i].e_int_clusters = 0;
 le16_add_cpu(&el->l_next_free_rec, 1);

 /* fe needs a new last extent block pointer, as does the
 * next_leaf on the previously last-extent-block. */

 ocfs2_et_set_last_eb_blk(et, new_last_eb_blk);

 eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
 eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);

 ocfs2_journal_dirty(handle, *last_eb_bh);
 ocfs2_journal_dirty(handle, et->et_root_bh);
 if (eb_bh)
  ocfs2_journal_dirty(handle, eb_bh);

 /*
 * Some callers want to track the rightmost leaf so pass it
 * back here.
 */

 brelse(*last_eb_bh);
 get_bh(new_eb_bhs[0]);
 *last_eb_bh = new_eb_bhs[0];

 status = 0;
bail:
 if (new_eb_bhs) {
  for (i = 0; i < new_blocks; i++)
   brelse(new_eb_bhs[i]);
  kfree(new_eb_bhs);
 }

 return status;
}

/*
 * adds another level to the allocation tree.
 * returns back the new extent block so you can add a branch to it
 * after this call.
 */

static int ocfs2_shift_tree_depth(handle_t *handle,
      struct ocfs2_extent_tree *et,
      struct ocfs2_alloc_context *meta_ac,
      struct buffer_head **ret_new_eb_bh)
{
 int status, i, block_given = 0;
 u32 new_clusters;
 struct buffer_head *new_eb_bh = NULL;
 struct ocfs2_extent_block *eb;
 struct ocfs2_extent_list  *root_el;
 struct ocfs2_extent_list  *eb_el;

 if (!ocfs2_is_dealloc_empty(et)) {
  status = ocfs2_reuse_blk_from_dealloc(handle, et,
            &new_eb_bh, 1,
            &block_given);
 } else if (meta_ac) {
  status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac,
         &new_eb_bh);

 } else {
  BUG();
 }

 if (status < 0) {
  mlog_errno(status);
  goto bail;
 }

 eb = (struct ocfs2_extent_block *) new_eb_bh->b_data;
 /* ocfs2_create_new_meta_bhs() should create it right! */
 BUG_ON(!OCFS2_IS_VALID_EXTENT_BLOCK(eb));

 eb_el = &eb->h_list;
 root_el = et->et_root_el;

 status = ocfs2_journal_access_eb(handle, et->et_ci, new_eb_bh,
      OCFS2_JOURNAL_ACCESS_CREATE);
 if (status < 0) {
  mlog_errno(status);
  goto bail;
 }

 /* copy the root extent list data into the new extent block */
 eb_el->l_tree_depth = root_el->l_tree_depth;
 eb_el->l_next_free_rec = root_el->l_next_free_rec;
 for (i = 0; i < le16_to_cpu(root_el->l_next_free_rec); i++)
  eb_el->l_recs[i] = root_el->l_recs[i];

 ocfs2_journal_dirty(handle, new_eb_bh);

 status = ocfs2_et_root_journal_access(handle, et,
           OCFS2_JOURNAL_ACCESS_WRITE);
 if (status < 0) {
  mlog_errno(status);
  goto bail;
 }

 new_clusters = ocfs2_sum_rightmost_rec(eb_el);

 /* update root_bh now */
 le16_add_cpu(&root_el->l_tree_depth, 1);
 root_el->l_recs[0].e_cpos = 0;
 root_el->l_recs[0].e_blkno = eb->h_blkno;
 root_el->l_recs[0].e_int_clusters = cpu_to_le32(new_clusters);
 for (i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
  memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
 root_el->l_next_free_rec = cpu_to_le16(1);

 /* If this is our 1st tree depth shift, then last_eb_blk
 * becomes the allocated extent block */

 if (root_el->l_tree_depth == cpu_to_le16(1))
  ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));

 ocfs2_journal_dirty(handle, et->et_root_bh);

 *ret_new_eb_bh = new_eb_bh;
 new_eb_bh = NULL;
 status = 0;
bail:
 brelse(new_eb_bh);

 return status;
}

/*
 * Should only be called when there is no space left in any of the
 * leaf nodes. What we want to do is find the lowest tree depth
 * non-leaf extent block with room for new records. There are three
 * valid results of this search:
 *
 * 1) a lowest extent block is found, then we pass it back in
 *    *lowest_eb_bh and return '0'
 *
 * 2) the search fails to find anything, but the root_el has room. We
 *    pass NULL back in *lowest_eb_bh, but still return '0'
 *
 * 3) the search fails to find anything AND the root_el is full, in
 *    which case we return > 0
 *
 * return status < 0 indicates an error.
 */

static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et,
        struct buffer_head **target_bh)
{
 int status = 0, i;
 u64 blkno;
 struct ocfs2_extent_block *eb;
 struct ocfs2_extent_list  *el;
 struct buffer_head *bh = NULL;
 struct buffer_head *lowest_bh = NULL;

 *target_bh = NULL;

 el = et->et_root_el;

 while(le16_to_cpu(el->l_tree_depth) > 1) {
  if (le16_to_cpu(el->l_next_free_rec) == 0) {
   status = ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
     "Owner %llu has empty extent list (next_free_rec == 0)\n",
     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
   goto bail;
  }
  i = le16_to_cpu(el->l_next_free_rec) - 1;
  blkno = le64_to_cpu(el->l_recs[i].e_blkno);
  if (!blkno) {
   status = ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
     "Owner %llu has extent list where extent # %d has no physical block start\n",
     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), i);
   goto bail;
  }

  brelse(bh);
  bh = NULL;

  status = ocfs2_read_extent_block(et->et_ci, blkno, &bh);
  if (status < 0) {
   mlog_errno(status);
   goto bail;
  }

  eb = (struct ocfs2_extent_block *) bh->b_data;
  el = &eb->h_list;

  if (le16_to_cpu(el->l_next_free_rec) <
      le16_to_cpu(el->l_count)) {
   brelse(lowest_bh);
   lowest_bh = bh;
   get_bh(lowest_bh);
  }
 }

 /* If we didn't find one and the fe doesn't have any room,
 * then return '1' */

 el = et->et_root_el;
 if (!lowest_bh && (el->l_next_free_rec == el->l_count))
  status = 1;

 *target_bh = lowest_bh;
bail:
 brelse(bh);

 return status;
}

/*
 * Grow a b-tree so that it has more records.
 *
 * We might shift the tree depth in which case existing paths should
 * be considered invalid.
 *
 * Tree depth after the grow is returned via *final_depth.
 *
 * *last_eb_bh will be updated by ocfs2_add_branch().
 */

static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et,
      int *final_depth, struct buffer_head **last_eb_bh,
      struct ocfs2_alloc_context *meta_ac)
{
 int ret, shift;
 struct ocfs2_extent_list *el = et->et_root_el;
 int depth = le16_to_cpu(el->l_tree_depth);
 struct buffer_head *bh = NULL;

 BUG_ON(meta_ac == NULL && ocfs2_is_dealloc_empty(et));

 shift = ocfs2_find_branch_target(et, &bh);
 if (shift < 0) {
  ret = shift;
  mlog_errno(ret);
  goto out;
 }

 /* We traveled all the way to the bottom of the allocation tree
 * and didn't find room for any more extents - we need to add
 * another tree level */

 if (shift) {
  BUG_ON(bh);
  trace_ocfs2_grow_tree(
   (unsigned long long)
   ocfs2_metadata_cache_owner(et->et_ci),
   depth);

  /* ocfs2_shift_tree_depth will return us a buffer with
 * the new extent block (so we can pass that to
 * ocfs2_add_branch). */

  ret = ocfs2_shift_tree_depth(handle, et, meta_ac, &bh);
  if (ret < 0) {
   mlog_errno(ret);
   goto out;
  }
  depth++;
  if (depth == 1) {
   /*
 * Special case: we have room now if we shifted from
 * tree_depth 0, so no more work needs to be done.
 *
 * We won't be calling add_branch, so pass
 * back *last_eb_bh as the new leaf. At depth
 * zero, it should always be null so there's
 * no reason to brelse.
 */

   BUG_ON(*last_eb_bh);
   get_bh(bh);
   *last_eb_bh = bh;
   goto out;
  }
 }

 /* call ocfs2_add_branch to add the final part of the tree with
 * the new data. */

 ret = ocfs2_add_branch(handle, et, bh, last_eb_bh,
          meta_ac);
 if (ret < 0)
  mlog_errno(ret);

out:
 if (final_depth)
  *final_depth = depth;
 brelse(bh);
 return ret;
}

/*
 * This function will discard the rightmost extent record.
 */

static void ocfs2_shift_records_right(struct ocfs2_extent_list *el)
{
 int next_free = le16_to_cpu(el->l_next_free_rec);
 int count = le16_to_cpu(el->l_count);
 unsigned int num_bytes;

 BUG_ON(!next_free);
 /* This will cause us to go off the end of our extent list. */
 BUG_ON(next_free >= count);

 num_bytes = sizeof(struct ocfs2_extent_rec) * next_free;

 memmove(&el->l_recs[1], &el->l_recs[0], num_bytes);
}

static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,
         struct ocfs2_extent_rec *insert_rec)
{
 int i, insert_index, next_free, has_empty, num_bytes;
 u32 insert_cpos = le32_to_cpu(insert_rec->e_cpos);
 struct ocfs2_extent_rec *rec;

 next_free = le16_to_cpu(el->l_next_free_rec);
 has_empty = ocfs2_is_empty_extent(&el->l_recs[0]);

 BUG_ON(!next_free);

 /* The tree code before us didn't allow enough room in the leaf. */
 BUG_ON(el->l_next_free_rec == el->l_count && !has_empty);

 /*
 * The easiest way to approach this is to just remove the
 * empty extent and temporarily decrement next_free.
 */

 if (has_empty) {
  /*
 * If next_free was 1 (only an empty extent), this
 * loop won't execute, which is fine. We still want
 * the decrement above to happen.
 */

  for(i = 0; i < (next_free - 1); i++)
   el->l_recs[i] = el->l_recs[i+1];

  next_free--;
 }

 /*
 * Figure out what the new record index should be.
 */

 for(i = 0; i < next_free; i++) {
  rec = &el->l_recs[i];

  if (insert_cpos < le32_to_cpu(rec->e_cpos))
   break;
 }
 insert_index = i;

 trace_ocfs2_rotate_leaf(insert_cpos, insert_index,
    has_empty, next_free,
    le16_to_cpu(el->l_count));

 BUG_ON(insert_index < 0);
 BUG_ON(insert_index >= le16_to_cpu(el->l_count));
 BUG_ON(insert_index > next_free);

 /*
 * No need to memmove if we're just adding to the tail.
 */

 if (insert_index != next_free) {
  BUG_ON(next_free >= le16_to_cpu(el->l_count));

  num_bytes = next_free - insert_index;
  num_bytes *= sizeof(struct ocfs2_extent_rec);
  memmove(&el->l_recs[insert_index + 1],
   &el->l_recs[insert_index],
   num_bytes);
 }

 /*
 * Either we had an empty extent, and need to re-increment or
 * there was no empty extent on a non full rightmost leaf node,
 * in which case we still need to increment.
 */

 next_free++;
 el->l_next_free_rec = cpu_to_le16(next_free);
 /*
 * Make sure none of the math above just messed up our tree.
 */

 BUG_ON(le16_to_cpu(el->l_next_free_rec) > le16_to_cpu(el->l_count));

 el->l_recs[insert_index] = *insert_rec;

}

static void ocfs2_remove_empty_extent(struct ocfs2_extent_list *el)
{
 int size, num_recs = le16_to_cpu(el->l_next_free_rec);

 BUG_ON(num_recs == 0);

 if (ocfs2_is_empty_extent(&el->l_recs[0])) {
  num_recs--;
  size = num_recs * sizeof(struct ocfs2_extent_rec);
  memmove(&el->l_recs[0], &el->l_recs[1], size);
  memset(&el->l_recs[num_recs], 0,
         sizeof(struct ocfs2_extent_rec));
  el->l_next_free_rec = cpu_to_le16(num_recs);
 }
}

/*
 * Create an empty extent record .
 *
 * l_next_free_rec may be updated.
 *
 * If an empty extent already exists do nothing.
 */

static void ocfs2_create_empty_extent(struct ocfs2_extent_list *el)
{
 int next_free = le16_to_cpu(el->l_next_free_rec);

 BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);

 if (next_free == 0)
  goto set_and_inc;

 if (ocfs2_is_empty_extent(&el->l_recs[0]))
  return;

 mlog_bug_on_msg(el->l_count == el->l_next_free_rec,
   "Asked to create an empty extent in a full list:\n"
   "count = %u, tree depth = %u",
   le16_to_cpu(el->l_count),
   le16_to_cpu(el->l_tree_depth));

 ocfs2_shift_records_right(el);

set_and_inc:
 le16_add_cpu(&el->l_next_free_rec, 1);
 memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
}

/*
 * For a rotation which involves two leaf nodes, the "root node" is
 * the lowest level tree node which contains a path to both leafs. This
 * resulting set of information can be used to form a complete "subtree"
 *
 * This function is passed two full paths from the dinode down to a
 * pair of adjacent leaves. It's task is to figure out which path
 * index contains the subtree root - this can be the root index itself
 * in a worst-case rotation.
 *
 * The array index of the subtree root is passed back.
 */

int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
       struct ocfs2_path *left,
       struct ocfs2_path *right)
{
 int i = 0;

 /*
 * Check that the caller passed in two paths from the same tree.
 */

 BUG_ON(path_root_bh(left) != path_root_bh(right));

 do {
  i++;

  /*
 * The caller didn't pass two adjacent paths.
 */

  mlog_bug_on_msg(i > left->p_tree_depth,
    "Owner %llu, left depth %u, right depth %u\n"
    "left leaf blk %llu, right leaf blk %llu\n",
    (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
    left->p_tree_depth, right->p_tree_depth,
    (unsigned long long)path_leaf_bh(left)->b_blocknr,
    (unsigned long long)path_leaf_bh(right)->b_blocknr);
 } while (left->p_node[i].bh->b_blocknr ==
   right->p_node[i].bh->b_blocknr);

 return i - 1;
}

typedef void (path_insert_t)(void *, struct buffer_head *);

/*
 * Traverse a btree path in search of cpos, starting at root_el.
 *
 * This code can be called with a cpos larger than the tree, in which
 * case it will return the rightmost path.
 */

static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
        struct ocfs2_extent_list *root_el, u32 cpos,
        path_insert_t *func, void *data)
{
 int i, ret = 0;
 u32 range;
 u64 blkno;
 struct buffer_head *bh = NULL;
 struct ocfs2_extent_block *eb;
 struct ocfs2_extent_list *el;
 struct ocfs2_extent_rec *rec;

 el = root_el;
 while (el->l_tree_depth) {
  if (unlikely(le16_to_cpu(el->l_tree_depth) >= OCFS2_MAX_PATH_DEPTH)) {
   ocfs2_error(ocfs2_metadata_cache_get_super(ci),
        "Owner %llu has invalid tree depth %u in extent list\n",
        (unsigned long long)ocfs2_metadata_cache_owner(ci),
        le16_to_cpu(el->l_tree_depth));
   ret = -EROFS;
   goto out;
  }
  if (le16_to_cpu(el->l_next_free_rec) == 0) {
   ocfs2_error(ocfs2_metadata_cache_get_super(ci),
        "Owner %llu has empty extent list at depth %u\n",
        (unsigned long long)ocfs2_metadata_cache_owner(ci),
        le16_to_cpu(el->l_tree_depth));
   ret = -EROFS;
   goto out;

  }

  for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
   rec = &el->l_recs[i];

   /*
 * In the case that cpos is off the allocation
 * tree, this should just wind up returning the
 * rightmost record.
 */

   range = le32_to_cpu(rec->e_cpos) +
    ocfs2_rec_clusters(el, rec);
   if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
       break;
  }

  blkno = le64_to_cpu(el->l_recs[i].e_blkno);
  if (blkno == 0) {
   ocfs2_error(ocfs2_metadata_cache_get_super(ci),
        "Owner %llu has bad blkno in extent list at depth %u (index %d)\n",
        (unsigned long long)ocfs2_metadata_cache_owner(ci),
        le16_to_cpu(el->l_tree_depth), i);
   ret = -EROFS;
   goto out;
  }

  brelse(bh);
  bh = NULL;
  ret = ocfs2_read_extent_block(ci, blkno, &bh);
  if (ret) {
   mlog_errno(ret);
   goto out;
  }

  eb = (struct ocfs2_extent_block *) bh->b_data;
  el = &eb->h_list;

  if (le16_to_cpu(el->l_next_free_rec) >
      le16_to_cpu(el->l_count)) {
   ocfs2_error(ocfs2_metadata_cache_get_super(ci),
        "Owner %llu has bad count in extent list at block %llu (next free=%u, count=%u)\n",
        (unsigned long long)ocfs2_metadata_cache_owner(ci),
        (unsigned long long)bh->b_blocknr,
        le16_to_cpu(el->l_next_free_rec),
        le16_to_cpu(el->l_count));
   ret = -EROFS;
   goto out;
  }

  if (func)
   func(data, bh);
 }

out:
 /*
 * Catch any trailing bh that the loop didn't handle.
 */

 brelse(bh);

 return ret;
}

/*
 * Given an initialized path (that is, it has a valid root extent
 * list), this function will traverse the btree in search of the path
 * which would contain cpos.
 *
 * The path traveled is recorded in the path structure.
 *
 * Note that this will not do any comparisons on leaf node extent
 * records, so it will work fine in the case that we just added a tree
 * branch.
 */

struct find_path_data {
 int index;
 struct ocfs2_path *path;
};
static void find_path_ins(void *data, struct buffer_head *bh)
{
 struct find_path_data *fp = data;

 get_bh(bh);
 ocfs2_path_insert_eb(fp->path, fp->index, bh);
 fp->index++;
}
int ocfs2_find_path(struct ocfs2_caching_info *ci,
      struct ocfs2_path *path, u32 cpos)
{
 struct find_path_data data;

 data.index = 1;
 data.path = path;
 return __ocfs2_find_path(ci, path_root_el(path), cpos,
     find_path_ins, &data);
}

static void find_leaf_ins(void *data, struct buffer_head *bh)
{
 struct ocfs2_extent_block *eb =(struct ocfs2_extent_block *)bh->b_data;
 struct ocfs2_extent_list *el = &eb->h_list;
 struct buffer_head **ret = data;

 /* We want to retain only the leaf block. */
 if (le16_to_cpu(el->l_tree_depth) == 0) {
  get_bh(bh);
  *ret = bh;
 }
}
/*
 * Find the leaf block in the tree which would contain cpos. No
 * checking of the actual leaf is done.
 *
 * Some paths want to call this instead of allocating a path structure
 * and calling ocfs2_find_path().
 *
 * This function doesn't handle non btree extent lists.
 */

int ocfs2_find_leaf(struct ocfs2_caching_info *ci,
      struct ocfs2_extent_list *root_el, u32 cpos,
      struct buffer_head **leaf_bh)
{
 int ret;
 struct buffer_head *bh = NULL;

 ret = __ocfs2_find_path(ci, root_el, cpos, find_leaf_ins, &bh);
 if (ret) {
  mlog_errno(ret);
  goto out;
 }

 *leaf_bh = bh;
out:
 return ret;
}

/*
 * Adjust the adjacent records (left_rec, right_rec) involved in a rotation.
 *
 * Basically, we've moved stuff around at the bottom of the tree and
 * we need to fix up the extent records above the changes to reflect
 * the new changes.
 *
 * left_rec: the record on the left.
 * right_rec: the record to the right of left_rec
 * right_child_el: is the child list pointed to by right_rec
 *
 * By definition, this only works on interior nodes.
 */

static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
      struct ocfs2_extent_rec *right_rec,
      struct ocfs2_extent_list *right_child_el)
{
 u32 left_clusters, right_end;

 /*
 * Interior nodes never have holes. Their cpos is the cpos of
 * the leftmost record in their child list. Their cluster
 * count covers the full theoretical range of their child list
 * - the range between their cpos and the cpos of the record
 * immediately to their right.
 */

 left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
 if (!ocfs2_rec_clusters(right_child_el, &right_child_el->l_recs[0])) {
  BUG_ON(right_child_el->l_tree_depth);
  BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
  left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
 }
 left_clusters -= le32_to_cpu(left_rec->e_cpos);
 left_rec->e_int_clusters = cpu_to_le32(left_clusters);

 /*
 * Calculate the rightmost cluster count boundary before
 * moving cpos - we will need to adjust clusters after
 * updating e_cpos to keep the same highest cluster count.
 */

 right_end = le32_to_cpu(right_rec->e_cpos);
 right_end += le32_to_cpu(right_rec->e_int_clusters);

 right_rec->e_cpos = left_rec->e_cpos;
 le32_add_cpu(&right_rec->e_cpos, left_clusters);

 right_end -= le32_to_cpu(right_rec->e_cpos);
 right_rec->e_int_clusters = cpu_to_le32(right_end);
}

/*
 * Adjust the adjacent root node records involved in a
 * rotation. left_el_blkno is passed in as a key so that we can easily
 * find it's index in the root list.
 */

static void ocfs2_adjust_root_records(struct ocfs2_extent_list *root_el,
          struct ocfs2_extent_list *left_el,
          struct ocfs2_extent_list *right_el,
          u64 left_el_blkno)
{
 int i;

 BUG_ON(le16_to_cpu(root_el->l_tree_depth) <=
        le16_to_cpu(left_el->l_tree_depth));

 for(i = 0; i < le16_to_cpu(root_el->l_next_free_rec) - 1; i++) {
  if (le64_to_cpu(root_el->l_recs[i].e_blkno) == left_el_blkno)
   break;
 }

 /*
 * The path walking code should have never returned a root and
 * two paths which are not adjacent.
 */

 BUG_ON(i >= (le16_to_cpu(root_el->l_next_free_rec) - 1));

 ocfs2_adjust_adjacent_records(&root_el->l_recs[i],
          &root_el->l_recs[i + 1], right_el);
}

/*
 * We've changed a leaf block (in right_path) and need to reflect that
 * change back up the subtree.
 *
 * This happens in multiple places:
 *   - When we've moved an extent record from the left path leaf to the right
 *     path leaf to make room for an empty extent in the left path leaf.
 *   - When our insert into the right path leaf is at the leftmost edge
 *     and requires an update of the path immediately to it's left. This
 *     can occur at the end of some types of rotation and appending inserts.
 *   - When we've adjusted the last extent record in the left path leaf and the
 *     1st extent record in the right path leaf during cross extent block merge.
 */

static void ocfs2_complete_edge_insert(handle_t *handle,
           struct ocfs2_path *left_path,
           struct ocfs2_path *right_path,
           int subtree_index)
{
 int i, idx;
 struct ocfs2_extent_list *el, *left_el, *right_el;
 struct ocfs2_extent_rec *left_rec, *right_rec;
 struct buffer_head *root_bh;

 /*
 * Update the counts and position values within all the
 * interior nodes to reflect the leaf rotation we just did.
 *
 * The root node is handled below the loop.
 *
 * We begin the loop with right_el and left_el pointing to the
 * leaf lists and work our way up.
 *
 * NOTE: within this loop, left_el and right_el always refer
 * to the *child* lists.
 */

 left_el = path_leaf_el(left_path);
 right_el = path_leaf_el(right_path);
 for(i = left_path->p_tree_depth - 1; i > subtree_index; i--) {
  trace_ocfs2_complete_edge_insert(i);

  /*
 * One nice property of knowing that all of these
 * nodes are below the root is that we only deal with
 * the leftmost right node record and the rightmost
 * left node record.
 */

  el = left_path->p_node[i].el;
  idx = le16_to_cpu(left_el->l_next_free_rec) - 1;
  left_rec = &el->l_recs[idx];

  el = right_path->p_node[i].el;
  right_rec = &el->l_recs[0];

  ocfs2_adjust_adjacent_records(left_rec, right_rec, right_el);

  ocfs2_journal_dirty(handle, left_path->p_node[i].bh);
  ocfs2_journal_dirty(handle, right_path->p_node[i].bh);

  /*
 * Setup our list pointers now so that the current
 * parents become children in the next iteration.
 */

  left_el = left_path->p_node[i].el;
  right_el = right_path->p_node[i].el;
 }

 /*
 * At the root node, adjust the two adjacent records which
 * begin our path to the leaves.
 */


 el = left_path->p_node[subtree_index].el;
 left_el = left_path->p_node[subtree_index + 1].el;
 right_el = right_path->p_node[subtree_index + 1].el;

 ocfs2_adjust_root_records(el, left_el, right_el,
      left_path->p_node[subtree_index + 1].bh->b_blocknr);

 root_bh = left_path->p_node[subtree_index].bh;

 ocfs2_journal_dirty(handle, root_bh);
}

static int ocfs2_rotate_subtree_right(handle_t *handle,
          struct ocfs2_extent_tree *et,
          struct ocfs2_path *left_path,
          struct ocfs2_path *right_path,
          int subtree_index)
{
 int ret, i;
 struct buffer_head *right_leaf_bh;
 struct buffer_head *left_leaf_bh = NULL;
 struct buffer_head *root_bh;
 struct ocfs2_extent_list *right_el, *left_el;
 struct ocfs2_extent_rec move_rec;

 left_leaf_bh = path_leaf_bh(left_path);
 left_el = path_leaf_el(left_path);

 if (left_el->l_next_free_rec != left_el->l_count) {
  ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
       "Inode %llu has non-full interior leaf node %llu (next free = %u)\n",
       (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
       (unsigned long long)left_leaf_bh->b_blocknr,
       le16_to_cpu(left_el->l_next_free_rec));
  return -EROFS;
 }

 /*
 * This extent block may already have an empty record, so we
 * return early if so.
 */

 if (ocfs2_is_empty_extent(&left_el->l_recs[0]))
  return 0;

 root_bh = left_path->p_node[subtree_index].bh;
 BUG_ON(root_bh != right_path->p_node[subtree_index].bh);

 ret = ocfs2_path_bh_journal_access(handle, et->et_ci, right_path,
        subtree_index);
 if (ret) {
  mlog_errno(ret);
  goto out;
 }

 for(i = subtree_index + 1; i < path_num_items(right_path); i++) {
  ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
         right_path, i);
  if (ret) {
   mlog_errno(ret);
   goto out;
  }

  ret = ocfs2_path_bh_journal_access(handle, et->et_ci,
         left_path, i);
  if (ret) {
   mlog_errno(ret);
   goto out;
  }
 }

 right_leaf_bh = path_leaf_bh(right_path);
 right_el = path_leaf_el(right_path);

 /* This is a code error, not a disk corruption. */
 mlog_bug_on_msg(!right_el->l_next_free_rec, "Inode %llu: Rotate fails "
   "because rightmost leaf block %llu is empty\n",
   (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
   (unsigned long long)right_leaf_bh->b_blocknr);

 ocfs2_create_empty_extent(right_el);

 ocfs2_journal_dirty(handle, right_leaf_bh);

 /* Do the copy now. */
 i = le16_to_cpu(left_el->l_next_free_rec) - 1;
 move_rec = left_el->l_recs[i];
 right_el->l_recs[0] = move_rec;

 /*
 * Clear out the record we just copied and shift everything
 * over, leaving an empty extent in the left leaf.
 *
 * We temporarily subtract from next_free_rec so that the
 * shift will lose the tail record (which is now defunct).
 */

 le16_add_cpu(&left_el->l_next_free_rec, -1);
 ocfs2_shift_records_right(left_el);
 memset(&left_el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
 le16_add_cpu(&left_el->l_next_free_rec, 1);

 ocfs2_journal_dirty(handle, left_leaf_bh);

 ocfs2_complete_edge_insert(handle, left_path, right_path,
       subtree_index);

out:
 return ret;
}

/*
 * Given a full path, determine what cpos value would return us a path
 * containing the leaf immediately to the left of the current one.
 *
 * Will return zero if the path passed in is already the leftmost path.
 */

int ocfs2_find_cpos_for_left_leaf(struct super_block *sb,
      struct ocfs2_path *path, u32 *cpos)
{
 int i, j, ret = 0;
 u64 blkno;
 struct ocfs2_extent_list *el;

 BUG_ON(path->p_tree_depth == 0);

 *cpos = 0;

 blkno = path_leaf_bh(path)->b_blocknr;

 /* Start at the tree node just above the leaf and work our way up. */
 i = path->p_tree_depth - 1;
 while (i >= 0) {
  el = path->p_node[i].el;

  /*
 * Find the extent record just before the one in our
 * path.
 */

  for(j = 0; j < le16_to_cpu(el->l_next_free_rec); j++) {
   if (le64_to_cpu(el->l_recs[j].e_blkno) == blkno) {
    if (j == 0) {
     if (i == 0) {
      /*
 * We've determined that the
 * path specified is already
 * the leftmost one - return a
 * cpos of zero.
 */

      goto out;
     }
     /*
 * The leftmost record points to our
 * leaf - we need to travel up the
 * tree one level.
 */

     goto next_node;
    }

    *cpos = le32_to_cpu(el->l_recs[j - 1].e_cpos);
    *cpos = *cpos + ocfs2_rec_clusters(el,
          &el->l_recs[j - 1]);
    *cpos = *cpos - 1;
    goto out;
   }
  }

  /*
 * If we got here, we never found a valid node where
 * the tree indicated one should be.
 */

  ocfs2_error(sb, "Invalid extent tree at extent block %llu\n",
       (unsigned long long)blkno);
  ret = -EROFS;
  goto out;

next_node:
  blkno = path->p_node[i].bh->b_blocknr;
  i--;
 }

out:
 return ret;
}

/*
 * Extend the transaction by enough credits to complete the rotation,
 * and still leave at least the original number of credits allocated
 * to this transaction.
 */

static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth,
        int op_credits,
        struct ocfs2_path *path)
{
 int ret = 0;
 int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits;

 if (jbd2_handle_buffer_credits(handle) < credits)
  ret = ocfs2_extend_trans(handle,
    credits - jbd2_handle_buffer_credits(handle));

 return ret;
}

/*
 * Trap the case where we're inserting into the theoretical range past
 * the _actual_ left leaf range. Otherwise, we'll rotate a record
 * whose cpos is less than ours into the right leaf.
 *
 * It's only necessary to look at the rightmost record of the left
 * leaf because the logic that calls us should ensure that the
 * theoretical ranges in the path components above the leaves are
 * correct.
 */

static int ocfs2_rotate_requires_path_adjustment(struct ocfs2_path *left_path,
       u32 insert_cpos)
{
 struct ocfs2_extent_list *left_el;
 struct ocfs2_extent_rec *rec;
 int next_free;

 left_el = path_leaf_el(left_path);
 next_free = le16_to_cpu(left_el->l_next_free_rec);
 rec = &left_el->l_recs[next_free - 1];

 if (insert_cpos > le32_to_cpu(rec->e_cpos))
  return 1;
 return 0;
}

static int ocfs2_leftmost_rec_contains(struct ocfs2_extent_list *el, u32 cpos)
{
 int next_free = le16_to_cpu(el->l_next_free_rec);
 unsigned int range;
 struct ocfs2_extent_rec *rec;

 if (next_free == 0)
  return 0;

 rec = &el->l_recs[0];
 if (ocfs2_is_empty_extent(rec)) {
  /* Empty list. */
  if (next_free == 1)
   return 0;
  rec = &el->l_recs[1];
 }

 range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
 if (cpos >= le32_to_cpu(rec->e_cpos) && cpos < range)
  return 1;
 return 0;
}

/*
 * Rotate all the records in a btree right one record, starting at insert_cpos.
 *
 * The path to the rightmost leaf should be passed in.
 *
 * The array is assumed to be large enough to hold an entire path (tree depth).
 *
 * Upon successful return from this function:
 *
 * - The 'right_path' array will contain a path to the leaf block
 *   whose range contains e_cpos.
 * - That leaf block will have a single empty extent in list index 0.
 * - In the case that the rotation requires a post-insert update,
 *   *ret_left_path will contain a valid path which can be passed to
 *   ocfs2_insert_path().
 */

static int ocfs2_rotate_tree_right(handle_t *handle,
       struct ocfs2_extent_tree *et,
       enum ocfs2_split_type split,
       u32 insert_cpos,
       struct ocfs2_path *right_path,
       struct ocfs2_path **ret_left_path)
{
 int ret, start, orig_credits = jbd2_handle_buffer_credits(handle);
 u32 cpos;
 struct ocfs2_path *left_path = NULL;
 struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);

 *ret_left_path = NULL;

 left_path = ocfs2_new_path_from_path(right_path);
 if (!left_path) {
  ret = -ENOMEM;
  mlog_errno(ret);
  goto out;
 }

 ret = ocfs2_find_cpos_for_left_leaf(sb, right_path, &cpos);
 if (ret) {
  mlog_errno(ret);
  goto out;
 }

 trace_ocfs2_rotate_tree_right(
  (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
  insert_cpos, cpos);

 /*
 * What we want to do here is:
 *
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=88 G=91

¤ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.