ocfs2: Hook rest of the file system into dentry locking API
authorMark Fasheh <mark.fasheh@oracle.com>
Fri, 8 Sep 2006 21:21:03 +0000 (14:21 -0700)
committerMark Fasheh <mark.fasheh@oracle.com>
Sun, 24 Sep 2006 20:50:43 +0000 (13:50 -0700)
Actually replace the vote calls with the new dentry operations. Make any
necessary adjustments to get the scheme to work.

Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
fs/ocfs2/cluster/tcp_internal.h
fs/ocfs2/export.c
fs/ocfs2/inode.c
fs/ocfs2/namei.c

index ff9e2e2104c245b09e4e32ef2533cbc4a4a0e6b9..da42b515cd1d4609a23dd11d6818bce5d6e1d8e4 100644 (file)
  * locking semantics of the file system using the protocol.  It should 
  * be somewhere else, I'm sure, but right now it isn't.
  *
+ * New in version 3:
+ *     - Replace dentry votes with a cluster lock
+ *
  * New in version 2:
  *     - full 64 bit i_size in the metadata lock lvbs
  *     - introduction of "rw" lock and pushing meta/data locking down
  */
-#define O2NET_PROTOCOL_VERSION 2ULL
+#define O2NET_PROTOCOL_VERSION 3ULL
 struct o2net_handshake {
        __be64  protocol_version;
        __be64  connector_id;
index ec55ab3c1214cf3a64a1d2dce17995ae6db7008c..ffcd79749e0d21d5faf05b8d122e93280076add5 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "dir.h"
 #include "dlmglue.h"
+#include "dcache.h"
 #include "export.h"
 #include "inode.h"
 
@@ -77,6 +78,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp)
                mlog_errno(-ENOMEM);
                return ERR_PTR(-ENOMEM);
        }
+       result->d_op = &ocfs2_dentry_ops;
 
        mlog_exit_ptr(result);
        return result;
@@ -127,6 +129,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
                parent = ERR_PTR(-ENOMEM);
        }
 
+       parent->d_op = &ocfs2_dentry_ops;
+
 bail_unlock:
        ocfs2_meta_unlock(dir, 0);
 
index 7bcf69154592ec6a1083c3a840865097f1d1593a..66ca7a82b68a3ab09abf61f5d5f460fbe637a174 100644 (file)
@@ -1025,12 +1025,10 @@ void ocfs2_drop_inode(struct inode *inode)
        /* Testing ip_orphaned_slot here wouldn't work because we may
         * not have gotten a delete_inode vote from any other nodes
         * yet. */
-       if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) {
-               mlog(0, "Inode was orphaned on another node, clearing nlink.\n");
-               inode->i_nlink = 0;
-       }
-
-       generic_drop_inode(inode);
+       if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
+               generic_delete_inode(inode);
+       else
+               generic_drop_inode(inode);
 
        mlog_exit_void();
 }
index 0d3e939b1f561a655eea61c2090ecf7eb88fbc38..5a942e0123ea6b970181cca547e61bbbca8ee010 100644 (file)
@@ -199,10 +199,32 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
        spin_unlock(&oi->ip_lock);
 
 bail_add:
-
        dentry->d_op = &ocfs2_dentry_ops;
        ret = d_splice_alias(inode, dentry);
 
