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