1*d2a8fad3SMartin Matuska /* 2*d2a8fad3SMartin Matuska * CDDL HEADER START 3*d2a8fad3SMartin Matuska * 4*d2a8fad3SMartin Matuska * The contents of this file are subject to the terms of the 5*d2a8fad3SMartin Matuska * Common Development and Distribution License (the "License"). 6*d2a8fad3SMartin Matuska * You may not use this file except in compliance with the License. 7*d2a8fad3SMartin Matuska * 8*d2a8fad3SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d2a8fad3SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10*d2a8fad3SMartin Matuska * See the License for the specific language governing permissions 11*d2a8fad3SMartin Matuska * and limitations under the License. 12*d2a8fad3SMartin Matuska * 13*d2a8fad3SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14*d2a8fad3SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d2a8fad3SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16*d2a8fad3SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17*d2a8fad3SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18*d2a8fad3SMartin Matuska * 19*d2a8fad3SMartin Matuska * CDDL HEADER END 20*d2a8fad3SMartin Matuska */ 21*d2a8fad3SMartin Matuska /* 22*d2a8fad3SMartin Matuska * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23*d2a8fad3SMartin Matuska * Copyright (c) 2011, 2020 by Delphix. All rights reserved. 24*d2a8fad3SMartin Matuska * Copyright (c) 2025, Klara, Inc. 25*d2a8fad3SMartin Matuska */ 26*d2a8fad3SMartin Matuska 27*d2a8fad3SMartin Matuska #include <sys/zfs_context.h> 28*d2a8fad3SMartin Matuska #include <sys/spa.h> 29*d2a8fad3SMartin Matuska #include <sys/vdev_file.h> 30*d2a8fad3SMartin Matuska #include <sys/vdev_impl.h> 31*d2a8fad3SMartin Matuska #include <sys/zio.h> 32*d2a8fad3SMartin Matuska #include <sys/fs/zfs.h> 33*d2a8fad3SMartin Matuska #include <sys/fm/fs/zfs.h> 34*d2a8fad3SMartin Matuska #include <sys/abd.h> 35*d2a8fad3SMartin Matuska #include <sys/stat.h> 36*d2a8fad3SMartin Matuska 37*d2a8fad3SMartin Matuska /* 38*d2a8fad3SMartin Matuska * Virtual device vector for files. 39*d2a8fad3SMartin Matuska */ 40*d2a8fad3SMartin Matuska 41*d2a8fad3SMartin Matuska static taskq_t *vdev_file_taskq; 42*d2a8fad3SMartin Matuska 43*d2a8fad3SMartin Matuska /* 44*d2a8fad3SMartin Matuska * By default, the logical/physical ashift for file vdevs is set to 45*d2a8fad3SMartin Matuska * SPA_MINBLOCKSHIFT (9). This allows all file vdevs to use 512B (1 << 9) 46*d2a8fad3SMartin Matuska * blocksizes. Users may opt to change one or both of these for testing 47*d2a8fad3SMartin Matuska * or performance reasons. Care should be taken as these values will 48*d2a8fad3SMartin Matuska * impact the vdev_ashift setting which can only be set at vdev creation 49*d2a8fad3SMartin Matuska * time. 50*d2a8fad3SMartin Matuska */ 51*d2a8fad3SMartin Matuska static uint_t vdev_file_logical_ashift = SPA_MINBLOCKSHIFT; 52*d2a8fad3SMartin Matuska static uint_t vdev_file_physical_ashift = SPA_MINBLOCKSHIFT; 53*d2a8fad3SMartin Matuska 54*d2a8fad3SMartin Matuska void 55*d2a8fad3SMartin Matuska vdev_file_init(void) 56*d2a8fad3SMartin Matuska { 57*d2a8fad3SMartin Matuska vdev_file_taskq = taskq_create("z_vdev_file", MAX(boot_ncpus, 16), 58*d2a8fad3SMartin Matuska minclsyspri, boot_ncpus, INT_MAX, TASKQ_DYNAMIC); 59*d2a8fad3SMartin Matuska 60*d2a8fad3SMartin Matuska VERIFY(vdev_file_taskq); 61*d2a8fad3SMartin Matuska } 62*d2a8fad3SMartin Matuska 63*d2a8fad3SMartin Matuska void 64*d2a8fad3SMartin Matuska vdev_file_fini(void) 65*d2a8fad3SMartin Matuska { 66*d2a8fad3SMartin Matuska taskq_destroy(vdev_file_taskq); 67*d2a8fad3SMartin Matuska } 68*d2a8fad3SMartin Matuska 69*d2a8fad3SMartin Matuska static void 70*d2a8fad3SMartin Matuska vdev_file_hold(vdev_t *vd) 71*d2a8fad3SMartin Matuska { 72*d2a8fad3SMartin Matuska ASSERT3P(vd->vdev_path, !=, NULL); 73*d2a8fad3SMartin Matuska } 74*d2a8fad3SMartin Matuska 75*d2a8fad3SMartin Matuska static void 76*d2a8fad3SMartin Matuska vdev_file_rele(vdev_t *vd) 77*d2a8fad3SMartin Matuska { 78*d2a8fad3SMartin Matuska ASSERT3P(vd->vdev_path, !=, NULL); 79*d2a8fad3SMartin Matuska } 80*d2a8fad3SMartin Matuska 81*d2a8fad3SMartin Matuska static mode_t 82*d2a8fad3SMartin Matuska vdev_file_open_mode(spa_mode_t spa_mode) 83*d2a8fad3SMartin Matuska { 84*d2a8fad3SMartin Matuska mode_t mode = 0; 85*d2a8fad3SMartin Matuska 86*d2a8fad3SMartin Matuska if ((spa_mode & SPA_MODE_READ) && (spa_mode & SPA_MODE_WRITE)) { 87*d2a8fad3SMartin Matuska mode = O_RDWR; 88*d2a8fad3SMartin Matuska } else if (spa_mode & SPA_MODE_READ) { 89*d2a8fad3SMartin Matuska mode = O_RDONLY; 90*d2a8fad3SMartin Matuska } else if (spa_mode & SPA_MODE_WRITE) { 91*d2a8fad3SMartin Matuska mode = O_WRONLY; 92*d2a8fad3SMartin Matuska } 93*d2a8fad3SMartin Matuska 94*d2a8fad3SMartin Matuska return (mode | O_LARGEFILE); 95*d2a8fad3SMartin Matuska } 96*d2a8fad3SMartin Matuska 97*d2a8fad3SMartin Matuska static int 98*d2a8fad3SMartin Matuska vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, 99*d2a8fad3SMartin Matuska uint64_t *logical_ashift, uint64_t *physical_ashift) 100*d2a8fad3SMartin Matuska { 101*d2a8fad3SMartin Matuska vdev_file_t *vf; 102*d2a8fad3SMartin Matuska zfs_file_t *fp; 103*d2a8fad3SMartin Matuska zfs_file_attr_t zfa; 104*d2a8fad3SMartin Matuska int error; 105*d2a8fad3SMartin Matuska 106*d2a8fad3SMartin Matuska /* 107*d2a8fad3SMartin Matuska * Rotational optimizations only make sense on block devices. 108*d2a8fad3SMartin Matuska */ 109*d2a8fad3SMartin Matuska vd->vdev_nonrot = B_TRUE; 110*d2a8fad3SMartin Matuska 111*d2a8fad3SMartin Matuska /* 112*d2a8fad3SMartin Matuska * Allow TRIM on file based vdevs. This may not always be supported, 113*d2a8fad3SMartin Matuska * since it depends on your kernel version and underlying filesystem 114*d2a8fad3SMartin Matuska * type but it is always safe to attempt. 115*d2a8fad3SMartin Matuska */ 116*d2a8fad3SMartin Matuska vd->vdev_has_trim = B_TRUE; 117*d2a8fad3SMartin Matuska 118*d2a8fad3SMartin Matuska /* 119*d2a8fad3SMartin Matuska * Disable secure TRIM on file based vdevs. There is no way to 120*d2a8fad3SMartin Matuska * request this behavior from the underlying filesystem. 121*d2a8fad3SMartin Matuska */ 122*d2a8fad3SMartin Matuska vd->vdev_has_securetrim = B_FALSE; 123*d2a8fad3SMartin Matuska 124*d2a8fad3SMartin Matuska /* 125*d2a8fad3SMartin Matuska * We must have a pathname, and it must be absolute. 126*d2a8fad3SMartin Matuska */ 127*d2a8fad3SMartin Matuska if (vd->vdev_path == NULL || vd->vdev_path[0] != '/') { 128*d2a8fad3SMartin Matuska vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL; 129*d2a8fad3SMartin Matuska return (SET_ERROR(EINVAL)); 130*d2a8fad3SMartin Matuska } 131*d2a8fad3SMartin Matuska 132*d2a8fad3SMartin Matuska /* 133*d2a8fad3SMartin Matuska * Reopen the device if it's not currently open. Otherwise, 134*d2a8fad3SMartin Matuska * just update the physical size of the device. 135*d2a8fad3SMartin Matuska */ 136*d2a8fad3SMartin Matuska if (vd->vdev_tsd != NULL) { 137*d2a8fad3SMartin Matuska ASSERT(vd->vdev_reopening); 138*d2a8fad3SMartin Matuska vf = vd->vdev_tsd; 139*d2a8fad3SMartin Matuska goto skip_open; 140*d2a8fad3SMartin Matuska } 141*d2a8fad3SMartin Matuska 142*d2a8fad3SMartin Matuska vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP); 143*d2a8fad3SMartin Matuska 144*d2a8fad3SMartin Matuska /* 145*d2a8fad3SMartin Matuska * We always open the files from the root of the global zone, even if 146*d2a8fad3SMartin Matuska * we're in a local zone. If the user has gotten to this point, the 147*d2a8fad3SMartin Matuska * administrator has already decided that the pool should be available 148*d2a8fad3SMartin Matuska * to local zone users, so the underlying devices should be as well. 149*d2a8fad3SMartin Matuska */ 150*d2a8fad3SMartin Matuska ASSERT3P(vd->vdev_path, !=, NULL); 151*d2a8fad3SMartin Matuska ASSERT3S(vd->vdev_path[0], ==, '/'); 152*d2a8fad3SMartin Matuska 153*d2a8fad3SMartin Matuska error = zfs_file_open(vd->vdev_path, 154*d2a8fad3SMartin Matuska vdev_file_open_mode(spa_mode(vd->vdev_spa)), 0, &fp); 155*d2a8fad3SMartin Matuska if (error) { 156*d2a8fad3SMartin Matuska vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 157*d2a8fad3SMartin Matuska return (error); 158*d2a8fad3SMartin Matuska } 159*d2a8fad3SMartin Matuska 160*d2a8fad3SMartin Matuska vf->vf_file = fp; 161*d2a8fad3SMartin Matuska 162*d2a8fad3SMartin Matuska #ifdef _KERNEL 163*d2a8fad3SMartin Matuska /* 164*d2a8fad3SMartin Matuska * Make sure it's a regular file. 165*d2a8fad3SMartin Matuska */ 166*d2a8fad3SMartin Matuska if (zfs_file_getattr(fp, &zfa)) { 167*d2a8fad3SMartin Matuska return (SET_ERROR(ENODEV)); 168*d2a8fad3SMartin Matuska } 169*d2a8fad3SMartin Matuska if (!S_ISREG(zfa.zfa_mode)) { 170*d2a8fad3SMartin Matuska vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 171*d2a8fad3SMartin Matuska return (SET_ERROR(ENODEV)); 172*d2a8fad3SMartin Matuska } 173*d2a8fad3SMartin Matuska #endif 174*d2a8fad3SMartin Matuska 175*d2a8fad3SMartin Matuska skip_open: 176*d2a8fad3SMartin Matuska 177*d2a8fad3SMartin Matuska error = zfs_file_getattr(vf->vf_file, &zfa); 178*d2a8fad3SMartin Matuska if (error) { 179*d2a8fad3SMartin Matuska vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED; 180*d2a8fad3SMartin Matuska return (error); 181*d2a8fad3SMartin Matuska } 182*d2a8fad3SMartin Matuska 183*d2a8fad3SMartin Matuska *max_psize = *psize = zfa.zfa_size; 184*d2a8fad3SMartin Matuska *logical_ashift = vdev_file_logical_ashift; 185*d2a8fad3SMartin Matuska *physical_ashift = vdev_file_physical_ashift; 186*d2a8fad3SMartin Matuska 187*d2a8fad3SMartin Matuska return (0); 188*d2a8fad3SMartin Matuska } 189*d2a8fad3SMartin Matuska 190*d2a8fad3SMartin Matuska static void 191*d2a8fad3SMartin Matuska vdev_file_close(vdev_t *vd) 192*d2a8fad3SMartin Matuska { 193*d2a8fad3SMartin Matuska vdev_file_t *vf = vd->vdev_tsd; 194*d2a8fad3SMartin Matuska 195*d2a8fad3SMartin Matuska if (vd->vdev_reopening || vf == NULL) 196*d2a8fad3SMartin Matuska return; 197*d2a8fad3SMartin Matuska 198*d2a8fad3SMartin Matuska if (vf->vf_file != NULL) { 199*d2a8fad3SMartin Matuska (void) zfs_file_close(vf->vf_file); 200*d2a8fad3SMartin Matuska } 201*d2a8fad3SMartin Matuska 202*d2a8fad3SMartin Matuska vd->vdev_delayed_close = B_FALSE; 203*d2a8fad3SMartin Matuska kmem_free(vf, sizeof (vdev_file_t)); 204*d2a8fad3SMartin Matuska vd->vdev_tsd = NULL; 205*d2a8fad3SMartin Matuska } 206*d2a8fad3SMartin Matuska 207*d2a8fad3SMartin Matuska static void 208*d2a8fad3SMartin Matuska vdev_file_io_strategy(void *arg) 209*d2a8fad3SMartin Matuska { 210*d2a8fad3SMartin Matuska zio_t *zio = (zio_t *)arg; 211*d2a8fad3SMartin Matuska vdev_t *vd = zio->io_vd; 212*d2a8fad3SMartin Matuska vdev_file_t *vf = vd->vdev_tsd; 213*d2a8fad3SMartin Matuska void *buf; 214*d2a8fad3SMartin Matuska ssize_t resid; 215*d2a8fad3SMartin Matuska loff_t off; 216*d2a8fad3SMartin Matuska ssize_t size; 217*d2a8fad3SMartin Matuska int err; 218*d2a8fad3SMartin Matuska 219*d2a8fad3SMartin Matuska off = zio->io_offset; 220*d2a8fad3SMartin Matuska size = zio->io_size; 221*d2a8fad3SMartin Matuska resid = 0; 222*d2a8fad3SMartin Matuska 223*d2a8fad3SMartin Matuska ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); 224*d2a8fad3SMartin Matuska if (zio->io_type == ZIO_TYPE_READ) { 225*d2a8fad3SMartin Matuska buf = abd_borrow_buf(zio->io_abd, zio->io_size); 226*d2a8fad3SMartin Matuska err = zfs_file_pread(vf->vf_file, buf, size, off, &resid); 227*d2a8fad3SMartin Matuska abd_return_buf_copy(zio->io_abd, buf, size); 228*d2a8fad3SMartin Matuska } else { 229*d2a8fad3SMartin Matuska buf = abd_borrow_buf_copy(zio->io_abd, zio->io_size); 230*d2a8fad3SMartin Matuska err = zfs_file_pwrite(vf->vf_file, buf, size, off, &resid); 231*d2a8fad3SMartin Matuska abd_return_buf(zio->io_abd, buf, size); 232*d2a8fad3SMartin Matuska } 233*d2a8fad3SMartin Matuska zio->io_error = err; 234*d2a8fad3SMartin Matuska if (resid != 0 && zio->io_error == 0) 235*d2a8fad3SMartin Matuska zio->io_error = SET_ERROR(ENOSPC); 236*d2a8fad3SMartin Matuska 237*d2a8fad3SMartin Matuska zio_delay_interrupt(zio); 238*d2a8fad3SMartin Matuska } 239*d2a8fad3SMartin Matuska 240*d2a8fad3SMartin Matuska static void 241*d2a8fad3SMartin Matuska vdev_file_io_fsync(void *arg) 242*d2a8fad3SMartin Matuska { 243*d2a8fad3SMartin Matuska zio_t *zio = (zio_t *)arg; 244*d2a8fad3SMartin Matuska vdev_file_t *vf = zio->io_vd->vdev_tsd; 245*d2a8fad3SMartin Matuska 246*d2a8fad3SMartin Matuska zio->io_error = zfs_file_fsync(vf->vf_file, O_SYNC | O_DSYNC); 247*d2a8fad3SMartin Matuska 248*d2a8fad3SMartin Matuska zio_interrupt(zio); 249*d2a8fad3SMartin Matuska } 250*d2a8fad3SMartin Matuska 251*d2a8fad3SMartin Matuska static void 252*d2a8fad3SMartin Matuska vdev_file_io_deallocate(void *arg) 253*d2a8fad3SMartin Matuska { 254*d2a8fad3SMartin Matuska zio_t *zio = (zio_t *)arg; 255*d2a8fad3SMartin Matuska vdev_file_t *vf = zio->io_vd->vdev_tsd; 256*d2a8fad3SMartin Matuska 257*d2a8fad3SMartin Matuska zio->io_error = zfs_file_deallocate(vf->vf_file, 258*d2a8fad3SMartin Matuska zio->io_offset, zio->io_size); 259*d2a8fad3SMartin Matuska 260*d2a8fad3SMartin Matuska zio_interrupt(zio); 261*d2a8fad3SMartin Matuska } 262*d2a8fad3SMartin Matuska 263*d2a8fad3SMartin Matuska static void 264*d2a8fad3SMartin Matuska vdev_file_io_start(zio_t *zio) 265*d2a8fad3SMartin Matuska { 266*d2a8fad3SMartin Matuska vdev_t *vd = zio->io_vd; 267*d2a8fad3SMartin Matuska 268*d2a8fad3SMartin Matuska if (zio->io_type == ZIO_TYPE_FLUSH) { 269*d2a8fad3SMartin Matuska /* XXPOLICY */ 270*d2a8fad3SMartin Matuska if (!vdev_readable(vd)) { 271*d2a8fad3SMartin Matuska zio->io_error = SET_ERROR(ENXIO); 272*d2a8fad3SMartin Matuska zio_interrupt(zio); 273*d2a8fad3SMartin Matuska return; 274*d2a8fad3SMartin Matuska } 275*d2a8fad3SMartin Matuska 276*d2a8fad3SMartin Matuska if (zfs_nocacheflush) { 277*d2a8fad3SMartin Matuska zio_interrupt(zio); 278*d2a8fad3SMartin Matuska return; 279*d2a8fad3SMartin Matuska } 280*d2a8fad3SMartin Matuska 281*d2a8fad3SMartin Matuska VERIFY3U(taskq_dispatch(vdev_file_taskq, 282*d2a8fad3SMartin Matuska vdev_file_io_fsync, zio, TQ_SLEEP), !=, TASKQID_INVALID); 283*d2a8fad3SMartin Matuska 284*d2a8fad3SMartin Matuska return; 285*d2a8fad3SMartin Matuska } 286*d2a8fad3SMartin Matuska 287*d2a8fad3SMartin Matuska if (zio->io_type == ZIO_TYPE_TRIM) { 288*d2a8fad3SMartin Matuska ASSERT3U(zio->io_size, !=, 0); 289*d2a8fad3SMartin Matuska 290*d2a8fad3SMartin Matuska VERIFY3U(taskq_dispatch(vdev_file_taskq, 291*d2a8fad3SMartin Matuska vdev_file_io_deallocate, zio, TQ_SLEEP), !=, 292*d2a8fad3SMartin Matuska TASKQID_INVALID); 293*d2a8fad3SMartin Matuska 294*d2a8fad3SMartin Matuska return; 295*d2a8fad3SMartin Matuska } 296*d2a8fad3SMartin Matuska 297*d2a8fad3SMartin Matuska ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); 298*d2a8fad3SMartin Matuska zio->io_target_timestamp = zio_handle_io_delay(zio); 299*d2a8fad3SMartin Matuska 300*d2a8fad3SMartin Matuska VERIFY3U(taskq_dispatch(vdev_file_taskq, vdev_file_io_strategy, zio, 301*d2a8fad3SMartin Matuska TQ_SLEEP), !=, TASKQID_INVALID); 302*d2a8fad3SMartin Matuska } 303*d2a8fad3SMartin Matuska 304*d2a8fad3SMartin Matuska static void 305*d2a8fad3SMartin Matuska vdev_file_io_done(zio_t *zio) 306*d2a8fad3SMartin Matuska { 307*d2a8fad3SMartin Matuska (void) zio; 308*d2a8fad3SMartin Matuska } 309*d2a8fad3SMartin Matuska 310*d2a8fad3SMartin Matuska vdev_ops_t vdev_file_ops = { 311*d2a8fad3SMartin Matuska .vdev_op_init = NULL, 312*d2a8fad3SMartin Matuska .vdev_op_fini = NULL, 313*d2a8fad3SMartin Matuska .vdev_op_open = vdev_file_open, 314*d2a8fad3SMartin Matuska .vdev_op_close = vdev_file_close, 315*d2a8fad3SMartin Matuska .vdev_op_asize = vdev_default_asize, 316*d2a8fad3SMartin Matuska .vdev_op_min_asize = vdev_default_min_asize, 317*d2a8fad3SMartin Matuska .vdev_op_min_alloc = NULL, 318*d2a8fad3SMartin Matuska .vdev_op_io_start = vdev_file_io_start, 319*d2a8fad3SMartin Matuska .vdev_op_io_done = vdev_file_io_done, 320*d2a8fad3SMartin Matuska .vdev_op_state_change = NULL, 321*d2a8fad3SMartin Matuska .vdev_op_need_resilver = NULL, 322*d2a8fad3SMartin Matuska .vdev_op_hold = vdev_file_hold, 323*d2a8fad3SMartin Matuska .vdev_op_rele = vdev_file_rele, 324*d2a8fad3SMartin Matuska .vdev_op_remap = NULL, 325*d2a8fad3SMartin Matuska .vdev_op_xlate = vdev_default_xlate, 326*d2a8fad3SMartin Matuska .vdev_op_rebuild_asize = NULL, 327*d2a8fad3SMartin Matuska .vdev_op_metaslab_init = NULL, 328*d2a8fad3SMartin Matuska .vdev_op_config_generate = NULL, 329*d2a8fad3SMartin Matuska .vdev_op_nparity = NULL, 330*d2a8fad3SMartin Matuska .vdev_op_ndisks = NULL, 331*d2a8fad3SMartin Matuska .vdev_op_type = VDEV_TYPE_FILE, /* name of this vdev type */ 332*d2a8fad3SMartin Matuska .vdev_op_leaf = B_TRUE /* leaf vdev */ 333*d2a8fad3SMartin Matuska }; 334*d2a8fad3SMartin Matuska 335*d2a8fad3SMartin Matuska /* 336*d2a8fad3SMartin Matuska * From userland we access disks just like files. 337*d2a8fad3SMartin Matuska */ 338*d2a8fad3SMartin Matuska #ifndef _KERNEL 339*d2a8fad3SMartin Matuska 340*d2a8fad3SMartin Matuska vdev_ops_t vdev_disk_ops = { 341*d2a8fad3SMartin Matuska .vdev_op_init = NULL, 342*d2a8fad3SMartin Matuska .vdev_op_fini = NULL, 343*d2a8fad3SMartin Matuska .vdev_op_open = vdev_file_open, 344*d2a8fad3SMartin Matuska .vdev_op_close = vdev_file_close, 345*d2a8fad3SMartin Matuska .vdev_op_asize = vdev_default_asize, 346*d2a8fad3SMartin Matuska .vdev_op_min_asize = vdev_default_min_asize, 347*d2a8fad3SMartin Matuska .vdev_op_min_alloc = NULL, 348*d2a8fad3SMartin Matuska .vdev_op_io_start = vdev_file_io_start, 349*d2a8fad3SMartin Matuska .vdev_op_io_done = vdev_file_io_done, 350*d2a8fad3SMartin Matuska .vdev_op_state_change = NULL, 351*d2a8fad3SMartin Matuska .vdev_op_need_resilver = NULL, 352*d2a8fad3SMartin Matuska .vdev_op_hold = vdev_file_hold, 353*d2a8fad3SMartin Matuska .vdev_op_rele = vdev_file_rele, 354*d2a8fad3SMartin Matuska .vdev_op_remap = NULL, 355*d2a8fad3SMartin Matuska .vdev_op_xlate = vdev_default_xlate, 356*d2a8fad3SMartin Matuska .vdev_op_rebuild_asize = NULL, 357*d2a8fad3SMartin Matuska .vdev_op_metaslab_init = NULL, 358*d2a8fad3SMartin Matuska .vdev_op_config_generate = NULL, 359*d2a8fad3SMartin Matuska .vdev_op_nparity = NULL, 360*d2a8fad3SMartin Matuska .vdev_op_ndisks = NULL, 361*d2a8fad3SMartin Matuska .vdev_op_type = VDEV_TYPE_DISK, /* name of this vdev type */ 362*d2a8fad3SMartin Matuska .vdev_op_leaf = B_TRUE /* leaf vdev */ 363*d2a8fad3SMartin Matuska }; 364*d2a8fad3SMartin Matuska 365*d2a8fad3SMartin Matuska #endif 366*d2a8fad3SMartin Matuska 367*d2a8fad3SMartin Matuska ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, logical_ashift, UINT, ZMOD_RW, 368*d2a8fad3SMartin Matuska "Logical ashift for file-based devices"); 369*d2a8fad3SMartin Matuska ZFS_MODULE_PARAM(zfs_vdev_file, vdev_file_, physical_ashift, UINT, ZMOD_RW, 370*d2a8fad3SMartin Matuska "Physical ashift for file-based devices"); 371