summaryrefslogtreecommitdiff
path: root/fs/ocfs2/alloc.c
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2008-08-18 17:38:48 +0800
committerMark Fasheh <mfasheh@suse.com>2008-10-13 16:57:01 -0700
commitf56654c435c06f2b2bd5751889b1a08a3add7d6c (patch)
treeb186d68aedc5dda7afe435f5a68c03937ae382ff /fs/ocfs2/alloc.c
parentac11c827192272eabb68b8f4cf844066461d9690 (diff)
downloadlwn-f56654c435c06f2b2bd5751889b1a08a3add7d6c.tar.gz
lwn-f56654c435c06f2b2bd5751889b1a08a3add7d6c.zip
ocfs2: Add extent tree operation for xattr value btrees
Add some thin wrappers around ocfs2_insert_extent() for each of the 3 different btree types, ocfs2_inode_insert_extent(), ocfs2_xattr_value_insert_extent() and ocfs2_xattr_tree_insert_extent(). The last is for the xattr index btree, which will be used in a followup patch. All the old callers in file.c etc will call ocfs2_dinode_insert_extent(), while the other two handle the xattr issue. And the init of extent tree are handled by these functions. When storing xattr value which is too large, we will allocate some clusters for it and here ocfs2_extent_list and ocfs2_extent_rec will also be used. In order to re-use the b-tree operation code, a new parameter named "private" is added into ocfs2_extent_tree and it is used to indicate the root of ocfs2_exent_list. The reason is that we can't deduce the root from the buffer_head now. It may be in an inode, an ocfs2_xattr_block or even worse, in any place in an ocfs2_xattr_bucket. Signed-off-by: Tao Ma <tao.ma@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r--fs/ocfs2/alloc.c184
1 files changed, 149 insertions, 35 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index cacfc118b71c..e45421fee204 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -78,6 +78,7 @@ struct ocfs2_extent_tree {
struct ocfs2_extent_tree_operations *eops;
struct buffer_head *root_bh;
struct ocfs2_extent_list *root_el;
+ void *private;
};
static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
@@ -136,9 +137,50 @@ static struct ocfs2_extent_tree_operations ocfs2_dinode_et_ops = {
.sanity_check = ocfs2_dinode_sanity_check,
};
+static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
+ u64 blkno)
+{
+ struct ocfs2_xattr_value_root *xv =
+ (struct ocfs2_xattr_value_root *)et->private;
+
+ 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_root *xv =
+ (struct ocfs2_xattr_value_root *) et->private;
+
+ return le64_to_cpu(xv->xr_last_eb_blk);
+}
+
+static void ocfs2_xattr_value_update_clusters(struct inode *inode,
+ struct ocfs2_extent_tree *et,
+ u32 clusters)
+{
+ struct ocfs2_xattr_value_root *xv =
+ (struct ocfs2_xattr_value_root *)et->private;
+
+ le32_add_cpu(&xv->xr_clusters, clusters);
+}
+
+static int ocfs2_xattr_value_sanity_check(struct inode *inode,
+ struct ocfs2_extent_tree *et)
+{
+ return 0;
+}
+
+static struct ocfs2_extent_tree_operations ocfs2_xattr_et_ops = {
+ .set_last_eb_blk = ocfs2_xattr_value_set_last_eb_blk,
+ .get_last_eb_blk = ocfs2_xattr_value_get_last_eb_blk,
+ .update_clusters = ocfs2_xattr_value_update_clusters,
+ .sanity_check = ocfs2_xattr_value_sanity_check,
+};
+
static struct ocfs2_extent_tree*
ocfs2_new_extent_tree(struct buffer_head *bh,
- enum ocfs2_extent_tree_type et_type)
+ enum ocfs2_extent_tree_type et_type,
+ void *private)
{
struct ocfs2_extent_tree *et;
@@ -149,12 +191,16 @@ static struct ocfs2_extent_tree*
et->type = et_type;
get_bh(bh);
et->root_bh = bh;
+ et->private = private;
- /* current we only support dinode extent. */
- BUG_ON(et->type != OCFS2_DINODE_EXTENT);
if (et_type == OCFS2_DINODE_EXTENT) {
et->root_el = &((struct ocfs2_dinode *)bh->b_data)->id2.i_list;
et->eops = &ocfs2_dinode_et_ops;
+ } else if (et_type == OCFS2_XATTR_VALUE_EXTENT) {
+ struct ocfs2_xattr_value_root *xv =
+ (struct ocfs2_xattr_value_root *) private;
+ et->root_el = &xv->xr_list;
+ et->eops = &ocfs2_xattr_et_ops;
}
return et;
@@ -495,7 +541,8 @@ struct ocfs2_merge_ctxt {
int ocfs2_num_free_extents(struct ocfs2_super *osb,
struct inode *inode,
struct buffer_head *root_bh,
- enum ocfs2_extent_tree_type type)
+ enum ocfs2_extent_tree_type type,
+ void *private)
{
int retval;
struct ocfs2_extent_list *el = NULL;
@@ -517,6 +564,12 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
if (fe->i_last_eb_blk)
last_eb_blk = le64_to_cpu(fe->i_last_eb_blk);
el = &fe->id2.i_list;
+ } else if (type == OCFS2_XATTR_VALUE_EXTENT) {
+ struct ocfs2_xattr_value_root *xv =
+ (struct ocfs2_xattr_value_root *) private;
+
+ last_eb_blk = le64_to_cpu(xv->xr_last_eb_blk);
+ el = &xv->xr_list;
}
if (last_eb_blk) {
@@ -4209,33 +4262,25 @@ out:
*
* The caller needs to update fe->i_clusters
*/
-int ocfs2_insert_extent(struct ocfs2_super *osb,
- handle_t *handle,
- struct inode *inode,
- struct buffer_head *root_bh,
- u32 cpos,
- u64 start_blk,
- u32 new_clusters,
- u8 flags,
- struct ocfs2_alloc_context *meta_ac,
- enum ocfs2_extent_tree_type et_type)
+static int ocfs2_insert_extent(struct ocfs2_super *osb,
+ handle_t *handle,
+ struct inode *inode,
+ struct buffer_head *root_bh,
+ u32 cpos,
+ u64 start_blk,
+ u32 new_clusters,
+ u8 flags,
+ struct ocfs2_alloc_context *meta_ac,
+ struct ocfs2_extent_tree *et)
{
int status;
int uninitialized_var(free_records);
struct buffer_head *last_eb_bh = NULL;
struct ocfs2_insert_type insert = {0, };
struct ocfs2_extent_rec rec;
- struct ocfs2_extent_tree *et = NULL;
BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
- et = ocfs2_new_extent_tree(root_bh, et_type);
- if (!et) {
- status = -ENOMEM;
- mlog_errno(status);
- goto bail;
- }
-
mlog(0, "add %u clusters at position %u to inode %llu\n",
new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -4287,9 +4332,68 @@ bail:
if (last_eb_bh)
brelse(last_eb_bh);
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_dinode_insert_extent(struct ocfs2_super *osb,
+ handle_t *handle,
+ struct inode *inode,
+ struct buffer_head *root_bh,
+ u32 cpos,
+ u64 start_blk,
+ u32 new_clusters,
+ u8 flags,
+ struct ocfs2_alloc_context *meta_ac)
+{
+ int status;
+ struct ocfs2_extent_tree *et = NULL;
+
+ et = ocfs2_new_extent_tree(root_bh, OCFS2_DINODE_EXTENT, NULL);
+ if (!et) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_insert_extent(osb, handle, inode, root_bh,
+ cpos, start_blk, new_clusters,
+ flags, meta_ac, et);
+
if (et)
ocfs2_free_extent_tree(et);
- mlog_exit(status);
+bail:
+ return status;
+}
+
+int ocfs2_xattr_value_insert_extent(struct ocfs2_super *osb,
+ handle_t *handle,
+ struct inode *inode,
+ struct buffer_head *root_bh,
+ u32 cpos,
+ u64 start_blk,
+ u32 new_clusters,
+ u8 flags,
+ struct ocfs2_alloc_context *meta_ac,
+ void *private)
+{
+ int status;
+ struct ocfs2_extent_tree *et = NULL;
+
+ et = ocfs2_new_extent_tree(root_bh, OCFS2_XATTR_VALUE_EXTENT, private);
+ if (!et) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_insert_extent(osb, handle, inode, root_bh,
+ cpos, start_blk, new_clusters,
+ flags, meta_ac, et);
+
+ if (et)
+ ocfs2_free_extent_tree(et);
+bail:
return status;
}
@@ -4311,7 +4415,8 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
struct ocfs2_alloc_context *data_ac,
struct ocfs2_alloc_context *meta_ac,
enum ocfs2_alloc_restarted *reason_ret,
- enum ocfs2_extent_tree_type type)
+ enum ocfs2_extent_tree_type type,
+ void *private)
{
int status = 0;
int free_extents;
@@ -4325,7 +4430,8 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
if (mark_unwritten)
flags = OCFS2_EXT_UNWRITTEN;
- free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type);
+ free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type,
+ private);
if (free_extents < 0) {
status = free_extents;
mlog_errno(status);
@@ -4372,9 +4478,16 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
- status = ocfs2_insert_extent(osb, handle, inode, root_bh,
- *logical_offset, block, num_bits,
- flags, meta_ac, type);
+ if (type == OCFS2_DINODE_EXTENT)
+ status = ocfs2_dinode_insert_extent(osb, handle, inode, root_bh,
+ *logical_offset, block,
+ num_bits, flags, meta_ac);
+ else
+ status = ocfs2_xattr_value_insert_extent(osb, handle,
+ inode, root_bh,
+ *logical_offset,
+ block, num_bits, flags,
+ meta_ac, private);
if (status < 0) {
mlog_errno(status);
goto leave;
@@ -4655,7 +4768,8 @@ int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh,
handle_t *handle, u32 cpos, u32 len, u32 phys,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc,
- enum ocfs2_extent_tree_type et_type)
+ enum ocfs2_extent_tree_type et_type,
+ void *private)
{
int ret, index;
u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
@@ -4676,7 +4790,7 @@ int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh,
goto out;
}
- et = ocfs2_new_extent_tree(root_bh, et_type);
+ et = ocfs2_new_extent_tree(root_bh, et_type, private);
if (!et) {
ret = -ENOMEM;
mlog_errno(ret);
@@ -4964,7 +5078,8 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh,
u32 cpos, u32 len, handle_t *handle,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc,
- enum ocfs2_extent_tree_type et_type)
+ enum ocfs2_extent_tree_type et_type,
+ void *private)
{
int ret, index;
u32 rec_range, trunc_range;
@@ -4973,7 +5088,7 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh,
struct ocfs2_path *path = NULL;
struct ocfs2_extent_tree *et = NULL;
- et = ocfs2_new_extent_tree(root_bh, et_type);
+ et = ocfs2_new_extent_tree(root_bh, et_type, private);
if (!et) {
ret = -ENOMEM;
mlog_errno(ret);
@@ -6608,9 +6723,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
* this proves to be false, we could always re-build
* the in-inode data from our pages.
*/
- ret = ocfs2_insert_extent(osb, handle, inode, di_bh,
- 0, block, 1, 0,
- NULL, OCFS2_DINODE_EXTENT);
+ ret = ocfs2_dinode_insert_extent(osb, handle, inode, di_bh,
+ 0, block, 1, 0, NULL);
if (ret) {
mlog_errno(ret);
goto out_commit;