[Ocfs2-commits] mfasheh commits r933 - in trunk: . src src/inc
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon May 24 20:24:58 CDT 2004
Author: mfasheh
Date: 2004-05-24 19:24:56 -0500 (Mon, 24 May 2004)
New Revision: 933
Modified:
trunk/TODO
trunk/src/Makefile
trunk/src/alloc.c
trunk/src/bitmap.c
trunk/src/dir.c
trunk/src/file.c
trunk/src/hash.c
trunk/src/inc/journal.h
trunk/src/inc/ocfs.h
trunk/src/inc/proto.h
trunk/src/journal.c
trunk/src/namei.c
trunk/src/osb.c
trunk/src/sysfile.c
Log:
* Journal bitmap changes. This should help us with performance on
extends / creates as those transactions are buffered and we can avoid
the sync write normally associated with writing the new
bitmap. Unfortunately, delete / truncate can still lose bits to the
bitmap. Ext3 has restartable truncate, but we don't yet. All this
means is that there's a potential to lose space (no real metadata
corruption possible).
* Fix a bug in truncate where we were using blocks instead of (ugh) bytes
* Use inode->i_sem instead of vol_alloc_sem and node_alloc_sem
* Since we journal bitmap changes, we can get rid of handle->abort_bits.
One day, we won't even have handle->commit_bits....
* There is a function now called ocfs_ugly_hack which works around a
fundamental flaw in the bh_sem hash. We can remove it when we remove
the bh_sem hash (soon).
* We had an extra OCFS_PUT_DATA in and error case of
extend. Fixed. Of course, the real fix is to get rid of bh_sem hash.
Hmm, I notice a theme here...
* Fix a bug I inadvertantly created with local alloc recovery. Also
managed to clean up ocfs_sync_local_to_main quite a bit.
* update the TODO list
Modified: trunk/TODO
===================================================================
--- trunk/TODO 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/TODO 2004-05-25 00:24:56 UTC (rev 933)
@@ -5,10 +5,8 @@
* provide an ocfsmigrate utility to migrate v1 -> v2 and back.
-* System files should be locked with cache lock, and we need inodes
- for them so that we can cache our reads to them. This can also count
- for the main bitmap. Data writes to the bitmap files can be
- writethrough or journalled (with delayed playback).
+* System files should be locked with cache lock so we can cache our reads to
+ them. This can also count for the main bitmap.
* Make bitmap reads only read those blocks which we care about
@@ -61,3 +59,11 @@
* Clean up the local alloc path a bit. Specifically the part in
find_space_from_local where we take the main bitmap lock a bit early... We
can probably eliminate that and just let it get taken later...
+
+* Remove ocfs_ugly_hack. This can be totally removed after we've gotten rid
+ of the bh_sem_hash.
+
+* Local alloc code can be slightly revamped to not use the commit_bits on
+ the journal handle any more. Also, investigate whether we can use the
+ "undo" access flag on that bitmap.
+
Modified: trunk/src/Makefile
===================================================================
--- trunk/src/Makefile 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/Makefile 2004-05-25 00:24:56 UTC (rev 933)
@@ -64,6 +64,9 @@
#GLOBAL_DEFINES += -DVERBOSE_BH_SEM
#GLOBAL_DEFINES += -DBH_SEM_DEBUG
+#off by default as it's expensive
+#GLOBAL_DEFINES += -DBH_SEM_LEAK_CHECKING
+
ifneq ($(OCFS_PROCESSOR),ia64)
#GLOBAL_DEFINES += -DOCFS_DBG_TIMING
endif
@@ -222,7 +225,7 @@
build-modules:
$(MAKE) -C $(KDIR) SUBDIRS=$(CURDIR) modules
-
+
endif # OCFS_KERNEL_2_6
INSTALL_RULES = install-ocfs
Modified: trunk/src/alloc.c
===================================================================
--- trunk/src/alloc.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/alloc.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -36,6 +36,27 @@
/* Tracing */
#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_ALLOC
+/* Remove this after the bh_sem hash is removed. */
+static inline int ocfs_ugly_hack(ocfs_journal_handle *handle,
+ struct buffer_head *bh)
+{
+ int status = 0;
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ return(status);
+ }
+ OCFS_BH_GET_DATA_WRITE(bh);
+ OCFS_BH_PUT_DATA(bh);
+ status = ocfs_journal_dirty(handle, bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ return(status);
+ }
+
+ return(status);
+}
+
static int ocfs_kill_this_tree(ocfs_super *osb, struct buffer_head *extent_grp_bh,
ocfs_journal_handle *handle, struct inode *inode);
static int ocfs_allocate_new_data_node (ocfs_super * osb,
@@ -52,7 +73,8 @@
static int _squish_extent_entries(ocfs_super *osb, ocfs_alloc_ext *extarr,
__u8 *freeExtent,
ocfs_journal_handle *handle,
- __u64 FileSize, int flag, struct inode *inode) ;
+ __u64 FileSize, int flag,
+ struct inode *inode);
static int ocfs_fix_extent_group(ocfs_super *osb, struct buffer_head *group_bh, struct inode *inode);
@@ -64,12 +86,14 @@
static int ocfs_update_last_ext_ptr(ocfs_super *osb, ocfs_file_entry *fe, struct inode *inode);
-static int ocfs_free_vol_block (ocfs_super * osb, ocfs_free_rec * FreeLog,
- __u32 NodeNum, __u32 Type);
+static int ocfs_free_vol_block (ocfs_super * osb, ocfs_journal_handle *handle,
+ ocfs_free_rec * FreeLog, __u32 NodeNum,
+ __u32 Type);
static int ocfs_free_disk_bitmap (ocfs_super * osb, ocfs_free_rec *free_log);
static inline int ocfs_free_main_bitmap(ocfs_super *osb,
+ ocfs_journal_handle *handle,
ocfs_free_rec *freelog);
static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh,
@@ -78,8 +102,6 @@
static int ocfs_sync_local_to_main(ocfs_super *osb,
ocfs_bitmap_free_head **f,
struct buffer_head *local_alloc_bh,
- struct buffer_head *bm_lock_bh,
- struct inode *bm_inode,
int in_recovery);
static __u32 ocfs_alloc_count_bits(ocfs_local_alloc *alloc);
static void ocfs_clear_local_alloc(ocfs_local_alloc *alloc);
@@ -98,8 +120,6 @@
LOG_ENTRY_ARGS("(osb=0x%p, f=0x%p, f->num_logs = %d)\n", osb, f,
f->num_logs);
- ocfs_take_trans_lock(osb);
-
list_for_each_safe(p, n, &(f->free_logs)) {
LOG_TRACE_ARGS("f->num_logs = %d\n", f->num_logs);
log = list_entry(p, ocfs_free_rec, log_list);
@@ -111,8 +131,6 @@
f->num_logs--;
}
- ocfs_release_trans_lock(osb);
-
LOG_EXIT_STATUS(status);
return(status);
}
@@ -194,6 +212,11 @@
__u32 tmp_indx;
__u64 lock_id;
struct buffer_head *globalbh = NULL;
+ ocfs_journal_handle *handle = NULL;
+ int credits = 33; /* one for each potential sysfile fe. This
+ * goes away when ocfs_ugly_hack goes
+ * away. */
+ struct buffer_head *ugly_hack_bh = NULL;
LOG_ENTRY_ARGS ("(0x%p, 0x%p)\n", osb, free_log);
@@ -223,7 +246,6 @@
extnode_inode[i] = NULL;
}
- /* alloc memory */
num_upd = free_log->num_updates;
for (i = 0; i < num_upd; i++) {
switch (free_log->update[i].type) {
@@ -239,6 +261,8 @@
free_dir_node[node_num]->num_updates = 0;
}
tmp_log = free_dir_node[node_num];
+
+ credits++;
break;
case DISK_ALLOC_EXTENT_NODE:
@@ -253,6 +277,8 @@
free_ext_node[node_num]->num_updates = 0;
}
tmp_log = free_ext_node[node_num];
+
+ credits++;
break;
case DISK_ALLOC_VOLUME:
@@ -266,6 +292,9 @@
free_vol_bits->num_updates = 0;
}
tmp_log = free_vol_bits;
+
+ credits += 1 + free_log->update[i].length /
+ OCFS_BITS_IN_CHUNK;
break;
default:
@@ -273,6 +302,7 @@
break;
}
+
if (tmp_log) {
ocfs_bitmap_update *fb1, *fb2;
@@ -290,9 +320,17 @@
}
}
+ /* start the transaction here to preserve ordering with the
+ * bitmap i_sems... */
+ handle = ocfs_start_trans(osb, credits);
+ if (!handle) {
+ status = -ENOMEM;
+ LOG_ERROR_STATUS(status);
+ goto finally;
+ }
+
/* Get all the locks we need. do global bitmap last to
* preserve lock ordering with extend/create */
-
lock_id = (OCFS_FILE_DIR_ALLOC_BITMAP * osb->sect_size) +
osb->vol_layout.root_int_off;
for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
@@ -301,17 +339,27 @@
if (!dirnode_inode[i]) {
status = -EINVAL;
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+ down(&dirnode_inode[i]->i_sem);
+
status = ocfs_acquire_lock (osb, lock_id,
OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE,
- NULL, dirnode_inode[i]);
+ &ugly_hack_bh,
+ dirnode_inode[i]);
if (status < 0) {
+ up(&dirnode_inode[i]->i_sem);
+ iput(dirnode_inode[i]);
+ dirnode_inode[i] = NULL;
if (status != -EINTR)
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+
+ ocfs_ugly_hack(handle, ugly_hack_bh);
+ brelse(ugly_hack_bh);
+ ugly_hack_bh = NULL;
}
}
@@ -323,17 +371,27 @@
if (!extnode_inode[i]) {
status = -EINVAL;
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+ down(&extnode_inode[i]->i_sem);
+
status = ocfs_acquire_lock (osb, lock_id,
OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE,
- NULL, extnode_inode[i]);
+ &ugly_hack_bh,
+ extnode_inode[i]);
if (status < 0) {
+ up(&extnode_inode[i]->i_sem);
+ iput(extnode_inode[i]);
+ extnode_inode[i] = NULL;
if (status != -EINTR)
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+
+ ocfs_ugly_hack(handle, ugly_hack_bh);
+ brelse(ugly_hack_bh);
+ ugly_hack_bh = NULL;
}
}
@@ -342,53 +400,80 @@
if (!vol_inode) {
status = -EINVAL;
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+ down(&vol_inode->i_sem);
status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE,
&globalbh, vol_inode);
if (status < 0) {
+ up(&vol_inode->i_sem);
+ iput(vol_inode);
+ vol_inode = NULL;
+
if (status != -EINTR)
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+ ocfs_ugly_hack(handle, globalbh);
+ brelse(ugly_hack_bh);
+ ugly_hack_bh = NULL;
}
/* free vol block */
if (free_vol_bits != NULL)
- ocfs_free_vol_block (osb, free_vol_bits, -1, DISK_ALLOC_VOLUME);
+ ocfs_free_vol_block (osb, handle, free_vol_bits, -1,
+ DISK_ALLOC_VOLUME);
/* We can potentiallly loose some allocation for dirNodes or extent */
/* nodes but they should not be much... */
for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
if (free_dir_node[i] != NULL)
- ocfs_free_vol_block (osb, free_dir_node[i], i,
+ ocfs_free_vol_block (osb, handle, free_dir_node[i], i,
DISK_ALLOC_DIR_NODE);
if (free_ext_node[i] != NULL)
- ocfs_free_vol_block (osb, free_ext_node[i], i,
+ ocfs_free_vol_block (osb, handle, free_ext_node[i], i,
DISK_ALLOC_EXTENT_NODE);
}
/* release all locks */
- if (free_vol_bits != NULL) {
+ if (free_vol_bits) {
ocfs_file_entry *bm_lock;
+ status = ocfs_journal_access(handle, globalbh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto abort;
+ }
+
bm_lock = (ocfs_file_entry *)OCFS_BH_GET_DATA_WRITE(globalbh); /* write */
bm_lock->u.bitinfo.used_bits = ocfs_count_bits(&osb->cluster_bitmap);
OCFS_BH_PUT_DATA(globalbh);
- status = ocfs_write_bh(osb, globalbh, 0, NULL);
+ status = ocfs_journal_dirty(handle, globalbh);
if (status < 0) {
LOG_ERROR_STATUS (status);
- goto finally;
+ goto abort;
}
+ }
+
+ ocfs_commit_trans(handle);
+
+ handle = NULL;
+abort:
+ if (handle)
+ ocfs_abort_trans(handle);
+
+ if (free_vol_bits) {
status = ocfs_release_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, globalbh, vol_inode);
+ FLAG_FILE_CREATE, globalbh,
+ vol_inode);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto finally;
@@ -429,15 +514,22 @@
finally:
for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- if (extnode_inode[i])
+ if (extnode_inode[i]) {
+ up(&extnode_inode[i]->i_sem);
iput(extnode_inode[i]);
- if (dirnode_inode[i])
+ }
+ if (dirnode_inode[i]) {
+ up(&dirnode_inode[i]->i_sem);
iput(dirnode_inode[i]);
+ }
}
+ if (vol_inode) {
+ up(&vol_inode->i_sem);
+ iput(vol_inode);
+ }
+
if (globalbh)
brelse(globalbh);
- if (vol_inode)
- iput(vol_inode);
for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
ocfs_safefree (free_dir_node[i]);
@@ -455,7 +547,9 @@
return status;
} /* ocfs_free_disk_bitmap */
-static inline int ocfs_free_main_bitmap(ocfs_super *osb, ocfs_free_rec *freelog)
+static inline int ocfs_free_main_bitmap(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ ocfs_free_rec *freelog)
{
int i;
ocfs_alloc_bm *bitmap;
@@ -467,12 +561,7 @@
bitmap = &osb->cluster_bitmap;
bitmapblocks = (OCFS_ALIGN(bitmap->validbits, OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
- /* TODO: Fix this so that we only read and write which sectors
- * off disk that we actually need instead of the whole honkin'
- * bitmap at once...
- *
- * Also, can the reads/writes be cached?
- */
+
status = ocfs_read_bhs(osb, osb->vol_layout.bitmap_off,
bitmapblocks * osb->sect_size,
bitmap->chunk, 0, NULL);
@@ -482,21 +571,8 @@
}
for (i = 0; i < freelog->num_updates; i++)
- ocfs_clear_bits(bitmap, freelog->update[i].file_off, freelog->update[i].length);
+ ocfs_clear_bits(handle, bitmap, freelog->update[i].file_off, freelog->update[i].length);
- /* we don't know which blocks we've changed and which
- * haven't, so just write them all out */
- for(i = 0; i < bitmapblocks; i++) {
- OCFS_BH_GET_DATA_WRITE(bitmap->chunk[i]);
- OCFS_BH_PUT_DATA(bitmap->chunk[i]);
- }
-
- status = ocfs_write_bhs(osb, bitmap->chunk, bitmapblocks, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
status = 0;
bail:
LOG_EXIT_STATUS(status);
@@ -507,7 +583,7 @@
* ocfs_free_vol_block()
*
*/
-static int ocfs_free_vol_block (ocfs_super * osb, ocfs_free_rec * FreeLog, __u32 NodeNum, __u32 Type)
+static int ocfs_free_vol_block (ocfs_super * osb, ocfs_journal_handle *handle, ocfs_free_rec * FreeLog, __u32 NodeNum, __u32 Type)
{
int status = 0;
__u64 fileSize = 0;
@@ -521,7 +597,6 @@
ocfs_alloc_bm *tmpbitmap = NULL;
__u32 i;
int needs_uninit = 0;
- int needs_unlock = 0;
LOG_ENTRY ();
@@ -561,16 +636,10 @@
}
if (Type == DISK_ALLOC_VOLUME) {
- down (&(osb->vol_alloc_sem));
- needs_unlock = 1;
-
/* don't need to read it here as
* ocfs_free_main_bitmap handles that for us. */
tmpbitmap = &osb->cluster_bitmap;
} else {
- down(&(osb->node_alloc_sem));
- needs_unlock = 1;
-
/* Read in the bitmap file for the dir alloc and look
for the required space, if found */
status = ocfs_get_system_file_size (osb, fileId, &fileSize, &allocSize);
@@ -595,7 +664,7 @@
}
if (Type == DISK_ALLOC_VOLUME) {
- status = ocfs_free_main_bitmap(osb, FreeLog);
+ status = ocfs_free_main_bitmap(osb, handle, FreeLog);
if (status < 0){
LOG_ERROR_STATUS (status);
goto leave;
@@ -606,41 +675,19 @@
LOG_ERROR_ARGS ("offset=0, type=%x, blksz=%d", Type,
blockSize);
}
-
+
if (Type == DISK_ALLOC_VOLUME)
foundBit = (__u32) FreeLog->update[i].file_off;
else
foundBit = (__u32)
(FreeLog->update[i].file_off >>
blockSizeBits);
- ocfs_clear_bits(tmpbitmap, (__u32) foundBit,
+ ocfs_clear_bits(handle, tmpbitmap, (__u32) foundBit,
(__u32) FreeLog->update[i].length);
}
}
- /* ocfs_free_main_bitmap handles all the reads/writes for the
- * main bitmap */
- if (Type != DISK_ALLOC_VOLUME) {
- /* we don't know which blocks we've changed and which
- * haven't, so just write them all out */
- for(i = 0; i < bitmapblocks; i++) {
- OCFS_BH_GET_DATA_WRITE(tmpbitmap->chunk[i]);
- OCFS_BH_PUT_DATA(tmpbitmap->chunk[i]);
- }
- status = ocfs_write_bhs(osb, tmpbitmap->chunk, bitmapblocks,
- 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
leave:
- if (needs_unlock) {
- if (Type == DISK_ALLOC_VOLUME)
- up (&(osb->vol_alloc_sem));
- else
- up (&(osb->node_alloc_sem));
- }
if (needs_uninit)
ocfs_uninitialize_bitmap(tmpbitmap);
@@ -1519,7 +1566,8 @@
diskOffsetTobeFreed, lengthTobeFreed = 0,
actualSize = 0, origLength = 0;
- LOG_ENTRY ();
+ LOG_ENTRY_ARGS("(*freeExtent = %u, FileSize = %llu, flag = %d)\n",
+ *freeExtent, FileSize, flag);
firstfree = *freeExtent;
@@ -2707,19 +2755,18 @@
* Pass in 'lock_bh' and bitmap_inode only if you've already taken the
* vol_alloc semaphore, and you've done the acquire_lock on the bitmap.
*/
-int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, int sysfile, struct buffer_head *lock_bh, struct inode *bitmap_inode)
+int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, ocfs_journal_handle *handle, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, int sysfile, struct buffer_head *lock_bh, struct inode *bitmap_inode)
{
- int status = 0, tmpstat, startbh, numblocks;
+ int status = 0, startbh, numblocks;
__u32 bitoffset = 0, ClusterCount = 0;
__u64 ByteCount = 0;
__u32 LargeAlloc = 0;
static __u32 LargeAllocOffset = 0;
static __u32 SmallAllocOffset = 0;
- int bLockAcquired = 0;
struct buffer_head *bh = NULL;
ocfs_file_entry *bm_lock = NULL;
__u32 bitmapblocks; /* we only care about the valid blocks */
- int local_lock = 1;
+ int local_lock = 0;
int local_inode = 0;
__u32 five_percent;
@@ -2727,12 +2774,6 @@
OCFS_ASSERT (osb);
- if (lock_bh) {
- local_lock = 0;
- bh = lock_bh;
- } else /* local lock */
- down (&(osb->vol_alloc_sem));
-
if (!bitmap_inode) {
bitmap_inode = ocfs_iget(osb, OCFS_BITMAP_LOCK_OFFSET, NULL);
if (!bitmap_inode) {
@@ -2743,7 +2784,13 @@
local_inode = 1;
}
- if (local_lock) {
+ if (lock_bh) {
+ bh = lock_bh;
+ } else { /* local lock */
+ local_lock = 1;
+
+ down(&bitmap_inode->i_sem);
+
/* Get the allocation lock here */
status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
OCFS_DLM_EXCLUSIVE_LOCK, 0,
@@ -2753,8 +2800,16 @@
LOG_ERROR_STATUS (status);
goto leave;
}
- bLockAcquired = 1;
+ ocfs_journal_add_lock(handle, OCFS_DLM_EXCLUSIVE_LOCK,
+ 0, bh, bitmap_inode);
}
+
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
bm_lock = (ocfs_file_entry *)OCFS_BH_GET_DATA_WRITE(bh); /* write */
ClusterCount = (__u32) ((__u64) (file_size + (osb->vol_layout.cluster_size-1)) >>
@@ -2843,7 +2898,7 @@
LOG_TRACE_ARGS ("setting at bit offset=%u\n", bitoffset);
- ocfs_set_bits (&osb->cluster_bitmap, bitoffset, ClusterCount);
+ ocfs_set_bits (handle, &osb->cluster_bitmap, bitoffset, ClusterCount);
/* Ok, write out the bitmap now. We optimize only by writing
* out the bitmap blocks which have changed, and not all of
@@ -2852,22 +2907,13 @@
numblocks = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset + ClusterCount - 1) - startbh + 1;
LOG_TRACE_ARGS("bitoffset = %u, ClusterCount = %u, startbh = %u, numblocks = %u\n", bitoffset, ClusterCount, startbh, numblocks);
-
- status = ocfs_write_bhs(osb, &osb->cluster_bitmap.chunk[startbh],
- numblocks, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
/* write the bitmap size info to the lock sector */
- /* TODO: optimize by making this part of ocfs_release_lock
- * for now, it will be back-to-back writes to same sector */
bm_lock->u.bitinfo.used_bits = ocfs_count_bits(&osb->cluster_bitmap);
OCFS_BH_PUT_DATA(bh);
bm_lock = NULL;
- status = ocfs_write_bh (osb, bh, 0, NULL);
+ status = ocfs_journal_dirty(handle, bh);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto leave;
@@ -2882,16 +2928,8 @@
OCFS_BH_PUT_DATA(bh);
if (local_lock) {
- up (&(osb->vol_alloc_sem));
+ up (&bitmap_inode->i_sem);
- if (bLockAcquired) {
- tmpstat = ocfs_release_lock(osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, bh, bitmap_inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
if (bh != NULL)
brelse(bh);
}
@@ -2911,7 +2949,6 @@
int ocfs_alloc_node_block (ocfs_super * osb, __u64 FileSize, __u64 * DiskOffset, __u64 * file_off, __u32 NodeNum, __u32 Type, ocfs_journal_handle *handle)
{
int status = 0;
- int tmpstat = 0;
int startbh, numblocks;
__u64 fileSize = 0;
__u64 offset = 0;
@@ -2926,7 +2963,6 @@
__u32 numBits = 0;
__u32 foundBit = -1;
__u32 blockSize = 0, blockSizeBits = 0;
- int bLockAcquired = 0;
__u32 bm_file = 0;
__u32 alloc_file = 0;
struct buffer_head *bh = NULL;
@@ -2972,8 +3008,17 @@
LOG_ERROR_STATUS (status);
goto leave;
}
- bLockAcquired = 1;
+ ocfs_journal_add_lock(handle, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE,
+ bh, inode);
+
+ status = ocfs_ugly_hack(handle, bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+
numBits = ((FileSize + (blockSize-1)) >> blockSizeBits);
numBytes = numBits << blockSizeBits;
@@ -3083,20 +3128,12 @@
LOG_TRACE_ARGS ("byte offset=%d\n", foundBit);
- ocfs_set_bits (&bitmap, (__u32) foundBit, (__u32) numBits);
+ ocfs_set_bits (handle, &bitmap, (__u32) foundBit, (__u32) numBits);
/* only write out what has changed... */
startbh = OCFS_GLOBAL_OFF_TO_CHUNK(foundBit);
numblocks = OCFS_GLOBAL_OFF_TO_CHUNK(foundBit + numBits - 1) - startbh + 1;
- /* Write the bitmap file back */
- status = ocfs_write_bhs(osb, &bitmap.chunk[startbh], numblocks,
- 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
LOG_TRACE_ARGS ("offset=%u, type=%x, blksz=%u, foundbit=%u, fileid=%u\n",
foundBit * blockSize, Type, blockSize, foundBit, alloc_file);
*DiskOffset = ocfs_file_to_disk_off (osb, (alloc_file),
@@ -3118,23 +3155,9 @@
if (needs_uninit)
ocfs_uninitialize_bitmap(&bitmap);
- if (bLockAcquired && delay_lockrel) {
- ocfs_journal_add_lock(handle, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- bh, inode);
- tmpstat = 0;
- } else if (bLockAcquired) {
- tmpstat =
- ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, bh, inode);
-
- }
-
if (inode)
iput(inode);
- if (tmpstat < 0)
- status = tmpstat;
if (bh != NULL)
brelse(bh);
@@ -3390,18 +3413,12 @@
static int ocfs_sync_local_to_main(ocfs_super *osb,
ocfs_bitmap_free_head **f,
struct buffer_head *local_alloc_bh,
- struct buffer_head *bm_lock_bh,
- struct inode *bm_inode,
int in_recovery)
{
- int status = 0, tmpstat;
- __u32 bitmapblocks;
- struct buffer_head *bh = NULL;
+ int status = 0;
int bit_off, left;
ocfs_local_alloc *alloc = NULL;
- int local_lock = 1, got_lock = 0;
void *bitmap;
- struct inode *local_inode = NULL;
LOG_ENTRY();
@@ -3416,50 +3433,6 @@
}
OCFS_BH_PUT_DATA(local_alloc_bh);
- if (bm_lock_bh) {
- local_lock = 0;
- bh = bm_lock_bh;
- }
-
- if (bm_inode) {
- atomic_inc(&bm_inode->i_count);
- local_inode = bm_inode;
- } else {
- local_inode = ocfs_iget(osb, OCFS_BITMAP_LOCK_OFFSET, NULL);
- if (!local_inode) {
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- }
-
- if (local_lock) {
- down (&(osb->vol_alloc_sem));
-
- /* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- (in_recovery) ? FLAG_FILE_RECOVERY
- : 0, &bh, local_inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- got_lock = 1;
- }
-
- bitmapblocks = (OCFS_ALIGN(osb->cluster_bitmap.validbits,
- OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
-
- status = ocfs_read_bhs(osb, osb->vol_layout.bitmap_off,
- bitmapblocks * osb->sect_size,
- osb->cluster_bitmap.chunk, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
if (!(*f)) {
*f = ocfs_alloc_bitmap_free_head();
if (*f == NULL) {
@@ -3500,24 +3473,7 @@
OCFS_BH_PUT_DATA(local_alloc_bh);
bail:
- if (local_lock) {
- up (&(osb->vol_alloc_sem));
- if (got_lock) {
- tmpstat = ocfs_release_lock (osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, bh, local_inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
- if (bh != NULL)
- brelse(bh);
- }
-
- if (local_inode)
- iput(local_inode);
-
LOG_EXIT_STATUS(status);
return(status);
} /* ocfs_sync_local_to_main */
@@ -3549,7 +3505,8 @@
"new window.\n", alloc_bytes,
ocfs_local_alloc_window_bits(osb));
- status = ocfs_find_contiguous_space_from_bitmap(osb, alloc_bytes,
+ status = ocfs_find_contiguous_space_from_bitmap(osb, handle,
+ alloc_bytes,
&cluster_off,
&cluster_count, 0,
lock_bh, bm_inode);
@@ -3575,18 +3532,7 @@
LOG_TRACE_ARGS("window alloc_size = %u\n", alloc->alloc_size);
OCFS_BH_PUT_DATA(osb->local_alloc_bh);
- status = ocfs_handle_add_abort_bits(handle, cluster_count,
- alloc->bitmap_start, -1,
- DISK_ALLOC_VOLUME);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- /* In case of this error, we want to shutdown the
- * local alloc bitmap. We'll let shutdown handling
- * deal with freeing newly allocated bits. */
- ocfs_free_bitmap_free_head(handle->abort_bits);
- handle->abort_bits = NULL;
- }
bail:
LOG_EXIT_STATUS(status);
return(status);
@@ -3670,7 +3616,7 @@
void *bitmap;
LOG_ENTRY_ARGS("(bitswanted = %u)\n", bitswanted);
-
+
if (!osb->have_local_alloc)
BUG();
@@ -3736,35 +3682,37 @@
OCFS_BH_PUT_DATA(osb->local_alloc_bh);
alloc = NULL;
- /* lock bitmap here */
- down (&(osb->vol_alloc_sem));
-
if (!main_bm_inode)
main_bm_inode = ocfs_iget(osb, OCFS_BITMAP_LOCK_OFFSET,
NULL);
if (!main_bm_inode) {
- up (&(osb->vol_alloc_sem));
status = -EINVAL;
LOG_ERROR_STATUS (status);
goto bail;
}
+ /* lock bitmap here */
+ down(&main_bm_inode->i_sem);
+
/* Get the allocation lock here */
status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
OCFS_DLM_EXCLUSIVE_LOCK, 0,
&main_bm_bh,
main_bm_inode);
if (status < 0) {
- up (&(osb->vol_alloc_sem));
+ up(&main_bm_inode->i_sem);
+ main_bm_bh = NULL;
if (status != -EINTR)
LOG_ERROR_STATUS (status);
goto bail;
}
+ ocfs_journal_add_lock(handle, OCFS_DLM_EXCLUSIVE_LOCK, 0,
+ main_bm_bh, main_bm_inode);
+
status = ocfs_sync_local_to_main(osb, &(handle->commit_bits),
- NULL, main_bm_bh,
- main_bm_inode, 0);
+ NULL, 0);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -3816,15 +3764,7 @@
bail:
/* if we locked the main bitmap, cleanup after ourselves. */
if (main_bm_bh) {
- up (&(osb->vol_alloc_sem));
-
- tmpstat = ocfs_release_lock (osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, main_bm_bh,
- main_bm_inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
+ up(&main_bm_inode->i_sem);
brelse(main_bm_bh);
}
@@ -3895,7 +3835,8 @@
}
if (use_global) {
- status = ocfs_find_contiguous_space_from_bitmap(osb, file_size,
+ status = ocfs_find_contiguous_space_from_bitmap(osb, handle,
+ file_size,
cluster_off,
cluster_count,
sysfile, NULL,
@@ -3997,8 +3938,7 @@
else
bh = osb->local_alloc_bh;
- status = ocfs_sync_local_to_main(osb, &f, NULL, NULL, NULL,
- in_recovery);
+ status = ocfs_sync_local_to_main(osb, &f, bh, in_recovery);
if (status < 0)
LOG_ERROR_STATUS(status);
else if (f)
Modified: trunk/src/bitmap.c
===================================================================
--- trunk/src/bitmap.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/bitmap.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -123,6 +123,33 @@
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 (test_bit(nr, bh->b_data))
+ return 0;
+ if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
+ return 1;
+ return !test_bit(nr, bh2jh(bh)->b_committed_data);
+}
+
/*
* ocfs_find_clear_bits()
*
@@ -174,6 +201,7 @@
localstart: if the current one is a zero
*/
if (bitoff >= size) {
+nextbh:
/* we've hit the end of our bh. */
OCFS_BH_PUT_DATA(currbh);
/*LOG_TRACE_ARGS("bitoff >= size (%u)\n", bitoff,c);*/
@@ -196,7 +224,17 @@
continue;
}
- if (bitoff == localstart) {
+ 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_CHUNK_TO_GLOBAL_OFF(c, bitoff) + 1;
+ } else if (bitoff == localstart) {
/*LOG_TRACE_ARGS("bitoff == localstart (%u)\n",
bitoff);*/
/* cool, we have another zero! */
@@ -263,19 +301,20 @@
} /* ocfs_count_bits */
#ifdef __KERNEL__
-
-/* HEY LOOK! These two functions are IDENTICAL except for one line!
+/* 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 (ocfs_alloc_bm * bitmap, __u32 start, __u32 num)
+void ocfs_set_bits (ocfs_journal_handle *handle, 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, %u, %u)\n", bitmap, start, num);
@@ -289,6 +328,12 @@
local = OCFS_GLOBAL_OFF_TO_LOCAL(start);
currbh = bitmap->chunk[i];
+ status = ocfs_journal_access(handle, currbh, OCFS_JOURNAL_ACCESS_UNDO);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
buff = OCFS_BH_GET_DATA_WRITE(currbh); /* write */
while (num--) {
@@ -296,13 +341,33 @@
if (local >= OCFS_BITS_IN_CHUNK && num != 0) {
local = 0;
OCFS_BH_PUT_DATA(currbh);
+ 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, currbh,
+ OCFS_JOURNAL_ACCESS_UNDO);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
buff = OCFS_BH_GET_DATA_WRITE(currbh); /* write */
}
}
OCFS_BH_PUT_DATA(currbh);
+
+ status = ocfs_journal_dirty(handle, currbh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
bail:
LOG_EXIT ();
return;
@@ -312,11 +377,13 @@
* ocfs_clear_bits()
*
*/
-void ocfs_clear_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num)
+void ocfs_clear_bits (ocfs_journal_handle *handle, 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, %u, %u)\n", bitmap, start, num);
@@ -330,20 +397,52 @@
local = OCFS_GLOBAL_OFF_TO_LOCAL(start);
currbh = bitmap->chunk[i];
+ status = ocfs_journal_access(handle, currbh, OCFS_JOURNAL_ACCESS_UNDO);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
buff = OCFS_BH_GET_DATA_WRITE(currbh); /* write */
while (num--) {
- clear_bit (local++, buff);
+ clear_bit (local, buff);
+ if (handle)
+ set_bit(local, bh2jh(currbh)->b_committed_data);
+ local++;
+
if (local >= OCFS_BITS_IN_CHUNK && num != 0) {
local = 0;
OCFS_BH_PUT_DATA(currbh);
+
+ 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, currbh,
+ OCFS_JOURNAL_ACCESS_UNDO);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
buff = OCFS_BH_GET_DATA_WRITE(currbh); /* write */
}
}
OCFS_BH_PUT_DATA(currbh);
+
+ status = ocfs_journal_dirty(handle, currbh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
bail:
LOG_EXIT ();
return;
Modified: trunk/src/dir.c
===================================================================
--- trunk/src/dir.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/dir.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -1004,6 +1004,7 @@
__u8 dir_num_ent_used;
unsigned long blk;
struct buffer_head *lock_bh = NULL;
+ struct inode *dir_alloc_inode = NULL;
LOG_ENTRY ();
@@ -1214,16 +1215,26 @@
} else {
/* Allocate a new dir node */
__u64 fileOffset = 0;
+ __u64 dir_alloc_off;
LOG_TRACE_ARGS("ocfs_insert_file: CASE 2B\n");
- down(&osb->node_alloc_sem);
+ dir_alloc_off = ((OCFS_FILE_DIR_ALLOC_BITMAP + osb->node_num) * osb->sect_size) + osb->vol_layout.root_int_off;
+
+ dir_alloc_inode = ocfs_iget(osb, dir_alloc_off, NULL);
+ if (!dir_alloc_inode) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ down(&dir_alloc_inode->i_sem);
status = ocfs_alloc_node_block(osb,
osb->vol_layout.dir_node_size,
&bitmapOffset, &fileOffset,
osb->node_num,
DISK_ALLOC_DIR_NODE, handle);
- up(&osb->node_alloc_sem);
+ up(&dir_alloc_inode->i_sem);
if (status < 0) {
ocfs_safefree(newbhs);
LOG_ERROR_STATUS (status);
@@ -1319,6 +1330,9 @@
if (lock_bh)
brelse(lock_bh);
+ if (dir_alloc_inode)
+ iput(dir_alloc_inode);
+
LOG_EXIT_STATUS (status);
return status;
} /* ocfs_insert_file */
Modified: trunk/src/file.c
===================================================================
--- trunk/src/file.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/file.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -986,9 +986,11 @@
LOG_ENTRY_ARGS ("(file_off = %llu, file_size = %llu\n",
file_off, file_size);
- new_alloc_size = (file_size + (osb->vol_layout.cluster_size - 1)) >>
- osb->cluster_size_bits;
+ new_alloc_size = ((file_size + (osb->vol_layout.cluster_size - 1)) >>
+ osb->cluster_size_bits) << osb->cluster_size_bits;
+ LOG_TRACE_ARGS("new_alloc_size = %llu\n", new_alloc_size);
+
status = ocfs_read_bh (osb, file_off, &bh, OCFS_BH_CACHED, inode);
if (status < 0) {
LOG_ERROR_STATUS (status);
@@ -1136,6 +1138,9 @@
struct buffer_head *bh = NULL;
int flags = 0;
ocfs_journal_handle *handle = NULL;
+ int credits;
+ struct inode *ext_alloc_inode = NULL;
+ __u64 ext_alloc_off;
LOG_ENTRY ();
@@ -1161,11 +1166,16 @@
OCFS_BH_PUT_DATA(bh);
goto leave;
}
+
+ allocSize = file_size - fileEntry->alloc_size;
OCFS_BH_PUT_DATA(bh);
fileEntry = NULL;
if (passed_handle == NULL) {
+ credits = ocfs_calc_extend_credits(((__u32) allocSize),
+ osb->vol_layout.cluster_size);
+
/* cannot call start_trans with a locked buffer head. */
handle = ocfs_start_trans(osb, OCFS_FILE_EXTEND_CREDITS);
if (handle == NULL) {
@@ -1268,12 +1278,19 @@
}
}
- down (&osb->node_alloc_sem);
+ ext_alloc_off = ((OCFS_FILE_FILE_ALLOC_BITMAP + osb->node_num) * osb->sect_size) + osb->vol_layout.root_int_off;
+ ext_alloc_inode = ocfs_iget(osb, ext_alloc_off, NULL);
+ if (!ext_alloc_inode) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ down(&ext_alloc_inode->i_sem);
status = ocfs_allocate_extent (osb, bh, handle,
actualDiskOffset, actualLength, inode);
- up (&osb->node_alloc_sem);
+ up(&ext_alloc_inode->i_sem);
if (status < 0) {
- OCFS_BH_PUT_DATA(bh);
LOG_ERROR_STATUS (status);
goto leave;
}
@@ -1346,6 +1363,9 @@
if (bh != NULL)
brelse(bh);
+ if (ext_alloc_inode)
+ iput(ext_alloc_inode);
+
LOG_EXIT_STATUS (status);
return status;
} /* ocfs_extend_file */
Modified: trunk/src/hash.c
===================================================================
--- trunk/src/hash.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/hash.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -438,9 +438,12 @@
if (++bucket < OcfsGlobalCtxt.bh_sem_hash_sz)
goto again;
- if (found)
+ if (found) {
LOG_ERROR_ARGS("Found %d modified buffers!\n", found);
-
+#ifdef BH_SEM_LEAK_CHECKING
+ BUG();
+#endif
+ }
return found;
} /* ocfs_bh_sem_hash_cleanup_pid() */
Modified: trunk/src/inc/journal.h
===================================================================
--- trunk/src/inc/journal.h 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/inc/journal.h 2004-05-25 00:24:56 UTC (rev 933)
@@ -153,10 +153,6 @@
* freed ONLY if
* we commit the
* handle. */
- struct _ocfs_bitmap_free_head *abort_bits; /* bits to be
- * freed ONLY if
- * we abort the
- * handle. */
__u64 new_file_lockid; /* offset for the
* most recently
* created file
@@ -200,21 +196,6 @@
type); \
rv; \
})
-#define ocfs_handle_add_abort_bits(handle, len, fileoff, nodenum, type) \
-({ \
- int rv = 0; \
- if (!handle->abort_bits) \
- handle->abort_bits = ocfs_alloc_bitmap_free_head(); \
- \
- if (!handle->abort_bits) \
- rv = -ENOMEM; \
- else \
- rv = ocfs_add_to_bitmap_free_head(handle->osb, \
- handle->abort_bits, \
- len, fileoff, nodenum, \
- type); \
- rv; \
-})
/*
* Journal Configuration Management:
@@ -285,6 +266,7 @@
*/
#define OCFS_JOURNAL_ACCESS_CREATE 0
#define OCFS_JOURNAL_ACCESS_WRITE 1
+#define OCFS_JOURNAL_ACCESS_UNDO 2
int ocfs_journal_access(ocfs_journal_handle *handle,
struct buffer_head *bh, int type);
/*
@@ -344,17 +326,42 @@
/* locknode + new fe + dirnode head + new dirnode for parent directory
* + extending (diralloc, filealloc, dirallocbitmap, fileallocbitmap)
- * + a second dirnode for handling mkdir + some fuzz. */
+ * + a second dirnode for handling mkdir + 2 * 2 = 4 blocks for
+ * setting the bits in the dir alloc bitmap and the metadata alloc
+ * bitmap if dir alloc needs to be extended + some fuzz. */
#define OCFS_MKNOD_CREDITS (1 + 1 + (OCFS_DEFAULT_DIR_NODE_SECTS*2) + \
(OCFS_SINGLE_FILE_EXTEND_CREDITS * 4) + \
OCFS_JOURNAL_FUZZ_CREDITS)
/* single file metadata updates * 3 because we might have to extend
* the file alloc and file alloc bitmap files + possible update to
- * local bitmap. */
+ * local bitmap. + 2 blocks for bits to set in the metadata alloc
+ * bitmap file */
#define OCFS_FILE_EXTEND_CREDITS (OCFS_SINGLE_FILE_EXTEND_CREDITS * 3 \
- + 1 + OCFS_JOURNAL_FUZZ_CREDITS)
+ + 1 + 2 + OCFS_JOURNAL_FUZZ_CREDITS)
+/* Now that we journal bitmap writes, this might get a bit more
+ * complicated, use this function to determine how many credits are
+ * needed for an extend. Unfortunately, we're in bytes because the
+ * rest of the file system is.
+ *
+ * PLEASE can we fix up our include file mess so this can be a static inline?!
+ */
+static inline int ocfs_calc_extend_credits(__u32 bytes_wanted,
+ __u32 cluster_size)
+{
+ int bitmap_blocks;
+ unsigned int bits_wanted;
+
+ bits_wanted = OCFS_ALIGN(bytes_wanted, cluster_size) / cluster_size;
+ /* take advantage of the fact that we always allocate in one
+ * large chunk. */
+ bitmap_blocks = 1 + OCFS_ALIGN(bits_wanted, OCFS_BITS_IN_CHUNK) /
+ OCFS_BITS_IN_CHUNK;
+
+ return(bitmap_blocks + OCFS_FILE_EXTEND_CREDITS);
+}
+
/* fe, anything along new 'edge' of tree + fuzz*/
#define OCFS_FILE_TRUNCATE_CREDITS (1 + 4 + OCFS_JOURNAL_FUZZ_CREDITS)
@@ -362,10 +369,11 @@
#define OCFS_FILE_DELETE_CREDITS (1 + 1 + 1 + OCFS_JOURNAL_FUZZ_CREDITS)
/* need to create a new file and extend it to hold the info for the
- * symlink. we wind up with twice the fuzz because we reuse some
- * macros so we subtract one.*/
+ * symlink we add one for a potential write of the main bitmap. Since
+ * we wind up with twice the fuzz because we reuse some macros so we
+ * subtract one.*/
#define OCFS_SYMLINK_CREDITS (OCFS_MKNOD_CREDITS + OCFS_FILE_EXTEND_CREDITS \
- - OCFS_JOURNAL_FUZZ_CREDITS)
+ + 1 - OCFS_JOURNAL_FUZZ_CREDITS)
/* fe change, locknode change, dirnode head, times two plus a possible
* delete, three to fix the up_node_hdr_ptr values of any extents
Modified: trunk/src/inc/ocfs.h
===================================================================
--- trunk/src/inc/ocfs.h 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/inc/ocfs.h 2004-05-25 00:24:56 UTC (rev 933)
@@ -97,6 +97,43 @@
#endif
#include <linux/smp_lock.h>
+
+#define OCFS_BITMAP_CHUNK (512) /* size of a chunk, in bytes */
+#define OCFS_BITS_IN_CHUNK (OCFS_BITMAP_CHUNK * 8)
+//#define OCFS_BITMAP_NUM_BH (ONE_MEGA_BYTE / OCFS_BITMAP_CHUNK)
+/* Lovely convenience macros. If we move to a scheme where
+ * OCFS_BITS_IN_CHUNK or OCFS_BITMAP_NUM_BH are not constant, this'll
+ * be nice. */
+#define OCFS_CHUNK_TO_GLOBAL_OFF(index, localoffset) \
+ ((index) * OCFS_BITS_IN_CHUNK + (localoffset))
+#define OCFS_GLOBAL_OFF_TO_CHUNK(globaloffset) \
+ ((globaloffset) / OCFS_BITS_IN_CHUNK)
+#define OCFS_GLOBAL_OFF_TO_LOCAL(globaloffset) \
+ ((globaloffset) % OCFS_BITS_IN_CHUNK)
+#define OCFS_BITMAP_RANGE_BITS(startbh, startoff, endbh, endoff) \
+ (OCFS_CHUNK_TO_GLOBAL_OFF((endbh), (endoff)) - \
+ OCFS_CHUNK_TO_GLOBAL_OFF((startbh), (startoff)))
+
+typedef struct _ocfs_alloc_bm
+{
+ __u32 validbits; /* number of valid bits */
+ __u32 allocbits; /* number of allocated bits */
+ __u32 failed;
+ __u32 ok_retries;
+ /* 'numbh' is the number of buffer heads in chunk. We keep
+ * around enough buffer heads to cover the entire alloc'd size
+ * of the bitmap, even though we may only ever care about the
+ * valid size */
+ __u32 numbh;
+ struct buffer_head **chunk;
+}
+ocfs_alloc_bm;
+
+#define OCFS_ALIGN(val, align) \
+ ((__u64)val + \
+ (((__u64)val % align) ? (align - ((__u64)val % align)): 0))
+
+
#include "journal.h"
@@ -609,11 +646,6 @@
(((__u64)buf % OCFS_SECTOR_SIZE) ? \
(OCFS_SECTOR_SIZE - ((__u64)buf % OCFS_SECTOR_SIZE)):0))
-
-#define OCFS_ALIGN(val, align) \
- ((__u64)val + \
- (((__u64)val % align) ? (align - ((__u64)val % align)): 0))
-
/*
** Structures...
*/
@@ -1453,38 +1485,6 @@
}
BARF_BARF_BARF;
-
-#define OCFS_BITMAP_CHUNK (512) /* size of a chunk, in bytes */
-#define OCFS_BITS_IN_CHUNK (OCFS_BITMAP_CHUNK * 8)
-//#define OCFS_BITMAP_NUM_BH (ONE_MEGA_BYTE / OCFS_BITMAP_CHUNK)
-/* Lovely convenience macros. If we move to a scheme where
- * OCFS_BITS_IN_CHUNK or OCFS_BITMAP_NUM_BH are not constant, this'll
- * be nice. */
-#define OCFS_CHUNK_TO_GLOBAL_OFF(index, localoffset) \
- ((index) * OCFS_BITS_IN_CHUNK + (localoffset))
-#define OCFS_GLOBAL_OFF_TO_CHUNK(globaloffset) \
- ((globaloffset) / OCFS_BITS_IN_CHUNK)
-#define OCFS_GLOBAL_OFF_TO_LOCAL(globaloffset) \
- ((globaloffset) % OCFS_BITS_IN_CHUNK)
-#define OCFS_BITMAP_RANGE_BITS(startbh, startoff, endbh, endoff) \
- (OCFS_CHUNK_TO_GLOBAL_OFF((endbh), (endoff)) - \
- OCFS_CHUNK_TO_GLOBAL_OFF((startbh), (startoff)))
-
-typedef struct _ocfs_alloc_bm
-{
- __u32 validbits; /* number of valid bits */
- __u32 allocbits; /* number of allocated bits */
- __u32 failed;
- __u32 ok_retries;
- /* 'numbh' is the number of buffer heads in chunk. We keep
- * around enough buffer heads to cover the entire alloc'd size
- * of the bitmap, even though we may only ever care about the
- * valid size */
- __u32 numbh;
- struct buffer_head **chunk;
-}
-ocfs_alloc_bm;
-
typedef struct _ocfs_extent
{
struct list_head list;
@@ -1814,8 +1814,6 @@
__u32 recovery_map;
int disable_recovery;
atomic_t num_recovery_threads;
- struct semaphore node_alloc_sem;
- struct semaphore vol_alloc_sem;
struct timer_list lock_timer;
atomic_t lock_stop;
wait_queue_head_t lock_event;
Modified: trunk/src/inc/proto.h
===================================================================
--- trunk/src/inc/proto.h 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/inc/proto.h 2004-05-25 00:24:56 UTC (rev 933)
@@ -31,7 +31,7 @@
int ocfs_free_extents_for_truncate (ocfs_super * osb, ocfs_file_entry * FileEntry, ocfs_journal_handle *handle, struct inode *inode);
int ocfs_lookup_file_allocation (ocfs_super * osb, __s64 Vbo, __s64 * Lbo, __u32 sectors, u32 *sector_count, struct inode *inode);
int ocfs_get_leaf_extent (ocfs_super * osb, ocfs_file_entry * FileEntry, __s64 Vbo, struct buffer_head **data_extent_bh, struct inode *inode);
-int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count,int sysfile, struct buffer_head *lock_bh, struct inode *bitmap_inode);
+int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, ocfs_journal_handle *handle, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count,int sysfile, struct buffer_head *lock_bh, struct inode *bitmap_inode);
int ocfs_alloc_node_block (ocfs_super * osb, __u64 FileSize, __u64 * DiskOffset, __u64 * file_off, __u32 NodeNum, __u32 Type, ocfs_journal_handle *handle);
int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe, ocfs_journal_handle *handle, struct inode *inode);
int ocfs_free_file_extents (ocfs_super * osb, struct buffer_head *fe_bh, ocfs_journal_handle *handle, struct inode *inode);
@@ -187,8 +187,8 @@
void ocfs_reinitialize_bitmap(ocfs_alloc_bm *bitmap, __u32 validbits, __u32 allocbits);
int ocfs_find_clear_bits (ocfs_super *osb, ocfs_alloc_bm * bitmap, __u32 numBits, __u32 offset, __u32 sysonly);
int ocfs_count_bits (ocfs_alloc_bm * bitmap);
-void ocfs_set_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num);
-void ocfs_clear_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num);
+void ocfs_set_bits (ocfs_journal_handle *handle, ocfs_alloc_bm * bitmap, __u32 start, __u32 num);
+void ocfs_clear_bits (ocfs_journal_handle *handle, ocfs_alloc_bm * bitmap, __u32 start, __u32 num);
int ocfs_get_config (ocfs_super * osb);
int ocfs_chk_update_config (ocfs_super * osb);
Modified: trunk/src/journal.c
===================================================================
--- trunk/src/journal.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/journal.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -92,7 +92,7 @@
retval->journal = &osb->journal;
retval->osb = osb;
- retval->commit_bits = retval->abort_bits = NULL;
+ retval->commit_bits = NULL;
/* actually start the transaction now */
retval->k_handle = journal_start(journal, max_buffs);
@@ -339,7 +339,7 @@
int retval, i;
int checkpoint, sync;
ocfs_journal *journal;
- ocfs_bitmap_free_head *commit_head, *abort_head;
+ ocfs_bitmap_free_head *commit_head;
LOG_ENTRY();
@@ -443,8 +443,7 @@
/* save off while we still have trans lock */
commit_head = handle->commit_bits;
- abort_head = handle->abort_bits;
- handle->commit_bits = handle->abort_bits = NULL;
+ handle->commit_bits = NULL;
/* This has to happen after we release the other locks. */
ocfs_release_trans_lock(osb);
@@ -455,7 +454,6 @@
ocfs_process_bitmap_free_head(osb, commit_head);
}
ocfs_free_bitmap_free_head(commit_head);
- ocfs_free_bitmap_free_head(abort_head);
if (checkpoint)
ocfs_free(handle);
@@ -578,28 +576,20 @@
osb->journal.curr = NULL;
up(&osb->journal.commit_sem);
- /* Ok, we now want to fill our buffers with the older (but
- * valid) data, instead of leaving them with the aborted
- * data. To do so we want to first checkpoint the valid
- * transactions in the journal so that we know that disk
- * reflects the latest correct blocks. After that, we just
- * repopulate the buffers from disk. */
- journal_lock_updates(journal->k_journal);
- retval = journal_flush(journal->k_journal);
- journal_unlock_updates(journal->k_journal);
- if (retval < 0)
- LOG_ERROR_STATUS(retval);
+ if (handle->num_buffs) {
+ /* Ok, we now want to fill our buffers with the older (but
+ * valid) data, instead of leaving them with the aborted
+ * data. To do so we want to first checkpoint the valid
+ * transactions in the journal so that we know that disk
+ * reflects the latest correct blocks. After that, we just
+ * repopulate the buffers from disk. */
+ journal_lock_updates(journal->k_journal);
+ retval = journal_flush(journal->k_journal);
+ journal_unlock_updates(journal->k_journal);
+ if (retval < 0)
+ LOG_ERROR_STATUS(retval);
+ }
- /* If we ever worry about abort performance, I'm 90% sure this
- * read is not necessary. */
- if (handle->num_buffs != 0)
- retval = ocfs_read_bhs(osb,
- handle->buffs[0]->b_blocknr * osb->sect_size,
- handle->num_buffs * osb->sect_size,
- handle->buffs, 0, NULL);
- if (retval < 0)
- LOG_ERROR_STATUS(retval);
-
for(i = 0; i < handle->num_buffs; i++) {
ocfs_clear_buffer_modified(handle->buffs[i]);
brelse(handle->buffs[i]);
@@ -613,12 +603,8 @@
/* This has to happen after we release the other locks. */
ocfs_release_trans_lock(osb);
- /* no need to save off commit or abort heads here; not on any lists */
- if (handle->abort_bits && (retval == 0))
- ocfs_process_bitmap_free_head(osb, handle->abort_bits);
-
+ /* Should only be processed in commit. */
ocfs_free_bitmap_free_head(handle->commit_bits);
- ocfs_free_bitmap_free_head(handle->abort_bits);
if (handle->buffs)
ocfs_free(handle->buffs);
@@ -690,9 +676,11 @@
handle->co_buffs[i].data = NULL;
handle->co_buffs[i].forget = 1;
} else {
+ /* WRITE or UNDO access */
LOG_TRACE_ARGS("Copying block (%llu) out to position"
"%d\n",
(unsigned long long)bh->b_blocknr, i);
+
/* This malloc should just be a slab. */
handle->co_buffs[i].data = ocfs_malloc(bh->b_size);
if (handle->co_buffs[i].data == NULL) {
@@ -713,6 +701,10 @@
#endif
break;
+ case OCFS_JOURNAL_ACCESS_UNDO:
+ status = journal_get_undo_access(handle->k_handle, bh);
+ break;
+
default:
status = -EINVAL;
LOG_ERROR_STR("Uknown access type!");
Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/namei.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -259,6 +259,7 @@
struct buffer_head *fe_bh = NULL;
int i;
unsigned long blk;
+ struct inode *dir_alloc_inode = NULL;
LOG_ENTRY_ARGS ("(0x%p, 0x%p, %d, %d, '%*s')\n", dir, dentry, mode,
dev, dentry->d_name.len, dentry->d_name.name);
@@ -329,6 +330,7 @@
int numblks;
int bufsize;
void *tmp;
+ __u64 dir_alloc_off;
numblks = osb->vol_layout.dir_node_size >> osb->sect_size_bits;
bufsize = numblks * sizeof(struct buffer_head *);
@@ -340,12 +342,19 @@
memset(dirbhs, 0, bufsize);
/* allocate directory space and setup pointers */
- down(&osb->node_alloc_sem);
+ dir_alloc_off = ((OCFS_FILE_DIR_ALLOC_BITMAP + osb->node_num) * osb->sect_size) + osb->vol_layout.root_int_off;
+ dir_alloc_inode = ocfs_iget(osb, dir_alloc_off, NULL);
+ if (!dir_alloc_inode) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ down(&dir_alloc_inode->i_sem);
status = ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size, &bitmapOffset, &fileOffset, osb->node_num, DISK_ALLOC_DIR_NODE, handle);
- up(&osb->node_alloc_sem);
+ up(&dir_alloc_inode->i_sem);
if (status < 0) {
ocfs_safefree (dirbhs);
-// OCFS_BH_PUT_DATA(lock_bh);
LOG_ERROR_STATUS (status);
goto leave;
}
@@ -415,6 +424,9 @@
leave:
ocfs_release_file_entry(fe);
+ if (dir_alloc_inode)
+ iput(dir_alloc_inode);
+
LOG_EXIT_STATUS (status);
return status;
} /* ocfs_mknod_locked */
Modified: trunk/src/osb.c
===================================================================
--- trunk/src/osb.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/osb.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -73,8 +73,6 @@
init_MUTEX (&(osb->extend_sem));
init_MUTEX (&(osb->cfg_lock));
init_MUTEX (&(osb->vote_sem));
- init_MUTEX (&(osb->node_alloc_sem));
- init_MUTEX (&(osb->vol_alloc_sem));
init_MUTEX (&(osb->local_alloc_sem));
spin_lock_init(&osb->recovery_map_lock);
Modified: trunk/src/sysfile.c
===================================================================
--- trunk/src/sysfile.c 2004-05-24 21:34:48 UTC (rev 932)
+++ trunk/src/sysfile.c 2004-05-25 00:24:56 UTC (rev 933)
@@ -281,7 +281,7 @@
__u64 numClusterAlloc = 0, BitmapOffset = 0;
status =
- ocfs_find_contiguous_space_from_bitmap (osb,
+ ocfs_find_contiguous_space_from_bitmap (osb, handle,
FileSize - alloc_size,
&BitmapOffset,
&numClusterAlloc, 1,
@@ -305,6 +305,7 @@
}
if (zero) {
+ /* I think at this point, this can be journalled too */
numbhs = actualLength >> osb->sect_size_bits;
bhs = ocfs_malloc(numbhs*sizeof(struct buffer_head *));
More information about the Ocfs2-commits
mailing list