Print this page
*** NO COMMENTS ***


 461                 return (0);
 462         }
 463 
 464         /* otherwise, the mapping should already exist */
 465         lsp = ddi_get_soft_state(lofi_statep, minor);
 466         if (lsp == NULL) {
 467                 mutex_exit(&lofi_lock);
 468                 return (EINVAL);
 469         }
 470 
 471         if (lsp->ls_vp == NULL) {
 472                 mutex_exit(&lofi_lock);
 473                 return (ENXIO);
 474         }
 475 
 476         if (mark_opened(lsp, otyp) == -1) {
 477                 mutex_exit(&lofi_lock);
 478                 return (EINVAL);
 479         }
 480 

 481         mutex_exit(&lofi_lock);




 482         return (0);
 483 }
 484 
 485 /*ARGSUSED*/
 486 static int
 487 lofi_close(dev_t dev, int flag, int otyp, struct cred *credp)
 488 {
 489         minor_t minor;
 490         struct lofi_state *lsp;
 491 
 492         mutex_enter(&lofi_lock);
 493         minor = getminor(dev);
 494         lsp = ddi_get_soft_state(lofi_statep, minor);
 495         if (lsp == NULL) {
 496                 mutex_exit(&lofi_lock);
 497                 return (EINVAL);
 498         }
 499 
 500         if (minor == 0) {
 501                 mutex_exit(&lofi_lock);


1603         error = ddi_copyout(klip, ulip, sizeof (struct lofi_ioctl), flag);
1604         if (error)
1605                 return (EFAULT);
1606         return (0);
1607 }
1608 
1609 static int
1610 lofi_access(struct lofi_state *lsp)
1611 {
1612         ASSERT(MUTEX_HELD(&lofi_lock));
1613         if (INGLOBALZONE(curproc) || lsp->ls_zone.zref_zone == curzone)
1614                 return (0);
1615         return (EPERM);
1616 }
1617 
1618 /*
1619  * Find the lofi state for the given filename. We compare by vnode to
1620  * allow the global zone visibility into NGZ lofi nodes.
1621  */
1622 static int
1623 file_to_lofi_nocheck(char *filename, struct lofi_state **lspp)

1624 {
1625         struct lofi_state *lsp;
1626         vnode_t *vp = NULL;
1627         int err = 0;

1628 
1629         ASSERT(MUTEX_HELD(&lofi_lock));
1630 
1631         if ((err = lookupname(filename, UIO_SYSSPACE, FOLLOW,
1632             NULLVPP, &vp)) != 0)
1633                 goto out;
1634 
1635         if (vp->v_type == VREG) {
1636                 vnode_t *realvp;
1637                 if (VOP_REALVP(vp, &realvp, NULL) == 0) {
1638                         VN_HOLD(realvp);
1639                         VN_RELE(vp);
1640                         vp = realvp;
1641                 }
1642         }
1643 
1644         for (lsp = list_head(&lofi_list); lsp != NULL;
1645             lsp = list_next(&lofi_list, lsp)) {
1646                 if (lsp->ls_vp == vp) {
1647                         if (lspp != NULL)
1648                                 *lspp = lsp;






1649                         goto out;
1650                 }
1651         }
1652 
1653         err = ENOENT;
1654 












1655 out:
1656         if (vp != NULL)
1657                 VN_RELE(vp);
1658         return (err);
1659 }
1660 
1661 /*
1662  * Find the minor for the given filename, checking the zone can access
1663  * it.
1664  */
1665 static int
1666 file_to_lofi(char *filename, struct lofi_state **lspp)
1667 {
1668         int err = 0;
1669 
1670         ASSERT(MUTEX_HELD(&lofi_lock));
1671 
1672         if ((err = file_to_lofi_nocheck(filename, lspp)) != 0)
1673                 return (err);
1674 
1675         if ((err = lofi_access(*lspp)) != 0)
1676                 return (err);
1677 
1678         return (0);
1679 }
1680 
1681 /*
1682  * Fakes up a disk geometry, and one big partition, based on the size
1683  * of the file. This is needed because we allow newfs'ing the device,
1684  * and newfs will do several disk ioctls to figure out the geometry and
1685  * partition information. It uses that information to determine the parameters
1686  * to pass to mkfs. Geometry is pretty much irrelevant these days, but we
1687  * have to support it.
1688  */
1689 static void
1690 fake_disk_geometry(struct lofi_state *lsp)
1691 {
1692         u_offset_t dsize = lsp->ls_vp_size - lsp->ls_crypto_offset;


2105         vattr_t vattr;
2106         int     flag;
2107         dev_t   newdev;
2108         char    namebuf[50];
2109 
2110         error = copy_in_lofi_ioctl(ulip, &klip, ioctl_flag);
2111         if (error != 0)
2112                 return (error);
2113 
2114         mutex_enter(&lofi_lock);
2115 
2116         mutex_enter(&curproc->p_lock);
2117         if ((error = rctl_incr_lofi(curproc, curproc->p_zone, 1)) != 0) {
2118                 mutex_exit(&curproc->p_lock);
2119                 mutex_exit(&lofi_lock);
2120                 free_lofi_ioctl(klip);
2121                 return (error);
2122         }
2123         mutex_exit(&curproc->p_lock);
2124 
2125         if (file_to_lofi_nocheck(klip->li_filename, NULL) == 0) {

2126                 error = EBUSY;
2127                 goto err;
2128         }
2129 
2130         if (pickminor) {
2131                 minor = (minor_t)id_allocff_nosleep(lofi_minor_id);
2132                 if (minor == (minor_t)-1) {
2133                         error = EAGAIN;
2134                         goto err;
2135                 }
2136         } else {
2137                 if (ddi_get_soft_state(lofi_statep, klip->li_minor) != NULL) {
2138                         error = EEXIST;
2139                         goto err;
2140                 }
2141 
2142                 minor = (minor_t)
2143                     id_alloc_specific_nosleep(lofi_minor_id, klip->li_minor);
2144                 ASSERT(minor != (minor_t)-1);
2145         }


2226                          */
2227                         VN_HOLD(realvp);
2228                         lsp->ls_vp = realvp;
2229                 }
2230         }
2231 
2232         lsp->ls_vp_size = vattr.va_size;
2233         lsp->ls_vp_comp_size = lsp->ls_vp_size;
2234 
2235         lsp->ls_kstat = kstat_create_zone(LOFI_DRIVER_NAME, minor,
2236             NULL, "disk", KSTAT_TYPE_IO, 1, 0, getzoneid());
2237 
2238         if (lsp->ls_kstat == NULL) {
2239                 error = ENOMEM;
2240                 goto err;
2241         }
2242 
2243         lsp->ls_kstat->ks_lock = &lsp->ls_kstat_lock;
2244         kstat_zone_add(lsp->ls_kstat, GLOBAL_ZONEID);
2245 


