fss.c revision 1.46 1 /* $NetBSD: fss.c,v 1.46 2008/06/17 14:53:10 reinoud 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.46 2008/06/17 14:53:10 reinoud 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, 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 vrele(nd.ni_vp);
561 sc->sc_flags |= FSS_PERSISTENT;
562
563 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fss->fss_bstore);
564 if ((error = vn_open(&nd, FREAD, 0)) != 0)
565 return error;
566 sc->sc_bs_vp = nd.ni_vp;
567
568 fsbsize = sc->sc_bs_vp->v_mount->mnt_stat.f_iosize;
569 bits = sizeof(sc->sc_bs_bshift)*NBBY;
570 for (sc->sc_bs_bshift = 1; sc->sc_bs_bshift < bits;
571 sc->sc_bs_bshift++)
572 if (FSS_FSBSIZE(sc) == fsbsize)
573 break;
574 if (sc->sc_bs_bshift >= bits) {
575 VOP_UNLOCK(sc->sc_bs_vp, 0);
576 return EINVAL;
577 }
578
579 sc->sc_bs_bmask = FSS_FSBSIZE(sc)-1;
580 sc->sc_clshift = 0;
581
582 error = VFS_SNAPSHOT(sc->sc_mount, sc->sc_bs_vp, &ts);
583 TIMESPEC_TO_TIMEVAL(&sc->sc_time, &ts);
584
585 VOP_UNLOCK(sc->sc_bs_vp, 0);
586
587 return error;
588 }
589 vrele(nd.ni_vp);
590
591 /*
592 * Get the block device it is mounted on.
593 */
594
595 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE,
596 sc->sc_mount->mnt_stat.f_mntfromname);
597 if ((error = namei(&nd)) != 0)
598 return error;
599
600 if (nd.ni_vp->v_type != VBLK) {
601 vrele(nd.ni_vp);
602 return EINVAL;
603 }
604
605 error = VOP_IOCTL(nd.ni_vp, DIOCGPART, &dpart, FREAD, l->l_cred);
606 if (error) {
607 vrele(nd.ni_vp);
608 return error;
609 }
610
611 sc->sc_bdev = nd.ni_vp->v_rdev;
612 *bsize = (off_t)dpart.disklab->d_secsize*dpart.part->p_size;
613 vrele(nd.ni_vp);
614
615 /*
616 * Get the backing store
617 */
618
619 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fss->fss_bstore);
620 if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0)
621 return error;
622 VOP_UNLOCK(nd.ni_vp, 0);
623
624 sc->sc_bs_vp = nd.ni_vp;
625
626 if (nd.ni_vp->v_type != VREG && nd.ni_vp->v_type != VCHR)
627 return EINVAL;
628
629 if (sc->sc_bs_vp->v_type == VREG) {
630 error = VOP_GETATTR(sc->sc_bs_vp, &va, l->l_cred);
631 if (error != 0)
632 return error;
633 sc->sc_bs_size = va.va_size;
634 fsbsize = sc->sc_bs_vp->v_mount->mnt_stat.f_iosize;
635 if (fsbsize & (fsbsize-1)) /* No power of two */
636 return EINVAL;
637 for (sc->sc_bs_bshift = 1; sc->sc_bs_bshift < 32;
638 sc->sc_bs_bshift++)
639 if (FSS_FSBSIZE(sc) == fsbsize)
640 break;
641 if (sc->sc_bs_bshift >= 32)
642 return EINVAL;
643 sc->sc_bs_bmask = FSS_FSBSIZE(sc)-1;
644 } else {
645 sc->sc_bs_bshift = DEV_BSHIFT;
646 sc->sc_bs_bmask = FSS_FSBSIZE(sc)-1;
647 }
648
649 /*
650 * As all IO to from/to the backing store goes through
651 * VOP_STRATEGY() clean the buffer cache to prevent
652 * cache incoherencies.
653 */
654 if ((error = vinvalbuf(sc->sc_bs_vp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
655 return error;
656
657 return 0;
658 }
659
660 /*
661 * Create a snapshot.
662 */
663 static int
664 fss_create_snapshot(struct fss_softc *sc, struct fss_set *fss, struct lwp *l)
665 {
666 int len, error;
667 u_int32_t csize;
668 off_t bsize;
669
670 bsize = 0; /* XXX gcc */
671
672 /*
673 * Open needed files.
674 */
675 if ((error = fss_create_files(sc, fss, &bsize, l)) != 0)
676 goto bad;
677
678 if (sc->sc_flags & FSS_PERSISTENT) {
679 fss_softc_alloc(sc);
680 sc->sc_flags |= FSS_ACTIVE;
681 return 0;
682 }
683
684 /*
685 * Set cluster size. Must be a power of two and
686 * a multiple of backing store block size.
687 */
688 if (fss->fss_csize <= 0)
689 csize = MAXPHYS;
690 else
691 csize = fss->fss_csize;
692 if (bsize/csize > FSS_CLUSTER_MAX)
693 csize = bsize/FSS_CLUSTER_MAX+1;
694
695 for (sc->sc_clshift = sc->sc_bs_bshift; sc->sc_clshift < 32;
696 sc->sc_clshift++)
697 if (FSS_CLSIZE(sc) >= csize)
698 break;
699 if (sc->sc_clshift >= 32) {
700 error = EINVAL;
701 goto bad;
702 }
703 sc->sc_clmask = FSS_CLSIZE(sc)-1;
704
705 /*
706 * Set number of cache slots.
707 */
708 if (FSS_CLSIZE(sc) <= 8192)
709 sc->sc_cache_size = 32;
710 else if (FSS_CLSIZE(sc) <= 65536)
711 sc->sc_cache_size = 8;
712 else
713 sc->sc_cache_size = 4;
714
715 /*
716 * Set number of clusters and size of last cluster.
717 */
718 sc->sc_clcount = FSS_BTOCL(sc, bsize-1)+1;
719 sc->sc_clresid = FSS_CLOFF(sc, bsize-1)+1;
720
721 /*
722 * Set size of indirect table.
723 */
724 len = sc->sc_clcount*sizeof(u_int32_t);
725 sc->sc_indir_size = FSS_BTOCL(sc, len)+1;
726 sc->sc_clnext = sc->sc_indir_size;
727 sc->sc_indir_cur = 0;
728
729 if ((error = fss_softc_alloc(sc)) != 0)
730 goto bad;
731
732 /*
733 * Activate the snapshot.
734 */
735
736 if ((error = vfs_suspend(sc->sc_mount, 0)) != 0)
737 goto bad;
738
739 microtime(&sc->sc_time);
740
741 if (error == 0)
742 error = fscow_establish(sc->sc_mount,
743 fss_copy_on_write, sc);
744 if (error == 0)
745 sc->sc_flags |= FSS_ACTIVE;
746
747 vfs_resume(sc->sc_mount);
748
749 if (error != 0)
750 goto bad;
751
752 #ifdef DEBUG
753 printf("fss%d: %s snapshot active\n", sc->sc_unit, sc->sc_mntname);
754 printf("fss%d: %u clusters of %u, %u cache slots, %u indir clusters\n",
755 sc->sc_unit, sc->sc_clcount, FSS_CLSIZE(sc),
756 sc->sc_cache_size, sc->sc_indir_size);
757 #endif
758
759 return 0;
760
761 bad:
762 fss_softc_free(sc);
763 if (sc->sc_bs_vp != NULL) {
764 if (sc->sc_flags & FSS_PERSISTENT)
765 vn_close(sc->sc_bs_vp, FREAD, l->l_cred);
766 else
767 vn_close(sc->sc_bs_vp, FREAD|FWRITE, l->l_cred);
768 }
769 sc->sc_bs_vp = NULL;
770
771 return error;
772 }
773
774 /*
775 * Delete a snapshot.
776 */
777 static int
778 fss_delete_snapshot(struct fss_softc *sc, struct lwp *l)
779 {
780 int s;
781
782 if ((sc->sc_flags & FSS_PERSISTENT) == 0)
783 fscow_disestablish(sc->sc_mount, fss_copy_on_write, sc);
784
785 FSS_LOCK(sc, s);
786 sc->sc_flags &= ~(FSS_ACTIVE|FSS_ERROR);
787 sc->sc_mount = NULL;
788 sc->sc_bdev = NODEV;
789 FSS_UNLOCK(sc, s);
790
791 fss_softc_free(sc);
792 if (sc->sc_flags & FSS_PERSISTENT)
793 vn_close(sc->sc_bs_vp, FREAD, l->l_cred);
794 else
795 vn_close(sc->sc_bs_vp, FREAD|FWRITE, l->l_cred);
796 sc->sc_bs_vp = NULL;
797 sc->sc_flags &= ~FSS_PERSISTENT;
798
799 FSS_STAT_CLEAR(sc);
800
801 return 0;
802 }
803
804 /*
805 * A read from the snapshotted block device has completed.
806 */
807 static void
808 fss_cluster_iodone(struct buf *bp)
809 {
810 int s;
811 struct fss_cache *scp = bp->b_private;
812
813 KASSERT(bp->b_vp == NULL);
814
815 FSS_LOCK(scp->fc_softc, s);
816
817 if (bp->b_error != 0)
818 fss_error(scp->fc_softc, "fs read error %d", bp->b_error);
819
820 if (--scp->fc_xfercount == 0)
821 wakeup(&scp->fc_data);
822
823 FSS_UNLOCK(scp->fc_softc, s);
824
825 putiobuf(bp);
826 }
827
828 /*
829 * Read a cluster from the snapshotted block device to the cache.
830 */
831 static void
832 fss_read_cluster(struct fss_softc *sc, u_int32_t cl)
833 {
834 int s, todo, len;
835 char *addr;
836 daddr_t dblk;
837 struct buf *bp;
838 struct fss_cache *scp, *scl;
839
840 /*
841 * Get a free cache slot.
842 */
843 scl = sc->sc_cache+sc->sc_cache_size;
844
845 FSS_LOCK(sc, s);
846
847 restart:
848 if (isset(sc->sc_copied, cl) || !FSS_ISVALID(sc)) {
849 FSS_UNLOCK(sc, s);
850 return;
851 }
852
853 for (scp = sc->sc_cache; scp < scl; scp++)
854 if (scp->fc_type != FSS_CACHE_FREE &&
855 scp->fc_cluster == cl) {
856 ltsleep(&scp->fc_type, PRIBIO, "cowwait2", 0,
857 &sc->sc_slock);
858 goto restart;
859 }
860
861 for (scp = sc->sc_cache; scp < scl; scp++)
862 if (scp->fc_type == FSS_CACHE_FREE) {
863 scp->fc_type = FSS_CACHE_BUSY;
864 scp->fc_cluster = cl;
865 break;
866 }
867 if (scp >= scl) {
868 FSS_STAT_INC(sc, cow_cache_full);
869 ltsleep(&sc->sc_cache, PRIBIO, "cowwait3", 0, &sc->sc_slock);
870 goto restart;
871 }
872
873 FSS_UNLOCK(sc, s);
874
875 /*
876 * Start the read.
877 */
878 FSS_STAT_INC(sc, cow_copied);
879
880 dblk = btodb(FSS_CLTOB(sc, cl));
881 addr = scp->fc_data;
882 if (cl == sc->sc_clcount-1) {
883 todo = sc->sc_clresid;
884 memset((char *)addr + todo, 0, FSS_CLSIZE(sc) - todo);
885 } else
886 todo = FSS_CLSIZE(sc);
887 while (todo > 0) {
888 len = todo;
889 if (len > MAXPHYS)
890 len = MAXPHYS;
891
892 bp = getiobuf(NULL, true);
893 bp->b_flags = B_READ;
894 bp->b_bcount = len;
895 bp->b_bufsize = bp->b_bcount;
896 bp->b_error = 0;
897 bp->b_data = addr;
898 bp->b_blkno = dblk;
899 bp->b_proc = NULL;
900 bp->b_dev = sc->sc_bdev;
901 bp->b_private = scp;
902 bp->b_iodone = fss_cluster_iodone;
903
904 bdev_strategy(bp);
905
906 FSS_LOCK(sc, s);
907 scp->fc_xfercount++;
908 FSS_UNLOCK(sc, s);
909
910 dblk += btodb(len);
911 addr += len;
912 todo -= len;
913 }
914
915 /*
916 * Wait for all read requests to complete.
917 */
918 FSS_LOCK(sc, s);
919 while (scp->fc_xfercount > 0)
920 ltsleep(&scp->fc_data, PRIBIO, "cowwait", 0, &sc->sc_slock);
921
922 scp->fc_type = FSS_CACHE_VALID;
923 setbit(sc->sc_copied, scp->fc_cluster);
924 FSS_UNLOCK(sc, s);
925
926 wakeup(&sc->sc_bs_lwp);
927 }
928
929 /*
930 * Read/write clusters from/to backing store.
931 * For persistent snapshots must be called with cl == 0. off is the
932 * offset into the snapshot.
933 */
934 static int
935 fss_bs_io(struct fss_softc *sc, fss_io_type rw,
936 u_int32_t cl, off_t off, int len, void *data)
937 {
938 int error;
939
940 off += FSS_CLTOB(sc, cl);
941
942 vn_lock(sc->sc_bs_vp, LK_EXCLUSIVE|LK_RETRY);
943
944 error = vn_rdwr((rw == FSS_READ ? UIO_READ : UIO_WRITE), sc->sc_bs_vp,
945 data, len, off, UIO_SYSSPACE, IO_UNIT|IO_NODELOCKED,
946 sc->sc_bs_lwp->l_cred, NULL, NULL);
947 if (error == 0) {
948 mutex_enter(&sc->sc_bs_vp->v_interlock);
949 error = VOP_PUTPAGES(sc->sc_bs_vp, trunc_page(off),
950 round_page(off+len), PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);
951 }
952
953 VOP_UNLOCK(sc->sc_bs_vp, 0);
954
955 return error;
956 }
957
958 /*
959 * Get a pointer to the indirect slot for this cluster.
960 */
961 static u_int32_t *
962 fss_bs_indir(struct fss_softc *sc, u_int32_t cl)
963 {
964 u_int32_t icl;
965 int ioff;
966
967 icl = cl/(FSS_CLSIZE(sc)/sizeof(u_int32_t));
968 ioff = cl%(FSS_CLSIZE(sc)/sizeof(u_int32_t));
969
970 if (sc->sc_indir_cur == icl)
971 return &sc->sc_indir_data[ioff];
972
973 if (sc->sc_indir_dirty) {
974 FSS_STAT_INC(sc, indir_write);
975 if (fss_bs_io(sc, FSS_WRITE, sc->sc_indir_cur, 0,
976 FSS_CLSIZE(sc), (void *)sc->sc_indir_data) != 0)
977 return NULL;
978 setbit(sc->sc_indir_valid, sc->sc_indir_cur);
979 }
980
981 sc->sc_indir_dirty = 0;
982 sc->sc_indir_cur = icl;
983
984 if (isset(sc->sc_indir_valid, sc->sc_indir_cur)) {
985 FSS_STAT_INC(sc, indir_read);
986 if (fss_bs_io(sc, FSS_READ, sc->sc_indir_cur, 0,
987 FSS_CLSIZE(sc), (void *)sc->sc_indir_data) != 0)
988 return NULL;
989 } else
990 memset(sc->sc_indir_data, 0, FSS_CLSIZE(sc));
991
992 return &sc->sc_indir_data[ioff];
993 }
994
995 /*
996 * The kernel thread (one for every active snapshot).
997 *
998 * After wakeup it cleans the cache and runs the I/O requests.
999 */
1000 static void
1001 fss_bs_thread(void *arg)
1002 {
1003 int error, len, nfreed, nio, s;
1004 long off;
1005 char *addr;
1006 u_int32_t c, cl, ch, *indirp;
1007 struct buf *bp, *nbp;
1008 struct fss_softc *sc;
1009 struct fss_cache *scp, *scl;
1010
1011 sc = arg;
1012
1013 scl = sc->sc_cache+sc->sc_cache_size;
1014
1015 nbp = getiobuf(NULL, true);
1016
1017 nfreed = nio = 1; /* Dont sleep the first time */
1018
1019 FSS_LOCK(sc, s);
1020
1021 for (;;) {
1022 if (nfreed == 0 && nio == 0)
1023 ltsleep(&sc->sc_bs_lwp, PVM-1, "fssbs", 0,
1024 &sc->sc_slock);
1025
1026 if ((sc->sc_flags & FSS_BS_THREAD) == 0) {
1027 sc->sc_bs_lwp = NULL;
1028 wakeup(&sc->sc_bs_lwp);
1029
1030 FSS_UNLOCK(sc, s);
1031
1032 putiobuf(nbp);
1033 #ifdef FSS_STATISTICS
1034 if ((sc->sc_flags & FSS_PERSISTENT) == 0) {
1035 printf("fss%d: cow called %" PRId64 " times,"
1036 " copied %" PRId64 " clusters,"
1037 " cache full %" PRId64 " times\n",
1038 sc->sc_unit,
1039 FSS_STAT_VAL(sc, cow_calls),
1040 FSS_STAT_VAL(sc, cow_copied),
1041 FSS_STAT_VAL(sc, cow_cache_full));
1042 printf("fss%d: %" PRId64 " indir reads,"
1043 " %" PRId64 " indir writes\n",
1044 sc->sc_unit,
1045 FSS_STAT_VAL(sc, indir_read),
1046 FSS_STAT_VAL(sc, indir_write));
1047 }
1048 #endif /* FSS_STATISTICS */
1049 kthread_exit(0);
1050 }
1051
1052 /*
1053 * Process I/O requests (persistent)
1054 */
1055
1056 if (sc->sc_flags & FSS_PERSISTENT) {
1057 nfreed = nio = 0;
1058
1059 if ((bp = BUFQ_GET(sc->sc_bufq)) == NULL)
1060 continue;
1061
1062 nio++;
1063
1064 if (FSS_ISVALID(sc)) {
1065 FSS_UNLOCK(sc, s);
1066
1067 error = fss_bs_io(sc, FSS_READ, 0,
1068 dbtob(bp->b_blkno), bp->b_bcount,
1069 bp->b_data);
1070
1071 FSS_LOCK(sc, s);
1072 } else
1073 error = ENXIO;
1074
1075 if (error) {
1076 bp->b_error = error;
1077 bp->b_resid = bp->b_bcount;
1078 } else
1079 bp->b_resid = 0;
1080
1081 biodone(bp);
1082
1083 continue;
1084 }
1085
1086 /*
1087 * Clean the cache
1088 */
1089 nfreed = 0;
1090 for (scp = sc->sc_cache; scp < scl; scp++) {
1091 if (scp->fc_type != FSS_CACHE_VALID)
1092 continue;
1093
1094 FSS_UNLOCK(sc, s);
1095
1096 indirp = fss_bs_indir(sc, scp->fc_cluster);
1097 if (indirp != NULL) {
1098 error = fss_bs_io(sc, FSS_WRITE, sc->sc_clnext,
1099 0, FSS_CLSIZE(sc), scp->fc_data);
1100 } else
1101 error = EIO;
1102
1103 FSS_LOCK(sc, s);
1104
1105 if (error == 0) {
1106 *indirp = sc->sc_clnext++;
1107 sc->sc_indir_dirty = 1;
1108 } else
1109 fss_error(sc, "write bs error %d", error);
1110
1111 scp->fc_type = FSS_CACHE_FREE;
1112 nfreed++;
1113 wakeup(&scp->fc_type);
1114 }
1115
1116 if (nfreed)
1117 wakeup(&sc->sc_cache);
1118
1119 /*
1120 * Process I/O requests
1121 */
1122 nio = 0;
1123
1124 if ((bp = BUFQ_GET(sc->sc_bufq)) == NULL)
1125 continue;
1126
1127 nio++;
1128
1129 if (!FSS_ISVALID(sc)) {
1130 bp->b_error = ENXIO;
1131 bp->b_resid = bp->b_bcount;
1132 biodone(bp);
1133 continue;
1134 }
1135
1136 /*
1137 * First read from the snapshotted block device.
1138 * XXX Split to only read those parts that have not
1139 * been saved to backing store?
1140 */
1141
1142 FSS_UNLOCK(sc, s);
1143
1144 buf_init(nbp);
1145 nbp->b_flags = B_READ;
1146 nbp->b_bcount = bp->b_bcount;
1147 nbp->b_bufsize = bp->b_bcount;
1148 nbp->b_error = 0;
1149 nbp->b_data = bp->b_data;
1150 nbp->b_blkno = bp->b_blkno;
1151 nbp->b_proc = bp->b_proc;
1152 nbp->b_dev = sc->sc_bdev;
1153 SET(nbp->b_cflags, BC_BUSY); /* mark buffer busy */
1154
1155 bdev_strategy(nbp);
1156
1157 if (biowait(nbp) != 0) {
1158 bp->b_resid = bp->b_bcount;
1159 bp->b_error = nbp->b_error;
1160 biodone(bp);
1161 FSS_LOCK(sc, s);
1162 continue;
1163 }
1164
1165 cl = FSS_BTOCL(sc, dbtob(bp->b_blkno));
1166 off = FSS_CLOFF(sc, dbtob(bp->b_blkno));
1167 ch = FSS_BTOCL(sc, dbtob(bp->b_blkno)+bp->b_bcount-1);
1168 bp->b_resid = bp->b_bcount;
1169 addr = bp->b_data;
1170
1171 FSS_LOCK(sc, s);
1172
1173 /*
1174 * Replace those parts that have been saved to backing store.
1175 */
1176
1177 for (c = cl; c <= ch;
1178 c++, off = 0, bp->b_resid -= len, addr += len) {
1179 len = FSS_CLSIZE(sc)-off;
1180 if (len > bp->b_resid)
1181 len = bp->b_resid;
1182
1183 if (isclr(sc->sc_copied, c))
1184 continue;
1185
1186 FSS_UNLOCK(sc, s);
1187
1188 indirp = fss_bs_indir(sc, c);
1189
1190 FSS_LOCK(sc, s);
1191
1192 if (indirp == NULL || *indirp == 0) {
1193 /*
1194 * Not on backing store. Either in cache
1195 * or hole in the snapshotted block device.
1196 */
1197 for (scp = sc->sc_cache; scp < scl; scp++)
1198 if (scp->fc_type == FSS_CACHE_VALID &&
1199 scp->fc_cluster == c)
1200 break;
1201 if (scp < scl)
1202 memcpy(addr, (char *)scp->fc_data+off, len);
1203 else
1204 memset(addr, 0, len);
1205 continue;
1206 }
1207 /*
1208 * Read from backing store.
1209 */
1210
1211 FSS_UNLOCK(sc, s);
1212
1213 if ((error = fss_bs_io(sc, FSS_READ, *indirp,
1214 off, len, addr)) != 0) {
1215 bp->b_resid = bp->b_bcount;
1216 bp->b_error = error;
1217 FSS_LOCK(sc, s);
1218 break;
1219 }
1220
1221 FSS_LOCK(sc, s);
1222
1223 }
1224
1225 biodone(bp);
1226 }
1227 }
1228