1 /* $NetBSD: fss.c,v 1.108 2019/08/07 10:36:19 maxv Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Juergen Hannken-Illjes. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * File system snapshot disk driver. 34 * 35 * Block/character interface to the snapshot of a mounted file system. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.108 2019/08/07 10:36:19 maxv Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/namei.h> 44 #include <sys/proc.h> 45 #include <sys/errno.h> 46 #include <sys/malloc.h> 47 #include <sys/buf.h> 48 #include <sys/ioctl.h> 49 #include <sys/disklabel.h> 50 #include <sys/device.h> 51 #include <sys/disk.h> 52 #include <sys/stat.h> 53 #include <sys/mount.h> 54 #include <sys/vnode.h> 55 #include <sys/file.h> 56 #include <sys/uio.h> 57 #include <sys/conf.h> 58 #include <sys/kthread.h> 59 #include <sys/fstrans.h> 60 #include <sys/vfs_syscalls.h> /* For do_sys_unlink(). */ 61 62 #include <miscfs/specfs/specdev.h> 63 64 #include <dev/fssvar.h> 65 66 #include <uvm/uvm.h> 67 68 #include "ioconf.h" 69 70 dev_type_open(fss_open); 71 dev_type_close(fss_close); 72 dev_type_read(fss_read); 73 dev_type_write(fss_write); 74 dev_type_ioctl(fss_ioctl); 75 dev_type_strategy(fss_strategy); 76 dev_type_dump(fss_dump); 77 dev_type_size(fss_size); 78 79 static void fss_unmount_hook(struct mount *); 80 static int fss_copy_on_write(void *, struct buf *, bool); 81 static inline void fss_error(struct fss_softc *, const char *); 82 static int fss_create_files(struct fss_softc *, struct fss_set *, 83 off_t *, struct lwp *); 84 static int fss_create_snapshot(struct fss_softc *, struct fss_set *, 85 struct lwp *); 86 static int fss_delete_snapshot(struct fss_softc *, struct lwp *); 87 static int fss_softc_alloc(struct fss_softc *); 88 static void fss_softc_free(struct fss_softc *); 89 static int fss_read_cluster(struct fss_softc *, u_int32_t); 90 static void fss_bs_thread(void *); 91 static int fss_bs_io(struct fss_softc *, fss_io_type, 92 u_int32_t, off_t, int, void *, size_t *); 93 static u_int32_t *fss_bs_indir(struct fss_softc *, u_int32_t); 94 95 static kmutex_t fss_device_lock; /* Protect all units. */ 96 static kcondvar_t fss_device_cv; /* Serialize snapshot creation. */ 97 static bool fss_creating = false; /* Currently creating a snapshot. */ 98 static int fss_num_attached = 0; /* Number of attached devices. */ 99 static struct vfs_hooks fss_vfs_hooks = { 100 .vh_unmount = fss_unmount_hook 101 }; 102 103 const struct bdevsw fss_bdevsw = { 104 .d_open = fss_open, 105 .d_close = fss_close, 106 .d_strategy = fss_strategy, 107 .d_ioctl = fss_ioctl, 108 .d_dump = fss_dump, 109 .d_psize = fss_size, 110 .d_discard = nodiscard, 111 .d_flag = D_DISK | D_MPSAFE 112 }; 113 114 const struct cdevsw fss_cdevsw = { 115 .d_open = fss_open, 116 .d_close = fss_close, 117 .d_read = fss_read, 118 .d_write = fss_write, 119 .d_ioctl = fss_ioctl, 120 .d_stop = nostop, 121 .d_tty = notty, 122 .d_poll = nopoll, 123 .d_mmap = nommap, 124 .d_kqfilter = nokqfilter, 125 .d_discard = nodiscard, 126 .d_flag = D_DISK | D_MPSAFE 127 }; 128 129 static int fss_match(device_t, cfdata_t, void *); 130 static void fss_attach(device_t, device_t, void *); 131 static int fss_detach(device_t, int); 132 133 CFATTACH_DECL_NEW(fss, sizeof(struct fss_softc), 134 fss_match, fss_attach, fss_detach, NULL); 135 136 void 137 fssattach(int num) 138 { 139 140 mutex_init(&fss_device_lock, MUTEX_DEFAULT, IPL_NONE); 141 cv_init(&fss_device_cv, "snapwait"); 142 if (config_cfattach_attach(fss_cd.cd_name, &fss_ca)) 143 aprint_error("%s: unable to register\n", fss_cd.cd_name); 144 } 145 146 static int 147 fss_match(device_t self, cfdata_t cfdata, void *aux) 148 { 149 return 1; 150 } 151 152 static void 153 fss_attach(device_t parent, device_t self, void *aux) 154 { 155 struct fss_softc *sc = device_private(self); 156 157 sc->sc_dev = self; 158 sc->sc_bdev = NODEV; 159 mutex_init(&sc->sc_slock, MUTEX_DEFAULT, IPL_NONE); 160 cv_init(&sc->sc_work_cv, "fssbs"); 161 cv_init(&sc->sc_cache_cv, "cowwait"); 162 bufq_alloc(&sc->sc_bufq, "fcfs", 0); 163 sc->sc_dkdev = malloc(sizeof(*sc->sc_dkdev), M_DEVBUF, M_WAITOK); 164 sc->sc_dkdev->dk_info = NULL; 165 disk_init(sc->sc_dkdev, device_xname(self), NULL); 166 if (!pmf_device_register(self, NULL, NULL)) 167 aprint_error_dev(self, "couldn't establish power handler\n"); 168 169 if (fss_num_attached++ == 0) 170 vfs_hooks_attach(&fss_vfs_hooks); 171 } 172 173 static int 174 fss_detach(device_t self, int flags) 175 { 176 struct fss_softc *sc = device_private(self); 177 178 mutex_enter(&sc->sc_slock); 179 if (sc->sc_state != FSS_IDLE) { 180 mutex_exit(&sc->sc_slock); 181 return EBUSY; 182 } 183 mutex_exit(&sc->sc_slock); 184 185 if (--fss_num_attached == 0) 186 vfs_hooks_detach(&fss_vfs_hooks); 187 188 pmf_device_deregister(self); 189 mutex_destroy(&sc->sc_slock); 190 cv_destroy(&sc->sc_work_cv); 191 cv_destroy(&sc->sc_cache_cv); 192 bufq_drain(sc->sc_bufq); 193 bufq_free(sc->sc_bufq); 194 disk_destroy(sc->sc_dkdev); 195 free(sc->sc_dkdev, M_DEVBUF); 196 197 return 0; 198 } 199 200 int 201 fss_open(dev_t dev, int flags, int mode, struct lwp *l) 202 { 203 int mflag; 204 cfdata_t cf; 205 struct fss_softc *sc; 206 207 mflag = (mode == S_IFCHR ? FSS_CDEV_OPEN : FSS_BDEV_OPEN); 208 209 mutex_enter(&fss_device_lock); 210 211 sc = device_lookup_private(&fss_cd, minor(dev)); 212 if (sc == NULL) { 213 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK); 214 cf->cf_name = fss_cd.cd_name; 215 cf->cf_atname = fss_cd.cd_name; 216 cf->cf_unit = minor(dev); 217 cf->cf_fstate = FSTATE_STAR; 218 sc = device_private(config_attach_pseudo(cf)); 219 if (sc == NULL) { 220 mutex_exit(&fss_device_lock); 221 return ENOMEM; 222 } 223 sc->sc_state = FSS_IDLE; 224 } 225 226 mutex_enter(&sc->sc_slock); 227 228 sc->sc_flags |= mflag; 229 230 mutex_exit(&sc->sc_slock); 231 mutex_exit(&fss_device_lock); 232 233 return 0; 234 } 235 236 int 237 fss_close(dev_t dev, int flags, int mode, struct lwp *l) 238 { 239 int mflag, error; 240 cfdata_t cf; 241 struct fss_softc *sc = device_lookup_private(&fss_cd, minor(dev)); 242 243 mflag = (mode == S_IFCHR ? FSS_CDEV_OPEN : FSS_BDEV_OPEN); 244 error = 0; 245 246 mutex_enter(&fss_device_lock); 247 restart: 248 mutex_enter(&sc->sc_slock); 249 if ((sc->sc_flags & (FSS_CDEV_OPEN|FSS_BDEV_OPEN)) != mflag) { 250 sc->sc_flags &= ~mflag; 251 mutex_exit(&sc->sc_slock); 252 mutex_exit(&fss_device_lock); 253 return 0; 254 } 255 if (sc->sc_state != FSS_IDLE && 256 (sc->sc_uflags & FSS_UNCONFIG_ON_CLOSE) != 0) { 257 sc->sc_uflags &= ~FSS_UNCONFIG_ON_CLOSE; 258 mutex_exit(&sc->sc_slock); 259 error = fss_ioctl(dev, FSSIOCCLR, NULL, FWRITE, l); 260 goto restart; 261 } 262 if (sc->sc_state != FSS_IDLE) { 263 mutex_exit(&sc->sc_slock); 264 mutex_exit(&fss_device_lock); 265 return error; 266 } 267 268 KASSERT(sc->sc_state == FSS_IDLE); 269 KASSERT((sc->sc_flags & (FSS_CDEV_OPEN|FSS_BDEV_OPEN)) == mflag); 270 mutex_exit(&sc->sc_slock); 271 cf = device_cfdata(sc->sc_dev); 272 error = config_detach(sc->sc_dev, DETACH_QUIET); 273 if (! error) 274 free(cf, M_DEVBUF); 275 mutex_exit(&fss_device_lock); 276 277 return error; 278 } 279 280 void 281 fss_strategy(struct buf *bp) 282 { 283 const bool write = ((bp->b_flags & B_READ) != B_READ); 284 struct fss_softc *sc = device_lookup_private(&fss_cd, minor(bp->b_dev)); 285 286 mutex_enter(&sc->sc_slock); 287 288 if (write || sc->sc_state != FSS_ACTIVE) { 289 bp->b_error = (write ? EROFS : ENXIO); 290 goto done; 291 } 292 /* Check bounds for non-persistent snapshots. */ 293 if ((sc->sc_flags & FSS_PERSISTENT) == 0 && 294 bounds_check_with_mediasize(bp, DEV_BSIZE, 295 btodb(FSS_CLTOB(sc, sc->sc_clcount - 1) + sc->sc_clresid)) <= 0) 296 goto done; 297 298 bp->b_rawblkno = bp->b_blkno; 299 bufq_put(sc->sc_bufq, bp); 300 cv_signal(&sc->sc_work_cv); 301 302 mutex_exit(&sc->sc_slock); 303 return; 304 305 done: 306 mutex_exit(&sc->sc_slock); 307 bp->b_resid = bp->b_bcount; 308 biodone(bp); 309 } 310 311 int 312 fss_read(dev_t dev, struct uio *uio, int flags) 313 { 314 return physio(fss_strategy, NULL, dev, B_READ, minphys, uio); 315 } 316 317 int 318 fss_write(dev_t dev, struct uio *uio, int flags) 319 { 320 return physio(fss_strategy, NULL, dev, B_WRITE, minphys, uio); 321 } 322 323 int 324 fss_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 325 { 326 int error = 0; 327 struct fss_softc *sc = device_lookup_private(&fss_cd, minor(dev)); 328 struct fss_set _fss; 329 struct fss_set *fss = (struct fss_set *)data; 330 struct fss_set50 *fss50 = (struct fss_set50 *)data; 331 struct fss_get *fsg = (struct fss_get *)data; 332 #ifndef _LP64 333 struct fss_get50 *fsg50 = (struct fss_get50 *)data; 334 #endif 335 336 switch (cmd) { 337 case FSSIOCSET50: 338 fss = &_fss; 339 fss->fss_mount = fss50->fss_mount; 340 fss->fss_bstore = fss50->fss_bstore; 341 fss->fss_csize = fss50->fss_csize; 342 fss->fss_flags = 0; 343 /* Fall through */ 344 case FSSIOCSET: 345 mutex_enter(&sc->sc_slock); 346 if ((flag & FWRITE) == 0) 347 error = EPERM; 348 if (error == 0 && sc->sc_state != FSS_IDLE) { 349 error = EBUSY; 350 } else { 351 sc->sc_state = FSS_CREATING; 352 copyinstr(fss->fss_mount, sc->sc_mntname, 353 sizeof(sc->sc_mntname), NULL); 354 memset(&sc->sc_time, 0, sizeof(sc->sc_time)); 355 sc->sc_clshift = 0; 356 } 357 mutex_exit(&sc->sc_slock); 358 if (error) 359 break; 360 361 /* 362 * Serialize snapshot creation. 363 */ 364 mutex_enter(&fss_device_lock); 365 while (fss_creating) { 366 error = cv_wait_sig(&fss_device_cv, &fss_device_lock); 367 if (error) { 368 mutex_enter(&sc->sc_slock); 369 KASSERT(sc->sc_state == FSS_CREATING); 370 sc->sc_state = FSS_IDLE; 371 mutex_exit(&sc->sc_slock); 372 mutex_exit(&fss_device_lock); 373 break; 374 } 375 } 376 fss_creating = true; 377 mutex_exit(&fss_device_lock); 378 379 error = fss_create_snapshot(sc, fss, l); 380 mutex_enter(&sc->sc_slock); 381 if (error == 0) { 382 KASSERT(sc->sc_state == FSS_ACTIVE); 383 sc->sc_uflags = fss->fss_flags; 384 } else { 385 KASSERT(sc->sc_state == FSS_CREATING); 386 sc->sc_state = FSS_IDLE; 387 } 388 mutex_exit(&sc->sc_slock); 389 390 mutex_enter(&fss_device_lock); 391 fss_creating = false; 392 cv_broadcast(&fss_device_cv); 393 mutex_exit(&fss_device_lock); 394 395 break; 396 397 case FSSIOCCLR: 398 mutex_enter(&sc->sc_slock); 399 if ((flag & FWRITE) == 0) { 400 error = EPERM; 401 } else if (sc->sc_state != FSS_ACTIVE) { 402 error = EBUSY; 403 } else { 404 sc->sc_state = FSS_DESTROYING; 405 } 406 mutex_exit(&sc->sc_slock); 407 if (error) 408 break; 409 410 error = fss_delete_snapshot(sc, l); 411 mutex_enter(&sc->sc_slock); 412 if (error) 413 fss_error(sc, "Failed to delete snapshot"); 414 else 415 KASSERT(sc->sc_state == FSS_IDLE); 416 mutex_exit(&sc->sc_slock); 417 break; 418 419 #ifndef _LP64 420 case FSSIOCGET50: 421 mutex_enter(&sc->sc_slock); 422 if (sc->sc_state == FSS_IDLE) { 423 error = ENXIO; 424 } else if ((sc->sc_flags & FSS_PERSISTENT) == 0) { 425 memcpy(fsg50->fsg_mount, sc->sc_mntname, MNAMELEN); 426 fsg50->fsg_csize = FSS_CLSIZE(sc); 427 timeval_to_timeval50(&sc->sc_time, &fsg50->fsg_time); 428 fsg50->fsg_mount_size = sc->sc_clcount; 429 fsg50->fsg_bs_size = sc->sc_clnext; 430 error = 0; 431 } else { 432 memcpy(fsg50->fsg_mount, sc->sc_mntname, MNAMELEN); 433 fsg50->fsg_csize = 0; 434 timeval_to_timeval50(&sc->sc_time, &fsg50->fsg_time); 435 fsg50->fsg_mount_size = 0; 436 fsg50->fsg_bs_size = 0; 437 error = 0; 438 } 439 mutex_exit(&sc->sc_slock); 440 break; 441 #endif /* _LP64 */ 442 443 case FSSIOCGET: 444 mutex_enter(&sc->sc_slock); 445 if (sc->sc_state == FSS_IDLE) { 446 error = ENXIO; 447 } else if ((sc->sc_flags & FSS_PERSISTENT) == 0) { 448 memcpy(fsg->fsg_mount, sc->sc_mntname, MNAMELEN); 449 fsg->fsg_csize = FSS_CLSIZE(sc); 450 fsg->fsg_time = sc->sc_time; 451 fsg->fsg_mount_size = sc->sc_clcount; 452 fsg->fsg_bs_size = sc->sc_clnext; 453 error = 0; 454 } else { 455 memcpy(fsg->fsg_mount, sc->sc_mntname, MNAMELEN); 456 fsg->fsg_csize = 0; 457 fsg->fsg_time = sc->sc_time; 458 fsg->fsg_mount_size = 0; 459 fsg->fsg_bs_size = 0; 460 error = 0; 461 } 462 mutex_exit(&sc->sc_slock); 463 break; 464 465 case FSSIOFSET: 466 mutex_enter(&sc->sc_slock); 467 sc->sc_uflags = *(int *)data; 468 mutex_exit(&sc->sc_slock); 469 error = 0; 470 break; 471 472 case FSSIOFGET: 473 mutex_enter(&sc->sc_slock); 474 *(int *)data = sc->sc_uflags; 475 mutex_exit(&sc->sc_slock); 476 error = 0; 477 break; 478 479 default: 480 error = EINVAL; 481 break; 482 } 483 484 return error; 485 } 486 487 int 488 fss_size(dev_t dev) 489 { 490 return -1; 491 } 492 493 int 494 fss_dump(dev_t dev, daddr_t blkno, void *va, 495 size_t size) 496 { 497 return EROFS; 498 } 499 500 /* 501 * An error occurred reading or writing the snapshot or backing store. 502 * If it is the first error log to console and disestablish cow handler. 503 * The caller holds the mutex. 504 */ 505 static inline void 506 fss_error(struct fss_softc *sc, const char *msg) 507 { 508 509 KASSERT(mutex_owned(&sc->sc_slock)); 510 511 if ((sc->sc_flags & FSS_ERROR)) 512 return; 513 514 aprint_error_dev(sc->sc_dev, "snapshot invalid: %s\n", msg); 515 if ((sc->sc_flags & FSS_PERSISTENT) == 0) { 516 mutex_exit(&sc->sc_slock); 517 fscow_disestablish(sc->sc_mount, fss_copy_on_write, sc); 518 mutex_enter(&sc->sc_slock); 519 } 520 sc->sc_flags |= FSS_ERROR; 521 } 522 523 /* 524 * Allocate the variable sized parts of the softc and 525 * fork the kernel thread. 526 * 527 * The fields sc_clcount, sc_clshift, sc_cache_size and sc_indir_size 528 * must be initialized. 529 */ 530 static int 531 fss_softc_alloc(struct fss_softc *sc) 532 { 533 int i, error; 534 535 if ((sc->sc_flags & FSS_PERSISTENT) == 0) { 536 sc->sc_copied = 537 kmem_zalloc(howmany(sc->sc_clcount, NBBY), KM_SLEEP); 538 sc->sc_cache = kmem_alloc(sc->sc_cache_size * 539 sizeof(struct fss_cache), KM_SLEEP); 540 for (i = 0; i < sc->sc_cache_size; i++) { 541 sc->sc_cache[i].fc_type = FSS_CACHE_FREE; 542 sc->sc_cache[i].fc_data = 543 kmem_alloc(FSS_CLSIZE(sc), KM_SLEEP); 544 cv_init(&sc->sc_cache[i].fc_state_cv, "cowwait1"); 545 } 546 547 sc->sc_indir_valid = 548 kmem_zalloc(howmany(sc->sc_indir_size, NBBY), KM_SLEEP); 549 sc->sc_indir_data = kmem_zalloc(FSS_CLSIZE(sc), KM_SLEEP); 550 } else { 551 sc->sc_copied = NULL; 552 sc->sc_cache = NULL; 553 sc->sc_indir_valid = NULL; 554 sc->sc_indir_data = NULL; 555 } 556 557 sc->sc_flags |= FSS_BS_THREAD; 558 if ((error = kthread_create(PRI_BIO, KTHREAD_MUSTJOIN, NULL, 559 fss_bs_thread, sc, &sc->sc_bs_lwp, 560 "%s", device_xname(sc->sc_dev))) != 0) { 561 sc->sc_flags &= ~FSS_BS_THREAD; 562 return error; 563 } 564 565 disk_attach(sc->sc_dkdev); 566 567 return 0; 568 } 569 570 /* 571 * Free the variable sized parts of the softc. 572 */ 573 static void 574 fss_softc_free(struct fss_softc *sc) 575 { 576 int i; 577 578 if ((sc->sc_flags & FSS_BS_THREAD) != 0) { 579 mutex_enter(&sc->sc_slock); 580 sc->sc_flags &= ~FSS_BS_THREAD; 581 cv_signal(&sc->sc_work_cv); 582 mutex_exit(&sc->sc_slock); 583 kthread_join(sc->sc_bs_lwp); 584 585 disk_detach(sc->sc_dkdev); 586 } 587 588 if (sc->sc_copied != NULL) 589 kmem_free(sc->sc_copied, howmany(sc->sc_clcount, NBBY)); 590 sc->sc_copied = NULL; 591 592 if (sc->sc_cache != NULL) { 593 for (i = 0; i < sc->sc_cache_size; i++) 594 if (sc->sc_cache[i].fc_data != NULL) { 595 cv_destroy(&sc->sc_cache[i].fc_state_cv); 596 kmem_free(sc->sc_cache[i].fc_data, 597 FSS_CLSIZE(sc)); 598 } 599 kmem_free(sc->sc_cache, 600 sc->sc_cache_size*sizeof(struct fss_cache)); 601 } 602 sc->sc_cache = NULL; 603 604 if (sc->sc_indir_valid != NULL) 605 kmem_free(sc->sc_indir_valid, howmany(sc->sc_indir_size, NBBY)); 606 sc->sc_indir_valid = NULL; 607 608 if (sc->sc_indir_data != NULL) 609 kmem_free(sc->sc_indir_data, FSS_CLSIZE(sc)); 610 sc->sc_indir_data = NULL; 611 } 612 613 /* 614 * Set all active snapshots on this file system into ERROR state. 615 */ 616 static void 617 fss_unmount_hook(struct mount *mp) 618 { 619 int i; 620 struct fss_softc *sc; 621 622 mutex_enter(&fss_device_lock); 623 for (i = 0; i < fss_cd.cd_ndevs; i++) { 624 if ((sc = device_lookup_private(&fss_cd, i)) == NULL) 625 continue; 626 mutex_enter(&sc->sc_slock); 627 if (sc->sc_state != FSS_IDLE && sc->sc_mount == mp) 628 fss_error(sc, "forced by unmount"); 629 mutex_exit(&sc->sc_slock); 630 } 631 mutex_exit(&fss_device_lock); 632 } 633 634 /* 635 * A buffer is written to the snapshotted block device. Copy to 636 * backing store if needed. 637 */ 638 static int 639 fss_copy_on_write(void *v, struct buf *bp, bool data_valid) 640 { 641 int error; 642 u_int32_t cl, ch, c; 643 struct fss_softc *sc = v; 644 645 mutex_enter(&sc->sc_slock); 646 if (sc->sc_state != FSS_ACTIVE) { 647 mutex_exit(&sc->sc_slock); 648 return 0; 649 } 650 651 cl = FSS_BTOCL(sc, dbtob(bp->b_blkno)); 652 ch = FSS_BTOCL(sc, dbtob(bp->b_blkno)+bp->b_bcount-1); 653 error = 0; 654 if (curlwp == uvm.pagedaemon_lwp) { 655 for (c = cl; c <= ch; c++) 656 if (isclr(sc->sc_copied, c)) { 657 error = ENOMEM; 658 break; 659 } 660 } 661 mutex_exit(&sc->sc_slock); 662 663 if (error == 0) 664 for (c = cl; c <= ch; c++) { 665 error = fss_read_cluster(sc, c); 666 if (error) 667 break; 668 } 669 670 return error; 671 } 672 673 /* 674 * Lookup and open needed files. 675 * 676 * For file system internal snapshot initializes sc_mntname, sc_mount, 677 * sc_bs_vp and sc_time. 678 * 679 * Otherwise returns dev and size of the underlying block device. 680 * Initializes sc_mntname, sc_mount, sc_bdev, sc_bs_vp and sc_mount 681 */ 682 static int 683 fss_create_files(struct fss_softc *sc, struct fss_set *fss, 684 off_t *bsize, struct lwp *l) 685 { 686 int error, bits, fsbsize; 687 uint64_t numsec; 688 unsigned int secsize; 689 struct timespec ts; 690 /* nd -> nd2 to reduce mistakes while updating only some namei calls */ 691 struct pathbuf *pb2; 692 struct nameidata nd2; 693 struct vnode *vp; 694 695 /* 696 * Get the mounted file system. 697 */ 698 699 error = namei_simple_user(fss->fss_mount, 700 NSM_FOLLOW_NOEMULROOT, &vp); 701 if (error != 0) 702 return error; 703 704 if ((vp->v_vflag & VV_ROOT) != VV_ROOT) { 705 vrele(vp); 706 return EINVAL; 707 } 708 709 sc->sc_mount = vp->v_mount; 710 memcpy(sc->sc_mntname, sc->sc_mount->mnt_stat.f_mntonname, MNAMELEN); 711 712 vrele(vp); 713 714 /* 715 * Check for file system internal snapshot. 716 */ 717 718 error = namei_simple_user(fss->fss_bstore, 719 NSM_FOLLOW_NOEMULROOT, &vp); 720 if (error != 0) 721 return error; 722 723 if (vp->v_type == VREG && vp->v_mount == sc->sc_mount) { 724 sc->sc_flags |= FSS_PERSISTENT; 725 sc->sc_bs_vp = vp; 726 727 fsbsize = sc->sc_bs_vp->v_mount->mnt_stat.f_iosize; 728 bits = sizeof(sc->sc_bs_bshift)*NBBY; 729 for (sc->sc_bs_bshift = 1; sc->sc_bs_bshift < bits; 730 sc->sc_bs_bshift++) 731 if (FSS_FSBSIZE(sc) == fsbsize) 732 break; 733 if (sc->sc_bs_bshift >= bits) 734 return EINVAL; 735 736 sc->sc_bs_bmask = FSS_FSBSIZE(sc)-1; 737 sc->sc_clshift = 0; 738 739 if ((fss->fss_flags & FSS_UNLINK_ON_CREATE) != 0) { 740 error = do_sys_unlink(fss->fss_bstore, UIO_USERSPACE); 741 if (error) 742 return error; 743 } 744 error = vn_lock(vp, LK_EXCLUSIVE); 745 if (error != 0) 746 return error; 747 error = VFS_SNAPSHOT(sc->sc_mount, sc->sc_bs_vp, &ts); 748 TIMESPEC_TO_TIMEVAL(&sc->sc_time, &ts); 749 750 VOP_UNLOCK(sc->sc_bs_vp); 751 752 return error; 753 } 754 vrele(vp); 755 756 /* 757 * Get the block device it is mounted on and its size. 758 */ 759 760 error = spec_node_lookup_by_mount(sc->sc_mount, &vp); 761 if (error) 762 return error; 763 sc->sc_bdev = vp->v_rdev; 764 765 error = getdisksize(vp, &numsec, &secsize); 766 vrele(vp); 767 if (error) 768 return error; 769 770 *bsize = (off_t)numsec*secsize; 771 772 /* 773 * Get the backing store 774 */ 775 776 error = pathbuf_copyin(fss->fss_bstore, &pb2); 777 if (error) { 778 return error; 779 } 780 NDINIT(&nd2, LOOKUP, FOLLOW, pb2); 781 if ((error = vn_open(&nd2, FREAD|FWRITE, 0)) != 0) { 782 pathbuf_destroy(pb2); 783 return error; 784 } 785 VOP_UNLOCK(nd2.ni_vp); 786 787 sc->sc_bs_vp = nd2.ni_vp; 788 789 if (nd2.ni_vp->v_type != VREG && nd2.ni_vp->v_type != VCHR) { 790 pathbuf_destroy(pb2); 791 return EINVAL; 792 } 793 pathbuf_destroy(pb2); 794 795 if ((fss->fss_flags & FSS_UNLINK_ON_CREATE) != 0) { 796 error = do_sys_unlink(fss->fss_bstore, UIO_USERSPACE); 797 if (error) 798 return error; 799 } 800 if (sc->sc_bs_vp->v_type == VREG) { 801 fsbsize = sc->sc_bs_vp->v_mount->mnt_stat.f_iosize; 802 if (fsbsize & (fsbsize-1)) /* No power of two */ 803 return EINVAL; 804 for (sc->sc_bs_bshift = 1; sc->sc_bs_bshift < 32; 805 sc->sc_bs_bshift++) 806 if (FSS_FSBSIZE(sc) == fsbsize) 807 break; 808 if (sc->sc_bs_bshift >= 32) 809 return EINVAL; 810 sc->sc_bs_bmask = FSS_FSBSIZE(sc)-1; 811 } else { 812 sc->sc_bs_bshift = DEV_BSHIFT; 813 sc->sc_bs_bmask = FSS_FSBSIZE(sc)-1; 814 } 815 816 return 0; 817 } 818 819 /* 820 * Create a snapshot. 821 */ 822 static int 823 fss_create_snapshot(struct fss_softc *sc, struct fss_set *fss, struct lwp *l) 824 { 825 int len, error; 826 u_int32_t csize; 827 off_t bsize; 828 829 bsize = 0; /* XXX gcc */ 830 831 /* 832 * Open needed files. 833 */ 834 if ((error = fss_create_files(sc, fss, &bsize, l)) != 0) 835 goto bad; 836 837 if (sc->sc_flags & FSS_PERSISTENT) { 838 fss_softc_alloc(sc); 839 mutex_enter(&sc->sc_slock); 840 sc->sc_state = FSS_ACTIVE; 841 mutex_exit(&sc->sc_slock); 842 return 0; 843 } 844 845 /* 846 * Set cluster size. Must be a power of two and 847 * a multiple of backing store block size. 848 */ 849 if (fss->fss_csize <= 0) 850 csize = MAXPHYS; 851 else 852 csize = fss->fss_csize; 853 if (bsize/csize > FSS_CLUSTER_MAX) 854 csize = bsize/FSS_CLUSTER_MAX+1; 855 856 for (sc->sc_clshift = sc->sc_bs_bshift; sc->sc_clshift < 32; 857 sc->sc_clshift++) 858 if (FSS_CLSIZE(sc) >= csize) 859 break; 860 if (sc->sc_clshift >= 32) { 861 error = EINVAL; 862 goto bad; 863 } 864 sc->sc_clmask = FSS_CLSIZE(sc)-1; 865 866 /* 867 * Set number of cache slots. 868 */ 869 if (FSS_CLSIZE(sc) <= 8192) 870 sc->sc_cache_size = 32; 871 else if (FSS_CLSIZE(sc) <= 65536) 872 sc->sc_cache_size = 8; 873 else 874 sc->sc_cache_size = 4; 875 876 /* 877 * Set number of clusters and size of last cluster. 878 */ 879 sc->sc_clcount = FSS_BTOCL(sc, bsize-1)+1; 880 sc->sc_clresid = FSS_CLOFF(sc, bsize-1)+1; 881 882 /* 883 * Set size of indirect table. 884 */ 885 len = sc->sc_clcount*sizeof(u_int32_t); 886 sc->sc_indir_size = FSS_BTOCL(sc, len)+1; 887 sc->sc_clnext = sc->sc_indir_size; 888 sc->sc_indir_cur = 0; 889 890 if ((error = fss_softc_alloc(sc)) != 0) 891 goto bad; 892 893 /* 894 * Activate the snapshot. 895 */ 896 897 if ((error = vfs_suspend(sc->sc_mount, 0)) != 0) 898 goto bad; 899 900 microtime(&sc->sc_time); 901 902 vrele_flush(sc->sc_mount); 903 error = VFS_SYNC(sc->sc_mount, MNT_WAIT, curlwp->l_cred); 904 if (error == 0) 905 error = fscow_establish(sc->sc_mount, fss_copy_on_write, sc); 906 if (error == 0) { 907 mutex_enter(&sc->sc_slock); 908 sc->sc_state = FSS_ACTIVE; 909 mutex_exit(&sc->sc_slock); 910 } 911 912 vfs_resume(sc->sc_mount); 913 914 if (error != 0) 915 goto bad; 916 917 aprint_debug_dev(sc->sc_dev, "%s snapshot active\n", sc->sc_mntname); 918 aprint_debug_dev(sc->sc_dev, 919 "%u clusters of %u, %u cache slots, %u indir clusters\n", 920 sc->sc_clcount, FSS_CLSIZE(sc), 921 sc->sc_cache_size, sc->sc_indir_size); 922 923 return 0; 924 925 bad: 926 fss_softc_free(sc); 927 if (sc->sc_bs_vp != NULL) { 928 if (sc->sc_flags & FSS_PERSISTENT) 929 vrele(sc->sc_bs_vp); 930 else 931 vn_close(sc->sc_bs_vp, FREAD|FWRITE, l->l_cred); 932 } 933 sc->sc_bs_vp = NULL; 934 935 return error; 936 } 937 938 /* 939 * Delete a snapshot. 940 */ 941 static int 942 fss_delete_snapshot(struct fss_softc *sc, struct lwp *l) 943 { 944 945 mutex_enter(&sc->sc_slock); 946 if ((sc->sc_flags & FSS_PERSISTENT) == 0 && 947 (sc->sc_flags & FSS_ERROR) == 0) { 948 mutex_exit(&sc->sc_slock); 949 fscow_disestablish(sc->sc_mount, fss_copy_on_write, sc); 950 } else { 951 mutex_exit(&sc->sc_slock); 952 } 953 954 fss_softc_free(sc); 955 if (sc->sc_flags & FSS_PERSISTENT) 956 vrele(sc->sc_bs_vp); 957 else 958 vn_close(sc->sc_bs_vp, FREAD|FWRITE, l->l_cred); 959 960 mutex_enter(&sc->sc_slock); 961 sc->sc_state = FSS_IDLE; 962 sc->sc_mount = NULL; 963 sc->sc_bdev = NODEV; 964 sc->sc_bs_vp = NULL; 965 sc->sc_flags &= ~FSS_PERSISTENT; 966 mutex_exit(&sc->sc_slock); 967 968 return 0; 969 } 970 971 /* 972 * Read a cluster from the snapshotted block device to the cache. 973 */ 974 static int 975 fss_read_cluster(struct fss_softc *sc, u_int32_t cl) 976 { 977 int error, todo, offset, len; 978 daddr_t dblk; 979 struct buf *bp, *mbp; 980 struct fss_cache *scp, *scl; 981 982 /* 983 * Get a free cache slot. 984 */ 985 scl = sc->sc_cache+sc->sc_cache_size; 986 987 mutex_enter(&sc->sc_slock); 988 989 restart: 990 if (isset(sc->sc_copied, cl) || sc->sc_state != FSS_ACTIVE) { 991 mutex_exit(&sc->sc_slock); 992 return 0; 993 } 994 995 for (scp = sc->sc_cache; scp < scl; scp++) { 996 if (scp->fc_type == FSS_CACHE_VALID) { 997 if (scp->fc_cluster == cl) { 998 mutex_exit(&sc->sc_slock); 999 return 0; 1000 } 1001 } else if (scp->fc_type == FSS_CACHE_BUSY) { 1002 if (scp->fc_cluster == cl) { 1003 cv_wait(&scp->fc_state_cv, &sc->sc_slock); 1004 goto restart; 1005 } 1006 } 1007 } 1008 1009 for (scp = sc->sc_cache; scp < scl; scp++) 1010 if (scp->fc_type == FSS_CACHE_FREE) { 1011 scp->fc_type = FSS_CACHE_BUSY; 1012 scp->fc_cluster = cl; 1013 break; 1014 } 1015 if (scp >= scl) { 1016 cv_wait(&sc->sc_cache_cv, &sc->sc_slock); 1017 goto restart; 1018 } 1019 1020 mutex_exit(&sc->sc_slock); 1021 1022 /* 1023 * Start the read. 1024 */ 1025 dblk = btodb(FSS_CLTOB(sc, cl)); 1026 if (cl == sc->sc_clcount-1) { 1027 todo = sc->sc_clresid; 1028 memset((char *)scp->fc_data + todo, 0, FSS_CLSIZE(sc) - todo); 1029 } else 1030 todo = FSS_CLSIZE(sc); 1031 offset = 0; 1032 mbp = getiobuf(NULL, true); 1033 mbp->b_bufsize = todo; 1034 mbp->b_data = scp->fc_data; 1035 mbp->b_resid = mbp->b_bcount = todo; 1036 mbp->b_flags = B_READ; 1037 mbp->b_cflags = BC_BUSY; 1038 mbp->b_dev = sc->sc_bdev; 1039 while (todo > 0) { 1040 len = todo; 1041 if (len > MAXPHYS) 1042 len = MAXPHYS; 1043 if (btodb(FSS_CLTOB(sc, cl)) == dblk && len == todo) 1044 bp = mbp; 1045 else { 1046 bp = getiobuf(NULL, true); 1047 nestiobuf_setup(mbp, bp, offset, len); 1048 } 1049 bp->b_lblkno = 0; 1050 bp->b_blkno = dblk; 1051 bdev_strategy(bp); 1052 dblk += btodb(len); 1053 offset += len; 1054 todo -= len; 1055 } 1056 error = biowait(mbp); 1057 if (error == 0 && mbp->b_resid != 0) 1058 error = EIO; 1059 putiobuf(mbp); 1060 1061 mutex_enter(&sc->sc_slock); 1062 scp->fc_type = (error ? FSS_CACHE_FREE : FSS_CACHE_VALID); 1063 cv_broadcast(&scp->fc_state_cv); 1064 if (error == 0) { 1065 setbit(sc->sc_copied, scp->fc_cluster); 1066 cv_signal(&sc->sc_work_cv); 1067 } 1068 mutex_exit(&sc->sc_slock); 1069 1070 return error; 1071 } 1072 1073 /* 1074 * Read/write clusters from/to backing store. 1075 * For persistent snapshots must be called with cl == 0. off is the 1076 * offset into the snapshot. 1077 */ 1078 static int 1079 fss_bs_io(struct fss_softc *sc, fss_io_type rw, 1080 u_int32_t cl, off_t off, int len, void *data, size_t *resid) 1081 { 1082 int error; 1083 1084 off += FSS_CLTOB(sc, cl); 1085 1086 vn_lock(sc->sc_bs_vp, LK_EXCLUSIVE|LK_RETRY); 1087 1088 error = vn_rdwr((rw == FSS_READ ? UIO_READ : UIO_WRITE), sc->sc_bs_vp, 1089 data, len, off, UIO_SYSSPACE, 1090 IO_ADV_ENCODE(POSIX_FADV_NOREUSE) | IO_NODELOCKED, 1091 sc->sc_bs_lwp->l_cred, resid, NULL); 1092 if (error == 0) { 1093 mutex_enter(sc->sc_bs_vp->v_interlock); 1094 error = VOP_PUTPAGES(sc->sc_bs_vp, trunc_page(off), 1095 round_page(off+len), PGO_CLEANIT | PGO_FREE | PGO_SYNCIO); 1096 } 1097 1098 VOP_UNLOCK(sc->sc_bs_vp); 1099 1100 return error; 1101 } 1102 1103 /* 1104 * Get a pointer to the indirect slot for this cluster. 1105 */ 1106 static u_int32_t * 1107 fss_bs_indir(struct fss_softc *sc, u_int32_t cl) 1108 { 1109 u_int32_t icl; 1110 int ioff; 1111 1112 icl = cl/(FSS_CLSIZE(sc)/sizeof(u_int32_t)); 1113 ioff = cl%(FSS_CLSIZE(sc)/sizeof(u_int32_t)); 1114 1115 if (sc->sc_indir_cur == icl) 1116 return &sc->sc_indir_data[ioff]; 1117 1118 if (sc->sc_indir_dirty) { 1119 if (fss_bs_io(sc, FSS_WRITE, sc->sc_indir_cur, 0, 1120 FSS_CLSIZE(sc), (void *)sc->sc_indir_data, NULL) != 0) 1121 return NULL; 1122 setbit(sc->sc_indir_valid, sc->sc_indir_cur); 1123 } 1124 1125 sc->sc_indir_dirty = 0; 1126 sc->sc_indir_cur = icl; 1127 1128 if (isset(sc->sc_indir_valid, sc->sc_indir_cur)) { 1129 if (fss_bs_io(sc, FSS_READ, sc->sc_indir_cur, 0, 1130 FSS_CLSIZE(sc), (void *)sc->sc_indir_data, NULL) != 0) 1131 return NULL; 1132 } else 1133 memset(sc->sc_indir_data, 0, FSS_CLSIZE(sc)); 1134 1135 return &sc->sc_indir_data[ioff]; 1136 } 1137 1138 /* 1139 * The kernel thread (one for every active snapshot). 1140 * 1141 * After wakeup it cleans the cache and runs the I/O requests. 1142 */ 1143 static void 1144 fss_bs_thread(void *arg) 1145 { 1146 bool thread_idle, is_valid; 1147 int error, i, todo, len, crotor, is_read; 1148 long off; 1149 char *addr; 1150 u_int32_t c, cl, ch, *indirp; 1151 size_t resid; 1152 struct buf *bp, *nbp; 1153 struct fss_softc *sc; 1154 struct fss_cache *scp, *scl; 1155 1156 sc = arg; 1157 scl = sc->sc_cache+sc->sc_cache_size; 1158 crotor = 0; 1159 thread_idle = false; 1160 1161 mutex_enter(&sc->sc_slock); 1162 1163 for (;;) { 1164 if (thread_idle) 1165 cv_wait(&sc->sc_work_cv, &sc->sc_slock); 1166 thread_idle = true; 1167 if ((sc->sc_flags & FSS_BS_THREAD) == 0) { 1168 mutex_exit(&sc->sc_slock); 1169 kthread_exit(0); 1170 } 1171 1172 /* 1173 * Process I/O requests (persistent) 1174 */ 1175 1176 if (sc->sc_flags & FSS_PERSISTENT) { 1177 if ((bp = bufq_get(sc->sc_bufq)) == NULL) 1178 continue; 1179 is_valid = (sc->sc_state == FSS_ACTIVE); 1180 is_read = (bp->b_flags & B_READ); 1181 thread_idle = false; 1182 mutex_exit(&sc->sc_slock); 1183 1184 if (is_valid) { 1185 disk_busy(sc->sc_dkdev); 1186 error = fss_bs_io(sc, FSS_READ, 0, 1187 dbtob(bp->b_blkno), bp->b_bcount, 1188 bp->b_data, &resid); 1189 if (error) 1190 resid = bp->b_bcount; 1191 disk_unbusy(sc->sc_dkdev, 1192 (error ? 0 : bp->b_bcount), is_read); 1193 } else { 1194 error = ENXIO; 1195 resid = bp->b_bcount; 1196 } 1197 1198 bp->b_error = error; 1199 bp->b_resid = resid; 1200 biodone(bp); 1201 1202 mutex_enter(&sc->sc_slock); 1203 continue; 1204 } 1205 1206 /* 1207 * Clean the cache 1208 */ 1209 for (i = 0; i < sc->sc_cache_size; i++) { 1210 crotor = (crotor + 1) % sc->sc_cache_size; 1211 scp = sc->sc_cache + crotor; 1212 if (scp->fc_type != FSS_CACHE_VALID) 1213 continue; 1214 mutex_exit(&sc->sc_slock); 1215 1216 thread_idle = false; 1217 indirp = fss_bs_indir(sc, scp->fc_cluster); 1218 if (indirp != NULL) { 1219 error = fss_bs_io(sc, FSS_WRITE, sc->sc_clnext, 1220 0, FSS_CLSIZE(sc), scp->fc_data, NULL); 1221 } else 1222 error = EIO; 1223 1224 mutex_enter(&sc->sc_slock); 1225 if (error == 0) { 1226 *indirp = sc->sc_clnext++; 1227 sc->sc_indir_dirty = 1; 1228 } else 1229 fss_error(sc, "write error on backing store"); 1230 1231 scp->fc_type = FSS_CACHE_FREE; 1232 cv_broadcast(&sc->sc_cache_cv); 1233 break; 1234 } 1235 1236 /* 1237 * Process I/O requests 1238 */ 1239 if ((bp = bufq_get(sc->sc_bufq)) == NULL) 1240 continue; 1241 is_valid = (sc->sc_state == FSS_ACTIVE); 1242 is_read = (bp->b_flags & B_READ); 1243 thread_idle = false; 1244 1245 if (!is_valid) { 1246 mutex_exit(&sc->sc_slock); 1247 1248 bp->b_error = ENXIO; 1249 bp->b_resid = bp->b_bcount; 1250 biodone(bp); 1251 1252 mutex_enter(&sc->sc_slock); 1253 continue; 1254 } 1255 1256 disk_busy(sc->sc_dkdev); 1257 1258 /* 1259 * First read from the snapshotted block device unless 1260 * this request is completely covered by backing store. 1261 */ 1262 1263 cl = FSS_BTOCL(sc, dbtob(bp->b_blkno)); 1264 off = FSS_CLOFF(sc, dbtob(bp->b_blkno)); 1265 ch = FSS_BTOCL(sc, dbtob(bp->b_blkno)+bp->b_bcount-1); 1266 error = 0; 1267 bp->b_resid = 0; 1268 bp->b_error = 0; 1269 for (c = cl; c <= ch; c++) { 1270 if (isset(sc->sc_copied, c)) 1271 continue; 1272 mutex_exit(&sc->sc_slock); 1273 1274 /* Not on backing store, read from device. */ 1275 nbp = getiobuf(NULL, true); 1276 nbp->b_flags = B_READ; 1277 nbp->b_resid = nbp->b_bcount = bp->b_bcount; 1278 nbp->b_bufsize = bp->b_bcount; 1279 nbp->b_data = bp->b_data; 1280 nbp->b_blkno = bp->b_blkno; 1281 nbp->b_lblkno = 0; 1282 nbp->b_dev = sc->sc_bdev; 1283 SET(nbp->b_cflags, BC_BUSY); /* mark buffer busy */ 1284 1285 bdev_strategy(nbp); 1286 1287 error = biowait(nbp); 1288 if (error == 0 && nbp->b_resid != 0) 1289 error = EIO; 1290 if (error != 0) { 1291 bp->b_resid = bp->b_bcount; 1292 bp->b_error = nbp->b_error; 1293 disk_unbusy(sc->sc_dkdev, 0, is_read); 1294 biodone(bp); 1295 } 1296 putiobuf(nbp); 1297 1298 mutex_enter(&sc->sc_slock); 1299 break; 1300 } 1301 if (error) 1302 continue; 1303 1304 /* 1305 * Replace those parts that have been saved to backing store. 1306 */ 1307 1308 addr = bp->b_data; 1309 todo = bp->b_bcount; 1310 for (c = cl; c <= ch; c++, off = 0, todo -= len, addr += len) { 1311 len = FSS_CLSIZE(sc)-off; 1312 if (len > todo) 1313 len = todo; 1314 if (isclr(sc->sc_copied, c)) 1315 continue; 1316 mutex_exit(&sc->sc_slock); 1317 1318 indirp = fss_bs_indir(sc, c); 1319 if (indirp == NULL || *indirp == 0) { 1320 /* 1321 * Not on backing store. Either in cache 1322 * or hole in the snapshotted block device. 1323 */ 1324 1325 mutex_enter(&sc->sc_slock); 1326 for (scp = sc->sc_cache; scp < scl; scp++) 1327 if (scp->fc_type == FSS_CACHE_VALID && 1328 scp->fc_cluster == c) 1329 break; 1330 if (scp < scl) 1331 memcpy(addr, (char *)scp->fc_data+off, 1332 len); 1333 else 1334 memset(addr, 0, len); 1335 continue; 1336 } 1337 1338 /* 1339 * Read from backing store. 1340 */ 1341 error = fss_bs_io(sc, FSS_READ, 1342 *indirp, off, len, addr, NULL); 1343 1344 mutex_enter(&sc->sc_slock); 1345 if (error) { 1346 bp->b_resid = bp->b_bcount; 1347 bp->b_error = error; 1348 break; 1349 } 1350 } 1351 mutex_exit(&sc->sc_slock); 1352 1353 disk_unbusy(sc->sc_dkdev, (error ? 0 : bp->b_bcount), is_read); 1354 biodone(bp); 1355 1356 mutex_enter(&sc->sc_slock); 1357 } 1358 } 1359 1360 #ifdef _MODULE 1361 1362 #include <sys/module.h> 1363 1364 MODULE(MODULE_CLASS_DRIVER, fss, "bufq_fcfs"); 1365 CFDRIVER_DECL(fss, DV_DISK, NULL); 1366 1367 devmajor_t fss_bmajor = -1, fss_cmajor = -1; 1368 1369 static int 1370 fss_modcmd(modcmd_t cmd, void *arg) 1371 { 1372 int error = 0; 1373 1374 switch (cmd) { 1375 case MODULE_CMD_INIT: 1376 mutex_init(&fss_device_lock, MUTEX_DEFAULT, IPL_NONE); 1377 cv_init(&fss_device_cv, "snapwait"); 1378 error = config_cfdriver_attach(&fss_cd); 1379 if (error) { 1380 mutex_destroy(&fss_device_lock); 1381 break; 1382 } 1383 error = config_cfattach_attach(fss_cd.cd_name, &fss_ca); 1384 if (error) { 1385 config_cfdriver_detach(&fss_cd); 1386 mutex_destroy(&fss_device_lock); 1387 break; 1388 } 1389 error = devsw_attach(fss_cd.cd_name, 1390 &fss_bdevsw, &fss_bmajor, &fss_cdevsw, &fss_cmajor); 1391 1392 if (error) { 1393 config_cfattach_detach(fss_cd.cd_name, &fss_ca); 1394 config_cfdriver_detach(&fss_cd); 1395 mutex_destroy(&fss_device_lock); 1396 break; 1397 } 1398 break; 1399 1400 case MODULE_CMD_FINI: 1401 devsw_detach(&fss_bdevsw, &fss_cdevsw); 1402 error = config_cfattach_detach(fss_cd.cd_name, &fss_ca); 1403 if (error) { 1404 devsw_attach(fss_cd.cd_name, &fss_bdevsw, &fss_bmajor, 1405 &fss_cdevsw, &fss_cmajor); 1406 break; 1407 } 1408 error = config_cfdriver_detach(&fss_cd); 1409 if (error) { 1410 devsw_attach(fss_cd.cd_name, 1411 &fss_bdevsw, &fss_bmajor, &fss_cdevsw, &fss_cmajor); 1412 devsw_attach(fss_cd.cd_name, &fss_bdevsw, &fss_bmajor, 1413 &fss_cdevsw, &fss_cmajor); 1414 break; 1415 } 1416 cv_destroy(&fss_device_cv); 1417 mutex_destroy(&fss_device_lock); 1418 break; 1419 1420 default: 1421 error = ENOTTY; 1422 break; 1423 } 1424 1425 return error; 1426 } 1427 1428 #endif /* _MODULE */ 1429