[Ocfs2-commits] mfasheh commits r1538 - branches/dlm-changes/src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Fri Oct 1 17:07:14 CDT 2004
Author: mfasheh
Date: 2004-10-01 17:07:13 -0500 (Fri, 01 Oct 2004)
New Revision: 1538
Added:
branches/dlm-changes/src/localalloc.c
branches/dlm-changes/src/localalloc.h
Modified:
branches/dlm-changes/src/Makefile
branches/dlm-changes/src/alloc.c
branches/dlm-changes/src/journal.c
branches/dlm-changes/src/ocfs_log.h
branches/dlm-changes/src/super.c
Log:
* move the local alloc stuff into it's own file
Modified: branches/dlm-changes/src/Makefile
===================================================================
--- branches/dlm-changes/src/Makefile 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/Makefile 2004-10-01 22:07:13 UTC (rev 1538)
@@ -73,6 +73,7 @@
inode.c \
ioctl.c \
journal.c \
+ localalloc.c \
lockres.c \
namei.c \
nm.c \
@@ -106,6 +107,7 @@
inode.h \
ioctl.h \
journal.h \
+ localalloc.h \
lockres.h \
namei.h \
nm.h \
Modified: branches/dlm-changes/src/alloc.c
===================================================================
--- branches/dlm-changes/src/alloc.c 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/alloc.c 2004-10-01 22:07:13 UTC (rev 1538)
@@ -41,6 +41,7 @@
#include "dlm.h"
#include "extmap.h"
#include "inode.h"
+#include "localalloc.h"
#include "util.h"
#include "suballoc.h"
#include "sysfile.h"
@@ -110,41 +111,14 @@
struct buffer_head *bh,
ocfs_free_rec *freelog);
-/* The largest cluster size where we even consider using local alloc. */
-#define OCFS_LOCAL_ALLOC_MAX_CSIZE (128 * 1024)
-/* The largest allocation to use the local bitmap for. */
-#define OCFS_LOCAL_ALLOC_MAX_ALLOC (2 * 1024 * 1024)
-static inline int ocfs_local_alloc_window_bits(ocfs_super *osb);
-static inline int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits);
-static int ocfs_local_alloc_full_window_change(ocfs_super *osb,
- struct inode * local_alloc_inode);
-static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh,
- struct inode *bm_inode,
- ocfs_journal_handle *handle);
-static int ocfs_sync_local_from_shutdown(ocfs_super *osb,
- ocfs_bitmap_free_head **f,
- struct buffer_head *local_alloc_bh,
- int in_recovery);
-static __u32 ocfs_alloc_count_bits(ocfs2_dinode *alloc);
-static void ocfs_clear_local_alloc(ocfs2_dinode *alloc);
-static int ocfs_local_find_clear_bits(ocfs_super *osb,
- ocfs2_dinode *alloc,
- __u32 numbits);
static int ocfs_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
u64 blkno);
-static inline int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits);
-
static int ocfs_reserve_main_bitmap_bits(ocfs_super *osb,
ocfs_journal_handle *handle,
u32 bits_wanted,
ocfs2_alloc_context *ac);
-static int ocfs_reserve_local_bits(ocfs_super *osb,
- ocfs_journal_handle *passed_handle,
- u32 bits_wanted,
- ocfs2_alloc_context *ac);
-
static int ocfs_claim_main_bitmap_bits(ocfs_super *osb,
ocfs_journal_handle *handle,
ocfs2_alloc_context *ac,
@@ -152,13 +126,6 @@
u32 *bit_off,
u32 *num_bits);
-static int ocfs_claim_local_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_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
u64 blkno)
{
@@ -2789,12 +2756,12 @@
OCFS_ASSERT(ac->ac_handle == handle);
if (ac->ac_which == OCFS_AC_USE_LOCAL) {
- status = ocfs_claim_local_bitmap_bits(osb,
- handle,
- ac,
- min_bits,
- bit_off,
- num_bits);
+ status = ocfs_claim_local_alloc_bits(osb,
+ handle,
+ ac,
+ min_bits,
+ bit_off,
+ num_bits);
} else {
status = ocfs_claim_main_bitmap_bits(osb,
handle,
@@ -2904,62 +2871,6 @@
return(status);
}
-static int ocfs_claim_local_bitmap_bits(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_alloc_context *ac,
- u32 min_bits,
- u32 *bit_off,
- u32 *num_bits)
-{
- int status, start;
- struct inode *local_alloc_inode;
- u32 bits_wanted;
- void *bitmap;
- ocfs2_dinode *alloc;
-
- LOG_ENTRY();
- OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL);
-
- bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
- local_alloc_inode = ac->ac_inode;
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
- start = ocfs_local_find_clear_bits(osb, alloc, bits_wanted);
- if (start == -1) {
- /* TODO: Shouldn't we just BUG here? */
- status = -ENOSPC;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
- *bit_off = LOCAL_ALLOC(alloc)->la_bm_off + start;
- /* local alloc is always contiguous by nature -- we never
- * delete bits from it! */
- *num_bits = bits_wanted;
-
- status = ocfs_journal_access(handle, osb->local_alloc_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- while(bits_wanted--)
- set_bit(start++, bitmap);
-
- status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- 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,
@@ -2983,10 +2894,10 @@
status = -ENOSPC;
if (ocfs_alloc_should_use_local(osb, bits_wanted)) {
- status = ocfs_reserve_local_bits(osb,
- handle,
- bits_wanted,
- *ac);
+ status = ocfs_reserve_local_alloc_bits(osb,
+ handle,
+ bits_wanted,
+ *ac);
if ((status < 0) && (status != -ENOSPC)) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -3089,211 +3000,7 @@
return(status);
}
-/*
- * ocfs_reserve_local_bits
- *
- * make sure we've got at least bitswanted contiguous bits in the
- * local alloc. You lose them when you drop ip_io_sem.
- *
- * We will add ourselves to the transaction passed in, but may start
- * our own in order to shift windows.
- *
- * When we stop being lame and support multiple chunks of
- * discontiguous space, we this turns into a really simple check of
- * ->la_bits_set
- */
-static int ocfs_reserve_local_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;
-
- LOG_ENTRY();
-
- OCFS_ASSERT(passed_handle);
- OCFS_ASSERT(ac);
- OCFS_ASSERT(!(passed_handle->flags & OCFS_HANDLE_STARTED));
-
- local_alloc_inode =
- ocfs_get_system_file_inode(osb,
- LOCAL_ALLOC_SYSTEM_INODE,
- osb->node_num);
- if (!local_alloc_inode) {
- status = -ENOENT;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- ocfs_handle_add_inode(passed_handle, local_alloc_inode);
-
- if (!osb->have_local_alloc) {
- status = -ENOSPC;
- goto bail;
- }
-
-#warning "isn't it about time we turned this check off?"
- if (bits_wanted > ocfs_clusters_for_bytes(osb->sb,
- OCFS_LOCAL_ALLOC_MAX_ALLOC)) {
- LOG_TRACE_STR("Asking for more than max local alloction!\n");
- status = -ENOSPC;
- goto bail;
- }
-
- if (bits_wanted > ocfs_local_alloc_window_bits(osb)) {
- LOG_TRACE_STR("Asking for more than my max window size!\n");
- status = -ENOSPC;
- goto bail;
- }
-
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
- startoff = ocfs_local_find_clear_bits(osb, alloc, bits_wanted);
- if (startoff == -1) {
- /* uhoh, window change time. */
- status =
- ocfs_local_alloc_full_window_change(osb,
- local_alloc_inode);
- if (status < 0) {
- if (status != -ENOSPC)
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- }
-
- ac->ac_inode = igrab(local_alloc_inode);
- get_bh(osb->local_alloc_bh);
- ac->ac_bh = osb->local_alloc_bh;
-
- status = 0;
-bail:
- if (local_alloc_inode)
- iput(local_alloc_inode);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
/*
- * ocfs_find_contiguous_space_from_bitmap()
- *
- * Used only from local alloc right now. Eventually will go away, so
- * don't add more callers to this function. Use the reserve / claim
- * apis instead as they'll even get you distcongiuous areas.
- *
- * TODO: The Bitmap stuff needs to be changed for handling more than 32 bits...
- * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
- *
- * Returns 0 on success, < 0 on error.
- */
-static int ocfs_find_contiguous_space_from_bitmap(ocfs_super *osb,
- ocfs_journal_handle *handle,
- __u64 file_size,
- u32 *cluster_off,
- u32 *cluster_count,
- struct buffer_head *bh,
- struct inode *bitmap_inode)
-{
- int status = 0, startbh, numblocks;
- u32 bitoffset = 0, num_clusters = 0;
- ocfs2_dinode *bm_lock;
- __u32 bitmapblocks; /* we only care about the valid blocks */
- __u32 free_bits;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT(osb);
- OCFS_ASSERT(bh);
- OCFS_ASSERT(bitmap_inode);
- OCFS_ASSERT(handle);
-
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- bm_lock = (ocfs2_dinode *) bh->b_data;
-
- num_clusters = (u32) ((u64) (file_size + (osb->s_clustersize-1)) >>
- osb->s_clustersize_bits);
- if (num_clusters == 0) {
- LOG_ERROR_STR ("DISK_FULL?: num_clusters==0");
- status = 0;
- goto leave;
- }
-
- free_bits = le32_to_cpu(bm_lock->id1.bitmap1.i_total) -
- le32_to_cpu(bm_lock->id1.bitmap1.i_used);
-
- if (num_clusters > free_bits) {
- LOG_ERROR_ARGS("Disk Full: num_clusters=%u, free_bits=%u\n",
- num_clusters, free_bits);
- status = -ENOSPC;
- goto leave;
- }
-
- bitmapblocks =
- ocfs_blocks_for_bits(osb->sb,
- osb->cluster_bitmap.validbits);
-
- /* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
- if (ocfs_read_bhs(osb, osb->bitmap_blkno << osb->sb->s_blocksize_bits,
- bitmapblocks << osb->sb->s_blocksize_bits,
- osb->cluster_bitmap.chunk, OCFS_BH_CACHED, bitmap_inode)) {
- LOG_ERROR_STATUS(-EIO);
- goto leave;
- }
-
- status = 0;
- status = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
- num_clusters, &bitoffset,
- NULL);
- if (status < 0) {
- osb->cluster_bitmap.failed++;
- LOG_TRACE_ARGS("Cannot allocate %u contiguous clusters "
- "for system file\n", num_clusters);
- status = -ENOSPC;
- goto leave;
- }
-
- LOG_TRACE_ARGS ("setting %u bits at bit offset=%u\n",
- num_clusters, bitoffset);
-
- ocfs_set_bits(osb->sb, handle, &osb->cluster_bitmap, bitoffset,
- num_clusters);
-
- /* Ok, write out the bitmap now. We optimize only by writing
- * out the bitmap blocks which have changed, and not all of
- * them like before. */
- numblocks = ocfs_bitmap_blocks_affected(osb->sb,
- bitoffset,
- num_clusters,
- &startbh);
-
- LOG_TRACE_ARGS("bitoffset = %u, num_clusters = %u, startbh = %u, numblocks = %u\n", bitoffset, num_clusters, startbh, numblocks);
-
- /* write the bitmap size info to the lock sector */
- bm_lock->id1.bitmap1.i_used =
- ocfs_count_bits(osb->sb, &osb->cluster_bitmap);
-
- status = ocfs_journal_dirty(handle, bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- *cluster_off = bitoffset;
- *cluster_count = num_clusters;
- status = 0;
-
-leave:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_find_contiguous_space_from_bitmap */
-
-/*
* ocfs_free_file_extents()
*
*/
@@ -3364,739 +3071,3 @@
return status;
} /* ocfs_free_file_extents */
-/* Some constants and functions that control how we allocate and use
- * local alloc bitmaps. These are intended to be easily
- * tunable. Possibly even remove them once we've found a good mix. */
-
-/*
- * ocfs_local_alloc_window_bits
- *
- * Determine how large our local alloc window should be, in bits. This
- * is entirely changeable -- just replace this function. Right now as
- * a *testing* default, we have a function that takes cluster size
- * into account in the following manner:
- *
- * 4k -> 1024 bits, 8k -> 512 bits, 16k -> 256 bits,
- * 32k -> 128 bits, 64k -> 64 bits
- */
-static inline int ocfs_local_alloc_window_bits(ocfs_super *osb)
-{
- int numbits;
-
- switch (osb->s_clustersize) {
- case (4*1024):
- numbits = 1024;
- break;
-
- case (8*1024):
- numbits = 512;
- break;
-
- case (16*1024):
- numbits = 256;
- break;
-
- case (32*1024):
- numbits = 128;
- break;
-
- default:
- numbits = 64;
- break;
- }
- return(numbits);
-} /* ocfs_local_alloc_window_bits */
-
-static inline int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits)
-{
- if (osb->have_local_alloc
- && ((bits<<osb->s_clustersize_bits) <= OCFS_LOCAL_ALLOC_MAX_ALLOC)
- && (bits <= ocfs_local_alloc_window_bits(osb)))
- return(1);
- return(0);
-}
-
-/*
- * ocfs_alloc_count_bits
- */
-static __u32 ocfs_alloc_count_bits(ocfs2_dinode *alloc)
-{
- int i;
- __u8 tmp;
- __u8 *buffer;
- __u32 count = 0;
-
- LOG_ENTRY();
-
- buffer = LOCAL_ALLOC(alloc)->la_bitmap;
- for (i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++) {
- memcpy(&tmp, buffer, 1);
- count+= BITCOUNT(tmp);
- buffer++;
- }
-
- LOG_EXIT_ULONG ((unsigned long)count);
- return(count);
-} /* ocfs_alloc_count_bits */
-
-/*
- * ocfs_clear_local_alloc
- */
-static void ocfs_clear_local_alloc(ocfs2_dinode *alloc)
-{
- int i;
- LOG_ENTRY();
-
- LOCAL_ALLOC(alloc)->la_bm_bits = 0;
- LOCAL_ALLOC(alloc)->la_bits_set = 0;
- LOCAL_ALLOC(alloc)->la_bm_off = 0;
- for(i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++)
- LOCAL_ALLOC(alloc)->la_bitmap[i] = 0;
-
- LOG_EXIT();
- return;
-} /* ocfs_clear_local_alloc */
-
-/*
- * ocfs_sync_local_to_main
- *
- * sync the local alloc to main bitmap.
- *
- * assumes you've already locked the main bitmap -- the bitmap inode
- * passed is used for caching.
- */
-static int ocfs_sync_local_to_main(ocfs_super *osb,
- ocfs_journal_handle *handle,
- ocfs2_dinode *alloc,
- struct inode *main_bm_inode,
- struct buffer_head *main_bm_bh)
-{
- int status = 0;
- int bit_off, left;
- 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,
- ocfs_alloc_count_bits(alloc),
- LOCAL_ALLOC(alloc)->la_bits_set);
-
- if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
- LOG_TRACE_STR("nothing to sync!");
- 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_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_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- 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_bhs(osb,
- (osb->bitmap_blkno + start) << osb->sb->s_blocksize_bits,
- numblocks << osb->sb->s_blocksize_bits,
- &osb->cluster_bitmap.chunk[start], OCFS_BH_CACHED,
- main_bm_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
- /* any unset bits in local alloc need to be unset in bitmap. */
- bit_off = 0;
- left = LOCAL_ALLOC(alloc)->la_bm_bits;
- while ((bit_off = find_next_zero_bit(bitmap, left, bit_off))
- != -1) {
- if (bit_off >= left) {
- /*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
- break;
- }
-
- LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n",
- bit_off + LOCAL_ALLOC(alloc)->la_bm_off);
- ocfs_clear_bits(osb->sb, handle, &osb->cluster_bitmap,
- bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
- 1);
- bm_fe->id1.bitmap1.i_used--;
- bit_off++;
- }
-
- status = ocfs_journal_dirty(handle, main_bm_bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
-bail:
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_sync_local_to_main */
-
-/*
- * This essentially does the same thing as sync_local_to_main, but
- * without a journal handle -- used during shutdown and recovery.
- */
-static int ocfs_sync_local_from_shutdown(ocfs_super *osb,
- ocfs_bitmap_free_head **f,
- struct buffer_head *local_alloc_bh,
- int in_recovery)
-{
- int status = 0;
- int bit_off, left;
- ocfs2_dinode *alloc = NULL;
- void *bitmap;
-
- LOG_ENTRY();
-
- if (!local_alloc_bh)
- BUG();
-
- alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
- if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
- LOG_TRACE_STR("nothing to sync!");
- goto bail;
- }
-
- if (!(*f)) {
- *f = ocfs_alloc_bitmap_free_head();
- if (*f == NULL) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto bail;
- }
- }
-
- alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
-
- LOG_TRACE_ARGS("alloc->la_bm_bits = %u, COUNT = %u, la_bits_set = %u\n",
- LOCAL_ALLOC(alloc)->la_bm_bits,
- ocfs_alloc_count_bits(alloc),
- LOCAL_ALLOC(alloc)->la_bits_set);
-
- bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-
- /* any unset bits in local alloc need to be unset in bitmap. */
- bit_off = 0;
- left = LOCAL_ALLOC(alloc)->la_bm_bits;
- while ((bit_off = find_next_zero_bit(bitmap, left, bit_off))
- != -1) {
- if (bit_off >= left) {
- /*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
- break;
- }
- /* LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n", bit_off);*/
- status = ocfs_add_to_bitmap_free_head(osb,
- *f, 1,
- bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
- -1, 0, DISK_ALLOC_VOLUME);
- if (status < 0) {
- ocfs_free_bitmap_free_head(*f);
- *f = NULL;
- }
- bit_off++;
- }
-
-bail:
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_sync_local_from_shutdown */
-
-/*
- * ocfs_alloc_new_window
- *
- * pass it the bitmap lock in lock_bh if you have it.
- */
-static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh,
- struct inode *bm_inode,
- ocfs_journal_handle *handle)
-{
- int status = 0;
- __u64 alloc_bytes;
- u32 cluster_off, cluster_count;
- ocfs2_dinode *alloc = NULL;
-
- LOG_ENTRY();
-
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
- if (LOCAL_ALLOC(alloc)->la_bm_bits != 0)
- LOG_TRACE_STR("asking me to alloc a new window over a"
- " non-empty one");
-
- /* we try to use find_contig_space_from_bitmap here for now. */
- alloc_bytes = (u64)ocfs_local_alloc_window_bits(osb) << osb->s_clustersize_bits;
- LOG_TRACE_ARGS("Allocating %llu bytes (%u clusters) for a "
- "new window.\n", alloc_bytes,
- ocfs_local_alloc_window_bits(osb));
-
- status = ocfs_find_contiguous_space_from_bitmap(osb, handle,
- alloc_bytes,
- &cluster_off,
- &cluster_count,
- lock_bh,
- bm_inode);
- if (status < 0) {
- if (status != -ENOSPC)
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- atomic_inc(&osb->alloc_stats.bitmap_data);
-
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
- LOCAL_ALLOC(alloc)->la_bm_off = cluster_off;
- LOCAL_ALLOC(alloc)->la_bm_bits = cluster_count;
- /* just in case... In the future when we find space ourselves,
- * we don't have to get all contiguous -- but we'll have to
- * set all previously used bits in bitmap and update
- * la_bits_set before setting the bits in the main bitmap. */
- LOCAL_ALLOC(alloc)->la_bits_set = 0;
- memset(LOCAL_ALLOC(alloc)->la_bitmap, 0,
- LOCAL_ALLOC(alloc)->la_size);
-
- LOG_TRACE_STR("New window allocated:");
- LOG_TRACE_ARGS("window la_bm_off = %u\n",
- LOCAL_ALLOC(alloc)->la_bm_off);
- LOG_TRACE_ARGS("window la_bm_bits = %u\n",
- LOCAL_ALLOC(alloc)->la_bm_bits);
-
-bail:
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_alloc_new_window */
-
-/*
- * ocfs_local_find_clear_bits
- */
-static int ocfs_local_find_clear_bits(ocfs_super *osb,
- ocfs2_dinode *alloc,
- __u32 numbits)
-{
- int numfound, bitoff, left, startoff, lastzero;
- void *bitmap = NULL;
-
- LOG_ENTRY_ARGS("(numbits wanted = %u)\n", numbits);
-
- if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
- LOG_TRACE_STR("No bits in my window!");
- bitoff = -1;
- goto bail;
- }
-
- bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-
- numfound = bitoff = startoff = 0;
- lastzero = -1;
- left = LOCAL_ALLOC(alloc)->la_bm_bits;
- while ((bitoff = find_next_zero_bit(bitmap, left, startoff)) != -1) {
- if (bitoff == left) {
- /* LOG_TRACE_ARGS("bitoff (%d) == left", bitoff); */
- break;
- }
- /* LOG_TRACE_ARGS("Found a zero: bitoff = %d, startoff = %d, "
- "numfound = %d\n", bitoff, startoff, numfound);*/
-
- /* Ok, we found a zero bit... is it contig. or do we
- * start over?*/
- if (bitoff == startoff) {
- /* we found a zero */
- numfound++;
- startoff++;
- } else {
- /* got a zero after some ones */
- numfound = 1;
- startoff = bitoff+1;
- }
- /* we got everything we needed */
- if (numfound == numbits) {
- /* LOG_TRACE_STR("Found it all!"); */
- break;
- }
- }
-
- LOG_TRACE_ARGS("Exiting loop, bitoff = %d, numfound = %d\n", bitoff,
- numfound);
-
- if (numfound == numbits)
- bitoff = startoff - numfound;
- else
- bitoff = -1;
-
-bail:
- LOG_EXIT_STATUS(bitoff);
- return(bitoff);
-} /* ocfs_local_find_clear_bits */
-
-/* Note that we do *NOT* lock the local alloc inode here as
- * it's been locked already for us. */
-static int ocfs_local_alloc_full_window_change(ocfs_super *osb,
- struct inode *local_alloc_inode)
-{
- int status = 0;
- struct buffer_head *main_bm_bh = NULL;
- struct inode *main_bm_inode = NULL;
- ocfs_journal_handle *handle = NULL;
- ocfs2_dinode *alloc;
- ocfs2_dinode *alloc_copy = NULL;
-
- LOG_ENTRY();
-
- main_bm_inode = ocfs_get_system_file_inode(osb,
- GLOBAL_BITMAP_SYSTEM_INODE,
- -1);
- if (!main_bm_inode) {
- status = -EINVAL;
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- handle = ocfs_alloc_handle(osb);
- if (!handle) {
- status = -ENOMEM;
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* Get the allocation lock here */
- status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE,
- 0, &main_bm_bh, main_bm_inode);
- if (status < 0) {
- main_bm_bh = NULL;
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE,
- 0, main_bm_inode);
- ocfs_handle_add_inode(handle, main_bm_inode);
-
- handle = ocfs_start_trans(osb, handle, OCFS_WINDOW_MOVE_CREDITS);
- if (!handle) {
- status = -ENOMEM;
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- ocfs_handle_set_always_commits(handle, 1);
-
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
- /* We want to clear the local alloc before doing anything
- * else, so that if we error later during this operation,
- * local alloc shutdown won't try to double free main bitmap
- * bits. Make a copy so the sync function knows which bits to
- * free. */
- alloc_copy = kmalloc(osb->local_alloc_bh->b_size, GFP_KERNEL);
- if (!alloc_copy) {
- status = -ENOMEM;
- goto bail;
- }
- memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
-
- status = ocfs_journal_access(handle, osb->local_alloc_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- ocfs_clear_local_alloc(alloc);
-
- status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = ocfs_sync_local_to_main(osb, handle, alloc_copy,
- main_bm_inode, main_bm_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = ocfs_alloc_new_window(osb, main_bm_bh, main_bm_inode, handle);
- if (status < 0) {
- if (status != -ENOSPC)
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- atomic_inc(&osb->alloc_stats.moves);
-
- status = 0;
-bail:
- if (handle)
- ocfs_commit_trans(handle);
-
- if (main_bm_bh)
- brelse(main_bm_bh);
-
- if (main_bm_inode)
- iput(main_bm_inode);
-
- if (alloc_copy)
- kfree(alloc_copy);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- * ocfs_load_local_alloc
- */
-int ocfs_load_local_alloc(ocfs_super *osb)
-{
- int status = 0;
- ocfs2_dinode *alloc = NULL;
- struct buffer_head *alloc_bh = NULL;
- __u32 num_used;
- struct inode *inode = NULL;
-
- LOG_ENTRY();
-
- /* we don't enable local alloc on cluster sizes >= 128k */
- if (osb->s_clustersize > OCFS_LOCAL_ALLOC_MAX_CSIZE)
- goto bail;
-
- /* read the alloc off disk */
- inode = ocfs_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE, osb->node_num);
- if (!inode) {
- LOG_ERROR_STATUS(status=-EINVAL);
- goto bail;
- }
- status = ocfs_read_bh(osb,
- OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
- &alloc_bh, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs2_dinode *) alloc_bh->b_data;
-
- /* do a little verification. */
- num_used = ocfs_alloc_count_bits(alloc);
-
- /* nowadays the local alloc has always been recovered before
- * we load it so there should be no bits used from the main
- * bitmap. */
- if (num_used
- || LOCAL_ALLOC(alloc)->la_bits_set
- || LOCAL_ALLOC(alloc)->la_bm_bits
- || LOCAL_ALLOC(alloc)->la_bm_off) {
- LOG_ERROR_ARGS("Local alloc hasn't been recovered!\n"
- "found = %u, set = %u, taken = %u, off = %u\n",
- num_used,
- LOCAL_ALLOC(alloc)->la_bits_set,
- LOCAL_ALLOC(alloc)->la_bm_bits,
- LOCAL_ALLOC(alloc)->la_bm_off);
- status = -EFAIL;
- goto bail;
- }
-
- if (!LOCAL_ALLOC(alloc)->la_size ||
- (LOCAL_ALLOC(alloc)->la_size > ocfs2_local_alloc_size(inode->i_sb))) {
- LOG_ERROR_ARGS("Local alloc size is invalid (la_size = %u)\n",
- LOCAL_ALLOC(alloc)->la_size);
- status = -EINVAL;
- goto bail;
- }
-
- osb->local_alloc_bh = alloc_bh;
- osb->have_local_alloc = 1;
-
-bail:
- if (status < 0)
- if (alloc_bh)
- brelse(alloc_bh);
- if (inode)
- iput(inode);
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_load_local_alloc */
-
-/*
- * ocfs_shutdown_local_alloc
- *
- * return any unused bits to the bitmap and write out a clean
- * local_alloc.
- *
- * local_alloc_bh is optional. If not passed, we will simply use the
- * one off osb. If you do pass it however, be warned that it *will* be
- * returned brelse'd and NULL'd out.*/
-void ocfs_shutdown_local_alloc(ocfs_super *osb)
-{
- int status;
- ocfs2_dinode *alloc = NULL;
- ocfs_bitmap_free_head *f = NULL;
- struct buffer_head *bh = NULL;
- ocfs_journal_handle *handle = NULL;
- struct inode *local_alloc_inode = NULL;
- ocfs_inode_private *oip;
-
- LOG_ENTRY();
-
- local_alloc_inode =
- ocfs_get_system_file_inode(osb,
- LOCAL_ALLOC_SYSTEM_INODE,
- osb->node_num);
- if (!local_alloc_inode) {
- status = -ENOENT;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- oip = OCFS_I(local_alloc_inode);
-
- /* Take io_sem here to turn off local alloc before another guy
- * can come in and start using him. */
- down_write(&oip->ip_io_sem);
- if (!osb->have_local_alloc) {
- up_write(&oip->ip_io_sem);
- goto bail;
- }
- osb->have_local_alloc = 0;
- up_write(&oip->ip_io_sem);
-
- bh = osb->local_alloc_bh;
-
- status = ocfs_sync_local_from_shutdown(osb, &f, bh, 0);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- handle = ocfs_start_trans(osb, NULL, 1);
- if (!handle) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto bail;
- }
- ocfs_handle_set_always_commits(handle, 1);
-
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs2_dinode *) bh->b_data;
- ocfs_clear_local_alloc(alloc);
-
- status = ocfs_journal_dirty(handle, bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- brelse(bh);
-
- ocfs_commit_trans(handle);
- handle = NULL;
-
- osb->local_alloc_bh = NULL;
- osb->have_local_alloc = 0;
-
- if (f)
- ocfs_process_bitmap_free_head(osb, f);
-
-bail:
- if (handle)
- ocfs_commit_trans(handle);
-
- if (f)
- ocfs_free_bitmap_free_head(f);
-
- if (local_alloc_inode)
- iput(local_alloc_inode);
-
- LOG_EXIT();
- return;
-} /* ocfs_shutdown_local_alloc */
-
-/*
- * ocfs_recover_local_alloc
- *
- * We want to free the bitmap bits outside of any recovery context, so
- * it's allocated and passed back for you.
- */
-int ocfs_recover_local_alloc(ocfs_super *osb,
- int node_num,
- ocfs_bitmap_free_head **bits_to_free)
-{
- int status = 0;
- struct buffer_head *alloc_bh = NULL;
- struct inode *inode = NULL;
- ocfs2_dinode *alloc;
-
- LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
-
- inode = ocfs_get_system_file_inode(osb,
- LOCAL_ALLOC_SYSTEM_INODE,
- node_num);
- if (!inode) {
- LOG_ERROR_STATUS(status=-EINVAL);
- goto bail;
- }
-
- status = ocfs_read_bh(osb,
- OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
- &alloc_bh,
- 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = ocfs_sync_local_from_shutdown(osb,
- bits_to_free,
- alloc_bh,
- 1);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs2_dinode *) alloc_bh->b_data;
- ocfs_clear_local_alloc(alloc);
-
- status = ocfs_write_bh(osb, alloc_bh, inode);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
-bail:
- if (alloc_bh)
- brelse(alloc_bh);
-
- if (inode)
- iput(inode);
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_recover_local_alloc */
Modified: branches/dlm-changes/src/journal.c
===================================================================
--- branches/dlm-changes/src/journal.c 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/journal.c 2004-10-01 22:07:13 UTC (rev 1538)
@@ -41,6 +41,7 @@
#include "extmap.h"
#include "inode.h"
#include "journal.h"
+#include "localalloc.h"
#include "lockres.h"
#include "namei.h"
#include "nm.h"
Added: branches/dlm-changes/src/localalloc.c
===================================================================
--- branches/dlm-changes/src/localalloc.c 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/localalloc.c 2004-10-01 22:07:13 UTC (rev 1538)
@@ -0,0 +1,1091 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * localalloc.c
+ *
+ * Node local data allocation
+ *
+ * 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.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ * Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_LOCALALLOC
+
+#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 "alloc.h"
+#include "bitmap.h"
+#include "dlm.h"
+#include "extmap.h"
+#include "inode.h"
+#include "localalloc.h"
+#include "util.h"
+#include "suballoc.h"
+#include "sysfile.h"
+#include "file.h"
+
+#include "ocfs_journal.h"
+#include "buffer_head_io.h"
+
+/* The largest cluster size where we even consider using local alloc. */
+#define OCFS_LOCAL_ALLOC_MAX_CSIZE (128 * 1024)
+
+/* The largest allocation to use the local bitmap for. */
+#define OCFS_LOCAL_ALLOC_MAX_ALLOC (2 * 1024 * 1024)
+
+static inline int ocfs_local_alloc_window_bits(ocfs_super *osb);
+
+static __u32 ocfs_local_alloc_count_bits(ocfs2_dinode *alloc);
+
+static int ocfs_local_alloc_find_clear_bits(ocfs_super *osb,
+ ocfs2_dinode *alloc,
+ __u32 numbits);
+
+static void ocfs_clear_local_alloc(ocfs2_dinode *alloc);
+
+static int ocfs_local_alloc_new_window(ocfs_super *osb,
+ struct buffer_head *lock_bh,
+ struct inode *bm_inode,
+ ocfs_journal_handle *handle);
+
+static int ocfs_sync_local_from_shutdown(ocfs_super *osb,
+ ocfs_bitmap_free_head **f,
+ struct buffer_head *local_alloc_bh,
+ int in_recovery);
+
+static int ocfs_sync_local_to_main(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_dinode *alloc,
+ struct inode *main_bm_inode,
+ struct buffer_head *main_bm_bh);
+
+static int ocfs_local_alloc_slide_window(ocfs_super *osb,
+ struct inode * local_alloc_inode);
+
+static int ocfs_find_contiguous_space_from_bitmap(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ __u64 file_size,
+ u32 *cluster_off,
+ u32 *cluster_count,
+ struct buffer_head *bh,
+ struct inode *bitmap_inode);
+
+/*
+ * ocfs_local_alloc_window_bits
+ *
+ * Determine how large our local alloc window should be, in bits. This
+ * is entirely changeable -- just replace this function. Right now as
+ * a *testing* default, we have a function that takes cluster size
+ * into account in the following manner:
+ *
+ * 4k -> 1024 bits, 8k -> 512 bits, 16k -> 256 bits,
+ * 32k -> 128 bits, 64k -> 64 bits
+ */
+static inline int ocfs_local_alloc_window_bits(ocfs_super *osb)
+{
+ int numbits;
+
+ switch (osb->s_clustersize) {
+ case (4*1024):
+ numbits = 1024;
+ break;
+
+ case (8*1024):
+ numbits = 512;
+ break;
+
+ case (16*1024):
+ numbits = 256;
+ break;
+
+ case (32*1024):
+ numbits = 128;
+ break;
+
+ default:
+ numbits = 64;
+ break;
+ }
+ return(numbits);
+} /* ocfs_local_alloc_window_bits */
+
+int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits)
+{
+ if (osb->have_local_alloc
+ && ((bits<<osb->s_clustersize_bits) <= OCFS_LOCAL_ALLOC_MAX_ALLOC)
+ && (bits <= ocfs_local_alloc_window_bits(osb)))
+ return(1);
+ return(0);
+}
+
+/*
+ * ocfs_load_local_alloc
+ */
+int ocfs_load_local_alloc(ocfs_super *osb)
+{
+ int status = 0;
+ ocfs2_dinode *alloc = NULL;
+ struct buffer_head *alloc_bh = NULL;
+ __u32 num_used;
+ struct inode *inode = NULL;
+
+ LOG_ENTRY();
+
+ /* we don't enable local alloc on cluster sizes >= 128k */
+ if (osb->s_clustersize > OCFS_LOCAL_ALLOC_MAX_CSIZE)
+ goto bail;
+
+ /* read the alloc off disk */
+ inode = ocfs_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE,
+ osb->node_num);
+ if (!inode) {
+ LOG_ERROR_STATUS(status=-EINVAL);
+ goto bail;
+ }
+ status = ocfs_read_bh(osb,
+ OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
+ &alloc_bh, 0, inode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ alloc = (ocfs2_dinode *) alloc_bh->b_data;
+
+ /* do a little verification. */
+ num_used = ocfs_local_alloc_count_bits(alloc);
+
+ /* nowadays the local alloc has always been recovered before
+ * we load it so there should be no bits used from the main
+ * bitmap. */
+ if (num_used
+ || LOCAL_ALLOC(alloc)->la_bits_set
+ || LOCAL_ALLOC(alloc)->la_bm_bits
+ || LOCAL_ALLOC(alloc)->la_bm_off) {
+ LOG_ERROR_ARGS("Local alloc hasn't been recovered!\n"
+ "found = %u, set = %u, taken = %u, off = %u\n",
+ num_used,
+ LOCAL_ALLOC(alloc)->la_bits_set,
+ LOCAL_ALLOC(alloc)->la_bm_bits,
+ LOCAL_ALLOC(alloc)->la_bm_off);
+ status = -EFAIL;
+ goto bail;
+ }
+
+ if (!LOCAL_ALLOC(alloc)->la_size ||
+ (LOCAL_ALLOC(alloc)->la_size > ocfs2_local_alloc_size(inode->i_sb))) {
+ LOG_ERROR_ARGS("Local alloc size is invalid (la_size = %u)\n",
+ LOCAL_ALLOC(alloc)->la_size);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ osb->local_alloc_bh = alloc_bh;
+ osb->have_local_alloc = 1;
+
+bail:
+ if (status < 0)
+ if (alloc_bh)
+ brelse(alloc_bh);
+ if (inode)
+ iput(inode);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_load_local_alloc */
+
+/*
+ * ocfs_shutdown_local_alloc
+ *
+ * return any unused bits to the bitmap and write out a clean
+ * local_alloc.
+ *
+ * local_alloc_bh is optional. If not passed, we will simply use the
+ * one off osb. If you do pass it however, be warned that it *will* be
+ * returned brelse'd and NULL'd out.*/
+void ocfs_shutdown_local_alloc(ocfs_super *osb)
+{
+ int status;
+ ocfs2_dinode *alloc = NULL;
+ ocfs_bitmap_free_head *f = NULL;
+ struct buffer_head *bh = NULL;
+ ocfs_journal_handle *handle = NULL;
+ struct inode *local_alloc_inode = NULL;
+ ocfs_inode_private *oip;
+
+ LOG_ENTRY();
+
+ local_alloc_inode =
+ ocfs_get_system_file_inode(osb,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ osb->node_num);
+ if (!local_alloc_inode) {
+ status = -ENOENT;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ oip = OCFS_I(local_alloc_inode);
+
+ /* Take io_sem here to turn off local alloc before another guy
+ * can come in and start using him. */
+ down_write(&oip->ip_io_sem);
+ if (!osb->have_local_alloc) {
+ up_write(&oip->ip_io_sem);
+ goto bail;
+ }
+ osb->have_local_alloc = 0;
+ up_write(&oip->ip_io_sem);
+
+ bh = osb->local_alloc_bh;
+
+ status = ocfs_sync_local_from_shutdown(osb, &f, bh, 0);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+
+ handle = ocfs_start_trans(osb, NULL, 1);
+ if (!handle) {
+ LOG_ERROR_STATUS(-ENOMEM);
+ goto bail;
+ }
+ ocfs_handle_set_always_commits(handle, 1);
+
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ alloc = (ocfs2_dinode *) bh->b_data;
+ ocfs_clear_local_alloc(alloc);
+
+ status = ocfs_journal_dirty(handle, bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ brelse(bh);
+
+ ocfs_commit_trans(handle);
+ handle = NULL;
+
+ osb->local_alloc_bh = NULL;
+ osb->have_local_alloc = 0;
+
+ if (f)
+ ocfs_process_bitmap_free_head(osb, f);
+
+bail:
+ if (handle)
+ ocfs_commit_trans(handle);
+
+ if (f)
+ ocfs_free_bitmap_free_head(f);
+
+ if (local_alloc_inode)
+ iput(local_alloc_inode);
+
+ LOG_EXIT();
+ return;
+} /* ocfs_shutdown_local_alloc */
+
+/*
+ * ocfs_recover_local_alloc
+ *
+ * We want to free the bitmap bits outside of any recovery context, so
+ * it's allocated and passed back for you.
+ */
+int ocfs_recover_local_alloc(ocfs_super *osb,
+ int node_num,
+ ocfs_bitmap_free_head **bits_to_free)
+{
+ int status = 0;
+ struct buffer_head *alloc_bh = NULL;
+ struct inode *inode = NULL;
+ ocfs2_dinode *alloc;
+
+ LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
+
+ inode = ocfs_get_system_file_inode(osb,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ node_num);
+ if (!inode) {
+ LOG_ERROR_STATUS(status=-EINVAL);
+ goto bail;
+ }
+
+ status = ocfs_read_bh(osb,
+ OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
+ &alloc_bh,
+ 0, inode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ status = ocfs_sync_local_from_shutdown(osb,
+ bits_to_free,
+ alloc_bh,
+ 1);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ alloc = (ocfs2_dinode *) alloc_bh->b_data;
+ ocfs_clear_local_alloc(alloc);
+
+ status = ocfs_write_bh(osb, alloc_bh, inode);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+
+bail:
+ if (alloc_bh)
+ brelse(alloc_bh);
+
+ if (inode)
+ iput(inode);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_recover_local_alloc */
+
+/*
+ * ocfs_reserve_local_alloc_bits
+ *
+ * make sure we've got at least bitswanted contiguous bits in the
+ * local alloc. You lose them when you drop ip_io_sem.
+ *
+ * We will add ourselves to the transaction passed in, but may start
+ * our own in order to shift windows.
+ *
+ * When we stop being lame and support multiple chunks of
+ * discontiguous space, we this turns into a really simple check of
+ * ->la_bits_set
+ */
+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;
+
+ LOG_ENTRY();
+
+ OCFS_ASSERT(passed_handle);
+ OCFS_ASSERT(ac);
+ OCFS_ASSERT(!(passed_handle->flags & OCFS_HANDLE_STARTED));
+
+ local_alloc_inode =
+ ocfs_get_system_file_inode(osb,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ osb->node_num);
+ if (!local_alloc_inode) {
+ status = -ENOENT;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ ocfs_handle_add_inode(passed_handle, local_alloc_inode);
+
+ if (!osb->have_local_alloc) {
+ status = -ENOSPC;
+ goto bail;
+ }
+
+#warning "isn't it about time we turned this check off?"
+ if (bits_wanted > ocfs_clusters_for_bytes(osb->sb,
+ OCFS_LOCAL_ALLOC_MAX_ALLOC)) {
+ LOG_TRACE_STR("Asking for more than max local alloction!\n");
+ status = -ENOSPC;
+ goto bail;
+ }
+
+ if (bits_wanted > ocfs_local_alloc_window_bits(osb)) {
+ LOG_TRACE_STR("Asking for more than my max window size!\n");
+ status = -ENOSPC;
+ goto bail;
+ }
+
+ alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+ startoff = ocfs_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+ if (startoff == -1) {
+ /* uhoh, window change time. */
+ status =
+ ocfs_local_alloc_slide_window(osb, local_alloc_inode);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ }
+
+ ac->ac_inode = igrab(local_alloc_inode);
+ get_bh(osb->local_alloc_bh);
+ ac->ac_bh = osb->local_alloc_bh;
+
+ status = 0;
+bail:
+ if (local_alloc_inode)
+ iput(local_alloc_inode);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+}
+
+int ocfs_claim_local_alloc_bits(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_alloc_context *ac,
+ u32 min_bits,
+ u32 *bit_off,
+ u32 *num_bits)
+{
+ int status, start;
+ struct inode *local_alloc_inode;
+ u32 bits_wanted;
+ void *bitmap;
+ ocfs2_dinode *alloc;
+
+ LOG_ENTRY();
+ OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL);
+
+ bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+ local_alloc_inode = ac->ac_inode;
+ alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+ start = ocfs_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+ if (start == -1) {
+ /* TODO: Shouldn't we just BUG here? */
+ status = -ENOSPC;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+ *bit_off = LOCAL_ALLOC(alloc)->la_bm_off + start;
+ /* local alloc is always contiguous by nature -- we never
+ * delete bits from it! */
+ *num_bits = bits_wanted;
+
+ status = ocfs_journal_access(handle, osb->local_alloc_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ while(bits_wanted--)
+ set_bit(start++, bitmap);
+
+ status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ LOG_EXIT_STATUS(status);
+ return(status);
+}
+
+/*
+ * ocfs_local_alloc_count_bits
+ */
+static __u32 ocfs_local_alloc_count_bits(ocfs2_dinode *alloc)
+{
+ int i;
+ __u8 tmp;
+ __u8 *buffer;
+ __u32 count = 0;
+
+ LOG_ENTRY();
+
+ buffer = LOCAL_ALLOC(alloc)->la_bitmap;
+ for (i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++) {
+ memcpy(&tmp, buffer, 1);
+ count+= BITCOUNT(tmp);
+ buffer++;
+ }
+
+ LOG_EXIT_ULONG ((unsigned long)count);
+ return(count);
+} /* ocfs_local_alloc_count_bits */
+
+/*
+ * ocfs_local_alloc_find_clear_bits
+ */
+static int ocfs_local_alloc_find_clear_bits(ocfs_super *osb,
+ ocfs2_dinode *alloc,
+ __u32 numbits)
+{
+ int numfound, bitoff, left, startoff, lastzero;
+ void *bitmap = NULL;
+
+ LOG_ENTRY_ARGS("(numbits wanted = %u)\n", numbits);
+
+ if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
+ LOG_TRACE_STR("No bits in my window!");
+ bitoff = -1;
+ goto bail;
+ }
+
+ bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+
+ numfound = bitoff = startoff = 0;
+ lastzero = -1;
+ left = LOCAL_ALLOC(alloc)->la_bm_bits;
+ while ((bitoff = find_next_zero_bit(bitmap, left, startoff)) != -1) {
+ if (bitoff == left) {
+ /* LOG_TRACE_ARGS("bitoff (%d) == left", bitoff); */
+ break;
+ }
+ /* LOG_TRACE_ARGS("Found a zero: bitoff = %d, startoff = %d, "
+ "numfound = %d\n", bitoff, startoff, numfound);*/
+
+ /* Ok, we found a zero bit... is it contig. or do we
+ * start over?*/
+ if (bitoff == startoff) {
+ /* we found a zero */
+ numfound++;
+ startoff++;
+ } else {
+ /* got a zero after some ones */
+ numfound = 1;
+ startoff = bitoff+1;
+ }
+ /* we got everything we needed */
+ if (numfound == numbits) {
+ /* LOG_TRACE_STR("Found it all!"); */
+ break;
+ }
+ }
+
+ LOG_TRACE_ARGS("Exiting loop, bitoff = %d, numfound = %d\n", bitoff,
+ numfound);
+
+ if (numfound == numbits)
+ bitoff = startoff - numfound;
+ else
+ bitoff = -1;
+
+bail:
+ LOG_EXIT_STATUS(bitoff);
+ return(bitoff);
+} /* ocfs_local_find_alloc_clear_bits */
+
+/*
+ * ocfs_clear_local_alloc
+ */
+static void ocfs_clear_local_alloc(ocfs2_dinode *alloc)
+{
+ int i;
+ LOG_ENTRY();
+
+ LOCAL_ALLOC(alloc)->la_bm_bits = 0;
+ LOCAL_ALLOC(alloc)->la_bits_set = 0;
+ LOCAL_ALLOC(alloc)->la_bm_off = 0;
+ for(i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++)
+ LOCAL_ALLOC(alloc)->la_bitmap[i] = 0;
+
+ LOG_EXIT();
+ return;
+} /* ocfs_clear_local_alloc */
+
+/*
+ * ocfs_local_alloc_new_window
+ *
+ * pass it the bitmap lock in lock_bh if you have it.
+ */
+static int ocfs_local_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh,
+ struct inode *bm_inode,
+ ocfs_journal_handle *handle)
+{
+ int status = 0;
+ __u64 alloc_bytes;
+ u32 cluster_off, cluster_count;
+ ocfs2_dinode *alloc = NULL;
+
+ LOG_ENTRY();
+
+ alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+ if (LOCAL_ALLOC(alloc)->la_bm_bits != 0)
+ LOG_TRACE_STR("asking me to alloc a new window over a"
+ " non-empty one");
+
+ /* we try to use find_contig_space_from_bitmap here for now. */
+ alloc_bytes = (u64)ocfs_local_alloc_window_bits(osb) << osb->s_clustersize_bits;
+ LOG_TRACE_ARGS("Allocating %llu bytes (%u clusters) for a "
+ "new window.\n", alloc_bytes,
+ ocfs_local_alloc_window_bits(osb));
+
+ status = ocfs_find_contiguous_space_from_bitmap(osb, handle,
+ alloc_bytes,
+ &cluster_off,
+ &cluster_count,
+ lock_bh,
+ bm_inode);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ atomic_inc(&osb->alloc_stats.bitmap_data);
+
+ alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+ LOCAL_ALLOC(alloc)->la_bm_off = cluster_off;
+ LOCAL_ALLOC(alloc)->la_bm_bits = cluster_count;
+ /* just in case... In the future when we find space ourselves,
+ * we don't have to get all contiguous -- but we'll have to
+ * set all previously used bits in bitmap and update
+ * la_bits_set before setting the bits in the main bitmap. */
+ LOCAL_ALLOC(alloc)->la_bits_set = 0;
+ memset(LOCAL_ALLOC(alloc)->la_bitmap, 0,
+ LOCAL_ALLOC(alloc)->la_size);
+
+ LOG_TRACE_STR("New window allocated:");
+ LOG_TRACE_ARGS("window la_bm_off = %u\n",
+ LOCAL_ALLOC(alloc)->la_bm_off);
+ LOG_TRACE_ARGS("window la_bm_bits = %u\n",
+ LOCAL_ALLOC(alloc)->la_bm_bits);
+
+bail:
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_local_alloc_new_window */
+
+/*
+ * This essentially does the same thing as sync_local_to_main, but
+ * without a journal handle -- used during shutdown and recovery.
+ */
+static int ocfs_sync_local_from_shutdown(ocfs_super *osb,
+ ocfs_bitmap_free_head **f,
+ struct buffer_head *local_alloc_bh,
+ int in_recovery)
+{
+ int status = 0;
+ int bit_off, left;
+ ocfs2_dinode *alloc = NULL;
+ void *bitmap;
+
+ LOG_ENTRY();
+
+ if (!local_alloc_bh)
+ BUG();
+
+ alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
+ if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
+ LOG_TRACE_STR("nothing to sync!");
+ goto bail;
+ }
+
+ if (!(*f)) {
+ *f = ocfs_alloc_bitmap_free_head();
+ if (*f == NULL) {
+ LOG_ERROR_STATUS(-ENOMEM);
+ goto bail;
+ }
+ }
+
+ alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
+
+ LOG_TRACE_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);
+
+ bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+
+ /* any unset bits in local alloc need to be unset in bitmap. */
+ bit_off = 0;
+ left = LOCAL_ALLOC(alloc)->la_bm_bits;
+ while ((bit_off = find_next_zero_bit(bitmap, left, bit_off))
+ != -1) {
+ if (bit_off >= left) {
+ /*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
+ break;
+ }
+ /* LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n", bit_off);*/
+ status = ocfs_add_to_bitmap_free_head(osb,
+ *f, 1,
+ bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
+ -1, 0, DISK_ALLOC_VOLUME);
+ if (status < 0) {
+ ocfs_free_bitmap_free_head(*f);
+ *f = NULL;
+ }
+ bit_off++;
+ }
+
+bail:
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_sync_local_from_shutdown */
+
+/*
+ * ocfs_sync_local_to_main
+ *
+ * sync the local alloc to main bitmap.
+ *
+ * assumes you've already locked the main bitmap -- the bitmap inode
+ * passed is used for caching.
+ */
+static int ocfs_sync_local_to_main(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_dinode *alloc,
+ struct inode *main_bm_inode,
+ struct buffer_head *main_bm_bh)
+{
+ int status = 0;
+ int bit_off, left;
+ 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,
+ ocfs_local_alloc_count_bits(alloc),
+ LOCAL_ALLOC(alloc)->la_bits_set);
+
+ if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
+ LOG_TRACE_STR("nothing to sync!");
+ 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_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ 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_bhs(osb,
+ (osb->bitmap_blkno + start) << osb->sb->s_blocksize_bits,
+ numblocks << osb->sb->s_blocksize_bits,
+ &osb->cluster_bitmap.chunk[start], OCFS_BH_CACHED,
+ main_bm_inode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+ /* any unset bits in local alloc need to be unset in bitmap. */
+ bit_off = 0;
+ left = LOCAL_ALLOC(alloc)->la_bm_bits;
+ while ((bit_off = find_next_zero_bit(bitmap, left, bit_off))
+ != -1) {
+ if (bit_off >= left) {
+ /*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
+ break;
+ }
+
+ LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n",
+ bit_off + LOCAL_ALLOC(alloc)->la_bm_off);
+ ocfs_clear_bits(osb->sb, handle, &osb->cluster_bitmap,
+ bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
+ 1);
+ bm_fe->id1.bitmap1.i_used--;
+ bit_off++;
+ }
+
+ status = ocfs_journal_dirty(handle, main_bm_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto bail;
+ }
+
+bail:
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_sync_local_to_main */
+
+/* Note that we do *NOT* lock the local alloc inode here as
+ * it's been locked already for us. */
+static int ocfs_local_alloc_slide_window(ocfs_super *osb,
+ struct inode *local_alloc_inode)
+{
+ int status = 0;
+ struct buffer_head *main_bm_bh = NULL;
+ struct inode *main_bm_inode = NULL;
+ ocfs_journal_handle *handle = NULL;
+ ocfs2_dinode *alloc;
+ ocfs2_dinode *alloc_copy = NULL;
+
+ LOG_ENTRY();
+
+ main_bm_inode = ocfs_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ -1);
+ if (!main_bm_inode) {
+ status = -EINVAL;
+ LOG_ERROR_STATUS (status);
+ goto bail;
+ }
+
+ handle = ocfs_alloc_handle(osb);
+ if (!handle) {
+ status = -ENOMEM;
+ LOG_ERROR_STATUS (status);
+ goto bail;
+ }
+
+ /* Get the allocation lock here */
+ status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE,
+ 0, &main_bm_bh, main_bm_inode);
+ if (status < 0) {
+ main_bm_bh = NULL;
+ if (status != -EINTR)
+ LOG_ERROR_STATUS (status);
+ goto bail;
+ }
+ ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE,
+ 0, main_bm_inode);
+ ocfs_handle_add_inode(handle, main_bm_inode);
+
+ handle = ocfs_start_trans(osb, handle, OCFS_WINDOW_MOVE_CREDITS);
+ if (!handle) {
+ status = -ENOMEM;
+ LOG_ERROR_STATUS (status);
+ goto bail;
+ }
+ ocfs_handle_set_always_commits(handle, 1);
+
+ alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+ /* We want to clear the local alloc before doing anything
+ * else, so that if we error later during this operation,
+ * local alloc shutdown won't try to double free main bitmap
+ * bits. Make a copy so the sync function knows which bits to
+ * free. */
+ alloc_copy = kmalloc(osb->local_alloc_bh->b_size, GFP_KERNEL);
+ if (!alloc_copy) {
+ status = -ENOMEM;
+ goto bail;
+ }
+ memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
+
+ status = ocfs_journal_access(handle, osb->local_alloc_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ ocfs_clear_local_alloc(alloc);
+
+ status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ status = ocfs_sync_local_to_main(osb, handle, alloc_copy,
+ main_bm_inode, main_bm_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ status = ocfs_local_alloc_new_window(osb, main_bm_bh, main_bm_inode,
+ handle);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ atomic_inc(&osb->alloc_stats.moves);
+
+ status = 0;
+bail:
+ if (handle)
+ ocfs_commit_trans(handle);
+
+ if (main_bm_bh)
+ brelse(main_bm_bh);
+
+ if (main_bm_inode)
+ iput(main_bm_inode);
+
+ if (alloc_copy)
+ kfree(alloc_copy);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+}
+
+/*
+ * ocfs_find_contiguous_space_from_bitmap()
+ *
+ * Used only from local alloc right now. Eventually will go away, so
+ * don't add more callers to this function. Use the reserve / claim
+ * apis instead as they'll even get you distcongiuous areas.
+ *
+ * TODO: The Bitmap stuff needs to be changed for handling more than 32 bits...
+ * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
+ *
+ * Returns 0 on success, < 0 on error.
+ */
+static int ocfs_find_contiguous_space_from_bitmap(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ __u64 file_size,
+ u32 *cluster_off,
+ u32 *cluster_count,
+ struct buffer_head *bh,
+ struct inode *bitmap_inode)
+{
+ int status = 0, startbh, numblocks;
+ u32 bitoffset = 0, num_clusters = 0;
+ ocfs2_dinode *bm_lock;
+ __u32 bitmapblocks; /* we only care about the valid blocks */
+ __u32 free_bits;
+
+ LOG_ENTRY ();
+
+ OCFS_ASSERT(osb);
+ OCFS_ASSERT(bh);
+ OCFS_ASSERT(bitmap_inode);
+ OCFS_ASSERT(handle);
+
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ bm_lock = (ocfs2_dinode *) bh->b_data;
+
+ num_clusters = (u32) ((u64) (file_size + (osb->s_clustersize-1)) >>
+ osb->s_clustersize_bits);
+ if (num_clusters == 0) {
+ LOG_ERROR_STR ("DISK_FULL?: num_clusters==0");
+ status = 0;
+ goto leave;
+ }
+
+ free_bits = le32_to_cpu(bm_lock->id1.bitmap1.i_total) -
+ le32_to_cpu(bm_lock->id1.bitmap1.i_used);
+
+ if (num_clusters > free_bits) {
+ LOG_ERROR_ARGS("Disk Full: num_clusters=%u, free_bits=%u\n",
+ num_clusters, free_bits);
+ status = -ENOSPC;
+ goto leave;
+ }
+
+ bitmapblocks =
+ ocfs_blocks_for_bits(osb->sb,
+ osb->cluster_bitmap.validbits);
+
+ /* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
+ if (ocfs_read_bhs(osb, osb->bitmap_blkno << osb->sb->s_blocksize_bits,
+ bitmapblocks << osb->sb->s_blocksize_bits,
+ osb->cluster_bitmap.chunk, OCFS_BH_CACHED, bitmap_inode)) {
+ LOG_ERROR_STATUS(-EIO);
+ goto leave;
+ }
+
+ status = 0;
+ status = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
+ num_clusters, &bitoffset,
+ NULL);
+ if (status < 0) {
+ osb->cluster_bitmap.failed++;
+ LOG_TRACE_ARGS("Cannot allocate %u contiguous clusters "
+ "for system file\n", num_clusters);
+ status = -ENOSPC;
+ goto leave;
+ }
+
+ LOG_TRACE_ARGS ("setting %u bits at bit offset=%u\n",
+ num_clusters, bitoffset);
+
+ ocfs_set_bits(osb->sb, handle, &osb->cluster_bitmap, bitoffset,
+ num_clusters);
+
+ /* Ok, write out the bitmap now. We optimize only by writing
+ * out the bitmap blocks which have changed, and not all of
+ * them like before. */
+ numblocks = ocfs_bitmap_blocks_affected(osb->sb,
+ bitoffset,
+ num_clusters,
+ &startbh);
+
+ LOG_TRACE_ARGS("bitoffset = %u, num_clusters = %u, startbh = %u, numblocks = %u\n", bitoffset, num_clusters, startbh, numblocks);
+
+ /* write the bitmap size info to the lock sector */
+ bm_lock->id1.bitmap1.i_used =
+ ocfs_count_bits(osb->sb, &osb->cluster_bitmap);
+
+ status = ocfs_journal_dirty(handle, bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+
+ *cluster_off = bitoffset;
+ *cluster_count = num_clusters;
+ status = 0;
+
+leave:
+ LOG_EXIT_STATUS (status);
+ return status;
+} /* ocfs_find_contiguous_space_from_bitmap */
+
Added: branches/dlm-changes/src/localalloc.h
===================================================================
--- branches/dlm-changes/src/localalloc.h 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/localalloc.h 2004-10-01 22:07:13 UTC (rev 1538)
@@ -0,0 +1,55 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * localalloc.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.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ * Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#ifndef OCFS2_LOCALALLOC_H
+#define OCFS2_LOCALALLOC_H
+
+int ocfs_load_local_alloc(ocfs_super *osb);
+
+void ocfs_shutdown_local_alloc(ocfs_super *osb);
+
+int ocfs_recover_local_alloc(ocfs_super *osb,
+ int node_num,
+ ocfs_bitmap_free_head **bits_to_free);
+
+int ocfs_alloc_should_use_local(ocfs_super *osb,
+ u64 bits);
+
+int ocfs_reserve_local_alloc_bits(ocfs_super *osb,
+ ocfs_journal_handle *passed_handle,
+ u32 bits_wanted,
+ ocfs2_alloc_context *ac);
+
+int ocfs_claim_local_alloc_bits(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs2_alloc_context *ac,
+ u32 min_bits,
+ u32 *bit_off,
+ u32 *num_bits);
+
+#endif /* OCFS2_LOCALALLOC_H */
Modified: branches/dlm-changes/src/ocfs_log.h
===================================================================
--- branches/dlm-changes/src/ocfs_log.h 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/ocfs_log.h 2004-10-01 22:07:13 UTC (rev 1538)
@@ -113,7 +113,7 @@
#define OCFS_DEBUG_CONTEXT_INODE 0x00000400 /* inode.c */
#define OCFS_DEBUG_CONTEXT_JOURNAL 0x00000800 /* journal.c */
#define OCFS_DEBUG_CONTEXT_CHAINALLOC 0x00001000 /* */
-#define OCFS_DEBUG_CONTEXT_UNUSED2 0x00002000 /* */
+#define OCFS_DEBUG_CONTEXT_LOCALALLOC 0x00002000 /* */
#define OCFS_DEBUG_CONTEXT_SYSFILE 0x00004000 /* sysfile.c */
#define OCFS_DEBUG_CONTEXT_VOLCFG 0x00008000 /* volcfg.c */
#define OCFS_DEBUG_CONTEXT_DCACHE 0x00010000 /* dcache.c */
Modified: branches/dlm-changes/src/super.c
===================================================================
--- branches/dlm-changes/src/super.c 2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/super.c 2004-10-01 22:07:13 UTC (rev 1538)
@@ -56,6 +56,7 @@
#include "heartbeat.h"
#include "inode.h"
#include "journal.h"
+#include "localalloc.h"
#include "nm.h"
#include "proc.h"
#include "super.h"
More information about the Ocfs2-commits
mailing list