[Ocfs2-commits] mfasheh commits r1053 - in trunk/src: . inc

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Jun 11 17:07:07 CDT 2004


Author: mfasheh
Date: 2004-06-11 16:07:06 -0500 (Fri, 11 Jun 2004)
New Revision: 1053

Modified:
   trunk/src/alloc.c
   trunk/src/dir.c
   trunk/src/dlm.c
   trunk/src/file.c
   trunk/src/inc/ocfs.h
   trunk/src/inc/proto.h
   trunk/src/inode.c
   trunk/src/namei.c
   trunk/src/nm.c
   trunk/src/super.c
Log:
* First pass at orphaned inode directory. We now can do posix style
  deletes, even from one node to another! The recovery process (in case
  the whole cluster takes a nosedive, etc) still needs to be completed.

* performance improvement in ocfs_mknod_locked and ocfs_bread: don't
  read a newly allocated block off disk as we're about to destroy
  everything in it anyway.

* Fix a bug in ocfs_free_disk_bitmap.



Modified: trunk/src/alloc.c
===================================================================
--- trunk/src/alloc.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/alloc.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -366,8 +366,6 @@
 			goto abort;
 		}
 		ocfs_ugly_hack(handle, globalbh);
-		brelse(ugly_hack_bh);
-		ugly_hack_bh = NULL;
 	}
 
 

Modified: trunk/src/dir.c
===================================================================
--- trunk/src/dir.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/dir.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -170,7 +170,7 @@
 /* ocfs_find_files_on_disk()
  * NOTE: this should always be called with parent dir ip_io_sem taken!
  */
-int ocfs_find_files_on_disk (ocfs_super * osb, struct dentry * dentry, __u64 *fe_off, struct inode *inode, int take_lock, struct buffer_head **dirent_bh, struct ocfs2_dir_entry **dirent)
+int ocfs_find_files_on_disk (ocfs_super * osb, const char *name, int namelen, __u64 *fe_off, struct inode *inode, int take_lock, struct buffer_head **dirent_bh, struct ocfs2_dir_entry **dirent)
 {
 	int status = -ENOENT;
 	int tmpstat;
@@ -178,9 +178,10 @@
 	struct buffer_head *bh = NULL;
 	__u32 lock_type = OCFS_DLM_ENABLE_CACHE_LOCK;
 	__u64 parent_off = GET_INODE_FEOFF(inode);
-	
-	LOG_ENTRY_ARGS ("(osb=%p, parent=%llu, dentry=%p, inode=%p)\n", osb, parent_off, dentry, inode);
 
+	LOG_ENTRY_ARGS ("(osb=%p, parent=%llu, name='%*s', fe_off=%p, inode=%p)\n",
+			osb, parent_off, namelen, name, fe_off, inode);
+
 	if (take_lock) {
 		/* Get a lock on the directory... */
 		status = ocfs_acquire_lock (osb, parent_off, lock_type, FLAG_DIR|FLAG_READDIR, 
@@ -195,7 +196,7 @@
 	}
 
 	status = -ENOENT;
-	*dirent_bh = ocfs_find_entry (dentry, dirent);
+	*dirent_bh = ocfs_find_entry (name, namelen, inode, dirent);
 	if (!*dirent_bh || !*dirent)
 		goto leave;
 

Modified: trunk/src/dlm.c
===================================================================
--- trunk/src/dlm.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/dlm.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -634,8 +634,7 @@
 	/* no need to alert master for these cases */
 	if (S_ISDIR (inode->i_mode) ||
 	    lockres->master_node_num == OCFS_INVALID_NODE_NUM ||
-	    (!(lockres->lock_state & FLAG_ALWAYS_UPDATE_OPEN) &&
-	     IS_NODE_ALIVE (lockres->oin_openmap, osb->node_num, OCFS_MAXIMUM_NODES))) {
+	    IS_NODE_ALIVE (lockres->oin_openmap, osb->node_num, OCFS_MAXIMUM_NODES)) {
 		status = 0;
 		goto bail;
 	}
@@ -862,7 +861,8 @@
 	if (lockres->master_node_num != osb->node_num &&
 	    (wait_on_recovery || no_owner || owner_dead)) {
 		extra_lock_flags = FLAG_REMASTER;
-	} else if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)) {
+	} else if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME 
+			    | FLAG_RELEASE_DENTRY)) {
 		if (ocfs_journal_new_file_search(osb, lock_id)!=0) {
 			extra_lock_flags = 0;
 		} else if (lockres->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK)
@@ -1001,7 +1001,8 @@
 
 	/* Send an update to all nodes alive, can be optimized later TODO */
 	if ((flags & FLAG_FILE_RENAME) || (flags & FLAG_FILE_DELETE)
-	    || (flags & FLAG_FILE_TRUNCATE) || (flags & FLAG_FILE_EXTEND))
+	    || (flags & FLAG_RELEASE_DENTRY) || (flags & FLAG_FILE_TRUNCATE) 
+	    || (flags & FLAG_FILE_EXTEND))
 		votemap = osb->publ_map;
 
 	/* TODO: figure out how to properly handle inode updates w/no oin */
@@ -1013,7 +1014,7 @@
 	if (votemap == 0ULL)
 		goto finally;
 
-	if (!(flags & FLAG_FILE_UPDATE_OIN) && !(flags & FLAG_FILE_DELETE))
+	if (!(flags & FLAG_FILE_UPDATE_OIN))
 		goto finally;
 
 	status = -EAGAIN;
@@ -1163,7 +1164,7 @@
 	}
 
 	lockres->lock_type = OCFS_DLM_NO_LOCK;
-	if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RELEASE_MASTER))
+	if (flags & FLAG_FILE_RELEASE_MASTER)
 		lockres->master_node_num = OCFS_INVALID_NODE_NUM;
 
 	status = ocfs_disk_release_lock (osb, lock_id, lock_type, flags, bh, inode);
@@ -1271,7 +1272,8 @@
 
 	
 	/* figure out who to vote with */
-	if (flags & (FLAG_REMASTER | FLAG_FILE_DELETE | FLAG_FILE_RENAME))
+	if (flags & (FLAG_REMASTER | FLAG_FILE_DELETE | FLAG_FILE_RENAME 
+		     | FLAG_RELEASE_DENTRY))
 		vote_map = osb->publ_map; /* broadcast */
 	else if (flags & FLAG_DROP_READONLY) {
 		/* all nodes that see this is readonly */

Modified: trunk/src/file.c
===================================================================
--- trunk/src/file.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/file.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -356,12 +356,6 @@
 		if (OCFS_I(inode)->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO)
 			OCFS_CLEAR_FLAG(OCFS_I(inode)->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
 
-		if (OCFS_I(inode)->oin_flags & OCFS_OIN_NEEDS_DELETION) {
-			up (&(OCFS_I(inode)->priv_sem));
-			LOG_ERROR_STR("Not deleting lockrse on a last close! eek!");
-			goto bail;
-		}
-
 		/* we might still be holding inode_extend_sem on
 		 * behalf of another node, so release it here. */
 		down(&recovery_list_sem);
@@ -642,7 +636,6 @@
 
 	/* Set the valid bit here */
 	SET_VALID_BIT (fileEntry->sync_flags);
-	fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
 
 	flags = OCFS_FE_CACHE_FLAGS(osb, fileEntry);
 	OCFS_BH_PUT_DATA(bh);
@@ -1033,7 +1026,6 @@
 
 	DISK_LOCK_SEQNUM (fe) = 0;
 	SET_VALID_BIT (fe->sync_flags);
-	fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
 	fe->modify_time = OCFS_CURRENT_TIME;
 	
 	flags = OCFS_FE_CACHE_FLAGS(osb, fe);
@@ -1270,7 +1262,6 @@
 		ocfs_fe_set_attributes(fileEntry, attr);
 	/* Set the Valid bit and reset the change bit here... TODO */
 	SET_VALID_BIT (fileEntry->sync_flags);
-	fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
 	fileEntry->modify_time = OCFS_CURRENT_TIME;
 
 	tempOffset = fileEntry->this_sector;

Modified: trunk/src/inc/ocfs.h
===================================================================
--- trunk/src/inc/ocfs.h	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/inc/ocfs.h	2004-06-11 21:07:06 UTC (rev 1053)
@@ -162,8 +162,8 @@
 enum {
 	INVALID_REQUEST,      // reply with a NO vote
 	UPDATE_OIN_INODE,     // update both oin and inode
-	DELETE_RENAME_ACQUIRE,// delete or rename acquire request
-	DELETE_RENAME_RELEASE,// delete or rename release request
+	DELETE_ACQUIRE,// delete or rename acquire request
+	DELETE_RELEASE,// delete or rename release request
 	RELEASE_CACHE,        // release a cache lock I hold
 	CHANGE_MASTER,        // request to change master to requestor
 	ADD_OIN_MAP,          // add requestor into oin map
@@ -171,7 +171,8 @@
 	REMASTER_THIS,        // remaster lock to me
 	REMASTER_REQUESTOR,   // remaster lock to requestor
 	DROP_READONLY,	      // RO cachelock needs to convert to RW
-	READONLY	      // a RW or RO cachelock, requesting RO
+	READONLY,	      // a RW or RO cachelock, requesting RO
+	RELEASE_DENTRY
 };
 
 #define  OCFS_MAX_DLM_PKT_SIZE			256
@@ -259,7 +260,7 @@
 #define  FLAG_FILE_CREATE_DIR     0x00000040
 #define  FLAG_FILE_UPDATE_OIN     0x00000080
 #define  FLAG_FILE_RELEASE_MASTER 0x00000100
-#define  FLAG_DROP_LINK           0x00000200
+#define  FLAG_RELEASE_DENTRY      0x00000200
 #define  FLAG_CHANGE_MASTER       0x00000400
 #define  FLAG_ADD_OIN_MAP         0x00000800
 #define  FLAG_DIR                 0x00001000
@@ -310,6 +311,7 @@
 #define LOG_FILE_BASE_ID             (OCFS_RECOVER_LOG_SYSFILE    * OCFS_MAXIMUM_NODES)		// unused in version 2
 #define CLEANUP_FILE_BASE_ID         (OCFS_CLEANUP_LOG_SYSFILE    * OCFS_MAXIMUM_NODES)		// unused in version 2
 #define OCFS_LOCAL_ALLOC_FILE        (OCFS_VOL_BM_SYSFILE         * OCFS_MAXIMUM_NODES)		// was OCFS_VOL_BITMAP_FILE
+#define OCFS_ORPHAN_DIR              (OCFS_ORPHAN_DIR_SYSFILE     * OCFS_MAXIMUM_NODES)
 #define OCFS_JOURNAL_FILE            (OCFS_JOURNAL_SYSFILE        * OCFS_MAXIMUM_NODES)
 #define OCFS_INODE_FILE              (OCFS_INODE_SYSFILE          * OCFS_MAXIMUM_NODES)
 #define OCFS_INODE_BITMAP            (OCFS_INODE_BM_SYSFILE       * OCFS_MAXIMUM_NODES)
@@ -433,11 +435,11 @@
 ** File Entry contains this information
 */
 // SYNCFLAG MASK
-#define  OCFS_SYNC_FLAG_DELETED            (0)
+#define  OCFS_SYNC_FLAG_UNUSED1            (0)
 #define  OCFS_SYNC_FLAG_VALID              (0x1)
-#define  OCFS_SYNC_FLAG_CHANGE             (0x2)
-#define  OCFS_SYNC_FLAG_MARK_FOR_DELETION  (0x4)
-#define  OCFS_SYNC_FLAG_NAME_DELETED       (0x8)
+#define  OCFS_SYNC_FLAG_UNUSED2            (0x2)
+#define  OCFS_SYNC_FLAG_ORPHANED           (0x4)
+#define  OCFS_SYNC_FLAG_UNUSED3            (0x8)
 
 // ATTRIBS MASK
 #define  OCFS_ATTRIB_DIRECTORY             (0x1)
@@ -1142,7 +1144,7 @@
 			__u32 used_bits;
 			__u32 total_bits;
 		} ip_bitinfo;
-	} u;     
+	} u;
 
 	ocfs_lock_res     i_lockres;
 	__u32 		  i_dir_start_lookup;
