Home | History | Annotate | Line # | Download | only in dev
fss.c revision 1.3
      1 /*	$NetBSD: fss.c,v 1.3 2004/01/10 17:16:38 hannken 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  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * File system snapshot disk driver.
     41  *
     42  * Block/character interface to the snapshot of a mounted file system.
     43  */
     44 
     45 #include <sys/cdefs.h>
     46 __KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.3 2004/01/10 17:16:38 hannken Exp $");
     47 
     48 #include <sys/param.h>
     49 #include <sys/systm.h>
     50 #include <sys/namei.h>
     51 #include <sys/proc.h>
     52 #include <sys/errno.h>
     53 #include <sys/buf.h>
     54 #include <sys/malloc.h>
     55 #include <sys/ioctl.h>
     56 #include <sys/disklabel.h>
     57 #include <sys/device.h>
     58 #include <sys/disk.h>
     59 #include <sys/stat.h>
     60 #include <sys/mount.h>
     61 #include <sys/vnode.h>
     62 #include <sys/file.h>
     63 #include <sys/uio.h>
     64 #include <sys/conf.h>
     65 #include <sys/kthread.h>
     66 
     67 #include <miscfs/specfs/specdev.h>
     68 
     69 #include <machine/stdarg.h>
     70 
     71 #include "fss.h"
     72 #include <dev/fssvar.h>
     73 
     74 #ifdef DEBUG
     75 #include "opt_ddb.h"
     76 #include <ddb/ddbvar.h>
     77 #include <machine/db_machdep.h>
     78 #include <ddb/db_command.h>
     79 #include <ddb/db_interface.h>
     80 #endif
     81 
     82 #ifdef DEBUG
     83 #define FSS_STATISTICS
     84 #endif
     85 
     86 #ifdef FSS_STATISTICS
     87 struct fss_stat {
     88 	u_int64_t	cow_calls;
     89 	u_int64_t	cow_copied;
     90 	u_int64_t	cow_cache_full;
     91 	u_int64_t	indir_read;
     92 	u_int64_t	indir_write;
     93 };
     94 
     95 static struct fss_stat fss_stat[NFSS];
     96 
     97 #define FSS_STAT_INC(sc, field)	\
     98 			do { \
     99 				fss_stat[sc->sc_unit].field++; \
    100 			} while (0)
    101 #define FSS_STAT_SET(sc, field, value) \
    102 			do { \
    103 				fss_stat[sc->sc_unit].field = value; \
    104 			} while (0)
    105 #define FSS_STAT_ADD(sc, field, value) \
    106 			do { \
    107 				fss_stat[sc->sc_unit].field += value; \
    108 			} while (0)
    109 #define FSS_STAT_VAL(sc, field) fss_stat[sc->sc_unit].field
    110 #define FSS_STAT_CLEAR(sc) \
    111 			do { \
    112 				memset(&fss_stat[sc->sc_unit], 0, \
    113 				    sizeof(struct fss_stat)); \
    114 			} while (0)
    115 #else /* FSS_STATISTICS */
    116 #define FSS_STAT_INC(sc, field)
    117 #define FSS_STAT_SET(sc, field, value)
    118 #define FSS_STAT_ADD(sc, field, value)
    119 #define FSS_STAT_CLEAR(sc)
    120 #endif /* FSS_STATISTICS */
    121 
    122 typedef enum {
    123 	FSS_READ,
    124 	FSS_WRITE
    125 } fss_io_type;
    126 
    127 void fssattach(int);
    128 
    129 dev_type_open(fss_open);
    130 dev_type_close(fss_close);
    131 dev_type_read(fss_read);
    132 dev_type_write(fss_write);
    133 dev_type_ioctl(fss_ioctl);
    134 dev_type_strategy(fss_strategy);
    135 dev_type_dump(fss_dump);
    136 dev_type_size(fss_size);
    137 
    138 static inline void fss_error(struct fss_softc *, const char *, ...);
    139 static inline int fss_valid(struct fss_softc *);
    140 static int fss_create_snapshot(struct fss_softc *, struct fss_set *,
    141     struct proc *);
    142 static int fss_delete_snapshot(struct fss_softc *, struct proc *);
    143 static int fss_softc_alloc(struct fss_softc *);
    144 static void fss_softc_free(struct fss_softc *);
    145 static void fss_cluster_iodone(struct buf *);
    146 static void fss_read_cluster(struct fss_softc *, u_int32_t);
    147 static int fss_write_cluster(struct fss_cache *, u_int32_t);
    148 static void fss_bs_thread(void *);
    149 static inline void block_to_cluster(struct fss_softc *, daddr_t, long,
    150     u_int32_t *, long *);
    151 static int fss_bs_io(struct fss_softc *, fss_io_type,
    152     u_int32_t, long, int, caddr_t);
    153 static u_int32_t *fss_bs_indir(struct fss_softc *, u_int32_t);
    154 
    155 const struct bdevsw fss_bdevsw = {
    156 	fss_open, fss_close, fss_strategy, fss_ioctl,
    157 	fss_dump, fss_size, D_DISK
    158 };
    159 
    160 const struct cdevsw fss_cdevsw = {
    161 	fss_open, fss_close, fss_read, fss_write, fss_ioctl,
    162 	nostop, notty, nopoll, nommap, nokqfilter, D_DISK
    163 };
    164 
    165 void
    166 fssattach(int num)
    167 {
    168 	int i;
    169 	struct fss_softc *sc;
    170 
    171 	for (i = 0; i < NFSS; i++) {
    172 		sc = &fss_softc[i];
    173 		sc->sc_unit = i;
    174 		sc->sc_bdev = NODEV;
    175 		lockinit(&sc->sc_lock, PRIBIO, "fsslock", 0, 0);
    176 		bufq_alloc(&sc->sc_bufq, BUFQ_FCFS|BUFQ_SORT_RAWBLOCK);
    177 	}
    178 }
    179 
    180 int
    181 fss_open(dev_t dev, int flags, int mode, struct proc *p)
    182 {
    183 	struct fss_softc *sc;
    184 
    185 	if (fss_dev_to_softc(dev, &sc) != 0)
    186 		return ENXIO;
    187 
    188 	return 0;
    189 }
    190 
    191 int
    192 fss_close(dev_t dev, int flags, int mode, struct proc *p)
    193 {
    194 	struct fss_softc *sc;
    195 
    196 	if (fss_dev_to_softc(dev, &sc) != 0)
    197 		return ENXIO;
    198 
    199 	return 0;
    200 }
    201 
    202 void
    203 fss_strategy(struct buf *bp)
    204 {
    205 	struct fss_softc *sc;
    206 
    207 	if ((bp->b_flags & B_READ) != B_READ ||
    208 	    fss_dev_to_softc(bp->b_dev, &sc) != 0 ||
    209 	    !fss_valid(sc)) {
    210 		bp->b_error = ENXIO;
    211 		bp->b_flags |= B_ERROR;
    212 		bp->b_resid = bp->b_bcount;
    213 		biodone(bp);
    214 		return;
    215 	}
    216 
    217 	bp->b_rawblkno = bp->b_blkno;
    218 	BUFQ_PUT(&sc->sc_bufq, bp);
    219 	wakeup(&sc->sc_bs_proc);
    220 }
    221 
    222 int
    223 fss_read(dev_t dev, struct uio *uio, int flags)
    224 {
    225 	return physio(fss_strategy, NULL, dev, B_READ, minphys, uio);
    226 }
    227 
    228 int
    229 fss_write(dev_t dev, struct uio *uio, int flags)
    230 {
    231 	return physio(fss_strategy, NULL, dev, B_WRITE, minphys, uio);
    232 }
    233 
    234 int
    235 fss_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
    236 {
    237 	int error;
    238 	struct fss_softc *sc;
    239 	struct fss_set *fss = (struct fss_set *)data;
    240 	struct fss_get *fsg = (struct fss_get *)data;
    241 
    242 	if ((error = fss_dev_to_softc(dev, &sc)) != 0)
    243 		return error;
    244 
    245 	lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
    246 
    247 	error = EINVAL;
    248 
    249 	switch (cmd) {
    250 	case FSSIOCSET:
    251 		if ((flag & FWRITE) == 0)
    252 			error = EPERM;
    253 		else if ((sc->sc_flags & FSS_ACTIVE) != 0)
    254 			error = EBUSY;
    255 		else
    256 			error = fss_create_snapshot(sc, fss, p);
    257 		break;
    258 
    259 	case FSSIOCCLR:
    260 		if ((flag & FWRITE) == 0)
    261 			error = EPERM;
    262 		else if ((sc->sc_flags & FSS_ACTIVE) == 0)
    263 			error = ENXIO;
    264 		else
    265 			error = fss_delete_snapshot(sc, p);
    266 		break;
    267 
    268 	case FSSIOCGET:
    269 		if ((sc->sc_flags & FSS_ACTIVE) == FSS_ACTIVE) {
    270 			memcpy(fsg->fsg_mount, sc->sc_mntname, MNAMELEN);
    271 			fsg->fsg_csize = sc->sc_clsize;
    272 			fsg->fsg_time = sc->sc_time;
    273 			fsg->fsg_mount_size = sc->sc_clcount;
    274 			fsg->fsg_bs_size = sc->sc_clnext;
    275 			error = 0;
    276 		} else
    277 			error = ENXIO;
    278 		break;
    279 	}
    280 
    281 	lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
    282 
    283 	return error;
    284 }
    285 
    286 int
    287 fss_size(dev_t dev)
    288 {
    289 	return -1;
    290 }
    291 
    292 int
    293 fss_dump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
    294 {
    295 	return ENXIO;
    296 }
    297 
    298 /*
    299  * An error occured reading or writing the snapshot or backing store.
    300  * If it is the first error log to console.
    301  */
    302 static inline void
    303 fss_error(struct fss_softc *sc, const char *fmt, ...)
    304 {
    305 	int s;
    306 	va_list ap;
    307 
    308 	s = splbio();
    309 	if ((sc->sc_flags & (FSS_ACTIVE|FSS_ERROR)) == FSS_ACTIVE) {
    310 		va_start(ap, fmt);
    311 		printf("fss%d: snapshot invalid: ", sc->sc_unit);
    312 		vprintf(fmt, ap);
    313 		printf("\n");
    314 		va_end(ap);
    315 	}
    316 	if ((sc->sc_flags & FSS_ACTIVE) == FSS_ACTIVE)
    317 		sc->sc_flags |= FSS_ERROR;
    318 	splx(s);
    319 }
    320 
    321 /*
    322  * Check if this snapshot is still valid.
    323  */
    324 static inline int
    325 fss_valid(struct fss_softc *sc)
    326 {
    327 	int s, valid;
    328 
    329 	s = splbio();
    330 	valid = ((sc->sc_flags & (FSS_ACTIVE|FSS_ERROR)) == FSS_ACTIVE);
    331 	splx(s);
    332 
    333 	return valid;
    334 }
    335 
    336 /*
    337  * Allocate the variable sized parts of the softc and
    338  * fork the kernel thread.
    339  *
    340  * The fields sc_clcount, sc_clsize, sc_cache_size and sc_indir_size
    341  * must be initialized.
    342  */
    343 static int
    344 fss_softc_alloc(struct fss_softc *sc)
    345 {
    346 	int i, len, error;
    347 
    348 	len = (sc->sc_clcount+NBBY-1)/NBBY;
    349 	sc->sc_copied = malloc(len, M_TEMP, M_ZERO|M_WAITOK);
    350 
    351 	len = sc->sc_cache_size*sizeof(struct fss_cache);
    352 	sc->sc_cache = malloc(len, M_TEMP, M_WAITOK);
    353 
    354 	len = sc->sc_clsize;
    355 	for (i = 0; i < sc->sc_cache_size; i++) {
    356 		sc->sc_cache[i].fc_type = FSS_CACHE_FREE;
    357 		sc->sc_cache[i].fc_softc = sc;
    358 		sc->sc_cache[i].fc_xfercount = 0;
    359 		sc->sc_cache[i].fc_data = malloc(len, M_TEMP, M_WAITOK);
    360 	}
    361 
    362 	len = (sc->sc_indir_size+NBBY-1)/NBBY;
    363 	sc->sc_indir_valid = malloc(len, M_TEMP, M_ZERO|M_WAITOK);
    364 
    365 	len = sc->sc_clsize;
    366 	sc->sc_indir_data = malloc(len, M_TEMP, M_ZERO|M_WAITOK);
    367 
    368 	if ((error = kthread_create1(fss_bs_thread, sc, &sc->sc_bs_proc,
    369 	    "fssbs%d", sc->sc_unit)) != 0)
    370 		return error;
    371 
    372 	sc->sc_flags |= FSS_BS_THREAD;
    373 	return 0;
    374 }
    375 
    376 /*
    377  * Free the variable sized parts of the softc.
    378  */
    379 static void
    380 fss_softc_free(struct fss_softc *sc)
    381 {
    382 	int i;
    383 
    384 	if ((sc->sc_flags & FSS_BS_THREAD) != 0) {
    385 		sc->sc_flags &= ~FSS_BS_THREAD;
    386 		wakeup(&sc->sc_bs_proc);
    387 		while (sc->sc_bs_proc != NULL)
    388 			tsleep(sc, PRIBIO, "fssthread", 1);
    389 	}
    390 
    391 	if (sc->sc_copied != NULL)
    392 		free(sc->sc_copied, M_TEMP);
    393 	sc->sc_copied = NULL;
    394 
    395 	if (sc->sc_cache != NULL) {
    396 		for (i = 0; i < sc->sc_cache_size; i++)
    397 			free(sc->sc_cache[i].fc_data, M_TEMP);
    398 		free(sc->sc_cache, M_TEMP);
    399 	}
    400 	sc->sc_cache = NULL;
    401 
    402 	if (sc->sc_indir_valid != NULL)
    403 		free(sc->sc_indir_valid, M_TEMP);
    404 	sc->sc_indir_valid = NULL;
    405 
    406 	if (sc->sc_indir_data != NULL)
    407 		free(sc->sc_indir_data, M_TEMP);
    408 	sc->sc_indir_data = NULL;
    409 }
    410 
    411 /*
    412  * Check if an unmount is ok. If forced, set this snapshot into ERROR state.
    413  */
    414 int
    415 fss_umount_hook(struct mount *mp, int forced)
    416 {
    417 	int i, s;
    418 
    419 	s = splbio();
    420 	for (i = 0; i < NFSS; i++)
    421 		if ((fss_softc[i].sc_flags & FSS_ACTIVE) != 0 &&
    422 		    fss_softc[i].sc_mount == mp) {
    423 			if (forced)
    424 				fss_error(&fss_softc[i], "forced unmount");
    425 			else {
    426 				splx(s);
    427 				return EBUSY;
    428 			}
    429 		}
    430 	splx(s);
    431 	return 0;
    432 }
    433 
    434 /*
    435  * A buffer is written to the snapshotted block device. Copy to
    436  * backing store if needed.
    437  */
    438 void
    439 fss_copy_on_write(struct fss_softc *sc, struct buf *bp)
    440 {
    441 	u_int32_t cl, ch, c;
    442 
    443 #ifdef DIAGNOSTIC
    444 	/*
    445 	 * Buffer written on a suspended file system. This is always an error.
    446 	 */
    447 	if (sc->sc_mount &&
    448 	    (sc->sc_mount->mnt_iflag & IMNT_SUSPENDED) == IMNT_SUSPENDED) {
    449 		printf_nolog("fss%d: write while suspended, %lu@%" PRId64 "\n",
    450 		    sc->sc_unit, bp->b_bcount, bp->b_blkno);
    451 #ifdef DEBUG
    452 		db_stack_trace_print((db_expr_t)__builtin_frame_address(0),
    453 		    TRUE, 65535, "", printf_nolog);
    454 #endif /* DEBUG */
    455 	}
    456 #endif /* DIAGNOSTIC */
    457 
    458 	if (!fss_valid(sc))
    459 		return;
    460 
    461 	sc->sc_cowcount++;
    462 
    463 	FSS_STAT_INC(sc, cow_calls);
    464 
    465 	block_to_cluster(sc, bp->b_blkno, 0, &cl, NULL);
    466 	block_to_cluster(sc, bp->b_blkno, bp->b_bcount-1, &ch, NULL);
    467 	for (c = cl; c <= ch; c++) {
    468 		if (!fss_valid(sc))
    469 			break;
    470 
    471 		fss_read_cluster(sc, c);
    472 	}
    473 
    474 	if (--sc->sc_cowcount == 0)
    475 		wakeup(&sc->sc_cowcount);
    476 }
    477 
    478 /*
    479  * Lookup and open needed files.
    480  *
    481  * Returns dev and size of the underlying block device.
    482  * Initializes the fields sc_mntname, sc_bs_vp, sc_mount and sc_strategy
    483  */
    484 static int
    485 fss_create_files(struct fss_softc *sc, struct fss_set *fss,
    486     dev_t *bdev, off_t *bsize, struct proc *p)
    487 {
    488 	int error;
    489 	struct partinfo dpart;
    490 	struct statfs statfs;
    491 	struct nameidata nd;
    492 	const struct bdevsw *bdevsw;
    493 
    494 	/*
    495 	 * Get the mounted file system.
    496 	 */
    497 
    498 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fss->fss_mount, p);
    499 	if ((error = namei(&nd)) != 0)
    500 		return error;
    501 
    502 	if ((nd.ni_vp->v_flag & VROOT) != VROOT) {
    503 		vrele(nd.ni_vp);
    504 		return EINVAL;
    505 	}
    506 
    507 	sc->sc_mount = nd.ni_vp->v_mount;
    508 
    509 	/*
    510 	 * Get the block device it is mounted on.
    511 	 */
    512 
    513 	error = VFS_STATFS(sc->sc_mount, &statfs, p);
    514 	vrele(nd.ni_vp);
    515 	if (error != 0)
    516 		return error;
    517 
    518 	memcpy(sc->sc_mntname, statfs.f_mntonname, MNAMELEN);
    519 
    520 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, statfs.f_mntfromname, p);
    521 	if ((error = namei(&nd)) != 0)
    522 		return error;
    523 
    524 	if (nd.ni_vp->v_type != VBLK) {
    525 		vrele(nd.ni_vp);
    526 		return EINVAL;
    527 	}
    528 
    529 	error = VOP_IOCTL(nd.ni_vp, DIOCGPART, &dpart, FREAD, p->p_ucred, p);
    530 	if (error) {
    531 		vrele(nd.ni_vp);
    532 		return error;
    533 	}
    534 
    535 	*bdev = nd.ni_vp->v_rdev;
    536 	*bsize = (off_t)dpart.disklab->d_secsize*dpart.part->p_size;
    537 	vrele(nd.ni_vp);
    538 
    539 	if ((bdevsw = bdevsw_lookup(*bdev)) == NULL)
    540 		return EINVAL;
    541 	sc->sc_strategy = bdevsw->d_strategy;
    542 
    543 	/*
    544 	 * Get the backing store
    545 	 */
    546 
    547 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fss->fss_bstore, p);
    548 	if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0)
    549 		return error;
    550 	VOP_UNLOCK(nd.ni_vp, 0);
    551 
    552 	sc->sc_bs_vp = nd.ni_vp;
    553 
    554 	if (nd.ni_vp->v_type != VREG && nd.ni_vp->v_type != VCHR)
    555 		return EINVAL;
    556 
    557 	if (nd.ni_vp->v_mount == sc->sc_mount)
    558 		return EDEADLK;
    559 
    560 	if (sc->sc_bs_vp->v_type == VREG) {
    561 		error = VFS_STATFS(sc->sc_bs_vp->v_mount, &statfs, p);
    562 		if (error != 0)
    563 			return error;
    564 		sc->sc_bs_bsize = statfs.f_iosize;
    565 	} else
    566 		sc->sc_bs_bsize = DEV_BSIZE;
    567 
    568 	/*
    569 	 * As all IO to from/to the backing store goes through
    570 	 * VOP_STRATEGY() clean the buffer cache to prevent
    571 	 * cache incoherencies.
    572 	 */
    573 	if ((error = vinvalbuf(sc->sc_bs_vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
    574 		return error;
    575 
    576 	return 0;
    577 }
    578 
    579 /*
    580  * Create a snapshot.
    581  */
    582 static int
    583 fss_create_snapshot(struct fss_softc *sc, struct fss_set *fss, struct proc *p)
    584 {
    585 	int len, error;
    586 	dev_t bdev;
    587 	off_t bsize;
    588 
    589 	/*
    590 	 * Open needed files.
    591 	 */
    592 	if ((error = fss_create_files(sc, fss, &bdev, &bsize, p)) != 0)
    593 		goto bad;
    594 
    595 	/*
    596 	 * Set parameters.
    597 	 */
    598 	if (fss->fss_csize == 0)
    599 		sc->sc_clsize = MAXPHYS;
    600 	else if (fss->fss_csize < 0 || (fss->fss_csize & (DEV_BSIZE-1)) != 0) {
    601 		error = EINVAL;
    602 		goto bad;
    603 	} else if (bsize/fss->fss_csize > FSS_CLUSTER_MAX)
    604 		sc->sc_clsize = (bsize/FSS_CLUSTER_MAX+DEV_BSIZE-1) &
    605 		    ~(DEV_BSIZE-1);
    606 	else
    607 		sc->sc_clsize = fss->fss_csize;
    608 
    609 	if (sc->sc_clsize <= 8192)
    610 		sc->sc_cache_size = 32;
    611 	else if (sc->sc_clsize <= 65536)
    612 		sc->sc_cache_size = 8;
    613 	else
    614 		sc->sc_cache_size = 4;
    615 
    616 	block_to_cluster(sc, btodb(bsize)-1, DEV_BSIZE-1,
    617 	    &sc->sc_clcount, &sc->sc_cllast);
    618 	sc->sc_clcount += 1;
    619 	sc->sc_cllast += 1;
    620 
    621 	len = sc->sc_clcount*sizeof(u_int32_t);
    622 	sc->sc_indir_size = (len+sc->sc_clsize-1)/sc->sc_clsize;
    623 	sc->sc_clnext = sc->sc_indir_size;
    624 	sc->sc_indir_cur = 0;
    625 
    626 	if ((error = fss_softc_alloc(sc)) != 0)
    627 		goto bad;
    628 
    629 	/* XXX FSSNAP_PREPARE */
    630 
    631 	/*
    632 	 * Activate the snapshot.
    633 	 */
    634 
    635 	if ((error = vfs_write_suspend(sc->sc_mount, PUSER|PCATCH, 0)) != 0)
    636 		goto bad;
    637 
    638 	microtime(&sc->sc_time);
    639 
    640 	/* XXX FSSNAP_CREATE */
    641 
    642 	if (error == 0) {
    643 		sc->sc_flags |= FSS_ACTIVE;
    644 		sc->sc_bdev = bdev;
    645 	}
    646 
    647 	vfs_write_resume(sc->sc_mount);
    648 
    649 	if (error != 0)
    650 		goto bad;
    651 
    652 #ifdef DEBUG
    653 	printf("fss%d: %s snapshot active\n", sc->sc_unit, sc->sc_mntname);
    654 	printf("fss%d: %u clusters of %u, %u cache slots, %u indir clusters\n",
    655 	    sc->sc_unit, sc->sc_clcount, sc->sc_clsize,
    656 	    sc->sc_cache_size, sc->sc_indir_size);
    657 #endif
    658 
    659 	return 0;
    660 
    661 bad:
    662 	fss_softc_free(sc);
    663 	if (sc->sc_bs_vp != NULL)
    664 		vn_close(sc->sc_bs_vp, FREAD|FWRITE, p->p_ucred, p);
    665 	sc->sc_bs_vp = NULL;
    666 
    667 	return error;
    668 }
    669 
    670 /*
    671  * Delete a snapshot.
    672  */
    673 static int
    674 fss_delete_snapshot(struct fss_softc *sc, struct proc *p)
    675 {
    676 	int s;
    677 
    678 	s = splbio();
    679 	sc->sc_flags &= ~(FSS_ACTIVE|FSS_ERROR);
    680 	splx(s);
    681 
    682 	while (sc->sc_cowcount > 0) {
    683 		tsleep(&sc->sc_cowcount, PRIBIO, "cowwait1", 0);
    684 	}
    685 
    686 	sc->sc_mount = NULL;
    687 	sc->sc_bdev = NODEV;
    688 	fss_softc_free(sc);
    689 	vn_close(sc->sc_bs_vp, FREAD|FWRITE, p->p_ucred, p);
    690 	sc->sc_bs_vp = NULL;
    691 
    692 	/* XXX FSSNAP_DESTROY */
    693 
    694 	FSS_STAT_CLEAR(sc);
    695 
    696 	return 0;
    697 }
    698 
    699 /*
    700  * Convert disk block with offset to backing store cluster with offset.
    701  */
    702 static inline void
    703 block_to_cluster(struct fss_softc *sc, daddr_t blkno, long off,
    704                  u_int32_t *cblk, long *coff)
    705 {
    706 	blkno = dbtob(blkno)+off;
    707 	if (cblk != NULL)
    708 		*cblk = blkno/sc->sc_clsize;
    709 	if (coff != NULL)
    710 		*coff = blkno%sc->sc_clsize;
    711 }
    712 
    713 /*
    714  * A read from the snapshotted block device has completed.
    715  */
    716 static void
    717 fss_cluster_iodone(struct buf *bp)
    718 {
    719 	int s;
    720 	struct fss_cache *scp = bp->b_private;
    721 
    722 	s = splbio();
    723 
    724 	if (bp->b_flags & B_EINTR)
    725 		fss_error(scp->fc_softc, "fs read interrupted");
    726 	if (bp->b_flags & B_ERROR)
    727 		fss_error(scp->fc_softc, "fs read error %d", bp->b_error);
    728 
    729 	if (bp->b_vp != NULL)
    730 		brelvp(bp);
    731 
    732 	if (--scp->fc_xfercount == 0)
    733 		wakeup(&scp->fc_data);
    734 
    735 	pool_put(&bufpool, bp);
    736 
    737 	splx(s);
    738 }
    739 
    740 /*
    741  * Read a cluster from the snapshotted block device to the cache.
    742  */
    743 static void
    744 fss_read_cluster(struct fss_softc *sc, u_int32_t cl)
    745 {
    746 	int s, todo, len;
    747 	caddr_t addr;
    748 	daddr_t dblk;
    749 	struct buf *bp;
    750 	struct fss_cache *scp, *scl;
    751 
    752 	/*
    753 	 * Get a free cache slot.
    754 	 */
    755 	scl = sc->sc_cache+sc->sc_cache_size;
    756 
    757 restart:
    758 	if (isset(sc->sc_copied, cl)) {
    759 		return;
    760 	}
    761 
    762 	for (scp = sc->sc_cache; scp < scl; scp++)
    763 		if (scp->fc_type != FSS_CACHE_FREE &&
    764 		    scp->fc_cluster == cl) {
    765 			tsleep(&scp->fc_type, PRIBIO, "cowwait2", 0);
    766 			goto restart;
    767 		}
    768 
    769 	for (scp = sc->sc_cache; scp < scl; scp++)
    770 		if (scp->fc_type == FSS_CACHE_FREE) {
    771 			scp->fc_type = FSS_CACHE_BUSY;
    772 			scp->fc_cluster = cl;
    773 			break;
    774 		}
    775 	if (scp >= scl) {
    776 		FSS_STAT_INC(sc, cow_cache_full);
    777 		tsleep(&sc->sc_cache, PRIBIO, "cowwait3", 0);
    778 		goto restart;
    779 	}
    780 
    781 	/*
    782 	 * Start the read.
    783 	 */
    784 	FSS_STAT_INC(sc, cow_copied);
    785 
    786 	dblk = cl*btodb(sc->sc_clsize);
    787 	addr = scp->fc_data;
    788 	if (cl == sc->sc_clcount-1) {
    789 		todo = sc->sc_cllast;
    790 		memset(addr+todo, 0, sc->sc_clsize-todo);
    791 	} else
    792 		todo = sc->sc_clsize;
    793 	while (todo > 0) {
    794 		len = todo;
    795 		if (len > MAXPHYS)
    796 			len = MAXPHYS;
    797 
    798 		s = splbio();
    799 		bp = pool_get(&bufpool, PR_WAITOK);
    800 		splx(s);
    801 
    802 		BUF_INIT(bp);
    803 		bp->b_flags = B_READ|B_CALL;
    804 		bp->b_bcount = len;
    805 		bp->b_bufsize = bp->b_bcount;
    806 		bp->b_error = 0;
    807 		bp->b_data = addr;
    808 		bp->b_blkno = bp->b_rawblkno = dblk;
    809 		bp->b_proc = NULL;
    810 		bp->b_dev = sc->sc_bdev;
    811 		bp->b_vp = NULLVP;
    812 		bp->b_private = scp;
    813 		bp->b_iodone = fss_cluster_iodone;
    814 
    815 		(*sc->sc_strategy)(bp);
    816 
    817 		s = splbio();
    818 		scp->fc_xfercount++;
    819 		splx(s);
    820 
    821 		dblk += btodb(len);
    822 		addr += len;
    823 		todo -= len;
    824 	}
    825 
    826 	/*
    827 	 * Wait for all read requests to complete.
    828 	 */
    829 	s = splbio();
    830 	while (scp->fc_xfercount > 0)
    831 		tsleep(&scp->fc_data, PRIBIO, "cowwait", 0);
    832 	splx(s);
    833 
    834 	scp->fc_type = FSS_CACHE_VALID;
    835 	setbit(sc->sc_copied, scp->fc_cluster);
    836 	wakeup(&sc->sc_bs_proc);
    837 }
    838 
    839 /*
    840  * Write a cluster from the cache to the backing store.
    841  */
    842 static int
    843 fss_write_cluster(struct fss_cache *scp, u_int32_t cl)
    844 {
    845 	int s, error, todo, len, nra;
    846 	daddr_t nbn;
    847 	caddr_t addr;
    848 	off_t pos;
    849 	struct buf *bp;
    850 	struct vnode *vp;
    851 	struct fss_softc *sc;
    852 
    853 	error = 0;
    854 	sc = scp->fc_softc;
    855 
    856 	pos = (off_t)cl*sc->sc_clsize;
    857 	addr = scp->fc_data;
    858 	todo = sc->sc_clsize;
    859 
    860 	while (todo > 0) {
    861 		vn_lock(sc->sc_bs_vp, LK_EXCLUSIVE|LK_RETRY);
    862 		error = VOP_BMAP(sc->sc_bs_vp, pos/sc->sc_bs_bsize,
    863 		    &vp, &nbn, &nra);
    864 		VOP_UNLOCK(sc->sc_bs_vp, 0);
    865 		if (error == 0 && nbn == (daddr_t)-1)
    866 			error = EIO;
    867 		if (error)
    868 			break;
    869 
    870 		len = (nra+1)*sc->sc_bs_bsize-pos%sc->sc_bs_bsize;
    871 		if (len > todo)
    872 			len = todo;
    873 
    874 		s = splbio();
    875 		bp = pool_get(&bufpool, PR_WAITOK);
    876 		splx(s);
    877 
    878 		BUF_INIT(bp);
    879 		bp->b_flags = B_CALL;
    880 		bp->b_bcount = len;
    881 		bp->b_bufsize = bp->b_bcount;
    882 		bp->b_error = 0;
    883 		bp->b_data = addr;
    884 		bp->b_blkno = bp->b_rawblkno = nbn+btodb(pos%sc->sc_bs_bsize);
    885 		bp->b_proc = NULL;
    886 		bp->b_vp = NULLVP;
    887 		bp->b_private = scp;
    888 		bp->b_iodone = fss_cluster_iodone;
    889 		bgetvp(vp, bp);
    890 		bp->b_vp->v_numoutput++;
    891 
    892 		VOP_STRATEGY(bp);
    893 
    894 		s = splbio();
    895 		scp->fc_xfercount++;
    896 		splx(s);
    897 
    898 		pos += len;
    899 		addr += len;
    900 		todo -= len;
    901 	}
    902 
    903 	/*
    904 	 * Wait for all write requests to complete.
    905 	 */
    906 	s = splbio();
    907 	while (scp->fc_xfercount > 0)
    908 		tsleep(&scp->fc_data, PRIBIO, "bswwait", 0);
    909 	splx(s);
    910 
    911 	return error;
    912 }
    913 
    914 /*
    915  * Read/write clusters from/to backing store.
    916  */
    917 static int
    918 fss_bs_io(struct fss_softc *sc, fss_io_type rw,
    919     u_int32_t cl, long off, int len, caddr_t data)
    920 {
    921 	int s, error, todo, count, nra;
    922 	off_t pos;
    923 	daddr_t nbn;
    924 	struct buf *bp;
    925 	struct vnode *vp;
    926 
    927 	todo = len;
    928 	pos = (off_t)cl*sc->sc_clsize+off;
    929 	error = 0;
    930 
    931 	while (todo > 0) {
    932 		vn_lock(sc->sc_bs_vp, LK_EXCLUSIVE|LK_RETRY);
    933 		error = VOP_BMAP(sc->sc_bs_vp, pos/sc->sc_bs_bsize,
    934 		    &vp, &nbn, &nra);
    935 		VOP_UNLOCK(sc->sc_bs_vp, 0);
    936 		if (error == 0 && nbn == (daddr_t)-1)
    937 			error = EIO;
    938 		if (error)
    939 			break;
    940 
    941 		count = (nra+1)*sc->sc_bs_bsize-pos%sc->sc_bs_bsize;
    942 		if (count > todo)
    943 			count = todo;
    944 
    945 		s = splbio();
    946 		bp = pool_get(&bufpool, PR_WAITOK);
    947 		splx(s);
    948 
    949 		BUF_INIT(bp);
    950 		bp->b_flags = (rw == FSS_READ ? B_READ : 0);
    951 		bp->b_bcount = count;
    952 		bp->b_bufsize = bp->b_bcount;
    953 		bp->b_error = 0;
    954 		bp->b_data = data;
    955 		bp->b_blkno = bp->b_rawblkno = nbn+btodb(pos%sc->sc_bs_bsize);
    956 		bp->b_proc = NULL;
    957 		bp->b_vp = NULLVP;
    958 		bgetvp(vp, bp);
    959 		if ((bp->b_flags & B_READ) == 0)
    960 			bp->b_vp->v_numoutput++;
    961 		VOP_STRATEGY(bp);
    962 
    963 		error = biowait(bp);
    964 
    965 		if (bp->b_vp != NULL)
    966 			brelvp(bp);
    967 
    968 		s = splbio();
    969 		pool_put(&bufpool, bp);
    970 		splx(s);
    971 
    972 		if (error)
    973 			break;
    974 
    975 		todo -= count;
    976 		data += count;
    977 		pos += count;
    978 	}
    979 
    980 	return error;
    981 }
    982 
    983 /*
    984  * Get a pointer to the indirect slot for this cluster.
    985  */
    986 static u_int32_t *
    987 fss_bs_indir(struct fss_softc *sc, u_int32_t cl)
    988 {
    989 	u_int32_t icl;
    990 	int ioff;
    991 
    992 	icl = cl/(sc->sc_clsize/sizeof(u_int32_t));
    993 	ioff = cl%(sc->sc_clsize/sizeof(u_int32_t));
    994 
    995 	if (sc->sc_indir_cur == icl)
    996 		return &sc->sc_indir_data[ioff];
    997 
    998 	if (sc->sc_indir_dirty) {
    999 		FSS_STAT_INC(sc, indir_write);
   1000 		if (fss_bs_io(sc, FSS_WRITE, sc->sc_indir_cur, 0,
   1001 		    sc->sc_clsize, (caddr_t)sc->sc_indir_data) != 0)
   1002 			return NULL;
   1003 		setbit(sc->sc_indir_valid, sc->sc_indir_cur);
   1004 	}
   1005 
   1006 	sc->sc_indir_dirty = 0;
   1007 	sc->sc_indir_cur = icl;
   1008 
   1009 	if (isset(sc->sc_indir_valid, sc->sc_indir_cur)) {
   1010 		FSS_STAT_INC(sc, indir_read);
   1011 		if (fss_bs_io(sc, FSS_READ, sc->sc_indir_cur, 0,
   1012 		    sc->sc_clsize, (caddr_t)sc->sc_indir_data) != 0)
   1013 			return NULL;
   1014 	} else
   1015 		memset(sc->sc_indir_data, 0, sc->sc_clsize);
   1016 
   1017 	return &sc->sc_indir_data[ioff];
   1018 }
   1019 
   1020 /*
   1021  * The kernel thread (one for every active snapshot).
   1022  *
   1023  * After wakeup it cleans the cache and runs the I/O requests.
   1024  */
   1025 static void
   1026 fss_bs_thread(void *arg)
   1027 {
   1028 	int error, len, nfreed, nio, s;
   1029 	long off;
   1030 	caddr_t addr;
   1031 	u_int32_t c, cl, ch, *indirp;
   1032 	struct buf *bp, *nbp;
   1033 	struct fss_softc *sc;
   1034 	struct fss_cache *scp, *scl;
   1035 
   1036 	sc = arg;
   1037 
   1038 	scl = sc->sc_cache+sc->sc_cache_size;
   1039 
   1040 	s = splbio();
   1041 	nbp = pool_get(&bufpool, PR_WAITOK);
   1042 	splx(s);
   1043 
   1044 	nfreed = nio = 1;		/* Dont sleep the first time */
   1045 
   1046 	for (;;) {
   1047 		if (nfreed == 0 && nio == 0)
   1048 			tsleep(&sc->sc_bs_proc, PVM, "fssbs", 0);
   1049 		if ((sc->sc_flags & FSS_BS_THREAD) == 0) {
   1050 			s = splbio();
   1051 			pool_put(&bufpool, nbp);
   1052 			splx(s);
   1053 #ifdef FSS_STATISTICS
   1054 			printf("fss%d: cow called %" PRId64 " times,"
   1055 			    " copied %" PRId64 " clusters,"
   1056 			    " cache full %" PRId64 " times\n",
   1057 			    sc->sc_unit,
   1058 			    FSS_STAT_VAL(sc, cow_calls),
   1059 			    FSS_STAT_VAL(sc, cow_copied),
   1060 			    FSS_STAT_VAL(sc, cow_cache_full));
   1061 			printf("fss%d: %" PRId64 " indir reads,"
   1062 			    " %" PRId64 " indir writes\n",
   1063 			    sc->sc_unit,
   1064 			    FSS_STAT_VAL(sc, indir_read),
   1065 			    FSS_STAT_VAL(sc, indir_write));
   1066 #endif /* FSS_STATISTICS */
   1067 			sc->sc_bs_proc = NULL;
   1068 			kthread_exit(0);
   1069 		}
   1070 
   1071 		/*
   1072 		 * Clean the cache
   1073 		 */
   1074 		nfreed = 0;
   1075 		for (scp = sc->sc_cache; scp < scl; scp++) {
   1076 			if (scp->fc_type != FSS_CACHE_VALID)
   1077 				continue;
   1078 			indirp = fss_bs_indir(sc, scp->fc_cluster);
   1079 			if (indirp != NULL) {
   1080 				error = fss_write_cluster(scp, sc->sc_clnext);
   1081 			} else
   1082 				error = EIO;
   1083 
   1084 			if (error == 0) {
   1085 				*indirp = sc->sc_clnext++;
   1086 				sc->sc_indir_dirty = 1;
   1087 			} else
   1088 				fss_error(sc, "write bs error %d", error);
   1089 
   1090 			scp->fc_type = FSS_CACHE_FREE;
   1091 			nfreed++;
   1092 			wakeup(&scp->fc_type);
   1093 		}
   1094 		if (nfreed)
   1095 			wakeup(&sc->sc_cache);
   1096 
   1097 		/*
   1098 		 * Process I/O requests
   1099 		 */
   1100 		nio = 0;
   1101 
   1102 		if ((bp = BUFQ_GET(&sc->sc_bufq)) == NULL)
   1103 			continue;
   1104 
   1105 		nio++;
   1106 
   1107 		if (!fss_valid(sc)) {
   1108 			bp->b_error = ENXIO;
   1109 			bp->b_flags |= B_ERROR;
   1110 			bp->b_resid = bp->b_bcount;
   1111 			biodone(bp);
   1112 			continue;
   1113 		}
   1114 
   1115 		/*
   1116 		 * First read from the snapshotted block device.
   1117 		 * XXX Split to only read those parts that have not
   1118 		 * been saved to backing store?
   1119 		 */
   1120 		BUF_INIT(nbp);
   1121 		nbp->b_flags = B_READ;
   1122 		nbp->b_bcount = bp->b_bcount;
   1123 		nbp->b_bufsize = bp->b_bcount;
   1124 		nbp->b_error = 0;
   1125 		nbp->b_data = bp->b_data;
   1126 		nbp->b_blkno = nbp->b_rawblkno = bp->b_blkno;
   1127 		nbp->b_proc = bp->b_proc;
   1128 		nbp->b_dev = sc->sc_bdev;
   1129 		nbp->b_vp = NULLVP;
   1130 
   1131 		(*sc->sc_strategy)(nbp);
   1132 
   1133 		if (biowait(nbp) != 0) {
   1134 			bp->b_resid = bp->b_bcount;
   1135 			bp->b_error = nbp->b_error;
   1136 			bp->b_flags |= B_ERROR;
   1137 			biodone(bp);
   1138 			continue;
   1139 		}
   1140 
   1141 		block_to_cluster(sc, bp->b_blkno, 0, &cl, &off);
   1142 		block_to_cluster(sc, bp->b_blkno, bp->b_bcount-1, &ch, NULL);
   1143 		bp->b_resid = bp->b_bcount;
   1144 		addr = bp->b_data;
   1145 
   1146 		/*
   1147 		 * Replace those parts that have been saved to backing store.
   1148 		 */
   1149 		for (c = cl; c <= ch;
   1150 		    c++, off = 0, bp->b_resid -= len, addr += len) {
   1151 			len = sc->sc_clsize-off;
   1152 			if (len > bp->b_resid)
   1153 				len = bp->b_resid;
   1154 
   1155 			if (isclr(sc->sc_copied, c))
   1156 				continue;
   1157 
   1158 			indirp = fss_bs_indir(sc, c);
   1159 			if (indirp == NULL || *indirp == 0) {
   1160 				/*
   1161 				 * Not on backing store. Either in cache
   1162 				 * or hole in the snapshotted block device.
   1163 				 */
   1164 				for (scp = sc->sc_cache; scp < scl; scp++)
   1165 					if (scp->fc_type == FSS_CACHE_VALID &&
   1166 					    scp->fc_cluster == c)
   1167 						break;
   1168 				if (scp < scl)
   1169 					memcpy(addr, scp->fc_data+off, len);
   1170 				else
   1171 					memset(addr, 0, len);
   1172 				continue;
   1173 			}
   1174 			/*
   1175 			 * Read from backing store.
   1176 			 */
   1177 			if ((error = fss_bs_io(sc, FSS_READ, *indirp,
   1178 			    off, len, addr)) != 0) {
   1179 				bp->b_resid = bp->b_bcount;
   1180 				bp->b_error = error;
   1181 				bp->b_flags |= B_ERROR;
   1182 				break;
   1183 			}
   1184 		}
   1185 
   1186 		biodone(bp);
   1187 	}
   1188 }
   1189