1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 221544Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/zfs_context.h> 29789Sahrens #include <sys/spa.h> 30789Sahrens #include <sys/vdev_file.h> 31789Sahrens #include <sys/vdev_impl.h> 32789Sahrens #include <sys/zio.h> 33789Sahrens #include <sys/fs/zfs.h> 34789Sahrens 35789Sahrens /* 36789Sahrens * Virtual device vector for files. 37789Sahrens */ 38789Sahrens 39789Sahrens static int 40789Sahrens vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) 41789Sahrens { 42789Sahrens vdev_file_t *vf; 43789Sahrens vnode_t *vp; 44789Sahrens vattr_t vattr; 45789Sahrens int error; 46789Sahrens 47789Sahrens /* 48789Sahrens * We must have a pathname, and it must be absolute. 49789Sahrens */ 50789Sahrens if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') { 51789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL; 52789Sahrens return (EINVAL); 53789Sahrens } 54789Sahrens 55789Sahrens vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP); 56789Sahrens 57789Sahrens /* 58789Sahrens * We always open the files from the root of the global zone, even if 59789Sahrens * we're in a local zone. If the user has gotten to this point, the 60789Sahrens * administrator has already decided that the pool should be available 61789Sahrens * to local zone users, so the underlying devices should be as well. 62789Sahrens */ 63789Sahrens ASSERT(vd->vdev_path != NULL && vd->vdev_path[0] == '/'); 64789Sahrens error = vn_openat(vd->vdev_path + 1, UIO_SYSSPACE, spa_mode | FOFFMAX, 65789Sahrens 0, &vp, 0, 0, rootdir); 66789Sahrens 67789Sahrens if (error) { 68789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 69789Sahrens return (error); 70789Sahrens } 71789Sahrens 72789Sahrens vf->vf_vnode = vp; 73789Sahrens 74789Sahrens #ifdef _KERNEL 75789Sahrens /* 76789Sahrens * Make sure it's a regular file. 77789Sahrens */ 78789Sahrens if (vp->v_type != VREG) { 79789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 80789Sahrens return (ENODEV); 81789Sahrens } 82789Sahrens #endif 83789Sahrens 84789Sahrens /* 85789Sahrens * Determine the physical size of the file. 86789Sahrens */ 87789Sahrens vattr.va_mask = AT_SIZE; 88789Sahrens error = VOP_GETATTR(vp, &vattr, 0, kcred); 89789Sahrens if (error) { 90789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 91789Sahrens return (error); 92789Sahrens } 93789Sahrens 94789Sahrens *psize = vattr.va_size; 95789Sahrens *ashift = SPA_MINBLOCKSHIFT; 96789Sahrens 97789Sahrens return (0); 98789Sahrens } 99789Sahrens 100789Sahrens static void 101789Sahrens vdev_file_close(vdev_t *vd) 102789Sahrens { 103789Sahrens vdev_file_t *vf = vd->vdev_tsd; 104789Sahrens 105789Sahrens if (vf == NULL) 106789Sahrens return; 107789Sahrens 108789Sahrens if (vf->vf_vnode != NULL) { 109789Sahrens (void) VOP_PUTPAGE(vf->vf_vnode, 0, 0, B_INVAL, kcred); 110789Sahrens (void) VOP_CLOSE(vf->vf_vnode, spa_mode, 1, 0, kcred); 111789Sahrens VN_RELE(vf->vf_vnode); 112789Sahrens } 113789Sahrens 114789Sahrens kmem_free(vf, sizeof (vdev_file_t)); 115789Sahrens vd->vdev_tsd = NULL; 116789Sahrens } 117789Sahrens 118789Sahrens static void 119789Sahrens vdev_file_io_start(zio_t *zio) 120789Sahrens { 121789Sahrens vdev_t *vd = zio->io_vd; 122789Sahrens vdev_file_t *vf = vd->vdev_tsd; 123789Sahrens ssize_t resid; 124789Sahrens int error; 125789Sahrens 126789Sahrens if (zio->io_type == ZIO_TYPE_IOCTL) { 127789Sahrens zio_vdev_io_bypass(zio); 128789Sahrens 129789Sahrens /* XXPOLICY */ 130789Sahrens if (vdev_is_dead(vd)) { 131789Sahrens zio->io_error = ENXIO; 132789Sahrens zio_next_stage_async(zio); 133789Sahrens return; 134789Sahrens } 135789Sahrens 136789Sahrens switch (zio->io_cmd) { 137789Sahrens case DKIOCFLUSHWRITECACHE: 138789Sahrens zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, 139789Sahrens kcred); 140789Sahrens dprintf("fsync(%s) = %d\n", vdev_description(vd), 141789Sahrens zio->io_error); 142789Sahrens break; 143789Sahrens default: 144789Sahrens zio->io_error = ENOTSUP; 145789Sahrens } 146789Sahrens 147789Sahrens zio_next_stage_async(zio); 148789Sahrens return; 149789Sahrens } 150789Sahrens 151*3059Sahrens /* 152*3059Sahrens * In the kernel, don't bother double-caching, but in userland, 153*3059Sahrens * we want to test the vdev_cache code. 154*3059Sahrens */ 155*3059Sahrens #ifndef _KERNEL 156789Sahrens if (zio->io_type == ZIO_TYPE_READ && vdev_cache_read(zio) == 0) 157789Sahrens return; 158*3059Sahrens #endif 159789Sahrens 160789Sahrens if ((zio = vdev_queue_io(zio)) == NULL) 161789Sahrens return; 162789Sahrens 163789Sahrens /* XXPOLICY */ 164789Sahrens error = vdev_is_dead(vd) ? ENXIO : vdev_error_inject(vd, zio); 165789Sahrens if (error) { 166789Sahrens zio->io_error = error; 167789Sahrens zio_next_stage_async(zio); 168789Sahrens return; 169789Sahrens } 170789Sahrens 171789Sahrens zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? 172789Sahrens UIO_READ : UIO_WRITE, vf->vf_vnode, zio->io_data, 173789Sahrens zio->io_size, zio->io_offset, UIO_SYSSPACE, 174789Sahrens 0, RLIM64_INFINITY, kcred, &resid); 175789Sahrens 176789Sahrens if (resid != 0 && zio->io_error == 0) 177789Sahrens zio->io_error = ENOSPC; 178789Sahrens 179789Sahrens zio_next_stage_async(zio); 180789Sahrens } 181789Sahrens 182789Sahrens static void 183789Sahrens vdev_file_io_done(zio_t *zio) 184789Sahrens { 185789Sahrens vdev_queue_io_done(zio); 186789Sahrens 187*3059Sahrens #ifndef _KERNEL 188789Sahrens if (zio->io_type == ZIO_TYPE_WRITE) 189789Sahrens vdev_cache_write(zio); 190*3059Sahrens #endif 191789Sahrens 1921544Seschrock if (zio_injection_enabled && zio->io_error == 0) 1931544Seschrock zio->io_error = zio_handle_device_injection(zio->io_vd, EIO); 1941544Seschrock 195789Sahrens zio_next_stage(zio); 196789Sahrens } 197789Sahrens 198789Sahrens vdev_ops_t vdev_file_ops = { 199789Sahrens vdev_file_open, 200789Sahrens vdev_file_close, 201789Sahrens vdev_default_asize, 202789Sahrens vdev_file_io_start, 203789Sahrens vdev_file_io_done, 204789Sahrens NULL, 205789Sahrens VDEV_TYPE_FILE, /* name of this vdev type */ 206789Sahrens B_TRUE /* leaf vdev */ 207789Sahrens }; 208789Sahrens 209789Sahrens /* 210789Sahrens * From userland we access disks just like files. 211789Sahrens */ 212789Sahrens #ifndef _KERNEL 213789Sahrens 214789Sahrens vdev_ops_t vdev_disk_ops = { 215789Sahrens vdev_file_open, 216789Sahrens vdev_file_close, 217789Sahrens vdev_default_asize, 218789Sahrens vdev_file_io_start, 219789Sahrens vdev_file_io_done, 220789Sahrens NULL, 221789Sahrens VDEV_TYPE_DISK, /* name of this vdev type */ 222789Sahrens B_TRUE /* leaf vdev */ 223789Sahrens }; 224789Sahrens 225789Sahrens #endif 226