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.c82
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 */
84STATIC int 84STATIC int
85xfs_lock_for_rename( 85xfs_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(
218int 199int
219xfs_rename( 200xfs_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;