aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/namei.c56
1 files changed, 37 insertions, 19 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 7e9da946c777..5bd5f9948a2f 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -104,13 +104,6 @@ static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
104 struct buffer_head *fe_bh, 104 struct buffer_head *fe_bh,
105 struct ocfs2_alloc_context *data_ac); 105 struct ocfs2_alloc_context *data_ac);
106 106
107static int ocfs2_double_lock(struct ocfs2_super *osb,
108 struct ocfs2_journal_handle *handle,
109 struct buffer_head **bh1,
110 struct inode *inode1,
111 struct buffer_head **bh2,
112 struct inode *inode2);
113
114static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 107static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
115 struct inode **ret_orphan_dir, 108 struct inode **ret_orphan_dir,
116 struct inode *inode, 109 struct inode *inode,
@@ -992,7 +985,6 @@ leave:
992 * if they have the same id, then the 1st one is the only one locked. 985 * if they have the same id, then the 1st one is the only one locked.
993 */ 986 */
994static int ocfs2_double_lock(struct ocfs2_super *osb, 987static int ocfs2_double_lock(struct ocfs2_super *osb,
995 struct ocfs2_journal_handle *handle,
996 struct buffer_head **bh1, 988 struct buffer_head **bh1,
997 struct inode *inode1, 989 struct inode *inode1,
998 struct buffer_head **bh2, 990 struct buffer_head **bh2,
@@ -1008,8 +1000,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
1008 (unsigned long long)oi1->ip_blkno, 1000 (unsigned long long)oi1->ip_blkno,
1009 (unsigned long long)oi2->ip_blkno); 1001 (unsigned long long)oi2->ip_blkno);
1010 1002
1011 BUG_ON(!handle);
1012
1013 if (*bh1) 1003 if (*bh1)
1014 *bh1 = NULL; 1004 *bh1 = NULL;
1015 if (*bh2) 1005 if (*bh2)
@@ -1029,25 +1019,41 @@ static int ocfs2_double_lock(struct ocfs2_super *osb,
1029 inode1 = tmpinode; 1019 inode1 = tmpinode;
1030 } 1020 }
1031 /* lock id2 */ 1021 /* lock id2 */
1032 status = ocfs2_meta_lock(inode2, handle, bh2, 1); 1022 status = ocfs2_meta_lock(inode2, NULL, bh2, 1);
1033 if (status < 0) { 1023 if (status < 0) {
1034 if (status != -ENOENT) 1024 if (status != -ENOENT)
1035 mlog_errno(status); 1025 mlog_errno(status);
1036 goto bail; 1026 goto bail;
1037 } 1027 }
1038 } 1028 }
1029
1039 /* lock id1 */ 1030 /* lock id1 */
1040 status = ocfs2_meta_lock(inode1, handle, bh1, 1); 1031 status = ocfs2_meta_lock(inode1, NULL, bh1, 1);
1041 if (status < 0) { 1032 if (status < 0) {
1033 /*
1034 * An error return must mean that no cluster locks
1035 * were held on function exit.
1036 */
1037 if (oi1->ip_blkno != oi2->ip_blkno)
1038 ocfs2_meta_unlock(inode2, 1);
1039
1042 if (status != -ENOENT) 1040 if (status != -ENOENT)
1043 mlog_errno(status); 1041 mlog_errno(status);
1044 goto bail;
1045 } 1042 }
1043
1046bail: 1044bail:
1047 mlog_exit(status); 1045 mlog_exit(status);
1048 return status; 1046 return status;
1049} 1047}
1050 1048
1049static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
1050{
1051 ocfs2_meta_unlock(inode1, 1);
1052
1053 if (inode1 != inode2)
1054 ocfs2_meta_unlock(inode2, 1);
1055}
1056
1051#define PARENT_INO(buffer) \ 1057#define PARENT_INO(buffer) \
1052 ((struct ocfs2_dir_entry *) \ 1058 ((struct ocfs2_dir_entry *) \
1053 ((char *)buffer + \ 1059 ((char *)buffer + \
@@ -1058,7 +1064,8 @@ static int ocfs2_rename(struct inode *old_dir,
1058 struct inode *new_dir, 1064 struct inode *new_dir,
1059 struct dentry *new_dentry) 1065 struct dentry *new_dentry)
1060{ 1066{
1061 int status = 0, rename_lock = 0; 1067 int status = 0, rename_lock = 0, parents_locked = 0;
1068 int old_child_locked = 0, new_child_locked = 0;
1062 struct inode *old_inode = old_dentry->d_inode; 1069 struct inode *old_inode = old_dentry->d_inode;
1063 struct inode *new_inode = new_dentry->d_inode; 1070 struct inode *new_inode = new_dentry->d_inode;
1064 struct inode *orphan_dir = NULL; 1071 struct inode *orphan_dir = NULL;
@@ -1122,13 +1129,13 @@ static int ocfs2_rename(struct inode *old_dir,
1122 } 1129 }
1123 1130
1124 /* if old and new are the same, this'll just do one lock. */ 1131 /* if old and new are the same, this'll just do one lock. */
1125 status = ocfs2_double_lock(osb, handle, 1132 status = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
1126 &old_dir_bh, old_dir, 1133 &new_dir_bh, new_dir);
1127 &new_dir_bh, new_dir);
1128 if (status < 0) { 1134 if (status < 0) {
1129 mlog_errno(status); 1135 mlog_errno(status);
1130 goto bail; 1136 goto bail;
1131 } 1137 }
1138 parents_locked = 1;
1132 1139
1133 /* make sure both dirs have bhs 1140 /* make sure both dirs have bhs
1134 * get an extra ref on old_dir_bh if old==new */ 1141 * get an extra ref on old_dir_bh if old==new */
@@ -1149,12 +1156,13 @@ static int ocfs2_rename(struct inode *old_dir,
1149 * the vote thread on other nodes won't have to concurrently 1156 * the vote thread on other nodes won't have to concurrently
1150 * downconvert the inode and the dentry locks. 1157 * downconvert the inode and the dentry locks.
1151 */ 1158 */
1152 status = ocfs2_meta_lock(old_inode, handle, NULL, 1); 1159 status = ocfs2_meta_lock(old_inode, NULL, NULL, 1);
1153 if (status < 0) { 1160 if (status < 0) {
1154 if (status != -ENOENT) 1161 if (status != -ENOENT)
1155 mlog_errno(status); 1162 mlog_errno(status);
1156 goto bail; 1163 goto bail;
1157 } 1164 }
1165 old_child_locked = 1;
1158 1166
1159 status = ocfs2_remote_dentry_delete(old_dentry); 1167 status = ocfs2_remote_dentry_delete(old_dentry);
1160 if (status < 0) { 1168 if (status < 0) {
@@ -1240,12 +1248,13 @@ static int ocfs2_rename(struct inode *old_dir,
1240 goto bail; 1248 goto bail;
1241 } 1249 }
1242 1250
1243 status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1); 1251 status = ocfs2_meta_lock(new_inode, NULL, &newfe_bh, 1);
1244 if (status < 0) { 1252 if (status < 0) {
1245 if (status != -ENOENT) 1253 if (status != -ENOENT)
1246 mlog_errno(status); 1254 mlog_errno(status);
1247 goto bail; 1255 goto bail;
1248 } 1256 }
1257 new_child_locked = 1;
1249 1258
1250 status = ocfs2_remote_dentry_delete(new_dentry); 1259 status = ocfs2_remote_dentry_delete(new_dentry);
1251 if (status < 0) { 1260 if (status < 0) {
@@ -1435,6 +1444,15 @@ bail:
1435 if (handle) 1444 if (handle)
1436 ocfs2_commit_trans(handle); 1445 ocfs2_commit_trans(handle);
1437 1446
1447 if (parents_locked)
1448 ocfs2_double_unlock(old_dir, new_dir);
1449
1450 if (old_child_locked)
1451 ocfs2_meta_unlock(old_inode, 1);
1452
1453 if (new_child_locked)
1454 ocfs2_meta_unlock(new_inode, 1);
1455
1438 if (orphan_dir) { 1456 if (orphan_dir) {
1439 /* This was locked for us in ocfs2_prepare_orphan_dir() */ 1457 /* This was locked for us in ocfs2_prepare_orphan_dir() */
1440 ocfs2_meta_unlock(orphan_dir, 1); 1458 ocfs2_meta_unlock(orphan_dir, 1);