Print this page
4045 zfs write throttle & i/o scheduler performance work
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>


1771         mutex_enter(&dn->dn_mtx);
1772         space = DN_USED_BYTES(dn->dn_phys);
1773         if (delta > 0) {
1774                 ASSERT3U(space + delta, >=, space); /* no overflow */
1775         } else {
1776                 ASSERT3U(space, >=, -delta); /* no underflow */
1777         }
1778         space += delta;
1779         if (spa_version(dn->dn_objset->os_spa) < SPA_VERSION_DNODE_BYTES) {
1780                 ASSERT((dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) == 0);
1781                 ASSERT0(P2PHASE(space, 1<<DEV_BSHIFT));
1782                 dn->dn_phys->dn_used = space >> DEV_BSHIFT;
1783         } else {
1784                 dn->dn_phys->dn_used = space;
1785                 dn->dn_phys->dn_flags |= DNODE_FLAG_USED_BYTES;
1786         }
1787         mutex_exit(&dn->dn_mtx);
1788 }
1789 
1790 /*
1791  * Call when we think we're going to write/free space in open context.
1792  * Be conservative (ie. OK to write less than this or free more than
1793  * this, but don't write more or free less).
1794  */
1795 void
1796 dnode_willuse_space(dnode_t *dn, int64_t space, dmu_tx_t *tx)
1797 {
1798         objset_t *os = dn->dn_objset;
1799         dsl_dataset_t *ds = os->os_dsl_dataset;

1800 
1801         if (space > 0)
1802                 space = spa_get_asize(os->os_spa, space);


1803 
1804         if (ds)
1805                 dsl_dir_willuse_space(ds->ds_dir, space, tx);
1806 
1807         dmu_tx_willuse_space(tx, space);
1808 }
1809 
1810 /*
1811  * Scans a block at the indicated "level" looking for a hole or data,
1812  * depending on 'flags'.
1813  *
1814  * If level > 0, then we are scanning an indirect block looking at its
1815  * pointers.  If level == 0, then we are looking at a block of dnodes.
1816  *
1817  * If we don't find what we are looking for in the block, we return ESRCH.
1818  * Otherwise, return with *offset pointing to the beginning (if searching
1819  * forwards) or end (if searching backwards) of the range covered by the
1820  * block pointer we matched on (or dnode).
1821  *
1822  * The basic search algorithm used below by dnode_next_offset() is to
1823  * use this function to search up the block tree (widen the search) until
1824  * we find something (i.e., we don't return ESRCH) and then search back
1825  * down the tree (narrow the search) until we reach our original search
1826  * level.
1827  */




1771         mutex_enter(&dn->dn_mtx);
1772         space = DN_USED_BYTES(dn->dn_phys);
1773         if (delta > 0) {
1774                 ASSERT3U(space + delta, >=, space); /* no overflow */
1775         } else {
1776                 ASSERT3U(space, >=, -delta); /* no underflow */
1777         }
1778         space += delta;
1779         if (spa_version(dn->dn_objset->os_spa) < SPA_VERSION_DNODE_BYTES) {
1780                 ASSERT((dn->dn_phys->dn_flags & DNODE_FLAG_USED_BYTES) == 0);
1781                 ASSERT0(P2PHASE(space, 1<<DEV_BSHIFT));
1782                 dn->dn_phys->dn_used = space >> DEV_BSHIFT;
1783         } else {
1784                 dn->dn_phys->dn_used = space;
1785                 dn->dn_phys->dn_flags |= DNODE_FLAG_USED_BYTES;
1786         }
1787         mutex_exit(&dn->dn_mtx);
1788 }
1789 
1790 /*
1791  * Call when we think we're going to write/free space in open context to track
1792  * the amount of memory in use by the currently open txg.

1793  */
1794 void
1795 dnode_willuse_space(dnode_t *dn, int64_t space, dmu_tx_t *tx)
1796 {
1797         objset_t *os = dn->dn_objset;
1798         dsl_dataset_t *ds = os->os_dsl_dataset;
1799         int64_t aspace = spa_get_asize(os->os_spa, space);
1800 
1801         if (ds != NULL) {
1802                 dsl_dir_willuse_space(ds->ds_dir, aspace, tx);
1803                 dsl_pool_dirty_space(dmu_tx_pool(tx), space, tx);
1804         }
1805 
1806         dmu_tx_willuse_space(tx, aspace);



1807 }
1808 
1809 /*
1810  * Scans a block at the indicated "level" looking for a hole or data,
1811  * depending on 'flags'.
1812  *
1813  * If level > 0, then we are scanning an indirect block looking at its
1814  * pointers.  If level == 0, then we are looking at a block of dnodes.
1815  *
1816  * If we don't find what we are looking for in the block, we return ESRCH.
1817  * Otherwise, return with *offset pointing to the beginning (if searching
1818  * forwards) or end (if searching backwards) of the range covered by the
1819  * block pointer we matched on (or dnode).
1820  *
1821  * The basic search algorithm used below by dnode_next_offset() is to
1822  * use this function to search up the block tree (widen the search) until
1823  * we find something (i.e., we don't return ESRCH) and then search back
1824  * down the tree (narrow the search) until we reach our original search
1825  * level.
1826  */