2246         if ((error = lofi_init_crypto(lsp, klip)) != 0)
2247                 goto err;
2248 
2249         if ((error = lofi_init_compress(lsp)) != 0)
2250                 goto err;
2251 
2252         fake_disk_geometry(lsp);
2253 
2254         /* create minor nodes */
2255 
2256         (void) snprintf(namebuf, sizeof (namebuf), "%d", minor);
2257         error = ddi_create_minor_node(lofi_dip, namebuf, S_IFBLK, minor,
2258             DDI_PSEUDO, NULL);
2259         if (error != DDI_SUCCESS) {
2260                 error = ENXIO;
2261                 goto err;
2262         }
2263 
2264         (void) snprintf(namebuf, sizeof (namebuf), "%d,raw", minor);
2265         error = ddi_create_minor_node(lofi_dip, namebuf, S_IFCHR, minor,


2326         return (error);
2327 }
2328 
2329 /*
2330  * unmap a file.
2331  */
2332 static int
2333 lofi_unmap_file(struct lofi_ioctl *ulip, int byfilename,
2334     struct cred *credp, int ioctl_flag)
2335 {
2336         struct lofi_state *lsp;
2337         struct lofi_ioctl *klip;
2338         int err;
2339 
2340         err = copy_in_lofi_ioctl(ulip, &klip, ioctl_flag);
2341         if (err != 0)
2342                 return (err);
2343 
2344         mutex_enter(&lofi_lock);
2345         if (byfilename) {
2346                 if ((err = file_to_lofi(klip->li_filename, &lsp)) != 0) {

2347                         mutex_exit(&lofi_lock);
2348                         return (err);
2349                 }
2350         } else if (klip->li_minor == 0) {
2351                 mutex_exit(&lofi_lock);
2352                 free_lofi_ioctl(klip);
2353                 return (ENXIO);
2354         } else {
2355                 lsp = ddi_get_soft_state(lofi_statep, klip->li_minor);
2356         }
2357 
2358         if (lsp == NULL || lsp->ls_vp == NULL || lofi_access(lsp) != 0) {
2359                 mutex_exit(&lofi_lock);
2360                 free_lofi_ioctl(klip);
2361                 return (ENXIO);
2362         }
2363 
2364         klip->li_minor = getminor(lsp->ls_dev);
2365 
2366         /*


2443                 }
2444 
2445                 mutex_enter(&lofi_lock);
2446                 lsp = ddi_get_soft_state(lofi_statep, klip->li_minor);
2447                 if (lsp == NULL || lofi_access(lsp) != 0) {
2448                         mutex_exit(&lofi_lock);
2449                         free_lofi_ioctl(klip);
2450                         return (ENXIO);
2451                 }
2452 
2453                 /*
2454                  * This may fail if, for example, we're trying to look
2455                  * up a zoned NFS path from the global zone.
2456                  */
2457                 if (vnodetopath(NULL, lsp->ls_stacked_vp, klip->li_filename,
2458                     sizeof (klip->li_filename), CRED()) != 0) {
2459                         (void) strlcpy(klip->li_filename, "?",
2460                             sizeof (klip->li_filename));
2461                 }
2462 


2463                 (void) strlcpy(klip->li_algorithm, lsp->ls_comp_algorithm,
2464                     sizeof (klip->li_algorithm));
2465                 klip->li_crypto_enabled = lsp->ls_crypto_enabled;
2466                 mutex_exit(&lofi_lock);
2467                 error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
2468                 free_lofi_ioctl(klip);
2469                 return (error);
2470         case LOFI_GET_MINOR:
2471                 mutex_enter(&lofi_lock);
2472                 error = file_to_lofi(klip->li_filename, &lsp);

2473                 if (error == 0)
2474                         klip->li_minor = getminor(lsp->ls_dev);
2475                 mutex_exit(&lofi_lock);
2476 
2477                 if (error == 0)
2478                         error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
2479 
2480                 free_lofi_ioctl(klip);
2481                 return (error);
2482         case LOFI_CHECK_COMPRESSED:
2483                 mutex_enter(&lofi_lock);
2484                 error = file_to_lofi(klip->li_filename, &lsp);

2485                 if (error != 0) {
2486                         mutex_exit(&lofi_lock);
2487                         free_lofi_ioctl(klip);
2488                         return (error);
2489                 }
2490 
2491                 klip->li_minor = getminor(lsp->ls_dev);
2492                 (void) strlcpy(klip->li_algorithm, lsp->ls_comp_algorithm,
2493                     sizeof (klip->li_algorithm));
2494 
2495                 mutex_exit(&lofi_lock);
2496                 error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
2497                 free_lofi_ioctl(klip);
2498                 return (error);
2499         default:
2500                 free_lofi_ioctl(klip);
2501                 return (EINVAL);
2502         }
2503 }
2504 




 461                 return (0);
 462         }
 463 
 464         /* otherwise, the mapping should already exist */
 465         lsp = ddi_get_soft_state(lofi_statep, minor);
 466         if (lsp == NULL) {
 467                 mutex_exit(&lofi_lock);
 468                 return (EINVAL);
 469         }
 470 
 471         if (lsp->ls_vp == NULL) {
 472                 mutex_exit(&lofi_lock);
 473                 return (ENXIO);
 474         }
 475 
 476         if (mark_opened(lsp, otyp) == -1) {
 477                 mutex_exit(&lofi_lock);
 478                 return (EINVAL);
 479         }
 480 
 481         if (lsp->ls_readonly && (flag & FWRITE)) {
 482                 mutex_exit(&lofi_lock);
 483                 return (EROFS);
 484         }
 485 
 486         mutex_exit(&lofi_lock);
 487         return (0);
 488 }
 489 
 490 /*ARGSUSED*/
 491 static int
 492 lofi_close(dev_t dev, int flag, int otyp, struct cred *credp)
 493 {
 494         minor_t minor;
 495         struct lofi_state *lsp;
 496 
 497         mutex_enter(&lofi_lock);
 498         minor = getminor(dev);
 499         lsp = ddi_get_soft_state(lofi_statep, minor);
 500         if (lsp == NULL) {
 501                 mutex_exit(&lofi_lock);
 502                 return (EINVAL);
 503         }
 504 
 505         if (minor == 0) {
 506                 mutex_exit(&lofi_lock);


1608         error = ddi_copyout(klip, ulip, sizeof (struct lofi_ioctl), flag);
1609         if (error)
1610                 return (EFAULT);
1611         return (0);
1612 }
1613 
1614 static int
1615 lofi_access(struct lofi_state *lsp)
1616 {
1617         ASSERT(MUTEX_HELD(&lofi_lock));
1618         if (INGLOBALZONE(curproc) || lsp->ls_zone.zref_zone == curzone)
1619                 return (0);
1620         return (EPERM);
1621 }
1622 
1623 /*
1624  * Find the lofi state for the given filename. We compare by vnode to
1625  * allow the global zone visibility into NGZ lofi nodes.
1626  */
1627 static int
1628 file_to_lofi_nocheck(char *filename, boolean_t readonly,
1629     struct lofi_state **lspp)
1630 {
1631         struct lofi_state *lsp;
1632         vnode_t *vp = NULL;
1633         int err = 0;
1634         int rdfiles = 0;
1635 
1636         ASSERT(MUTEX_HELD(&lofi_lock));
1637 
1638         if ((err = lookupname(filename, UIO_SYSSPACE, FOLLOW,
1639             NULLVPP, &vp)) != 0)
1640                 goto out;
1641 
1642         if (vp->v_type == VREG) {
1643                 vnode_t *realvp;
1644                 if (VOP_REALVP(vp, &realvp, NULL) == 0) {
1645                         VN_HOLD(realvp);
1646                         VN_RELE(vp);
1647                         vp = realvp;
1648                 }
1649         }
1650 
1651         for (lsp = list_head(&lofi_list); lsp != NULL;
1652             lsp = list_next(&lofi_list, lsp)) {
1653                 if (lsp->ls_vp == vp) {
1654                         if (lspp != NULL)
1655                                 *lspp = lsp;
1656                         if (lsp->ls_readonly) {
1657                                 rdfiles++;
1658                                 /* Skip if '-r' is specified */
1659                                 if (readonly)
1660                                         continue;
1661                         }
1662                         goto out;
1663                 }
1664         }
1665 
1666         err = ENOENT;
1667 
1668         /*
1669          * If a filename is given as an argument for lofi_unmap, we shouldn't
1670          * allow unmap if there are multiple read-only lofi devices associated
1671          * with this file.
1672          */
1673         if (lspp != NULL) {
1674                 if (rdfiles == 1)
1675                         err = 0;
1676                 else if (rdfiles > 1)
1677                         err = EBUSY;
1678         }
1679 
1680 out:
1681         if (vp != NULL)
1682                 VN_RELE(vp);
1683         return (err);
1684 }
1685 
1686 /*
1687  * Find the minor for the given filename, checking the zone can access
1688  * it.
1689  */
1690 static int
1691 file_to_lofi(char *filename, boolean_t readonly, struct lofi_state **lspp)
1692 {
1693         int err = 0;
1694 
1695         ASSERT(MUTEX_HELD(&lofi_lock));
1696 
1697         if ((err = file_to_lofi_nocheck(filename, readonly, lspp)) != 0)
1698                 return (err);
1699 
1700         if ((err = lofi_access(*lspp)) != 0)
1701                 return (err);
1702 
1703         return (0);
1704 }
1705 
1706 /*
1707  * Fakes up a disk geometry, and one big partition, based on the size
1708  * of the file. This is needed because we allow newfs'ing the device,
1709  * and newfs will do several disk ioctls to figure out the geometry and
1710  * partition information. It uses that information to determine the parameters
1711  * to pass to mkfs. Geometry is pretty much irrelevant these days, but we
1712  * have to support it.
1713  */
1714 static void
1715 fake_disk_geometry(struct lofi_state *lsp)
1716 {
1717         u_offset_t dsize = lsp->ls_vp_size - lsp->ls_crypto_offset;


2130         vattr_t vattr;
2131         int     flag;
2132         dev_t   newdev;
2133         char    namebuf[50];
2134 
2135         error = copy_in_lofi_ioctl(ulip, &klip, ioctl_flag);
2136         if (error != 0)
2137                 return (error);
2138 
2139         mutex_enter(&lofi_lock);
2140 
2141         mutex_enter(&curproc->p_lock);
2142         if ((error = rctl_incr_lofi(curproc, curproc->p_zone, 1)) != 0) {
2143                 mutex_exit(&curproc->p_lock);
2144                 mutex_exit(&lofi_lock);
2145                 free_lofi_ioctl(klip);
2146                 return (error);
2147         }
2148         mutex_exit(&curproc->p_lock);
2149 
2150         if (file_to_lofi_nocheck(klip->li_filename, klip->li_readonly,
2151             NULL) == 0) {
2152                 error = EBUSY;
2153                 goto err;
2154         }
2155 
2156         if (pickminor) {
2157                 minor = (minor_t)id_allocff_nosleep(lofi_minor_id);
2158                 if (minor == (minor_t)-1) {
2159                         error = EAGAIN;
2160                         goto err;
2161                 }
2162         } else {
2163                 if (ddi_get_soft_state(lofi_statep, klip->li_minor) != NULL) {
2164                         error = EEXIST;
2165                         goto err;
2166                 }
2167 
2168                 minor = (minor_t)
2169                     id_alloc_specific_nosleep(lofi_minor_id, klip->li_minor);
2170                 ASSERT(minor != (minor_t)-1);
2171         }


2252                          */
2253                         VN_HOLD(realvp);
2254                         lsp->ls_vp = realvp;
2255                 }
2256         }
2257 
2258         lsp->ls_vp_size = vattr.va_size;
2259         lsp->ls_vp_comp_size = lsp->ls_vp_size;
2260 
2261         lsp->ls_kstat = kstat_create_zone(LOFI_DRIVER_NAME, minor,
2262             NULL, "disk", KSTAT_TYPE_IO, 1, 0, getzoneid());
2263 
2264         if (lsp->ls_kstat == NULL) {
2265                 error = ENOMEM;
2266                 goto err;
2267         }
2268 
2269         lsp->ls_kstat->ks_lock = &lsp->ls_kstat_lock;
2270         kstat_zone_add(lsp->ls_kstat, GLOBAL_ZONEID);
2271 
2272         lsp->ls_readonly = klip->li_readonly;
2273 
2274         if ((error = lofi_init_crypto(lsp, klip)) != 0)
2275                 goto err;
2276 
2277         if ((error = lofi_init_compress(lsp)) != 0)
2278                 goto err;
2279 
2280         fake_disk_geometry(lsp);
2281 
2282         /* create minor nodes */
2283 
2284         (void) snprintf(namebuf, sizeof (namebuf), "%d", minor);
2285         error = ddi_create_minor_node(lofi_dip, namebuf, S_IFBLK, minor,
2286             DDI_PSEUDO, NULL);
2287         if (error != DDI_SUCCESS) {
2288                 error = ENXIO;
2289                 goto err;
2290         }
2291 
2292         (void) snprintf(namebuf, sizeof (namebuf), "%d,raw", minor);
2293         error = ddi_create_minor_node(lofi_dip, namebuf, S_IFCHR, minor,


2354         return (error);
2355 }
2356 
2357 /*
2358  * unmap a file.
2359  */
2360 static int
2361 lofi_unmap_file(struct lofi_ioctl *ulip, int byfilename,
2362     struct cred *credp, int ioctl_flag)
2363 {
2364         struct lofi_state *lsp;
2365         struct lofi_ioctl *klip;
2366         int err;
2367 
2368         err = copy_in_lofi_ioctl(ulip, &klip, ioctl_flag);
2369         if (err != 0)
2370                 return (err);
2371 
2372         mutex_enter(&lofi_lock);
2373         if (byfilename) {
2374                 if ((err = file_to_lofi(klip->li_filename, klip->li_readonly,
2375                     &lsp)) != 0) {
2376                         mutex_exit(&lofi_lock);
2377                         return (err);
2378                 }
2379         } else if (klip->li_minor == 0) {
2380                 mutex_exit(&lofi_lock);
2381                 free_lofi_ioctl(klip);
2382                 return (ENXIO);
2383         } else {
2384                 lsp = ddi_get_soft_state(lofi_statep, klip->li_minor);
2385         }
2386 
2387         if (lsp == NULL || lsp->ls_vp == NULL || lofi_access(lsp) != 0) {
2388                 mutex_exit(&lofi_lock);
2389                 free_lofi_ioctl(klip);
2390                 return (ENXIO);
2391         }
2392 
2393         klip->li_minor = getminor(lsp->ls_dev);
2394 
2395         /*


2472                 }
2473 
2474                 mutex_enter(&lofi_lock);
2475                 lsp = ddi_get_soft_state(lofi_statep, klip->li_minor);
2476                 if (lsp == NULL || lofi_access(lsp) != 0) {
2477                         mutex_exit(&lofi_lock);
2478                         free_lofi_ioctl(klip);
2479                         return (ENXIO);
2480                 }
2481 
2482                 /*
2483                  * This may fail if, for example, we're trying to look
2484                  * up a zoned NFS path from the global zone.
2485                  */
2486                 if (vnodetopath(NULL, lsp->ls_stacked_vp, klip->li_filename,
2487                     sizeof (klip->li_filename), CRED()) != 0) {
2488                         (void) strlcpy(klip->li_filename, "?",
2489                             sizeof (klip->li_filename));
2490                 }
2491 
2492                 klip->li_readonly = lsp->ls_readonly;
2493 
2494                 (void) strlcpy(klip->li_algorithm, lsp->ls_comp_algorithm,
2495                     sizeof (klip->li_algorithm));
2496                 klip->li_crypto_enabled = lsp->ls_crypto_enabled;
2497                 mutex_exit(&lofi_lock);
2498                 error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
2499                 free_lofi_ioctl(klip);
2500                 return (error);
2501         case LOFI_GET_MINOR:
2502                 mutex_enter(&lofi_lock);
2503                 error = file_to_lofi(klip->li_filename,
2504                     klip->li_readonly, &lsp);
2505                 if (error == 0)
2506                         klip->li_minor = getminor(lsp->ls_dev);
2507                 mutex_exit(&lofi_lock);
2508 
2509                 if (error == 0)
2510                         error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
2511 
2512                 free_lofi_ioctl(klip);
2513                 return (error);
2514         case LOFI_CHECK_COMPRESSED:
2515                 mutex_enter(&lofi_lock);
2516                 error = file_to_lofi(klip->li_filename,
2517                     klip->li_readonly, &lsp);
2518                 if (error != 0) {
2519                         mutex_exit(&lofi_lock);
2520                         free_lofi_ioctl(klip);
2521                         return (error);
2522                 }
2523 
2524                 klip->li_minor = getminor(lsp->ls_dev);
2525                 (void) strlcpy(klip->li_algorithm, lsp->ls_comp_algorithm,
2526                     sizeof (klip->li_algorithm));
2527 
2528                 mutex_exit(&lofi_lock);
2529                 error = copy_out_lofi_ioctl(klip, ulip, ioctl_flag);
2530                 free_lofi_ioctl(klip);
2531                 return (error);
2532         default:
2533                 free_lofi_ioctl(klip);
2534                 return (EINVAL);
2535         }
2536 }
2537