diff options
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 20 | ||||
| -rw-r--r-- | fs/xfs/xfs_export.c | 8 | ||||
| -rw-r--r-- | fs/xfs/xfs_log.c | 348 | ||||
| -rw-r--r-- | fs/xfs/xfs_trace.h | 12 |
4 files changed, 200 insertions, 188 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index c68baeb0974a..d0ab78837057 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -2383,6 +2383,8 @@ xfs_bmap_btalloc( | |||
| 2383 | int tryagain; | 2383 | int tryagain; |
| 2384 | int error; | 2384 | int error; |
| 2385 | 2385 | ||
| 2386 | ASSERT(ap->length); | ||
| 2387 | |||
| 2386 | mp = ap->ip->i_mount; | 2388 | mp = ap->ip->i_mount; |
| 2387 | align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; | 2389 | align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; |
| 2388 | if (unlikely(align)) { | 2390 | if (unlikely(align)) { |
| @@ -4629,6 +4631,8 @@ xfs_bmapi_allocate( | |||
| 4629 | int error; | 4631 | int error; |
| 4630 | int rt; | 4632 | int rt; |
| 4631 | 4633 | ||
| 4634 | ASSERT(bma->length > 0); | ||
| 4635 | |||
| 4632 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip); | 4636 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip); |
| 4633 | 4637 | ||
| 4634 | /* | 4638 | /* |
| @@ -4849,6 +4853,7 @@ xfs_bmapi_write( | |||
| 4849 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); | 4853 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); |
| 4850 | ASSERT(!(flags & XFS_BMAPI_IGSTATE)); | 4854 | ASSERT(!(flags & XFS_BMAPI_IGSTATE)); |
| 4851 | ASSERT(tp != NULL); | 4855 | ASSERT(tp != NULL); |
| 4856 | ASSERT(len > 0); | ||
| 4852 | 4857 | ||
| 4853 | whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | 4858 | whichfork = (flags & XFS_BMAPI_ATTRFORK) ? |
| 4854 | XFS_ATTR_FORK : XFS_DATA_FORK; | 4859 | XFS_ATTR_FORK : XFS_DATA_FORK; |
| @@ -4918,9 +4923,22 @@ xfs_bmapi_write( | |||
| 4918 | bma.eof = eof; | 4923 | bma.eof = eof; |
| 4919 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); | 4924 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); |
| 4920 | bma.wasdel = wasdelay; | 4925 | bma.wasdel = wasdelay; |
| 4921 | bma.length = len; | ||
| 4922 | bma.offset = bno; | 4926 | bma.offset = bno; |
| 4923 | 4927 | ||
| 4928 | /* | ||
| 4929 | * There's a 32/64 bit type mismatch between the | ||
| 4930 | * allocation length request (which can be 64 bits in | ||
| 4931 | * length) and the bma length request, which is | ||
| 4932 | * xfs_extlen_t and therefore 32 bits. Hence we have to | ||
| 4933 | * check for 32-bit overflows and handle them here. | ||
| 4934 | */ | ||
| 4935 | if (len > (xfs_filblks_t)MAXEXTLEN) | ||
| 4936 | bma.length = MAXEXTLEN; | ||
| 4937 | else | ||
| 4938 | bma.length = len; | ||
| 4939 | |||
| 4940 | ASSERT(len > 0); | ||
| 4941 | ASSERT(bma.length > 0); | ||
| 4924 | error = xfs_bmapi_allocate(&bma, flags); | 4942 | error = xfs_bmapi_allocate(&bma, flags); |
| 4925 | if (error) | 4943 | if (error) |
| 4926 | goto error0; | 4944 | goto error0; |
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index da108977b21f..558910f5e3c0 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c | |||
| @@ -98,22 +98,22 @@ xfs_fs_encode_fh( | |||
| 98 | switch (fileid_type) { | 98 | switch (fileid_type) { |
| 99 | case FILEID_INO32_GEN_PARENT: | 99 | case FILEID_INO32_GEN_PARENT: |
| 100 | spin_lock(&dentry->d_lock); | 100 | spin_lock(&dentry->d_lock); |
| 101 | fid->i32.parent_ino = dentry->d_parent->d_inode->i_ino; | 101 | fid->i32.parent_ino = XFS_I(dentry->d_parent->d_inode)->i_ino; |
| 102 | fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; | 102 | fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; |
| 103 | spin_unlock(&dentry->d_lock); | 103 | spin_unlock(&dentry->d_lock); |
| 104 | /*FALLTHRU*/ | 104 | /*FALLTHRU*/ |
| 105 | case FILEID_INO32_GEN: | 105 | case FILEID_INO32_GEN: |
| 106 | fid->i32.ino = inode->i_ino; | 106 | fid->i32.ino = XFS_I(inode)->i_ino; |
| 107 | fid->i32.gen = inode->i_generation; | 107 | fid->i32.gen = inode->i_generation; |
| 108 | break; | 108 | break; |
| 109 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | 109 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: |
| 110 | spin_lock(&dentry->d_lock); | 110 | spin_lock(&dentry->d_lock); |
| 111 | fid64->parent_ino = dentry->d_parent->d_inode->i_ino; | 111 | fid64->parent_ino = XFS_I(dentry->d_parent->d_inode)->i_ino; |
| 112 | fid64->parent_gen = dentry->d_parent->d_inode->i_generation; | 112 | fid64->parent_gen = dentry->d_parent->d_inode->i_generation; |
| 113 | spin_unlock(&dentry->d_lock); | 113 | spin_unlock(&dentry->d_lock); |
| 114 | /*FALLTHRU*/ | 114 | /*FALLTHRU*/ |
| 115 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | 115 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: |
| 116 | fid64->ino = inode->i_ino; | 116 | fid64->ino = XFS_I(inode)->i_ino; |
| 117 | fid64->gen = inode->i_generation; | 117 | fid64->gen = inode->i_generation; |
| 118 | break; | 118 | break; |
| 119 | } | 119 | } |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index a14cd89fe465..34817adf4b9e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -150,6 +150,117 @@ xlog_grant_add_space( | |||
| 150 | } while (head_val != old); | 150 | } while (head_val != old); |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | STATIC bool | ||
| 154 | xlog_reserveq_wake( | ||
| 155 | struct log *log, | ||
| 156 | int *free_bytes) | ||
| 157 | { | ||
| 158 | struct xlog_ticket *tic; | ||
| 159 | int need_bytes; | ||
| 160 | |||
| 161 | list_for_each_entry(tic, &log->l_reserveq, t_queue) { | ||
| 162 | if (tic->t_flags & XLOG_TIC_PERM_RESERV) | ||
| 163 | need_bytes = tic->t_unit_res * tic->t_cnt; | ||
| 164 | else | ||
| 165 | need_bytes = tic->t_unit_res; | ||
| 166 | |||
| 167 | if (*free_bytes < need_bytes) | ||
| 168 | return false; | ||
| 169 | *free_bytes -= need_bytes; | ||
| 170 | |||
| 171 | trace_xfs_log_grant_wake_up(log, tic); | ||
| 172 | wake_up(&tic->t_wait); | ||
| 173 | } | ||
| 174 | |||
| 175 | return true; | ||
| 176 | } | ||
| 177 | |||
| 178 | STATIC bool | ||
| 179 | xlog_writeq_wake( | ||
| 180 | struct log *log, | ||
| 181 | int *free_bytes) | ||
| 182 | { | ||
| 183 | struct xlog_ticket *tic; | ||
| 184 | int need_bytes; | ||
| 185 | |||
| 186 | list_for_each_entry(tic, &log->l_writeq, t_queue) { | ||
| 187 | ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); | ||
| 188 | |||
| 189 | need_bytes = tic->t_unit_res; | ||
| 190 | |||
| 191 | if (*free_bytes < need_bytes) | ||
| 192 | return false; | ||
| 193 | *free_bytes -= need_bytes; | ||
| 194 | |||
| 195 | trace_xfs_log_regrant_write_wake_up(log, tic); | ||
| 196 | wake_up(&tic->t_wait); | ||
| 197 | } | ||
| 198 | |||
| 199 | return true; | ||
| 200 | } | ||
| 201 | |||
| 202 | STATIC int | ||
| 203 | xlog_reserveq_wait( | ||
| 204 | struct log *log, | ||
| 205 | struct xlog_ticket *tic, | ||
| 206 | int need_bytes) | ||
| 207 | { | ||
| 208 | list_add_tail(&tic->t_queue, &log->l_reserveq); | ||
| 209 | |||
| 210 | do { | ||
| 211 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 212 | goto shutdown; | ||
| 213 | xlog_grant_push_ail(log, need_bytes); | ||
| 214 | |||
| 215 | XFS_STATS_INC(xs_sleep_logspace); | ||
| 216 | trace_xfs_log_grant_sleep(log, tic); | ||
| 217 | |||
| 218 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); | ||
| 219 | trace_xfs_log_grant_wake(log, tic); | ||
| 220 | |||
| 221 | spin_lock(&log->l_grant_reserve_lock); | ||
| 222 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 223 | goto shutdown; | ||
| 224 | } while (xlog_space_left(log, &log->l_grant_reserve_head) < need_bytes); | ||
| 225 | |||
| 226 | list_del_init(&tic->t_queue); | ||
| 227 | return 0; | ||
| 228 | shutdown: | ||
| 229 | list_del_init(&tic->t_queue); | ||
| 230 | return XFS_ERROR(EIO); | ||
| 231 | } | ||
| 232 | |||
| 233 | STATIC int | ||
| 234 | xlog_writeq_wait( | ||
| 235 | struct log *log, | ||
| 236 | struct xlog_ticket *tic, | ||
| 237 | int need_bytes) | ||
| 238 | { | ||
| 239 | list_add_tail(&tic->t_queue, &log->l_writeq); | ||
| 240 | |||
| 241 | do { | ||
| 242 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 243 | goto shutdown; | ||
| 244 | xlog_grant_push_ail(log, need_bytes); | ||
| 245 | |||
| 246 | XFS_STATS_INC(xs_sleep_logspace); | ||
| 247 | trace_xfs_log_regrant_write_sleep(log, tic); | ||
| 248 | |||
| 249 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); | ||
| 250 | trace_xfs_log_regrant_write_wake(log, tic); | ||
| 251 | |||
| 252 | spin_lock(&log->l_grant_write_lock); | ||
| 253 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 254 | goto shutdown; | ||
| 255 | } while (xlog_space_left(log, &log->l_grant_write_head) < need_bytes); | ||
| 256 | |||
| 257 | list_del_init(&tic->t_queue); | ||
| 258 | return 0; | ||
| 259 | shutdown: | ||
| 260 | list_del_init(&tic->t_queue); | ||
| 261 | return XFS_ERROR(EIO); | ||
| 262 | } | ||
| 263 | |||
| 153 | static void | 264 | static void |
| 154 | xlog_tic_reset_res(xlog_ticket_t *tic) | 265 | xlog_tic_reset_res(xlog_ticket_t *tic) |
| 155 | { | 266 | { |
| @@ -350,8 +461,19 @@ xfs_log_reserve( | |||
| 350 | retval = xlog_grant_log_space(log, internal_ticket); | 461 | retval = xlog_grant_log_space(log, internal_ticket); |
| 351 | } | 462 | } |
| 352 | 463 | ||
| 464 | if (unlikely(retval)) { | ||
| 465 | /* | ||
| 466 | * If we are failing, make sure the ticket doesn't have any | ||
| 467 | * current reservations. We don't want to add this back | ||
| 468 | * when the ticket/ transaction gets cancelled. | ||
| 469 | */ | ||
| 470 | internal_ticket->t_curr_res = 0; | ||
| 471 | /* ungrant will give back unit_res * t_cnt. */ | ||
| 472 | internal_ticket->t_cnt = 0; | ||
| 473 | } | ||
| 474 | |||
| 353 | return retval; | 475 | return retval; |
| 354 | } /* xfs_log_reserve */ | 476 | } |
| 355 | 477 | ||
| 356 | 478 | ||
| 357 | /* | 479 | /* |
| @@ -2481,8 +2603,8 @@ restart: | |||
| 2481 | /* | 2603 | /* |
| 2482 | * Atomically get the log space required for a log ticket. | 2604 | * Atomically get the log space required for a log ticket. |
| 2483 | * | 2605 | * |
| 2484 | * Once a ticket gets put onto the reserveq, it will only return after | 2606 | * Once a ticket gets put onto the reserveq, it will only return after the |
| 2485 | * the needed reservation is satisfied. | 2607 | * needed reservation is satisfied. |
| 2486 | * | 2608 | * |
| 2487 | * This function is structured so that it has a lock free fast path. This is | 2609 | * This function is structured so that it has a lock free fast path. This is |
| 2488 | * necessary because every new transaction reservation will come through this | 2610 | * necessary because every new transaction reservation will come through this |
| @@ -2490,113 +2612,53 @@ restart: | |||
| 2490 | * every pass. | 2612 | * every pass. |
| 2491 | * | 2613 | * |
| 2492 | * As tickets are only ever moved on and off the reserveq under the | 2614 | * As tickets are only ever moved on and off the reserveq under the |
| 2493 | * l_grant_reserve_lock, we only need to take that lock if we are going | 2615 | * l_grant_reserve_lock, we only need to take that lock if we are going to add |
| 2494 | * to add the ticket to the queue and sleep. We can avoid taking the lock if the | 2616 | * the ticket to the queue and sleep. We can avoid taking the lock if the ticket |
| 2495 | * ticket was never added to the reserveq because the t_queue list head will be | 2617 | * was never added to the reserveq because the t_queue list head will be empty |
| 2496 | * empty and we hold the only reference to it so it can safely be checked | 2618 | * and we hold the only reference to it so it can safely be checked unlocked. |
| 2497 | * unlocked. | ||
| 2498 | */ | 2619 | */ |
| 2499 | STATIC int | 2620 | STATIC int |
| 2500 | xlog_grant_log_space(xlog_t *log, | 2621 | xlog_grant_log_space( |
| 2501 | xlog_ticket_t *tic) | 2622 | struct log *log, |
| 2623 | struct xlog_ticket *tic) | ||
| 2502 | { | 2624 | { |
| 2503 | int free_bytes; | 2625 | int free_bytes, need_bytes; |
| 2504 | int need_bytes; | 2626 | int error = 0; |
| 2505 | 2627 | ||
| 2506 | #ifdef DEBUG | 2628 | ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY)); |
| 2507 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | ||
| 2508 | panic("grant Recovery problem"); | ||
| 2509 | #endif | ||
| 2510 | 2629 | ||
| 2511 | trace_xfs_log_grant_enter(log, tic); | 2630 | trace_xfs_log_grant_enter(log, tic); |
| 2512 | 2631 | ||
| 2632 | /* | ||
| 2633 | * If there are other waiters on the queue then give them a chance at | ||
| 2634 | * logspace before us. Wake up the first waiters, if we do not wake | ||
| 2635 | * up all the waiters then go to sleep waiting for more free space, | ||
| 2636 | * otherwise try to get some space for this transaction. | ||
| 2637 | */ | ||
| 2513 | need_bytes = tic->t_unit_res; | 2638 | need_bytes = tic->t_unit_res; |
| 2514 | if (tic->t_flags & XFS_LOG_PERM_RESERV) | 2639 | if (tic->t_flags & XFS_LOG_PERM_RESERV) |
| 2515 | need_bytes *= tic->t_ocnt; | 2640 | need_bytes *= tic->t_ocnt; |
| 2516 | |||
| 2517 | /* something is already sleeping; insert new transaction at end */ | ||
| 2518 | if (!list_empty_careful(&log->l_reserveq)) { | ||
| 2519 | spin_lock(&log->l_grant_reserve_lock); | ||
| 2520 | /* recheck the queue now we are locked */ | ||
| 2521 | if (list_empty(&log->l_reserveq)) { | ||
| 2522 | spin_unlock(&log->l_grant_reserve_lock); | ||
| 2523 | goto redo; | ||
| 2524 | } | ||
| 2525 | list_add_tail(&tic->t_queue, &log->l_reserveq); | ||
| 2526 | |||
| 2527 | trace_xfs_log_grant_sleep1(log, tic); | ||
| 2528 | |||
| 2529 | /* | ||
| 2530 | * Gotta check this before going to sleep, while we're | ||
| 2531 | * holding the grant lock. | ||
| 2532 | */ | ||
| 2533 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 2534 | goto error_return; | ||
| 2535 | |||
| 2536 | XFS_STATS_INC(xs_sleep_logspace); | ||
| 2537 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); | ||
| 2538 | |||
| 2539 | /* | ||
| 2540 | * If we got an error, and the filesystem is shutting down, | ||
| 2541 | * we'll catch it down below. So just continue... | ||
| 2542 | */ | ||
| 2543 | trace_xfs_log_grant_wake1(log, tic); | ||
| 2544 | } | ||
| 2545 | |||
| 2546 | redo: | ||
| 2547 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 2548 | goto error_return_unlocked; | ||
| 2549 | |||
| 2550 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); | 2641 | free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); |
| 2551 | if (free_bytes < need_bytes) { | 2642 | if (!list_empty_careful(&log->l_reserveq)) { |
| 2552 | spin_lock(&log->l_grant_reserve_lock); | 2643 | spin_lock(&log->l_grant_reserve_lock); |
| 2553 | if (list_empty(&tic->t_queue)) | 2644 | if (!xlog_reserveq_wake(log, &free_bytes) || |
| 2554 | list_add_tail(&tic->t_queue, &log->l_reserveq); | 2645 | free_bytes < need_bytes) |
| 2555 | 2646 | error = xlog_reserveq_wait(log, tic, need_bytes); | |
| 2556 | trace_xfs_log_grant_sleep2(log, tic); | 2647 | spin_unlock(&log->l_grant_reserve_lock); |
| 2557 | 2648 | } else if (free_bytes < need_bytes) { | |
| 2558 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 2559 | goto error_return; | ||
| 2560 | |||
| 2561 | xlog_grant_push_ail(log, need_bytes); | ||
| 2562 | |||
| 2563 | XFS_STATS_INC(xs_sleep_logspace); | ||
| 2564 | xlog_wait(&tic->t_wait, &log->l_grant_reserve_lock); | ||
| 2565 | |||
| 2566 | trace_xfs_log_grant_wake2(log, tic); | ||
| 2567 | goto redo; | ||
| 2568 | } | ||
| 2569 | |||
| 2570 | if (!list_empty(&tic->t_queue)) { | ||
| 2571 | spin_lock(&log->l_grant_reserve_lock); | 2649 | spin_lock(&log->l_grant_reserve_lock); |
| 2572 | list_del_init(&tic->t_queue); | 2650 | error = xlog_reserveq_wait(log, tic, need_bytes); |
| 2573 | spin_unlock(&log->l_grant_reserve_lock); | 2651 | spin_unlock(&log->l_grant_reserve_lock); |
| 2574 | } | 2652 | } |
| 2653 | if (error) | ||
| 2654 | return error; | ||
| 2575 | 2655 | ||
| 2576 | /* we've got enough space */ | ||
| 2577 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); | 2656 | xlog_grant_add_space(log, &log->l_grant_reserve_head, need_bytes); |
| 2578 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | 2657 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); |
| 2579 | trace_xfs_log_grant_exit(log, tic); | 2658 | trace_xfs_log_grant_exit(log, tic); |
| 2580 | xlog_verify_grant_tail(log); | 2659 | xlog_verify_grant_tail(log); |
| 2581 | return 0; | 2660 | return 0; |
| 2582 | 2661 | } | |
| 2583 | error_return_unlocked: | ||
| 2584 | spin_lock(&log->l_grant_reserve_lock); | ||
| 2585 | error_return: | ||
| 2586 | list_del_init(&tic->t_queue); | ||
| 2587 | spin_unlock(&log->l_grant_reserve_lock); | ||
| 2588 | trace_xfs_log_grant_error(log, tic); | ||
| 2589 | |||
| 2590 | /* | ||
| 2591 | * If we are failing, make sure the ticket doesn't have any | ||
| 2592 | * current reservations. We don't want to add this back when | ||
| 2593 | * the ticket/transaction gets cancelled. | ||
| 2594 | */ | ||
| 2595 | tic->t_curr_res = 0; | ||
| 2596 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ | ||
| 2597 | return XFS_ERROR(EIO); | ||
| 2598 | } /* xlog_grant_log_space */ | ||
| 2599 | |||
| 2600 | 2662 | ||
| 2601 | /* | 2663 | /* |
| 2602 | * Replenish the byte reservation required by moving the grant write head. | 2664 | * Replenish the byte reservation required by moving the grant write head. |
| @@ -2605,10 +2667,12 @@ error_return: | |||
| 2605 | * free fast path. | 2667 | * free fast path. |
| 2606 | */ | 2668 | */ |
| 2607 | STATIC int | 2669 | STATIC int |
| 2608 | xlog_regrant_write_log_space(xlog_t *log, | 2670 | xlog_regrant_write_log_space( |
| 2609 | xlog_ticket_t *tic) | 2671 | struct log *log, |
| 2672 | struct xlog_ticket *tic) | ||
| 2610 | { | 2673 | { |
| 2611 | int free_bytes, need_bytes; | 2674 | int free_bytes, need_bytes; |
| 2675 | int error = 0; | ||
| 2612 | 2676 | ||
| 2613 | tic->t_curr_res = tic->t_unit_res; | 2677 | tic->t_curr_res = tic->t_unit_res; |
| 2614 | xlog_tic_reset_res(tic); | 2678 | xlog_tic_reset_res(tic); |
| @@ -2616,104 +2680,38 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
| 2616 | if (tic->t_cnt > 0) | 2680 | if (tic->t_cnt > 0) |
| 2617 | return 0; | 2681 | return 0; |
| 2618 | 2682 | ||
| 2619 | #ifdef DEBUG | 2683 | ASSERT(!(log->l_flags & XLOG_ACTIVE_RECOVERY)); |
| 2620 | if (log->l_flags & XLOG_ACTIVE_RECOVERY) | ||
| 2621 | panic("regrant Recovery problem"); | ||
| 2622 | #endif | ||
| 2623 | 2684 | ||
| 2624 | trace_xfs_log_regrant_write_enter(log, tic); | 2685 | trace_xfs_log_regrant_write_enter(log, tic); |
| 2625 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 2626 | goto error_return_unlocked; | ||
| 2627 | 2686 | ||
| 2628 | /* If there are other waiters on the queue then give them a | 2687 | /* |
| 2629 | * chance at logspace before us. Wake up the first waiters, | 2688 | * If there are other waiters on the queue then give them a chance at |
| 2630 | * if we do not wake up all the waiters then go to sleep waiting | 2689 | * logspace before us. Wake up the first waiters, if we do not wake |
| 2631 | * for more free space, otherwise try to get some space for | 2690 | * up all the waiters then go to sleep waiting for more free space, |
| 2632 | * this transaction. | 2691 | * otherwise try to get some space for this transaction. |
| 2633 | */ | 2692 | */ |
| 2634 | need_bytes = tic->t_unit_res; | 2693 | need_bytes = tic->t_unit_res; |
| 2635 | if (!list_empty_careful(&log->l_writeq)) { | ||
| 2636 | struct xlog_ticket *ntic; | ||
| 2637 | |||
| 2638 | spin_lock(&log->l_grant_write_lock); | ||
| 2639 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); | ||
| 2640 | list_for_each_entry(ntic, &log->l_writeq, t_queue) { | ||
| 2641 | ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV); | ||
| 2642 | |||
| 2643 | if (free_bytes < ntic->t_unit_res) | ||
| 2644 | break; | ||
| 2645 | free_bytes -= ntic->t_unit_res; | ||
| 2646 | wake_up(&ntic->t_wait); | ||
| 2647 | } | ||
| 2648 | |||
| 2649 | if (ntic != list_first_entry(&log->l_writeq, | ||
| 2650 | struct xlog_ticket, t_queue)) { | ||
| 2651 | if (list_empty(&tic->t_queue)) | ||
| 2652 | list_add_tail(&tic->t_queue, &log->l_writeq); | ||
| 2653 | trace_xfs_log_regrant_write_sleep1(log, tic); | ||
| 2654 | |||
| 2655 | xlog_grant_push_ail(log, need_bytes); | ||
| 2656 | |||
| 2657 | XFS_STATS_INC(xs_sleep_logspace); | ||
| 2658 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); | ||
| 2659 | trace_xfs_log_regrant_write_wake1(log, tic); | ||
| 2660 | } else | ||
| 2661 | spin_unlock(&log->l_grant_write_lock); | ||
| 2662 | } | ||
| 2663 | |||
| 2664 | redo: | ||
| 2665 | if (XLOG_FORCED_SHUTDOWN(log)) | ||
| 2666 | goto error_return_unlocked; | ||
| 2667 | |||
| 2668 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); | 2694 | free_bytes = xlog_space_left(log, &log->l_grant_write_head); |
| 2669 | if (free_bytes < need_bytes) { | 2695 | if (!list_empty_careful(&log->l_writeq)) { |
| 2670 | spin_lock(&log->l_grant_write_lock); | 2696 | spin_lock(&log->l_grant_write_lock); |
| 2671 | if (list_empty(&tic->t_queue)) | 2697 | if (!xlog_writeq_wake(log, &free_bytes) || |
| 2672 | list_add_tail(&tic->t_queue, &log->l_writeq); | 2698 | free_bytes < need_bytes) |
| 2673 | 2699 | error = xlog_writeq_wait(log, tic, need_bytes); | |
| 2674 | if (XLOG_FORCED_SHUTDOWN(log)) | 2700 | spin_unlock(&log->l_grant_write_lock); |
| 2675 | goto error_return; | 2701 | } else if (free_bytes < need_bytes) { |
| 2676 | |||
| 2677 | xlog_grant_push_ail(log, need_bytes); | ||
| 2678 | |||
| 2679 | XFS_STATS_INC(xs_sleep_logspace); | ||
| 2680 | trace_xfs_log_regrant_write_sleep2(log, tic); | ||
| 2681 | xlog_wait(&tic->t_wait, &log->l_grant_write_lock); | ||
| 2682 | |||
| 2683 | trace_xfs_log_regrant_write_wake2(log, tic); | ||
| 2684 | goto redo; | ||
| 2685 | } | ||
| 2686 | |||
| 2687 | if (!list_empty(&tic->t_queue)) { | ||
| 2688 | spin_lock(&log->l_grant_write_lock); | 2702 | spin_lock(&log->l_grant_write_lock); |
| 2689 | list_del_init(&tic->t_queue); | 2703 | error = xlog_writeq_wait(log, tic, need_bytes); |
| 2690 | spin_unlock(&log->l_grant_write_lock); | 2704 | spin_unlock(&log->l_grant_write_lock); |
| 2691 | } | 2705 | } |
| 2692 | 2706 | ||
| 2693 | /* we've got enough space */ | 2707 | if (error) |
| 2708 | return error; | ||
| 2709 | |||
| 2694 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); | 2710 | xlog_grant_add_space(log, &log->l_grant_write_head, need_bytes); |
| 2695 | trace_xfs_log_regrant_write_exit(log, tic); | 2711 | trace_xfs_log_regrant_write_exit(log, tic); |
| 2696 | xlog_verify_grant_tail(log); | 2712 | xlog_verify_grant_tail(log); |
| 2697 | return 0; | 2713 | return 0; |
| 2698 | 2714 | } | |
| 2699 | |||
| 2700 | error_return_unlocked: | ||
| 2701 | spin_lock(&log->l_grant_write_lock); | ||
| 2702 | error_return: | ||
| 2703 | list_del_init(&tic->t_queue); | ||
| 2704 | spin_unlock(&log->l_grant_write_lock); | ||
| 2705 | trace_xfs_log_regrant_write_error(log, tic); | ||
| 2706 | |||
| 2707 | /* | ||
| 2708 | * If we are failing, make sure the ticket doesn't have any | ||
| 2709 | * current reservations. We don't want to add this back when | ||
| 2710 | * the ticket/transaction gets cancelled. | ||
| 2711 | */ | ||
| 2712 | tic->t_curr_res = 0; | ||
| 2713 | tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */ | ||
| 2714 | return XFS_ERROR(EIO); | ||
| 2715 | } /* xlog_regrant_write_log_space */ | ||
| 2716 | |||
| 2717 | 2715 | ||
| 2718 | /* The first cnt-1 times through here we don't need to | 2716 | /* The first cnt-1 times through here we don't need to |
| 2719 | * move the grant write head because the permanent | 2717 | * move the grant write head because the permanent |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index f1d2802b2f07..494035798873 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
| @@ -834,18 +834,14 @@ DEFINE_LOGGRANT_EVENT(xfs_log_umount_write); | |||
| 834 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_enter); | 834 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_enter); |
| 835 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_exit); | 835 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_exit); |
| 836 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_error); | 836 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_error); |
| 837 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep1); | 837 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep); |
| 838 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake1); | 838 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake); |
| 839 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep2); | ||
| 840 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake2); | ||
| 841 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up); | 839 | DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up); |
| 842 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); | 840 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter); |
| 843 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); | 841 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit); |
| 844 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); | 842 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error); |
| 845 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep1); | 843 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep); |
| 846 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake1); | 844 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake); |
| 847 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_sleep2); | ||
| 848 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake2); | ||
| 849 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake_up); | 845 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_wake_up); |
| 850 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); | 846 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter); |
| 851 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); | 847 | DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit); |
