552 } else {
553 nblks = (offset < dn->dn_datablksz);
554 }
555
556 if (nblks != 0) {
557 blkid = dbuf_whichblock(dn, offset);
558 for (i = 0; i < nblks; i++)
559 dbuf_prefetch(dn, blkid+i);
560 }
561
562 rw_exit(&dn->dn_struct_rwlock);
563
564 dnode_rele(dn, FTAG);
565 }
566
567 /*
568 * Get the next "chunk" of file data to free. We traverse the file from
569 * the end so that the file gets shorter over time (if we crashes in the
570 * middle, this will leave us in a better state). We find allocated file
571 * data by simply searching the allocated level 1 indirects.
572 */
573 static int
574 get_next_chunk(dnode_t *dn, uint64_t *start, uint64_t limit)
575 {
576 uint64_t len = *start - limit;
577 uint64_t blkcnt = 0;
578 uint64_t maxblks = DMU_MAX_ACCESS / (1ULL << (dn->dn_indblkshift + 1));
579 uint64_t iblkrange =
580 dn->dn_datablksz * EPB(dn->dn_indblkshift, SPA_BLKPTRSHIFT);
581
582 ASSERT(limit <= *start);
583
584 if (len <= iblkrange * maxblks) {
585 *start = limit;
586 return (0);
587 }
588 ASSERT(ISP2(iblkrange));
589
590 while (*start > limit && blkcnt < maxblks) {
591 int err;
592
593 /* find next allocated L1 indirect */
594 err = dnode_next_offset(dn,
595 DNODE_FIND_BACKWARDS, start, 2, 1, 0);
596
597 /* if there are no more, then we are done */
598 if (err == ESRCH) {
599 *start = limit;
600 return (0);
601 } else if (err) {
602 return (err);
603 }
604 blkcnt += 1;
605
606 /* reset offset to end of "next" block back */
607 *start = P2ALIGN(*start, iblkrange);
608 if (*start <= limit)
609 *start = limit;
610 else
611 *start -= 1;
612 }
613 return (0);
614 }
615
616 static int
617 dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
618 uint64_t length, boolean_t free_dnode)
619 {
620 dmu_tx_t *tx;
621 uint64_t object_size, start, end, len;
622 boolean_t trunc = (length == DMU_OBJECT_END);
623 int align, err;
624
625 align = 1 << dn->dn_datablkshift;
626 ASSERT(align > 0);
627 object_size = align == 1 ? dn->dn_datablksz :
628 (dn->dn_maxblkid + 1) << dn->dn_datablkshift;
629
630 end = offset + length;
631 if (trunc || end > object_size)
632 end = object_size;
633 if (end <= offset)
634 return (0);
635 length = end - offset;
636
637 while (length) {
638 start = end;
639 /* assert(offset <= start) */
640 err = get_next_chunk(dn, &start, offset);
641 if (err)
642 return (err);
643 len = trunc ? DMU_OBJECT_END : end - start;
644
645 tx = dmu_tx_create(os);
646 dmu_tx_hold_free(tx, dn->dn_object, start, len);
647 err = dmu_tx_assign(tx, TXG_WAIT);
648 if (err) {
649 dmu_tx_abort(tx);
650 return (err);
651 }
652
653 dnode_free_range(dn, start, trunc ? -1 : len, tx);
654
655 if (start == 0 && free_dnode) {
656 ASSERT(trunc);
657 dnode_free(dn, tx);
658 }
659
660 length -= end - start;
661
662 dmu_tx_commit(tx);
663 end = start;
664 }
665 return (0);
666 }
667
668 int
669 dmu_free_long_range(objset_t *os, uint64_t object,
670 uint64_t offset, uint64_t length)
671 {
672 dnode_t *dn;
673 int err;
674
675 err = dnode_hold(os, object, FTAG, &dn);
676 if (err != 0)
677 return (err);
678 err = dmu_free_long_range_impl(os, dn, offset, length, FALSE);
679 dnode_rele(dn, FTAG);
680 return (err);
681 }
682
683 int
684 dmu_free_object(objset_t *os, uint64_t object)
685 {
686 dnode_t *dn;
687 dmu_tx_t *tx;
688 int err;
689
690 err = dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED,
691 FTAG, &dn);
692 if (err != 0)
693 return (err);
694 if (dn->dn_nlevels == 1) {
695 tx = dmu_tx_create(os);
696 dmu_tx_hold_bonus(tx, object);
697 dmu_tx_hold_free(tx, dn->dn_object, 0, DMU_OBJECT_END);
698 err = dmu_tx_assign(tx, TXG_WAIT);
699 if (err == 0) {
700 dnode_free_range(dn, 0, DMU_OBJECT_END, tx);
701 dnode_free(dn, tx);
702 dmu_tx_commit(tx);
703 } else {
704 dmu_tx_abort(tx);
705 }
706 } else {
707 err = dmu_free_long_range_impl(os, dn, 0, DMU_OBJECT_END, TRUE);
708 }
709 dnode_rele(dn, FTAG);
710 return (err);
711 }
712
713 int
714 dmu_free_range(objset_t *os, uint64_t object, uint64_t offset,
715 uint64_t size, dmu_tx_t *tx)
716 {
717 dnode_t *dn;
718 int err = dnode_hold(os, object, FTAG, &dn);
719 if (err)
720 return (err);
721 ASSERT(offset < UINT64_MAX);
722 ASSERT(size == -1ULL || size <= UINT64_MAX - offset);
723 dnode_free_range(dn, offset, size, tx);
724 dnode_rele(dn, FTAG);
725 return (0);
726 }
727
728 int
729 dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
552 } else {
553 nblks = (offset < dn->dn_datablksz);
554 }
555
556 if (nblks != 0) {
557 blkid = dbuf_whichblock(dn, offset);
558 for (i = 0; i < nblks; i++)
559 dbuf_prefetch(dn, blkid+i);
560 }
561
562 rw_exit(&dn->dn_struct_rwlock);
563
564 dnode_rele(dn, FTAG);
565 }
566
567 /*
568 * Get the next "chunk" of file data to free. We traverse the file from
569 * the end so that the file gets shorter over time (if we crashes in the
570 * middle, this will leave us in a better state). We find allocated file
571 * data by simply searching the allocated level 1 indirects.
572 *
573 * On input, *start should be the first offset that does not need to be
574 * freed (e.g. "offset + length"). On return, *start will be the first
575 * offset that should be freed.
576 */
577 static int
578 get_next_chunk(dnode_t *dn, uint64_t *start, uint64_t minimum)
579 {
580 uint64_t maxblks = DMU_MAX_ACCESS >> (dn->dn_indblkshift + 1);
581 /* bytes of data covered by a level-1 indirect block */
582 uint64_t iblkrange =
583 dn->dn_datablksz * EPB(dn->dn_indblkshift, SPA_BLKPTRSHIFT);
584
585 ASSERT3U(minimum, <=, *start);
586
587 if (*start - minimum <= iblkrange * maxblks) {
588 *start = minimum;
589 return (0);
590 }
591 ASSERT(ISP2(iblkrange));
592
593 for (uint64_t blks = 0; *start > minimum && blks < maxblks; blks++) {
594 int err;
595
596 /*
597 * dnode_next_offset(BACKWARDS) will find an allocated L1
598 * indirect block at or before the input offset. We must
599 * decrement *start so that it is at the end of the region
600 * to search.
601 */
602 (*start)--;
603 err = dnode_next_offset(dn,
604 DNODE_FIND_BACKWARDS, start, 2, 1, 0);
605
606 /* if there are no indirect blocks before start, we are done */
607 if (err == ESRCH) {
608 *start = minimum;
609 break;
610 } else if (err != 0) {
611 return (err);
612 }
613
614 /* set start to the beginning of this L1 indirect */
615 *start = P2ALIGN(*start, iblkrange);
616 }
617 if (*start < minimum)
618 *start = minimum;
619 return (0);
620 }
621
622 static int
623 dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
624 uint64_t length)
625 {
626 uint64_t object_size = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
627 int err;
628
629 if (offset >= object_size)
630 return (0);
631
632 if (length == DMU_OBJECT_END || offset + length > object_size)
633 length = object_size - offset;
634
635 while (length != 0) {
636 uint64_t chunk_end, chunk_begin;
637
638 chunk_end = chunk_begin = offset + length;
639
640 /* move chunk_begin backwards to the beginning of this chunk */
641 err = get_next_chunk(dn, &chunk_begin, offset);
642 if (err)
643 return (err);
644 ASSERT3U(chunk_begin, >=, offset);
645 ASSERT3U(chunk_begin, <=, chunk_end);
646
647 dmu_tx_t *tx = dmu_tx_create(os);
648 dmu_tx_hold_free(tx, dn->dn_object,
649 chunk_begin, chunk_end - chunk_begin);
650 err = dmu_tx_assign(tx, TXG_WAIT);
651 if (err) {
652 dmu_tx_abort(tx);
653 return (err);
654 }
655 dnode_free_range(dn, chunk_begin, chunk_end - chunk_begin, tx);
656 dmu_tx_commit(tx);
657
658 length -= chunk_end - chunk_begin;
659 }
660 return (0);
661 }
662
663 int
664 dmu_free_long_range(objset_t *os, uint64_t object,
665 uint64_t offset, uint64_t length)
666 {
667 dnode_t *dn;
668 int err;
669
670 err = dnode_hold(os, object, FTAG, &dn);
671 if (err != 0)
672 return (err);
673 err = dmu_free_long_range_impl(os, dn, offset, length);
674 dnode_rele(dn, FTAG);
675 return (err);
676 }
677
678 int
679 dmu_free_long_object(objset_t *os, uint64_t object)
680 {
681 dmu_tx_t *tx;
682 int err;
683
684 err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
685 if (err != 0)
686 return (err);
687
688 tx = dmu_tx_create(os);
689 dmu_tx_hold_bonus(tx, object);
690 dmu_tx_hold_free(tx, object, 0, DMU_OBJECT_END);
691 err = dmu_tx_assign(tx, TXG_WAIT);
692 if (err == 0) {
693 err = dmu_object_free(os, object, tx);
694 dmu_tx_commit(tx);
695 } else {
696 dmu_tx_abort(tx);
697 }
698
699 return (err);
700 }
701
702 int
703 dmu_free_range(objset_t *os, uint64_t object, uint64_t offset,
704 uint64_t size, dmu_tx_t *tx)
705 {
706 dnode_t *dn;
707 int err = dnode_hold(os, object, FTAG, &dn);
708 if (err)
709 return (err);
710 ASSERT(offset < UINT64_MAX);
711 ASSERT(size == -1ULL || size <= UINT64_MAX - offset);
712 dnode_free_range(dn, offset, size, tx);
713 dnode_rele(dn, FTAG);
714 return (0);
715 }
716
717 int
718 dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|