[Ocfs2-commits] mfasheh commits r2376 - trunk/fs/ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Jun 7 19:25:17 CDT 2005


Author: mfasheh
Signed-off-by: jlbec
Date: 2005-06-07 19:25:15 -0500 (Tue, 07 Jun 2005)
New Revision: 2376

Modified:
   trunk/fs/ocfs2/dcache.c
   trunk/fs/ocfs2/dir.c
   trunk/fs/ocfs2/dir.h
   trunk/fs/ocfs2/dlmglue.c
   trunk/fs/ocfs2/namei.c
   trunk/fs/ocfs2/vote.c
Log:
* fail dentry_revalidate on *all* inodes without a link count, not just
  directories.

* allow a vote on a stale inode by proceeding as though it did not exist.   

* have ocfs2_mknod, ocfs2_symlink and ocfs2_link check their directories for 
  duplicate entries.

* in ocfs2_unlink and ocfs2_rename, fail gracefully when we don't find the inod
  removed in it's directory.

* have ocfs2_meta_lock return -ENOENT when it detects a stale inode.

* properly clean up cluster locks on error in ocfs2_meta_lock

Signed-off-by: jlbec



Modified: trunk/fs/ocfs2/dcache.c
===================================================================
--- trunk/fs/ocfs2/dcache.c	2005-06-07 23:57:14 UTC (rev 2375)
+++ trunk/fs/ocfs2/dcache.c	2005-06-08 00:25:15 UTC (rev 2376)
@@ -53,28 +53,25 @@
 
 	osb = OCFS2_SB(inode->i_sb);
 
-	OCFS2_ASSERT(osb);
+	BUG_ON(!osb);
 
-	if (inode == osb->root_inode) {
-		ret = 1;
-		goto bail;
-	}
-
-	spin_lock(&OCFS2_I(inode)->ip_lock);
-	/* did we or someone else delete this inode? */
-	if (INODE_DELETED(inode)) {
+	if (inode != osb->root_inode) {
+		spin_lock(&OCFS2_I(inode)->ip_lock);
+		/* did we or someone else delete this inode? */
+		if (INODE_DELETED(inode)) {
+			spin_unlock(&OCFS2_I(inode)->ip_lock);
+			mlog(0, "inode (%"MLFu64") deleted, returning false\n",
+			     OCFS2_I(inode)->ip_blkno);
+			goto bail;
+		}
 		spin_unlock(&OCFS2_I(inode)->ip_lock);
-		mlog(0, "inode (%"MLFu64") deleted, returning false\n",
-		     OCFS2_I(inode)->ip_blkno);
-		goto bail;
-	}
-	spin_unlock(&OCFS2_I(inode)->ip_lock);
 
-	/* XXX: Should we do this for all files? */
-	if (S_ISDIR(inode->i_mode) && (!inode->i_nlink)) {
-		mlog(0, "dir inode (%"MLFu64") orphaned, returning false\n",
-		     OCFS2_I(inode)->ip_blkno);
-		goto bail;
+		if (!inode->i_nlink) {
+			mlog(0, "Inode %"MLFu64" orphaned, returning false "
+			     "dir = %d\n", OCFS2_I(inode)->ip_blkno,
+			     S_ISDIR(inode->i_mode));
+			goto bail;
+		}
 	}
 
 	ret = 1;

Modified: trunk/fs/ocfs2/dir.c
===================================================================
--- trunk/fs/ocfs2/dir.c	2005-06-07 23:57:14 UTC (rev 2375)
+++ trunk/fs/ocfs2/dir.c	2005-06-08 00:25:15 UTC (rev 2376)
@@ -252,6 +252,38 @@
 	return status;
 }
 
+/* Check for a name within a directory.
+ *
+ * Return 0 if the name does not exist
+ * Return -EEXIST if the directory contains the name
+ *
+ * Callers should have i_sem + a cluster lock on dir
+ */
+int ocfs2_check_dir_for_entry(struct inode *dir,
+			      const char *name,
+			      int namelen)
+{
+	int ret;
+	struct buffer_head *dirent_bh = NULL;
+	struct ocfs2_dir_entry *dirent = NULL;
+
+	mlog_entry("dir %"MLFu64", name '%.*s'\n", OCFS2_I(dir)->ip_blkno,
+		   namelen, name);
+
+	ret = -EEXIST;
+	dirent_bh = ocfs2_find_entry(name, namelen, dir, &dirent);
+	if (dirent_bh)
+		goto bail;
+
+	ret = 0;
+bail:
+	if (dirent_bh)
+		brelse(dirent_bh);
+
+	mlog_exit(ret);
+	return ret;
+}
+
 /*
  * routine to check that the specified directory is empty (for rmdir)
  */

