[Ocfs2-commits] mfasheh commits r1255 - trunk/src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Jul 13 20:03:20 CDT 2004
Author: mfasheh
Date: 2004-07-13 19:03:19 -0500 (Tue, 13 Jul 2004)
New Revision: 1255
Modified:
trunk/src/alloc.c
Log:
* fix a hang with local alloc when we need to clean it up because of ENOSPC.
*
Modified: trunk/src/alloc.c
===================================================================
--- trunk/src/alloc.c 2004-07-13 22:18:45 UTC (rev 1254)
+++ trunk/src/alloc.c 2004-07-14 00:03:19 UTC (rev 1255)
@@ -118,6 +118,9 @@
static int ocfs_local_find_clear_bits(ocfs_super *osb,
ocfs2_dinode *alloc,
__u32 numbits);
+static int ocfs_abort_local_alloc(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *main_bm_inode);
static int ocfs_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
u64 blkno);
@@ -3785,6 +3788,77 @@
return(bitoff);
} /* ocfs_local_find_clear_bits */
+/* we hit some error on the local alloc and need to disable it.
+ * If you pass me the bitmap inode, I'll assume it's all locked for us.
+ */
+static int ocfs_abort_local_alloc(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *main_bm_inode)
+{
+ int status = 0;
+ struct buffer_head *main_bm_bh = NULL;
+ ocfs2_dinode *alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+ if (main_bm_inode) {
+ if (!igrab(main_bm_inode))
+ BUG();
+ } else {
+ 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;
+ }
+
+ ocfs_handle_add_inode(handle, main_bm_inode);
+
+ 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_bh, main_bm_inode, 1);
+ }
+
+ status = ocfs_journal_access(handle, osb->local_alloc_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ status = ocfs_sync_local_to_main(osb, handle, alloc, main_bm_inode);
+ 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;
+ }
+
+ osb->have_local_alloc = 0;
+ brelse(osb->local_alloc_bh);
+ osb->local_alloc_bh = NULL;
+bail:
+ if (main_bm_inode)
+ iput(main_bm_inode);
+
+ if (main_bm_bh)
+ brelse(main_bm_bh);
+
+ return(status);
+}
+
/*
* ocfs_find_space_from_local
*/
@@ -3803,8 +3877,10 @@
LOG_ENTRY_ARGS("(bitswanted = %u)\n", bitswanted);
- if (!osb->have_local_alloc)
- BUG();
+ if (!osb->have_local_alloc) {
+ status = -ENOSPC;
+ goto bail;
+ }
if (bitswanted > ocfs_local_alloc_window_bits(osb)) {
LOG_TRACE_STR("Asking for more than my max window size!\n");
@@ -3823,33 +3899,31 @@
tryagain:
/* If we need to initialize a new window, do so now. */
if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
- alloc = NULL;
LOG_TRACE_STR("Allocating a new window...");
status = ocfs_alloc_new_window(osb, main_bm_bh, main_bm_inode,
handle);
if (status < 0) {
if (status == -ENOSPC) {
- /* TODO: Remove this printk */
printk("ocfs2: disabling local alloc "
"bitmap for this mount.\n");
-#warning this call will hang
- ocfs_shutdown_local_alloc(osb, 0);
+#warning what if we abort_trans after this call?
+ tmpstat = ocfs_abort_local_alloc(osb,
+ handle,
+ main_bm_inode);
+ if (tmpstat < 0) {
+ LOG_ERROR_STATUS(tmpstat);
+ status = tmpstat;
+ }
- /* the bh might not have been dirtied to
- * the journal yet. */
- tmpstat = ocfs_journal_dirty(handle,
- osb->local_alloc_bh);
- if (tmpstat < 0)
- LOG_ERROR_STATUS(tmpstat);
+ alloc = NULL;
goto bail;
}
LOG_ERROR_STATUS(status);
goto bail;
}
atomic_inc(&osb->alloc_stats.moves);
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
}
/* Alright, try to satisfy the request. */
@@ -3860,7 +3934,6 @@
* clear the local out and try again. */
LOG_TRACE_STR("Could not find enough contiguous bits in local "
"alloc bitmap, trying to move my window.");
- alloc = NULL;
if (!main_bm_inode)
main_bm_inode = ocfs_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, -1);
@@ -3887,9 +3960,6 @@
ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE,
0, main_bm_bh, main_bm_inode, 1);
-
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
status = ocfs_sync_local_to_main(osb, handle, alloc,
main_bm_inode);
if (status < 0) {
@@ -3899,7 +3969,6 @@
ocfs_clear_local_alloc(alloc);
- alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
goto tryagain;
}
@@ -3920,8 +3989,6 @@
*bitoff = LOCAL_ALLOC(alloc)->la_bm_off + startoff;
*bitcount = bitswanted;
- alloc = NULL;
-
status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -3993,6 +4060,10 @@
}
ocfs_handle_add_inode(handle, local_alloc_inode);
+ /* If the local alloc has been disabled while we were
+ * waiting for another process to finish with it, then
+ * find_space_from_local will return -ENOSPC and we'll
+ * continue with the global. */
status = ocfs_find_space_from_local(osb, bitswanted,
cluster_off, cluster_count,
handle);
@@ -4064,10 +4135,19 @@
/* do a little verification. */
num_used = ocfs_alloc_count_bits(alloc);
- if (num_used != LOCAL_ALLOC(alloc)->la_bits_set) {
- LOG_TRACE_ARGS("num_used = %u, alloc->la_bits_set = %u!\n",
+ /* 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_bits_set,
+ LOCAL_ALLOC(alloc)->la_bm_bits,
+ LOCAL_ALLOC(alloc)->la_bm_off);
status = -EFAIL;
goto bail;
}
More information about the Ocfs2-commits
mailing list