/fs/ocfs2/alloc.c
C | 6079 lines | 4928 code | 1109 blank | 42 comment | 781 complexity | 34cfb83c6db173800841d0da37a34953 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * alloc.c
- *
- * Extent allocs and frees
- *
- * Copyright (C) 2002, 2004 Oracle. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- */
- #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 <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);
- struct ocfs2_extent_tree_operations {
- void (*eo_set_last_eb_blk)(struct ocfs2_extent_tree *et,
- u64 blkno);
- u64 (*eo_get_last_eb_blk)(struct ocfs2_extent_tree *et);
- void (*eo_update_clusters)(struct ocfs2_extent_tree *et,
- u32 new_clusters);
- void (*eo_extent_map_insert)(struct ocfs2_extent_tree *et,
- struct ocfs2_extent_rec *rec);
- void (*eo_extent_map_truncate)(struct ocfs2_extent_tree *et,
- u32 clusters);
- int (*eo_insert_check)(struct ocfs2_extent_tree *et,
- struct ocfs2_extent_rec *rec);
- int (*eo_sanity_check)(struct ocfs2_extent_tree *et);
- void (*eo_fill_root_el)(struct ocfs2_extent_tree *et);
- void (*eo_fill_max_leaf_clusters)(struct ocfs2_extent_tree *et);
- enum ocfs2_contig_type
- (*eo_extent_contig)(struct ocfs2_extent_tree *et,
- struct ocfs2_extent_rec *ext,
- struct ocfs2_extent_rec *insert_rec);
- };
- 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 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 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 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 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 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,
- 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_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);
- 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;
- }
- 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);
- }
- }
- 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);
- }
- }
- 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;
- }
- }
- 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;
- 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);
- }
- 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);
- }
- 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;
- }
- 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;
- }
- 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;
- }
- 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));
- 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;
- }
- if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
- ocfs2_error(sb,
- "Extent block #%llu has bad signature %.*s",
- (unsigned long long)bh->b_blocknr, 7,
- eb->h_signature);
- return -EINVAL;
- }
- if (le64_to_cpu(eb->h_blkno) != bh->b_blocknr) {
- ocfs2_error(sb,
- "Extent block #%llu has an invalid h_blkno "
- "of %llu",
- (unsigned long long)bh->b_blocknr,
- (unsigned long long)le64_to_cpu(eb->h_blkno));
- return -EINVAL;
- }
- if (le32_to_cpu(eb->h_fs_generation) != OCFS2_SB(sb)->fs_generation) {
- ocfs2_error(sb,
- "Extent block #%llu has an invalid "
- "h_fs_generation of #%u",
- (unsigned long long)bh->b_blocknr,
- le32_to_cpu(eb->h_fs_generation));
- return -EINVAL;
- }
- return 0;
- }
- 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 (!rc && !*bh)
- *bh = tmp;
- return rc;
- }
- int ocfs2_num_free_extents(struct ocfs2_super *osb,
- 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;
- }
- BUG_ON(el->l_tree_depth != 0);
- 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;
- }
- 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 = -EIO;
- 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;
-
- 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++;
- 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;
- }
- mlog_errno(status);
- }
- return status;
- }
- 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]);
- }
- 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;
- }
- 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;
- 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;
-
- 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 (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;
- }
- }
-
- new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *),
- GFP_KERNEL);
- if (!new_eb_bhs) {
- status = -ENOMEM;
- mlog_errno(status);
- goto bail;
- }
- status = ocfs2_create_new_meta_bhs(handle, et, new_blocks,
- meta_ac, new_eb_bhs);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
- }
- 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;
-
- 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);
- 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->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);
- }
- 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;
- }
- }
- 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);
- 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);
- 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;
- }
- 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;
- 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;
- status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac,
- &new_eb_bh);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
- }
- eb = (struct ocfs2_extent_block *) new_eb_bh->b_data;
-
- 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;
- }
-
- 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);
-
- 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 (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;
- }
- 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) {
- ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
- "Owner %llu has empty "
- "extent list (next_free_rec == 0)",
- (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci));
- status = -EIO;
- goto bail;
- }
- i = le16_to_cpu(el->l_next_free_rec) - 1;
- blkno = le64_to_cpu(el->l_recs[i].e_blkno);
- if (!blkno) {
- ocfs2_error(ocfs2_metadata_cache_get_super(et->et_ci),
- "Owner %llu has extent "
- "list where extent # %d has no physical "
- "block start",
- (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), i);
- status = -EIO;
- 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);
- }
- }
- 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;
- }
- 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);
- shift = ocfs2_find_branch_target(et, &bh);
- if (shift < 0) {
- ret = shift;
- mlog_errno(ret);
- goto out;
- }
- if (shift) {
- BUG_ON(bh);
- trace_ocfs2_grow_tree(
- (unsigned long long)
- ocfs2_metadata_cache_owner(et->et_ci),
- depth);
- ret = ocfs2_shift_tree_depth(handle, et, meta_ac, &bh);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
- depth++;
- if (depth == 1) {
- BUG_ON(*last_eb_bh);
- get_bh(bh);
- *last_eb_bh = bh;
- goto out;
- }
- }
- ret = ocfs2_add_branch(handle, et, bh, last_eb_bh,
- meta_ac);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
- out:
- if (final_depth)
- *final_depth = depth;
- brelse(bh);
- return ret;
- }
- 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);
-
- 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);
-
- BUG_ON(el->l_next_free_rec == el->l_count && !has_empty);
- if (has_empty) {
- for(i = 0; i < (next_free - 1); i++)
- el->l_recs[i] = el->l_recs[i+1];
- next_free--;
- }
- 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);
- 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);
- }
- next_free++;
- el->l_next_free_rec = cpu_to_le16(next_free);
- 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);
- }
- }
- 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));
- }
- int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
- struct ocfs2_path *left,
- struct ocfs2_path *right)
- {
- int i = 0;
- BUG_ON(path_root_bh(left) != path_root_bh(right));
- do {
- i++;
- 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 *);
- 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 (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];
- 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:
- brelse(bh);
- return ret;
- }
- 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;
-
- if (le16_to_cpu(el->l_tree_depth) == 0) {
- get_bh(bh);
- *ret = bh;
- }
- }
- 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;
- }
- static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
- struct ocfs2_extent_list *left_child_el,
- struct ocfs2_extent_rec *right_rec,
- struct ocfs2_extent_list *right_child_el)
- {
- u32 left_clusters, right_end;
- 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);
- 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);
- }
- 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;
- }
- BUG_ON(i >= (le16_to_cpu(root_el->l_next_free_rec) - 1));
- ocfs2_adjust_adjacent_records(&root_el->l_recs[i], left_el,
- &root_el->l_recs[i + 1], right_el);
- }
- 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 = left_path->p_node[subtree_index].bh;
- 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);
- 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, left_el, right_rec,
- right_el);
- ocfs2_journal_dirty(handle, left_path->p_node[i].bh);
- ocfs2_journal_dirty(handle, right_path->p_node[i].bh);
- left_el = left_path->p_node[i].el;
- right_el = right_path->p_node[i].el;
- }
- 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)",
- (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;
- }
- 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);
-
- 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);
-
- 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;
- 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;
- }
- 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;
-
- i = path->p_tree_depth - 1;
- while (i >= 0) {
- el = path->p_node[i].el;
- 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) {
- goto out;
- }
- 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;
- }
- }
- 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;
- }
- 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 (handle->h_buffer_credits < credits)
- ret = ocfs2_extend_trans(handle,
- credits - handle->h_buffer_credits);
- return ret;
- }
- 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)) {
-
- 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;
- }
- 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 = handle->h_buffer_credits;
- 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);
- while (cpos && insert_cpos <= cpos) {
- trace_ocfs2_rotate_tree_right(
- (unsigned long long)
- ocfs2_metadata_cache_owner(et->et_ci),
- insert_cpos, cpos);
- ret = ocfs2_find_path(et->et_ci, left_path, cpos);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
- mlog_bug_on_msg(path_leaf_bh(left_path) ==
- path_leaf_bh(right_path),
- "Owner %llu: error during insert of %u "
- "(left path cpos %u) results in two identical "
- "paths ending at %llu\n",
- (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
- insert_cpos, cpos,
- (unsigned long long)
- path_leaf_bh(left_path)->b_blocknr);
- if (split == SPLIT_NONE &&
- ocfs2_rotate_requires_path_adjustment(left_path,
- insert_cpos)) {
- *ret_left_path = left_path;
- goto out_ret_path;
- }
- start = ocfs2_find_subtree_root(et, left_path, right_path);
- trace_ocfs2_rotate_subtree(start,
- (unsigned long long)
- right_path->p_node[start].bh->b_blocknr,
- right_path->p_tree_depth);
- ret = ocfs2_extend_rotate_transaction(handle, start,
- orig_credits, right_path);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
- ret = ocfs2_rotate_subtree_right(handle, et, left_path,
- right_path, start);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
- if (split != SPLIT_NONE &&
- ocfs2_leftmost_rec_contains(path_leaf_el(right_path),
- insert_cpos)) {
- *ret_left_path = left_path;
- goto out_ret_path;
- }
- ocfs2_mv_path(right_path, left_path);
- ret = ocfs2_find_cpos_for_left_leaf(sb, right_path, &cpos);
- if (ret) {
- mlog_errno(ret);
- goto out;
- }
- }
- out:
- ocfs2_free_path(left_path);
- out_ret_path:
- return ret;
- }
- static int ocfs2_update_edge_lengths(handle…
Large files files are truncated, but you can click here to view the full file