@@ -1152,10 +1154,8 @@
  * merged. */
 /* oin_flags flags */
 #define  OCFS_OIN_DIRECTORY                      (0x00000002)
-#define  OCFS_OIN_DELETE_ON_CLOSE                (0x00000008)
-#define  OCFS_OIN_NEEDS_DELETION                 (0x00000010)
-#define  OCFS_OIN_OPEN_FOR_DIRECTIO              (0x00000100)
-#define  OCFS_OIN_OPEN_FOR_WRITE                 (0x00000200)
+#define  OCFS_OIN_OPEN_FOR_DIRECTIO              (0x00000008)
+#define  OCFS_OIN_OPEN_FOR_WRITE                 (0x00000010)
 
 /* 'flags' flags. */
 /* has this inode been deleted, either from this node or from another node. */
@@ -1166,6 +1166,8 @@
 #define OCFS_INODE_INITIALIZED      0x00000004
 /* is this a system file? */
 #define OCFS_INODE_SYSTEM_FILE      0x00000008
+/* are we going to let another node deal with deletion of this inode? */
+#define OCFS_INODE_SKIP_DELETE      0x00000010
 
 #define GET_INODE_CLEAN_SEQ(i)  (atomic_t *)(&(OCFS_I(i)->i_clean_buffer_seq))
 
@@ -1313,6 +1315,7 @@
 	FILE_ALLOC_BITMAP_SYSTEM_INODE,
 	INODE_ALLOC_BITMAP_SYSTEM_INODE,
 	JOURNAL_SYSTEM_INODE,
+	ORPHAN_DIR_SYSTEM_INODE,
 	NUM_SYSTEM_INODES
 };
 
@@ -1406,6 +1409,7 @@
 	struct semaphore vote_sem; /* protects calls to ocfs_process_vote */
 	struct list_head vote_obj_queue;
 	spinlock_t vote_obj_queue_lock;
+	unsigned long voting_ino; /* only safe from the process_vote pid */
 };
 
 typedef struct _ocfs_comm_info
@@ -1574,6 +1578,7 @@
 			__u32 used_bits;
 			__u32 total_bits;
 		} bitinfo;
+		__u64 i_dtime;
 	} u;
         __u64 alloc_file_off;             // NUMBER RANGE(0,ULONG_LONG_MAX)
         __u32 alloc_node;                 // NUMBER RANGE(0,31)

Modified: trunk/src/inc/proto.h
===================================================================
--- trunk/src/inc/proto.h	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/inc/proto.h	2004-06-11 21:07:06 UTC (rev 1053)
@@ -101,10 +101,10 @@
 
 /* dir.c */
 int empty_dir(struct inode *inode);  /* FIXME: to namei.c */
-int ocfs_find_files_on_disk(ocfs_super *osb, struct dentry *dentry,
-			    __u64 *fe_off, struct inode *inode,
-			    int take_lock, struct buffer_head **dirent_bh,
-			    struct ocfs2_dir_entry **dirent);
+int ocfs_find_files_on_disk (ocfs_super * osb, const char *name, int namelen, 
+			     __u64 *fe_off, struct inode *inode, int take_lock,
+			     struct buffer_head **dirent_bh, 
+			     struct ocfs2_dir_entry **dirent);
 int ocfs_readdir(struct file *filp, void *dirent, filldir_t filldir);
 
 /* dlm.c */
@@ -225,6 +225,7 @@
 struct buffer_head *ocfs_bread(ocfs_journal_handle *handle,
 			       struct inode * inode, int block,
 			       int create, int *err, int reada);
+void ocfs_delete_inode(struct inode *inode);
 void ocfs_clear_inode(struct inode *inode);
 struct inode *ocfs_iget(ocfs_super *osb, __u64 feoff);
 int ocfs_inode_init_private(struct inode *inode);
@@ -265,8 +266,9 @@
 #else
 int ocfs_create (struct inode *dir, struct dentry *dentry, int mode);
 #endif
-struct buffer_head *ocfs_find_entry(struct dentry *dentry,
-				    struct ocfs2_dir_entry **res_dir);
+struct buffer_head * ocfs_find_entry (const char *name, int namelen, 
+				      struct inode *dir, 
+				      struct ocfs2_dir_entry ** res_dir);
 int ocfs_link(struct dentry *old_dentry, struct inode *dir,
 	      struct dentry *dentry);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
@@ -283,11 +285,10 @@
 int ocfs_symlink(struct inode *dir, struct dentry *dentry,
 		 const char *symname);
 int ocfs_unlink(struct inode *dir, struct dentry *dentry);
+int ocfs_orphan_del(ocfs_super *osb, ocfs_journal_handle *handle, 
+		    struct inode *orphan_dir_inode, struct inode *inode, 
+		    struct buffer_head *orphan_dir_bh);
 
-/* FIXME: only in namei.c */
-int ocfs_orphan_add(ocfs_journal_handle *handle, struct inode *inode);
-int ocfs_orphan_del(ocfs_journal_handle *handle, struct inode *inode);
-
 /* nm.c */
 int ocfs_drop_readonly_cache_lock(ocfs_super *osb, struct inode *inode,
 				  int yield);

