[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