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 /* 226523Sek110237 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #include <sys/zfs_context.h> 27789Sahrens #include <sys/spa.h> 28789Sahrens #include <sys/vdev_file.h> 29789Sahrens #include <sys/vdev_impl.h> 30789Sahrens #include <sys/zio.h> 31789Sahrens #include <sys/fs/zfs.h> 326976Seschrock #include <sys/fm/fs/zfs.h> 33789Sahrens 34789Sahrens /* 35789Sahrens * Virtual device vector for files. 36789Sahrens */ 37789Sahrens 38789Sahrens static int 39*7754SJeff.Bonwick@Sun.COM vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) 40789Sahrens { 41789Sahrens vdev_file_t *vf; 42789Sahrens vnode_t *vp; 43*7754SJeff.Bonwick@Sun.COM vattr_t vattr; 44789Sahrens int error; 45789Sahrens 46789Sahrens /* 47789Sahrens * We must have a pathname, and it must be absolute. 48789Sahrens */ 49789Sahrens if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') { 50789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL; 51789Sahrens return (EINVAL); 52789Sahrens } 53789Sahrens 54789Sahrens vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP); 55789Sahrens 56789Sahrens /* 57789Sahrens * We always open the files from the root of the global zone, even if 58789Sahrens * we're in a local zone. If the user has gotten to this point, the 59789Sahrens * administrator has already decided that the pool should be available 60789Sahrens * to local zone users, so the underlying devices should be as well. 61789Sahrens */ 62789Sahrens ASSERT(vd->vdev_path != NULL && vd->vdev_path[0] == '/'); 635329Sgw25295 error = vn_openat(vd->vdev_path + 1, UIO_SYSSPACE, 645331Samw spa_mode | FOFFMAX, 0, &vp, 0, 0, rootdir, -1); 65789Sahrens 66789Sahrens if (error) { 67789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 68789Sahrens return (error); 69789Sahrens } 70789Sahrens 71789Sahrens vf->vf_vnode = vp; 72789Sahrens 73789Sahrens #ifdef _KERNEL 74789Sahrens /* 75789Sahrens * Make sure it's a regular file. 76789Sahrens */ 77789Sahrens if (vp->v_type != VREG) { 78789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 79789Sahrens return (ENODEV); 80789Sahrens } 81789Sahrens #endif 82789Sahrens /* 83789Sahrens * Determine the physical size of the file. 84789Sahrens */ 85789Sahrens vattr.va_mask = AT_SIZE; 865331Samw error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL); 87789Sahrens if (error) { 88789Sahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 89789Sahrens return (error); 90789Sahrens } 91789Sahrens 92789Sahrens *psize = vattr.va_size; 93789Sahrens *ashift = SPA_MINBLOCKSHIFT; 94789Sahrens 95789Sahrens return (0); 96789Sahrens } 97789Sahrens 98789Sahrens static void 99789Sahrens vdev_file_close(vdev_t *vd) 100789Sahrens { 101789Sahrens vdev_file_t *vf = vd->vdev_tsd; 102789Sahrens 103789Sahrens if (vf == NULL) 104789Sahrens return; 105789Sahrens 106789Sahrens if (vf->vf_vnode != NULL) { 1075331Samw (void) VOP_PUTPAGE(vf->vf_vnode, 0, 0, B_INVAL, kcred, NULL); 1085331Samw (void) VOP_CLOSE(vf->vf_vnode, spa_mode, 1, 0, kcred, NULL); 109789Sahrens VN_RELE(vf->vf_vnode); 110789Sahrens } 111789Sahrens 112789Sahrens kmem_free(vf, sizeof (vdev_file_t)); 113789Sahrens vd->vdev_tsd = NULL; 114789Sahrens } 115789Sahrens 1165329Sgw25295 static int 117789Sahrens vdev_file_io_start(zio_t *zio) 118789Sahrens { 119789Sahrens vdev_t *vd = zio->io_vd; 120789Sahrens vdev_file_t *vf = vd->vdev_tsd; 121789Sahrens ssize_t resid; 122789Sahrens 123789Sahrens if (zio->io_type == ZIO_TYPE_IOCTL) { 124789Sahrens /* XXPOLICY */ 1255329Sgw25295 if (!vdev_readable(vd)) { 126789Sahrens zio->io_error = ENXIO; 1275530Sbonwick return (ZIO_PIPELINE_CONTINUE); 128789Sahrens } 129789Sahrens 130789Sahrens switch (zio->io_cmd) { 131789Sahrens case DKIOCFLUSHWRITECACHE: 132789Sahrens zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, 1335331Samw kcred, NULL); 134789Sahrens break; 135789Sahrens default: 136789Sahrens zio->io_error = ENOTSUP; 137789Sahrens } 138789Sahrens 1395530Sbonwick return (ZIO_PIPELINE_CONTINUE); 140789Sahrens } 141789Sahrens 142789Sahrens zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? 143789Sahrens UIO_READ : UIO_WRITE, vf->vf_vnode, zio->io_data, 144789Sahrens zio->io_size, zio->io_offset, UIO_SYSSPACE, 145789Sahrens 0, RLIM64_INFINITY, kcred, &resid); 146789Sahrens 147789Sahrens if (resid != 0 && zio->io_error == 0) 148789Sahrens zio->io_error = ENOSPC; 149789Sahrens 1505530Sbonwick zio_interrupt(zio); 1515530Sbonwick 1525530Sbonwick return (ZIO_PIPELINE_STOP); 153789Sahrens } 154789Sahrens 155*7754SJeff.Bonwick@Sun.COM /* ARGSUSED */ 156*7754SJeff.Bonwick@Sun.COM static void 157789Sahrens vdev_file_io_done(zio_t *zio) 158789Sahrens { 159789Sahrens } 160789Sahrens 161789Sahrens vdev_ops_t vdev_file_ops = { 162789Sahrens vdev_file_open, 163789Sahrens vdev_file_close, 164789Sahrens vdev_default_asize, 165789Sahrens vdev_file_io_start, 166789Sahrens vdev_file_io_done, 167789Sahrens NULL, 168789Sahrens VDEV_TYPE_FILE, /* name of this vdev type */ 169789Sahrens B_TRUE /* leaf vdev */ 170789Sahrens }; 171789Sahrens 172789Sahrens /* 173789Sahrens * From userland we access disks just like files. 174789Sahrens */ 175789Sahrens #ifndef _KERNEL 176789Sahrens 177789Sahrens vdev_ops_t vdev_disk_ops = { 178789Sahrens vdev_file_open, 179789Sahrens vdev_file_close, 180789Sahrens vdev_default_asize, 181789Sahrens vdev_file_io_start, 182789Sahrens vdev_file_io_done, 183789Sahrens NULL, 184789Sahrens VDEV_TYPE_DISK, /* name of this vdev type */ 185789Sahrens B_TRUE /* leaf vdev */ 186789Sahrens }; 187789Sahrens 188789Sahrens #endif 189