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