aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-03-24 23:03:32 -0400
committerDave Chinner <david@fromorbit.com>2015-03-24 23:03:32 -0400
commit95afcf5c7bca93fb84d260f70c304f35ef4c3114 (patch)
tree00953639906542d16ddb87c1b07141debee5eb50
parent444a702231412e82fb1c09679adc159301e9242c (diff)
xfs: clean up inode locking for RENAME_WHITEOUT
When doing RENAME_WHITEOUT, we now have to lock 5 inodes into the rename transaction. This means we need to update xfs_sort_for_rename() and xfs_lock_inodes() to handle up to 5 inodes. Because of the vagaries of rename, this means we could have anywhere between 3 and 5 inodes locked into the transaction.... While xfs_lock_inodes() does not need anything other than an assert telling us we are passing more inodes that we ever thought we should see, it could do with a logic rework to remove all the indenting. This is not a functional change - it just makes the code a lot easier to read. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Eric Sandeen <sandeen@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/xfs_inode.c145
1 files changed, 67 insertions, 78 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index d0414f305967..d0a98bafcbac 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -329,15 +329,14 @@ xfs_lock_inumorder(int lock_mode, int subclass)
329} 329}
330 330
331/* 331/*
332 * The following routine will lock n inodes in exclusive mode. 332 * The following routine will lock n inodes in exclusive mode. We assume the
333 * We assume the caller calls us with the inodes in i_ino order. 333 * caller calls us with the inodes in i_ino order.
334 * 334 *
335 * We need to detect deadlock where an inode that we lock 335 * We need to detect deadlock where an inode that we lock is in the AIL and we
336 * is in the AIL and we start waiting for another inode that is locked 336 * start waiting for another inode that is locked by a thread in a long running
337 * by a thread in a long running transaction (such as truncate). This can 337 * transaction (such as truncate). This can result in deadlock since the long
338 * result in deadlock since the long running trans might need to wait 338 * running trans might need to wait for the inode we just locked in order to
339 * for the inode we just locked in order to push the tail and free space 339 * push the tail and free space in the log.
340 * in the log.
341 */ 340 */
342void 341void
343xfs_lock_inodes( 342xfs_lock_inodes(
@@ -348,30 +347,27 @@ xfs_lock_inodes(
348 int attempts = 0, i, j, try_lock; 347 int attempts = 0, i, j, try_lock;
349 xfs_log_item_t *lp; 348 xfs_log_item_t *lp;
350 349
351 ASSERT(ips && (inodes >= 2)); /* we need at least two */ 350 /* currently supports between 2 and 5 inodes */
351 ASSERT(ips && inodes >= 2 && inodes <= 5);
352 352
353 try_lock = 0; 353 try_lock = 0;
354 i = 0; 354 i = 0;
355
356again: 355again:
357 for (; i < inodes; i++) { 356 for (; i < inodes; i++) {
358 ASSERT(ips[i]); 357 ASSERT(ips[i]);
359 358
360 if (i && (ips[i] == ips[i-1])) /* Already locked */ 359 if (i && (ips[i] == ips[i - 1])) /* Already locked */
361 continue; 360 continue;
362 361
363 /* 362 /*
364 * If try_lock is not set yet, make sure all locked inodes 363 * If try_lock is not set yet, make sure all locked inodes are
365 * are not in the AIL. 364 * not in the AIL. If any are, set try_lock to be used later.
366 * If any are, set try_lock to be used later.
367 */ 365 */
368
369 if (!try_lock) { 366 if (!try_lock) {
370 for (j = (i - 1); j >= 0 && !try_lock; j--) { 367 for (j = (i - 1); j >= 0 && !try_lock; j--) {
371 lp = (xfs_log_item_t *)ips[j]->i_itemp; 368 lp = (xfs_log_item_t *)ips[j]->i_itemp;
372 if (lp && (lp->li_flags & XFS_LI_IN_AIL)) { 369 if (lp && (lp->li_flags & XFS_LI_IN_AIL))
373 try_lock++; 370 try_lock++;
374 }
375 } 371 }
376 } 372 }
377 373
@@ -381,51 +377,42 @@ again:
381 * we can't get any, we must release all we have 377 * we can't get any, we must release all we have
382 * and try again. 378 * and try again.
383 */ 379 */
380 if (!try_lock) {
381 xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
382 continue;
383 }
384
385 /* try_lock means we have an inode locked that is in the AIL. */
386 ASSERT(i != 0);
387 if (xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i)))
388 continue;
384 389
385 if (try_lock) { 390 /*
386 /* try_lock must be 0 if i is 0. */ 391 * Unlock all previous guys and try again. xfs_iunlock will try
392 * to push the tail if the inode is in the AIL.
393 */
394 attempts++;
395 for (j = i - 1; j >= 0; j--) {
387 /* 396 /*
388 * try_lock means we have an inode locked 397 * Check to see if we've already unlocked this one. Not
389 * that is in the AIL. 398 * the first one going back, and the inode ptr is the
399 * same.
390 */ 400 */
391 ASSERT(i != 0); 401 if (j != (i - 1) && ips[j] == ips[j + 1])
392 if (!xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i))) { 402 continue;
393 attempts++; 403
394 404 xfs_iunlock(ips[j], lock_mode);
395 /* 405 }
396 * Unlock all previous guys and try again.
397 * xfs_iunlock will try to push the tail
398 * if the inode is in the AIL.
399 */
400
401 for(j = i - 1; j >= 0; j--) {
402
403 /*
404 * Check to see if we've already
405 * unlocked this one.
406 * Not the first one going back,
407 * and the inode ptr is the same.
408 */
409 if ((j != (i - 1)) && ips[j] ==
410 ips[j+1])
411 continue;
412
413 xfs_iunlock(ips[j], lock_mode);
414 }
415 406
416 if ((attempts % 5) == 0) { 407 if ((attempts % 5) == 0) {
417 delay(1); /* Don't just spin the CPU */ 408 delay(1); /* Don't just spin the CPU */
418#ifdef DEBUG 409#ifdef DEBUG
419 xfs_lock_delays++; 410 xfs_lock_delays++;
420#endif 411#endif
421 }
422 i = 0;
423 try_lock = 0;
424 goto again;
425 }
426 } else {
427 xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
428 } 412 }
413 i = 0;
414 try_lock = 0;
415 goto again;
429 } 416 }
430 417
431#ifdef DEBUG 418#ifdef DEBUG
@@ -2615,19 +2602,22 @@ xfs_remove(
2615/* 2602/*
2616 * Enter all inodes for a rename transaction into a sorted array. 2603 * Enter all inodes for a rename transaction into a sorted array.
2617 */ 2604 */
2605#define __XFS_SORT_INODES 5
2618STATIC void 2606STATIC void
2619xfs_sort_for_rename( 2607xfs_sort_for_rename(
2620 xfs_inode_t *dp1, /* in: old (source) directory inode */ 2608 struct xfs_inode *dp1, /* in: old (source) directory inode */
2621 xfs_inode_t *dp2, /* in: new (target) directory inode */ 2609 struct xfs_inode *dp2, /* in: new (target) directory inode */
2622 xfs_inode_t *ip1, /* in: inode of old entry */ 2610 struct xfs_inode *ip1, /* in: inode of old entry */
2623 xfs_inode_t *ip2, /* in: inode of new entry, if it 2611 struct xfs_inode *ip2, /* in: inode of new entry */
2624 already exists, NULL otherwise. */ 2612 struct xfs_inode *wip, /* in: whiteout inode */
2625 xfs_inode_t **i_tab,/* out: array of inode returned, sorted */ 2613 struct xfs_inode **i_tab,/* out: sorted array of inodes */
2626 int *num_inodes) /* out: number of inodes in array */ 2614 int *num_inodes) /* in/out: inodes in array */
2627{ 2615{
2628 xfs_inode_t *temp;
2629 int i, j; 2616 int i, j;
2630 2617
2618 ASSERT(*num_inodes == __XFS_SORT_INODES);
2619 memset(i_tab, 0, *num_inodes * sizeof(struct xfs_inode *));
2620
2631 /* 2621 /*
2632 * i_tab contains a list of pointers to inodes. We initialize 2622 * i_tab contains a list of pointers to inodes. We initialize
2633 * the table here & we'll sort it. We will then use it to 2623 * the table here & we'll sort it. We will then use it to
@@ -2635,25 +2625,24 @@ xfs_sort_for_rename(
2635 * 2625 *
2636 * Note that the table may contain duplicates. e.g., dp1 == dp2. 2626 * Note that the table may contain duplicates. e.g., dp1 == dp2.
2637 */ 2627 */
2638 i_tab[0] = dp1; 2628 i = 0;
2639 i_tab[1] = dp2; 2629 i_tab[i++] = dp1;
2640 i_tab[2] = ip1; 2630 i_tab[i++] = dp2;
2641 if (ip2) { 2631 i_tab[i++] = ip1;
2642 *num_inodes = 4; 2632 if (ip2)
2643 i_tab[3] = ip2; 2633 i_tab[i++] = ip2;
2644 } else { 2634 if (wip)
2645 *num_inodes = 3; 2635 i_tab[i++] = wip;
2646 i_tab[3] = NULL; 2636 *num_inodes = i;
2647 }
2648 2637
2649 /* 2638 /*
2650 * Sort the elements via bubble sort. (Remember, there are at 2639 * Sort the elements via bubble sort. (Remember, there are at
2651 * most 4 elements to sort, so this is adequate.) 2640 * most 5 elements to sort, so this is adequate.)
2652 */ 2641 */
2653 for (i = 0; i < *num_inodes; i++) { 2642 for (i = 0; i < *num_inodes; i++) {
2654 for (j = 1; j < *num_inodes; j++) { 2643 for (j = 1; j < *num_inodes; j++) {
2655 if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) { 2644 if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {
2656 temp = i_tab[j]; 2645 struct xfs_inode *temp = i_tab[j];
2657 i_tab[j] = i_tab[j-1]; 2646 i_tab[j] = i_tab[j-1];
2658 i_tab[j-1] = temp; 2647 i_tab[j-1] = temp;
2659 } 2648 }
@@ -2801,16 +2790,16 @@ xfs_rename(
2801 xfs_fsblock_t first_block; 2790 xfs_fsblock_t first_block;
2802 int cancel_flags; 2791 int cancel_flags;
2803 int committed; 2792 int committed;
2804 xfs_inode_t *inodes[4]; 2793 xfs_inode_t *inodes[__XFS_SORT_INODES];
2794 int num_inodes = __XFS_SORT_INODES;
2805 int spaceres; 2795 int spaceres;
2806 int num_inodes;
2807 2796
2808 trace_xfs_rename(src_dp, target_dp, src_name, target_name); 2797 trace_xfs_rename(src_dp, target_dp, src_name, target_name);
2809 2798
2810 new_parent = (src_dp != target_dp); 2799 new_parent = (src_dp != target_dp);
2811 src_is_directory = S_ISDIR(src_ip->i_d.di_mode); 2800 src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
2812 2801
2813 xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip, 2802 xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip, NULL,
2814 inodes, &num_inodes); 2803 inodes, &num_inodes);
2815 2804
2816 xfs_bmap_init(&free_list, &first_block); 2805 xfs_bmap_init(&free_list, &first_block);