diff options
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, | |||
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); |