// 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/string.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_typeocfs2_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);Lines 1–500 of 7741. Load more
// 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/string.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);