fss.c revision 1.2 1 /* $NetBSD: fss.c,v 1.2 2003/12/13 18:59:29 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.2 2003/12/13 18:59:29 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)) != 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