Modified: trunk/src/inode.c
===================================================================
--- trunk/src/inode.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/inode.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -641,6 +641,179 @@
 }
 
 /*
+ * ocfs_delete_inode()
+ *
+ */
+void ocfs_delete_inode(struct inode *inode)
+{
+	struct inode *orphan_dir_inode = NULL;
+	ocfs_journal_handle *handle = NULL;
+	ocfs_super *osb = OCFS_SB(inode->i_sb);
+	int status = 0;
+	int release_disk_lock = 0;
+	struct buffer_head *orphan_dir_bh = NULL;
+	struct buffer_head *fe_bh = NULL;
+	__u32 lock_flags = FLAG_FILE_DELETE;
+	ocfs_file_entry *fe;
+
+	LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
+
+	if (OCFS_I(inode)->flags & OCFS_INODE_SYSTEM_FILE) {
+		LOG_TRACE_STR("Skipping system file delete.");
+		goto clear_inode;
+	}
+
+	if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+		LOG_TRACE_STR("Skipping root inode delete.");
+		goto clear_inode;
+	}
+
+	if (OCFS_I(inode)->flags & OCFS_INODE_SKIP_DELETE) {
+		LOG_TRACE_ARGS("Skipping delete of %lu because another node "
+			       "has done this for us.\n", inode->i_ino);
+		goto clear_inode;
+	}
+
+	/* If we're coming from process_vote we can't go into our own
+	 * voting [hello, deadlock city!], so unforuntately we just
+	 * have to skip deleting this guy. That's OK though because
+	 * the node who's doing the actual deleting should handle it
+	 * anyway. */
+	if (osb->voting_ino == inode->i_ino) {
+		LOG_TRACE_ARGS("Skipping delete of %lu because we're currently"
+			       "in process_vote\n", inode->i_ino);
+		goto clear_inode;
+	}
+
+	orphan_dir_inode = igrab(osb->system_inodes[ORPHAN_DIR_SYSTEM_INODE]);
+	if (!orphan_dir_inode) {
+		LOG_ERROR_STATUS(-EFAIL);
+		goto clear_inode;
+	}
+
+	lock_kernel();
+
+	/* Oop, lets be carefull of lock / trans ordering here... */
+	handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
+	if (handle == NULL) {
+		unlock_kernel();
+		LOG_ERROR_STATUS(-ENOMEM);
+		goto clear_inode;
+	}
+
+	ocfs_handle_add_inode(handle, orphan_dir_inode);
+
+	status = ocfs_acquire_lock(osb, GET_INODE_FEOFF(orphan_dir_inode), 
+				   OCFS_DLM_EXCLUSIVE_LOCK, 
+				   FLAG_FILE_CREATE | FLAG_DIR,
+				   &orphan_dir_bh, orphan_dir_inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail_locked;
+	}
+	ocfs_handle_add_lock(handle, OCFS_DLM_EXCLUSIVE_LOCK, 
+			     FLAG_FILE_CREATE | FLAG_DIR, orphan_dir_bh,
+			     orphan_dir_inode, 1);
+
+	/* take ip_io_sem on the inode, only to avoid a warning in
+	 * acquire_lockres. We can get rid of it when we get rid of
+	 * acquire_lockres */
+	down(&OCFS_I(inode)->ip_io_sem);
+	if (S_ISDIR(inode->i_mode))
+		lock_flags |= FLAG_DIR;
+	status = ocfs_acquire_lock(osb, GET_INODE_FEOFF(inode),
+				   OCFS_DLM_EXCLUSIVE_LOCK, lock_flags, 
+				   &fe_bh, inode);
+	up(&OCFS_I(inode)->ip_io_sem);
+	if (status < 0) {
+		/* EBUSY here is assumed to mean that other nodes are
+		 * still using the inode. We're done here though, so
+		 * avoid doing anything on disk and let them worry
+		 * about deleting it. */
+		if (status != -EBUSY)
+			LOG_ERROR_STATUS(status);
+		goto bail_locked;
+	}
+	release_disk_lock = 1;
+
+	/* check OCFS_SYNC_FLAG_ORPHANED */
+	fe = OCFS_BH_GET_DATA_READ(fe_bh);
+	if (!(fe->sync_flags & OCFS_SYNC_FLAG_ORPHANED)) {
+		OCFS_BH_PUT_DATA(fe_bh);
+		/* for lack of a better error? */
+		status = -EEXIST;
+		LOG_ERROR_STATUS(status);
+		goto bail_locked;
+	}
+
+	/* has someone already deleted us?! baaad... */
+	if (fe->u.i_dtime) {
+		OCFS_BH_PUT_DATA(fe_bh);
+
+		status = -EEXIST;
+		LOG_ERROR_STATUS(status);
+		goto bail_locked;
+	}
+	OCFS_BH_PUT_DATA(fe_bh);
+
+	status = ocfs_orphan_del(osb, handle, orphan_dir_inode, inode, 
+				 orphan_dir_bh);
+
+	/* set the inodes dtime */
+	status = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail_locked;
+	}
+
+	fe = OCFS_BH_GET_DATA_WRITE(fe_bh);
+	fe->u.i_dtime = CURRENT_TIME;
+	fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
+	fe->sync_flags &= (~OCFS_SYNC_FLAG_ORPHANED);
+	OCFS_BH_PUT_DATA(fe_bh);
+
+	status = ocfs_journal_dirty(handle, fe_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail_locked;
+	}
+
+	/* actually delete the data and the inode */
+	status = ocfs_free_file_extents(osb, fe_bh, handle, inode);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+
+bail_locked:
+	if (handle && (status == 0))
+		ocfs_commit_trans(handle);
+	else if (handle)
+		ocfs_abort_trans(handle);
+
+	if (release_disk_lock) {
+		down(&OCFS_I(inode)->ip_io_sem);
+		status = ocfs_release_lock(osb, GET_INODE_FEOFF(inode),
+					   OCFS_DLM_EXCLUSIVE_LOCK, lock_flags,
+					   fe_bh, inode);
+		up(&OCFS_I(inode)->ip_io_sem);
+		if (status < 0)
+			LOG_ERROR_STATUS(status);
+	}
+
+	unlock_kernel();
+
+	if (orphan_dir_bh)
+		brelse(orphan_dir_bh);
+	if (fe_bh)
+		brelse(fe_bh);
+
+	iput(orphan_dir_inode);
+clear_inode:
+	/* we must clear inode. */
+	clear_inode(inode);
+	LOG_EXIT();
+}				/* ocfs_delete_inode */
+
+/*
  * ocfs_clear_inode()
  *
  */
@@ -654,8 +827,8 @@
 	if (!inode)
 		goto bail;
 
-	LOG_TRACE_ARGS("Clearing inode feoff: %llu)\n", 
-		       GET_INODE_FEOFF(inode));
+	LOG_TRACE_ARGS("Clearing inode feoff: %llu, nlink = %u)\n", 
+		       GET_INODE_FEOFF(inode), inode->i_nlink);
 
 	/* we should not really be using osb in this context. */
 	osb = OCFS_SB(inode->i_sb);
@@ -896,25 +1069,35 @@
 	if (tmperr < 0)
 		goto fail;
 
