Commit 379dfe9d authored by Mark Fasheh's avatar Mark Fasheh

ocfs2: Hook rest of the file system into dentry locking API

Actually replace the vote calls with the new dentry operations. Make any
necessary adjustments to get the scheme to work.
Signed-off-by: default avatarMark Fasheh <mark.fasheh@oracle.com>
parent 80c05846
...@@ -44,11 +44,14 @@ ...@@ -44,11 +44,14 @@
* locking semantics of the file system using the protocol. It should * locking semantics of the file system using the protocol. It should
* be somewhere else, I'm sure, but right now it isn't. * 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: * New in version 2:
* - full 64 bit i_size in the metadata lock lvbs * - full 64 bit i_size in the metadata lock lvbs
* - introduction of "rw" lock and pushing meta/data locking down * - introduction of "rw" lock and pushing meta/data locking down
*/ */
#define O2NET_PROTOCOL_VERSION 2ULL #define O2NET_PROTOCOL_VERSION 3ULL
struct o2net_handshake { struct o2net_handshake {
__be64 protocol_version; __be64 protocol_version;
__be64 connector_id; __be64 connector_id;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "dir.h" #include "dir.h"
#include "dlmglue.h" #include "dlmglue.h"
#include "dcache.h"
#include "export.h" #include "export.h"
#include "inode.h" #include "inode.h"
...@@ -77,6 +78,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp) ...@@ -77,6 +78,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp)
mlog_errno(-ENOMEM); mlog_errno(-ENOMEM);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
result->d_op = &ocfs2_dentry_ops;
mlog_exit_ptr(result); mlog_exit_ptr(result);
return result; return result;
...@@ -127,6 +129,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) ...@@ -127,6 +129,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
parent = ERR_PTR(-ENOMEM); parent = ERR_PTR(-ENOMEM);
} }
parent->d_op = &ocfs2_dentry_ops;
bail_unlock: bail_unlock:
ocfs2_meta_unlock(dir, 0); ocfs2_meta_unlock(dir, 0);
......
...@@ -1025,12 +1025,10 @@ void ocfs2_drop_inode(struct inode *inode) ...@@ -1025,12 +1025,10 @@ void ocfs2_drop_inode(struct inode *inode)
/* Testing ip_orphaned_slot here wouldn't work because we may /* Testing ip_orphaned_slot here wouldn't work because we may
* not have gotten a delete_inode vote from any other nodes * not have gotten a delete_inode vote from any other nodes
* yet. */ * yet. */
if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) { if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
mlog(0, "Inode was orphaned on another node, clearing nlink.\n"); generic_delete_inode(inode);
inode->i_nlink = 0; else
} generic_drop_inode(inode);
generic_drop_inode(inode);
mlog_exit_void(); mlog_exit_void();
} }
......
...@@ -199,10 +199,32 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, ...@@ -199,10 +199,32 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
spin_unlock(&oi->ip_lock); spin_unlock(&oi->ip_lock);
bail_add: bail_add:
dentry->d_op = &ocfs2_dentry_ops; dentry->d_op = &ocfs2_dentry_ops;
ret = d_splice_alias(inode, dentry); 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: bail_unlock:
/* Don't drop the cluster lock until *after* the d_add -- /* Don't drop the cluster lock until *after* the d_add --
* unlink on another node will message us to remove that * unlink on another node will message us to remove that
...@@ -418,6 +440,13 @@ static int ocfs2_mknod(struct inode *dir, ...@@ -418,6 +440,13 @@ static int ocfs2_mknod(struct inode *dir,
goto leave; 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); insert_inode_hash(inode);
dentry->d_op = &ocfs2_dentry_ops; dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
...@@ -725,6 +754,13 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -725,6 +754,13 @@ static int ocfs2_link(struct dentry *old_dentry,
goto bail; 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); atomic_inc(&inode->i_count);
dentry->d_op = &ocfs2_dentry_ops; dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
...@@ -743,6 +779,23 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -743,6 +779,23 @@ static int ocfs2_link(struct dentry *old_dentry,
return err; 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, static int ocfs2_unlink(struct inode *dir,
struct dentry *dentry) struct dentry *dentry)
{ {
...@@ -832,8 +885,7 @@ static int ocfs2_unlink(struct inode *dir, ...@@ -832,8 +885,7 @@ static int ocfs2_unlink(struct inode *dir,
else else
inode->i_nlink--; inode->i_nlink--;
status = ocfs2_request_unlink_vote(inode, dentry, status = ocfs2_remote_dentry_delete(dentry);
(unsigned int) inode->i_nlink);
if (status < 0) { if (status < 0) {
/* This vote should succeed under all normal /* This vote should succeed under all normal
* circumstances. */ * circumstances. */
...@@ -1019,7 +1071,6 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -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, struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
// this is the 1st dirent bh // this is the 1st dirent bh
nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink; 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 /* At some point it might be nice to break this function up a
* bit. */ * bit. */
...@@ -1093,23 +1144,26 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -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 * Though we don't require an inode meta data update if
* the directory info so we can't get away with not * old_inode is not a directory, we lock anyway here to ensure
* doing node locking on it. */ * the vote thread on other nodes won't have to concurrently
status = ocfs2_meta_lock(old_inode, handle, NULL, 1); * downconvert the inode and the dentry locks.
if (status < 0) { */
if (status != -ENOENT) status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
mlog_errno(status); if (status < 0) {
goto bail; if (status != -ENOENT)
}
status = ocfs2_request_rename_vote(old_inode, old_dentry);
if (status < 0) {
mlog_errno(status); 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; status = -EIO;
old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0); old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0);
if (!old_inode_de_bh) if (!old_inode_de_bh)
...@@ -1123,14 +1177,6 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1123,14 +1177,6 @@ static int ocfs2_rename(struct inode *old_dir,
if (!new_inode && new_dir!=old_dir && if (!new_inode && new_dir!=old_dir &&
new_dir->i_nlink >= OCFS2_LINK_MAX) new_dir->i_nlink >= OCFS2_LINK_MAX)
goto bail; 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; status = -ENOENT;
...@@ -1202,13 +1248,7 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1202,13 +1248,7 @@ static int ocfs2_rename(struct inode *old_dir,
goto bail; goto bail;
} }
if (S_ISDIR(new_inode->i_mode)) status = ocfs2_remote_dentry_delete(new_dentry);
links_count = 0;
else
links_count = (unsigned int) (new_inode->i_nlink - 1);
status = ocfs2_request_unlink_vote(new_inode, new_dentry,
links_count);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
...@@ -1387,6 +1427,7 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -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; status = 0;
bail: bail:
if (rename_lock) if (rename_lock)
...@@ -1675,6 +1716,13 @@ static int ocfs2_symlink(struct inode *dir, ...@@ -1675,6 +1716,13 @@ static int ocfs2_symlink(struct inode *dir,
goto bail; 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); insert_inode_hash(inode);
dentry->d_op = &ocfs2_dentry_ops; dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment