[Ocfs2-commits] smushran commits r3039 - branches/ocfs2-1.2.6/fs/ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Jul 24 13:20:27 PDT 2007


Author: smushran
Date: 2007-07-24 13:20:26 -0700 (Tue, 24 Jul 2007)
New Revision: 3039

Modified:
   branches/ocfs2-1.2.6/fs/ocfs2/inode.c
   branches/ocfs2-1.2.6/fs/ocfs2/inode.h
   branches/ocfs2-1.2.6/fs/ocfs2/journal.c
   branches/ocfs2-1.2.6/fs/ocfs2/namei.c
   branches/ocfs2-1.2.6/fs/ocfs2/vote.c
   branches/ocfs2-1.2.6/fs/ocfs2/vote.h
Log:
ocfs2:  patch to synchronize inode delete during recovery

When a node deletes a file, it makes an entry into it's orphan directory. The
node that closes the file *last* will compelete the delete. If the node that
initiated the delete dies, then two nodes(one that is recovering the dead node
and the other that is closing the file) can compete to complete the delete
operation. Currently the node that is doing the recovery clears ip_flags
unconditionally so it can proceed with the delete just in case no other nodes
have done the complete. This is leading to duplicate delete and hence the
error.

FIX: Fix for this would be that nodes should remember the node that initiated
the delete and should clear ip_flags only if the recovery is being done for
that node.

Signed-off-by: seeda

Modified: branches/ocfs2-1.2.6/fs/ocfs2/inode.c
===================================================================
--- branches/ocfs2-1.2.6/fs/ocfs2/inode.c	2007-07-24 20:14:25 UTC (rev 3038)
+++ branches/ocfs2-1.2.6/fs/ocfs2/inode.c	2007-07-24 20:20:26 UTC (rev 3039)
@@ -180,7 +180,8 @@
 		 * has the state when it gets to delete_inode. */
 		if (args->fi_flags & OCFS2_FI_FLAG_DELETE) {
 			spin_lock(&oi->ip_lock);
-			ocfs2_mark_inode_remotely_deleted(inode);
+			ocfs2_mark_inode_remotely_deleted(inode,
+							O2NM_INVALID_NODE_NUM);
 			spin_unlock(&oi->ip_lock);
 		}
 		goto bail;
@@ -273,6 +274,7 @@
 
 	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
 	OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT;
+	OCFS2_I(inode)->ip_deleting_node = O2NM_INVALID_NODE_NUM;
 
 	if (create_ino)
 		inode->i_ino = ino_from_blkno(inode->i_sb,

Modified: branches/ocfs2-1.2.6/fs/ocfs2/inode.h
===================================================================
--- branches/ocfs2-1.2.6/fs/ocfs2/inode.h	2007-07-24 20:14:25 UTC (rev 3038)
+++ branches/ocfs2-1.2.6/fs/ocfs2/inode.h	2007-07-24 20:20:26 UTC (rev 3039)
@@ -45,6 +45,8 @@
 	struct ocfs2_extent_map	ip_map;
 	struct list_head	ip_io_markers;
 	int			ip_orphaned_slot;
+	/* to track the node that is doing the delete */
+	int			ip_deleting_node;
 
 	struct semaphore	ip_io_sem;
 

Modified: branches/ocfs2-1.2.6/fs/ocfs2/journal.c
===================================================================
--- branches/ocfs2-1.2.6/fs/ocfs2/journal.c	2007-07-24 20:14:25 UTC (rev 3038)
+++ branches/ocfs2-1.2.6/fs/ocfs2/journal.c	2007-07-24 20:20:26 UTC (rev 3039)
@@ -65,7 +65,7 @@
 static int ocfs2_trylock_journal(struct ocfs2_super *osb,
 				 int slot_num);
 static int ocfs2_recover_orphans(struct ocfs2_super *osb,
-				 int slot);
+				 int slot, int node_num);
 static int ocfs2_commit_thread(void *arg);
 
 static int ocfs2_commit_cache(struct ocfs2_super *osb)
@@ -882,6 +882,7 @@
 	int			lri_slot;
 	struct ocfs2_dinode	*lri_la_dinode;
 	struct ocfs2_dinode	*lri_tl_dinode;