-	tmperr = ocfs_read_bh(osb, lbo, &bh, readflags, inode);
-	if (tmperr < 0)
-		goto fail;
+	if (new) {
+		bh = getblk(OCFS_GET_BLOCKDEV(osb->sb), 
+			    lbo >> osb->sb->s_blocksize_bits, 
+			    osb->sb->s_blocksize);
+		if (!bh) {
+			tmperr = -EIO;
+			goto fail;
+		}
+		set_buffer_uptodate(bh);
+		SET_BH_SEQNUM(inode, bh);
 
-	tmperr = 0;
-	if (new) {
 		fatal = ocfs_journal_access(handle, bh,
 					   OCFS_JOURNAL_ACCESS_CREATE);
-		if (!fatal) {
-			char *buf = OCFS_BH_GET_DATA_WRITE(bh);
-			memset(buf, 0, osb->sect_size);
-			set_buffer_uptodate(bh);
-			OCFS_BH_PUT_DATA(bh);
-			fatal = ocfs_journal_dirty(handle, bh);
-		}
+		if (fatal)
+			goto fail;
+
+		char *buf = OCFS_BH_GET_DATA_WRITE(bh);
+		memset(buf, 0, osb->sect_size);
+		OCFS_BH_PUT_DATA(bh);
+		fatal = ocfs_journal_dirty(handle, bh);	
+		if (fatal)
+			goto fail;
+	} else {
+		tmperr = ocfs_read_bh(osb, lbo, &bh, readflags, inode);
+		if (tmperr < 0)
+			goto fail;
 	}
 
-	if (fatal)
-		goto fail;
+	tmperr = 0;
 
 	*err = 0;
 	return bh;
@@ -1790,14 +1973,13 @@
 		goto leave;
 
 	/* Add checks as needed */
-	if ((fe->sync_flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION) ||
-	    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
-		if (fe->sync_flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION) {
-			LOG_TRACE_STR
-				("File Entry is marked for deletion");
-		} else {
+	if ((fe->u.i_dtime) || (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+		if (fe->u.i_dtime)
+			LOG_ERROR_ARGS("Inode %lu has dtime = %llu\n", 
+				       inode->i_ino, fe->u.i_dtime);
+		else
 			LOG_TRACE_STR ("File Entry is invalid");
-		}
+
 		status = -ENOENT;
 		goto leave;
 	}

Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/namei.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -34,9 +34,17 @@
 
 extern spinlock_t oin_num_ext_lock;
 
-static int inline search_dirblock(struct buffer_head * bh, struct inode *dir, struct dentry *dentry, unsigned long offset, struct ocfs2_dir_entry ** res_dir);
-static int ocfs_delete_entry (ocfs_journal_handle *handle, struct inode * dir, struct ocfs2_dir_entry * de_del, struct buffer_head * bh);
-static int ocfs_add_entry (ocfs_journal_handle *handle, struct dentry *dentry, struct inode *inode, __u64 inode_off, struct buffer_head *parent_fe_bh);
+static int inline search_dirblock(struct buffer_head * bh, struct inode *dir, 
+				  const char *name, int namelen, 
+				  unsigned long offset, 
+				  struct ocfs2_dir_entry ** res_dir);
+static int ocfs_delete_entry (ocfs_journal_handle *handle, struct inode * dir, 
+			      struct ocfs2_dir_entry * de_del, 
+			      struct buffer_head * bh);
+static int __ocfs_add_entry (ocfs_journal_handle *handle, struct inode *dir,
+			     const char *name, int namelen, 
+			     struct inode *inode, __u64 inode_off, 
+			     struct buffer_head *parent_fe_bh);
 static inline int ocfs_match (int len, const char * const name, struct ocfs2_dir_entry * de);
 
 static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir, 
@@ -53,10 +61,23 @@
 			    struct buffer_head **bh2,
 		     	    struct inode *inode2);
 
+static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle, 
+			   struct inode *inode, ocfs_file_entry *fe);
+
 static struct dentry_operations ocfs_dentry_ops = {
 	.d_revalidate = ocfs_dentry_revalidate	// let's test it out!
 };
 
+static inline int ocfs_add_entry(ocfs_journal_handle *handle, 
+				 struct dentry *dentry, 
+				 struct inode *inode, __u64 inode_off, 
+				 struct buffer_head *parent_fe_bh) 
+{
+	return(__ocfs_add_entry(handle, dentry->d_parent->d_inode, 
+				dentry->d_name.name, dentry->d_name.len, 
+				inode, inode_off, parent_fe_bh));
+}
+
 /*
  * ocfs_lookup()
  *
@@ -90,7 +111,9 @@
 		       dir);
 
 	down(&OCFS_I(dir)->ip_io_sem);
-	status = ocfs_find_files_on_disk (osb, dentry, &fe_off, dir, 1, &dirent_bh, &dirent);
+	status = ocfs_find_files_on_disk(osb, dentry->d_name.name, 
+					 dentry->d_name.len, &fe_off, dir, 1, 
+					 &dirent_bh, &dirent);
 	up(&OCFS_I(dir)->ip_io_sem);
 	if (status < 0)
 		goto bail_add;
@@ -312,6 +335,7 @@
 	__u64 bitmapOffset = 0;
 	__u64 fileOffset = 0;
 	struct inode *inode_alloc_inode = NULL;
+	struct super_block *sb = osb->sb;
 
 	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %d, %d, '%*s')\n", dir, dentry, mode,
 			dev, dentry->d_name.len, dentry->d_name.name);
@@ -336,8 +360,16 @@
 		goto leave;
 	}
 
-	status = ocfs_read_bh(osb, bitmapOffset, new_fe_bh,
-				      OCFS_BH_CACHED, inode);
+	*new_fe_bh = getblk (OCFS_GET_BLOCKDEV(sb), 
+			     bitmapOffset >> sb->s_blocksize_bits, 
+			     sb->s_blocksize);
+	if (!*new_fe_bh) {
+		status = -EIO;
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+	set_buffer_uptodate(*new_fe_bh);
+	SET_BH_SEQNUM(inode, *new_fe_bh);
 
 	status = ocfs_journal_access(handle, *new_fe_bh, OCFS_JOURNAL_ACCESS_CREATE);
 	if (status < 0) {
@@ -391,7 +423,6 @@
 	fe->last_ext_ptr = 0;
 	strcpy (fe->signature, OCFS_FILE_ENTRY_SIGNATURE);
 	SET_VALID_BIT (fe->sync_flags);
-	fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
 	DISK_LOCK_SEQNUM (fe) = 0;
 	DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
 	DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
@@ -501,16 +532,14 @@
 	__u64 fe_off = GET_INODE_FEOFF(inode);
 	struct inode *parentInode = dentry->d_parent->d_inode;
 	ocfs_file_entry *fe = NULL;
-	__u32 lockFlags = (S_ISDIR (inode->i_mode) ? (FLAG_FILE_DELETE | FLAG_DIR) : FLAG_FILE_DELETE);
+	__u32 lockFlags = (S_ISDIR (inode->i_mode) ? (FLAG_RELEASE_DENTRY | FLAG_DIR) : FLAG_RELEASE_DENTRY);
 	struct buffer_head *fe_bh = NULL;
 	struct buffer_head *parent_node_bh = NULL; /* parent locknode */
 	ocfs_journal_handle *handle = NULL;
 	__u64 parent_off = GET_INODE_FEOFF(parentInode);
 	struct ocfs2_dir_entry *dirent = NULL;
 	struct buffer_head *dirent_bh = NULL;
-	int drop_inode = 0, dec_parent = 0;
 
-
 	LOG_ENTRY_ARGS ("(0x%p, 0x%p, '%*s')\n", dir, dentry,
 			dentry->d_name.len, dentry->d_name.name);
 
@@ -521,10 +550,9 @@
 	if (S_ISDIR (inode->i_mode) && !empty_dir(inode)) {
 		LOG_TRACE_STR ("dentry is not empty, cannot delete");
 		goto bail;
-	} else if (OCFS_I(inode)->open_hndl_cnt > 0) {
-		LOG_TRACE_ARGS ("Cannot remove an open file (open_hndl_cnt = %u, fe_off = %llu, d_count=%u)\n", OCFS_I(inode)->open_hndl_cnt, fe_off, atomic_read(&dentry->d_count));
-		goto bail;
-	} else if (inode == osb->root_inode) {
+	} 
+
+	if (inode == osb->root_inode) {
 		LOG_TRACE_STR ("Cannot delete the root directory");
 		status = -EPERM;
 		goto bail;
@@ -565,9 +593,10 @@
 	got_parent = 1;
 
 	/* this will re-read the directory now with the EXCLUSIVE */
-	/* lock already held; it will also return the fe_bh to us */
-	status = ocfs_find_files_on_disk (osb, dentry, &fe_off, parentInode, 
-					  0, &dirent_bh, &dirent);
+	/* lock already held */
+	status = ocfs_find_files_on_disk (osb, dentry->d_name.name, 
+					  dentry->d_name.len, &fe_off, 
+					  parentInode, 0, &dirent_bh, &dirent);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto leave;
@@ -590,7 +619,7 @@
 		goto leave;
 	}
 	got_file = 1;
-	
+
 	if (S_ISDIR (inode->i_mode)) {
 	       	if (!empty_dir(inode)) {
 			status = -ENOTEMPTY;
@@ -607,90 +636,78 @@
 		goto leave;
 	}
 
-	/* need to preserve locking order, so take a 'write' lock on
-	 * the dirnode sector first. it won't get passed to
-	 * journal_dirty until ocfs_remove_file so clean up the write
-	 * lock on errors before that */
 	status = ocfs_read_bh(osb, parent_off, &parent_node_bh, 
 			      OCFS_BH_CACHED, parentInode);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
 		goto leave;
 	}
-	OCFS_BH_GET_DATA_WRITE(parent_node_bh);
-	OCFS_BH_PUT_DATA(parent_node_bh);
 
-	/* we call ocfs_clear_buffer_modified in several error cases
-	 * here if we set the modify bit on this buffer, but haven't
-	 * journal_dirtied it yet. Otherwise, it'll stay modified even
-	 * after the abort_trans. */
 	fe = OCFS_BH_GET_DATA_WRITE(fe_bh);
+	if (fe->link_cnt != inode->i_nlink) {
+		printk("ocfs_unlink: hmm, inode has nlink = %u, fe has link_cnt = %u. Setting inode from fe.\n", inode->i_nlink, fe->link_cnt);
+		inode->i_nlink = fe->link_cnt;
+	}
+
 	if (S_ISDIR (inode->i_mode))
 		fe->link_cnt = 0;
-	else 
+	else
 		fe->link_cnt--;
+
 	if (!fe->link_cnt) {
-		drop_inode = 1;
-		OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_MARK_FOR_DELETION);
-		fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
+		status = ocfs_orphan_add(osb, handle, inode, fe);
+		if (status < 0) {
+			OCFS_BH_PUT_DATA(fe_bh);
+			LOG_ERROR_STATUS(status);
+			goto leave;
+		}
 	}
 	OCFS_BH_PUT_DATA(fe_bh);
 
