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