[Ocfs2-commits] mfasheh commits r1636 - trunk/src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Wed Nov 10 16:18:59 CST 2004
Author: mfasheh
Date: 2004-11-10 16:18:57 -0600 (Wed, 10 Nov 2004)
New Revision: 1636
Removed:
trunk/src/bitmap.c
trunk/src/bitmap.h
Modified:
trunk/src/Makefile
trunk/src/alloc.c
trunk/src/alloc.h
trunk/src/dir.c
trunk/src/dir.h
trunk/src/file.c
trunk/src/file.h
trunk/src/inode.c
trunk/src/localalloc.c
trunk/src/localalloc.h
trunk/src/namei.c
trunk/src/ocfs.h
trunk/src/ocfs2_fs.h
trunk/src/ocfs_journal.h
trunk/src/proc.c
trunk/src/suballoc.c
trunk/src/suballoc.h
trunk/src/super.c
Log:
* merge the cluster-groups branch back into trunk. ocfs2-tools merge
to follow. The cluster bitmap is now a chain allocator, arranged
much like the others, expcept of course instead of block groups we
have cluster groups.
Modified: trunk/src/Makefile
===================================================================
--- trunk/src/Makefile 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/Makefile 2004-11-10 22:18:57 UTC (rev 1636)
@@ -66,7 +66,6 @@
24io.c \
alloc.c \
aops.c \
- bitmap.c \
buffer_head_io.c \
dcache.c \
dir.c \
@@ -101,7 +100,6 @@
ocfs_journal.h \
buffer_head_io.h \
alloc.h \
- bitmap.h \
dcache.h \
dir.h \
dlm.h \
Modified: trunk/src/alloc.c
===================================================================
--- trunk/src/alloc.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/alloc.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -35,7 +35,6 @@
#include "ocfs2.h"
#include "alloc.h"
-#include "bitmap.h"
#include "dlm.h"
#include "extent_map.h"
#include "inode.h"
@@ -54,13 +53,6 @@
static int ocfs_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
u64 blkno);
-static int ocfs_free_clusters(ocfs_super *osb,
- ocfs_journal_handle *handle,
- struct inode *bitmap_inode,
- struct buffer_head *bitmap_bh,
- u64 start_blk,
- unsigned int num_clusters);
-
static int ocfs_create_new_meta_bhs(ocfs_super *osb,
ocfs_journal_handle *handle,
struct inode *inode,
@@ -95,13 +87,6 @@
struct buffer_head *fe_bh,
struct buffer_head **target_bh);
-static int ocfs_claim_main_bitmap_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u32 min_bits,
- u32 *bit_off,
- u32 *num_bits);
-
static int ocfs_find_new_last_ext_blk(ocfs_super *osb,
struct inode *inode,
ocfs2_dinode *fe,
@@ -124,66 +109,6 @@
ext->e_clusters));
}
-static int ocfs_free_clusters(ocfs_super *osb,
- ocfs_journal_handle *handle,
- struct inode *bitmap_inode,
- struct buffer_head *bitmap_bh,
- u64 start_blk,
- unsigned int num_clusters)
-{
- ocfs_alloc_bm *bitmap;
- int status;
- unsigned int start_cluster, bitmap_blocks, bitmap_start;
- ocfs2_dinode *fe;
-
- LOG_ENTRY();
-
- start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk);
-
- bitmap = &osb->cluster_bitmap;
-
- bitmap_blocks = ocfs_bitmap_blocks_affected(osb->sb,
- start_cluster,
- num_clusters,
- &bitmap_start);
-
- LOG_TRACE_ARGS("want to free %u clusters starting at block %llu\n",
- num_clusters, start_blk);
- LOG_TRACE_ARGS("bitmap_start = %u, bitmap_blkno = %llu, bitmap_blocks "
- "= %u\n", bitmap_start, osb->bitmap_blkno,
- bitmap_blocks);
- status = ocfs_read_blocks(osb, (osb->bitmap_blkno + bitmap_start),
- bitmap_blocks, &bitmap->chunk[bitmap_start],
- OCFS_BH_CACHED, bitmap_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = ocfs_journal_access(handle, bitmap_inode, bitmap_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- fe = (ocfs2_dinode *) bitmap_bh->b_data;
-
- ocfs_clear_bits(osb->sb, handle, bitmap_inode, bitmap, start_cluster,
- num_clusters);
- fe->id1.bitmap1.i_used -= num_clusters;
-
- status = ocfs_journal_dirty(handle, bitmap_bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- status = 0;
-bail:
- LOG_EXIT_STATUS(status);
- return(0);
-}
-
/*
* How many free extents have we got before we need more meta data?
*/
@@ -941,287 +866,6 @@
return status;
}
-void ocfs_free_alloc_context(ocfs2_alloc_context *ac)
-{
- if (ac->ac_inode)
- iput(ac->ac_inode);
- if (ac->ac_bh)
- brelse(ac->ac_bh);
- kfree(ac);
-}
-
-/*
- * min_bits - minimum contiguous chunk from this total allocation we
- * can handle. set to what we asked for originally for a full
- * contig. allocation, set to '1' to indicate we can deal with extents
- * of any size.
- */
-int ocfs_claim_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u32 min_bits,
- u32 *bit_off,
- u32 *num_bits)
-{
- int status;
-
- LOG_ENTRY();
-
- OCFS_ASSERT(ac);
- OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
-
- OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL
- || ac->ac_which == OCFS_AC_USE_MAIN);
- OCFS_ASSERT(ac->ac_handle == handle);
-
- if (ac->ac_which == OCFS_AC_USE_LOCAL) {
- status = ocfs_claim_local_alloc_bits(osb,
- handle,
- ac,
- min_bits,
- bit_off,
- num_bits);
- } else {
- status = ocfs_claim_main_bitmap_bits(osb,
- handle,
- ac,
- min_bits,
- bit_off,
- num_bits);
- }
- if (status < 0) {
- /* If you're not asking for contiguous blocks, then
- * the reserve function should've given you enough,
- * and ENOSPC this is a real error. */
- if ((status != -ENOSPC) || (min_bits == 1))
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- ac->ac_bits_given += *num_bits;
-
-bail:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-static int ocfs_claim_main_bitmap_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u32 min_bits,
- u32 *bit_off,
- u32 *num_bits)
-{
- int status, num_blocks;
- u32 bits_wanted;
- u32 best_fit_bits;
- ocfs2_dinode *fe;
- struct inode *bitmap_inode;
- struct buffer_head *bh;
-
- LOG_ENTRY();
- OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_MAIN);
-
- bitmap_inode = ac->ac_inode;
- bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
- bh = ac->ac_bh;
- fe = (ocfs2_dinode *) bh->b_data;
-
- num_blocks = ocfs_blocks_for_bits(osb->sb,
- osb->cluster_bitmap.validbits);
- /* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
- status = ocfs_read_blocks(osb, osb->bitmap_blkno, num_blocks,
- osb->cluster_bitmap.chunk, OCFS_BH_CACHED,
- bitmap_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- best_fit_bits = bits_wanted;
- status = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
- bits_wanted, bit_off,
- &best_fit_bits);
- if (status < 0) {
- osb->cluster_bitmap.failed++;
- LOG_TRACE_STR("Running out of space!");
- goto bail;
- }
-
- if (best_fit_bits < min_bits) {
- LOG_TRACE_ARGS ("Cannot allocate %u contiguous clusters for "
- "system file\n", min_bits);
- status = -ENOSPC;
- goto bail;
- }
-
- if (best_fit_bits != bits_wanted)
- LOG_TRACE_ARGS("discontiguous allocation done: wanted = %u, "
- "best_fit = %u, bit_off = %u!\n",
- bits_wanted, best_fit_bits, *bit_off);
-
- /* when we do discontig. just change this line. */
- *num_bits = best_fit_bits;
-
- /* cool, we've got some. set them now. */
- status = ocfs_journal_access(handle, bitmap_inode, bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- fe->id1.bitmap1.i_used += *num_bits;
-
- status = ocfs_journal_dirty(handle, bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- ocfs_set_bits(osb->sb, handle, bitmap_inode, &osb->cluster_bitmap,
- *bit_off, *num_bits);
- atomic_inc(&osb->alloc_stats.bitmap_data);
-
-#warning "implement this"
- /* At this point, we should see if local alloc was switched
- * off, and turn it back on if we have enough free bits in the
- * main bitmap.*/
- status = 0;
-bail:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/* caller is responsible for freeing 'ac' when he's done with it. */
-int ocfs_reserve_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- u32 bits_wanted,
- ocfs2_alloc_context **ac)
-{
- int status;
-
- LOG_ENTRY();
- OCFS_ASSERT(handle);
-
- *ac = kmalloc(sizeof(ocfs2_alloc_context), GFP_KERNEL);
- if (!(*ac)) {
- status = -ENOMEM;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- memset(*ac, 0, sizeof(ocfs2_alloc_context));
- (*ac)->ac_bits_wanted = bits_wanted;
- (*ac)->ac_handle = handle;
-
- status = -ENOSPC;
- if (ocfs_alloc_should_use_local(osb, bits_wanted)) {
- status = ocfs_reserve_local_alloc_bits(osb,
- handle,
- bits_wanted,
- *ac);
- if ((status < 0) && (status != -ENOSPC)) {
- LOG_ERROR_STATUS(status);
- goto bail;
- } else if (status == -ENOSPC) {
-#warning "need to deal with disabling local alloc better"
- /* reserve_local_bits will return enospc with
- * the local alloc inode still locked, so we
- * can change this safely here. */
- LOG_ERROR_STR("Disabling local alloc");
- osb->have_local_alloc = 0;
-// ocfs_shutdown_local_alloc(osb);
- } else
- (*ac)->ac_which = OCFS_AC_USE_LOCAL;
- }
-
- if (status == -ENOSPC) {
- status = ocfs_reserve_main_bitmap_bits(osb,
- handle,
- bits_wanted,
- *ac);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- (*ac)->ac_which = OCFS_AC_USE_MAIN;
- }
-
- status = 0;
-bail:
- if ((status < 0) && *ac) {
- ocfs_free_alloc_context(*ac);
- *ac = NULL;
- }
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-int ocfs_reserve_main_bitmap_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- u32 bits_wanted,
- ocfs2_alloc_context *ac)
-{
- int status = 0;
- struct inode *bitmap_inode;
- struct buffer_head *bh = NULL;
- ocfs2_dinode *fe;
- u32 free_bits;
-
- LOG_ENTRY();
-
- OCFS_ASSERT(!(handle->flags & OCFS_HANDLE_STARTED));
-
- bitmap_inode = ocfs_get_system_file_inode(osb,
- GLOBAL_BITMAP_SYSTEM_INODE,
- -1);
- if (!bitmap_inode) {
- status = -EINVAL;
- LOG_ERROR_STR("Could not get bitmap inode!");
- goto bail;
- }
-
- ocfs_handle_add_inode(handle, bitmap_inode);
- status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE,
- 0, &bh, bitmap_inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE,
- 0, bitmap_inode);
-
- fe = (ocfs2_dinode *) bh->b_data;
- free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) -
- le32_to_cpu(fe->id1.bitmap1.i_used);
-
- if (bits_wanted > free_bits) {
- LOG_ERROR_ARGS("Disk Full: wanted=%u, free_bits=%u\n",
- bits_wanted, free_bits);
- status = -ENOSPC;
- goto bail;
- }
-
- /* Ok, done - we've determined that there's enough space in
- * the bitmap. Actually finding it is the job of the
- * allocation function now. We keep things locked so that the
- * bitmap can't change underneath us. */
- ac->ac_inode = igrab(bitmap_inode);
- get_bh(bh);
- ac->ac_bh = bh;
-
-bail:
- if (bitmap_inode)
- iput(bitmap_inode);
- if (bh)
- brelse(bh);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
/* This function will figure out whether the currently last extent
* block will be deleted, and if it will, what the new last extent
* block will be so we can update his h_next_leaf_blk field, as well
@@ -1466,13 +1110,10 @@
OCFS_ASSERT(!el->l_recs[0].e_clusters);
OCFS_ASSERT(!el->l_recs[0].e_cpos);
OCFS_ASSERT(!el->l_recs[0].e_blkno);
- status = ocfs_free_suballoc_bits(osb,
- handle,
+ status = ocfs2_free_extent_block(handle,
tc->tc_ext_alloc_inode,
tc->tc_ext_alloc_bh,
- eb->h_suballoc_bit,
- eb->h_blkno,
- 1);
+ eb);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -1484,7 +1125,7 @@
}
OCFS_ASSERT(delete_blk);
- status = ocfs_free_clusters(osb, handle, tc->tc_bitmap_inode,
+ status = ocfs_free_clusters(handle, tc->tc_bitmap_inode,
tc->tc_bitmap_bh, delete_blk,
clusters_to_del);
if (status < 0) {
Modified: trunk/src/alloc.h
===================================================================
--- trunk/src/alloc.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/alloc.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -34,35 +34,6 @@
u64 blkno,
u32 new_clusters,
struct _ocfs2_alloc_context *meta_ac);
-
-typedef struct _ocfs2_alloc_context {
- struct inode *ac_inode; /* which bitmap are we allocating from? */
- struct buffer_head *ac_bh; /* file entry bh */
- u32 ac_bits_wanted;
- u32 ac_bits_given;
-#define OCFS_AC_USE_LOCAL 1
-#define OCFS_AC_USE_MAIN 2
-#define OCFS_AC_USE_INODE 3
-#define OCFS_AC_USE_META 4
- u32 ac_which;
- ocfs_journal_handle *ac_handle; /* debugging mostly. */
-} ocfs2_alloc_context;
-
-void ocfs_free_alloc_context(ocfs2_alloc_context *ac);
-static inline int ocfs_alloc_context_bits_left(ocfs2_alloc_context *ac)
-{
- return(ac->ac_bits_wanted - ac->ac_bits_given);
-}
-int ocfs_reserve_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- u32 bits_wanted,
- ocfs2_alloc_context **ac);
-int ocfs_claim_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u32 min_bits,
- u32 *bit_off,
- u32 *num_bits);
int ocfs_num_free_extents(ocfs_super *osb,
struct inode *inode,
ocfs2_dinode *fe);
@@ -80,13 +51,6 @@
return(fe->id2.i_list.l_tree_depth + 2);
}
-/* This is for local alloc ONLY. Others should use the generic apis
- * above. */
-int ocfs_reserve_main_bitmap_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- u32 bits_wanted,
- ocfs2_alloc_context *ac);
-
typedef struct _ocfs2_truncate_context {
struct inode *tc_bitmap_inode;
struct buffer_head *tc_bitmap_bh;
Deleted: trunk/src/bitmap.c
===================================================================
--- trunk/src/bitmap.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/bitmap.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -1,496 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * bitmap.c
- *
- * Bitmap infrastructure code
- *
- * 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 "ocfs_compat.h"
-
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-
-#include "ocfs_log.h"
-#include "ocfs.h"
-#include "ocfs2.h"
-
-#include "alloc.h"
-#include "bitmap.h"
-#include "util.h"
-
-#include "ocfs_journal.h"
-#include "buffer_head_io.h"
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_BITMAP
-
-/*
- * ocfs_initialize_bitmap()
- *
- */
-void ocfs_initialize_bitmap(struct super_block *sb,
- ocfs_alloc_bm *bitmap, __u32 validbits,
- __u32 allocbits)
-{
- LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u, %u)\n", sb, bitmap, validbits,
- allocbits);
-
- bitmap->validbits = validbits;
- bitmap->allocbits = allocbits;
- bitmap->failed = 0;
- bitmap->ok_retries = 0;
-
- bitmap->numbh = ocfs_blocks_for_bits(sb, bitmap->allocbits);
- bitmap->chunk = ocfs_malloc(bitmap->numbh * sizeof(struct buffer_head *));
- if (!bitmap->chunk)
- BUG();
-
- memset(bitmap->chunk, 0, (bitmap->numbh * sizeof(struct buffer_head *)));
-
- LOG_EXIT ();
- return;
-} /* ocfs_initialize_bitmap */
-
-void ocfs_uninitialize_bitmap(ocfs_alloc_bm *bitmap)
-{
- int i;
-
- LOG_ENTRY();
-
- for(i = 0; i < bitmap->numbh; i++)
- if (bitmap->chunk[i])
- brelse(bitmap->chunk[i]);
-
- kfree(bitmap->chunk);
- bitmap->chunk = NULL;
- bitmap->numbh = 0;
- bitmap->validbits = 0;
- bitmap->allocbits = 0;
- bitmap->failed = 0;
- bitmap->ok_retries = 0;
-
- LOG_EXIT();
- return;
-}
-
-/* we only handle if the bitmap has grown, not shrunk. */
-void ocfs_reinitialize_bitmap(struct super_block *sb,
- ocfs_alloc_bm *bitmap, __u32 validbits,
- __u32 allocbits)
-{
- __u32 newnumbh;
- struct buffer_head **newchunk;
-
- LOG_ENTRY();
-
- if (allocbits < bitmap->allocbits)
- BUG();
-
- /* most of the time the actual alloc'd size of the bitmap file
- * won't change and we don't have to update the buffer heads
- * or the number of bhs */
- if (allocbits == bitmap->allocbits)
- goto skipbhs;
-
- newnumbh = ocfs_blocks_for_bits(sb, allocbits);
- newchunk = ocfs_malloc(bitmap->numbh * sizeof(struct buffer_head *));
-
- if (!newchunk)
- BUG();
-
- memset(newchunk, 0, (newnumbh * sizeof(struct buffer_head *)));
-
- memcpy(newchunk, bitmap->chunk, (bitmap->numbh * sizeof(struct buffer_head *)));
-
- kfree(bitmap->chunk);
-
- bitmap->numbh = newnumbh;
- bitmap->chunk = newchunk;
- bitmap->allocbits = allocbits;
-skipbhs:
- bitmap->validbits = validbits;
-
- LOG_EXIT();
-}
-
-/*
- * More or less lifted from ext3. I'll leave their description below:
- *
- * For ext3 allocations, we must not reuse any blocks which are
- * allocated in the bitmap buffer's "last committed data" copy. This
- * prevents deletes from freeing up the page for reuse until we have
- * committed the delete transaction.
- *
- * If we didn't do this, then deleting something and reallocating it as
- * data would allow the old block to be overwritten before the
- * transaction committed (because we force data to disk before commit).
- * This would lead to corruption if we crashed between overwriting the
- * data and committing the delete.
- *
- * @@@ We may want to make this allocation behaviour conditional on
- * data-writes at some point, and disable it for metadata allocations or
- * sync-data inodes.
- */
-static int ocfs_test_allocatable(int nr, struct buffer_head *bh)
-{
- if (ocfs2_test_bit(nr, (unsigned long *)bh->b_data))
- return 0;
- if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
- return 1;
- return !ocfs2_test_bit(nr, (unsigned long *)bh2jh(bh)->b_committed_data);
-}
-
-/*
- * ocfs_find_clear_bits()
- *
- * if you don't pass in best_fit_bits, we only try contig and give you
- * -ENOSPC otherwise.
- *
- * if you pass in best_fit_bits we return -ENOSPC only if we're
- * completely full, otherwise we'll always set best_fit_bits to at max
- * bits_wanted, and of course *bitoff to your starting offset.
- */
-int ocfs_find_clear_bits(ocfs_super *osb, ocfs_alloc_bm * bitmap,
- u32 bits_wanted, u32 *bitoff,
- u32 *best_fit_bits)
-{
- int status = 0;
- __u32 globalsize, globaloff, localstart, lastbh;
- __u32 size = OCFS_BITS_IN_CHUNK(osb->sb);
- __u32 count = 0;
- u32 largest_start, largest_size;
- void *buffer;
- int c;
- struct buffer_head *currbh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u)\n", osb, bitmap, bits_wanted);
-
- /* We keep track of the biggest contiguous chunk we've seen so
- * far in these two variables. If we never completely fulfull
- * the request, we can pass them back for a best try. */
- largest_start = 0;
- largest_size = 0;
-
- if (best_fit_bits)
- *best_fit_bits = 0;
-
- *bitoff = 0;
- globalsize = bitmap->validbits;
- lastbh = ocfs_blocks_for_bits(osb->sb, globalsize) - 1;
-
- globaloff = 0;
- ocfs_bitmap_block_for_off(osb->sb, globaloff, &c, &localstart);
-
- if (lastbh == 0)
- size = globalsize;
-
- currbh = bitmap->chunk[c];
-
- /*LOG_TRACE_ARGS("globalsize=%u, bitmap->validbits=%u, sysonly=%u\n",
- globalsize, bitmap->validbits, sysonly);*/
- /*LOG_TRACE_ARGS("before loop: c=%u, lastbh=%u, size=%u, "
- "localstart=%u\n", c, lastbh, size, localstart);*/
- buffer = currbh->b_data;
-
- while ((*bitoff = ocfs2_find_next_zero_bit(buffer,
- OCFS_BITS_IN_CHUNK(osb->sb),
- localstart)) != -1) {
- /*LOG_TRACE_ARGS("c=%u, globaloff=%u, *bitoff=%u, "
- "localstart=%u\n", c, globaloff, *bitoff,
- localstart);*/
-
- /* find_next_zero_bit returns:
- >= size passed in: if no zero bits in here.
- some number < size: at the next zero bit
- localstart: if the current one is a zero
- */
- if (*bitoff >= size) {
-nextbh:
- /* we've hit the end of our bh. */
- /*LOG_TRACE_ARGS("*bitoff >= size (%u)\n", *bitoff,c);*/
-
- /* if it's the last bh, then quit the loop */
- if (c == lastbh) {
- count = 0;
- LOG_TRACE_STR("Didn't find enough!");
- break;
- }
- /* otherwise, reset localstart and switch bhs
- * and continue */
- localstart = *bitoff = 0;
- c++;
- currbh = bitmap->chunk[c];
- buffer = currbh->b_data;
- if (c == lastbh)
- size = globalsize -
- (OCFS_BITS_IN_CHUNK(osb->sb)
- * lastbh);
- globaloff = c * OCFS_BITS_IN_CHUNK(osb->sb);
- continue;
- }
-
- if (!ocfs_test_allocatable(*bitoff, currbh)) {
- /* We found a zero, but we can't use it as it
- * hasn't been put to disk yet! */
- count = 0;
- localstart = *bitoff + 1;
- /* In doing this, we might go over our current bh. */
- if (localstart >= size)
- goto nextbh;
-
- globaloff =
- ocfs_bitmap_off_for_block(osb->sb, c,
- *bitoff) + 1;
- } else if (*bitoff == localstart) {
- /*LOG_TRACE_ARGS("*bitoff == localstart (%u)\n",
- *bitoff);*/
- /* cool, we have another zero! */
- count++;
- localstart++;
- globaloff++;
- } else {
- /*LOG_TRACE_ARGS("*bitoff (%u) != localstart (%u)\n",
- *bitoff, localstart);*/
- /* we had to skip over some ones */
- count = 1;
- globaloff =
- ocfs_bitmap_off_for_block(osb->sb, c,
- *bitoff) + 1;
- localstart = *bitoff + 1;
- }
-
- if (count > largest_size) {
- largest_size = count;
- largest_start = globaloff - count;
- }
-
- if (count == bits_wanted) {
- /* we've found everything we wanted. */
- LOG_TRACE_ARGS("Found it all! (count=%u)\n", count);
- buffer = NULL;
- break;
- }
- }
-
- if (count == bits_wanted) {
- *bitoff = globaloff - count;
- if (best_fit_bits)
- *best_fit_bits = bits_wanted;
- } else if (best_fit_bits && largest_size) {
-#warning "can we go off the end of the bitmap here?"
- *best_fit_bits = largest_size;
- *bitoff = largest_start;
- } else
- status = -ENOSPC;
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_find_clear_bits */
-
-/*
- * ocfs_count_bits()
- *
- */
-int ocfs_count_bits(struct super_block *sb, ocfs_alloc_bm *bitmap)
-{
- __u32 count = 0, i, j;
- struct buffer_head *currbh;
- unsigned char tmp;
- __u8 *buffer;
- int validbytes, size;
-
- LOG_ENTRY ();
-
- size = (bitmap->validbits >> 3);
- validbytes = size;
- if (validbytes > sb->s_blocksize)
- validbytes = sb->s_blocksize;
-
- for (i = 0; size > 0; size -= validbytes, i++) {
- currbh = bitmap->chunk[i];
- buffer = currbh->b_data;
- for (j = 0; j < validbytes; j++) {
- /* U-U-U-GLY */
- memcpy(&tmp, buffer, 1);
- count += BITCOUNT(tmp);
- buffer++;
- }
- }
-
- LOG_EXIT_ULONG ((unsigned long)count);
- return count;
-} /* ocfs_count_bits */
-
-#ifdef __KERNEL__
-/* HEY LOOK! These two functions are IDENTICAL except for three lines!
- * We'd never do that... no, never... */
-
-/*
- * ocfs_set_bits()
- *
- */
-void ocfs_set_bits(struct super_block *sb,
- ocfs_journal_handle *handle,
- struct inode *inode,
- ocfs_alloc_bm * bitmap,
- u32 start,
- u32 num)
-{
- struct buffer_head *currbh = NULL;
- void *buff;
- int i, local;
- int status;
-
- LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p, %u, %u)\n", sb, handle,
- bitmap, start, num);
-
- if ((start + num) > bitmap->validbits) {
- LOG_ERROR_ARGS("bitmap->validbits = %u but start = %u and " \
- "num = %u!\n", bitmap->validbits, start, num);
- goto bail;
- }
-
- ocfs_bitmap_block_for_off(sb, start, &i, &local);
- currbh = bitmap->chunk[i];
-
- status = ocfs_journal_access(handle, inode, currbh,
- OCFS_JOURNAL_ACCESS_UNDO);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- buff = currbh->b_data;
-
- while (num--) {
- ocfs2_set_bit (local++, buff);
- if ((local >= OCFS_BITS_IN_CHUNK(sb)) && (num != 0)) {
- local = 0;
- status = ocfs_journal_dirty(handle, currbh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- i++;
- currbh = bitmap->chunk[i];
-
- status = ocfs_journal_access(handle, inode, currbh,
- OCFS_JOURNAL_ACCESS_UNDO);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- buff = currbh->b_data;
- }
- }
-
- status = ocfs_journal_dirty(handle, currbh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_set_bits */
-
-/*
- * ocfs_clear_bits()
- *
- */
-void ocfs_clear_bits(struct super_block *sb,
- ocfs_journal_handle *handle,
- struct inode *inode,
- ocfs_alloc_bm *bitmap,
- u32 start,
- u32 num)
-{
- struct buffer_head *currbh = NULL;
- void *buff;
- int i, local;
- int status;
-
- LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p, %u, %u)\n", sb, handle,
- bitmap, start, num);
-
- if ((start + num) > bitmap->validbits) {
- LOG_ERROR_ARGS("bitmap->validbits = %u but start = %u and " \
- "num = %u!\n", bitmap->validbits, start, num);
- goto bail;
- }
-
- ocfs_bitmap_block_for_off(sb, start, &i, &local);
- currbh = bitmap->chunk[i];
-
- status = ocfs_journal_access(handle, inode, currbh,
- OCFS_JOURNAL_ACCESS_UNDO);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- buff = currbh->b_data;
-
- while (num--) {
- ocfs2_clear_bit (local, buff);
- ocfs2_set_bit(local,
- (unsigned long *)bh2jh(currbh)->b_committed_data);
- local++;
-
- if ((local >= OCFS_BITS_IN_CHUNK(sb)) && (num != 0)) {
- local = 0;
-
- status = ocfs_journal_dirty(handle, currbh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- i++;
- currbh = bitmap->chunk[i];
-
- status = ocfs_journal_access(handle, inode, currbh,
- OCFS_JOURNAL_ACCESS_UNDO);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- buff = currbh->b_data;
- }
- }
-
- status = ocfs_journal_dirty(handle, currbh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_clear_bits */
-
-#endif /* __KERNEL */
Deleted: trunk/src/bitmap.h
===================================================================
--- trunk/src/bitmap.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/bitmap.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -1,52 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * bitmap.h
- *
- * Function prototypes
- *
- * 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.
- */
-
-#ifndef OCFS2_BITMAP_H
-#define OCFS2_BITMAP_H
-
-int ocfs_count_bits(struct super_block *sb, ocfs_alloc_bm *bitmap);
-void ocfs_clear_bits(struct super_block *sb,
- ocfs_journal_handle *handle,
- struct inode *inode,
- ocfs_alloc_bm *bitmap,
- u32 start,
- u32 num);
-int ocfs_find_clear_bits(ocfs_super *osb, ocfs_alloc_bm * bitmap,
- u32 numBits, u32 *bitoff, u32 *best_fit_bits);
-void ocfs_initialize_bitmap(struct super_block *sb,
- ocfs_alloc_bm *bitmap, __u32 validbits,
- __u32 allocbits);
-void ocfs_reinitialize_bitmap(struct super_block *sb,
- ocfs_alloc_bm *bitmap, __u32 validbits,
- __u32 allocbits);
-void ocfs_set_bits(struct super_block *sb,
- ocfs_journal_handle *handle,
- struct inode *inode,
- ocfs_alloc_bm * bitmap,
- u32 start,
- u32 num);
-void ocfs_uninitialize_bitmap(ocfs_alloc_bm *bitmap);
-
-#endif /* OCFS2_BITMAP_H */
Modified: trunk/src/dir.c
===================================================================
--- trunk/src/dir.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/dir.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -432,7 +432,7 @@
}
}
- status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+ status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
Modified: trunk/src/dir.h
===================================================================
--- trunk/src/dir.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/dir.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -39,11 +39,12 @@
const char *name,
int namelen,
struct buffer_head **ret_de_bh);
+struct _ocfs2_alloc_context;
int ocfs_do_extend_dir(struct super_block *sb,
ocfs_journal_handle *handle,
struct inode *dir,
struct buffer_head *parent_fe_bh,
- ocfs2_alloc_context *data_ac,
- ocfs2_alloc_context *meta_ac,
+ struct _ocfs2_alloc_context *data_ac,
+ struct _ocfs2_alloc_context *meta_ac,
struct buffer_head **new_bh);
#endif /* OCFS2_DIR_H */
Modified: trunk/src/file.c
===================================================================
--- trunk/src/file.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/file.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -983,7 +983,8 @@
goto leave;
}
- status = ocfs_claim_bits(osb, handle, data_ac, 1, &bit_off, &num_bits);
+ status = ocfs_claim_clusters(osb, handle, data_ac, 1,
+ &bit_off, &num_bits);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto leave;
@@ -1146,10 +1147,10 @@
}
}
- status = ocfs_reserve_bits(osb,
- handle,
- clusters_to_add,
- &data_ac);
+ status = ocfs_reserve_clusters(osb,
+ handle,
+ clusters_to_add,
+ &data_ac);
if (status < 0) {
if (status != -ENOSPC)
LOG_ERROR_STATUS(status);
@@ -1357,7 +1358,7 @@
status = ocfs_extend_file(osb, inode, newsize);
}
if (status < 0) {
- if (status != -EINTR)
+ if (status != -EINTR && status != -ENOSPC)
LOG_ERROR_STATUS (status);
error = -ENOSPC;
goto bail;
Modified: trunk/src/file.h
===================================================================
--- trunk/src/file.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/file.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -29,6 +29,7 @@
extern struct file_operations ocfs_fops;
extern struct file_operations ocfs_dops;
extern struct inode_operations ocfs_file_iops;
+struct _ocfs2_alloc_context;
enum ocfs2_alloc_restarted {
RESTART_TRANS = 0,
@@ -39,8 +40,8 @@
u32 clusters_to_add,
struct buffer_head *fe_bh,
ocfs_journal_handle *handle,
- ocfs2_alloc_context *data_ac,
- ocfs2_alloc_context *meta_ac,
+ struct _ocfs2_alloc_context *data_ac,
+ struct _ocfs2_alloc_context *meta_ac,
enum ocfs2_alloc_restarted *reason);
int ocfs_extend_file(ocfs_super *osb,
struct inode *inode,
Modified: trunk/src/inode.c
===================================================================
--- trunk/src/inode.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/inode.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -751,9 +751,9 @@
goto bail;
}
- status = ocfs_free_suballoc_bits(osb, handle, inode_alloc_inode,
- inode_alloc_bh, fe->i_suballoc_bit,
- fe->i_blkno, 1);
+ status = ocfs2_free_dinode(handle, inode_alloc_inode,
+ inode_alloc_bh, fe);
+
if (status < 0)
LOG_ERROR_STATUS(status);
Modified: trunk/src/localalloc.c
===================================================================
--- trunk/src/localalloc.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/localalloc.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -37,7 +37,6 @@
#include "ocfs2.h"
#include "alloc.h"
-#include "bitmap.h"
#include "dlm.h"
#include "localalloc.h"
#include "suballoc.h"
@@ -125,8 +124,8 @@
if (osb->have_local_alloc
&& (ocfs2_clusters_to_bytes(osb->sb, bits) <= OCFS_LOCAL_ALLOC_MAX_ALLOC)
&& (bits <= ocfs_local_alloc_window_bits(osb)))
- return(1);
- return(0);
+ return 1;
+ return 0;
}
/*
@@ -486,15 +485,15 @@
* discontiguous space, we this turns into a really simple check of
* ->la_bits_set
*/
-int ocfs_reserve_local_alloc_bits(ocfs_super *osb,
+int ocfs_reserve_local_alloc_bits(ocfs_super *osb,
ocfs_journal_handle *passed_handle,
u32 bits_wanted,
ocfs2_alloc_context *ac)
{
int status;
- struct inode *local_alloc_inode = NULL;
- int startoff;
ocfs2_dinode *alloc;
+ struct inode *local_alloc_inode;
+ int free_bits;
LOG_ENTRY();
@@ -518,7 +517,6 @@
goto bail;
}
-#warning "isn't it about time we turned this check off?"
if (bits_wanted > ocfs2_clusters_for_bytes(osb->sb,
OCFS_LOCAL_ALLOC_MAX_ALLOC)) {
LOG_TRACE_STR("Asking for more than max local alloction!\n");
@@ -533,8 +531,13 @@
}
alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
- startoff = ocfs_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
- if (startoff == -1) {
+
+ OCFS_ASSERT(LOCAL_ALLOC(alloc)->la_bits_set ==
+ ocfs_local_alloc_count_bits(alloc));
+
+ free_bits = le16_to_cpu(LOCAL_ALLOC(alloc)->la_bm_bits) -
+ le16_to_cpu(LOCAL_ALLOC(alloc)->la_bits_set);
+ if (bits_wanted > free_bits) {
/* uhoh, window change time. */
status =
ocfs_local_alloc_slide_window(osb, local_alloc_inode);
@@ -548,7 +551,7 @@
ac->ac_inode = igrab(local_alloc_inode);
get_bh(osb->local_alloc_bh);
ac->ac_bh = osb->local_alloc_bh;
-
+ ac->ac_which = OCFS_AC_USE_LOCAL;
status = 0;
bail:
if (local_alloc_inode)
@@ -603,6 +606,8 @@
while(bits_wanted--)
ocfs2_set_bit(start++, bitmap);
+ LOCAL_ALLOC(alloc)->la_bits_set += *num_bits;
+
status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -718,6 +723,25 @@
return;
} /* ocfs_clear_local_alloc */
+#if 0
+/* turn this on and uncomment below to aid debugging window shifts. */
+static void ocfs2_verify_zero_bits(unsigned long *bitmap,
+ unsigned int start,
+ unsigned int count)
+{
+ unsigned int tmp = count;
+ while(tmp--) {
+ if (ocfs2_test_bit(start + tmp, bitmap)) {
+ printk("ocfs2_verify_zero_bits: start = %u, count = "
+ "%u\n", start, count);
+ printk("ocfs2_verify_zero_bits: bit %u is set!",
+ start + tmp);
+ BUG();
+ }
+ }
+}
+#endif
+
/*
* ocfs_sync_local_to_main
*
@@ -733,13 +757,13 @@
struct buffer_head *main_bm_bh)
{
int status = 0;
- int bit_off, left;
+ int bit_off, left, count, start;
+ u64 la_start_blk;
+ u64 blkno;
void *bitmap;
- unsigned int start, numblocks, bitmapblocks;
- ocfs2_dinode *bm_fe;
- LOG_ENTRY_ARGS("alloc->la_bm_bits = %u, COUNT = %u, la_bits_set = %u\n",
- LOCAL_ALLOC(alloc)->la_bm_bits,
+ LOG_ENTRY_ARGS("alloc->la_bm_bits = %u, COUNT = %u, "
+ "la_bits_set = %u\n", LOCAL_ALLOC(alloc)->la_bm_bits,
ocfs_local_alloc_count_bits(alloc),
LOCAL_ALLOC(alloc)->la_bits_set);
@@ -748,77 +772,51 @@
goto bail;
}
- bitmapblocks =
- ocfs_blocks_for_bits(osb->sb,
- osb->cluster_bitmap.validbits);
-
- /* figure out which block in the bitmap to start on and the
- * maximum number of blocks we can span over -- we don't need
- * to read any more as that's the most we'll be touching... */
- numblocks = ocfs_bitmap_blocks_affected(osb->sb,
- LOCAL_ALLOC(alloc)->la_bm_off,
- LOCAL_ALLOC(alloc)->la_bits_set,
- &start);
-
- if ((start + numblocks) > bitmapblocks) {
- printk("uhoh, bitmap calculation is bad!\n");
- printk("alloc->la_bm_bits = %u, COUNT = %u, alloc->la_bits_set = %u"
- "start=%u, alloc->la_bm_off = %u, numblocks=%u, "
- "bitmapblocks = %u\n",
- LOCAL_ALLOC(alloc)->la_bm_bits, ocfs_local_alloc_count_bits(alloc),
- LOCAL_ALLOC(alloc)->la_bits_set, start, LOCAL_ALLOC(alloc)->la_bm_off, numblocks,
- bitmapblocks);
-
- BUG();
- }
-
- bm_fe = (ocfs2_dinode *) main_bm_bh->b_data;
- status = ocfs_journal_access(handle, main_bm_inode, main_bm_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
+ if (LOCAL_ALLOC(alloc)->la_bits_set ==
+ LOCAL_ALLOC(alloc)->la_bm_bits) {
+ LOG_TRACE_STR("all bits were taken!");
goto bail;
}
- LOG_TRACE_ARGS("start=%u, alloc->la_bm_off = %u, numblocks=%u\n", start,
- LOCAL_ALLOC(alloc)->la_bm_off, numblocks);
- status = ocfs_read_blocks(osb, (osb->bitmap_blkno + start), numblocks,
- &osb->cluster_bitmap.chunk[start],
- OCFS_BH_CACHED, main_bm_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
+ la_start_blk = ocfs2_clusters_to_blocks(osb->sb,
+ LOCAL_ALLOC(alloc)->la_bm_off);
bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
- /* any unset bits in local alloc need to be unset in bitmap. */
- bit_off = 0;
+ start = count = bit_off = 0;
left = LOCAL_ALLOC(alloc)->la_bm_bits;
- while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, bit_off))
+
+ while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start))
!= -1) {
- if (bit_off >= left) {
- /*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
- break;
- }
+ if ((bit_off < left) && (bit_off == start)) {
+ count++;
+ start++;
+ continue;
+ }
+ if (count) {
+// ocfs2_verify_zero_bits(bitmap, start, count);
- LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n",
- bit_off + LOCAL_ALLOC(alloc)->la_bm_off);
- ocfs_clear_bits(osb->sb, handle, main_bm_inode,
- &osb->cluster_bitmap,
- bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
- 1);
- bm_fe->id1.bitmap1.i_used--;
- bit_off++;
- }
+ blkno = la_start_blk +
+ ocfs2_clusters_to_blocks(osb->sb,
+ start - count);
- status = ocfs_journal_dirty(handle, main_bm_bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
+ LOG_TRACE_ARGS("freeing %u bits starting at local "
+ "alloc bit %u (la_start_blk = %llu, "
+ "blkno = %llu)\n", count, start - count,
+ la_start_blk, blkno);
+
+ status = ocfs_free_clusters(handle, main_bm_inode,
+ main_bm_bh, blkno, count);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ }
+ if (bit_off >= left)
+ break;
+ count = 1;
+ start = bit_off + 1;
}
bail:
-
LOG_EXIT_STATUS(status);
return(status);
} /* ocfs_sync_local_to_main */
@@ -839,17 +837,13 @@
}
memset(*ac, 0, sizeof(ocfs2_alloc_context));
(*ac)->ac_handle = handle;
-
(*ac)->ac_bits_wanted = ocfs_local_alloc_window_bits(osb);
- status = ocfs_reserve_main_bitmap_bits(osb,
- handle,
- (*ac)->ac_bits_wanted,
- *ac);
+
+ status = ocfs_reserve_cluster_bitmap_bits(osb, *ac);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
}
- (*ac)->ac_which = OCFS_AC_USE_MAIN;
*bitmap_inode = (*ac)->ac_inode;
igrab(*bitmap_inode);
@@ -888,15 +882,12 @@
LOG_TRACE_ARGS("Allocating %u clusters for a new window.\n",
ocfs_local_alloc_window_bits(osb));
- /* we used the main bitmap specific reserve function, but we
- * set everything up nicely, so there's no reason why we can't
- * use the generic claim. */
- status = ocfs_claim_bits(osb,
- handle,
- ac,
- ocfs_local_alloc_window_bits(osb),
- &cluster_off,
- &cluster_count);
+ /* we used the generic suballoc reserve function, but we set
+ * everything up nicely, so there's no reason why we can't use
+ * the more specific cluster api to claim bits. */
+ status = ocfs_claim_clusters(osb, handle, ac,
+ ocfs_local_alloc_window_bits(osb),
+ &cluster_off, &cluster_count);
if (status < 0) {
if (status != -ENOSPC)
LOG_ERROR_STATUS(status);
Modified: trunk/src/localalloc.h
===================================================================
--- trunk/src/localalloc.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/localalloc.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -40,14 +40,15 @@
int ocfs_alloc_should_use_local(ocfs_super *osb,
u64 bits);
+struct _ocfs2_alloc_context;
int ocfs_reserve_local_alloc_bits(ocfs_super *osb,
ocfs_journal_handle *passed_handle,
u32 bits_wanted,
- ocfs2_alloc_context *ac);
+ struct _ocfs2_alloc_context *ac);
int ocfs_claim_local_alloc_bits(ocfs_super *osb,
ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
+ struct _ocfs2_alloc_context *ac,
u32 min_bits,
u32 *bit_off,
u32 *num_bits);
Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/namei.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -359,7 +359,7 @@
/* are we making a directory? If so, reserve a cluster for his
* 1st extent. */
if (S_ISDIR(mode)) {
- status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+ status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto leave;
@@ -1589,7 +1589,7 @@
goto bail;
}
- status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+ status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
if (status < 0) {
LOG_ERROR_STATUS (status = -ENOMEM);
goto bail;
Modified: trunk/src/ocfs.h
===================================================================
--- trunk/src/ocfs.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/ocfs.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -530,7 +530,7 @@
u64 root_blkno;
u64 system_dir_blkno;
u64 bitmap_blkno;
- u32 bitmap_blocks;
+ u32 bitmap_cpg;
u64 publish_blkno;
u32 publish_blocks;
u64 vote_blkno;
@@ -542,6 +542,7 @@
u32 total_autoconfig_blocks;
u8 *uuid;
u8 *vol_label;
+ u64 first_cluster_group_blkno;
u32 s_feature_compat;
u32 s_feature_incompat;
@@ -567,7 +568,6 @@
int needs_flush;
struct proc_dir_entry *proc_sub_dir; /* points to /proc/fs/ocfs2/<maj_min> */
- ocfs_alloc_bm cluster_bitmap;
atomic_t vol_state;
struct semaphore orphan_recovery_lock;
struct semaphore recovery_lock;
Modified: trunk/src/ocfs2_fs.h
===================================================================
--- trunk/src/ocfs2_fs.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/ocfs2_fs.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -317,7 +317,8 @@
tunefs required */
__u16 s_reserved1;
__u32 s_reserved2;
- __u64 s_reserved3;
+ __u64 s_first_cluster_group; /* Block offset of 1st cluster
+ * group header */
/*50*/ __u8 s_label[64]; /* Label for mounting, etc. */
/*90*/ __u8 s_uuid[16]; /* Was vol_id */
/*A0*/
Modified: trunk/src/ocfs_journal.h
===================================================================
--- trunk/src/ocfs_journal.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/ocfs_journal.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -319,6 +319,9 @@
* prev. group desc. if we relink. */
#define OCFS_SUBALLOC_ALLOC (3)
+/* dinode + group descriptor update. We don't relink on free yet. */
+#define OCFS_SUBALLOC_FREE (2)
+
/* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
* bitmap block for the new bit) */
#define OCFS_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
@@ -329,7 +332,8 @@
+ OCFS_DIR_LINK_ADDITIONAL_CREDITS)
/* local alloc metadata change + main bitmap updates */
-#define OCFS_WINDOW_MOVE_CREDITS (OCFS_INODE_UPDATE_CREDITS + 8 + 5)
+#define OCFS_WINDOW_MOVE_CREDITS (OCFS_INODE_UPDATE_CREDITS \
+ + OCFS_SUBALLOC_ALLOC + OCFS_SUBALLOC_FREE)
/* used when we don't need an allocation change for a dir extend. One
* for the dinode, one for the new block. */
@@ -358,16 +362,17 @@
u32 bits_wanted)
{
int bitmap_blocks, sysfile_bitmap_blocks, dinode_blocks;
- /* take advantage of the fact that we always allocate in one
- * large chunk. */
- bitmap_blocks = ocfs_blocks_for_bits(sb, bits_wanted) + 1;
+ /* bitmap dinode, group desc. + relinked group. */
+ bitmap_blocks = OCFS_SUBALLOC_ALLOC;
+
/* we might need to shift tree depth so lets assume an
- * absolute worst case of complete fragmentation so for each
- * new metadata block we have a descriptor and the actual
- * block and of course 1 credit for the metadata dinode
- * update. */
- sysfile_bitmap_blocks = 1 + 3 * ocfs2_extend_meta_needed(fe);
+ * absolute worst case of complete fragmentation. Even with
+ * that, we only need one update for the dinode, and then
+ * however many metadata chunks needed * a remaining suballoc
+ * alloc. */
+ sysfile_bitmap_blocks = 1 +
+ (OCFS_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(fe);
/* this does not include *new* metadata blocks, which are
* accounted for in sysfile_bitmap_blocks. fe +
@@ -394,7 +399,7 @@
unsigned int cpg)
{
int blocks;
- int bitmap_blocks = ocfs_blocks_for_bits(sb, cpg) + 1;
+ int bitmap_blocks = OCFS_SUBALLOC_ALLOC + 1;
/* parent inode update + new block group header + bitmap inode update
+ bitmap blocks affected */
blocks = 1 + 1 + 1 + bitmap_blocks;
@@ -420,9 +425,9 @@
&& ((last_el->l_recs[i].e_clusters - clusters_to_del) == 0))
credits += 1 + fe->id2.i_list.l_tree_depth;
- /* bitmap fe + bitmap blocks covered by this extent */
- bitmap_blocks = 1 + ocfs_blocks_for_bits(sb,
- clusters_to_del);
+ /* bitmap fe + group descriptor */
+ bitmap_blocks = OCFS_SUBALLOC_FREE;
+
credits += bitmap_blocks;
return(credits);
Modified: trunk/src/proc.c
===================================================================
--- trunk/src/proc.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/proc.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -459,17 +459,13 @@
"Number of nodes : %u\n" \
"Cluster size : %d\n" \
"Volume size : %llu\n" \
- "Failed Large Allocs : %u\n" \
- "Retry Large Allocs : %u\n" \
"Open Transactions: : %u\n" \
"Delayed Locks : %u\n" \
"Checkpointing Locks : %u\n"
len = sprintf (page, PROC_STATS, pubmap,
osb->num_nodes, osb->s_clustersize,
- ocfs2_clusters_to_bytes(osb->sb, osb->cluster_bitmap.validbits),
- osb->cluster_bitmap.failed,
- osb->cluster_bitmap.ok_retries,
+ ocfs2_clusters_to_bytes(osb->sb, osb->num_clusters),
atomic_read(&osb->journal->num_trans),
atomic_read(&osb->journal->num_cmt_locks),
atomic_read(&osb->journal->num_chkpt_locks));
Modified: trunk/src/suballoc.c
===================================================================
--- trunk/src/suballoc.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/suballoc.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -37,6 +37,7 @@
#include "alloc.h"
#include "dlm.h"
+#include "localalloc.h"
#include "util.h"
#include "suballoc.h"
#include "sysfile.h"
@@ -58,18 +59,35 @@
static int ocfs_block_group_alloc(ocfs_super *osb,
struct inode *alloc_inode,
struct buffer_head *bh);
+
static int ocfs_reserve_suballoc_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
ocfs2_alloc_context *ac);
+
+static int ocfs2_cluster_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found);
+static int ocfs2_block_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found);
+static int ocfs_search_chain(ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno);
static int ocfs_claim_suballoc_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
ocfs2_alloc_context *ac,
u32 bits_wanted,
+ u32 min_bits,
u16 *bit_off,
unsigned int *num_bits,
u64 *bg_blkno);
+static int ocfs_test_bg_bit_allocatable(struct buffer_head *bg_bh,
+ int nr);
static int ocfs_block_group_find_clear_bits(ocfs_super *osb,
- ocfs2_group_desc *bg,
+ struct buffer_head *bg_bh,
unsigned int bits_wanted,
u16 *bit_off,
u16 *bits_found);
@@ -79,6 +97,13 @@
struct buffer_head *group_bh,
unsigned int bit_off,
unsigned int num_bits);
+static inline int ocfs_block_group_clear_bits(ocfs_journal_handle *handle,
+ struct inode *alloc_inode,
+ ocfs2_group_desc *bg,
+ struct buffer_head *group_bh,
+ unsigned int bit_off,
+ unsigned int num_bits);
+
static int ocfs_relink_block_group(ocfs_journal_handle *handle,
struct inode *alloc_inode,
struct buffer_head *fe_bh,
@@ -87,8 +112,33 @@
u16 chain);
static inline int ocfs_block_group_reasonably_empty(ocfs2_group_desc *bg,
u32 wanted);
-static inline u64 ocfs_which_suballoc_group(u64 block, unsigned int bit);
+static int ocfs_free_suballoc_bits(ocfs_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *alloc_bh,
+ unsigned int start_bit,
+ u64 bg_blkno,
+ unsigned int count);
+static inline u64 ocfs_which_suballoc_group(u64 block,
+ unsigned int bit);
+static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+ u64 bg_blkno,
+ u16 bg_bit_off);
+static inline u64 ocfs2_which_cluster_group(struct inode *inode,
+ u32 cluster);
+static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+ u64 data_blkno,
+ u64 *bg_blkno,
+ u16 *bg_bit_off);
+void ocfs_free_alloc_context(ocfs2_alloc_context *ac)
+{
+ if (ac->ac_inode)
+ iput(ac->ac_inode);
+ if (ac->ac_bh)
+ brelse(ac->ac_bh);
+ kfree(ac);
+}
+
static int ocfs2_block_group_fill(ocfs_journal_handle *handle,
struct inode *alloc_inode,
struct buffer_head *bg_bh,
@@ -235,6 +285,8 @@
struct buffer_head **zero_bhs = NULL;
#endif
+ OCFS_ASSERT(!ocfs2_is_cluster_bitmap(alloc_inode));
+
LOG_ENTRY();
handle = ocfs_alloc_handle(osb);
@@ -245,10 +297,10 @@
}
cl = &fe->id2.i_chain;
- status = ocfs_reserve_bits(osb,
- handle,
- cl->cl_cpg,
- &ac);
+ status = ocfs_reserve_clusters(osb,
+ handle,
+ cl->cl_cpg,
+ &ac);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -262,12 +314,12 @@
goto bail;
}
- status = ocfs_claim_bits(osb,
- handle,
- ac,
- cl->cl_cpg,
- &bit_off,
- &num_bits);
+ status = ocfs_claim_clusters(osb,
+ handle,
+ ac,
+ cl->cl_cpg,
+ &bit_off,
+ &num_bits);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -360,14 +412,15 @@
}
static int ocfs_reserve_suballoc_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
ocfs2_alloc_context *ac)
{
int status;
u32 bits_wanted = ac->ac_bits_wanted;
struct inode *alloc_inode = ac->ac_inode;
struct buffer_head *bh = NULL;
+ ocfs_journal_handle *handle = ac->ac_handle;
ocfs2_dinode *fe;
+ u32 free_bits;
LOG_ENTRY();
@@ -388,8 +441,18 @@
OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
OCFS_ASSERT_RO(fe->i_flags & OCFS2_CHAIN_FL);
- if (bits_wanted > (le32_to_cpu(fe->id1.bitmap1.i_total) -
- le32_to_cpu(fe->id1.bitmap1.i_used))) {
+ free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) -
+ le32_to_cpu(fe->id1.bitmap1.i_used);
+
+ if (bits_wanted > free_bits) {
+ /* cluster bitmap never grows */
+ if (ocfs2_is_cluster_bitmap(alloc_inode)) {
+ LOG_ERROR_ARGS("Disk Full: wanted=%u, free_bits=%u\n",
+ bits_wanted, free_bits);
+ status = -ENOSPC;
+ goto bail;
+ }
+
status = ocfs_block_group_alloc(osb, alloc_inode, bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -403,7 +466,6 @@
get_bh(bh);
ac->ac_bh = bh;
- status = 0;
bail:
if (bh)
brelse(bh);
@@ -443,8 +505,9 @@
}
(*ac)->ac_inode = igrab(alloc_inode);
+ (*ac)->ac_group_search = ocfs2_block_group_search;
- status = ocfs_reserve_suballoc_bits(osb, handle, (*ac));
+ status = ocfs_reserve_suballoc_bits(osb, (*ac));
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -490,8 +553,9 @@
}
(*ac)->ac_inode = igrab(alloc_inode);
+ (*ac)->ac_group_search = &ocfs2_block_group_search;
- status = ocfs_reserve_suballoc_bits(osb, handle, *ac);
+ status = ocfs_reserve_suballoc_bits(osb, *ac);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -511,8 +575,133 @@
return status;
}
+/* local alloc code has to do the same thing, so rather than do this
+ * twice.. */
+int ocfs_reserve_cluster_bitmap_bits(ocfs_super *osb,
+ ocfs2_alloc_context *ac)
+{
+ int status;
+
+ ac->ac_inode = ocfs_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ -1);
+ if (!ac->ac_inode) {
+ status = -EINVAL;
+ LOG_ERROR_STR("Could not get bitmap inode!");
+ goto bail;
+ }
+ ac->ac_which = OCFS_AC_USE_MAIN;
+ ac->ac_group_search = &ocfs2_cluster_group_search;
+
+ status = ocfs_reserve_suballoc_bits(osb, ac);
+ if (status < 0 && status != -ENOSPC)
+ LOG_ERROR_STATUS(status);
+bail:
+ return status;
+}
+
+/* Callers don't need to care which bitmap (local alloc or main) to
+ * use so we figure it out for them, but unfortunately this clutters
+ * things a bit. */
+int ocfs_reserve_clusters(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ u32 bits_wanted,
+ ocfs2_alloc_context **ac)
+{
+ int status;
+
+ LOG_ENTRY();
+
+ OCFS_ASSERT(handle);
+
+ *ac = kmalloc(sizeof(ocfs2_alloc_context), GFP_KERNEL);
+ if (!(*ac)) {
+ status = -ENOMEM;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ memset(*ac, 0, sizeof(ocfs2_alloc_context));
+ (*ac)->ac_bits_wanted = bits_wanted;
+ (*ac)->ac_handle = handle;
+
+ status = -ENOSPC;
+ if (ocfs_alloc_should_use_local(osb, bits_wanted)) {
+ status = ocfs_reserve_local_alloc_bits(osb,
+ handle,
+ bits_wanted,
+ *ac);
+ if ((status < 0) && (status != -ENOSPC)) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ } else if (status == -ENOSPC) {
+#warning "need to deal with disabling local alloc better"
+ /* reserve_local_bits will return enospc with
+ * the local alloc inode still locked, so we
+ * can change this safely here. */
+ LOG_ERROR_STR("Disabling local alloc");
+ osb->have_local_alloc = 0;
+// ocfs_shutdown_local_alloc(osb);
+ }
+ }
+
+ if (status == -ENOSPC) {
+ status = ocfs_reserve_cluster_bitmap_bits(osb, *ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ }
+
+ status = 0;
+bail:
+ if ((status < 0) && *ac) {
+ ocfs_free_alloc_context(*ac);
+ *ac = NULL;
+ }
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+}
+
+/*
+ * More or less lifted from ext3. I'll leave their description below:
+ *
+ * "For ext3 allocations, we must not reuse any blocks which are
+ * allocated in the bitmap buffer's "last committed data" copy. This
+ * prevents deletes from freeing up the page for reuse until we have
+ * committed the delete transaction.
+ *
+ * If we didn't do this, then deleting something and reallocating it as
+ * data would allow the old block to be overwritten before the
+ * transaction committed (because we force data to disk before commit).
+ * This would lead to corruption if we crashed between overwriting the
+ * data and committing the delete.
+ *
+ * @@@ We may want to make this allocation behaviour conditional on
+ * data-writes at some point, and disable it for metadata allocations or
+ * sync-data inodes."
+ *
+ * Note: OCFS2 already does this differently for metadata vs data
+ * allocations, as those bitmaps are seperate and undo access is never
+ * called on a metadata group descriptor.
+ */
+static int ocfs_test_bg_bit_allocatable(struct buffer_head *bg_bh,
+ int nr)
+{
+ ocfs2_group_desc *bg = (ocfs2_group_desc *) bg_bh->b_data;
+
+ if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap))
+ return 0;
+ if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data)
+ return 1;
+
+ bg = (ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data;
+ return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);
+}
+
static int ocfs_block_group_find_clear_bits(ocfs_super *osb,
- ocfs2_group_desc *bg,
+ struct buffer_head *bg_bh,
unsigned int bits_wanted,
u16 *bit_off,
u16 *bits_found)
@@ -520,6 +709,7 @@
void *bitmap;
u16 best_offset, best_size;
int offset, start, found, status = 0;
+ ocfs2_group_desc *bg = (ocfs2_group_desc *) bg_bh->b_data;
OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
@@ -532,7 +722,12 @@
if (offset == bg->bg_bits)
break;
- if (offset == start) {
+ if (!ocfs_test_bg_bit_allocatable(bg_bh, offset)) {
+ /* We found a zero, but we can't use it as it
+ * hasn't been put to disk yet! */
+ found = 0;
+ start = offset + 1;
+ } else if (offset == start) {
/* we found a zero */
found++;
start++;
@@ -575,6 +770,7 @@
{
int status;
void *bitmap = bg->bg_bitmap;
+ int journal_type = OCFS_JOURNAL_ACCESS_WRITE;
LOG_ENTRY();
@@ -584,10 +780,13 @@
LOG_TRACE_ARGS("block_group_set_bits: off = %u, num = %u\n", bit_off,
num_bits);
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ journal_type = OCFS_JOURNAL_ACCESS_UNDO;
+
status = ocfs_journal_access(handle,
alloc_inode,
group_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
+ journal_type);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -647,9 +846,9 @@
OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(prev_bg));
- printk("In suballoc %llu, chain %u, move group %llu to top, "
- "prev = %llu\n", fe->i_blkno, chain, bg->bg_blkno,
- prev_bg->bg_blkno);
+ LOG_TRACE_ARGS("In suballoc %llu, chain %u, move group %llu to top, "
+ "prev = %llu\n", fe->i_blkno, chain, bg->bg_blkno,
+ prev_bg->bg_blkno);
fe_ptr = fe->id2.i_chain.cl_recs[chain].c_blkno;
bg_ptr = bg->bg_next_group;
@@ -718,64 +917,95 @@
return bg->bg_free_bits_count > wanted;
}
-/* will give out up to bits_wanted contiguous bits. */
-static int ocfs_claim_suballoc_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u32 bits_wanted,
- u16 *bit_off,
- unsigned int *num_bits,
- u64 *bg_blkno)
+/* return 0 on success, -ENOSPC to keep searching and any other < 0
+ * value on error. */
+static int ocfs2_cluster_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found)
{
- int status, groups_read;
- struct inode *alloc_inode = ac->ac_inode;
- struct buffer_head *group_bh = NULL;
- struct buffer_head *prev_group_bh = NULL;
- ocfs2_chain_list *cl;
- ocfs2_dinode *fe;
- ocfs2_group_desc *bg;
- u16 chain, tmp_bits;
- u64 next_group;
+ int search = -ENOSPC;
+ int ret;
+ ocfs2_group_desc *bg = (ocfs2_group_desc *) group_bh->b_data;
+ u16 tmp_off, tmp_found;
- LOG_ENTRY();
+ OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
- OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
- OCFS_ASSERT(ac->ac_handle == handle);
- OCFS_ASSERT(bits_wanted <= (ac->ac_bits_wanted - ac->ac_bits_given));
- OCFS_ASSERT(ac->ac_bh);
+ if (bg->bg_free_bits_count) {
+ ret = ocfs_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
+ group_bh, bits_wanted,
+ &tmp_off, &tmp_found);
+ if (!ret) {
+ if (min_bits <= tmp_found) {
+ *bit_off = tmp_off;
+ *bits_found = tmp_found;
+ search = 0; /* success */
+ }
+ }
+ }
- fe = (ocfs2_dinode *) ac->ac_bh->b_data;
- OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
- OCFS_ASSERT_RO(fe->id1.bitmap1.i_used < fe->id1.bitmap1.i_total);
+ return search;
+}
- cl = (ocfs2_chain_list *) &fe->id2.i_chain;
+static int ocfs2_block_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found)
+{
+ int ret = -ENOSPC;
+ ocfs2_group_desc *bg = (ocfs2_group_desc *) group_bh->b_data;
- chain = ocfs2_find_victim_chain(cl);
+ OCFS_ASSERT(min_bits == 1);
+ OCFS_ASSERT(!ocfs2_is_cluster_bitmap(inode));
+ if (bg->bg_free_bits_count)
+ ret = ocfs_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
+ group_bh, bits_wanted,
+ bit_off, bits_found);
+
+ return ret;
+}
+
+static int ocfs_search_chain(ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno)
+{
+ int status;
+ u16 chain, tmp_bits;
+ u64 next_group;
+ ocfs_journal_handle *handle = ac->ac_handle;
+ struct inode *alloc_inode = ac->ac_inode;
+ struct buffer_head *group_bh = NULL;
+ struct buffer_head *prev_group_bh = NULL;
+ ocfs2_dinode *fe = (ocfs2_dinode *) ac->ac_bh->b_data;
+ ocfs2_chain_list *cl = (ocfs2_chain_list *) &fe->id2.i_chain;
+ ocfs2_group_desc *bg;
+
+ chain = ac->ac_chain;
LOG_TRACE_ARGS("trying to alloc %u bits from chain %u, inode %llu\n",
bits_wanted, chain, OCFS_I(alloc_inode)->ip_blkno);
- status = ocfs_read_block(osb, cl->cl_recs[chain].c_blkno,
- &group_bh, OCFS_BH_CACHED, alloc_inode);
+ status = ocfs_read_block(OCFS2_SB(alloc_inode->i_sb),
+ cl->cl_recs[chain].c_blkno, &group_bh,
+ OCFS_BH_CACHED, alloc_inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
}
-
bg = (ocfs2_group_desc *) group_bh->b_data;
OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
+ status = -ENOSPC;
/* for now, the chain search is a bit simplistic. We just use
* the 1st group with any empty bits. */
- groups_read = 1;
- while (!bg->bg_free_bits_count) {
- /*
- * This means we've walked off the end of a chain that
- * we thought had bits, but didn't. While this
- * _could_ be a code error, it is more likely to be
- * corruption on disk.
- */
- OCFS_ASSERT_RO(bg->bg_next_group);
+ while ((status = ac->ac_group_search(alloc_inode, group_bh,
+ bits_wanted, min_bits, bit_off,
+ &tmp_bits)) == -ENOSPC) {
+ if (!bg->bg_next_group)
+ break;
if (prev_group_bh) {
brelse(prev_group_bh);
@@ -784,31 +1014,29 @@
next_group = bg->bg_next_group;
prev_group_bh = group_bh;
group_bh = NULL;
- status = ocfs_read_block(osb, next_group, &group_bh,
+ status = ocfs_read_block(OCFS2_SB(alloc_inode->i_sb),
+ next_group, &group_bh,
OCFS_BH_CACHED, alloc_inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
}
- groups_read++;
bg = (ocfs2_group_desc *) group_bh->b_data;
OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
}
-
- status = ocfs_block_group_find_clear_bits(osb,
- bg,
- bits_wanted,
- bit_off,
- &tmp_bits);
if (status < 0) {
- LOG_ERROR_STATUS(status);
+ if (status != -ENOSPC)
+ LOG_ERROR_STATUS(status);
goto bail;
}
+
+ LOG_TRACE_ARGS("alloc succeeds: we give %u bits from block group "
+ "%llu\n", tmp_bits, bg->bg_blkno);
+
*num_bits = tmp_bits;
OCFS_ASSERT(*num_bits);
-#define OCFS2_BG_RELINK_TRIGGER 1
/*
* Keep track of previous block descriptor read. When
* we find a target, if we have read more than X
@@ -822,9 +1050,9 @@
* Do this *after* figuring out how many bits we're taking out
* of our target group.
*/
- if ((prev_group_bh)
- && (groups_read > OCFS2_BG_RELINK_TRIGGER)
- && (ocfs_block_group_reasonably_empty(bg, *num_bits))) {
+ if (ac->ac_allow_chain_relink &&
+ (prev_group_bh) &&
+ (ocfs_block_group_reasonably_empty(bg, *num_bits))) {
status = ocfs_relink_block_group(handle, alloc_inode,
ac->ac_bh, group_bh,
prev_group_bh, chain);
@@ -884,6 +1112,76 @@
return status;
}
+/* will give out up to bits_wanted contiguous bits. */
+static int ocfs_claim_suballoc_bits(ocfs_super *osb,
+ ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno)
+{
+ int status;
+ u16 victim, i;
+ ocfs2_chain_list *cl;
+ ocfs2_dinode *fe;
+
+ LOG_ENTRY();
+
+ OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
+ OCFS_ASSERT(bits_wanted <= (ac->ac_bits_wanted - ac->ac_bits_given));
+ OCFS_ASSERT(ac->ac_bh);
+
+ fe = (ocfs2_dinode *) ac->ac_bh->b_data;
+ OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
+ OCFS_ASSERT_RO(fe->id1.bitmap1.i_used < fe->id1.bitmap1.i_total);
+
+ cl = (ocfs2_chain_list *) &fe->id2.i_chain;
+
+ victim = ocfs2_find_victim_chain(cl);
+ ac->ac_chain = victim;
+ ac->ac_allow_chain_relink = 1;
+
+ status = ocfs_search_chain(ac, bits_wanted, min_bits, bit_off,
+ num_bits, bg_blkno);
+ if (!status)
+ goto bail;
+ if (status < 0 && status != -ENOSPC) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ LOG_TRACE_ARGS("Search of victim chain %u came up with nothing, "
+ "trying all chains now.\n", victim);
+
+ /* If we didn't pick a good victim, then just default to
+ * searching each chain in order. Don't allow chain relinking
+ * because we only calculate enough journal credits for one
+ * relink per alloc. */
+ ac->ac_allow_chain_relink = 0;
+ for (i = 0; i < cl->cl_next_free_rec; i ++) {
+ if (i == victim)
+ continue;
+ if (!cl->cl_recs[i].c_free)
+ continue;
+
+ ac->ac_chain = i;
+ status = ocfs_search_chain(ac, bits_wanted, min_bits,
+ bit_off, num_bits,
+ bg_blkno);
+ if (!status)
+ break;
+ if (status < 0 && status != -ENOSPC) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ }
+bail:
+
+ LOG_EXIT_STATUS(status);
+ return status;
+}
+
int ocfs_claim_metadata(ocfs_super *osb,
ocfs_journal_handle *handle,
ocfs2_alloc_context *ac,
@@ -901,9 +1199,9 @@
OCFS_ASSERT(ac->ac_handle == handle);
status = ocfs_claim_suballoc_bits(osb,
- handle,
ac,
bits_wanted,
+ 1,
suballoc_bit_start,
num_bits,
&bg_blkno);
@@ -938,11 +1236,11 @@
OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_INODE);
OCFS_ASSERT(ac->ac_handle == handle);
- status = ocfs_claim_suballoc_bits(osb,
- handle,
- ac,
- 1,
- suballoc_bit,
+ status = ocfs_claim_suballoc_bits(osb,
+ ac,
+ 1,
+ 1,
+ suballoc_bit,
&num_bits,
&bg_blkno);
if (status < 0) {
@@ -960,29 +1258,146 @@
return status;
}
-static inline u64 ocfs_which_suballoc_group(u64 block, unsigned int bit)
+/*
+ * min_bits - minimum contiguous chunk from this total allocation we
+ * can handle. set to what we asked for originally for a full
+ * contig. allocation, set to '1' to indicate we can deal with extents
+ * of any size.
+ */
+int ocfs_claim_clusters(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_alloc_context *ac,
+ u32 min_clusters,
+ u32 *cluster_start,
+ u32 *num_clusters)
{
- return(block - (u64) bit);
+ int status;
+ unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+ u64 bg_blkno;
+ u16 bg_bit_off;
+
+ LOG_ENTRY();
+
+ OCFS_ASSERT(ac);
+ OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
+
+ OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL
+ || ac->ac_which == OCFS_AC_USE_MAIN);
+ OCFS_ASSERT(ac->ac_handle == handle);
+
+ if (ac->ac_which == OCFS_AC_USE_LOCAL) {
+ status = ocfs_claim_local_alloc_bits(osb,
+ handle,
+ ac,
+ bits_wanted,
+ cluster_start,
+ num_clusters);
+ } else {
+ if (min_clusters > (osb->bitmap_cpg - 1)) {
+ /* The only paths asking for contiguousness
+ * should know about this already. */
+ LOG_ERROR_ARGS("minimum allocation requested exceeds "
+ "group bitmap size!");
+ status = -ENOSPC;
+ goto bail;
+ }
+ /* clamp the current request down to a realistic size. */
+ if (bits_wanted > (osb->bitmap_cpg - 1))
+ bits_wanted = osb->bitmap_cpg - 1;
+
+ status = ocfs_claim_suballoc_bits(osb,
+ ac,
+ bits_wanted,
+ min_clusters,
+ &bg_bit_off,
+ num_clusters,
+ &bg_blkno);
+ if (!status)
+ *cluster_start =
+ ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
+ bg_blkno,
+ bg_bit_off);
+ }
+ if (status < 0) {
+ /* If you're not asking for contiguous blocks, then
+ * the reserve function should've given you enough,
+ * and ENOSPC this is a real error. */
+ if ((status != -ENOSPC) || (min_clusters == 1))
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ ac->ac_bits_given += *num_clusters;
+
+bail:
+ LOG_EXIT_STATUS(status);
+ return(status);
}
+static inline int ocfs_block_group_clear_bits(ocfs_journal_handle *handle,
+ struct inode *alloc_inode,
+ ocfs2_group_desc *bg,
+ struct buffer_head *group_bh,
+ unsigned int bit_off,
+ unsigned int num_bits)
+{
+ int status;
+ unsigned int tmp;
+ int journal_type = OCFS_JOURNAL_ACCESS_WRITE;
+ ocfs2_group_desc *undo_bg = NULL;
+
+ LOG_ENTRY();
+
+ OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
+
+ LOG_TRACE_ARGS("off = %u, num = %u\n", bit_off, num_bits);
+
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ journal_type = OCFS_JOURNAL_ACCESS_UNDO;
+
+ status = ocfs_journal_access(handle, alloc_inode, group_bh,
+ journal_type);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ undo_bg = (ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data;
+
+ tmp = num_bits;
+ while(tmp--) {
+ ocfs2_clear_bit((bit_off + tmp),
+ (unsigned long *) bg->bg_bitmap);
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ ocfs2_set_bit(bit_off + tmp,
+ (unsigned long *) undo_bg->bg_bitmap);
+ }
+ bg->bg_free_bits_count += num_bits;
+
+ status = ocfs_journal_dirty(handle, group_bh);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+bail:
+ return status;
+}
+
/*
* expects the suballoc inode to already be locked.
*/
-int ocfs_free_suballoc_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- struct inode *alloc_inode,
- struct buffer_head *alloc_bh,
- unsigned int start_bit,
- u64 start_block,
- unsigned int count)
+static int ocfs_free_suballoc_bits(ocfs_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *alloc_bh,
+ unsigned int start_bit,
+ u64 bg_blkno,
+ unsigned int count)
{
int status = 0;
+ ocfs_super *osb = OCFS2_SB(alloc_inode->i_sb);
ocfs2_dinode *fe = (ocfs2_dinode *) alloc_bh->b_data;
ocfs2_chain_list *cl = &fe->id2.i_chain;
- u64 bg_blkno;
struct buffer_head *group_bh = NULL;
ocfs2_group_desc *group;
- unsigned int tmp;
LOG_ENTRY();
@@ -990,11 +1405,10 @@
OCFS_ASSERT((count + start_bit)
<= ((u32) cl->cl_cpg * (u32) cl->cl_bpc));
- bg_blkno = ocfs_which_suballoc_group(start_block, start_bit);
- LOG_TRACE_ARGS("freeing %u bits from group %llu, starting at %u "
- "(1st block = %llu, suballocator %llu)\n",
- count, bg_blkno, start_bit, start_block,
- OCFS_I(alloc_inode)->ip_blkno);
+ LOG_TRACE_ARGS("suballocator %llu: freeing %u bits from group %llu, "
+ "starting at %u\n",
+ OCFS_I(alloc_inode)->ip_blkno, count, bg_blkno,
+ start_bit);
status = ocfs_read_block(osb, bg_blkno, &group_bh, OCFS_BH_CACHED,
alloc_inode);
@@ -1005,27 +1419,16 @@
group = (ocfs2_group_desc *) group_bh->b_data;
OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(group));
+ OCFS_ASSERT((count + start_bit) <= group->bg_bits);
- status = ocfs_journal_access(handle, alloc_inode, group_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
+ status = ocfs_block_group_clear_bits(handle, alloc_inode,
+ group, group_bh,
+ start_bit, count);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
}
- tmp = count;
- while(tmp--)
- ocfs2_clear_bit((start_bit + tmp),
- (unsigned long *) group->bg_bitmap);
-
- group->bg_free_bits_count += count;
-
- status = ocfs_journal_dirty(handle, group_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
status = ocfs_journal_access(handle, alloc_inode, alloc_bh,
OCFS_JOURNAL_ACCESS_WRITE);
if (status < 0) {
@@ -1053,6 +1456,132 @@
return status;
}
+static inline u64 ocfs_which_suballoc_group(u64 block, unsigned int bit)
+{
+ u64 group = block - (u64) bit;
+
+ return group;
+}
+
+int ocfs2_free_dinode(ocfs_journal_handle *handle,
+ struct inode *inode_alloc_inode,
+ struct buffer_head *inode_alloc_bh,
+ ocfs2_dinode *di)
+{
+ u64 blk = le64_to_cpu(di->i_blkno);
+ u16 bit = le16_to_cpu(di->i_suballoc_bit);
+ u64 bg_blkno = ocfs_which_suballoc_group(blk, bit);
+
+ return ocfs_free_suballoc_bits(handle, inode_alloc_inode,
+ inode_alloc_bh, bit, bg_blkno, 1);
+}
+
+int ocfs2_free_extent_block(ocfs_journal_handle *handle,
+ struct inode *eb_alloc_inode,
+ struct buffer_head *eb_alloc_bh,
+ ocfs2_extent_block *eb)
+{
+ u64 blk = le64_to_cpu(eb->h_blkno);
+ u16 bit = le16_to_cpu(eb->h_suballoc_bit);
+ u64 bg_blkno = ocfs_which_suballoc_group(blk, bit);
+
+ return ocfs_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
+ bit, bg_blkno, 1);
+}
+
+/* translate a group desc. blkno and it's bitmap offset into
+ * disk cluster offset. */
+static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+ u64 bg_blkno,
+ u16 bg_bit_off)
+{
+ ocfs_super *osb = OCFS2_SB(inode->i_sb);
+ u32 cluster = 0;
+
+ OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+ if (bg_blkno != osb->first_cluster_group_blkno)
+ cluster = ocfs2_blocks_to_clusters(inode->i_sb, bg_blkno);
+ cluster += (u32) bg_bit_off;
+ return cluster;
+}
+
+/* given a cluster offset, calculate which block group it belongs to
+ * and return that block offset. */
+static inline u64 ocfs2_which_cluster_group(struct inode *inode,
+ u32 cluster)
+{
+ ocfs_super *osb = OCFS2_SB(inode->i_sb);
+ u32 group_no;
+
+ OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+ group_no = cluster / osb->bitmap_cpg;
+ if (!group_no)
+ return osb->first_cluster_group_blkno;
+ return ocfs2_clusters_to_blocks(inode->i_sb,
+ group_no * osb->bitmap_cpg);
+}
+
+/* given the block number of a cluster start, calculate which cluster
+ * group and descriptor bitmap offset that corresponds to. */
+static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+ u64 data_blkno,
+ u64 *bg_blkno,
+ u16 *bg_bit_off)
+{
+ ocfs_super *osb = OCFS2_SB(inode->i_sb);
+ u32 data_cluster = ocfs2_blocks_to_clusters(osb->sb, data_blkno);
+
+ OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+ *bg_blkno = ocfs2_which_cluster_group(inode,
+ data_cluster);
+
+ if (*bg_blkno == osb->first_cluster_group_blkno)
+ *bg_bit_off = (u16) data_cluster;
+ else
+ *bg_bit_off = (u16) ocfs2_blocks_to_clusters(osb->sb,
+ data_blkno - *bg_blkno);
+}
+
+int ocfs_free_clusters(ocfs_journal_handle *handle,
+ struct inode *bitmap_inode,
+ struct buffer_head *bitmap_bh,
+ u64 start_blk,
+ unsigned int num_clusters)
+{
+ int status;
+ u16 bg_start_bit;
+ u64 bg_blkno;
+ ocfs2_dinode *fe;
+
+ /* You can't ever have a contiguous set of clusters
+ * bigger than a block group bitmap so we never have to worry
+ * about looping on them. */
+
+ LOG_ENTRY();
+
+ fe = (ocfs2_dinode *) bitmap_bh->b_data;
+
+ ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno,
+ &bg_start_bit);
+
+ LOG_TRACE_ARGS("want to free %u clusters starting at block %llu\n",
+ num_clusters, start_blk);
+ LOG_TRACE_ARGS("bg_blkno = %llu, bg_start_bit = %u\n", bg_blkno,
+ bg_start_bit);
+
+ status = ocfs_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
+ bg_start_bit, bg_blkno,
+ num_clusters);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+
+ LOG_EXIT_STATUS(status);
+ return status;
+}
+
static inline void debug_bg(ocfs2_group_desc *bg)
{
printk("Block Group:\n");
@@ -1065,7 +1594,6 @@
printk("bg_next_group: %llu\n", bg->bg_next_group);
printk("bg_parent_dinode: %llu\n", bg->bg_parent_dinode);
printk("bg_blkno: %llu\n", bg->bg_blkno);
- return;
}
static inline void debug_suballoc_inode(ocfs2_dinode *fe)
@@ -1085,9 +1613,11 @@
printk("id2.i_chain.cl_next_free_rec: %u\n",
fe->id2.i_chain.cl_next_free_rec);
for(i = 0; i < fe->id2.i_chain.cl_next_free_rec; i++) {
- printk("fe->id2.i_chain.cl_recs[%d].c_free: %u\n", i, fe->id2.i_chain.cl_recs[i].c_free);
- printk("fe->id2.i_chain.cl_recs[%d].c_total: %u\n", i, fe->id2.i_chain.cl_recs[i].c_total);
- printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %llu\n", i, fe->id2.i_chain.cl_recs[i].c_blkno);
+ printk("fe->id2.i_chain.cl_recs[%d].c_free: %u\n", i,
+ fe->id2.i_chain.cl_recs[i].c_free);
+ printk("fe->id2.i_chain.cl_recs[%d].c_total: %u\n", i,
+ fe->id2.i_chain.cl_recs[i].c_total);
+ printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %llu\n", i,
+ fe->id2.i_chain.cl_recs[i].c_blkno);
}
- return;
}
Modified: trunk/src/suballoc.h
===================================================================
--- trunk/src/suballoc.h 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/suballoc.h 2004-11-10 22:18:57 UTC (rev 1636)
@@ -26,6 +26,37 @@
#ifndef _CHAINALLOC_H_
#define _CHAINALLOC_H_
+typedef int (group_search_t)(struct inode *,
+ struct buffer_head *,
+ u32,
+ u32,
+ u16 *,
+ u16 *);
+
+typedef struct _ocfs2_alloc_context {
+ struct inode *ac_inode; /* which bitmap are we allocating from? */
+ struct buffer_head *ac_bh; /* file entry bh */
+ u32 ac_bits_wanted;
+ u32 ac_bits_given;
+#define OCFS_AC_USE_LOCAL 1
+#define OCFS_AC_USE_MAIN 2
+#define OCFS_AC_USE_INODE 3
+#define OCFS_AC_USE_META 4
+ u32 ac_which;
+ ocfs_journal_handle *ac_handle;
+
+ /* these are used by the chain search */
+ u16 ac_chain;
+ int ac_allow_chain_relink;
+ group_search_t *ac_group_search;
+} ocfs2_alloc_context;
+
+void ocfs_free_alloc_context(ocfs2_alloc_context *ac);
+static inline int ocfs_alloc_context_bits_left(ocfs2_alloc_context *ac)
+{
+ return(ac->ac_bits_wanted - ac->ac_bits_given);
+}
+
int ocfs_reserve_new_metadata(ocfs_super *osb,
ocfs_journal_handle *handle,
ocfs2_dinode *fe,
@@ -33,11 +64,11 @@
int ocfs_reserve_new_inode(ocfs_super *osb,
ocfs_journal_handle *handle,
ocfs2_alloc_context **ac);
-int ocfs_claim_new_inode(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u16 *suballoc_bit,
- u64 *fe_blkno);
+int ocfs_reserve_clusters(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ u32 bits_wanted,
+ ocfs2_alloc_context **ac);
+
int ocfs_claim_metadata(ocfs_super *osb,
ocfs_journal_handle *handle,
ocfs2_alloc_context *ac,
@@ -45,11 +76,57 @@
u16 *suballoc_bit_start,
u32 *num_bits,
u64 *blkno_start);
-int ocfs_free_suballoc_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- struct inode *alloc_inode,
- struct buffer_head *alloc_bh,
- unsigned int start_bit,
- u64 start_block,
- unsigned int count);
+int ocfs_claim_new_inode(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_alloc_context *ac,
+ u16 *suballoc_bit,
+ u64 *fe_blkno);
+int ocfs_claim_clusters(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_alloc_context *ac,
+ u32 min_clusters,
+ u32 *cluster_start,
+ u32 *num_clusters);
+
+int ocfs2_free_dinode(ocfs_journal_handle *handle,
+ struct inode *inode_alloc_inode,
+ struct buffer_head *inode_alloc_bh,
+ ocfs2_dinode *di);
+int ocfs2_free_extent_block(ocfs_journal_handle *handle,
+ struct inode *eb_alloc_inode,
+ struct buffer_head *eb_alloc_bh,
+ ocfs2_extent_block *eb);
+int ocfs_free_clusters(ocfs_journal_handle *handle,
+ struct inode *bitmap_inode,
+ struct buffer_head *bitmap_bh,
+ u64 start_blk,
+ unsigned int num_clusters);
+
+static inline u32 ocfs2_cluster_from_desc(ocfs_super *osb,
+ u64 bg_blkno)
+{
+ /* This should work for all block group descriptors as only
+ * the 1st group descriptor of the cluster bitmap is
+ * different. */
+
+ if (bg_blkno == osb->first_cluster_group_blkno)
+ return 0;
+
+ /* the rest of the block groups are located at the beginning
+ * of their 1st cluster, so a direct translation just
+ * works. */
+ return ocfs2_blocks_to_clusters(osb->sb, bg_blkno);
+}
+
+static inline int ocfs2_is_cluster_bitmap(struct inode *inode)
+{
+ ocfs_super *osb = OCFS2_SB(inode->i_sb);
+ return osb->bitmap_blkno == OCFS_I(inode)->ip_blkno;
+}
+
+/* This is for local alloc ONLY. Others should use the task-specific
+ * apis above. */
+int ocfs_reserve_cluster_bitmap_bits(ocfs_super *osb,
+ ocfs2_alloc_context *ac);
+
#endif /* _CHAINALLOC_H_ */
Modified: trunk/src/super.c
===================================================================
--- trunk/src/super.c 2004-11-10 20:59:07 UTC (rev 1635)
+++ trunk/src/super.c 2004-11-10 22:18:57 UTC (rev 1636)
@@ -50,7 +50,6 @@
#include "ocfs1_fs_compat.h"
#include "alloc.h"
-#include "bitmap.h"
#include "extent_map.h"
#include "heartbeat.h"
#include "inode.h"
@@ -739,7 +738,6 @@
{
ocfs_super *osb;
__u32 numbits, freebits;
- unsigned int reserved_bits;
int status, ret = 0;
ocfs2_dinode *bm_lock;
struct buffer_head *bh = NULL;
@@ -770,23 +768,16 @@
bm_lock = (ocfs2_dinode *) bh->b_data;
- freebits = numbits = osb->cluster_bitmap.validbits;
+ numbits = le32_to_cpu(bm_lock->id1.bitmap1.i_total);
+ freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);
- if (numbits >= bm_lock->id1.bitmap1.i_used)
- freebits -= bm_lock->id1.bitmap1.i_used;
-
- /* take out the space reserved for system files */
- reserved_bits = ocfs2_clusters_for_bytes(sb, 8 * ONE_MEGA_BYTE);
- freebits -= reserved_bits;
-
buf->f_type = OCFS_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_namelen = OCFS2_MAX_FILENAME_LENGTH;
buf->f_bavail = buf->f_bfree;
buf->f_blocks = (sector_t) ((unsigned long) (numbits) *
(unsigned long) (osb->s_clustersize >>
- osb->sb->s_blocksize_bits) -
- reserved_bits);
+ osb->sb->s_blocksize_bits));
buf->f_bfree = (sector_t) (freebits *
(osb->s_clustersize >> osb->sb->s_blocksize_bits));
buf->f_bavail = buf->f_bfree;
@@ -1161,11 +1152,6 @@
}
spin_unlock (&mount_cnt_lock);
- down (&(OcfsGlobalCtxt.global_res));
- ocfs_uninitialize_bitmap(&osb->cluster_bitmap);
-// list_del(&osb->osb_next); /* this has been moved into ocfs_delete_osb */
- up (&(OcfsGlobalCtxt.global_res));
-
atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
if (AcquiredOSB) {
up (&(osb->osb_res));
@@ -1325,6 +1311,7 @@
u64 p_blkno;
struct buffer_head *publish_bh = NULL; /* our own publish sector */
struct buffer_head **publish_bhs = NULL; /* all the publish sectors */
+ struct buffer_head *bitmap_bh = NULL;
int i;
ocfs2_dinode *di = NULL;
struct inode *inode = NULL;
@@ -1515,6 +1502,7 @@
memcpy(osb->uuid, di->id2.i_super.s_uuid, MAX_VOL_ID_LENGTH);
osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);
osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno);
+ osb->first_cluster_group_blkno = le64_to_cpu(di->id2.i_super.s_first_cluster_group);
printk("vol_label: %s\n", osb->vol_label);
{
int ttt;
@@ -1611,39 +1599,21 @@
goto bail;
}
- status = ocfs2_extent_map_get_blocks(inode, 0ULL, 1, &p_blkno,
- NULL);
+ osb->bitmap_blkno = OCFS_I(inode)->ip_blkno;
+
+ status = ocfs_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0, inode);
+ iput(inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
}
+ di = (ocfs2_dinode *) bitmap_bh->b_data;
+ osb->bitmap_cpg = le32_to_cpu(di->id2.i_chain.cl_cpg);
+ osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total);
+ brelse(bitmap_bh);
+ printk("cluster bitmap inode: %llu, clusters per group: %u\n",
+ osb->bitmap_blkno, osb->bitmap_cpg);
- /* for now, just one extent... but in the future... */
- osb->bitmap_blkno = p_blkno;
- osb->bitmap_blocks =
- ocfs2_clusters_to_blocks(inode->i_sb,
- OCFS_I(inode)->ip_clusters);
- osb->num_clusters = OCFS_I(inode)->u.ip_bitinfo.total_bits;
- printk("bitmap_blkno=%llu, bitmap_blocks=%u, num_clusters=%u\n",
- osb->bitmap_blkno, osb->bitmap_blocks, osb->num_clusters);
-
- ocfs_initialize_bitmap(osb->sb, &osb->cluster_bitmap,
- osb->num_clusters,
- (u32)(ocfs2_clusters_to_bytes(inode->i_sb,
- OCFS_I(inode)->ip_clusters) << 3));
- /* read the whole cluster bitmap off disk, even though we only
- * need the beginning of it. */
- status = ocfs_read_blocks(osb,
- osb->bitmap_blkno,
- osb->bitmap_blocks,
- osb->cluster_bitmap.chunk, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- iput(inode);
-
-
osb->prealloc_lock = 0;
More information about the Ocfs2-commits
mailing list