-	if (drop_inode) {
-		/* Free up all the bits in the bitmap. */
-		/* mark all the extents (and extent metadata) for
-	 	* this file so we can remove them after commit. */
-		/* TODO: delay this.  see orphan comment below */
-		status = ocfs_free_file_extents (osb, fe_bh, handle, inode);
+	status = ocfs_journal_dirty(handle, fe_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	/* delete the name from the parent dir */
+	status = ocfs_delete_entry (handle, parentInode, dirent, dirent_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	if (S_ISDIR (inode->i_mode)) {
+		ocfs_file_entry *dirfe;
+		status = ocfs_journal_access(handle, parent_node_bh, 
+					     OCFS_JOURNAL_ACCESS_WRITE);
 		if (status < 0) {
-			ocfs_clear_buffer_modified(fe_bh);
-			ocfs_clear_buffer_modified(parent_node_bh);
-			LOG_ERROR_STATUS (status);
+			LOG_ERROR_STATUS(status);
 			goto leave;
 		}
-	
-		/* delete the name from the parent dir */
-		status = ocfs_delete_entry (handle, parentInode, dirent, dirent_bh);
+		dirfe = OCFS_BH_GET_DATA_WRITE(parent_node_bh);
+		dirfe->link_cnt--;
+		OCFS_BH_PUT_DATA(parent_node_bh);
+		status = ocfs_journal_dirty(handle, fe_bh);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
 			goto leave;
 		}
-		/* 
-	 	* TODO: we should link this entry into the local orphan dir after
-	 	* deleting the name from the parent.  do NOT do the free_file_extents
-	 	* in this function.  delay it until triggered by orphan_del (by 
-	 	* delete_inode, truncate or similar)
-	 	*/
-		if (S_ISDIR (inode->i_mode)) {
-			ocfs_file_entry *dirfe;
-			status = ocfs_journal_access(handle, parent_node_bh, 
-						     OCFS_JOURNAL_ACCESS_WRITE);
-			if (status < 0) {
-				LOG_ERROR_STATUS(status);
-				goto leave;
-			}
-			dirfe = OCFS_BH_GET_DATA_WRITE(parent_node_bh);
-			dirfe->link_cnt--;
-			OCFS_BH_PUT_DATA(parent_node_bh);
-			status = ocfs_journal_dirty(handle, fe_bh);
-			if (status < 0) {
-				LOG_ERROR_STATUS(status);
-				goto leave;
-			}
-			dec_parent=1;
-		}
 	}
 
-	status = ocfs_journal_dirty(handle, fe_bh);
-	if (status < 0)
-		LOG_ERROR_STATUS(status);
-
 leave:
 	if (handle) {
 		if (status < 0)
 			ocfs_abort_trans(handle);
-		else
+		else {
 			ocfs_commit_trans(handle);
+			// already checked to make sure dir has nlink==2
+			if (S_ISDIR (inode->i_mode)) {
+				inode->i_nlink = 0;
+				dir->i_nlink--;
+			} else
+				inode->i_nlink--;
+		}
 	}
 
 	/* need this to alert dentry-owners on other nodes */
@@ -714,19 +731,6 @@
 
 	}
 
-	if (status >= 0) {
-		// already checked to make sure dir has nlink==2
-		if (S_ISDIR (inode->i_mode))
-			inode->i_nlink = 0;
-		else
-			inode->i_nlink--;
-		if (dec_parent)
-			dir->i_nlink--;
-#warning is INODE_DELETED needed anymore?
-		if (drop_inode) 
-			SET_INODE_DELETED(inode);
-	}
-
 	up(&OCFS_I(inode)->ip_io_sem);
 	up(&OCFS_I(dir)->ip_io_sem);
 bail:
@@ -887,7 +891,6 @@
 	struct buffer_head *oldfe_bh = NULL;
 	struct buffer_head *newfe_bh = NULL;
 	struct buffer_head *insert_bh = NULL;
-	ocfs_file_entry *tmpfe = NULL;
 	ocfs_super *osb = NULL;
 	__u64 oldOffset, newDirOff, oldDirOff;
 	__u64 newfe_lockid = 0;
@@ -895,9 +898,9 @@
 	__u32 dir_lock_flags = FLAG_FILE_CREATE | FLAG_DIR;
 	struct buffer_head *old_dir_bh = NULL;
 	struct buffer_head *new_dir_bh = NULL;
-	__u32 oldfe_flags = 0;
-	__u32 newfe_flags = 0;
-	int needs_trunc = 0, drop_inode = 0;
+	__u32 oldfe_flags = FLAG_RELEASE_DENTRY | FLAG_FILE_RENAME;
+	__u32 newfe_flags = FLAG_RELEASE_DENTRY;
+	int needs_trunc = 0;
 	int got_oldlock = 0, got_newlock = 0;
 	struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry 
 							       // and new_dentry
@@ -921,7 +924,7 @@
 
 	/* new parent dir offset */
 	newDirOff = GET_INODE_FEOFF(new_dir);
-	
+
 	double_down(&OCFS_I(old_dir)->ip_io_sem, &OCFS_I(new_dir)->ip_io_sem);
 	down(&OCFS_I(old_inode)->ip_io_sem);
 
@@ -958,18 +961,6 @@
 	}
 	spin_unlock(&oin_num_ext_lock);
 
-	/* Don't ever take the main resource for the OIN before this as */
-	/* Locking hierarchy will be broken */
-	
-	if (new_inode) {
-		down (&(OCFS_I(new_inode)->priv_sem));
-		status = ocfs_verify_update_inode (osb, new_inode, 
-						   &needs_trunc, 0);
-		up (&(OCFS_I(new_inode)->priv_sem));
-		if (needs_trunc)
-			ocfs_truncate_inode_pages(new_inode, 0);
-	}
-
 	/* start our transaction */
 	handle = ocfs_start_trans(osb, OCFS_FILE_RENAME_CREDITS);
 	if (handle == NULL) {
@@ -977,12 +968,6 @@
 		goto bail;
 	}
 
