diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2006-01-24 15:34:47 -0500 |
commit | 0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch) | |
tree | 7b42490a676cf39ae0691b6859ecf7fd410f229b /fs/xfs/xfs_iomap.c | |
parent | 4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff) | |
parent | 3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff) |
Merge with /home/shaggy/git/linus-clean/
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) { |