diff options
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r-- | fs/ocfs2/namei.c | 116 |
1 files changed, 81 insertions, 35 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 0d3e939b1f56..849c3b4bb94a 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -179,7 +179,7 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, | |||
179 | if (status < 0) | 179 | if (status < 0) |
180 | goto bail_add; | 180 | goto bail_add; |
181 | 181 | ||
182 | inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno); | 182 | inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0); |
183 | if (IS_ERR(inode)) { | 183 | if (IS_ERR(inode)) { |
184 | mlog(ML_ERROR, "Unable to create inode %llu\n", | 184 | mlog(ML_ERROR, "Unable to create inode %llu\n", |
185 | (unsigned long long)blkno); | 185 | (unsigned long long)blkno); |
@@ -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); | ||
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); | ||
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,12 @@ 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 | if (err) { | ||
759 | mlog_errno(err); | ||
760 | goto bail; | ||
761 | } | ||
762 | |||
728 | atomic_inc(&inode->i_count); | 763 | atomic_inc(&inode->i_count); |
729 | dentry->d_op = &ocfs2_dentry_ops; | 764 | dentry->d_op = &ocfs2_dentry_ops; |
730 | d_instantiate(dentry, inode); | 765 | d_instantiate(dentry, inode); |
@@ -743,6 +778,23 @@ bail: | |||
743 | return err; | 778 | return err; |
744 | } | 779 | } |
745 | 780 | ||
781 | /* | ||
782 | * Takes and drops an exclusive lock on the given dentry. This will | ||
783 | * force other nodes to drop it. | ||
784 | */ | ||
785 | static int ocfs2_remote_dentry_delete(struct dentry *dentry) | ||
786 | { | ||
787 | int ret; | ||
788 | |||
789 | ret = ocfs2_dentry_lock(dentry, 1); | ||
790 | if (ret) | ||
791 | mlog_errno(ret); | ||
792 | else | ||
793 | ocfs2_dentry_unlock(dentry, 1); | ||
794 | |||
795 | return ret; | ||
796 | } | ||
797 | |||
746 | static int ocfs2_unlink(struct inode *dir, | 798 | static int ocfs2_unlink(struct inode *dir, |
747 | struct dentry *dentry) | 799 | struct dentry *dentry) |
748 | { | 800 | { |
@@ -832,8 +884,7 @@ static int ocfs2_unlink(struct inode *dir, | |||
832 | else | 884 | else |
833 | inode->i_nlink--; | 885 | inode->i_nlink--; |
834 | 886 | ||
835 | status = ocfs2_request_unlink_vote(inode, dentry, | 887 | status = ocfs2_remote_dentry_delete(dentry); |
836 | (unsigned int) inode->i_nlink); | ||
837 | if (status < 0) { | 888 | if (status < 0) { |
838 | /* This vote should succeed under all normal | 889 | /* This vote should succeed under all normal |
839 | * circumstances. */ | 890 | * circumstances. */ |
@@ -1019,7 +1070,6 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1019 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, | 1070 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, |
1020 | // this is the 1st dirent bh | 1071 | // this is the 1st dirent bh |
1021 | nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink; | 1072 | nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink; |
1022 | unsigned int links_count; | ||
1023 | 1073 | ||
1024 | /* At some point it might be nice to break this function up a | 1074 | /* At some point it might be nice to break this function up a |
1025 | * bit. */ | 1075 | * bit. */ |
@@ -1093,23 +1143,26 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1093 | } | 1143 | } |
1094 | } | 1144 | } |
1095 | 1145 | ||
1096 | if (S_ISDIR(old_inode->i_mode)) { | 1146 | /* |
1097 | /* Directories actually require metadata updates to | 1147 | * Though we don't require an inode meta data update if |
1098 | * the directory info so we can't get away with not | 1148 | * old_inode is not a directory, we lock anyway here to ensure |
1099 | * doing node locking on it. */ | 1149 | * the vote thread on other nodes won't have to concurrently |
1100 | status = ocfs2_meta_lock(old_inode, handle, NULL, 1); | 1150 | * downconvert the inode and the dentry locks. |
1101 | if (status < 0) { | 1151 | */ |
1102 | if (status != -ENOENT) | 1152 | status = ocfs2_meta_lock(old_inode, handle, NULL, 1); |
1103 | mlog_errno(status); | 1153 | if (status < 0) { |
1104 | goto bail; | 1154 | if (status != -ENOENT) |
1105 | } | ||
1106 | |||
1107 | status = ocfs2_request_rename_vote(old_inode, old_dentry); | ||
1108 | if (status < 0) { | ||
1109 | mlog_errno(status); | 1155 | mlog_errno(status); |
1110 | goto bail; | 1156 | goto bail; |
1111 | } | 1157 | } |
1158 | |||
1159 | status = ocfs2_remote_dentry_delete(old_dentry); | ||
1160 | if (status < 0) { | ||
1161 | mlog_errno(status); | ||
1162 | goto bail; | ||
1163 | } | ||
1112 | 1164 | ||
1165 | if (S_ISDIR(old_inode->i_mode)) { | ||
1113 | status = -EIO; | 1166 | status = -EIO; |
1114 | old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0); | 1167 | old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0); |
1115 | if (!old_inode_de_bh) | 1168 | if (!old_inode_de_bh) |
@@ -1123,14 +1176,6 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1123 | if (!new_inode && new_dir!=old_dir && | 1176 | if (!new_inode && new_dir!=old_dir && |
1124 | new_dir->i_nlink >= OCFS2_LINK_MAX) | 1177 | new_dir->i_nlink >= OCFS2_LINK_MAX) |
1125 | goto bail; | 1178 | 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 | } | 1179 | } |
1135 | 1180 | ||
1136 | status = -ENOENT; | 1181 | status = -ENOENT; |
@@ -1202,13 +1247,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1202 | goto bail; | 1247 | goto bail; |
1203 | } | 1248 | } |
1204 | 1249 | ||
1205 | if (S_ISDIR(new_inode->i_mode)) | 1250 | 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) { | 1251 | if (status < 0) { |
1213 | mlog_errno(status); | 1252 | mlog_errno(status); |
1214 | goto bail; | 1253 | goto bail; |
@@ -1387,6 +1426,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1387 | } | 1426 | } |
1388 | } | 1427 | } |
1389 | 1428 | ||
1429 | ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); | ||
1390 | status = 0; | 1430 | status = 0; |
1391 | bail: | 1431 | bail: |
1392 | if (rename_lock) | 1432 | if (rename_lock) |
@@ -1675,6 +1715,12 @@ static int ocfs2_symlink(struct inode *dir, | |||
1675 | goto bail; | 1715 | goto bail; |
1676 | } | 1716 | } |
1677 | 1717 | ||
1718 | status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); | ||
1719 | if (status) { | ||
1720 | mlog_errno(status); | ||
1721 | goto bail; | ||
1722 | } | ||
1723 | |||
1678 | insert_inode_hash(inode); | 1724 | insert_inode_hash(inode); |
1679 | dentry->d_op = &ocfs2_dentry_ops; | 1725 | dentry->d_op = &ocfs2_dentry_ops; |
1680 | d_instantiate(dentry, inode); | 1726 | d_instantiate(dentry, inode); |