[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