From owner-svn-src-head@freebsd.org Fri Sep 11 12:50:52 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A5EECA01D40; Fri, 11 Sep 2015 12:50:52 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 965E41F4A; Fri, 11 Sep 2015 12:50:52 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t8BCoqoK035527; Fri, 11 Sep 2015 12:50:52 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t8BCoqai035526; Fri, 11 Sep 2015 12:50:52 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201509111250.t8BCoqai035526@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Fri, 11 Sep 2015 12:50:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287664 - head/sys/cam/ctl X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Sep 2015 12:50:52 -0000 Author: mav Date: Fri Sep 11 12:50:52 2015 New Revision: 287664 URL: https://svnweb.freebsd.org/changeset/base/287664 Log: Reference/release devices on every I/O, rather on open/close. While this may be slower, it allows device destruction to complete, rather then block waiting for indefinitely long time. Modified: head/sys/cam/ctl/ctl_backend_block.c Modified: head/sys/cam/ctl/ctl_backend_block.c ============================================================================== --- head/sys/cam/ctl/ctl_backend_block.c Fri Sep 11 12:45:56 2015 (r287663) +++ head/sys/cam/ctl/ctl_backend_block.c Fri Sep 11 12:50:52 2015 (r287664) @@ -126,18 +126,11 @@ typedef enum { CTL_BE_BLOCK_FILE } ctl_be_block_type; -struct ctl_be_block_devdata { - struct cdev *cdev; - struct cdevsw *csw; - int dev_ref; -}; - struct ctl_be_block_filedata { struct ucred *cred; }; union ctl_be_block_bedata { - struct ctl_be_block_devdata dev; struct ctl_be_block_filedata file; }; @@ -823,16 +816,15 @@ static void ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun, struct ctl_be_block_io *beio) { - struct ctl_be_block_devdata *dev_data; union ctl_io *io; + struct cdevsw *csw; + struct cdev *dev; struct uio xuio; struct iovec *xiovec; - int flags; - int error, i; + int error, flags, i, ref; DPRINTF("entered\n"); - dev_data = &be_lun->backend.dev; io = beio->io; flags = 0; if (ARGS(io)->flags & CTL_LLF_DPO) @@ -865,13 +857,20 @@ ctl_be_block_dispatch_zvol(struct ctl_be devstat_start_transaction(beio->lun->disk_stats, &beio->ds_t0); mtx_unlock(&be_lun->io_lock); - if (beio->bio_cmd == BIO_READ) { - error = (*dev_data->csw->d_read)(dev_data->cdev, &xuio, flags); + csw = devvn_refthread(be_lun->vn, &dev, &ref); + if (csw) { + if (beio->bio_cmd == BIO_READ) + error = csw->d_read(dev, &xuio, flags); + else + error = csw->d_write(dev, &xuio, flags); + dev_relthread(dev, ref); + } else + error = ENXIO; + + if (beio->bio_cmd == BIO_READ) SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0); - } else { - error = (*dev_data->csw->d_write)(dev_data->cdev, &xuio, flags); + else SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0); - } mtx_lock(&be_lun->io_lock); devstat_end_transaction(beio->lun->disk_stats, beio->io_len, @@ -915,23 +914,30 @@ static void ctl_be_block_gls_zvol(struct ctl_be_block_lun *be_lun, struct ctl_be_block_io *beio) { - struct ctl_be_block_devdata *dev_data = &be_lun->backend.dev; union ctl_io *io = beio->io; + struct cdevsw *csw; + struct cdev *dev; struct ctl_lba_len_flags *lbalen = ARGS(io); struct scsi_get_lba_status_data *data; off_t roff, off; - int error, status; + int error, ref, status; DPRINTF("entered\n"); + csw = devvn_refthread(be_lun->vn, &dev, &ref); + if (csw == NULL) { + status = 0; /* unknown up to the end */ + off = be_lun->size_bytes; + goto done; + } off = roff = ((off_t)lbalen->lba) * be_lun->cbe_lun.blocksize; - error = (*dev_data->csw->d_ioctl)(dev_data->cdev, FIOSEEKHOLE, - (caddr_t)&off, FREAD, curthread); + error = csw->d_ioctl(dev, FIOSEEKHOLE, (caddr_t)&off, FREAD, + curthread); if (error == 0 && off > roff) status = 0; /* mapped up to off */ else { - error = (*dev_data->csw->d_ioctl)(dev_data->cdev, FIOSEEKDATA, - (caddr_t)&off, FREAD, curthread); + error = csw->d_ioctl(dev, FIOSEEKDATA, (caddr_t)&off, FREAD, + curthread); if (error == 0 && off > roff) status = 1; /* deallocated up to off */ else { @@ -939,7 +945,9 @@ ctl_be_block_gls_zvol(struct ctl_be_bloc off = be_lun->size_bytes; } } + dev_relthread(dev, ref); +done: data = (struct scsi_get_lba_status_data *)io->scsiio.kern_data_ptr; scsi_u64to8b(lbalen->lba, data->descr[0].addr); scsi_ulto4b(MIN(UINT32_MAX, off / be_lun->cbe_lun.blocksize - @@ -955,9 +963,10 @@ ctl_be_block_flush_dev(struct ctl_be_blo { struct bio *bio; union ctl_io *io; - struct ctl_be_block_devdata *dev_data; + struct cdevsw *csw; + struct cdev *dev; + int ref; - dev_data = &be_lun->backend.dev; io = beio->io; DPRINTF("entered\n"); @@ -966,7 +975,6 @@ ctl_be_block_flush_dev(struct ctl_be_blo bio = g_alloc_bio(); bio->bio_cmd = BIO_FLUSH; - bio->bio_dev = dev_data->cdev; bio->bio_offset = 0; bio->bio_data = 0; bio->bio_done = ctl_be_block_biodone; @@ -986,7 +994,15 @@ ctl_be_block_flush_dev(struct ctl_be_blo devstat_start_transaction(be_lun->disk_stats, &beio->ds_t0); mtx_unlock(&be_lun->io_lock); - (*dev_data->csw->d_strategy)(bio); + csw = devvn_refthread(be_lun->vn, &dev, &ref); + if (csw) { + bio->bio_dev = dev; + csw->d_strategy(bio); + dev_relthread(dev, ref); + } else { + bio->bio_error = ENXIO; + ctl_be_block_biodone(bio); + } } static void @@ -995,15 +1011,17 @@ ctl_be_block_unmap_dev_range(struct ctl_ uint64_t off, uint64_t len, int last) { struct bio *bio; - struct ctl_be_block_devdata *dev_data; uint64_t maxlen; + struct cdevsw *csw; + struct cdev *dev; + int ref; - dev_data = &be_lun->backend.dev; + csw = devvn_refthread(be_lun->vn, &dev, &ref); maxlen = LONG_MAX - (LONG_MAX % be_lun->cbe_lun.blocksize); while (len > 0) { bio = g_alloc_bio(); bio->bio_cmd = BIO_DELETE; - bio->bio_dev = dev_data->cdev; + bio->bio_dev = dev; bio->bio_offset = off; bio->bio_length = MIN(len, maxlen); bio->bio_data = 0; @@ -1020,8 +1038,15 @@ ctl_be_block_unmap_dev_range(struct ctl_ beio->send_complete = 1; mtx_unlock(&be_lun->io_lock); - (*dev_data->csw->d_strategy)(bio); + if (csw) { + csw->d_strategy(bio); + } else { + bio->bio_error = ENXIO; + ctl_be_block_biodone(bio); + } } + if (csw) + dev_relthread(dev, ref); } static void @@ -1029,12 +1054,10 @@ ctl_be_block_unmap_dev(struct ctl_be_blo struct ctl_be_block_io *beio) { union ctl_io *io; - struct ctl_be_block_devdata *dev_data; struct ctl_ptr_len_flags *ptrlen; struct scsi_unmap_desc *buf, *end; uint64_t len; - dev_data = &be_lun->backend.dev; io = beio->io; DPRINTF("entered\n"); @@ -1067,23 +1090,25 @@ ctl_be_block_dispatch_dev(struct ctl_be_ struct ctl_be_block_io *beio) { TAILQ_HEAD(, bio) queue = TAILQ_HEAD_INITIALIZER(queue); - int i; struct bio *bio; - struct ctl_be_block_devdata *dev_data; + struct cdevsw *csw; + struct cdev *dev; off_t cur_offset; - int max_iosize; + int i, max_iosize, ref; DPRINTF("entered\n"); - - dev_data = &be_lun->backend.dev; + csw = devvn_refthread(be_lun->vn, &dev, &ref); /* * We have to limit our I/O size to the maximum supported by the * backend device. Hopefully it is MAXPHYS. If the driver doesn't * set it properly, use DFLTPHYS. */ - max_iosize = dev_data->cdev->si_iosize_max; - if (max_iosize < PAGE_SIZE) + if (csw) { + max_iosize = dev->si_iosize_max; + if (max_iosize < PAGE_SIZE) + max_iosize = DFLTPHYS; + } else max_iosize = DFLTPHYS; cur_offset = beio->io_offset; @@ -1101,7 +1126,7 @@ ctl_be_block_dispatch_dev(struct ctl_be_ KASSERT(bio != NULL, ("g_alloc_bio() failed!\n")); bio->bio_cmd = beio->bio_cmd; - bio->bio_dev = dev_data->cdev; + bio->bio_dev = dev; bio->bio_caller1 = beio; bio->bio_length = min(cur_size, max_iosize); bio->bio_offset = cur_offset; @@ -1128,23 +1153,36 @@ ctl_be_block_dispatch_dev(struct ctl_be_ */ while ((bio = TAILQ_FIRST(&queue)) != NULL) { TAILQ_REMOVE(&queue, bio, bio_queue); - (*dev_data->csw->d_strategy)(bio); + if (csw) + csw->d_strategy(bio); + else { + bio->bio_error = ENXIO; + ctl_be_block_biodone(bio); + } } + if (csw) + dev_relthread(dev, ref); } static uint64_t ctl_be_block_getattr_dev(struct ctl_be_block_lun *be_lun, const char *attrname) { - struct ctl_be_block_devdata *dev_data = &be_lun->backend.dev; struct diocgattr_arg arg; - int error; + struct cdevsw *csw; + struct cdev *dev; + int error, ref; - if (dev_data->csw == NULL || dev_data->csw->d_ioctl == NULL) + csw = devvn_refthread(be_lun->vn, &dev, &ref); + if (csw == NULL) return (UINT64_MAX); strlcpy(arg.name, attrname, sizeof(arg.name)); arg.len = sizeof(arg.value.off); - error = dev_data->csw->d_ioctl(dev_data->cdev, - DIOCGATTR, (caddr_t)&arg, FREAD, curthread); + if (csw->d_ioctl) { + error = csw->d_ioctl(dev, DIOCGATTR, (caddr_t)&arg, FREAD, + curthread); + } else + error = ENODEV; + dev_relthread(dev, ref); if (error != 0) return (UINT64_MAX); return (arg.value.off); @@ -1853,22 +1891,19 @@ ctl_be_block_open_dev(struct ctl_be_bloc { struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun; struct ctl_lun_create_params *params; - struct vattr vattr; + struct cdevsw *csw; struct cdev *dev; - struct cdevsw *devsw; char *value; - int error, atomic, maxio, unmap, tmp; + int error, atomic, maxio, ref, unmap, tmp; off_t ps, pss, po, pos, us, uss, uo, uos, otmp; params = &be_lun->params; be_lun->dev_type = CTL_BE_BLOCK_DEV; - be_lun->backend.dev.cdev = be_lun->vn->v_rdev; - be_lun->backend.dev.csw = dev_refthread(be_lun->backend.dev.cdev, - &be_lun->backend.dev.dev_ref); - if (be_lun->backend.dev.csw == NULL) - panic("Unable to retrieve device switch"); - if (strcmp(be_lun->backend.dev.csw->d_name, "zvol") == 0) { + csw = devvn_refthread(be_lun->vn, &dev, &ref); + if (csw == NULL) + return (ENXIO); + if (strcmp(csw->d_name, "zvol") == 0) { be_lun->dispatch = ctl_be_block_dispatch_zvol; be_lun->get_lba_status = ctl_be_block_gls_zvol; atomic = maxio = CTLBLK_MAX_IO_SIZE; @@ -1876,7 +1911,7 @@ ctl_be_block_open_dev(struct ctl_be_bloc be_lun->dispatch = ctl_be_block_dispatch_dev; be_lun->get_lba_status = NULL; atomic = 0; - maxio = be_lun->backend.dev.cdev->si_iosize_max; + maxio = dev->si_iosize_max; if (maxio <= 0) maxio = DFLTPHYS; if (maxio > CTLBLK_MAX_IO_SIZE) @@ -1886,26 +1921,17 @@ ctl_be_block_open_dev(struct ctl_be_bloc be_lun->getattr = ctl_be_block_getattr_dev; be_lun->unmap = ctl_be_block_unmap_dev; - error = VOP_GETATTR(be_lun->vn, &vattr, NOCRED); - if (error) { + if (!csw->d_ioctl) { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), - "error getting vnode attributes for device %s", - be_lun->dev_path); - return (error); - } - - dev = be_lun->vn->v_rdev; - devsw = dev->si_devsw; - if (!devsw->d_ioctl) { - snprintf(req->error_str, sizeof(req->error_str), - "no d_ioctl for device %s!", - be_lun->dev_path); + "no d_ioctl for device %s!", be_lun->dev_path); return (ENODEV); } - error = devsw->d_ioctl(dev, DIOCGSECTORSIZE, (caddr_t)&tmp, FREAD, + error = csw->d_ioctl(dev, DIOCGSECTORSIZE, (caddr_t)&tmp, FREAD, curthread); if (error) { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), "error %d returned for DIOCGSECTORSIZE ioctl " "on %s!", error, be_lun->dev_path); @@ -1923,14 +1949,15 @@ ctl_be_block_open_dev(struct ctl_be_bloc if (params->blocksize_bytes % tmp == 0) { cbe_lun->blocksize = params->blocksize_bytes; } else { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), "requested blocksize %u is not an even " "multiple of backing device blocksize %u", params->blocksize_bytes, tmp); return (EINVAL); - } } else if (params->blocksize_bytes != 0) { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), "requested blocksize %u < backing device " "blocksize %u", params->blocksize_bytes, tmp); @@ -1938,9 +1965,10 @@ ctl_be_block_open_dev(struct ctl_be_bloc } else cbe_lun->blocksize = tmp; - error = devsw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&otmp, FREAD, - curthread); + error = csw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&otmp, FREAD, + curthread); if (error) { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), "error %d returned for DIOCGMEDIASIZE " " ioctl on %s!", error, @@ -1950,6 +1978,7 @@ ctl_be_block_open_dev(struct ctl_be_bloc if (params->lun_size_bytes != 0) { if (params->lun_size_bytes > otmp) { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), "requested LUN size %ju > backing device " "size %ju", @@ -1965,13 +1994,13 @@ ctl_be_block_open_dev(struct ctl_be_bloc cbe_lun->maxlba = (be_lun->size_blocks == 0) ? 0 : (be_lun->size_blocks - 1); - error = devsw->d_ioctl(dev, DIOCGSTRIPESIZE, - (caddr_t)&ps, FREAD, curthread); + error = csw->d_ioctl(dev, DIOCGSTRIPESIZE, (caddr_t)&ps, FREAD, + curthread); if (error) ps = po = 0; else { - error = devsw->d_ioctl(dev, DIOCGSTRIPEOFFSET, - (caddr_t)&po, FREAD, curthread); + error = csw->d_ioctl(dev, DIOCGSTRIPEOFFSET, (caddr_t)&po, + FREAD, curthread); if (error) po = 0; } @@ -2016,8 +2045,8 @@ ctl_be_block_open_dev(struct ctl_be_bloc strlcpy(arg.name, "GEOM::candelete", sizeof(arg.name)); arg.len = sizeof(arg.value.i); - error = devsw->d_ioctl(dev, DIOCGATTR, - (caddr_t)&arg, FREAD, curthread); + error = csw->d_ioctl(dev, DIOCGATTR, (caddr_t)&arg, FREAD, + curthread); unmap = (error == 0) ? arg.value.i : 0; } value = ctl_get_opt(&cbe_lun->options, "unmap"); @@ -2028,6 +2057,7 @@ ctl_be_block_open_dev(struct ctl_be_bloc else cbe_lun->flags &= ~CTL_LUN_FLAG_UNMAP; + dev_relthread(dev, ref); return (0); } @@ -2038,24 +2068,6 @@ ctl_be_block_close(struct ctl_be_block_l int flags; if (be_lun->vn) { - switch (be_lun->dev_type) { - case CTL_BE_BLOCK_DEV: - if (be_lun->backend.dev.csw) { - dev_relthread(be_lun->backend.dev.cdev, - be_lun->backend.dev.dev_ref); - be_lun->backend.dev.csw = NULL; - be_lun->backend.dev.cdev = NULL; - } - break; - case CTL_BE_BLOCK_FILE: - break; - case CTL_BE_BLOCK_NONE: - break; - default: - panic("Unexpected backend type."); - break; - } - flags = FREAD; if ((cbe_lun->flags & CTL_LUN_FLAG_READONLY) == 0) flags |= FWRITE; @@ -2553,21 +2565,25 @@ ctl_be_block_modify_dev(struct ctl_be_bl struct ctl_lun_req *req) { struct ctl_be_lun *cbe_lun = &be_lun->cbe_lun; - struct ctl_be_block_devdata *dev_data; - int error; struct ctl_lun_create_params *params = &be_lun->params; + struct cdevsw *csw; + struct cdev *dev; uint64_t size_bytes; + int error, ref; - dev_data = &be_lun->backend.dev; - if (!dev_data->csw->d_ioctl) { + csw = devvn_refthread(be_lun->vn, &dev, &ref); + if (csw == NULL) + return (ENXIO); + if (csw->d_ioctl == NULL) { + dev_relthread(dev, ref); snprintf(req->error_str, sizeof(req->error_str), "no d_ioctl for device %s!", be_lun->dev_path); return (ENODEV); } - error = dev_data->csw->d_ioctl(dev_data->cdev, DIOCGMEDIASIZE, - (caddr_t)&size_bytes, FREAD, - curthread); + error = csw->d_ioctl(dev, DIOCGMEDIASIZE, (caddr_t)&size_bytes, FREAD, + curthread); + dev_relthread(dev, ref); if (error) { snprintf(req->error_str, sizeof(req->error_str), "error %d returned for DIOCGMEDIASIZE ioctl "