diff options
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r-- | fs/xfs/xfs_iomap.c | 69 |
1 files changed, 30 insertions, 39 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 991f8a61f7c4..2edd6769e5d3 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -278,7 +278,9 @@ phase2: | |||
278 | switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { | 278 | switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { |
279 | case BMAPI_WRITE: | 279 | case BMAPI_WRITE: |
280 | /* If we found an extent, return it */ | 280 | /* If we found an extent, return it */ |
281 | if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) { | 281 | if (nimaps && |
282 | (imap.br_startblock != HOLESTARTBLOCK) && | ||
283 | (imap.br_startblock != DELAYSTARTBLOCK)) { | ||
282 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, | 284 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, |
283 | offset, count, iomapp, &imap, flags); | 285 | offset, count, iomapp, &imap, flags); |
284 | break; | 286 | break; |
@@ -383,15 +385,15 @@ xfs_iomap_write_direct( | |||
383 | int nimaps, maps; | 385 | int nimaps, maps; |
384 | int error; | 386 | int error; |
385 | int bmapi_flag; | 387 | int bmapi_flag; |
388 | int quota_flag; | ||
386 | int rt; | 389 | int rt; |
387 | xfs_trans_t *tp; | 390 | xfs_trans_t *tp; |
388 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; | 391 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; |
389 | xfs_bmap_free_t free_list; | 392 | xfs_bmap_free_t free_list; |
390 | int aeof; | 393 | int aeof; |
391 | xfs_filblks_t datablocks; | 394 | xfs_filblks_t datablocks, qblocks, resblks; |
392 | int committed; | 395 | int committed; |
393 | int numrtextents; | 396 | int numrtextents; |
394 | uint resblks; | ||
395 | 397 | ||
396 | /* | 398 | /* |
397 | * Make sure that the dquots are there. This doesn't hold | 399 | * Make sure that the dquots are there. This doesn't hold |
@@ -417,7 +419,6 @@ xfs_iomap_write_direct( | |||
417 | xfs_fileoff_t map_last_fsb; | 419 | xfs_fileoff_t map_last_fsb; |
418 | 420 | ||
419 | map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; | 421 | map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; |
420 | |||
421 | if (map_last_fsb < last_fsb) { | 422 | if (map_last_fsb < last_fsb) { |
422 | last_fsb = map_last_fsb; | 423 | last_fsb = map_last_fsb; |
423 | count_fsb = last_fsb - offset_fsb; | 424 | count_fsb = last_fsb - offset_fsb; |
@@ -426,56 +427,47 @@ xfs_iomap_write_direct( | |||
426 | } | 427 | } |
427 | 428 | ||
428 | /* | 429 | /* |
429 | * determine if reserving space on | 430 | * Determine if reserving space on the data or realtime partition. |
430 | * the data or realtime partition. | ||
431 | */ | 431 | */ |
432 | if ((rt = XFS_IS_REALTIME_INODE(ip))) { | 432 | if ((rt = XFS_IS_REALTIME_INODE(ip))) { |
433 | int sbrtextsize, iprtextsize; | 433 | xfs_extlen_t extsz; |
434 | 434 | ||
435 | sbrtextsize = mp->m_sb.sb_rextsize; | 435 | if (!(extsz = ip->i_d.di_extsize)) |
436 | iprtextsize = | 436 | extsz = mp->m_sb.sb_rextsize; |
437 | ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; | 437 | numrtextents = qblocks = (count_fsb + extsz - 1); |
438 | numrtextents = (count_fsb + iprtextsize - 1); | 438 | do_div(numrtextents, mp->m_sb.sb_rextsize); |
439 | do_div(numrtextents, sbrtextsize); | 439 | quota_flag = XFS_QMOPT_RES_RTBLKS; |
440 | datablocks = 0; | 440 | datablocks = 0; |
441 | } else { | 441 | } else { |
442 | datablocks = count_fsb; | 442 | datablocks = qblocks = count_fsb; |
443 | quota_flag = XFS_QMOPT_RES_REGBLKS; | ||
443 | numrtextents = 0; | 444 | numrtextents = 0; |
444 | } | 445 | } |
445 | 446 | ||
446 | /* | 447 | /* |
447 | * allocate and setup the transaction | 448 | * Allocate and setup the transaction |
448 | */ | 449 | */ |
449 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 450 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
450 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); | 451 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); |
451 | |||
452 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); | 452 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); |
453 | |||
454 | error = xfs_trans_reserve(tp, resblks, | 453 | error = xfs_trans_reserve(tp, resblks, |
455 | XFS_WRITE_LOG_RES(mp), numrtextents, | 454 | XFS_WRITE_LOG_RES(mp), numrtextents, |
456 | XFS_TRANS_PERM_LOG_RES, | 455 | XFS_TRANS_PERM_LOG_RES, |
457 | XFS_WRITE_LOG_COUNT); | 456 | XFS_WRITE_LOG_COUNT); |
458 | 457 | ||
459 | /* | 458 | /* |
460 | * check for running out of space | 459 | * Check for running out of space, note: need lock to return |
461 | */ | 460 | */ |
462 | if (error) | 461 | if (error) |
463 | /* | ||
464 | * Free the transaction structure. | ||
465 | */ | ||
466 | xfs_trans_cancel(tp, 0); | 462 | xfs_trans_cancel(tp, 0); |
467 | |||
468 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 463 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
469 | |||
470 | if (error) | 464 | if (error) |
471 | goto error_out; /* Don't return in above if .. trans .., | 465 | goto error_out; |
472 | need lock to return */ | ||
473 | 466 | ||
474 | if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { | 467 | if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) { |
475 | error = (EDQUOT); | 468 | error = (EDQUOT); |
476 | goto error1; | 469 | goto error1; |
477 | } | 470 | } |
478 | nimaps = 1; | ||
479 | 471 | ||
480 | bmapi_flag = XFS_BMAPI_WRITE; | 472 | bmapi_flag = XFS_BMAPI_WRITE; |
481 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 473 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
@@ -485,31 +477,29 @@ xfs_iomap_write_direct( | |||
485 | bmapi_flag |= XFS_BMAPI_PREALLOC; | 477 | bmapi_flag |= XFS_BMAPI_PREALLOC; |
486 | 478 | ||
487 | /* | 479 | /* |
488 | * issue the bmapi() call to allocate the blocks | 480 | * Issue the bmapi() call to allocate the blocks |
489 | */ | 481 | */ |
490 | XFS_BMAP_INIT(&free_list, &firstfsb); | 482 | XFS_BMAP_INIT(&free_list, &firstfsb); |
483 | nimaps = 1; | ||
491 | imapp = &imap[0]; | 484 | imapp = &imap[0]; |
492 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 485 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, |
493 | bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); | 486 | bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); |
494 | if (error) { | 487 | if (error) |
495 | goto error0; | 488 | goto error0; |
496 | } | ||
497 | 489 | ||
498 | /* | 490 | /* |
499 | * complete the transaction | 491 | * Complete the transaction |
500 | */ | 492 | */ |
501 | |||
502 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); | 493 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); |
503 | if (error) { | 494 | if (error) |
504 | goto error0; | 495 | goto error0; |
505 | } | ||
506 | |||
507 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); | 496 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); |
508 | if (error) { | 497 | if (error) |
509 | goto error_out; | 498 | goto error_out; |
510 | } | ||
511 | 499 | ||
512 | /* copy any maps to caller's array and return any error. */ | 500 | /* |
501 | * Copy any maps to caller's array and return any error. | ||
502 | */ | ||
513 | if (nimaps == 0) { | 503 | if (nimaps == 0) { |
514 | error = (ENOSPC); | 504 | error = (ENOSPC); |
515 | goto error_out; | 505 | goto error_out; |
@@ -528,10 +518,11 @@ xfs_iomap_write_direct( | |||
528 | } | 518 | } |
529 | return 0; | 519 | return 0; |
530 | 520 | ||
531 | error0: /* Cancel bmap, unlock inode, and cancel trans */ | 521 | error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ |
532 | xfs_bmap_cancel(&free_list); | 522 | xfs_bmap_cancel(&free_list); |
523 | XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag); | ||
533 | 524 | ||
534 | error1: /* Just cancel transaction */ | 525 | error1: /* Just cancel transaction */ |
535 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | 526 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); |
536 | *nmaps = 0; /* nothing set-up here */ | 527 | *nmaps = 0; /* nothing set-up here */ |
537 | 528 | ||