1302 */ |
1320 */ |
1303 if (nvpair_type(elem) == DATA_TYPE_UINT64 && |
1321 if (nvpair_type(elem) == DATA_TYPE_UINT64 && |
1304 nvpair_value_uint64(elem, &intval) == 0 && |
1322 nvpair_value_uint64(elem, &intval) == 0 && |
1305 intval >= ZIO_COMPRESS_GZIP_1 && |
1323 intval >= ZIO_COMPRESS_GZIP_1 && |
1306 intval <= ZIO_COMPRESS_GZIP_9) { |
1324 intval <= ZIO_COMPRESS_GZIP_9) { |
1307 spa_t *spa; |
1325 if (zfs_check_version(name, |
1308 |
1326 SPA_VERSION_GZIP_COMPRESSION)) |
1309 if (spa_open(name, &spa, FTAG) == 0) { |
1327 return (ENOTSUP); |
1310 if (spa_version(spa) < |
|
1311 SPA_VERSION_GZIP_COMPRESSION) { |
|
1312 spa_close(spa, FTAG); |
|
1313 return (ENOTSUP); |
|
1314 } |
|
1315 |
|
1316 spa_close(spa, FTAG); |
|
1317 } |
|
1318 } |
1328 } |
1319 break; |
1329 break; |
1320 |
1330 |
1321 case ZFS_PROP_COPIES: |
1331 case ZFS_PROP_COPIES: |
1322 { |
1332 if (zfs_check_version(name, SPA_VERSION_DITTO_BLOCKS)) |
1323 spa_t *spa; |
1333 return (ENOTSUP); |
1324 |
|
1325 if (spa_open(name, &spa, FTAG) == 0) { |
|
1326 if (spa_version(spa) < |
|
1327 SPA_VERSION_DITTO_BLOCKS) { |
|
1328 spa_close(spa, FTAG); |
|
1329 return (ENOTSUP); |
|
1330 } |
|
1331 spa_close(spa, FTAG); |
|
1332 } |
|
1333 break; |
1334 break; |
1334 } |
1335 case ZFS_PROP_NORMALIZE: |
1335 } |
1336 case ZFS_PROP_UTF8ONLY: |
|
1337 case ZFS_PROP_CASE: |
|
1338 if (zfs_check_version(name, SPA_VERSION_NORMALIZATION)) |
|
1339 return (ENOTSUP); |
|
1340 |
|
1341 } |
|
1342 if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) |
|
1343 return (error); |
1336 } |
1344 } |
1337 |
1345 |
1338 elem = NULL; |
1346 elem = NULL; |
1339 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { |
1347 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { |
1340 const char *propname = nvpair_name(elem); |
1348 const char *propname = nvpair_name(elem); |
1640 |
1648 |
1641 /* ARGSUSED */ |
1649 /* ARGSUSED */ |
1642 static void |
1650 static void |
1643 zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) |
1651 zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) |
1644 { |
1652 { |
1645 nvlist_t *nvprops = arg; |
1653 zfs_creat_t *zct = arg; |
1646 uint64_t version = ZPL_VERSION; |
1654 uint64_t version; |
1647 |
1655 |
1648 (void) nvlist_lookup_uint64(nvprops, |
1656 if (spa_version(dmu_objset_spa(os)) >= SPA_VERSION_FUID) |
|
1657 version = ZPL_VERSION; |
|
1658 else |
|
1659 version = ZPL_VERSION_FUID - 1; |
|
1660 |
|
1661 (void) nvlist_lookup_uint64(zct->zct_props, |
1649 zfs_prop_to_name(ZFS_PROP_VERSION), &version); |
1662 zfs_prop_to_name(ZFS_PROP_VERSION), &version); |
1650 |
1663 |
1651 zfs_create_fs(os, cr, version, tx); |
1664 zfs_create_fs(os, cr, version, zct->zct_norm, tx); |
|
1665 } |
|
1666 |
|
1667 /* |
|
1668 * zfs_prop_lookup() |
|
1669 * |
|
1670 * Look for the property first in the existing property nvlist. If |
|
1671 * it's already present, you're done. If it's not there, attempt to |
|
1672 * find the property value from a parent dataset. If that fails, fall |
|
1673 * back to the property's default value. In either of these two |
|
1674 * cases, if update is TRUE, add a value for the property to the |
|
1675 * property nvlist. |
|
1676 * |
|
1677 * If the rval pointer is non-NULL, copy the discovered value to rval. |
|
1678 * |
|
1679 * If we get any unexpected errors, bail and return the error number |
|
1680 * to the caller. |
|
1681 * |
|
1682 * If we succeed, return 0. |
|
1683 */ |
|
1684 static int |
|
1685 zfs_prop_lookup(const char *parentname, zfs_prop_t propnum, |
|
1686 nvlist_t *proplist, uint64_t *rval, boolean_t update) |
|
1687 { |
|
1688 const char *propname; |
|
1689 uint64_t value; |
|
1690 int error = ENOENT; |
|
1691 |
|
1692 propname = zfs_prop_to_name(propnum); |
|
1693 if (proplist != NULL) |
|
1694 error = nvlist_lookup_uint64(proplist, propname, &value); |
|
1695 if (error == ENOENT) { |
|
1696 error = dsl_prop_get_integer(parentname, propname, |
|
1697 &value, NULL); |
|
1698 if (error == ENOENT) |
|
1699 value = zfs_prop_default_numeric(propnum); |
|
1700 else if (error != 0) |
|
1701 return (error); |
|
1702 if (update) { |
|
1703 ASSERT(proplist != NULL); |
|
1704 error = nvlist_add_uint64(proplist, propname, value); |
|
1705 } |
|
1706 } |
|
1707 if (error == 0 && rval) |
|
1708 *rval = value; |
|
1709 return (error); |
|
1710 } |
|
1711 |
|
1712 /* |
|
1713 * zfs_normalization_get |
|
1714 * |
|
1715 * Get the normalization flag value. If the properties have |
|
1716 * non-default values, make sure the pool version is recent enough to |
|
1717 * support these choices. |
|
1718 */ |
|
1719 static int |
|
1720 zfs_normalization_get(const char *dataset, nvlist_t *proplist, int *norm, |
|
1721 boolean_t update) |
|
1722 { |
|
1723 char parentname[MAXNAMELEN]; |
|
1724 char poolname[MAXNAMELEN]; |
|
1725 char *cp; |
|
1726 uint64_t value; |
|
1727 int check = 0; |
|
1728 int error; |
|
1729 |
|
1730 ASSERT(norm != NULL); |
|
1731 *norm = 0; |
|
1732 |
|
1733 (void) strncpy(parentname, dataset, sizeof (parentname)); |
|
1734 cp = strrchr(parentname, '@'); |
|
1735 if (cp != NULL) { |
|
1736 cp[0] = '\0'; |
|
1737 } else { |
|
1738 cp = strrchr(parentname, '/'); |
|
1739 if (cp == NULL) |
|
1740 return (ENOENT); |
|
1741 cp[0] = '\0'; |
|
1742 } |
|
1743 |
|
1744 (void) strncpy(poolname, dataset, sizeof (poolname)); |
|
1745 cp = strchr(poolname, '/'); |
|
1746 if (cp != NULL) |
|
1747 cp[0] = '\0'; |
|
1748 |
|
1749 error = zfs_prop_lookup(parentname, ZFS_PROP_UTF8ONLY, |
|
1750 proplist, &value, update); |
|
1751 if (error != 0) |
|
1752 return (error); |
|
1753 if (value != zfs_prop_default_numeric(ZFS_PROP_UTF8ONLY)) |
|
1754 check = 1; |
|
1755 |
|
1756 error = zfs_prop_lookup(parentname, ZFS_PROP_NORMALIZE, |
|
1757 proplist, &value, update); |
|
1758 if (error != 0) |
|
1759 return (error); |
|
1760 if (value != zfs_prop_default_numeric(ZFS_PROP_NORMALIZE)) { |
|
1761 check = 1; |
|
1762 switch ((int)value) { |
|
1763 case ZFS_NORMALIZE_NONE: |
|
1764 break; |
|
1765 case ZFS_NORMALIZE_C: |
|
1766 *norm |= U8_TEXTPREP_NFC; |
|
1767 break; |
|
1768 case ZFS_NORMALIZE_D: |
|
1769 *norm |= U8_TEXTPREP_NFD; |
|
1770 break; |
|
1771 case ZFS_NORMALIZE_KC: |
|
1772 *norm |= U8_TEXTPREP_NFKC; |
|
1773 break; |
|
1774 case ZFS_NORMALIZE_KD: |
|
1775 *norm |= U8_TEXTPREP_NFKD; |
|
1776 break; |
|
1777 default: |
|
1778 ASSERT((int)value >= ZFS_NORMALIZE_NONE); |
|
1779 ASSERT((int)value <= ZFS_NORMALIZE_KD); |
|
1780 break; |
|
1781 } |
|
1782 } |
|
1783 |
|
1784 error = zfs_prop_lookup(parentname, ZFS_PROP_CASE, |
|
1785 proplist, &value, update); |
|
1786 if (error != 0) |
|
1787 return (error); |
|
1788 if (value != zfs_prop_default_numeric(ZFS_PROP_CASE)) { |
|
1789 check = 1; |
|
1790 switch ((int)value) { |
|
1791 case ZFS_CASE_SENSITIVE: |
|
1792 break; |
|
1793 case ZFS_CASE_INSENSITIVE: |
|
1794 *norm |= U8_TEXTPREP_TOUPPER; |
|
1795 break; |
|
1796 case ZFS_CASE_MIXED: |
|
1797 *norm |= U8_TEXTPREP_TOUPPER; |
|
1798 break; |
|
1799 default: |
|
1800 ASSERT((int)value >= ZFS_CASE_SENSITIVE); |
|
1801 ASSERT((int)value <= ZFS_CASE_MIXED); |
|
1802 break; |
|
1803 } |
|
1804 } |
|
1805 |
|
1806 if (check == 1) |
|
1807 if (zfs_check_version(poolname, SPA_VERSION_NORMALIZATION)) |
|
1808 return (ENOTSUP); |
|
1809 return (0); |
1652 } |
1810 } |
1653 |
1811 |
1654 static int |
1812 static int |
1655 zfs_ioc_create(zfs_cmd_t *zc) |
1813 zfs_ioc_create(zfs_cmd_t *zc) |
1656 { |
1814 { |
1657 objset_t *clone; |
1815 objset_t *clone; |
1658 int error = 0; |
1816 int error = 0; |
|
1817 zfs_creat_t zct; |
1659 nvlist_t *nvprops = NULL; |
1818 nvlist_t *nvprops = NULL; |
1660 void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); |
1819 void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); |
1661 dmu_objset_type_t type = zc->zc_objset_type; |
1820 dmu_objset_type_t type = zc->zc_objset_type; |
1662 |
1821 |
1663 switch (type) { |
1822 switch (type) { |
1697 if (error) { |
1859 if (error) { |
1698 nvlist_free(nvprops); |
1860 nvlist_free(nvprops); |
1699 return (error); |
1861 return (error); |
1700 } |
1862 } |
1701 error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); |
1863 error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); |
|
1864 if (error) { |
|
1865 dmu_objset_close(clone); |
|
1866 nvlist_free(nvprops); |
|
1867 return (error); |
|
1868 } |
|
1869 /* |
|
1870 * If caller did not provide any properties, allocate |
|
1871 * an nvlist for properties, as we will be adding our set-once |
|
1872 * properties to it. This carries the choices made on the |
|
1873 * original file system into the clone. |
|
1874 */ |
|
1875 if (nvprops == NULL) |
|
1876 VERIFY(nvlist_alloc(&nvprops, |
|
1877 NV_UNIQUE_NAME, KM_SLEEP) == 0); |
|
1878 |
|
1879 /* |
|
1880 * We have to have normalization and case-folding |
|
1881 * flags correct when we do the file system creation, |
|
1882 * so go figure them out now. All we really care about |
|
1883 * here is getting these values into the property list. |
|
1884 */ |
|
1885 error = zfs_normalization_get(zc->zc_value, nvprops, |
|
1886 &zct.zct_norm, B_TRUE); |
|
1887 if (error != 0) { |
|
1888 dmu_objset_close(clone); |
|
1889 nvlist_free(nvprops); |
|
1890 return (error); |
|
1891 } |
1702 dmu_objset_close(clone); |
1892 dmu_objset_close(clone); |
1703 } else { |
1893 } else { |
1704 if (cbfunc == NULL) { |
1894 if (cbfunc == NULL) { |
1705 nvlist_free(nvprops); |
1895 nvlist_free(nvprops); |
1706 return (EINVAL); |
1896 return (EINVAL); |
1735 nvlist_free(nvprops); |
1925 nvlist_free(nvprops); |
1736 return (error); |
1926 return (error); |
1737 } |
1927 } |
1738 } else if (type == DMU_OST_ZFS) { |
1928 } else if (type == DMU_OST_ZFS) { |
1739 uint64_t version; |
1929 uint64_t version; |
1740 |
1930 int error; |
1741 if (0 == nvlist_lookup_uint64(nvprops, |
1931 |
1742 zfs_prop_to_name(ZFS_PROP_VERSION), &version) && |
1932 error = nvlist_lookup_uint64(nvprops, |
1743 (version < ZPL_VERSION_INITIAL || |
1933 zfs_prop_to_name(ZFS_PROP_VERSION), &version); |
|
1934 |
|
1935 if (error == 0 && (version < ZPL_VERSION_INITIAL || |
1744 version > ZPL_VERSION)) { |
1936 version > ZPL_VERSION)) { |
1745 nvlist_free(nvprops); |
1937 nvlist_free(nvprops); |
1746 return (EINVAL); |
1938 return (ENOTSUP); |
|
1939 } else if (error == 0 && version >= ZPL_VERSION_FUID && |
|
1940 zfs_check_version(zc->zc_name, SPA_VERSION_FUID)) { |
|
1941 nvlist_free(nvprops); |
|
1942 return (ENOTSUP); |
1747 } |
1943 } |
1748 } |
1944 |
1749 |
1945 /* |
|
1946 * We have to have normalization and |
|
1947 * case-folding flags correct when we do the |
|
1948 * file system creation, so go figure them out |
|
1949 * now. The final argument to zfs_normalization_get() |
|
1950 * tells that routine not to update the nvprops |
|
1951 * list. |
|
1952 */ |
|
1953 error = zfs_normalization_get(zc->zc_name, nvprops, |
|
1954 &zct.zct_norm, B_FALSE); |
|
1955 if (error != 0) { |
|
1956 nvlist_free(nvprops); |
|
1957 return (error); |
|
1958 } |
|
1959 } |
1750 error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, |
1960 error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, |
1751 nvprops); |
1961 &zct); |
1752 } |
1962 } |
1753 |
1963 |
1754 /* |
1964 /* |
1755 * It would be nice to do this atomically. |
1965 * It would be nice to do this atomically. |
1756 */ |
1966 */ |
2121 } |
2331 } |
2122 |
2332 |
2123 /* |
2333 /* |
2124 * We don't want to have a hard dependency |
2334 * We don't want to have a hard dependency |
2125 * against some special symbols in sharefs |
2335 * against some special symbols in sharefs |
2126 * and nfs. Determine them if needed when |
2336 * nfs, and smbsrv. Determine them if needed when |
2127 * the first file system is shared. |
2337 * the first file system is shared. |
2128 * Neither sharefs or nfs are unloadable modules. |
2338 * Neither sharefs, nfs or smbsrv are unloadable modules. |
2129 */ |
2339 */ |
2130 int (*zexport_fs)(void *arg); |
2340 int (*znfsexport_fs)(void *arg); |
2131 int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); |
2341 int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); |
2132 |
2342 int (*zsmbexport_fs)(void *arg, boolean_t add_share); |
2133 int zfs_share_inited; |
2343 |
|
2344 int zfs_nfsshare_inited; |
|
2345 int zfs_smbshare_inited; |
|
2346 |
2134 ddi_modhandle_t nfs_mod; |
2347 ddi_modhandle_t nfs_mod; |
2135 ddi_modhandle_t sharefs_mod; |
2348 ddi_modhandle_t sharefs_mod; |
|
2349 ddi_modhandle_t smbsrv_mod; |
2136 kmutex_t zfs_share_lock; |
2350 kmutex_t zfs_share_lock; |
2137 |
2351 |
2138 static int |
2352 static int |
|
2353 zfs_init_sharefs() |
|
2354 { |
|
2355 int error; |
|
2356 |
|
2357 ASSERT(MUTEX_HELD(&zfs_share_lock)); |
|
2358 /* Both NFS and SMB shares also require sharetab support. */ |
|
2359 if (sharefs_mod == NULL && ((sharefs_mod = |
|
2360 ddi_modopen("fs/sharefs", |
|
2361 KRTLD_MODE_FIRST, &error)) == NULL)) { |
|
2362 return (ENOSYS); |
|
2363 } |
|
2364 if (zshare_fs == NULL && ((zshare_fs = |
|
2365 (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) |
|
2366 ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { |
|
2367 return (ENOSYS); |
|
2368 } |
|
2369 return (0); |
|
2370 } |
|
2371 |
|
2372 static int |
2139 zfs_ioc_share(zfs_cmd_t *zc) |
2373 zfs_ioc_share(zfs_cmd_t *zc) |
2140 { |
2374 { |
2141 int error; |
2375 int error; |
2142 int opcode; |
2376 int opcode; |
2143 |
2377 |
2144 if (zfs_share_inited == 0) { |
2378 switch (zc->zc_share.z_sharetype) { |
2145 mutex_enter(&zfs_share_lock); |
2379 case ZFS_SHARE_NFS: |
2146 nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); |
2380 case ZFS_UNSHARE_NFS: |
2147 sharefs_mod = ddi_modopen("fs/sharefs", |
2381 if (zfs_nfsshare_inited == 0) { |
2148 KRTLD_MODE_FIRST, &error); |
2382 mutex_enter(&zfs_share_lock); |
2149 if (nfs_mod == NULL || sharefs_mod == NULL) { |
2383 if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", |
|
2384 KRTLD_MODE_FIRST, &error)) == NULL)) { |
|
2385 mutex_exit(&zfs_share_lock); |
|
2386 return (ENOSYS); |
|
2387 } |
|
2388 if (znfsexport_fs == NULL && |
|
2389 ((znfsexport_fs = (int (*)(void *)) |
|
2390 ddi_modsym(nfs_mod, |
|
2391 "nfs_export", &error)) == NULL)) { |
|
2392 mutex_exit(&zfs_share_lock); |
|
2393 return (ENOSYS); |
|
2394 } |
|
2395 error = zfs_init_sharefs(); |
|
2396 if (error) { |
|
2397 mutex_exit(&zfs_share_lock); |
|
2398 return (ENOSYS); |
|
2399 } |
|
2400 zfs_nfsshare_inited = 1; |
2150 mutex_exit(&zfs_share_lock); |
2401 mutex_exit(&zfs_share_lock); |
2151 return (ENOSYS); |
2402 } |
2152 } |
2403 break; |
2153 if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) |
2404 case ZFS_SHARE_SMB: |
2154 ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { |
2405 case ZFS_UNSHARE_SMB: |
|
2406 if (zfs_smbshare_inited == 0) { |
|
2407 mutex_enter(&zfs_share_lock); |
|
2408 if (smbsrv_mod == NULL && ((smbsrv_mod = |
|
2409 ddi_modopen("drv/smbsrv", |
|
2410 KRTLD_MODE_FIRST, &error)) == NULL)) { |
|
2411 mutex_exit(&zfs_share_lock); |
|
2412 return (ENOSYS); |
|
2413 } |
|
2414 if (zsmbexport_fs == NULL && ((zsmbexport_fs = |
|
2415 (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, |
|
2416 "lmshrd_share_upcall", &error)) == NULL)) { |
|
2417 mutex_exit(&zfs_share_lock); |
|
2418 return (ENOSYS); |
|
2419 } |
|
2420 error = zfs_init_sharefs(); |
|
2421 if (error) { |
|
2422 mutex_exit(&zfs_share_lock); |
|
2423 return (ENOSYS); |
|
2424 } |
|
2425 zfs_smbshare_inited = 1; |
2155 mutex_exit(&zfs_share_lock); |
2426 mutex_exit(&zfs_share_lock); |
2156 return (ENOSYS); |
2427 } |
2157 } |
2428 break; |
2158 |
2429 default: |
2159 if (zshare_fs == NULL && ((zshare_fs = |
2430 return (EINVAL); |
2160 (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) |
2431 } |
2161 ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { |
2432 |
2162 mutex_exit(&zfs_share_lock); |
2433 switch (zc->zc_share.z_sharetype) { |
2163 return (ENOSYS); |
2434 case ZFS_SHARE_NFS: |
2164 } |
2435 case ZFS_UNSHARE_NFS: |
2165 zfs_share_inited = 1; |
2436 if (error = |
2166 mutex_exit(&zfs_share_lock); |
2437 znfsexport_fs((void *) |
2167 } |
2438 (uintptr_t)zc->zc_share.z_exportdata)) |
2168 |
2439 return (error); |
2169 if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) |
2440 break; |
2170 return (error); |
2441 case ZFS_SHARE_SMB: |
2171 |
2442 case ZFS_UNSHARE_SMB: |
2172 opcode = (zc->zc_share.z_sharetype == B_TRUE) ? |
2443 if (error = zsmbexport_fs((void *) |
|
2444 (uintptr_t)zc->zc_share.z_exportdata, |
|
2445 zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? |
|
2446 B_TRUE : B_FALSE)) { |
|
2447 return (error); |
|
2448 } |
|
2449 break; |
|
2450 } |
|
2451 |
|
2452 opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || |
|
2453 zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? |
2173 SHAREFS_ADD : SHAREFS_REMOVE; |
2454 SHAREFS_ADD : SHAREFS_REMOVE; |
2174 |
2455 |
|
2456 /* |
|
2457 * Add or remove share from sharetab |
|
2458 */ |
2175 error = zshare_fs(opcode, |
2459 error = zshare_fs(opcode, |
2176 (void *)(uintptr_t)zc->zc_share.z_sharedata, |
2460 (void *)(uintptr_t)zc->zc_share.z_sharedata, |
2177 zc->zc_share.z_sharemax); |
2461 zc->zc_share.z_sharemax); |
2178 |
2462 |
2179 return (error); |
2463 return (error); |