diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2006-09-08 23:21:03 +0200 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2006-09-24 22:50:43 +0200 |
commit | 379dfe9d0db99ed33fb089fcb9c07f5f92566e9e (patch) | |
tree | 8f04d8dbf97fa70d8f02fcbb037e7b318cd7143e /fs/ocfs2/namei.c | |
parent | ocfs2: Add dentry tracking API (diff) | |
download | linux-379dfe9d0db99ed33fb089fcb9c07f5f92566e9e.tar.xz linux-379dfe9d0db99ed33fb089fcb9c07f5f92566e9e.zip |
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: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 116 |
1 files changed, 82 insertions, 34 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 0d3e939b1f56..5a942e0123ea 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -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); |