+	int 			lri_node_num;
 };
 
 /* Does the second half of the recovery process. By this point, the
@@ -944,7 +945,8 @@
 			kfree(tl_dinode);
 		}
 
-		ret = ocfs2_recover_orphans(osb, item->lri_slot);
+		ret = ocfs2_recover_orphans(osb, item->lri_slot, 
+							item->lri_node_num);
 		if (ret < 0)
 			mlog_errno(ret);
 
@@ -961,7 +963,8 @@
 static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
 					    int slot_num,
 					    struct ocfs2_dinode *la_dinode,
-					    struct ocfs2_dinode *tl_dinode)
+					    struct ocfs2_dinode *tl_dinode,
+					    int node_num)
 {
 	struct ocfs2_la_recovery_item *item;
 
@@ -983,6 +986,7 @@
 	INIT_LIST_HEAD(&item->lri_list);
 	item->lri_la_dinode = la_dinode;
 	item->lri_slot = slot_num;
+	item->lri_node_num = node_num;
 	item->lri_tl_dinode = tl_dinode;
 
 	spin_lock(&journal->j_lock);
@@ -1003,7 +1007,8 @@
 		ocfs2_queue_recovery_completion(journal,
 						osb->slot_num,
 						osb->local_alloc_copy,
-						NULL);
+						NULL,
+						osb->node_num);
 		ocfs2_schedule_truncate_log_flush(osb, 0);
 
 		osb->local_alloc_copy = NULL;
@@ -1013,7 +1018,8 @@
 
 static int __ocfs2_recovery_thread(void *arg)
 {
-	int status, node_num;
+	int status;
+	int node_num = O2NM_INVALID_NODE_NUM;
 	struct ocfs2_super *osb = arg;
 
 	mlog_entry_void();
@@ -1056,7 +1062,7 @@
 	 * node(s) may have voted "no" on an inode delete earlier. A
 	 * revote is therefore required. */
 	ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL,
-					NULL);
+					NULL, node_num);
 
 bail:
 	down(&osb->recovery_lock);
@@ -1299,7 +1305,7 @@
 
 	/* This will kfree the memory pointed to by la_copy and tl_copy */
 	ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy,
-					tl_copy);
+					tl_copy, node_num);
 
 	status = 0;
 done:
@@ -1397,6 +1403,7 @@
 
 static int ocfs2_queue_orphans(struct ocfs2_super *osb,
 			       int slot,
+			       int node_num,
 			       struct inode **head)
 {
 	int status;
@@ -1406,6 +1413,7 @@
 	struct buffer_head *bh = NULL;
 	struct ocfs2_dir_entry *de;
 	struct super_block *sb = osb->sb;
+	struct ocfs2_inode_info *oi;
 
 	orphan_dir_inode = ocfs2_get_system_file_inode(osb,
 						       ORPHAN_DIR_SYSTEM_INODE,
@@ -1483,6 +1491,23 @@
 
 			mlog(0, "queue orphan %"MLFu64"\n",
 			     OCFS2_I(iter)->ip_blkno);
+
+			oi = OCFS2_I(iter);
+			spin_lock(&oi->ip_lock);
+			/* Delete voting may have set these on the assumption
+			 * that the other node would wipe them successfully.
+			 * If they are still in the node's orphan dir, we need
+			 * to reset that state. */
+			if (oi->ip_deleting_node == node_num)
+				oi->ip_flags &= 
+				~(OCFS2_INODE_DELETED|OCFS2_INODE_SKIP_DELETE);
+
+			/* Set the proper information to get us going into
+			 * ocfs2_delete_inode. */
+			oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
+			oi->ip_orphaned_slot = slot;
+			spin_unlock(&oi->ip_lock);
+
 			/* No locking is required for the next_orphan
 			 * queue as there is only ever a single
 			 * process doing orphan recovery. */
@@ -1557,7 +1582,7 @@
  *   advertising our state to ocfs2_delete_inode().
  */
 static int ocfs2_recover_orphans(struct ocfs2_super *osb,
-				 int slot)
+				 int slot, int node_num)
 {
 	int ret = 0;
 	struct inode *inode = NULL;
@@ -1567,7 +1592,7 @@
 	mlog(0, "Recover inodes from orphan dir in slot %d\n", slot);
 
 	ocfs2_mark_recovering_orphan_dir(osb, slot);
-	ret = ocfs2_queue_orphans(osb, slot, &inode);
+	ret = ocfs2_queue_orphans(osb, slot, node_num, &inode);
 	ocfs2_clear_recovering_orphan_dir(osb, slot);
 
 	/* Error here should be noted, but we want to continue with as
@@ -1581,19 +1606,6 @@
 
 		iter = oi->ip_next_orphan;
 
-		spin_lock(&oi->ip_lock);
-		/* Delete voting may have set these on the assumption
-		 * that the other node would wipe them successfully.
-		 * If they are still in the node's orphan dir, we need
-		 * to reset that state. */
-		oi->ip_flags &= ~(OCFS2_INODE_DELETED|OCFS2_INODE_SKIP_DELETE);
-
-		/* Set the proper information to get us going into
-		 * ocfs2_delete_inode. */
-		oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
-		oi->ip_orphaned_slot = slot;
-		spin_unlock(&oi->ip_lock);
-
 		iput(inode);
 
 		inode = iter;

Modified: branches/ocfs2-1.2.6/fs/ocfs2/namei.c
===================================================================
--- branches/ocfs2-1.2.6/fs/ocfs2/namei.c	2007-07-24 20:14:25 UTC (rev 3038)
+++ branches/ocfs2-1.2.6/fs/ocfs2/namei.c	2007-07-24 20:20:26 UTC (rev 3039)
@@ -194,6 +194,7 @@
 	spin_lock(&oi->ip_lock);
 	oi->ip_flags &= ~OCFS2_INODE_MAYBE_ORPHANED;
 	oi->ip_orphaned_slot = OCFS2_INVALID_SLOT;
+	oi->ip_deleting_node = O2NM_INVALID_NODE_NUM;
 	spin_unlock(&oi->ip_lock);
 
 bail_add:

Modified: branches/ocfs2-1.2.6/fs/ocfs2/vote.c
===================================================================
--- branches/ocfs2-1.2.6/fs/ocfs2/vote.c	2007-07-24 20:14:25 UTC (rev 3038)
+++ branches/ocfs2-1.2.6/fs/ocfs2/vote.c	2007-07-24 20:20:26 UTC (rev 3039)
@@ -156,7 +156,7 @@
 	ocfs2_node_map_set_bit(osb, &osb->umount_map, node_num);
 }
 
-void ocfs2_mark_inode_remotely_deleted(struct inode *inode)
+void ocfs2_mark_inode_remotely_deleted(struct inode *inode, int deleting_node)
 {
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
@@ -167,10 +167,13 @@
 	 * the inode as a result of a crash, then recovery will pick
 	 * up the slack. */
 	oi->ip_flags |= OCFS2_INODE_DELETED|OCFS2_INODE_SKIP_DELETE;
+	if (deleting_node != O2NM_INVALID_NODE_NUM)
+		oi->ip_deleting_node = deleting_node;
 }
 
 static int ocfs2_process_delete_request(struct inode *inode,
-					int *orphaned_slot)
+					int *orphaned_slot,
+					int deleting_node)
 {
 	int response = OCFS2_RESPONSE_BUSY;
 
@@ -247,7 +250,7 @@
 	}
 
 	/* Mark the inode as being wiped from disk. */
-	ocfs2_mark_inode_remotely_deleted(inode);
+	ocfs2_mark_inode_remotely_deleted(inode, deleting_node);
 	spin_unlock(&OCFS2_I(inode)->ip_lock);
 
 	/* Not sure this is necessary anymore. */
@@ -369,6 +372,7 @@
 {
 	int net_status, vote_response;
 	int orphaned_slot = 0;
+	int deleting_node = O2NM_INVALID_NODE_NUM;
 	int rename = 0;
 	unsigned int node_num, generation, new_nlink, namelen;
 	u64 blkno, parent_blkno;
@@ -382,8 +386,10 @@
 	blkno = be64_to_cpu(hdr->h_blkno);
 	generation = be32_to_cpu(hdr->h_generation);
 	node_num = be32_to_cpu(hdr->h_node_num);
-	if (request == OCFS2_VOTE_REQ_DELETE)
+	if (request == OCFS2_VOTE_REQ_DELETE) {
 		orphaned_slot = be32_to_cpu(msg->md1.v_orphaned_slot);
+		deleting_node = be32_to_cpu(msg->v_hdr.h_node_num);
+	}
 
 	mlog(0, "processing vote: request = %u, blkno = %"MLFu64", "
 	     "generation = %u, node_num = %u, priv1 = %u\n", request,
@@ -447,7 +453,7 @@
 	switch (request) {
 	case OCFS2_VOTE_REQ_DELETE:
 		vote_response = ocfs2_process_delete_request(inode,
-							     &orphaned_slot);
+					     &orphaned_slot, deleting_node);
 		break;
 	case OCFS2_VOTE_REQ_RENAME:
 		rename = 1;

Modified: branches/ocfs2-1.2.6/fs/ocfs2/vote.h
===================================================================
--- branches/ocfs2-1.2.6/fs/ocfs2/vote.h	2007-07-24 20:14:25 UTC (rev 3038)
+++ branches/ocfs2-1.2.6/fs/ocfs2/vote.h	2007-07-24 20:20:26 UTC (rev 3039)
@@ -49,7 +49,7 @@
 int ocfs2_register_net_handlers(struct ocfs2_super *osb);
 void ocfs2_unregister_net_handlers(struct ocfs2_super *osb);
 
-void ocfs2_mark_inode_remotely_deleted(struct inode *inode);
+void ocfs2_mark_inode_remotely_deleted(struct inode *inode, int deleting_node);
 
 void ocfs2_remove_node_from_vote_queues(struct ocfs2_super *osb,
 					int node_num);




More information about the Ocfs2-commits mailing list