Modified: trunk/fs/ocfs2/dir.h
===================================================================
--- trunk/fs/ocfs2/dir.h	2005-06-07 23:57:14 UTC (rev 2375)
+++ trunk/fs/ocfs2/dir.h	2005-06-08 00:25:15 UTC (rev 2376)
@@ -26,6 +26,9 @@
 #ifndef OCFS2_DIR_H
 #define OCFS2_DIR_H
 
+int ocfs2_check_dir_for_entry(struct inode *dir,
+			      const char *name,
+			      int namelen);
 int ocfs2_empty_dir(struct inode *inode);  /* FIXME: to namei.c */
 int ocfs2_find_files_on_disk(ocfs2_super *osb, const char *name,
 			     int namelen, u64 *blkno,

Modified: trunk/fs/ocfs2/dlmglue.c
===================================================================
--- trunk/fs/ocfs2/dlmglue.c	2005-06-07 23:57:14 UTC (rev 2375)
+++ trunk/fs/ocfs2/dlmglue.c	2005-06-08 00:25:15 UTC (rev 2376)
@@ -1470,12 +1470,14 @@
 	mlog_entry_void();
 
 	spin_lock(&OCFS2_I(inode)->ip_lock);
-	if (INODE_DELETED(inode))
-		mlog(ML_ERROR,
-		     "Orphaned inode %"MLFu64"was deleted while we "
+	if (INODE_DELETED(inode)) {
+		mlog(0, "Orphaned inode %"MLFu64" was deleted while we "
 		     "were waiting on a lock. ip_flags = 0x%x\n",
-		     OCFS2_I(inode)->ip_blkno,
-		     OCFS2_I(inode)->ip_flags);
+		     OCFS2_I(inode)->ip_blkno, OCFS2_I(inode)->ip_flags);
+		spin_unlock(&OCFS2_I(inode)->ip_lock);
+		status = -ENOENT;
+		goto bail;
+	}
 	spin_unlock(&OCFS2_I(inode)->ip_lock);
 
 	lockres = &OCFS2_I(inode)->ip_meta_lockres;
@@ -1501,7 +1503,13 @@
 		fe = (ocfs2_dinode *) (*bh)->b_data;
 
 		/* This is a good chance to make sure we're not
-		 * locking an invalid object. */
+		 * locking an invalid object.
+		 *
+		 * We bug on a stale inode here because we checked
+		 * above whether it was wiped from disk. The wiping
+		 * node provides a guarantee that we receive that
+		 * message and can mark the inode before dropping any
+		 * locks associated with it. */
 		OCFS2_BUG_ON_INVALID_DINODE(fe);
 		mlog_bug_on_msg(inode->i_generation !=
 				le32_to_cpu(fe->i_generation),
@@ -1574,7 +1582,7 @@
 			 ocfs2_lock_callback cb,
 			 unsigned long cb_data)
 {
-	int status, level, dlm_flags;
+	int status, level, dlm_flags, acquired;
 	struct ocfs2_lock_res *lockres;
 	ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct buffer_head *local_bh = NULL;
@@ -1588,6 +1596,7 @@
 	     ex ? "EXMODE" : "PRMODE");
 
 	status = 0;
+	acquired = 0;
 
 	if (!(flags & OCFS2_META_LOCK_RECOVERY))
 		status = wait_event_interruptible(osb->recovery_event,
@@ -1612,6 +1621,9 @@
 		goto bail;
 	}
 
+	/* Notify the error cleanup path to drop the cluster lock. */
+	acquired = 1;
+
 	/* We wait twice because a node may have died while we were in
 	 * the lower dlm layers. The second time though, we've
 	 * committed to owning this lock so we don't allow signals to
@@ -1647,9 +1659,13 @@
 	}
 
 bail:
-	if (status < 0 && ret_bh && (*ret_bh)) {
-		brelse(*ret_bh);
-		*ret_bh = NULL;
+	if (status < 0) {
+		if (ret_bh && (*ret_bh)) {
+			brelse(*ret_bh);
+			*ret_bh = NULL;
+		}
+		if (acquired)
+			ocfs2_meta_unlock(inode, ex);
 	}
 
 	if (local_bh)

Modified: trunk/fs/ocfs2/namei.c
===================================================================
--- trunk/fs/ocfs2/namei.c	2005-06-07 23:57:14 UTC (rev 2375)
+++ trunk/fs/ocfs2/namei.c	2005-06-08 00:25:15 UTC (rev 2376)
@@ -362,6 +362,11 @@
 		goto leave;
 	}
 
+	status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
+					   dentry->d_name.len);
+	if (status)
+		goto leave;
+
 	/* get a spot inside the dir. */
 	status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 
 					      dentry->d_name.name, 
@@ -666,6 +671,11 @@
 		goto bail;
 	}
 