+       if (inode) {
+               /*
+                * If d_splice_alias() finds a DCACHE_DISCONNECTED
+                * dentry, it will d_move() it on top of ourse. The
+                * return value will indicate this however, so in
+                * those cases, we switch them around for the locking
+                * code.
+                *
+                * NOTE: This dentry already has ->d_op set from
+                * ocfs2_get_parent() and ocfs2_get_dentry()
+                */
+               if (ret)
+                       dentry = ret;
+
+               status = ocfs2_dentry_attach_lock(dentry, inode,
+                                                 OCFS2_I(dir)->ip_blkno, 0);
+               if (status) {
+                       mlog_errno(status);
+                       ret = ERR_PTR(status);
+                       goto bail_unlock;
+               }
+       }
+
 bail_unlock:
        /* Don't drop the cluster lock until *after* the d_add --
         * unlink on another node will message us to remove that
@@ -418,6 +440,13 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
+       status = ocfs2_dentry_attach_lock(dentry, inode,
+                                         OCFS2_I(dir)->ip_blkno, 1);
+       if (status) {
+               mlog_errno(status);
+               goto leave;
+       }
+
        insert_inode_hash(inode);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
@@ -725,6 +754,13 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto bail;
        }
 
+       err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno,
+                                      0);
+       if (err) {
+               mlog_errno(err);
+               goto bail;
+       }
+
        atomic_inc(&inode->i_count);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
@@ -743,6 +779,23 @@ bail:
        return err;
 }
 
+/*
+ * Takes and drops an exclusive lock on the given dentry. This will
+ * force other nodes to drop it.
+ */
+static int ocfs2_remote_dentry_delete(struct dentry *dentry)
+{
+       int ret;
+
+       ret = ocfs2_dentry_lock(dentry, 1);
+       if (ret)
+               mlog_errno(ret);
+       else
+               ocfs2_dentry_unlock(dentry, 1);
+
+       return ret;
+}
+
 static int ocfs2_unlink(struct inode *dir,
                        struct dentry *dentry)
 {
@@ -832,8 +885,7 @@ static int ocfs2_unlink(struct inode *dir,
        else
                inode->i_nlink--;
 
-       status = ocfs2_request_unlink_vote(inode, dentry,
-                                          (unsigned int) inode->i_nlink);
+       status = ocfs2_remote_dentry_delete(dentry);
        if (status < 0) {
                /* This vote should succeed under all normal
                 * circumstances. */
@@ -1019,7 +1071,6 @@ static int ocfs2_rename(struct inode *old_dir,
        struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
                                                    // this is the 1st dirent bh
        nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
-       unsigned int links_count;
 
        /* At some point it might be nice to break this function up a
         * bit. */
@@ -1093,23 +1144,26 @@ static int ocfs2_rename(struct inode *old_dir,
                }
        }
 
-       if (S_ISDIR(old_inode->i_mode)) {
-               /* Directories actually require metadata updates to
-                * the directory info so we can't get away with not
-                * doing node locking on it. */
-               status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
-               if (status < 0) {
-                       if (status != -ENOENT)
-                               mlog_errno(status);
-                       goto bail;
-               }
-
-               status = ocfs2_request_rename_vote(old_inode, old_dentry);
-               if (status < 0) {
+       /*
+        * Though we don't require an inode meta data update if
+        * old_inode is not a directory, we lock anyway here to ensure
+        * the vote thread on other nodes won't have to concurrently
+        * downconvert the inode and the dentry locks.
+        */
+       status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
+       if (status < 0) {
+               if (status != -ENOENT)
                        mlog_errno(status);
-                       goto bail;
-               }
+               goto bail;
+       }
+
+       status = ocfs2_remote_dentry_delete(old_dentry);
+       if (status < 0) {
+               mlog_errno(status);
+               goto bail;
+       }
 
+       if (S_ISDIR(old_inode->i_mode)) {
                status = -EIO;
                old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0);
                if (!old_inode_de_bh)
@@ -1123,14 +1177,6 @@ static int ocfs2_rename(struct inode *old_dir,
                if (!new_inode && new_dir!=old_dir &&
                    new_dir->i_nlink >= OCFS2_LINK_MAX)
                        goto bail;
-       } else {
-               /* Ah, the simple case - we're a file so just send a
-                * message. */
-               status = ocfs2_request_rename_vote(old_inode, old_dentry);
-               if (status < 0) {
-                       mlog_errno(status);
-                       goto bail;
-               }
        }
 
        status = -ENOENT;
@@ -1202,13 +1248,7 @@ static int ocfs2_rename(struct inode *old_dir,
                        goto bail;
                }
 
-               if (S_ISDIR(new_inode->i_mode))
-                       links_count = 0;
-               else
-                       links_count = (unsigned int) (new_inode->i_nlink - 1);
-
-               status = ocfs2_request_unlink_vote(new_inode, new_dentry,
-                                                  links_count);
+               status = ocfs2_remote_dentry_delete(new_dentry);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1387,6 +1427,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
        }
 
+       ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
        status = 0;
 bail:
        if (rename_lock)
@@ -1675,6 +1716,13 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
+       status = ocfs2_dentry_attach_lock(dentry, inode,
+                                         OCFS2_I(dir)->ip_blkno, 1);
+       if (status) {
+               mlog_errno(status);
+               goto bail;
+       }
+
        insert_inode_hash(inode);
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);