diff options
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 426 |
1 files changed, 234 insertions, 192 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 45a77a3a6c07..788917f355c4 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | #include "xfs_ialloc.h" | 40 | #include "xfs_ialloc.h" |
| 41 | #include "xfs_btree.h" | 41 | #include "xfs_btree.h" |
| 42 | #include "xfs_bmap.h" | 42 | #include "xfs_bmap.h" |
| 43 | #include "xfs_bit.h" | ||
| 44 | #include "xfs_rtalloc.h" | 43 | #include "xfs_rtalloc.h" |
| 45 | #include "xfs_error.h" | 44 | #include "xfs_error.h" |
| 46 | #include "xfs_itable.h" | 45 | #include "xfs_itable.h" |
| @@ -263,7 +262,7 @@ phase2: | |||
| 263 | case BMAPI_WRITE: | 262 | case BMAPI_WRITE: |
| 264 | /* If we found an extent, return it */ | 263 | /* If we found an extent, return it */ |
| 265 | if (nimaps && | 264 | if (nimaps && |
| 266 | (imap.br_startblock != HOLESTARTBLOCK) && | 265 | (imap.br_startblock != HOLESTARTBLOCK) && |
| 267 | (imap.br_startblock != DELAYSTARTBLOCK)) { | 266 | (imap.br_startblock != DELAYSTARTBLOCK)) { |
| 268 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, | 267 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, |
| 269 | offset, count, iomapp, &imap, flags); | 268 | offset, count, iomapp, &imap, flags); |
| @@ -318,6 +317,58 @@ out: | |||
| 318 | } | 317 | } |
| 319 | 318 | ||
| 320 | STATIC int | 319 | STATIC int |
| 320 | xfs_iomap_eof_align_last_fsb( | ||
| 321 | xfs_mount_t *mp, | ||
| 322 | xfs_iocore_t *io, | ||
| 323 | xfs_fsize_t isize, | ||
| 324 | xfs_extlen_t extsize, | ||
| 325 | xfs_fileoff_t *last_fsb) | ||
| 326 | { | ||
| 327 | xfs_fileoff_t new_last_fsb = 0; | ||
| 328 | xfs_extlen_t align; | ||
| 329 | int eof, error; | ||
| 330 | |||
| 331 | if (io->io_flags & XFS_IOCORE_RT) | ||
| 332 | ; | ||
| 333 | /* | ||
| 334 | * If mounted with the "-o swalloc" option, roundup the allocation | ||
| 335 | * request to a stripe width boundary if the file size is >= | ||
| 336 | * stripe width and we are allocating past the allocation eof. | ||
| 337 | */ | ||
| 338 | else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) && | ||
| 339 | (isize >= XFS_FSB_TO_B(mp, mp->m_swidth))) | ||
| 340 | new_last_fsb = roundup_64(*last_fsb, mp->m_swidth); | ||
| 341 | /* | ||
| 342 | * Roundup the allocation request to a stripe unit (m_dalign) boundary | ||
| 343 | * if the file size is >= stripe unit size, and we are allocating past | ||
| 344 | * the allocation eof. | ||
| 345 | */ | ||
| 346 | else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))) | ||
| 347 | new_last_fsb = roundup_64(*last_fsb, mp->m_dalign); | ||
| 348 | |||
| 349 | /* | ||
| 350 | * Always round up the allocation request to an extent boundary | ||
| 351 | * (when file on a real-time subvolume or has di_extsize hint). | ||
| 352 | */ | ||
| 353 | if (extsize) { | ||
| 354 | if (new_last_fsb) | ||
| 355 | align = roundup_64(new_last_fsb, extsize); | ||
| 356 | else | ||
| 357 | align = extsize; | ||
| 358 | new_last_fsb = roundup_64(*last_fsb, align); | ||
| 359 | } | ||
| 360 | |||
| 361 | if (new_last_fsb) { | ||
| 362 | error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); | ||
| 363 | if (error) | ||
| 364 | return error; | ||
| 365 | if (eof) | ||
| 366 | *last_fsb = new_last_fsb; | ||
| 367 | } | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | STATIC int | ||
| 321 | xfs_flush_space( | 372 | xfs_flush_space( |
| 322 | xfs_inode_t *ip, | 373 | xfs_inode_t *ip, |
| 323 | int *fsynced, | 374 | int *fsynced, |
| @@ -363,19 +414,20 @@ xfs_iomap_write_direct( | |||
| 363 | xfs_iocore_t *io = &ip->i_iocore; | 414 | xfs_iocore_t *io = &ip->i_iocore; |
| 364 | xfs_fileoff_t offset_fsb; | 415 | xfs_fileoff_t offset_fsb; |
| 365 | xfs_fileoff_t last_fsb; | 416 | xfs_fileoff_t last_fsb; |
| 366 | xfs_filblks_t count_fsb; | 417 | xfs_filblks_t count_fsb, resaligned; |
| 367 | xfs_fsblock_t firstfsb; | 418 | xfs_fsblock_t firstfsb; |
| 419 | xfs_extlen_t extsz, temp; | ||
| 420 | xfs_fsize_t isize; | ||
| 368 | int nimaps; | 421 | int nimaps; |
| 369 | int error; | ||
| 370 | int bmapi_flag; | 422 | int bmapi_flag; |
| 371 | int quota_flag; | 423 | int quota_flag; |
| 372 | int rt; | 424 | int rt; |
| 373 | xfs_trans_t *tp; | 425 | xfs_trans_t *tp; |
| 374 | xfs_bmbt_irec_t imap; | 426 | xfs_bmbt_irec_t imap; |
| 375 | xfs_bmap_free_t free_list; | 427 | xfs_bmap_free_t free_list; |
| 376 | xfs_filblks_t qblocks, resblks; | 428 | uint qblocks, resblks, resrtextents; |
| 377 | int committed; | 429 | int committed; |
| 378 | int resrtextents; | 430 | int error; |
| 379 | 431 | ||
| 380 | /* | 432 | /* |
| 381 | * Make sure that the dquots are there. This doesn't hold | 433 | * Make sure that the dquots are there. This doesn't hold |
| @@ -385,38 +437,53 @@ xfs_iomap_write_direct( | |||
| 385 | if (error) | 437 | if (error) |
| 386 | return XFS_ERROR(error); | 438 | return XFS_ERROR(error); |
| 387 | 439 | ||
| 388 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 440 | rt = XFS_IS_REALTIME_INODE(ip); |
| 389 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | 441 | if (unlikely(rt)) { |
| 390 | count_fsb = last_fsb - offset_fsb; | 442 | if (!(extsz = ip->i_d.di_extsize)) |
| 391 | if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { | 443 | extsz = mp->m_sb.sb_rextsize; |
| 392 | xfs_fileoff_t map_last_fsb; | 444 | } else { |
| 393 | 445 | extsz = ip->i_d.di_extsize; | |
| 394 | map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; | ||
| 395 | if (map_last_fsb < last_fsb) { | ||
| 396 | last_fsb = map_last_fsb; | ||
| 397 | count_fsb = last_fsb - offset_fsb; | ||
| 398 | } | ||
| 399 | ASSERT(count_fsb > 0); | ||
| 400 | } | 446 | } |
| 401 | 447 | ||
| 402 | /* | 448 | isize = ip->i_d.di_size; |
| 403 | * Determine if reserving space on the data or realtime partition. | 449 | if (io->io_new_size > isize) |
| 404 | */ | 450 | isize = io->io_new_size; |
| 405 | if ((rt = XFS_IS_REALTIME_INODE(ip))) { | ||
| 406 | xfs_extlen_t extsz; | ||
| 407 | 451 | ||
| 408 | if (!(extsz = ip->i_d.di_extsize)) | 452 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
| 409 | extsz = mp->m_sb.sb_rextsize; | 453 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); |
| 410 | resrtextents = qblocks = (count_fsb + extsz - 1); | 454 | if ((offset + count) > isize) { |
| 411 | do_div(resrtextents, mp->m_sb.sb_rextsize); | 455 | error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, |
| 412 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); | 456 | &last_fsb); |
| 413 | quota_flag = XFS_QMOPT_RES_RTBLKS; | 457 | if (error) |
| 458 | goto error_out; | ||
| 414 | } else { | 459 | } else { |
| 415 | resrtextents = 0; | 460 | if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) |
| 416 | resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, count_fsb); | 461 | last_fsb = MIN(last_fsb, (xfs_fileoff_t) |
| 417 | quota_flag = XFS_QMOPT_RES_REGBLKS; | 462 | ret_imap->br_blockcount + |
| 463 | ret_imap->br_startoff); | ||
| 464 | } | ||
| 465 | count_fsb = last_fsb - offset_fsb; | ||
| 466 | ASSERT(count_fsb > 0); | ||
| 467 | |||
| 468 | resaligned = count_fsb; | ||
| 469 | if (unlikely(extsz)) { | ||
| 470 | if ((temp = do_mod(offset_fsb, extsz))) | ||
| 471 | resaligned += temp; | ||
| 472 | if ((temp = do_mod(resaligned, extsz))) | ||
| 473 | resaligned += extsz - temp; | ||
| 418 | } | 474 | } |
| 419 | 475 | ||
| 476 | if (unlikely(rt)) { | ||
| 477 | resrtextents = qblocks = resaligned; | ||
| 478 | resrtextents /= mp->m_sb.sb_rextsize; | ||
| 479 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); | ||
| 480 | quota_flag = XFS_QMOPT_RES_RTBLKS; | ||
| 481 | } else { | ||
| 482 | resrtextents = 0; | ||
| 483 | resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned); | ||
| 484 | quota_flag = XFS_QMOPT_RES_REGBLKS; | ||
| 485 | } | ||
| 486 | |||
| 420 | /* | 487 | /* |
| 421 | * Allocate and setup the transaction | 488 | * Allocate and setup the transaction |
| 422 | */ | 489 | */ |
| @@ -426,7 +493,6 @@ xfs_iomap_write_direct( | |||
| 426 | XFS_WRITE_LOG_RES(mp), resrtextents, | 493 | XFS_WRITE_LOG_RES(mp), resrtextents, |
| 427 | XFS_TRANS_PERM_LOG_RES, | 494 | XFS_TRANS_PERM_LOG_RES, |
| 428 | XFS_WRITE_LOG_COUNT); | 495 | XFS_WRITE_LOG_COUNT); |
| 429 | |||
| 430 | /* | 496 | /* |
| 431 | * Check for running out of space, note: need lock to return | 497 | * Check for running out of space, note: need lock to return |
| 432 | */ | 498 | */ |
| @@ -436,20 +502,20 @@ xfs_iomap_write_direct( | |||
| 436 | if (error) | 502 | if (error) |
| 437 | goto error_out; | 503 | goto error_out; |
| 438 | 504 | ||
| 439 | if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) { | 505 | error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, |
| 440 | error = (EDQUOT); | 506 | qblocks, 0, quota_flag); |
| 507 | if (error) | ||
| 441 | goto error1; | 508 | goto error1; |
| 442 | } | ||
| 443 | 509 | ||
| 444 | bmapi_flag = XFS_BMAPI_WRITE; | ||
| 445 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 510 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
| 446 | xfs_trans_ihold(tp, ip); | 511 | xfs_trans_ihold(tp, ip); |
| 447 | 512 | ||
| 448 | if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) | 513 | bmapi_flag = XFS_BMAPI_WRITE; |
| 514 | if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz)) | ||
| 449 | bmapi_flag |= XFS_BMAPI_PREALLOC; | 515 | bmapi_flag |= XFS_BMAPI_PREALLOC; |
| 450 | 516 | ||
| 451 | /* | 517 | /* |
| 452 | * Issue the bmapi() call to allocate the blocks | 518 | * Issue the xfs_bmapi() call to allocate the blocks |
| 453 | */ | 519 | */ |
| 454 | XFS_BMAP_INIT(&free_list, &firstfsb); | 520 | XFS_BMAP_INIT(&free_list, &firstfsb); |
| 455 | nimaps = 1; | 521 | nimaps = 1; |
| @@ -484,8 +550,10 @@ xfs_iomap_write_direct( | |||
| 484 | "extent-state : %x \n", | 550 | "extent-state : %x \n", |
| 485 | (ip->i_mount)->m_fsname, | 551 | (ip->i_mount)->m_fsname, |
| 486 | (long long)ip->i_ino, | 552 | (long long)ip->i_ino, |
| 487 | ret_imap->br_startblock, ret_imap->br_startoff, | 553 | (unsigned long long)ret_imap->br_startblock, |
| 488 | ret_imap->br_blockcount,ret_imap->br_state); | 554 | (unsigned long long)ret_imap->br_startoff, |
| 555 | (unsigned long long)ret_imap->br_blockcount, | ||
| 556 | ret_imap->br_state); | ||
| 489 | } | 557 | } |
| 490 | return 0; | 558 | return 0; |
| 491 | 559 | ||
| @@ -501,6 +569,63 @@ error_out: | |||
| 501 | return XFS_ERROR(error); | 569 | return XFS_ERROR(error); |
| 502 | } | 570 | } |
| 503 | 571 | ||
| 572 | /* | ||
| 573 | * If the caller is doing a write at the end of the file, | ||
| 574 | * then extend the allocation out to the file system's write | ||
| 575 | * iosize. We clean up any extra space left over when the | ||
| 576 | * file is closed in xfs_inactive(). | ||
| 577 | * | ||
| 578 | * For sync writes, we are flushing delayed allocate space to | ||
| 579 | * try to make additional space available for allocation near | ||
| 580 | * the filesystem full boundary - preallocation hurts in that | ||
| 581 | * situation, of course. | ||
| 582 | */ | ||
| 583 | STATIC int | ||
| 584 | xfs_iomap_eof_want_preallocate( | ||
| 585 | xfs_mount_t *mp, | ||
| 586 | xfs_iocore_t *io, | ||
| 587 | xfs_fsize_t isize, | ||
| 588 | xfs_off_t offset, | ||
| 589 | size_t count, | ||
| 590 | int ioflag, | ||
| 591 | xfs_bmbt_irec_t *imap, | ||
| 592 | int nimaps, | ||
| 593 | int *prealloc) | ||
| 594 | { | ||
| 595 | xfs_fileoff_t start_fsb; | ||
| 596 | xfs_filblks_t count_fsb; | ||
| 597 | xfs_fsblock_t firstblock; | ||
| 598 | int n, error, imaps; | ||
| 599 | |||
| 600 | *prealloc = 0; | ||
| 601 | if ((ioflag & BMAPI_SYNC) || (offset + count) <= isize) | ||
| 602 | return 0; | ||
| 603 | |||
| 604 | /* | ||
| 605 | * If there are any real blocks past eof, then don't | ||
| 606 | * do any speculative allocation. | ||
| 607 | */ | ||
| 608 | start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1))); | ||
| 609 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | ||
| 610 | while (count_fsb > 0) { | ||
| 611 | imaps = nimaps; | ||
| 612 | firstblock = NULLFSBLOCK; | ||
| 613 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, | ||
| 614 | 0, &firstblock, 0, imap, &imaps, NULL); | ||
| 615 | if (error) | ||
| 616 | return error; | ||
| 617 | for (n = 0; n < imaps; n++) { | ||
| 618 | if ((imap[n].br_startblock != HOLESTARTBLOCK) && | ||
| 619 | (imap[n].br_startblock != DELAYSTARTBLOCK)) | ||
| 620 | return 0; | ||
| 621 | start_fsb += imap[n].br_blockcount; | ||
| 622 | count_fsb -= imap[n].br_blockcount; | ||
| 623 | } | ||
| 624 | } | ||
| 625 | *prealloc = 1; | ||
| 626 | return 0; | ||
| 627 | } | ||
| 628 | |||
| 504 | int | 629 | int |
| 505 | xfs_iomap_write_delay( | 630 | xfs_iomap_write_delay( |
| 506 | xfs_inode_t *ip, | 631 | xfs_inode_t *ip, |
| @@ -514,13 +639,15 @@ xfs_iomap_write_delay( | |||
| 514 | xfs_iocore_t *io = &ip->i_iocore; | 639 | xfs_iocore_t *io = &ip->i_iocore; |
| 515 | xfs_fileoff_t offset_fsb; | 640 | xfs_fileoff_t offset_fsb; |
| 516 | xfs_fileoff_t last_fsb; | 641 | xfs_fileoff_t last_fsb; |
| 517 | xfs_fsize_t isize; | 642 | xfs_off_t aligned_offset; |
| 643 | xfs_fileoff_t ioalign; | ||
| 518 | xfs_fsblock_t firstblock; | 644 | xfs_fsblock_t firstblock; |
| 645 | xfs_extlen_t extsz; | ||
| 646 | xfs_fsize_t isize; | ||
| 519 | int nimaps; | 647 | int nimaps; |
| 520 | int error; | ||
| 521 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; | 648 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; |
| 522 | int aeof; | 649 | int prealloc, fsynced = 0; |
| 523 | int fsynced = 0; | 650 | int error; |
| 524 | 651 | ||
| 525 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); | 652 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); |
| 526 | 653 | ||
| @@ -528,152 +655,57 @@ xfs_iomap_write_delay( | |||
| 528 | * Make sure that the dquots are there. This doesn't hold | 655 | * Make sure that the dquots are there. This doesn't hold |
| 529 | * the ilock across a disk read. | 656 | * the ilock across a disk read. |
| 530 | */ | 657 | */ |
| 531 | |||
| 532 | error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); | 658 | error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); |
| 533 | if (error) | 659 | if (error) |
| 534 | return XFS_ERROR(error); | 660 | return XFS_ERROR(error); |
| 535 | 661 | ||
| 662 | if (XFS_IS_REALTIME_INODE(ip)) { | ||
| 663 | if (!(extsz = ip->i_d.di_extsize)) | ||
| 664 | extsz = mp->m_sb.sb_rextsize; | ||
| 665 | } else { | ||
| 666 | extsz = ip->i_d.di_extsize; | ||
| 667 | } | ||
| 668 | |||
| 669 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
| 670 | |||
| 536 | retry: | 671 | retry: |
| 537 | isize = ip->i_d.di_size; | 672 | isize = ip->i_d.di_size; |
| 538 | if (io->io_new_size > isize) { | 673 | if (io->io_new_size > isize) |
| 539 | isize = io->io_new_size; | 674 | isize = io->io_new_size; |
| 540 | } | ||
| 541 | 675 | ||
| 542 | aeof = 0; | 676 | error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count, |
| 543 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 677 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); |
| 544 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | 678 | if (error) |
| 545 | /* | 679 | return error; |
| 546 | * If the caller is doing a write at the end of the file, | ||
| 547 | * then extend the allocation (and the buffer used for the write) | ||
| 548 | * out to the file system's write iosize. We clean up any extra | ||
| 549 | * space left over when the file is closed in xfs_inactive(). | ||
| 550 | * | ||
| 551 | * For sync writes, we are flushing delayed allocate space to | ||
| 552 | * try to make additional space available for allocation near | ||
| 553 | * the filesystem full boundary - preallocation hurts in that | ||
| 554 | * situation, of course. | ||
| 555 | */ | ||
| 556 | if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { | ||
| 557 | xfs_off_t aligned_offset; | ||
| 558 | xfs_filblks_t count_fsb; | ||
| 559 | unsigned int iosize; | ||
| 560 | xfs_fileoff_t ioalign; | ||
| 561 | int n; | ||
| 562 | xfs_fileoff_t start_fsb; | ||
| 563 | 680 | ||
| 564 | /* | 681 | if (prealloc) { |
| 565 | * If there are any real blocks past eof, then don't | ||
| 566 | * do any speculative allocation. | ||
| 567 | */ | ||
| 568 | start_fsb = XFS_B_TO_FSBT(mp, | ||
| 569 | ((xfs_ufsize_t)(offset + count - 1))); | ||
| 570 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | ||
| 571 | while (count_fsb > 0) { | ||
| 572 | nimaps = XFS_WRITE_IMAPS; | ||
| 573 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, | ||
| 574 | 0, &firstblock, 0, imap, &nimaps, NULL); | ||
| 575 | if (error) { | ||
| 576 | return error; | ||
| 577 | } | ||
| 578 | for (n = 0; n < nimaps; n++) { | ||
| 579 | if ( !(io->io_flags & XFS_IOCORE_RT) && | ||
| 580 | !imap[n].br_startblock) { | ||
| 581 | cmn_err(CE_PANIC,"Access to block " | ||
| 582 | "zero: fs <%s> inode: %lld " | ||
| 583 | "start_block : %llx start_off " | ||
| 584 | ": %llx blkcnt : %llx " | ||
| 585 | "extent-state : %x \n", | ||
| 586 | (ip->i_mount)->m_fsname, | ||
| 587 | (long long)ip->i_ino, | ||
| 588 | imap[n].br_startblock, | ||
| 589 | imap[n].br_startoff, | ||
| 590 | imap[n].br_blockcount, | ||
| 591 | imap[n].br_state); | ||
| 592 | } | ||
| 593 | if ((imap[n].br_startblock != HOLESTARTBLOCK) && | ||
| 594 | (imap[n].br_startblock != DELAYSTARTBLOCK)) { | ||
| 595 | goto write_map; | ||
| 596 | } | ||
| 597 | start_fsb += imap[n].br_blockcount; | ||
| 598 | count_fsb -= imap[n].br_blockcount; | ||
| 599 | } | ||
| 600 | } | ||
| 601 | iosize = mp->m_writeio_blocks; | ||
| 602 | aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); | 682 | aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); |
| 603 | ioalign = XFS_B_TO_FSBT(mp, aligned_offset); | 683 | ioalign = XFS_B_TO_FSBT(mp, aligned_offset); |
| 604 | last_fsb = ioalign + iosize; | 684 | last_fsb = ioalign + mp->m_writeio_blocks; |
| 605 | aeof = 1; | 685 | } else { |
| 686 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | ||
| 606 | } | 687 | } |
| 607 | write_map: | ||
| 608 | nimaps = XFS_WRITE_IMAPS; | ||
| 609 | firstblock = NULLFSBLOCK; | ||
| 610 | 688 | ||
| 611 | /* | 689 | if (prealloc || extsz) { |
| 612 | * If mounted with the "-o swalloc" option, roundup the allocation | 690 | error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, |
| 613 | * request to a stripe width boundary if the file size is >= | 691 | &last_fsb); |
| 614 | * stripe width and we are allocating past the allocation eof. | 692 | if (error) |
| 615 | */ | ||
| 616 | if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth | ||
| 617 | && (mp->m_flags & XFS_MOUNT_SWALLOC) | ||
| 618 | && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) { | ||
| 619 | int eof; | ||
| 620 | xfs_fileoff_t new_last_fsb; | ||
| 621 | |||
| 622 | new_last_fsb = roundup_64(last_fsb, mp->m_swidth); | ||
| 623 | error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); | ||
| 624 | if (error) { | ||
| 625 | return error; | ||
| 626 | } | ||
| 627 | if (eof) { | ||
| 628 | last_fsb = new_last_fsb; | ||
| 629 | } | ||
| 630 | /* | ||
| 631 | * Roundup the allocation request to a stripe unit (m_dalign) boundary | ||
| 632 | * if the file size is >= stripe unit size, and we are allocating past | ||
| 633 | * the allocation eof. | ||
| 634 | */ | ||
| 635 | } else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign && | ||
| 636 | (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) { | ||
| 637 | int eof; | ||
| 638 | xfs_fileoff_t new_last_fsb; | ||
| 639 | new_last_fsb = roundup_64(last_fsb, mp->m_dalign); | ||
| 640 | error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); | ||
| 641 | if (error) { | ||
| 642 | return error; | ||
| 643 | } | ||
| 644 | if (eof) { | ||
| 645 | last_fsb = new_last_fsb; | ||
| 646 | } | ||
| 647 | /* | ||
| 648 | * Round up the allocation request to a real-time extent boundary | ||
| 649 | * if the file is on the real-time subvolume. | ||
| 650 | */ | ||
| 651 | } else if (io->io_flags & XFS_IOCORE_RT && aeof) { | ||
| 652 | int eof; | ||
| 653 | xfs_fileoff_t new_last_fsb; | ||
| 654 | |||
| 655 | new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize); | ||
| 656 | error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); | ||
| 657 | if (error) { | ||
| 658 | return error; | 693 | return error; |
| 659 | } | ||
| 660 | if (eof) | ||
| 661 | last_fsb = new_last_fsb; | ||
| 662 | } | 694 | } |
| 695 | |||
| 696 | nimaps = XFS_WRITE_IMAPS; | ||
| 697 | firstblock = NULLFSBLOCK; | ||
| 663 | error = xfs_bmapi(NULL, ip, offset_fsb, | 698 | error = xfs_bmapi(NULL, ip, offset_fsb, |
| 664 | (xfs_filblks_t)(last_fsb - offset_fsb), | 699 | (xfs_filblks_t)(last_fsb - offset_fsb), |
| 665 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | | 700 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | |
| 666 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, | 701 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, |
| 667 | &nimaps, NULL); | 702 | &nimaps, NULL); |
| 668 | /* | 703 | if (error && (error != ENOSPC)) |
| 669 | * This can be EDQUOT, if nimaps == 0 | ||
| 670 | */ | ||
| 671 | if (error && (error != ENOSPC)) { | ||
| 672 | return XFS_ERROR(error); | 704 | return XFS_ERROR(error); |
| 673 | } | 705 | |
| 674 | /* | 706 | /* |
| 675 | * If bmapi returned us nothing, and if we didn't get back EDQUOT, | 707 | * If bmapi returned us nothing, and if we didn't get back EDQUOT, |
| 676 | * then we must have run out of space. | 708 | * then we must have run out of space - flush delalloc, and retry.. |
| 677 | */ | 709 | */ |
| 678 | if (nimaps == 0) { | 710 | if (nimaps == 0) { |
| 679 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, | 711 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, |
| @@ -685,17 +717,21 @@ write_map: | |||
| 685 | goto retry; | 717 | goto retry; |
| 686 | } | 718 | } |
| 687 | 719 | ||
| 688 | *ret_imap = imap[0]; | 720 | if (!(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { |
| 689 | *nmaps = 1; | ||
| 690 | if ( !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { | ||
| 691 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " | 721 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " |
| 692 | "start_block : %llx start_off : %llx blkcnt : %llx " | 722 | "start_block : %llx start_off : %llx blkcnt : %llx " |
| 693 | "extent-state : %x \n", | 723 | "extent-state : %x \n", |
| 694 | (ip->i_mount)->m_fsname, | 724 | (ip->i_mount)->m_fsname, |
| 695 | (long long)ip->i_ino, | 725 | (long long)ip->i_ino, |
| 696 | ret_imap->br_startblock, ret_imap->br_startoff, | 726 | (unsigned long long)ret_imap->br_startblock, |
| 697 | ret_imap->br_blockcount,ret_imap->br_state); | 727 | (unsigned long long)ret_imap->br_startoff, |
| 728 | (unsigned long long)ret_imap->br_blockcount, | ||
| 729 | ret_imap->br_state); | ||
| 698 | } | 730 | } |
| 731 | |||
| 732 | *ret_imap = imap[0]; | ||
| 733 | *nmaps = 1; | ||
| 734 | |||
| 699 | return 0; | 735 | return 0; |
| 700 | } | 736 | } |
| 701 | 737 | ||
| @@ -821,17 +857,21 @@ xfs_iomap_write_allocate( | |||
| 821 | */ | 857 | */ |
| 822 | 858 | ||
| 823 | for (i = 0; i < nimaps; i++) { | 859 | for (i = 0; i < nimaps; i++) { |
| 824 | if ( !(io->io_flags & XFS_IOCORE_RT) && | 860 | if (!(io->io_flags & XFS_IOCORE_RT) && |
| 825 | !imap[i].br_startblock) { | 861 | !imap[i].br_startblock) { |
| 826 | cmn_err(CE_PANIC,"Access to block zero: " | 862 | cmn_err(CE_PANIC,"Access to block zero: " |
| 827 | "fs <%s> inode: %lld " | 863 | "fs <%s> inode: %lld " |
| 828 | "start_block : %llx start_off : %llx " | 864 | "start_block : %llx start_off : %llx " |
| 829 | "blkcnt : %llx extent-state : %x \n", | 865 | "blkcnt : %llx extent-state : %x \n", |
| 830 | (ip->i_mount)->m_fsname, | 866 | (ip->i_mount)->m_fsname, |
| 831 | (long long)ip->i_ino, | 867 | (long long)ip->i_ino, |
| 832 | imap[i].br_startblock, | 868 | (unsigned long long) |
| 833 | imap[i].br_startoff, | 869 | imap[i].br_startblock, |
| 834 | imap[i].br_blockcount,imap[i].br_state); | 870 | (unsigned long long) |
| 871 | imap[i].br_startoff, | ||
| 872 | (unsigned long long) | ||
| 873 | imap[i].br_blockcount, | ||
| 874 | imap[i].br_state); | ||
| 835 | } | 875 | } |
| 836 | if ((offset_fsb >= imap[i].br_startoff) && | 876 | if ((offset_fsb >= imap[i].br_startoff) && |
| 837 | (offset_fsb < (imap[i].br_startoff + | 877 | (offset_fsb < (imap[i].br_startoff + |
| @@ -868,17 +908,17 @@ xfs_iomap_write_unwritten( | |||
| 868 | { | 908 | { |
| 869 | xfs_mount_t *mp = ip->i_mount; | 909 | xfs_mount_t *mp = ip->i_mount; |
| 870 | xfs_iocore_t *io = &ip->i_iocore; | 910 | xfs_iocore_t *io = &ip->i_iocore; |
| 871 | xfs_trans_t *tp; | ||
| 872 | xfs_fileoff_t offset_fsb; | 911 | xfs_fileoff_t offset_fsb; |
| 873 | xfs_filblks_t count_fsb; | 912 | xfs_filblks_t count_fsb; |
| 874 | xfs_filblks_t numblks_fsb; | 913 | xfs_filblks_t numblks_fsb; |
| 875 | xfs_bmbt_irec_t imap; | 914 | xfs_fsblock_t firstfsb; |
| 915 | int nimaps; | ||
| 916 | xfs_trans_t *tp; | ||
| 917 | xfs_bmbt_irec_t imap; | ||
| 918 | xfs_bmap_free_t free_list; | ||
| 919 | uint resblks; | ||
| 876 | int committed; | 920 | int committed; |
| 877 | int error; | 921 | int error; |
| 878 | int nres; | ||
| 879 | int nimaps; | ||
| 880 | xfs_fsblock_t firstfsb; | ||
| 881 | xfs_bmap_free_t free_list; | ||
| 882 | 922 | ||
| 883 | xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, | 923 | xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, |
| 884 | &ip->i_iocore, offset, count); | 924 | &ip->i_iocore, offset, count); |
| @@ -887,9 +927,9 @@ xfs_iomap_write_unwritten( | |||
| 887 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 927 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
| 888 | count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); | 928 | count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); |
| 889 | 929 | ||
| 890 | do { | 930 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; |
| 891 | nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); | ||
| 892 | 931 | ||
| 932 | do { | ||
| 893 | /* | 933 | /* |
| 894 | * set up a transaction to convert the range of extents | 934 | * set up a transaction to convert the range of extents |
| 895 | * from unwritten to real. Do allocations in a loop until | 935 | * from unwritten to real. Do allocations in a loop until |
| @@ -897,7 +937,7 @@ xfs_iomap_write_unwritten( | |||
| 897 | */ | 937 | */ |
| 898 | 938 | ||
| 899 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); | 939 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); |
| 900 | error = xfs_trans_reserve(tp, nres, | 940 | error = xfs_trans_reserve(tp, resblks, |
| 901 | XFS_WRITE_LOG_RES(mp), 0, | 941 | XFS_WRITE_LOG_RES(mp), 0, |
| 902 | XFS_TRANS_PERM_LOG_RES, | 942 | XFS_TRANS_PERM_LOG_RES, |
| 903 | XFS_WRITE_LOG_COUNT); | 943 | XFS_WRITE_LOG_COUNT); |
| @@ -916,7 +956,7 @@ xfs_iomap_write_unwritten( | |||
| 916 | XFS_BMAP_INIT(&free_list, &firstfsb); | 956 | XFS_BMAP_INIT(&free_list, &firstfsb); |
| 917 | nimaps = 1; | 957 | nimaps = 1; |
| 918 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 958 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, |
| 919 | XFS_BMAPI_WRITE, &firstfsb, | 959 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, |
| 920 | 1, &imap, &nimaps, &free_list); | 960 | 1, &imap, &nimaps, &free_list); |
| 921 | if (error) | 961 | if (error) |
| 922 | goto error_on_bmapi_transaction; | 962 | goto error_on_bmapi_transaction; |
| @@ -930,15 +970,17 @@ xfs_iomap_write_unwritten( | |||
| 930 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 970 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 931 | if (error) | 971 | if (error) |
| 932 | goto error0; | 972 | goto error0; |
| 933 | 973 | ||
| 934 | if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) { | 974 | if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) { |
| 935 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> " | 975 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> " |
| 936 | "inode: %lld start_block : %llx start_off : " | 976 | "inode: %lld start_block : %llx start_off : " |
| 937 | "%llx blkcnt : %llx extent-state : %x \n", | 977 | "%llx blkcnt : %llx extent-state : %x \n", |
| 938 | (ip->i_mount)->m_fsname, | 978 | (ip->i_mount)->m_fsname, |
| 939 | (long long)ip->i_ino, | 979 | (long long)ip->i_ino, |
| 940 | imap.br_startblock,imap.br_startoff, | 980 | (unsigned long long)imap.br_startblock, |
| 941 | imap.br_blockcount,imap.br_state); | 981 | (unsigned long long)imap.br_startoff, |
| 982 | (unsigned long long)imap.br_blockcount, | ||
| 983 | imap.br_state); | ||
| 942 | } | 984 | } |
| 943 | 985 | ||
| 944 | if ((numblks_fsb = imap.br_blockcount) == 0) { | 986 | if ((numblks_fsb = imap.br_blockcount) == 0) { |
