* This thread is responsible for two things: First, it retrieves the correct * blkptr in the to ds if we need to send the data because of something from * the from thread. As a result of this, we're the first ones to discover that * some indirect blocks can be discarded because they're not holes. Second, * it issues prefetches for the data we need to send. */
| 1732 | * it issues prefetches for the data we need to send. |
| 1733 | */ |
| 1734 | static void |
| 1735 | send_reader_thread(void *arg) |
| 1736 | { |
| 1737 | struct send_reader_thread_arg *srta = arg; |
| 1738 | struct send_merge_thread_arg *smta = srta->smta; |
| 1739 | bqueue_t *inq = &smta->q; |
| 1740 | bqueue_t *outq = &srta->q; |
| 1741 | objset_t *os = smta->os; |
| 1742 | fstrans_cookie_t cookie = spl_fstrans_mark(); |
| 1743 | struct send_range *range = bqueue_dequeue(inq); |
| 1744 | int err = 0; |
| 1745 | |
| 1746 | /* |
| 1747 | * If the record we're analyzing is from a redaction bookmark from the |
| 1748 | * fromds, then we need to know whether or not it exists in the tods so |
| 1749 | * we know whether to create records for it or not. If it does, we need |
| 1750 | * the datablksz so we can generate an appropriate record for it. |
| 1751 | * Finally, if it isn't redacted, we need the blkptr so that we can send |
| 1752 | * a WRITE record containing the actual data. |
| 1753 | */ |
| 1754 | uint64_t last_obj = UINT64_MAX; |
| 1755 | uint64_t last_obj_exists = B_TRUE; |
| 1756 | while (!range->eos_marker && !srta->cancel && smta->error == 0 && |
| 1757 | err == 0) { |
| 1758 | switch (range->type) { |
| 1759 | case DATA: |
| 1760 | issue_data_read(srta, range); |
| 1761 | bqueue_enqueue(outq, range, range->sru.data.datablksz); |
| 1762 | range = get_next_range_nofree(inq, range); |
| 1763 | break; |
| 1764 | case HOLE: |
| 1765 | case OBJECT: |
| 1766 | case OBJECT_RANGE: |
| 1767 | case REDACT: // Redacted blocks must exist |
| 1768 | bqueue_enqueue(outq, range, sizeof (*range)); |
| 1769 | range = get_next_range_nofree(inq, range); |
| 1770 | break; |
| 1771 | case PREVIOUSLY_REDACTED: { |
| 1772 | /* |
| 1773 | * This entry came from the "from bookmark" when |
| 1774 | * sending from a bookmark that has a redaction |
| 1775 | * list. We need to check if this object/blkid |
| 1776 | * exists in the target ("to") dataset, and if |
| 1777 | * not then we drop this entry. We also need |
| 1778 | * to fill in the block pointer so that we know |
| 1779 | * what to prefetch. |
| 1780 | * |
| 1781 | * To accomplish the above, we first cache whether or |
| 1782 | * not the last object we examined exists. If it |
| 1783 | * doesn't, we can drop this record. If it does, we hold |
| 1784 | * the dnode and use it to call dbuf_dnode_findbp. We do |
| 1785 | * this instead of dbuf_bookmark_findbp because we will |
| 1786 | * often operate on large ranges, and holding the dnode |
| 1787 | * once is more efficient. |
| 1788 | */ |
| 1789 | boolean_t object_exists = B_TRUE; |
| 1790 | /* |
| 1791 | * If the data is redacted, we only care if it exists, |
nothing calls this directly
no test coverage detected