Print this page
zpool import speedup

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dmu_objset.c
          +++ new/usr/src/uts/common/fs/zfs/dmu_objset.c
↓ open down ↓ 39 lines elided ↑ open up ↑
  40   40  #include <sys/dbuf.h>
  41   41  #include <sys/zvol.h>
  42   42  #include <sys/dmu_tx.h>
  43   43  #include <sys/zap.h>
  44   44  #include <sys/zil.h>
  45   45  #include <sys/dmu_impl.h>
  46   46  #include <sys/zfs_ioctl.h>
  47   47  #include <sys/sa.h>
  48   48  #include <sys/zfs_onexit.h>
  49   49  #include <sys/dsl_destroy.h>
       50 +#include <sys/vdev.h>
  50   51  
  51   52  /*
  52   53   * Needed to close a window in dnode_move() that allows the objset to be freed
  53   54   * before it can be safely accessed.
  54   55   */
  55   56  krwlock_t os_lock;
  56   57  
  57   58  void
  58   59  dmu_objset_init(void)
  59   60  {
↓ open down ↓ 399 lines elided ↑ open up ↑
 459  460          }
 460  461          *osp = ds->ds_objset;
 461  462          mutex_exit(&ds->ds_opening_lock);
 462  463          return (err);
 463  464  }
 464  465  
 465  466  /*
 466  467   * Holds the pool while the objset is held.  Therefore only one objset
 467  468   * can be held at a time.
 468  469   */
 469      -int
 470      -dmu_objset_hold(const char *name, void *tag, objset_t **osp)
      470 +static int
      471 +dmu_objset_hold_impl(const char *name, void *tag, objset_t **osp, int lock)
 471  472  {
 472  473          dsl_pool_t *dp;
 473  474          dsl_dataset_t *ds;
 474  475          int err;
 475  476  
 476      -        err = dsl_pool_hold(name, tag, &dp);
      477 +        err = dsl_pool_hold_lock(name, tag, &dp, lock);
 477  478          if (err != 0)
 478  479                  return (err);
 479  480          err = dsl_dataset_hold(dp, name, tag, &ds);
 480  481          if (err != 0) {
 481  482                  dsl_pool_rele(dp, tag);
 482  483                  return (err);
 483  484          }
 484  485  
 485  486          err = dmu_objset_from_ds(ds, osp);
 486  487          if (err != 0) {
 487  488                  dsl_dataset_rele(ds, tag);
 488  489                  dsl_pool_rele(dp, tag);
 489  490          }
 490  491  
 491  492          return (err);
 492  493  }
 493  494  
      495 +int
      496 +dmu_objset_hold(const char *name, void *tag, objset_t **osp)
      497 +{
      498 +        return (dmu_objset_hold_impl(name, tag, osp, 1));
      499 +}
      500 +
      501 +int
      502 +dmu_objset_hold_nolock(const char *name, void *tag, objset_t **osp)
      503 +{
      504 +        return (dmu_objset_hold_impl(name, tag, osp, 0));
      505 +}
      506 +
 494  507  /*
 495  508   * dsl_pool must not be held when this is called.
 496  509   * Upon successful return, there will be a longhold on the dataset,
 497  510   * and the dsl_pool will not be held.
 498  511   */
 499      -int
 500      -dmu_objset_own(const char *name, dmu_objset_type_t type,
 501      -    boolean_t readonly, void *tag, objset_t **osp)
      512 +static int
      513 +dmu_objset_own_impl(const char *name, dmu_objset_type_t type,
      514 +    boolean_t readonly, void *tag, objset_t **osp, int lock)
 502  515  {
 503  516          dsl_pool_t *dp;
 504  517          dsl_dataset_t *ds;
 505  518          int err;
 506  519  
 507      -        err = dsl_pool_hold(name, FTAG, &dp);
      520 +        err = dsl_pool_hold_lock(name, FTAG, &dp, lock);
 508  521          if (err != 0)
 509  522                  return (err);
 510  523          err = dsl_dataset_own(dp, name, tag, &ds);
 511  524          if (err != 0) {
 512  525                  dsl_pool_rele(dp, FTAG);
 513  526                  return (err);
 514  527          }
 515  528  
 516  529          err = dmu_objset_from_ds(ds, osp);
 517  530          dsl_pool_rele(dp, FTAG);
↓ open down ↓ 2 lines elided ↑ open up ↑
 520  533          } else if (type != DMU_OST_ANY && type != (*osp)->os_phys->os_type) {
 521  534                  dsl_dataset_disown(ds, tag);
 522  535                  return (SET_ERROR(EINVAL));
 523  536          } else if (!readonly && dsl_dataset_is_snapshot(ds)) {
 524  537                  dsl_dataset_disown(ds, tag);
 525  538                  return (SET_ERROR(EROFS));
 526  539          }
 527  540          return (err);
 528  541  }
 529  542  
      543 +int
      544 +dmu_objset_own(const char *name, dmu_objset_type_t type,
      545 +    boolean_t readonly, void *tag, objset_t **osp)
      546 +{
      547 +        return (dmu_objset_own_impl(name, type, readonly, tag, osp, 1));
      548 +}
      549 +
      550 +int
      551 +dmu_objset_own_nolock(const char *name, dmu_objset_type_t type,
      552 +    boolean_t readonly, void *tag, objset_t **osp)
      553 +{
      554 +        return (dmu_objset_own_impl(name, type, readonly, tag, osp, 0));
      555 +}
      556 +
 530  557  void
 531  558  dmu_objset_rele(objset_t *os, void *tag)
 532  559  {
 533  560          dsl_pool_t *dp = dmu_objset_pool(os);
 534  561          dsl_dataset_rele(os->os_dsl_dataset, tag);
 535  562          dsl_pool_rele(dp, tag);
 536  563  }
 537  564  
 538  565  /*
 539  566   * When we are called, os MUST refer to an objset associated with a dataset
↓ open down ↓ 1226 lines elided ↑ open up ↑
1766 1793      int flags)
1767 1794  {
1768 1795          spa_t *spa;
1769 1796          int error;
1770 1797  
1771 1798          error = spa_open(name, &spa, FTAG);
1772 1799          if (error != 0)
1773 1800                  return (error);
1774 1801          error = dmu_objset_find_impl(spa, name, func, arg, flags);
1775 1802          spa_close(spa, FTAG);
     1803 +
     1804 +        return (error);
     1805 +}
     1806 +
     1807 +typedef struct dmu_objset_find_ctx {
     1808 +        taskq_t         *dc_tq;
     1809 +        spa_t           *dc_spa;
     1810 +        char            *dc_name;
     1811 +        int             (*dc_func)(const char *, void *);
     1812 +        void            *dc_arg;
     1813 +        int             dc_flags;
     1814 +        kmutex_t        *dc_error_lock;
     1815 +        int             *dc_error;
     1816 +} dmu_objset_find_ctx_t;
     1817 +
     1818 +static void
     1819 +dmu_objset_find_parallel_impl(void *arg)
     1820 +{
     1821 +        dmu_objset_find_ctx_t *dcp = arg;
     1822 +        dsl_dir_t *dd;
     1823 +        dsl_pool_t *dp = spa_get_dsl(dcp->dc_spa);
     1824 +        dsl_dataset_t *ds;
     1825 +        zap_cursor_t zc;
     1826 +        zap_attribute_t *attr;
     1827 +        char *child;
     1828 +        dmu_objset_find_ctx_t *child_dcp;
     1829 +        uint64_t thisobj;
     1830 +        int err;
     1831 +
     1832 +        /* don't process if there already was an error */
     1833 +        if (*dcp->dc_error)
     1834 +                goto out;
     1835 +
     1836 +        dsl_pool_config_enter(dp, FTAG);
     1837 +
     1838 +        err = dsl_dir_hold(dp, dcp->dc_name, FTAG, &dd, NULL);
     1839 +        if (err != 0) {
     1840 +                dsl_pool_config_exit(dp, FTAG);
     1841 +                goto fail;
     1842 +        }
     1843 +
     1844 +        /* Don't visit hidden ($MOS & $ORIGIN) objsets. */
     1845 +        if (dd->dd_myname[0] == '$') {
     1846 +                dsl_dir_rele(dd, FTAG);
     1847 +                dsl_pool_config_exit(dp, FTAG);
     1848 +                goto out;
     1849 +        }
     1850 +
     1851 +        thisobj = dd->dd_phys->dd_head_dataset_obj;
     1852 +        attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
     1853 +
     1854 +        /*
     1855 +         * Iterate over all children.
     1856 +         */
     1857 +        if (dcp->dc_flags & DS_FIND_CHILDREN) {
     1858 +                for (zap_cursor_init(&zc, dp->dp_meta_objset,
     1859 +                    dd->dd_phys->dd_child_dir_zapobj);
     1860 +                    zap_cursor_retrieve(&zc, attr) == 0;
     1861 +                    (void) zap_cursor_advance(&zc)) {
     1862 +                        ASSERT3U(attr->za_integer_length, ==,
     1863 +                            sizeof (uint64_t));
     1864 +                        ASSERT3U(attr->za_num_integers, ==, 1);
     1865 +
     1866 +                        child = kmem_asprintf("%s/%s", dcp->dc_name,
     1867 +                            attr->za_name);
     1868 +                        dsl_pool_config_exit(dp, FTAG);
     1869 +                        child_dcp = kmem_alloc(sizeof(*child_dcp), KM_SLEEP);
     1870 +                        *child_dcp = *dcp;
     1871 +                        child_dcp->dc_name = child;
     1872 +                        taskq_dispatch(dcp->dc_tq,
     1873 +                            dmu_objset_find_parallel_impl, child_dcp, TQ_SLEEP);
     1874 +                        dsl_pool_config_enter(dp, FTAG);
     1875 +                }
     1876 +                zap_cursor_fini(&zc);
     1877 +        }
     1878 +
     1879 +        dsl_dir_rele(dd, FTAG);
     1880 +        kmem_free(attr, sizeof (zap_attribute_t));
     1881 +        dsl_pool_config_exit(dp, FTAG);
     1882 +
     1883 +        err = dcp->dc_func(dcp->dc_name, dcp->dc_arg);
     1884 +
     1885 +fail:
     1886 +        if (err) {
     1887 +                mutex_enter(dcp->dc_error_lock);
     1888 +                /* only keep first error */
     1889 +                if (*dcp->dc_error == 0)
     1890 +                        *dcp->dc_error = err;
     1891 +                mutex_exit(dcp->dc_error_lock);
     1892 +        }
     1893 +
     1894 +out:
     1895 +        strfree(dcp->dc_name);
     1896 +        kmem_free(dcp, sizeof(*dcp));
     1897 +}
     1898 +
     1899 +int
     1900 +dmu_objset_find_parallel(char *name, int func(const char *, void *), void *arg,
     1901 +    int flags)
     1902 +{
     1903 +        spa_t *spa;
     1904 +        int error;
     1905 +        taskq_t *tq = NULL;
     1906 +        int ntasks;
     1907 +        dmu_objset_find_ctx_t *dcp;
     1908 +        kmutex_t err_lock;
     1909 +
     1910 +        error = spa_open(name, &spa, FTAG);
     1911 +        if (error != 0)
     1912 +                return (error);
     1913 +
     1914 +        ntasks = vdev_count_leaves(spa) * 4;
     1915 +        tq = taskq_create("dmu_objset_find", ntasks, minclsyspri, ntasks,
     1916 +            INT_MAX, 0);
     1917 +        if (!tq) {
     1918 +                spa_close(spa, FTAG);
     1919 +                return (dmu_objset_find(name, func, arg, flags));
     1920 +        }
     1921 +
     1922 +        mutex_init(&err_lock, NULL, MUTEX_DEFAULT, NULL);
     1923 +        dcp = kmem_alloc(sizeof(*dcp), KM_SLEEP);
     1924 +        dcp->dc_tq = tq;
     1925 +        dcp->dc_spa = spa;
     1926 +        dcp->dc_name = strdup(name);
     1927 +        dcp->dc_func = func;
     1928 +        dcp->dc_arg = arg;
     1929 +        dcp->dc_flags = flags;
     1930 +        dcp->dc_error_lock = &err_lock;
     1931 +        dcp->dc_error = &error;
     1932 +        /* dcp and dc_name will be freed by task */
     1933 +        taskq_dispatch(tq, dmu_objset_find_parallel_impl, dcp, TQ_SLEEP);
     1934 +
     1935 +        taskq_wait(tq);
     1936 +        taskq_destroy(tq);
     1937 +        mutex_destroy(&err_lock);
     1938 +
     1939 +        spa_close(spa, FTAG);
     1940 +
1776 1941          return (error);
1777 1942  }
1778 1943  
1779 1944  void
1780 1945  dmu_objset_set_user(objset_t *os, void *user_ptr)
1781 1946  {
1782 1947          ASSERT(MUTEX_HELD(&os->os_user_ptr_lock));
1783 1948          os->os_user_ptr = user_ptr;
1784 1949  }
1785 1950  
↓ open down ↓ 22 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX