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