-	/* for the (possibly two) parent directory locks, we just put
-	 * them in the journal handle to be released by
-	 * commit/abort. For rename, this is only a convenience and if
-	 * it is a problem, we can move the release_locks into the
-	 * bottom of this function. */
-
 	/* if old and new are the same, this'll just do one lock. */
 	status = ocfs_double_lock(osb, handle, 
 				  oldDirOff, OCFS_DLM_EXCLUSIVE_LOCK, 
@@ -1012,11 +997,6 @@
 	if (S_ISDIR(old_inode->i_mode))
 		oldfe_flags = FLAG_DIR;
 
-	if (old_dir != new_dir)
-		oldfe_flags |= FLAG_FILE_DELETE;
-	else
-		oldfe_flags |= FLAG_FILE_RENAME;
-
 	status = ocfs_acquire_lock(osb, oldOffset, OCFS_DLM_EXCLUSIVE_LOCK,
 				   oldfe_flags, NULL, old_inode);
 	if (status < 0) {
@@ -1040,7 +1020,9 @@
 	}
 	
 	status = -ENOENT;
-	old_de_bh = ocfs_find_entry (old_dentry, &old_de);
+	old_de_bh = ocfs_find_entry (old_dentry->d_name.name,
+				     old_dentry->d_name.len,
+				     old_dir, &old_de);
 	if (!old_de_bh)
 		goto finally;
 
@@ -1055,7 +1037,8 @@
 
 	/* check if the target already exists (in which case we need
 	 * to delete it */
-	status = ocfs_find_files_on_disk(osb, new_dentry, &newfe_lockid, 
+	status = ocfs_find_files_on_disk(osb, new_dentry->d_name.name, 
+					 new_dentry->d_name.len, &newfe_lockid,
 					 new_dir, 0, &new_de_bh, &new_de);
 	/* The only error we allow here is -ENOENT because the new
 	 * file not existing is perfectly valid. */
@@ -1066,31 +1049,21 @@
 		goto finally;
 	} 
 
+	if (!new_de && new_inode)
+		LOG_ERROR_ARGS("inode %lu does not exist in it's parent "
+			       "directory!", new_inode->i_ino);
+
 	/* In case we need to overwrite an existing file, we blow it
 	 * away first */
 	if (new_de) {
+		if (!new_inode)
+			BUG();
+
 		if (newfe_lockid != GET_INODE_FEOFF(new_inode))
 			BUG();
 
-		status = ocfs_read_bh(osb, newfe_lockid, &newfe_bh, 
-				      OCFS_BH_CACHED, new_inode);
-		if (status < 0) {
-			LOG_ERROR_STATUS(status);
-			goto finally;
-		}
-
-		/* TODO: change this block to the ext3-style orphan model */
-		newfe = OCFS_BH_GET_DATA_READ(newfe_bh);
-		if (newfe->attribs & OCFS_ATTRIB_DIRECTORY)
+		if (S_ISDIR(new_inode->i_mode))
 			newfe_flags = FLAG_DIR;
-		newfe_flags |= FLAG_FILE_DELETE;
-
-		if (newfe_lockid != newfe->this_sector)
-			BUG();
-
-		OCFS_BH_PUT_DATA(newfe_bh);
-		newfe = NULL;
-
 		status = ocfs_acquire_lock(osb, newfe_lockid, 
 					   OCFS_DLM_EXCLUSIVE_LOCK, 
 					   newfe_flags, &newfe_bh, 
@@ -1100,76 +1073,64 @@
 			goto finally;
 		}
 		got_newlock = 1;
-		LOG_ERROR_ARGS("aha rename over existing... new_de=%p newlockid=%llu newfebh=%p bhblocknr=%llu\n",
+
+		/* if our caching is working right, then after the
+		 * verify_update_inode, newfe->i_nlink ==
+		 * new_inode->i_nlink */
+		down (&(OCFS_I(new_inode)->priv_sem));
+		status = ocfs_verify_update_inode (osb, new_inode, 
+						   &needs_trunc, 0);
+		up (&(OCFS_I(new_inode)->priv_sem));
+		if (needs_trunc)
+			ocfs_truncate_inode_pages(new_inode, 0);
+
+		LOG_TRACE_ARGS("aha rename over existing... new_de=%p "
+			       "newlockid=%llu newfebh=%p bhblocknr=%llu\n",
 			       new_de, newfe_lockid, newfe_bh, newfe_bh ?
 			       (unsigned long long)newfe_bh->b_blocknr : 0ULL);
 
-		status = ocfs_journal_access(handle, newfe_bh, OCFS_JOURNAL_ACCESS_WRITE);
+		status = ocfs_journal_access(handle, newfe_bh, 
+					     OCFS_JOURNAL_ACCESS_WRITE);
 		if (status < 0) {
 			LOG_ERROR_STATUS (status);
 			goto finally;
 		}
-	
-		/* need to preserve locking order, so take a 'write' lock on
-		 * the dirnode sector first. it won't get passed to
-		 * journal_dirty until ocfs_remove_file so clean up the write
-		 * lock on errors before that */
-		OCFS_BH_GET_DATA_WRITE(new_dir_bh);
-		OCFS_BH_PUT_DATA(new_dir_bh);
 
-		/* we call ocfs_clear_buffer_modified in several error cases
-		 * here if we set the modify bit on this buffer, but haven't
-		 * journal_dirtied it yet. Otherwise, it'll stay modified even
-		 * after the abort_trans. */
-		newfe = OCFS_BH_GET_DATA_WRITE(newfe_bh);
-		if (S_ISDIR (new_inode->i_mode) && !empty_dir(new_inode)) {
-			status = -ENOTEMPTY;
-			OCFS_BH_PUT_DATA(newfe_bh);
-			newfe = NULL;
-			ocfs_clear_buffer_modified(new_dir_bh);
-			goto finally;
+		if (S_ISDIR (new_inode->i_mode)) {
+			if (!empty_dir(new_inode) || new_inode->i_nlink != 2) {
+				status = -ENOTEMPTY;
+				goto finally;
+			}
 		}
 
+		newfe = OCFS_BH_GET_DATA_WRITE(newfe_bh);
 		if (S_ISDIR (new_inode->i_mode))
 			newfe->link_cnt = 0;
 		else
 			newfe->link_cnt--;
+
 		if (!newfe->link_cnt) {
-			OCFS_SET_FLAG (newfe->sync_flags, OCFS_SYNC_FLAG_MARK_FOR_DELETION);
-			newfe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
-			drop_inode = 1;
+			status = ocfs_orphan_add(osb, handle, new_inode, 
+						 newfe);
+			if (status < 0) {
+				OCFS_BH_PUT_DATA(newfe_bh);
+				LOG_ERROR_STATUS(status);
+				goto finally;
+			}
 		}
+
 		OCFS_BH_PUT_DATA(newfe_bh);
 		newfe = NULL;
 
-		if (drop_inode) {	
-			/* Free up all the bits in the bitmap. */
-			/* mark all the extents (and extent metadata) for
-		 	* this file so we can remove them after commit. */
-			/* TODO: delay this.  see orphan comment below */
-			status = ocfs_free_file_extents (osb, newfe_bh, handle, new_inode);
-			if (status < 0) {
-				ocfs_clear_buffer_modified(newfe_bh);
-				ocfs_clear_buffer_modified(new_dir_bh);
-				LOG_ERROR_STATUS (status);
-				goto finally;
-			}
-	
-			/* 
-	 		* TODO: we should link this entry into the local orphan dir after
-	 		* deleting the name from the parent.  do NOT do the free_file_extents
-	 		* in this function.  delay it until triggered by orphan_del (by 
-	 		* delete_inode, truncate or similar)
-	 		*/
-			status = ocfs_journal_dirty(handle, newfe_bh);
-			if (status < 0) {
-				LOG_ERROR_STATUS (status);
-				goto finally;
-			}
+		status = ocfs_journal_dirty(handle, newfe_bh);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto finally;
 		}
 
 		/* change the dirent to point to the correct inode */
-		status = ocfs_journal_access(handle, new_de_bh, OCFS_JOURNAL_ACCESS_WRITE);
+		status = ocfs_journal_access(handle, new_de_bh, 
+					     OCFS_JOURNAL_ACCESS_WRITE);
 		if (status < 0) {
 			LOG_ERROR_STATUS (status);
 			goto finally;
@@ -1187,8 +1148,9 @@
 
 	} else {
 		/* if the name was not found in new_dir, add it now */
-		status = ocfs_add_entry (handle, new_dentry, old_inode, oldOffset, new_dir_bh);
-	} 
+		status = ocfs_add_entry (handle, new_dentry, old_inode, 
+					 oldOffset, new_dir_bh);
+	}
 	
 
 finally:
@@ -1204,7 +1166,7 @@
 	status = ocfs_delete_entry(handle, old_dir, old_de, old_de_bh);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
-		goto finally;
+		goto bail;
 	}
 
 	if (new_inode) {
@@ -1213,7 +1175,8 @@
 	}
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
 	if (old_inode_de_bh) {
-		status = ocfs_journal_access(handle, old_inode_de_bh, OCFS_JOURNAL_ACCESS_WRITE);
+		status = ocfs_journal_access(handle, old_inode_de_bh, 
+					     OCFS_JOURNAL_ACCESS_WRITE);
 		if (status < 0) {
 			LOG_ERROR_STATUS (status);
 			// BAD
@@ -1237,11 +1200,8 @@
 		}
 	}
 	mark_inode_dirty(old_dir);
-	if (new_inode) {
+	if (new_inode)
 		mark_inode_dirty(new_inode);
-		if (!new_inode->i_nlink)
-			ocfs_orphan_add(handle, new_inode);
-	}
 
 	if (old_dir != new_dir) {
 		if (new_dir_nlink != new_dir->i_nlink)
@@ -1281,18 +1241,13 @@
 		iput(new_inode);
 	}
 
-	if (tmpfe)
-		ocfs_release_file_entry (tmpfe);
 	if (oldfe_bh) {
 		if (oldfe)
 			OCFS_BH_PUT_DATA(oldfe_bh);
 		brelse(oldfe_bh);
 	}
-	if (newfe_bh) {
-		if (newfe)
-			OCFS_BH_PUT_DATA(newfe_bh);
+	if (newfe_bh)
 		brelse(newfe_bh);
-	}
 	if (insert_bh)
 		brelse(insert_bh);
 	if (old_dir_bh)
@@ -1506,12 +1461,13 @@
 	return !memcmp(name, de->name, len);
 }
 
-
-static int ocfs_add_entry (ocfs_journal_handle *handle, struct dentry *dentry, struct inode *inode, __u64 inode_off, struct buffer_head *parent_fe_bh)
+/* we don't always have a dentry for what we want to add, so people
+ * like orphan dir can call this instead. */
+static int __ocfs_add_entry (ocfs_journal_handle *handle, struct inode *dir,
+			     const char *name, int namelen, 
+			     struct inode *inode, __u64 inode_off, 
+			     struct buffer_head *parent_fe_bh) 
 {
-	struct inode *dir = dentry->d_parent->d_inode;
-	const char *name = dentry->d_name.name;
-	int namelen = dentry->d_name.len;
 	unsigned long offset;
 	unsigned short rec_len;
 	struct buffer_head * bh;
@@ -1680,15 +1636,13 @@
  */
 static int inline search_dirblock(struct buffer_head * bh,
 				  struct inode *dir,
-				  struct dentry *dentry,
+				  const char *name, int namelen,
 				  unsigned long offset,
 				  struct ocfs2_dir_entry ** res_dir)
 {
 	struct ocfs2_dir_entry * de;
 	char * dlimit;
 	int de_len;
-	const char *name = dentry->d_name.name;
-	int namelen = dentry->d_name.len;
 	int ret = 0;
 
 	de = OCFS_BH_GET_DATA_READ(bh);
@@ -1724,8 +1678,9 @@
 
 
 
-struct buffer_head * ocfs_find_entry (struct dentry *dentry,
-					struct ocfs2_dir_entry ** res_dir)
+struct buffer_head * ocfs_find_entry (const char *name, int namelen, 
+				      struct inode *dir, 
+				      struct ocfs2_dir_entry ** res_dir)
 {
 	struct super_block * sb;
 	struct buffer_head * bh_use[NAMEI_RA_SIZE];
@@ -1737,7 +1692,6 @@
 				   buffer */
 	int num = 0;
 	int nblocks, i, err;
-	struct inode *dir = dentry->d_parent->d_inode;
 
 	*res_dir = NULL;
 	sb = dir->i_sb;
@@ -1785,7 +1739,7 @@
 			brelse(bh);
 			goto next;
 		}
-		i = search_dirblock(bh, dir, dentry,
+		i = search_dirblock(bh, dir, name, namelen,
 			    block << OCFS_SB(sb)->sect_size_bits, res_dir);
 		if (i == 1) {
 			OCFS_I(dir)->i_dir_start_lookup = block;
@@ -1819,18 +1773,176 @@
 	return ret;
 }
 
+/*
+ * ocfs_orphan_add()
+ *
+ */
+static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle, 
+			   struct inode *inode, ocfs_file_entry *fe)
+{
+	struct inode *orphan_dir_inode = NULL;
+	struct buffer_head *orphan_dir_bh = NULL;
+	int status = 0;
+	char *name = NULL;
+	int namelen;
+	ocfs_file_entry *orphan_fe;
 
+	LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
 
-int ocfs_orphan_add(ocfs_journal_handle *handle, struct inode *inode)
+	/* create a unique name here. */
+	name = ocfs_malloc(OCFS_MAX_FILENAME_LENGTH+1);
+
+	namelen = snprintf(name, OCFS_MAX_FILENAME_LENGTH+1, "%llu", 
+			   GET_INODE_FEOFF(inode));
+	if (namelen <= 0) {
+		if (namelen)
+			status = namelen;
+		else
+			status = -EFAIL;
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	LOG_TRACE_ARGS("adding filename '%s' to orphan dir (len=%d)\n", name, 
+		       namelen);
+
+	orphan_dir_inode = igrab(osb->system_inodes[ORPHAN_DIR_SYSTEM_INODE]);
+	if (!orphan_dir_inode) {
+		status = -EFAIL;
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+	ocfs_handle_add_inode(handle, orphan_dir_inode);
+
+	/* disk lock orphan dir here. */
+	status = ocfs_acquire_lock(osb, GET_INODE_FEOFF(orphan_dir_inode),
+				   OCFS_DLM_EXCLUSIVE_LOCK,
+				   FLAG_FILE_CREATE | FLAG_DIR,
+				   &orphan_dir_bh, orphan_dir_inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+	ocfs_handle_add_lock(handle, OCFS_DLM_ENABLE_CACHE_LOCK, 
+			     FLAG_FILE_CREATE | FLAG_DIR, orphan_dir_bh,
+			     orphan_dir_inode, 1);
+
+	status = __ocfs_add_entry(handle, orphan_dir_inode, name, namelen, 
+				  inode, GET_INODE_FEOFF(inode), 
+				  orphan_dir_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	status = ocfs_journal_access(handle, orphan_dir_bh, 
+				     OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	/* we're a cluster, and nlink can change on disk from
+	 * underneath us... */
+	orphan_fe = OCFS_BH_GET_DATA_WRITE(orphan_dir_bh);
+	if (S_ISDIR(inode->i_mode))
+		orphan_fe->link_cnt++;
+	orphan_dir_inode->i_nlink = orphan_fe->link_cnt;
+	OCFS_BH_PUT_DATA(orphan_dir_bh);
+
+	status = ocfs_journal_dirty(handle, orphan_dir_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+
+	OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_ORPHANED);
+
+leave:
+	if (orphan_dir_inode)
+		iput(orphan_dir_inode);
+
+	if (name)
+		ocfs_free(name);
+
+	if (orphan_dir_bh)
+		brelse(orphan_dir_bh);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+}				/* ocfs_orphan_add */
+
+/* unlike orphan_add, we expect the orphan dir to already be locked here. */
+int ocfs_orphan_del(ocfs_super *osb, ocfs_journal_handle *handle, 
+		    struct inode *orphan_dir_inode, struct inode *inode, 
+		    struct buffer_head *orphan_dir_bh)
 {
-	LOG_ERROR_ARGS("need to add %llu to orphan dir, i_nlink=%d\n",
-			GET_INODE_FEOFF(inode), inode->i_nlink);
-	return 0;
-}
+	char *name = NULL;
+	int namelen;
+	ocfs_file_entry *orphan_fe;
+	int status = 0;
+	struct buffer_head *target_de_bh;
+	struct ocfs2_dir_entry *target_de = NULL;
 
-int ocfs_orphan_del(ocfs_journal_handle *handle, struct inode *inode)
-{
-	return 0;
+	name = ocfs_malloc(OCFS_MAX_FILENAME_LENGTH+1);
+
+	namelen = snprintf(name, OCFS_MAX_FILENAME_LENGTH+1, "%llu", 
+			   GET_INODE_FEOFF(inode));
+	if (namelen <= 0) {
+		if (namelen)
+			status = namelen;
+		else
+			status = -EFAIL;
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	LOG_TRACE_ARGS("removing '%s' from orphan dir (len=%d)\n", name, 
+		       namelen);
+
+	/* find it's spot in the orphan directory */
+	target_de_bh = ocfs_find_entry(name, namelen, orphan_dir_inode, 
+				       &target_de);
+	if (!target_de_bh) {
+		status = -EFAIL;
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	/* remove it from the orphan directory */
+	status = ocfs_delete_entry(handle, orphan_dir_inode, target_de, 
+				   target_de_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	status = ocfs_journal_access(handle, orphan_dir_bh, 
+				     OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	/* do the i_nlink dance! :) */
+	orphan_fe = OCFS_BH_GET_DATA_WRITE(orphan_dir_bh);
+	if (S_ISDIR(inode->i_mode))
+		orphan_fe->link_cnt--;
+	orphan_dir_inode->i_nlink = orphan_fe->link_cnt;
+	OCFS_BH_PUT_DATA(orphan_dir_bh);
+
+	status = ocfs_journal_dirty(handle, orphan_dir_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+leave:
+	if (name)
+		ocfs_free(name);
+
+	return status;
 }
 
 #if 0

Modified: trunk/src/nm.c
===================================================================
--- trunk/src/nm.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/nm.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -58,8 +58,8 @@
 static const char *process_vote_strings[] = {
 	"INVALID_REQUEST",      // reply with a NO vote
 	"UPDATE_OIN_INODE",     // update both oin and inode
-	"DELETE_RENAME_ACQUIRE",// delete or rename request
-	"DELETE_RENAME_RELEASE",// delete or rename release request
+	"DELETE_ACQUIRE",// delete or rename request
+	"DELETE_RELEASE",// delete or rename release request
 	"RELEASE_CACHE",        // release a cache lock I hold
 	"CHANGE_MASTER",        // request to change master to requestor
 	"ADD_OIN_MAP",          // add requestor into oin map
@@ -68,6 +68,7 @@
 	"REMASTER_REQUESTOR",   // remaster lock to requestor
 	"DROP_READONLY",        // RO cachelock needs to convert to RW
 	"READONLY",
+	"RELEASE_DENTRY"
 };
 #endif
 
@@ -522,10 +523,10 @@
 			my_node_wins = (node_num < osb->node_num);
 	}
 
-//	if (flags & FLAG_DROP_LINK) {
-//		vote_type = RELEASE_DENTRY;
-//		goto done;
-//	}
+	if (flags & (FLAG_RELEASE_DENTRY | FLAG_FILE_RENAME)) {
+		vote_type = RELEASE_DENTRY;
+		goto done;
+	}
 
 	if (flags & FLAG_DROP_READONLY) {
 		vote_type = DROP_READONLY;
@@ -539,11 +540,11 @@
 		goto done;
 	}
 		
-	if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)) {
+	if (flags & FLAG_FILE_DELETE) {
 		if (flags & FLAG_RELEASE_LOCK)
-			vote_type = DELETE_RENAME_RELEASE;
+			vote_type = DELETE_RELEASE;
 		else if (flags & FLAG_ACQUIRE_LOCK)
-			vote_type = DELETE_RENAME_ACQUIRE;
+			vote_type = DELETE_ACQUIRE;
 		else
 			vote_type = INVALID_REQUEST;
 	} else if (flags & FLAG_FILE_RELEASE_CACHE)
@@ -568,7 +569,7 @@
 			vote_type = REMASTER_REQUESTOR;
 	}
 	
-	if (inode == NULL && vote_type != DELETE_RENAME_RELEASE)
+	if (inode == NULL && vote_type != DELETE_RELEASE)
 		vote_type = INVALID_REQUEST;
 done:
 	LOG_EXIT_STATUS(vote_type);
@@ -629,7 +630,6 @@
 	ocfs_vote *vote = NULL;
 	struct buffer_head *fe_bh = NULL, *vote_bh = NULL;
 	int vote_type = INVALID_REQUEST, vote_response = 0;
-	int oin_sem = 0;
 	struct inode *inode = NULL;
 	int master_alive = 1, is_dir = 0;
 	int is_locked, open_handle;
@@ -685,7 +685,7 @@
 	 * look up the inode in the release case -- it should already
 	 * be gone. Eventually what we'll really want to do is get it
 	 * via the old offsets and set the new ones. */
-	if ((flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)) && (flags & FLAG_RELEASE_LOCK))
+	if ((flags & FLAG_FILE_DELETE) && (flags & FLAG_RELEASE_LOCK))
 		inode = NULL;
 	else {
 		inode = ocfs_iget(osb, lock_id);
@@ -698,6 +698,11 @@
 			goto leave;
 		}
 
+		/* ahh, so you find yourself asking "what the
+		 * heck is this?"
+		 * Please see the note in ocfs_delete_inode. */
+		osb->voting_ino = inode->i_ino;
+
 		down(&OCFS_I(inode)->ip_io_sem);
 		have_io_sem = 1;
 
@@ -774,137 +779,117 @@
 			vote_response = FLAG_VOTE_OIN_UPDATED;
 			break;
 
-#if 0
 		case RELEASE_DENTRY:
 			if (!inode)
 				BUG();
 
 			/* we always vote yes on this one. */
 			vote_response = FLAG_VOTE_NODE;
-			printk("going to prune dentries for inode %lu\n",
-			       inode->i_ino);
 
+			/* do nothing in the release case... hmm,
+			 * perhaps we should just do a verify_update
+			 * or something in case the guy aborted... */
+			if (flags & FLAG_RELEASE_LOCK)
+				break;
+
 			d_prune_aliases (inode);
-			inode->i_nlink--;
+
+			/* for rename, we don't drop link counts */
+			if (!(flags & FLAG_FILE_RENAME)) {
+				if (S_ISDIR(inode->i_mode))
+					inode->i_nlink = 0;
+				else
+					inode->i_nlink--;
+			}
+
+			LOG_TRACE_ARGS("pruned dentries for inode %lu, nlink "
+				       "= %u\n", inode->i_ino, inode->i_nlink);
 			break;
-#endif
-		case DELETE_RENAME_RELEASE:
+
+		case DELETE_RELEASE:
 			/* ACK and done */
 			vote_response = FLAG_VOTE_NODE;
 			break;
 
-		case DELETE_RENAME_ACQUIRE:
-			LOG_TRACE_STR("DELETE_RENAME");
+		case DELETE_ACQUIRE:
+			LOG_TRACE_STR("DELETE_ACQUIRE");
 
-			/* all cases except open_hndl_cnt > 0 will vote YES */
-			vote_response = FLAG_VOTE_NODE;
+			down (&(OCFS_I(inode)->priv_sem));
+			OCFS_I(inode)->needs_verification = 1;
+			tmpstat = ocfs_verify_update_inode(osb, inode, 
+							   &needs_trunc,
+							   1);
+			if (tmpstat < 0)
+				LOG_ERROR_STATUS (tmpstat);
 
-			if (inode) {
-				oin_sem = 1;
-				down (&(OCFS_I(inode)->priv_sem));
-				OCFS_I(inode)->needs_verification = 1;
-				tmpstat = ocfs_verify_update_inode(osb, inode, 
-								  &needs_trunc,
-								   1);
-				if (tmpstat < 0)
-					LOG_ERROR_STATUS (tmpstat);
-		
-				if (needs_trunc) {
-					ocfs_truncate_inode_pages(inode, 0);
-					needs_trunc = 0;
-				}
+			if (needs_trunc) 
+				ocfs_truncate_inode_pages(inode, 0);
 
-				if (OCFS_I(inode)->open_hndl_cnt > 0) {
-					/* the NO vote for delete/rename */
-					vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
-				} else {
-					spin_lock(&oin_num_ext_lock);
-					if (OCFS_I(inode)->num_extends) {
-						vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
-					} else {
-						OCFS_SET_FLAG (OCFS_I(inode)->oin_flags, OCFS_OIN_NEEDS_DELETION);
-						up(&(OCFS_I(inode)->priv_sem));
-						ocfs_release_lockres (lockres); // ocfs_process_vote
-						lockres = NULL;
-						oin_sem = 0;
-						if (needs_trunc) {
-							ocfs_truncate_inode_pages(inode, 0);
-							needs_trunc = 0;
-						}
-					}
-					spin_unlock(&oin_num_ext_lock);
-				}
+			LOG_TRACE_ARGS("DELETE vote on inode %lu, read "
+				       "lnk_cnt = %u\n", inode->i_ino, 
+				       inode->i_nlink);
+			/* verify_update_inode does a dirty read which
+			 * might set i_nlink to an old value. */
+			if (inode->i_nlink) {
+				LOG_ERROR_ARGS("Orphaned inode %lu has link "
+					       "count = %d!\n", inode->i_ino, 
+					       inode->i_nlink);
+				inode->i_nlink = 0;
 			}
 
-			/* If the inode exists and we we're going to
-			 * vote yes on the delete, then lets mark it
-			 * deleted now. It will retain a single
-			 * reference for the rest of this function (we
-			 * can sync it and change nlink) which we iput
-			 * before exit. */
-			if (inode && vote_response == FLAG_VOTE_NODE) {
-#warning is this needed anymore?
-				SET_INODE_DELETED(inode);
+			/* vote no if the file is still open. */
+			if (OCFS_I(inode)->open_hndl_cnt > 0) {
+				vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
+				up(&(OCFS_I(inode)->priv_sem));
+				goto delete_vote_no;
 			}
+			up(&(OCFS_I(inode)->priv_sem));
 
-			if (!lockres) {
-				/* is there an inode to dump? */
-				if (inode) {
-					inode->i_nlink = 0;
-					d_prune_aliases (inode);
+			/* vote no if someone's extending it. */
+			spin_lock(&oin_num_ext_lock);
+			if (OCFS_I(inode)->num_extends) {
+				spin_unlock(&oin_num_ext_lock);
+				vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
+				goto delete_vote_no;
+			}
+			spin_unlock(&oin_num_ext_lock);
+
+			vote_response = FLAG_VOTE_NODE;
+
+			SET_INODE_DELETED(inode);
+			/* if we vote yes, then we set the SKIP_DELETE
+			 * flag on the inode so we don't try to delete
+			 * it in delete_inode ourselves. */
+			OCFS_SET_FLAG(OCFS_I(inode)->flags, 
+				      OCFS_INODE_SKIP_DELETE);
+
+			inode->i_nlink = 0;
+			d_prune_aliases (inode);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-					sync_mapping_buffers(inode->i_mapping);
+			sync_mapping_buffers(inode->i_mapping);
 #else
-					fsync_inode_buffers (inode);
+			fsync_inode_buffers (inode);
 #endif
-					up(&OCFS_I(inode)->ip_io_sem);
-					have_io_sem = 0;
-				}
-				break;
-			}
+			/* Alright, for the YES case, we're done here. */
+			break;
 
-			if (inode) {
-				up(&OCFS_I(inode)->ip_io_sem);
-				have_io_sem = 0;
-			}
-
-			/* Set the always update master on open flag */
-			lockres->lock_state |= FLAG_ALWAYS_UPDATE_OPEN;
+delete_vote_no:
 			lockres->last_upd_seq_num = seq_num;
-			if (lockres->master_node_num == OCFS_INVALID_NODE_NUM || !master_alive)
+			/* (6/11/2004): the next two conditional are
+			 * likely useless relics.  If we don't hit
+			 * those error messages then we can delete
+			 * them.*/
+			if (lockres->master_node_num == OCFS_INVALID_NODE_NUM 
+			    || !master_alive) {
 				lockres->master_node_num = node_num;
-			
-			/* Change the master if there is no lock */
+				LOG_ERROR_STR("Wowzers, how'd I hit this code:"
+					      " master node is invalid!?!");
+			}
 			if (lockres->master_node_num == osb->node_num &&
 			    lockres->lock_type < OCFS_DLM_EXCLUSIVE_LOCK) {
-				/* Change the lock ownership to the node asking for vote */
-				/* and write new master on the disk */
-	
-				status = ocfs_read_bh(osb, lock_id, &fe_bh, lockflags, inode);
-				if (status < 0)
-					LOG_ERROR_STATUS (status);
-				if (status >= 0) {
-					fe = OCFS_BH_GET_DATA_WRITE(fe_bh);
-					DISK_LOCK_CURRENT_MASTER (fe) = node_num;
-					OCFS_BH_PUT_DATA(fe_bh);
-					status = ocfs_write_bh(osb, fe_bh, 0, inode);
-					if (status < 0)
-						LOG_ERROR_STATUS (status);
-					else
-						lockres->master_node_num = node_num;
-					brelse(fe_bh);
-				}
+				LOG_ERROR_STR("Wowzers, how'd I hit this "
+					      "code!?!");
 			}
-			if (oin_sem) {
-				up(&(OCFS_I(inode)->priv_sem));
-				oin_sem = 0;
-			}
-
-			if (needs_trunc) {
-				ocfs_truncate_inode_pages(inode, 0);
-				needs_trunc = 0;
-			}
-
 			break;
 
 		case READONLY:
@@ -1057,8 +1042,7 @@
 			}
 			fe = OCFS_BH_GET_DATA_READ(fe_bh);
 
-			if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
-			    (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
+			if (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID)) {
 				vote_response = FLAG_VOTE_FILE_DEL;
 				OCFS_BH_PUT_DATA(fe_bh);
 			} else {
@@ -1249,9 +1233,12 @@
 			ocfs_inc_inode_seq(osb, inode, 1);
 		if (have_io_sem)
 			up(&OCFS_I(inode)->ip_io_sem);
-		iput(inode);
 	}
 
+	if (inode)
+		iput(inode);
+	osb->voting_ino = 0;
+
 	up(&osb->vote_sem);
 
 	LOG_EXIT_STATUS (status);

Modified: trunk/src/super.c
===================================================================
--- trunk/src/super.c	2004-06-11 10:22:45 UTC (rev 1052)
+++ trunk/src/super.c	2004-06-11 21:07:06 UTC (rev 1053)
@@ -162,7 +162,7 @@
 	.put_inode = ocfs_put_inode,
 	.clear_inode = ocfs_clear_inode,
 	//put_inode =           force_delete,
-	//delete_inode =        ocfs_delete_inode, 
+	.delete_inode =        ocfs_delete_inode, 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 	.read_inode = ocfs_read_inode,
 	.read_inode2 = ocfs_read_inode2,
@@ -249,6 +249,17 @@
 	}
 	osb->system_inodes[JOURNAL_SYSTEM_INODE] = new;
 
+	/* orphan inode dir */
+	sys_off = osb->vol_layout.root_int_off + 
+		(OCFS_ORPHAN_DIR * osb->sect_size);
+	new = ocfs_iget(osb, sys_off);
+	if (!new) {
+		status = -EINVAL;
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+	osb->system_inodes[ORPHAN_DIR_SYSTEM_INODE] = new;
+
 bail:
 	LOG_EXIT_STATUS(status);
 	return(status);



More information about the Ocfs2-commits mailing list