+	err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
+					dentry->d_name.len);
+	if (err)
+		goto bail;
+
 	err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 
 					   dentry->d_name.name, 
 					   dentry->d_name.len, &de_bh);
@@ -793,10 +803,15 @@
 		goto leave;
 	}
 
-	mlog_bug_on_msg(OCFS2_I(inode)->ip_blkno != blkno,
-			"ip_blkno (%"MLFu64") != dirent blkno (%"MLFu64")\n",
-			OCFS2_I(inode)->ip_blkno, blkno);
+	if (OCFS2_I(inode)->ip_blkno != blkno) {
+		status = -ENOENT;
 
+		mlog(0, "ip_blkno (%"MLFu64") != dirent blkno (%"MLFu64") "
+		     "ip_flags = %x\n", OCFS2_I(inode)->ip_blkno, blkno,
+		     OCFS2_I(inode)->ip_flags);
+		goto leave;
+	}
+
 	status = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
 	if (status < 0) {
 		mlog_errno(status);
@@ -1139,11 +1154,16 @@
 	if (new_de) {
 		BUG_ON(!new_inode);
 
-		mlog_bug_on_msg(OCFS2_I(new_inode)->ip_blkno != newfe_blkno,
-				"Inode blkno (%"MLFu64") and dir (%"MLFu64") "
-				"disagree!\n", OCFS2_I(new_inode)->ip_blkno,
-				newfe_blkno);
+		if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) {
+			status = -ENOENT;
 
+			mlog(0, "Inode blkno (%"MLFu64") and dir (%"MLFu64") "
+			     "disagree. ip_flags = %x\n",
+			     OCFS2_I(new_inode)->ip_blkno, newfe_blkno,
+			     OCFS2_I(new_inode)->ip_flags);
+			goto bail;
+		}
+
 		status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1);
 		if (status < 0) {
 			mlog_errno(status);
@@ -1180,6 +1200,13 @@
 		}
 	} else {
 		OCFS2_ASSERT(new_dentry->d_parent->d_inode == new_dir);
+
+		status = ocfs2_check_dir_for_entry(new_dir,
+						   new_dentry->d_name.name,
+						   new_dentry->d_name.len);
+		if (status)
+			goto bail;
+
 		status = ocfs2_prepare_dir_for_insert(osb, new_dir, new_dir_bh,
 						      new_dentry->d_name.name, 
 						      new_dentry->d_name.len,
@@ -1521,6 +1548,11 @@
 		goto bail;
 	}
 
+	status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
+					   dentry->d_name.len);
+	if (status)
+		goto bail;
+
 	status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 
 					      dentry->d_name.name, 
 					      dentry->d_name.len, &de_bh);

Modified: trunk/fs/ocfs2/vote.c
===================================================================
--- trunk/fs/ocfs2/vote.c	2005-06-07 23:57:14 UTC (rev 2375)
+++ trunk/fs/ocfs2/vote.c	2005-06-08 00:25:15 UTC (rev 2376)
@@ -317,7 +317,20 @@
 	if (!inode)
 		goto respond;
 
-	OCFS2_ASSERT(inode->i_generation == generation);
+	/* Check generation values. It's possible for us to get a
+	 * request against a stale inode. If so then we proceed as if
+	 * we had not found an inode in the first place. */
+	if (inode->i_generation != generation) {
+		mlog(0, "generation passed %u != inode generation = %u, "
+		     "ip_flags = %x, ip_blkno = %"MLFu64", msg %"MLFu64", "
+		     "i_count = %u, message type = %u\n",
+		     generation, inode->i_generation, OCFS2_I(inode)->ip_flags,
+		     OCFS2_I(inode)->ip_blkno, blkno,
+		     atomic_read(&inode->i_count), request);
+		iput(inode);
+		inode = NULL;
+		goto respond;
+	}
 
 	switch (request) {
 	case OCFS2_VOTE_REQ_DELETE:



More information about the Ocfs2-commits mailing list