diff options
-rw-r--r-- | fs/ocfs2/cluster/tcp_internal.h | 5 | ||||
-rw-r--r-- | fs/ocfs2/export.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 10 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 116 |
4 files changed, 94 insertions, 41 deletions
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index ff9e2e2104c2..da42b515cd1d 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h | |||
@@ -44,11 +44,14 @@ | |||
44 | * locking semantics of the file system using the protocol. It should | 44 | * locking semantics of the file system using the protocol. It should |
45 | * be somewhere else, I'm sure, but right now it isn't. | 45 | * be somewhere else, I'm sure, but right now it isn't. |
46 | * | 46 | * |
47 | * New in version 3: | ||
48 | * - Replace dentry votes with a cluster lock | ||
49 | * | ||
47 | * New in version 2: | 50 | * New in version 2: |
48 | * - full 64 bit i_size in the metadata lock lvbs | 51 | * - full 64 bit i_size in the metadata lock lvbs |
49 | * - introduction of "rw" lock and pushing meta/data locking down | 52 | * - introduction of "rw" lock and pushing meta/data locking down |
50 | */ | 53 | */ |
51 | #define O2NET_PROTOCOL_VERSION 2ULL | 54 | #define O2NET_PROTOCOL_VERSION 3ULL |
52 | struct o2net_handshake { | 55 | struct o2net_handshake { |
53 | __be64 protocol_version; | 56 | __be64 protocol_version; |
54 | __be64 connector_id; | 57 | __be64 connector_id; |
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index ec55ab3c1214..ffcd79749e0d 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include "dir.h" | 34 | #include "dir.h" |
35 | #include "dlmglue.h" | 35 | #include "dlmglue.h" |
36 | #include "dcache.h" | ||
36 | #include "export.h" | 37 | #include "export.h" |
37 | #include "inode.h" | 38 | #include "inode.h" |
38 | 39 | ||
@@ -77,6 +78,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp) | |||
77 | mlog_errno(-ENOMEM); | 78 | mlog_errno(-ENOMEM); |
78 | return ERR_PTR(-ENOMEM); | 79 | return ERR_PTR(-ENOMEM); |
79 | } | 80 | } |
81 | result->d_op = &ocfs2_dentry_ops; | ||
80 | 82 | ||
81 | mlog_exit_ptr(result); | 83 | mlog_exit_ptr(result); |
82 | return result; | 84 | return result; |
@@ -127,6 +129,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) | |||
127 | parent = ERR_PTR(-ENOMEM); | 129 | parent = ERR_PTR(-ENOMEM); |
128 | } | 130 | } |
129 | 131 | ||
132 | parent->d_op = &ocfs2_dentry_ops; | ||
133 | |||
130 | bail_unlock: | 134 | bail_unlock: |
131 | ocfs2_meta_unlock(dir, 0); | 135 | ocfs2_meta_unlock(dir, 0); |
132 | 136 | ||
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 7bcf69154592..66ca7a82b68a 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -1025,12 +1025,10 @@ void ocfs2_drop_inode(struct inode *inode) | |||
1025 | /* Testing ip_orphaned_slot here wouldn't work because we may | 1025 | /* Testing ip_orphaned_slot here wouldn't work because we may |
1026 | * not have gotten a delete_inode vote from any other nodes | 1026 | * not have gotten a delete_inode vote from any other nodes |
1027 | * yet. */ | 1027 | * yet. */ |
1028 | if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) { | 1028 | if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) |
1029 | mlog(0, "Inode was orphaned on another node, clearing nlink.\n"); | 1029 | generic_delete_inode(inode); |
1030 | inode->i_nlink = 0; | 1030 | else |
1031 | } | 1031 | generic_drop_inode(inode); |
1032 | |||
1033 | generic_drop_inode(inode); | ||
1034 | 1032 | ||
1035 | mlog_exit_void(); | 1033 | mlog_exit_void(); |
1036 | } | 1034 | } |
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, | |||
199 | spin_unlock(&oi->ip_lock); | 199 | spin_unlock(&oi->ip_lock); |
200 | 200 | ||
201 | bail_add: | 201 | bail_add: |
202 | |||
203 | dentry->d_op = &ocfs2_dentry_ops; | 202 | dentry->d_op = &ocfs2_dentry_ops; |
204 | ret = d_splice_alias(inode, dentry); | 203 | ret = d_splice_alias(inode, dentry); |
205 | 204 | ||
205 | if (inode) { | ||
206 | /* | ||
207 | * If d_splice_alias() finds a DCACHE_DISCONNECTED | ||
208 | * dentry, it will d_move() it on top of ourse. The | ||
209 | * return value will indicate this however, so in | ||
210 | * those cases, we switch them around for the locking | ||
211 | * code. | ||
212 | * | ||
213 | * NOTE: This dentry already has ->d_op set from | ||
214 | * ocfs2_get_parent() and ocfs2_get_dentry() | ||
215 | */ | ||
216 | if (ret) | ||
217 | dentry = ret; | ||
218 | |||
219 | status = ocfs2_dentry_attach_lock(dentry, inode, | ||
220 | OCFS2_I(dir)->ip_blkno, 0); | ||
221 | if (status) { | ||
222 | mlog_errno(status); | ||
223 | ret = ERR_PTR(status); | ||
224 | goto bail_unlock; | ||
225 | } | ||
226 | } | ||
227 | |||
206 | bail_unlock: | 228 | bail_unlock: |
207 | /* Don't drop the cluster lock until *after* the d_add -- | 229 | /* Don't drop the cluster lock until *after* the d_add -- |
208 | * unlink on another node will message us to remove that | 230 | * unlink on another node will message us to remove that |
@@ -418,6 +440,13 @@ static int ocfs2_mknod(struct inode *dir, | |||
418 | goto leave; | 440 | goto leave; |
419 | } | 441 | } |
420 | 442 | ||
443 | status = ocfs2_dentry_attach_lock(dentry, inode, | ||
444 | OCFS2_I(dir)->ip_blkno, 1); | ||
445 | if (status) { | ||
446 | mlog_errno(status); | ||
447 | goto leave; | ||
448 | } | ||
449 | |||
421 | insert_inode_hash(inode); | 450 | insert_inode_hash(inode); |
422 | dentry->d_op = &ocfs2_dentry_ops; | 451 | dentry->d_op = &ocfs2_dentry_ops; |
423 | d_instantiate(dentry, inode); | 452 | d_instantiate(dentry, inode); |
@@ -725,6 +754,13 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
725 | goto bail; | 754 | goto bail; |
726 | } | 755 | } |
727 | 756 | ||
757 | err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno, | ||
758 | 0); | ||
759 | if (err) { | ||
760 | mlog_errno(err); | ||
761 | goto bail; | ||
762 | } | ||
763 | |||
728 | atomic_inc(&inode->i_count); | 764 | atomic_inc(&inode->i_count); |
729 | dentry->d_op = &ocfs2_dentry_ops; | 765 | dentry->d_op = &ocfs2_dentry_ops; |
730 | d_instantiate(dentry, inode); | 766 | d_instantiate(dentry, inode); |
@@ -743,6 +779,23 @@ bail: | |||
743 | return err; | 779 | return err; |
744 | } | 780 | } |
745 | 781 | ||
782 | /* | ||
783 | * Takes and drops an exclusive lock on the given dentry. This will | ||
784 | * force other nodes to drop it. | ||
785 | */ | ||
786 | static int ocfs2_remote_dentry_delete(struct dentry *dentry) | ||
787 | { | ||
788 | int ret; | ||
789 | |||
790 | ret = ocfs2_dentry_lock(dentry, 1); | ||
791 | if (ret) | ||
792 | mlog_errno(ret); | ||
793 | else | ||
794 | ocfs2_dentry_unlock(dentry, 1); | ||
795 | |||
796 | return ret; | ||
797 | } | ||
798 | |||
746 | static int ocfs2_unlink(struct inode *dir, | 799 | static int ocfs2_unlink(struct inode *dir, |
747 | struct dentry *dentry) | 800 | struct dentry *dentry) |
748 | { | 801 | { |
@@ -832,8 +885,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
832 | else | 885 | else |
833 | inode->i_nlink--; | 886 | inode->i_nlink--; |
834 | 887 | ||
835 | status = ocfs2_request_unlink_vote(inode, dentry, | 888 | status = ocfs2_remote_dentry_delete(dentry); |
836 | (unsigned int) inode->i_nlink); | ||
837 | if (status < 0) { | 889 | if (status < 0) { |
838 | /* This vote should succeed under all normal | 890 | /* This vote should succeed under all normal |
839 | * circumstances. */ | 891 | * circumstances. */ |
@@ -1019,7 +1071,6 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1019 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, | 1071 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, |
1020 | // this is the 1st dirent bh | 1072 | // this is the 1st dirent bh |
1021 | nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink; | 1073 | nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink; |
1022 | unsigned int links_count; | ||
1023 | 1074 | ||
1024 | /* At some point it might be nice to break this function up a | 1075 | /* At some point it might be nice to break this function up a |
1025 | * bit. */ | 1076 | * bit. */ |
@@ -1093,23 +1144,26 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1093 | } | 1144 | } |
1094 | } | 1145 | } |
1095 | 1146 | ||
1096 | if (S_ISDIR(old_inode->i_mode)) { | 1147 | /* |
1097 | /* Directories actually require metadata updates to | 1148 | * Though we don't require an inode meta data update if |
1098 | * the directory info so we can't get away with not | 1149 | * old_inode is not a directory, we lock anyway here to ensure |
1099 | * doing node locking on it. */ | 1150 | * the vote thread on other nodes won't have to concurrently |
1100 | status = ocfs2_meta_lock(old_inode, handle, NULL, 1); | 1151 | * downconvert the inode and the dentry locks. |
1101 | if (status < 0) { | 1152 | */ |
1102 | if (status != -ENOENT) | 1153 | status = ocfs2_meta_lock(old_inode, handle, NULL, 1); |
1103 | mlog_errno(status); | 1154 | if (status < 0) { |
1104 | goto bail; | 1155 | if (status != -ENOENT) |
1105 | } | ||
1106 | |||
1107 | status = ocfs2_request_rename_vote(old_inode, old_dentry); | ||
1108 | if (status < 0) { | ||
1109 | mlog_errno(status); | 1156 | mlog_errno(status); |
1110 | goto bail; | 1157 | goto bail; |
1111 | } | 1158 | } |
1159 | |||
1160 | status = ocfs2_remote_dentry_delete(old_dentry); | ||
1161 | if (status < 0) { | ||
1162 | mlog_errno(status); | ||
1163 | goto bail; | ||
1164 | } | ||
1112 | 1165 | ||
1166 | if (S_ISDIR(old_inode->i_mode)) { | ||
1113 | status = -EIO; | 1167 | status = -EIO; |
1114 | old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0); | 1168 | old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0); |
1115 | if (!old_inode_de_bh) | 1169 | if (!old_inode_de_bh) |
@@ -1123,14 +1177,6 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1123 | if (!new_inode && new_dir!=old_dir && | 1177 | if (!new_inode && new_dir!=old_dir && |
1124 | new_dir->i_nlink >= OCFS2_LINK_MAX) | 1178 | new_dir->i_nlink >= OCFS2_LINK_MAX) |
1125 | goto bail; | 1179 | goto bail; |
1126 | } else { | ||
1127 | /* Ah, the simple case - we're a file so just send a | ||
1128 | * message. */ | ||
1129 | status = ocfs2_request_rename_vote(old_inode, old_dentry); | ||
1130 | if (status < 0) { | ||
1131 | mlog_errno(status); | ||
1132 | goto bail; | ||
1133 | } | ||
1134 | } | 1180 | } |
1135 | 1181 | ||
1136 | status = -ENOENT; | 1182 | status = -ENOENT; |
@@ -1202,13 +1248,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1202 | goto bail; | 1248 | goto bail; |
1203 | } | 1249 | } |
1204 | 1250 | ||
1205 | if (S_ISDIR(new_inode->i_mode)) | 1251 | status = ocfs2_remote_dentry_delete(new_dentry); |
1206 | links_count = 0; | ||
1207 | else | ||
1208 | links_count = (unsigned int) (new_inode->i_nlink - 1); | ||
1209 | |||
1210 | status = ocfs2_request_unlink_vote(new_inode, new_dentry, | ||
1211 | links_count); | ||
1212 | if (status < 0) { | 1252 | if (status < 0) { |
1213 | mlog_errno(status); | 1253 | mlog_errno(status); |
1214 | goto bail; | 1254 | goto bail; |
@@ -1387,6 +1427,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1387 | } | 1427 | } |
1388 | } | 1428 | } |
1389 | 1429 | ||
1430 | ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); | ||
1390 | status = 0; | 1431 | status = 0; |
1391 | bail: | 1432 | bail: |
1392 | if (rename_lock) | 1433 | if (rename_lock) |
@@ -1675,6 +1716,13 @@ static int ocfs2_symlink(struct inode *dir, | |||
1675 | goto bail; | 1716 | goto bail; |
1676 | } | 1717 | } |
1677 | 1718 | ||
1719 | status = ocfs2_dentry_attach_lock(dentry, inode, | ||
1720 | OCFS2_I(dir)->ip_blkno, 1); | ||
1721 | if (status) { | ||
1722 | mlog_errno(status); | ||
1723 | goto bail; | ||
1724 | } | ||
1725 | |||
1678 | insert_inode_hash(inode); | 1726 | insert_inode_hash(inode); |
1679 | dentry->d_op = &ocfs2_dentry_ops; | 1727 | dentry->d_op = &ocfs2_dentry_ops; |
1680 | d_instantiate(dentry, inode); | 1728 | d_instantiate(dentry, inode); |