diff options
Diffstat (limited to 'fs/xfs/xfs_rename.c')
-rw-r--r-- | fs/xfs/xfs_rename.c | 82 |
1 files changed, 29 insertions, 53 deletions
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index c4d0bac56a5a..ee371890d85d 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c | |||
@@ -83,26 +83,23 @@ int xfs_rename_skip, xfs_rename_nskip; | |||
83 | */ | 83 | */ |
84 | STATIC int | 84 | STATIC int |
85 | xfs_lock_for_rename( | 85 | xfs_lock_for_rename( |
86 | xfs_inode_t *dp1, /* old (source) directory inode */ | 86 | xfs_inode_t *dp1, /* in: old (source) directory inode */ |
87 | xfs_inode_t *dp2, /* new (target) directory inode */ | 87 | xfs_inode_t *dp2, /* in: new (target) directory inode */ |
88 | bhv_vname_t *vname1,/* old entry name */ | 88 | xfs_inode_t *ip1, /* in: inode of old entry */ |
89 | bhv_vname_t *vname2,/* new entry name */ | 89 | struct xfs_name *name2, /* in: new entry name */ |
90 | xfs_inode_t **ipp1, /* inode of old entry */ | 90 | xfs_inode_t **ipp2, /* out: inode of new entry, if it |
91 | xfs_inode_t **ipp2, /* inode of new entry, if it | ||
92 | already exists, NULL otherwise. */ | 91 | already exists, NULL otherwise. */ |
93 | xfs_inode_t **i_tab,/* array of inode returned, sorted */ | 92 | xfs_inode_t **i_tab,/* out: array of inode returned, sorted */ |
94 | int *num_inodes) /* number of inodes in array */ | 93 | int *num_inodes) /* out: number of inodes in array */ |
95 | { | 94 | { |
96 | xfs_inode_t *ip1 = VNAME_TO_INODE(vname1); | 95 | xfs_inode_t *ip2 = NULL; |
97 | xfs_inode_t *ip2, *temp; | 96 | xfs_inode_t *temp; |
98 | xfs_ino_t inum1, inum2; | 97 | xfs_ino_t inum1, inum2; |
99 | int error; | 98 | int error; |
100 | int i, j; | 99 | int i, j; |
101 | uint lock_mode; | 100 | uint lock_mode; |
102 | int diff_dirs = (dp1 != dp2); | 101 | int diff_dirs = (dp1 != dp2); |
103 | 102 | ||
104 | ip2 = NULL; | ||
105 | |||
106 | /* | 103 | /* |
107 | * First, find out the current inums of the entries so that we | 104 | * First, find out the current inums of the entries so that we |
108 | * can determine the initial locking order. We'll have to | 105 | * can determine the initial locking order. We'll have to |
@@ -115,17 +112,15 @@ xfs_lock_for_rename( | |||
115 | 112 | ||
116 | inum1 = ip1->i_ino; | 113 | inum1 = ip1->i_ino; |
117 | 114 | ||
118 | |||
119 | /* | 115 | /* |
120 | * Unlock dp1 and lock dp2 if they are different. | 116 | * Unlock dp1 and lock dp2 if they are different. |
121 | */ | 117 | */ |
122 | |||
123 | if (diff_dirs) { | 118 | if (diff_dirs) { |
124 | xfs_iunlock_map_shared(dp1, lock_mode); | 119 | xfs_iunlock_map_shared(dp1, lock_mode); |
125 | lock_mode = xfs_ilock_map_shared(dp2); | 120 | lock_mode = xfs_ilock_map_shared(dp2); |
126 | } | 121 | } |
127 | 122 | ||
128 | error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2); | 123 | error = xfs_dir_lookup_int(dp2, lock_mode, name2, &inum2, &ip2); |
129 | if (error == ENOENT) { /* target does not need to exist. */ | 124 | if (error == ENOENT) { /* target does not need to exist. */ |
130 | inum2 = 0; | 125 | inum2 = 0; |
131 | } else if (error) { | 126 | } else if (error) { |
@@ -157,6 +152,7 @@ xfs_lock_for_rename( | |||
157 | *num_inodes = 4; | 152 | *num_inodes = 4; |
158 | i_tab[3] = ip2; | 153 | i_tab[3] = ip2; |
159 | } | 154 | } |
155 | *ipp2 = i_tab[3]; | ||
160 | 156 | ||
161 | /* | 157 | /* |
162 | * Sort the elements via bubble sort. (Remember, there are at | 158 | * Sort the elements via bubble sort. (Remember, there are at |
@@ -194,21 +190,6 @@ xfs_lock_for_rename( | |||
194 | xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED); | 190 | xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED); |
195 | } | 191 | } |
196 | 192 | ||
197 | /* | ||
198 | * Set the return value. Null out any unused entries in i_tab. | ||
199 | */ | ||
200 | *ipp1 = *ipp2 = NULL; | ||
201 | for (i=0; i < *num_inodes; i++) { | ||
202 | if (i_tab[i]->i_ino == inum1) { | ||
203 | *ipp1 = i_tab[i]; | ||
204 | } | ||
205 | if (i_tab[i]->i_ino == inum2) { | ||
206 | *ipp2 = i_tab[i]; | ||
207 | } | ||
208 | } | ||
209 | for (;i < 4; i++) { | ||
210 | i_tab[i] = NULL; | ||
211 | } | ||
212 | return 0; | 193 | return 0; |
213 | } | 194 | } |
214 | 195 | ||
@@ -218,12 +199,13 @@ xfs_lock_for_rename( | |||
218 | int | 199 | int |
219 | xfs_rename( | 200 | xfs_rename( |
220 | xfs_inode_t *src_dp, | 201 | xfs_inode_t *src_dp, |
221 | bhv_vname_t *src_vname, | 202 | struct xfs_name *src_name, |
203 | xfs_inode_t *src_ip, | ||
222 | xfs_inode_t *target_dp, | 204 | xfs_inode_t *target_dp, |
223 | bhv_vname_t *target_vname) | 205 | struct xfs_name *target_name) |
224 | { | 206 | { |
225 | xfs_trans_t *tp; | 207 | xfs_trans_t *tp; |
226 | xfs_inode_t *src_ip, *target_ip; | 208 | xfs_inode_t *target_ip; |
227 | xfs_mount_t *mp = src_dp->i_mount; | 209 | xfs_mount_t *mp = src_dp->i_mount; |
228 | int new_parent; /* moving to a new dir */ | 210 | int new_parent; /* moving to a new dir */ |
229 | int src_is_directory; /* src_name is a directory */ | 211 | int src_is_directory; /* src_name is a directory */ |
@@ -237,10 +219,6 @@ xfs_rename( | |||
237 | int spaceres; | 219 | int spaceres; |
238 | int target_link_zero = 0; | 220 | int target_link_zero = 0; |
239 | int num_inodes; | 221 | int num_inodes; |
240 | char *src_name = VNAME(src_vname); | ||
241 | char *target_name = VNAME(target_vname); | ||
242 | int src_namelen = VNAMELEN(src_vname); | ||
243 | int target_namelen = VNAMELEN(target_vname); | ||
244 | 222 | ||
245 | xfs_itrace_entry(src_dp); | 223 | xfs_itrace_entry(src_dp); |
246 | xfs_itrace_entry(target_dp); | 224 | xfs_itrace_entry(target_dp); |
@@ -250,7 +228,7 @@ xfs_rename( | |||
250 | error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME, | 228 | error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME, |
251 | src_dp, DM_RIGHT_NULL, | 229 | src_dp, DM_RIGHT_NULL, |
252 | target_dp, DM_RIGHT_NULL, | 230 | target_dp, DM_RIGHT_NULL, |
253 | src_name, target_name, | 231 | src_name->name, target_name->name, |
254 | 0, 0, 0); | 232 | 0, 0, 0); |
255 | if (error) { | 233 | if (error) { |
256 | return error; | 234 | return error; |
@@ -267,10 +245,8 @@ xfs_rename( | |||
267 | * does not exist in the source directory. | 245 | * does not exist in the source directory. |
268 | */ | 246 | */ |
269 | tp = NULL; | 247 | tp = NULL; |
270 | error = xfs_lock_for_rename(src_dp, target_dp, src_vname, | 248 | error = xfs_lock_for_rename(src_dp, target_dp, src_ip, target_name, |
271 | target_vname, &src_ip, &target_ip, inodes, | 249 | &target_ip, inodes, &num_inodes); |
272 | &num_inodes); | ||
273 | |||
274 | if (error) { | 250 | if (error) { |
275 | /* | 251 | /* |
276 | * We have nothing locked, no inode references, and | 252 | * We have nothing locked, no inode references, and |
@@ -316,7 +292,7 @@ xfs_rename( | |||
316 | XFS_BMAP_INIT(&free_list, &first_block); | 292 | XFS_BMAP_INIT(&free_list, &first_block); |
317 | tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME); | 293 | tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME); |
318 | cancel_flags = XFS_TRANS_RELEASE_LOG_RES; | 294 | cancel_flags = XFS_TRANS_RELEASE_LOG_RES; |
319 | spaceres = XFS_RENAME_SPACE_RES(mp, target_namelen); | 295 | spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len); |
320 | error = xfs_trans_reserve(tp, spaceres, XFS_RENAME_LOG_RES(mp), 0, | 296 | error = xfs_trans_reserve(tp, spaceres, XFS_RENAME_LOG_RES(mp), 0, |
321 | XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT); | 297 | XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT); |
322 | if (error == ENOSPC) { | 298 | if (error == ENOSPC) { |
@@ -374,9 +350,8 @@ xfs_rename( | |||
374 | * If there's no space reservation, check the entry will | 350 | * If there's no space reservation, check the entry will |
375 | * fit before actually inserting it. | 351 | * fit before actually inserting it. |
376 | */ | 352 | */ |
377 | if (spaceres == 0 && | 353 | error = xfs_dir_canenter(tp, target_dp, target_name, spaceres); |
378 | (error = xfs_dir_canenter(tp, target_dp, target_name, | 354 | if (error) |
379 | target_namelen))) | ||
380 | goto error_return; | 355 | goto error_return; |
381 | /* | 356 | /* |
382 | * If target does not exist and the rename crosses | 357 | * If target does not exist and the rename crosses |
@@ -384,8 +359,8 @@ xfs_rename( | |||
384 | * to account for the ".." reference from the new entry. | 359 | * to account for the ".." reference from the new entry. |
385 | */ | 360 | */ |
386 | error = xfs_dir_createname(tp, target_dp, target_name, | 361 | error = xfs_dir_createname(tp, target_dp, target_name, |
387 | target_namelen, src_ip->i_ino, | 362 | src_ip->i_ino, &first_block, |
388 | &first_block, &free_list, spaceres); | 363 | &free_list, spaceres); |
389 | if (error == ENOSPC) | 364 | if (error == ENOSPC) |
390 | goto error_return; | 365 | goto error_return; |
391 | if (error) | 366 | if (error) |
@@ -424,7 +399,7 @@ xfs_rename( | |||
424 | * name at the destination directory, remove it first. | 399 | * name at the destination directory, remove it first. |
425 | */ | 400 | */ |
426 | error = xfs_dir_replace(tp, target_dp, target_name, | 401 | error = xfs_dir_replace(tp, target_dp, target_name, |
427 | target_namelen, src_ip->i_ino, | 402 | src_ip->i_ino, |
428 | &first_block, &free_list, spaceres); | 403 | &first_block, &free_list, spaceres); |
429 | if (error) | 404 | if (error) |
430 | goto abort_return; | 405 | goto abort_return; |
@@ -461,7 +436,8 @@ xfs_rename( | |||
461 | * Rewrite the ".." entry to point to the new | 436 | * Rewrite the ".." entry to point to the new |
462 | * directory. | 437 | * directory. |
463 | */ | 438 | */ |
464 | error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino, | 439 | error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot, |
440 | target_dp->i_ino, | ||
465 | &first_block, &free_list, spaceres); | 441 | &first_block, &free_list, spaceres); |
466 | ASSERT(error != EEXIST); | 442 | ASSERT(error != EEXIST); |
467 | if (error) | 443 | if (error) |
@@ -497,8 +473,8 @@ xfs_rename( | |||
497 | goto abort_return; | 473 | goto abort_return; |
498 | } | 474 | } |
499 | 475 | ||
500 | error = xfs_dir_removename(tp, src_dp, src_name, src_namelen, | 476 | error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino, |
501 | src_ip->i_ino, &first_block, &free_list, spaceres); | 477 | &first_block, &free_list, spaceres); |
502 | if (error) | 478 | if (error) |
503 | goto abort_return; | 479 | goto abort_return; |
504 | xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 480 | xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
@@ -583,7 +559,7 @@ std_return: | |||
583 | (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME, | 559 | (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME, |
584 | src_dp, DM_RIGHT_NULL, | 560 | src_dp, DM_RIGHT_NULL, |
585 | target_dp, DM_RIGHT_NULL, | 561 | target_dp, DM_RIGHT_NULL, |
586 | src_name, target_name, | 562 | src_name->name, target_name->name, |
587 | 0, error, 0); | 563 | 0, error, 0); |
588 | } | 564 | } |
589 | return error; | 565 | return error; |