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