aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_rename.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_rename.c')
-rw-r--r--fs/xfs/xfs_rename.c121
1 files changed, 40 insertions, 81 deletions
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 7eb157a59f9e..ee371890d85d 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -36,7 +36,6 @@
36#include "xfs_bmap.h" 36#include "xfs_bmap.h"
37#include "xfs_error.h" 37#include "xfs_error.h"
38#include "xfs_quota.h" 38#include "xfs_quota.h"
39#include "xfs_refcache.h"
40#include "xfs_utils.h" 39#include "xfs_utils.h"
41#include "xfs_trans_space.h" 40#include "xfs_trans_space.h"
42#include "xfs_vnodeops.h" 41#include "xfs_vnodeops.h"
@@ -84,25 +83,23 @@ int xfs_rename_skip, xfs_rename_nskip;
84 */ 83 */
85STATIC int 84STATIC int
86xfs_lock_for_rename( 85xfs_lock_for_rename(
87 xfs_inode_t *dp1, /* old (source) directory inode */ 86 xfs_inode_t *dp1, /* in: old (source) directory inode */
88 xfs_inode_t *dp2, /* new (target) directory inode */ 87 xfs_inode_t *dp2, /* in: new (target) directory inode */
89 bhv_vname_t *vname1,/* old entry name */ 88 xfs_inode_t *ip1, /* in: inode of old entry */
90 bhv_vname_t *vname2,/* new entry name */ 89 struct xfs_name *name2, /* in: new entry name */
91 xfs_inode_t **ipp1, /* inode of old entry */ 90 xfs_inode_t **ipp2, /* out: inode of new entry, if it
92 xfs_inode_t **ipp2, /* inode of new entry, if it
93 already exists, NULL otherwise. */ 91 already exists, NULL otherwise. */
94 xfs_inode_t **i_tab,/* array of inode returned, sorted */ 92 xfs_inode_t **i_tab,/* out: array of inode returned, sorted */
95 int *num_inodes) /* number of inodes in array */ 93 int *num_inodes) /* out: number of inodes in array */
96{ 94{
97 xfs_inode_t *ip1, *ip2, *temp; 95 xfs_inode_t *ip2 = NULL;
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
@@ -110,27 +107,20 @@ xfs_lock_for_rename(
110 * to see if we still have the right inodes, directories, etc. 107 * to see if we still have the right inodes, directories, etc.
111 */ 108 */
112 lock_mode = xfs_ilock_map_shared(dp1); 109 lock_mode = xfs_ilock_map_shared(dp1);
113 error = xfs_get_dir_entry(vname1, &ip1); 110 IHOLD(ip1);
114 if (error) { 111 xfs_itrace_ref(ip1);
115 xfs_iunlock_map_shared(dp1, lock_mode);
116 return error;
117 }
118 112
119 inum1 = ip1->i_ino; 113 inum1 = ip1->i_ino;
120 114
121 ASSERT(ip1);
122 xfs_itrace_ref(ip1);
123
124 /* 115 /*
125 * Unlock dp1 and lock dp2 if they are different. 116 * Unlock dp1 and lock dp2 if they are different.
126 */ 117 */
127
128 if (diff_dirs) { 118 if (diff_dirs) {
129 xfs_iunlock_map_shared(dp1, lock_mode); 119 xfs_iunlock_map_shared(dp1, lock_mode);
130 lock_mode = xfs_ilock_map_shared(dp2); 120 lock_mode = xfs_ilock_map_shared(dp2);
131 } 121 }
132 122
133 error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2); 123 error = xfs_dir_lookup_int(dp2, lock_mode, name2, &inum2, &ip2);
134 if (error == ENOENT) { /* target does not need to exist. */ 124 if (error == ENOENT) { /* target does not need to exist. */
135 inum2 = 0; 125 inum2 = 0;
136 } else if (error) { 126 } else if (error) {
@@ -162,6 +152,7 @@ xfs_lock_for_rename(
162 *num_inodes = 4; 152 *num_inodes = 4;
163 i_tab[3] = ip2; 153 i_tab[3] = ip2;
164 } 154 }
155 *ipp2 = i_tab[3];
165 156
166 /* 157 /*
167 * Sort the elements via bubble sort. (Remember, there are at 158 * Sort the elements via bubble sort. (Remember, there are at
@@ -199,21 +190,6 @@ xfs_lock_for_rename(
199 xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED); 190 xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);
200 } 191 }
201 192
202 /*
203 * Set the return value. Null out any unused entries in i_tab.
204 */
205 *ipp1 = *ipp2 = NULL;
206 for (i=0; i < *num_inodes; i++) {
207 if (i_tab[i]->i_ino == inum1) {
208 *ipp1 = i_tab[i];
209 }
210 if (i_tab[i]->i_ino == inum2) {
211 *ipp2 = i_tab[i];
212 }
213 }
214 for (;i < 4; i++) {
215 i_tab[i] = NULL;
216 }
217 return 0; 193 return 0;
218} 194}
219 195
@@ -223,13 +199,13 @@ xfs_lock_for_rename(
223int 199int
224xfs_rename( 200xfs_rename(
225 xfs_inode_t *src_dp, 201 xfs_inode_t *src_dp,
226 bhv_vname_t *src_vname, 202 struct xfs_name *src_name,
227 bhv_vnode_t *target_dir_vp, 203 xfs_inode_t *src_ip,
228 bhv_vname_t *target_vname) 204 xfs_inode_t *target_dp,
205 struct xfs_name *target_name)
229{ 206{
230 bhv_vnode_t *src_dir_vp = XFS_ITOV(src_dp);
231 xfs_trans_t *tp; 207 xfs_trans_t *tp;
232 xfs_inode_t *target_dp, *src_ip, *target_ip; 208 xfs_inode_t *target_ip;
233 xfs_mount_t *mp = src_dp->i_mount; 209 xfs_mount_t *mp = src_dp->i_mount;
234 int new_parent; /* moving to a new dir */ 210 int new_parent; /* moving to a new dir */
235 int src_is_directory; /* src_name is a directory */ 211 int src_is_directory; /* src_name is a directory */
@@ -243,29 +219,16 @@ xfs_rename(
243 int spaceres; 219 int spaceres;
244 int target_link_zero = 0; 220 int target_link_zero = 0;
245 int num_inodes; 221 int num_inodes;
246 char *src_name = VNAME(src_vname);
247 char *target_name = VNAME(target_vname);
248 int src_namelen = VNAMELEN(src_vname);
249 int target_namelen = VNAMELEN(target_vname);
250 222
251 xfs_itrace_entry(src_dp); 223 xfs_itrace_entry(src_dp);
252 xfs_itrace_entry(xfs_vtoi(target_dir_vp)); 224 xfs_itrace_entry(target_dp);
253
254 /*
255 * Find the XFS behavior descriptor for the target directory
256 * vnode since it was not handed to us.
257 */
258 target_dp = xfs_vtoi(target_dir_vp);
259 if (target_dp == NULL) {
260 return XFS_ERROR(EXDEV);
261 }
262 225
263 if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) || 226 if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) ||
264 DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) { 227 DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) {
265 error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME, 228 error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,
266 src_dir_vp, DM_RIGHT_NULL, 229 src_dp, DM_RIGHT_NULL,
267 target_dir_vp, DM_RIGHT_NULL, 230 target_dp, DM_RIGHT_NULL,
268 src_name, target_name, 231 src_name->name, target_name->name,
269 0, 0, 0); 232 0, 0, 0);
270 if (error) { 233 if (error) {
271 return error; 234 return error;
@@ -282,10 +245,8 @@ xfs_rename(
282 * does not exist in the source directory. 245 * does not exist in the source directory.
283 */ 246 */
284 tp = NULL; 247 tp = NULL;
285 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,
286 target_vname, &src_ip, &target_ip, inodes, 249 &target_ip, inodes, &num_inodes);
287 &num_inodes);
288
289 if (error) { 250 if (error) {
290 /* 251 /*
291 * We have nothing locked, no inode references, and 252 * We have nothing locked, no inode references, and
@@ -331,7 +292,7 @@ xfs_rename(
331 XFS_BMAP_INIT(&free_list, &first_block); 292 XFS_BMAP_INIT(&free_list, &first_block);
332 tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME); 293 tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
333 cancel_flags = XFS_TRANS_RELEASE_LOG_RES; 294 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
334 spaceres = XFS_RENAME_SPACE_RES(mp, target_namelen); 295 spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len);
335 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,
336 XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT); 297 XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
337 if (error == ENOSPC) { 298 if (error == ENOSPC) {
@@ -365,10 +326,10 @@ xfs_rename(
365 * them when they unlock the inodes. Also, we need to be careful 326 * them when they unlock the inodes. Also, we need to be careful
366 * not to add an inode to the transaction more than once. 327 * not to add an inode to the transaction more than once.
367 */ 328 */
368 VN_HOLD(src_dir_vp); 329 IHOLD(src_dp);
369 xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL); 330 xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
370 if (new_parent) { 331 if (new_parent) {
371 VN_HOLD(target_dir_vp); 332 IHOLD(target_dp);
372 xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL); 333 xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
373 } 334 }
374 if ((src_ip != src_dp) && (src_ip != target_dp)) { 335 if ((src_ip != src_dp) && (src_ip != target_dp)) {
@@ -389,9 +350,8 @@ xfs_rename(
389 * If there's no space reservation, check the entry will 350 * If there's no space reservation, check the entry will
390 * fit before actually inserting it. 351 * fit before actually inserting it.
391 */ 352 */
392 if (spaceres == 0 && 353 error = xfs_dir_canenter(tp, target_dp, target_name, spaceres);
393 (error = xfs_dir_canenter(tp, target_dp, target_name, 354 if (error)
394 target_namelen)))
395 goto error_return; 355 goto error_return;
396 /* 356 /*
397 * If target does not exist and the rename crosses 357 * If target does not exist and the rename crosses
@@ -399,8 +359,8 @@ xfs_rename(
399 * to account for the ".." reference from the new entry. 359 * to account for the ".." reference from the new entry.
400 */ 360 */
401 error = xfs_dir_createname(tp, target_dp, target_name, 361 error = xfs_dir_createname(tp, target_dp, target_name,
402 target_namelen, src_ip->i_ino, 362 src_ip->i_ino, &first_block,
403 &first_block, &free_list, spaceres); 363 &free_list, spaceres);
404 if (error == ENOSPC) 364 if (error == ENOSPC)
405 goto error_return; 365 goto error_return;
406 if (error) 366 if (error)
@@ -439,7 +399,7 @@ xfs_rename(
439 * name at the destination directory, remove it first. 399 * name at the destination directory, remove it first.
440 */ 400 */
441 error = xfs_dir_replace(tp, target_dp, target_name, 401 error = xfs_dir_replace(tp, target_dp, target_name,
442 target_namelen, src_ip->i_ino, 402 src_ip->i_ino,
443 &first_block, &free_list, spaceres); 403 &first_block, &free_list, spaceres);
444 if (error) 404 if (error)
445 goto abort_return; 405 goto abort_return;
@@ -476,7 +436,8 @@ xfs_rename(
476 * Rewrite the ".." entry to point to the new 436 * Rewrite the ".." entry to point to the new
477 * directory. 437 * directory.
478 */ 438 */
479 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,
480 &first_block, &free_list, spaceres); 441 &first_block, &free_list, spaceres);
481 ASSERT(error != EEXIST); 442 ASSERT(error != EEXIST);
482 if (error) 443 if (error)
@@ -512,8 +473,8 @@ xfs_rename(
512 goto abort_return; 473 goto abort_return;
513 } 474 }
514 475
515 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,
516 src_ip->i_ino, &first_block, &free_list, spaceres); 477 &first_block, &free_list, spaceres);
517 if (error) 478 if (error)
518 goto abort_return; 479 goto abort_return;
519 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 480 xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -580,10 +541,8 @@ xfs_rename(
580 * the vnode references. 541 * the vnode references.
581 */ 542 */
582 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 543 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
583 if (target_ip != NULL) { 544 if (target_ip != NULL)
584 xfs_refcache_purge_ip(target_ip);
585 IRELE(target_ip); 545 IRELE(target_ip);
586 }
587 /* 546 /*
588 * Let interposed file systems know about removed links. 547 * Let interposed file systems know about removed links.
589 */ 548 */
@@ -598,9 +557,9 @@ std_return:
598 if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) || 557 if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) ||
599 DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) { 558 DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) {
600 (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME, 559 (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME,
601 src_dir_vp, DM_RIGHT_NULL, 560 src_dp, DM_RIGHT_NULL,
602 target_dir_vp, DM_RIGHT_NULL, 561 target_dp, DM_RIGHT_NULL,
603 src_name, target_name, 562 src_name->name, target_name->name,
604 0, error, 0); 563 0, error, 0);
605 } 564 }
606 return error; 565 return error;