Print this page
6494 ASSERT supported zio_types for file and disk vdevs
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Albert Lee <trisk@omniti.com>
NEX-4229 Panic destroying the pool using file backing store on FS with nbmand=on
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3958 CLONE - Port NEX-3957 TRIM on file-backed vdevs is broken
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3508 CLONE - Port NEX-2946 Add UNMAP/TRIM functionality to ZFS and illumos
Reviewed by: Josef Sipek <josef.sipek@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Conflicts:
    usr/src/uts/common/io/scsi/targets/sd.c
    usr/src/uts/common/sys/scsi/targets/sddef.h


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.

  24  */
  25 
  26 #include <sys/zfs_context.h>
  27 #include <sys/spa.h>
  28 #include <sys/spa_impl.h>
  29 #include <sys/vdev_file.h>
  30 #include <sys/vdev_impl.h>
  31 #include <sys/zio.h>
  32 #include <sys/fs/zfs.h>
  33 #include <sys/fm/fs/zfs.h>



  34 #include <sys/abd.h>
  35 
  36 /*
  37  * Virtual device vector for files.
  38  */
  39 
  40 static void
  41 vdev_file_hold(vdev_t *vd)
  42 {
  43         ASSERT(vd->vdev_path != NULL);
  44 }
  45 
  46 static void
  47 vdev_file_rele(vdev_t *vd)
  48 {
  49         ASSERT(vd->vdev_path != NULL);
  50 }
  51 
  52 static int
  53 vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,


 109         /*
 110          * Determine the physical size of the file.
 111          */
 112         vattr.va_mask = AT_SIZE;
 113         error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL);
 114         if (error) {
 115                 vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
 116                 return (error);
 117         }
 118 
 119         *max_psize = *psize = vattr.va_size;
 120         *ashift = SPA_MINBLOCKSHIFT;
 121 
 122         return (0);
 123 }
 124 
 125 static void
 126 vdev_file_close(vdev_t *vd)
 127 {
 128         vdev_file_t *vf = vd->vdev_tsd;

 129 
 130         if (vd->vdev_reopening || vf == NULL)
 131                 return;
 132 
 133         if (vf->vf_vnode != NULL) {
 134                 (void) VOP_PUTPAGE(vf->vf_vnode, 0, 0, B_INVAL, kcred, NULL);







 135                 (void) VOP_CLOSE(vf->vf_vnode, spa_mode(vd->vdev_spa), 1, 0,
 136                     kcred, NULL);
 137                 VN_RELE(vf->vf_vnode);
 138         }
 139 
 140         vd->vdev_delayed_close = B_FALSE;
 141         kmem_free(vf, sizeof (vdev_file_t));
 142         vd->vdev_tsd = NULL;
 143 }
 144 
 145 /*
 146  * Implements the interrupt side for file vdev types. This routine will be
 147  * called when the I/O completes allowing us to transfer the I/O to the
 148  * interrupt taskqs. For consistency, the code structure mimics disk vdev
 149  * types.
 150  */
 151 static void
 152 vdev_file_io_intr(buf_t *bp)
 153 {
 154         vdev_buf_t *vb = (vdev_buf_t *)bp;
 155         zio_t *zio = vb->vb_io;
 156 


 193 vdev_file_io_start(zio_t *zio)
 194 {
 195         vdev_t *vd = zio->io_vd;
 196         vdev_file_t *vf = vd->vdev_tsd;
 197         vdev_buf_t *vb;
 198         buf_t *bp;
 199 
 200         if (zio->io_type == ZIO_TYPE_IOCTL) {
 201                 /* XXPOLICY */
 202                 if (!vdev_readable(vd)) {
 203                         zio->io_error = SET_ERROR(ENXIO);
 204                         zio_interrupt(zio);
 205                         return;
 206                 }
 207 
 208                 switch (zio->io_cmd) {
 209                 case DKIOCFLUSHWRITECACHE:
 210                         zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC,
 211                             kcred, NULL);
 212                         break;



























 213                 default:
 214                         zio->io_error = SET_ERROR(ENOTSUP);
 215                 }
 216 
 217                 zio_execute(zio);
 218                 return;
 219         }
 220 
 221         ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE);
 222         zio->io_target_timestamp = zio_handle_io_delay(zio);
 223 
 224         vb = kmem_alloc(sizeof (vdev_buf_t), KM_SLEEP);
 225 
 226         vb->vb_io = zio;
 227         bp = &vb->vb_buf;
 228 
 229         bioinit(bp);
 230         bp->b_flags = (zio->io_type == ZIO_TYPE_READ ? B_READ : B_WRITE);
 231         bp->b_bcount = zio->io_size;
 232 




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <sys/zfs_context.h>
  28 #include <sys/spa.h>
  29 #include <sys/spa_impl.h>
  30 #include <sys/vdev_file.h>
  31 #include <sys/vdev_impl.h>
  32 #include <sys/zio.h>
  33 #include <sys/fs/zfs.h>
  34 #include <sys/fm/fs/zfs.h>
  35 #include <sys/fcntl.h>
  36 #include <sys/vnode.h>
  37 #include <sys/dkioc_free_util.h>
  38 #include <sys/abd.h>
  39 
  40 /*
  41  * Virtual device vector for files.
  42  */
  43 
  44 static void
  45 vdev_file_hold(vdev_t *vd)
  46 {
  47         ASSERT(vd->vdev_path != NULL);
  48 }
  49 
  50 static void
  51 vdev_file_rele(vdev_t *vd)
  52 {
  53         ASSERT(vd->vdev_path != NULL);
  54 }
  55 
  56 static int
  57 vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,


 113         /*
 114          * Determine the physical size of the file.
 115          */
 116         vattr.va_mask = AT_SIZE;
 117         error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL);
 118         if (error) {
 119                 vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
 120                 return (error);
 121         }
 122 
 123         *max_psize = *psize = vattr.va_size;
 124         *ashift = SPA_MINBLOCKSHIFT;
 125 
 126         return (0);
 127 }
 128 
 129 static void
 130 vdev_file_close(vdev_t *vd)
 131 {
 132         vdev_file_t *vf = vd->vdev_tsd;
 133         caller_context_t ct = {0};
 134 
 135         if (vd->vdev_reopening || vf == NULL)
 136                 return;
 137 
 138         if (vf->vf_vnode != NULL) {
 139                 (void) VOP_PUTPAGE(vf->vf_vnode, 0, 0, B_INVAL, kcred, NULL);
 140                 /*
 141                  * We need to supply caller context with PID zero to fop_close
 142                  * in order to clean properly a share reservation which might
 143                  * have been created by vdev_file_open if nbmand was "on" for
 144                  * underlaying filesystem. Mismatched PIDs in create and delete
 145                  * reservation calls would lead to orphaned reservation.
 146                  */
 147                 (void) VOP_CLOSE(vf->vf_vnode, spa_mode(vd->vdev_spa), 1, 0,
 148                     kcred, &ct);
 149                 VN_RELE(vf->vf_vnode);
 150         }
 151 
 152         vd->vdev_delayed_close = B_FALSE;
 153         kmem_free(vf, sizeof (vdev_file_t));
 154         vd->vdev_tsd = NULL;
 155 }
 156 
 157 /*
 158  * Implements the interrupt side for file vdev types. This routine will be
 159  * called when the I/O completes allowing us to transfer the I/O to the
 160  * interrupt taskqs. For consistency, the code structure mimics disk vdev
 161  * types.
 162  */
 163 static void
 164 vdev_file_io_intr(buf_t *bp)
 165 {
 166         vdev_buf_t *vb = (vdev_buf_t *)bp;
 167         zio_t *zio = vb->vb_io;
 168 


 205 vdev_file_io_start(zio_t *zio)
 206 {
 207         vdev_t *vd = zio->io_vd;
 208         vdev_file_t *vf = vd->vdev_tsd;
 209         vdev_buf_t *vb;
 210         buf_t *bp;
 211 
 212         if (zio->io_type == ZIO_TYPE_IOCTL) {
 213                 /* XXPOLICY */
 214                 if (!vdev_readable(vd)) {
 215                         zio->io_error = SET_ERROR(ENXIO);
 216                         zio_interrupt(zio);
 217                         return;
 218                 }
 219 
 220                 switch (zio->io_cmd) {
 221                 case DKIOCFLUSHWRITECACHE:
 222                         zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC,
 223                             kcred, NULL);
 224                         break;
 225                 case DKIOCFREE:
 226                 {
 227                         dkioc_free_list_t *dfl = zio->io_private;
 228 
 229                         ASSERT(dfl != NULL);
 230                         for (int i = 0; i < dfl->dfl_num_exts; i++) {
 231                                 struct flock64 flck;
 232                                 int error;
 233 
 234                                 if (dfl->dfl_exts[i].dfle_length == 0)
 235                                         continue;
 236 
 237                                 bzero(&flck, sizeof (flck));
 238                                 flck.l_type = F_FREESP;
 239                                 flck.l_start = dfl->dfl_exts[i].dfle_start +
 240                                     dfl->dfl_offset;
 241                                 flck.l_len = dfl->dfl_exts[i].dfle_length;
 242 
 243                                 error = VOP_SPACE(vf->vf_vnode,
 244                                     F_FREESP, &flck, 0, 0, kcred, NULL);
 245                                 if (error != 0) {
 246                                         zio->io_error = SET_ERROR(error);
 247                                         break;
 248                                 }
 249                         }
 250                         break;
 251                 }
 252                 default:
 253                         zio->io_error = SET_ERROR(ENOTSUP);
 254                 }
 255 
 256                 zio_execute(zio);
 257                 return;
 258         }
 259 
 260         ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE);
 261         zio->io_target_timestamp = zio_handle_io_delay(zio);
 262 
 263         vb = kmem_alloc(sizeof (vdev_buf_t), KM_SLEEP);
 264 
 265         vb->vb_io = zio;
 266         bp = &vb->vb_buf;
 267 
 268         bioinit(bp);
 269         bp->b_flags = (zio->io_type == ZIO_TYPE_READ ? B_READ : B_WRITE);
 270         bp->b_bcount = zio->io_size;
 271