lofi.c revision 406fc5100dac8d225a315a6def6be8d628f34e24
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * CDDL HEADER START
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Common Development and Distribution License (the "License").
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You may not use this file except in compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing permissions
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below this CDDL HEADER, with the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * information: Portions Copyright [yyyy] [name of copyright owner]
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * CDDL HEADER END
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2016 Andrey Sokolov
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright 2016 Toomas Soome <tsoome@me.com>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * lofi (loopback file) driver - allows you to attach a file to a device,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * which can then be accessed through that device. The simple model is that
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * you tell lofi to open a file, and then use the block device you get as
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * you would any block device. lofi translates access to the block device
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * into I/O on the underlying file. This is mostly useful for
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * mounting images of filesystems.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * lofi is controlled through /dev/lofictl - this is the only device exported
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * during attach, and is instance number 0. lofiadm communicates with lofi
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * through ioctls on this device. When a file is attached to lofi, block and
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * character devices are exported in /dev/lofi and /dev/rlofi. These devices
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * are identified by lofi instance number, and the instance number is also used
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * as the name in /dev/lofi.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Virtual disks, or, labeled lofi, implements virtual disk support to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * support partition table and related tools. Such mappings will cause
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * block and character devices to be exported in /dev/dsk and /dev/rdsk
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * directories.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * To support virtual disks, the instance number space is divided to two
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * parts, upper part for instance number and lower part for minor number
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * space to identify partitions and slices. The virtual disk support is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * implemented by stacking cmlb module. For virtual disks, the partition
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * related ioctl calls are routed to cmlb module. Compression and encryption
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is not supported for virtual disks.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Mapped devices are tracked with state structures handled with
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * ddi_soft_state(9F) for simplicity.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * A file attached to lofi is opened when attached and not closed until
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * explicitly detached from lofi. This seems more sensible than deferring
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * the open until the /dev/lofi device is opened, for a number of reasons.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * One is that any failure is likely to be noticed by the person (or script)
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * running lofiadm. Another is that it would be a security problem if the
ce4d3fddc8fe2eddd68a20af9570b3cc63ece5abNeil Madden * file was replaced by another one after being added but before being opened.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * The only hard part about lofi is the ioctls. In order to support things
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * like 'newfs' on a lofi device, it needs to support certain disk ioctls.
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna * So it has to fake disk geometry and partition information. More may need
57a1b25dcdf865eacb2fe2e17c5ca83e942da047David Luna * to be faked if your favorite utility doesn't work and you think it should
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (fdformat doesn't work because it really wants to know the type of floppy
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * controller to talk to, and that didn't seem easy to fake. Or possibly even
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * necessary, since we have mkfs_pcfs now).
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Normally, a lofi device cannot be detached if it is open (i.e. busy). To
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * support simulation of hotplug events, an optional force flag is provided.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * If a lofi device is open when a force detach is requested, then the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * underlying file is closed and any subsequent operations return EIO. When the
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * device is closed for the last time, it will be cleaned up at that time. In
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * addition, the DKIOCSTATE ioctl will return DKIO_DEV_GONE when the device is
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * detached but not removed.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Known problems:
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * UFS logging. Mounting a UFS filesystem image "logging"
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * works for basic copy testing but wedges during a build of ON through
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * that image. Some deadlock in lufs holding the log mutex and then
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * getting stuck on a buf. So for now, don't do that.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Direct I/O. Since the filesystem data is being cached in the buffer
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * cache, _and_ again in the underlying filesystem, it's tempting to
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * enable direct I/O on the underlying file. Don't, because that deadlocks.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * I think to fix the cache-twice problem we might need filesystem support.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Interesting things to do:
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Allow multiple files for each device. A poor-man's metadisk, basically.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Pass-through ioctls on block devices. You can (though it's not
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * documented), give lofi a block device as a file name. Then we shouldn't
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * need to fake a geometry, however, it may be relevant if you're replacing
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * metadisk, or using lofi to get crypto.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * It makes sense to do lofiadm -c aes -a /dev/dsk/c0t0d0s4 /dev/lofi/1
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and then in /etc/vfstab have an entry for /dev/lofi/1 as /export/home.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * In fact this even makes sense if you have lofi "above" metadisk.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Encryption:
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Each lofi device can have its own symmetric key and cipher.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * They are passed to us by lofiadm(1m) in the correct format for use
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * with the misc/kcf crypto_* routines.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Each block has its own IV, that is calculated in lofi_blk_mech(), based
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * on the "master" key held in the lsp and the block number of the buffer.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington#include <sys/scsi/scsi.h> /* for DTYPE_DIRECT */
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington if (((uio)->uio_loffset % DEV_BSIZE) != 0 || \
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic id_space_t *lofi_id; /* lofi ID values */
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Because lofi_taskq_nthreads limits the actual swamping of the device, the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * maxalloc parameter (lofi_taskq_maxalloc) should be tuned conservatively
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * high. If we want to be assured that the underlying device is always busy,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * we must be sure that the number of bytes enqueued when the number of
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * enqueued tasks exceeds maxalloc is sufficient to keep the device busy for
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * the duration of the sleep time in taskq_ent_alloc(). That is, lofi should
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * set maxalloc to be the maximum throughput (in bytes per second) of the
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * underlying device divided by the minimum I/O size. We assume a realistic
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * maximum throughput of one hundred megabytes per second; we set maxalloc on
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the lofi task queue to be 104857600 divided by DEV_BSIZE.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic int lofi_taskq_maxalloc = 104857600 / DEV_BSIZE;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic int lofi_taskq_nthreads = 4; /* # of taskq threads per device */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconst char lofi_crypto_magic[6] = LOFI_CRYPTO_MAGIC;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * To avoid decompressing data in a compressed segment multiple times
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * when accessing small parts of a segment's data, we cache and reuse
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * the uncompressed segment's data.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * A single cached segment is sufficient to avoid lots of duplicate
7f1ad89d15984c64fde1e507c3b38238cb2e3f8dJames Phillpotts * segment decompress operations. A small cache size also reduces the
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * memory footprint.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * lofi_max_comp_cache is the maximum number of decompressed data segments
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * cached for each compressed lofi image. It can be set to 0 to disable
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic int gzip_decompress(void *src, size_t srclen, void *dst,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic int lzma_decompress(void *src, size_t srclen, void *dst,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonlofi_compress_info_t lofi_compress_table[LOFI_COMPRESS_FUNCTIONS] = {
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington {gzip_decompress, NULL, 6, "gzip"}, /* default */
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic void lofi_strategy_task(void *);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic int lofi_tg_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic int lofi_tg_getinfo(dev_info_t *, int, void *, void *);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonstatic ISzAlloc g_Alloc = { SzAlloc, SzFree };
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Free data referenced by the linked list of cached uncompressed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ((lc = list_remove_head(&lsp->ls_comp_cache)) != NULL) {
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington kmem_free(lc->lc_data, lsp->ls_uncomp_seg_sz);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington kmem_free(lc, sizeof (struct lofi_comp_cache));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (i = 0; i < LOFI_PART_MAX; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Clean up the crypto state so that it doesn't hang around
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * in memory after we are done with it.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington/* ARGSUSED */
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonlofi_tg_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr, diskaddr_t start,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington if (instance == 0) /* control node does not have disk */
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington lsp = ddi_get_soft_state(lofi_statep, instance);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Make sure the mapping is set up by checking lsp->ls_vp_ready.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington if (P2PHASE(length, (1U << lsp->ls_lbshift)) != 0) {
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington /* We can only transfer whole blocks at a time! */
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington kstat_waitq_enter(KSTAT_IO_PTR(lsp->ls_kstat));
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington (void) taskq_dispatch(lsp->ls_taskq, lofi_strategy_task, bp, KM_SLEEP);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Get device geometry info for cmlb.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * We have mapped disk image as virtual block device and have to report
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * physical/virtual geometry to cmlb.
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * So we have two principal cases:
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * 1. Uninitialised image without any existing labels,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * for this case we fabricate the data based on mapped image.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * 2. Image with existing label information.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Since we have no information how the image was created (it may be
int instance;
int ashift;
return (ENXIO);
return (ENXIO);
return (ENXIO);
switch (cmd) {
case TG_GETPHYGEOM: {
case TG_GETCAPACITY:
case TG_GETBLOCKSIZE:
case TG_GETATTR: {
return (EINVAL);
for (i = 0; i < lofi_taskq_nthreads; i++) {
int id;
return (EINVAL);
return (EINVAL);
if (id == 0) {
return (EINVAL);
return (ENXIO);
return (EROFS);
return (EBUSY);
return (EBUSY);
for (int i = 0; i < OTYP_LYR; i++) {
return (EBUSY);
if (!ndelay) {
return (ENXIO);
return (ENXIO);
} else if (!ndelay) {
return (ENXIO);
int id;
return (EINVAL);
if (id == 0) {
* lsp->ls_mech.cm_param_len is set to the IV len.
* lsp->ls_mech.cm_param is set to the IV.
int ret;
char *iv;
void *data;
return (CRYPTO_DEVICE_ERROR);
/* lsp->ls_mech.cm_param{_len} has already been set for static iv */
return (CRYPTO_SUCCESS);
case IVM_ENC_BLKNO:
data = 0;
datasz = 0;
return (ret);
return (CRYPTO_SUCCESS);
int ret;
if (op_encrypt) {
lblkno++;
return (ret);
int isread;
int error;
if (isread) {
error = 0;
&resid);
return (error);
return (EIO);
error = 0;
&resid);
return (error);
int error;
int isread;
int smflags;
int save_error;
if (error) {
if (error == 0) {
smflags = 0;
if (isread) {
if (error == 0)
if (error == 0)
mapoffset = 0;
return (error);
static struct lofi_comp_cache *
return (lc);
return (NULL);
static struct lofi_comp_cache *
if (lofi_max_comp_cache == 0)
return (NULL);
return (NULL);
return (lc);
void *actual_src;
int error;
int syncflag = 0;
goto errout;
goto errout;
NULL);
uint64_t i;
goto done;
error = 0;
goto done;
for (j = 0; j < lofi_taskq_nthreads; j++) {
KM_SLEEP);
if (error != 0)
goto done;
KM_SLEEP);
goto done;
if (i == eblkno)
sblkoff = 0;
goto done;
done:
int shift;
p_lba = 0;
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (EINVAL);
int instance;
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_INFO_DEVT2INSTANCE:
return (DDI_SUCCESS);
return (DDI_FAILURE);
int error = 0;
DDI_PSEUDO, 0);
return (error);
int error = 0;
return (error);
return (error);
int error;
return (ENOMEM);
goto err;
goto lerr;
goto merr;
goto merr;
return (DDI_SUCCESS);
merr:
lerr:
err:
return (error);
int rv;
return (DDI_FAILURE);
if (instance == 0) {
return (DDI_FAILURE);
DDI_PSEUDO, 0);
return (DDI_FAILURE);
return (DDI_FAILURE);
if (rv == 0) {
if (rv != 0) {
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_FAILURE);
if (instance != 0) {
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
int flag)
int error;
if (error)
goto err;
goto err;
err:
return (error);
int flag)
int error;
if (error)
return (EFAULT);
return (EPERM);
int err = 0;
int rdfiles = 0;
goto out;
rdfiles++;
if (readonly)
goto out;
err = 0;
out:
return (err);
int err = 0;
return (err);
return (err);
int error;
return (EINVAL);
if (error != 0)
return (error);
return (error);
char *marker;
int error;
int ret;
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (EINVAL);
if (error != 0)
return (error);
for (i = 0; i < sizeof (struct crypto_meta); i++) {
return (EINVAL);
if (error != 0)
return (error);
sizeof (lofi_crypto_magic));
for (i = 0; i < LOFI_COMPRESS_FUNCTIONS; i++) {
int compress_index;
int error;
if (error != 0)
return (error);
return (ENOTSUP);
goto err;
} else if (*idp == 0) {
goto err;
goto err;
goto err;
goto err;
err:
return (error);
return (error);
goto err;
!= DDI_PROP_SUCCESS)
goto err;
!= NDI_SUCCESS)
goto err;
return (error);
goto done;
err:
done:
return (error);
char *p = NULL;
if (p != NULL)
int error;
int error;
int flag;
if (error != 0)
return (error);
NULL) == 0) {
goto err;
if (error) {
&vp, 0, 0);
if (error)
goto err;
goto err;
if (error)
goto err;
goto err;
if (pickminor) {
goto err;
goto err;
goto err;
goto err;
goto err;
!= DDI_PROP_SUCCESS) {
goto err;
if (rvalp)
err:
return (error);
int err;
if (err != 0)
return (err);
if (byfilename) {
&lsp)) != 0) {
return (err);
return (ENXIO);
return (ENXIO);
goto out;
return (EBUSY);
out:
int error;
if (error != 0)
return (error);
switch (which) {
case LOFI_GET_FILENAME:
return (EINVAL);
return (ENXIO);
return (error);
case LOFI_GET_MINOR:
if (error != 0) {
return (error);
return (error);
case LOFI_CHECK_COMPRESSED:
if (error != 0) {
return (error);
return (error);
return (EINVAL);
int rval;
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32: {
goto err;
case DDI_MODEL_NONE:
goto err;
goto err;
goto err;
goto err;
err:
return (rval);
int *rvalp)
int error;
int id;
if (id == 0) {
switch (cmd) {
case LOFI_MAP_FILE:
return (EPERM);
case LOFI_MAP_FILE_MINOR:
return (EPERM);
case LOFI_UNMAP_FILE:
return (EPERM);
case LOFI_UNMAP_FILE_MINOR:
return (EPERM);
case LOFI_GET_FILENAME:
case LOFI_GET_MINOR:
case LOFI_GET_MAXMINOR:
id = 0;
if (i > id)
id = i;
if (error)
return (EFAULT);
case LOFI_CHECK_COMPRESSED:
return (EINVAL);
return (ENXIO);
return (error);
return (EIO);
switch (cmd) {
case DKIOCGMEDIAINFO:
case DKIOCGMEDIAINFOEXT: {
int size;
return (EFAULT);
case DKIOCREMOVABLE: {
return (EFAULT);
case DKIOCGVTOC: {
case DDI_MODEL_ILP32: {
return (EFAULT);
case DDI_MODEL_NONE:
return (EFAULT);
case DKIOCINFO: {
return (EFAULT);
case DKIOCG_VIRTGEOM:
case DKIOCG_PHYGEOM:
case DKIOCGGEOM:
if (error)
return (EFAULT);
case DKIOCSTATE:
flag) != 0)
return (EFAULT);
return (EINTR);
return (EFAULT);
case USCSICMD: {
return (EFAULT);
return (EFAULT);
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32: {
flag) != 0)
return (EFAULT);
case DDI_MODEL_NONE:
flag) != 0)
return (EFAULT);
return (EFAULT);
return (EFAULT);
#ifdef DEBUG
return (ENOTTY);
&lofi_ops,
&modldrv,
_init(void)
int error;
sizeof (struct lofi_state), 0);
if (error) {
return (error);
return (DDI_FAILURE);
if (error == 0)
if (error) {
return (error);
_fini(void)
int error;
return (EBUSY);
if (error)
return (error);
return (error);