1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1544 eschrock * Common Development and Distribution License (the "License"). 6 1544 eschrock * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 789 ahrens /* 22 10850 George * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 789 ahrens * Use is subject to license terms. 24 789 ahrens */ 25 789 ahrens 26 789 ahrens #include <sys/zfs_context.h> 27 789 ahrens #include <sys/spa.h> 28 789 ahrens #include <sys/vdev_file.h> 29 789 ahrens #include <sys/vdev_impl.h> 30 789 ahrens #include <sys/zio.h> 31 789 ahrens #include <sys/fs/zfs.h> 32 6976 eschrock #include <sys/fm/fs/zfs.h> 33 789 ahrens 34 789 ahrens /* 35 789 ahrens * Virtual device vector for files. 36 789 ahrens */ 37 789 ahrens 38 789 ahrens static int 39 7754 Jeff vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) 40 789 ahrens { 41 789 ahrens vdev_file_t *vf; 42 789 ahrens vnode_t *vp; 43 7754 Jeff vattr_t vattr; 44 789 ahrens int error; 45 789 ahrens 46 789 ahrens /* 47 789 ahrens * We must have a pathname, and it must be absolute. 48 789 ahrens */ 49 789 ahrens if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') { 50 789 ahrens vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL; 51 789 ahrens return (EINVAL); 52 789 ahrens } 53 789 ahrens 54 10850 George /* 55 10850 George * Reopen the device if it's not currently open. Otherwise, 56 10850 George * just update the physical size of the device. 57 10850 George */ 58 10850 George if (vd->vdev_tsd != NULL) { 59 10850 George ASSERT(vd->vdev_reopening); 60 10850 George vf = vd->vdev_tsd; 61 10850 George goto skip_open; 62 10850 George } 63 10850 George 64 789 ahrens vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP); 65 789 ahrens 66 789 ahrens /* 67 789 ahrens * We always open the files from the root of the global zone, even if 68 789 ahrens * we're in a local zone. If the user has gotten to this point, the 69 789 ahrens * administrator has already decided that the pool should be available 70 789 ahrens * to local zone users, so the underlying devices should be as well. 71 789 ahrens */ 72 789 ahrens ASSERT(vd->vdev_path != NULL && vd->vdev_path[0] == '/'); 73 5329 gw25295 error = vn_openat(vd->vdev_path + 1, UIO_SYSSPACE, 74 8241 Jeff spa_mode(vd->vdev_spa) | FOFFMAX, 0, &vp, 0, 0, rootdir, -1); 75 789 ahrens 76 789 ahrens if (error) { 77 789 ahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 78 789 ahrens return (error); 79 789 ahrens } 80 789 ahrens 81 789 ahrens vf->vf_vnode = vp; 82 789 ahrens 83 789 ahrens #ifdef _KERNEL 84 789 ahrens /* 85 789 ahrens * Make sure it's a regular file. 86 789 ahrens */ 87 789 ahrens if (vp->v_type != VREG) { 88 789 ahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 89 789 ahrens return (ENODEV); 90 789 ahrens } 91 789 ahrens #endif 92 10850 George 93 10850 George skip_open: 94 789 ahrens /* 95 789 ahrens * Determine the physical size of the file. 96 789 ahrens */ 97 789 ahrens vattr.va_mask = AT_SIZE; 98 5331 amw error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL); 99 789 ahrens if (error) { 100 789 ahrens vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 101 789 ahrens return (error); 102 789 ahrens } 103 789 ahrens 104 789 ahrens *psize = vattr.va_size; 105 789 ahrens *ashift = SPA_MINBLOCKSHIFT; 106 789 ahrens 107 789 ahrens return (0); 108 789 ahrens } 109 789 ahrens 110 789 ahrens static void 111 789 ahrens vdev_file_close(vdev_t *vd) 112 789 ahrens { 113 789 ahrens vdev_file_t *vf = vd->vdev_tsd; 114 789 ahrens 115 10850 George if (vd->vdev_reopening || vf == NULL) 116 789 ahrens return; 117 789 ahrens 118 789 ahrens if (vf->vf_vnode != NULL) { 119 5331 amw (void) VOP_PUTPAGE(vf->vf_vnode, 0, 0, B_INVAL, kcred, NULL); 120 8241 Jeff (void) VOP_CLOSE(vf->vf_vnode, spa_mode(vd->vdev_spa), 1, 0, 121 8241 Jeff kcred, NULL); 122 789 ahrens VN_RELE(vf->vf_vnode); 123 789 ahrens } 124 789 ahrens 125 789 ahrens kmem_free(vf, sizeof (vdev_file_t)); 126 789 ahrens vd->vdev_tsd = NULL; 127 789 ahrens } 128 789 ahrens 129 5329 gw25295 static int 130 789 ahrens vdev_file_io_start(zio_t *zio) 131 789 ahrens { 132 789 ahrens vdev_t *vd = zio->io_vd; 133 789 ahrens vdev_file_t *vf = vd->vdev_tsd; 134 789 ahrens ssize_t resid; 135 789 ahrens 136 789 ahrens if (zio->io_type == ZIO_TYPE_IOCTL) { 137 789 ahrens /* XXPOLICY */ 138 5329 gw25295 if (!vdev_readable(vd)) { 139 789 ahrens zio->io_error = ENXIO; 140 5530 bonwick return (ZIO_PIPELINE_CONTINUE); 141 789 ahrens } 142 789 ahrens 143 789 ahrens switch (zio->io_cmd) { 144 789 ahrens case DKIOCFLUSHWRITECACHE: 145 789 ahrens zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, 146 5331 amw kcred, NULL); 147 789 ahrens break; 148 789 ahrens default: 149 789 ahrens zio->io_error = ENOTSUP; 150 789 ahrens } 151 789 ahrens 152 5530 bonwick return (ZIO_PIPELINE_CONTINUE); 153 789 ahrens } 154 789 ahrens 155 789 ahrens zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? 156 789 ahrens UIO_READ : UIO_WRITE, vf->vf_vnode, zio->io_data, 157 789 ahrens zio->io_size, zio->io_offset, UIO_SYSSPACE, 158 789 ahrens 0, RLIM64_INFINITY, kcred, &resid); 159 789 ahrens 160 789 ahrens if (resid != 0 && zio->io_error == 0) 161 789 ahrens zio->io_error = ENOSPC; 162 789 ahrens 163 5530 bonwick zio_interrupt(zio); 164 5530 bonwick 165 5530 bonwick return (ZIO_PIPELINE_STOP); 166 789 ahrens } 167 789 ahrens 168 7754 Jeff /* ARGSUSED */ 169 7754 Jeff static void 170 789 ahrens vdev_file_io_done(zio_t *zio) 171 789 ahrens { 172 789 ahrens } 173 789 ahrens 174 789 ahrens vdev_ops_t vdev_file_ops = { 175 789 ahrens vdev_file_open, 176 789 ahrens vdev_file_close, 177 789 ahrens vdev_default_asize, 178 789 ahrens vdev_file_io_start, 179 789 ahrens vdev_file_io_done, 180 789 ahrens NULL, 181 789 ahrens VDEV_TYPE_FILE, /* name of this vdev type */ 182 789 ahrens B_TRUE /* leaf vdev */ 183 789 ahrens }; 184 789 ahrens 185 789 ahrens /* 186 789 ahrens * From userland we access disks just like files. 187 789 ahrens */ 188 789 ahrens #ifndef _KERNEL 189 789 ahrens 190 789 ahrens vdev_ops_t vdev_disk_ops = { 191 789 ahrens vdev_file_open, 192 789 ahrens vdev_file_close, 193 789 ahrens vdev_default_asize, 194 789 ahrens vdev_file_io_start, 195 789 ahrens vdev_file_io_done, 196 789 ahrens NULL, 197 789 ahrens VDEV_TYPE_DISK, /* name of this vdev type */ 198 789 ahrens B_TRUE /* leaf vdev */ 199 789 ahrens }; 200 789 ahrens 201 789 ahrens #endif 202