HAMMER 23/many: Recovery, B-Tree, spike, I/O work.
[dragonfly.git] / sys / vfs / hammer / hammer_io.c
1 /*
2  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.17 2008/01/24 02:14:45 dillon Exp $
35  */
36 /*
37  * IO Primitives and buffer cache management
38  *
39  * All major data-tracking structures in HAMMER contain a struct hammer_io
40  * which is used to manage their backing store.  We use filesystem buffers
41  * for backing store and we leave them passively associated with their
42  * HAMMER structures.
43  *
44  * If the kernel tries to release a passively associated buf which we cannot
45  * yet let go we set B_LOCKED in the buffer and then actively released it
46  * later when we can.
47  */
48
49 #include "hammer.h"
50 #include <sys/fcntl.h>
51 #include <sys/nlookup.h>
52 #include <sys/buf.h>
53 #include <sys/buf2.h>
54
55 static void hammer_io_deallocate(struct buf *bp);
56 static int hammer_io_checkwrite(struct buf *bp);
57
58 /*
59  * Initialize an already-zero'd hammer_io structure
60  */
61 void
62 hammer_io_init(hammer_io_t io, enum hammer_io_type type)
63 {
64         io->type = type;
65         TAILQ_INIT(&io->deplist);
66 }
67
68 /*
69  * Helper routine to disassociate a buffer cache buffer from an I/O
70  * structure.  Called with the io structure exclusively locked.
71  *
72  * The io may have 0 or 1 references depending on who called us.  The
73  * caller is responsible for dealing with the refs.
74  *
75  * This call can only be made when no action is required on the buffer.
76  * HAMMER must own the buffer (released == 0) since we mess around with it.
77  */
78 static void
79 hammer_io_disassociate(hammer_io_structure_t iou, int elseit)
80 {
81         struct buf *bp = iou->io.bp;
82
83         KKASSERT(TAILQ_EMPTY(&iou->io.deplist) && iou->io.modified == 0);
84         buf_dep_init(bp);
85         iou->io.bp = NULL;
86         bp->b_flags &= ~B_LOCKED;
87         if (elseit) {
88                 KKASSERT(iou->io.released == 0);
89                 iou->io.released = 1;
90                 bqrelse(bp);
91         } else {
92                 KKASSERT(iou->io.released);
93         }
94
95         switch(iou->io.type) {
96         case HAMMER_STRUCTURE_VOLUME:
97                 iou->volume.ondisk = NULL;
98                 iou->volume.alist.meta = NULL;
99                 break;
100         case HAMMER_STRUCTURE_SUPERCL:
101                 iou->supercl.ondisk = NULL;
102                 iou->supercl.alist.meta = NULL;
103                 break;
104         case HAMMER_STRUCTURE_CLUSTER:
105                 iou->cluster.ondisk = NULL;
106                 iou->cluster.alist_master.meta = NULL;
107                 iou->cluster.alist_btree.meta = NULL;
108                 iou->cluster.alist_record.meta = NULL;
109                 iou->cluster.alist_mdata.meta = NULL;
110                 break;
111         case HAMMER_STRUCTURE_BUFFER:
112                 iou->buffer.ondisk = NULL;
113                 iou->buffer.alist.meta = NULL;
114                 break;
115         }
116 }
117
118 /*
119  * Wait for any physical IO to complete
120  */
121 static void
122 hammer_io_wait(hammer_io_t io)
123 {
124         if (io->running) {
125                 crit_enter();
126                 tsleep_interlock(io);
127                 io->waiting = 1;
128                 for (;;) {
129                         tsleep(io, 0, "hmrflw", 0);
130                         if (io->running == 0)
131                                 break;
132                         tsleep_interlock(io);
133                         io->waiting = 1;
134                         if (io->running == 0)
135                                 break;
136                 }
137                 crit_exit();
138         }
139 }
140
141 void
142 hammer_io_waitdep(hammer_io_t io)
143 {
144         while (TAILQ_FIRST(&io->deplist)) {
145                 kprintf("waitdep %p\n", io);
146                 tsleep(io, 0, "hmrdep", hz);
147         }
148 }
149
150 /*
151  * Load bp for a HAMMER structure.  The io is exclusively locked by the
152  * caller.
153  */
154 int
155 hammer_io_read(struct vnode *devvp, struct hammer_io *io)
156 {
157         struct buf *bp;
158         int error;
159
160         if ((bp = io->bp) == NULL) {
161                 error = bread(devvp, io->offset, HAMMER_BUFSIZE, &io->bp);
162                 if (error == 0) {
163                         bp = io->bp;
164                         bp->b_ops = &hammer_bioops;
165                         LIST_INSERT_HEAD(&bp->b_dep, &io->worklist, node);
166                         BUF_KERNPROC(bp);
167                 }
168                 io->modified = 0;       /* no new modifications yet */
169                 io->released = 0;       /* we hold an active lock on bp */
170                 io->running = 0;
171                 io->waiting = 0;
172         } else {
173                 error = 0;
174         }
175         return(error);
176 }
177
178 /*
179  * Similar to hammer_io_read() but returns a zero'd out buffer instead.
180  * vfs_bio_clrbuf() is kinda nasty, enforce serialization against background
181  * I/O so we can call it.
182  *
183  * The caller is responsible for calling hammer_modify_*() on the appropriate
184  * HAMMER structure.
185  */
186 int
187 hammer_io_new(struct vnode *devvp, struct hammer_io *io)
188 {
189         struct buf *bp;
190
191         if ((bp = io->bp) == NULL) {
192                 io->bp = getblk(devvp, io->offset, HAMMER_BUFSIZE, 0, 0);
193                 bp = io->bp;
194                 bp->b_ops = &hammer_bioops;
195                 LIST_INSERT_HEAD(&bp->b_dep, &io->worklist, node);
196                 io->modified = 0;
197                 io->released = 0;
198                 io->running = 0;
199                 io->waiting = 0;
200                 BUF_KERNPROC(bp);
201         } else {
202                 if (io->released) {
203                         regetblk(bp);
204                         BUF_KERNPROC(bp);
205                         io->released = 0;
206                 }
207         }
208         vfs_bio_clrbuf(bp);
209         return(0);
210 }
211
212 /*
213  * This routine is called on the last reference to a hammer structure.
214  * The io is usually locked exclusively (but may not be during unmount).
215  *
216  * If flush is 1, or B_LOCKED was set indicating that the kernel
217  * wanted to recycle the buffer, and there are no dependancies, this
218  * function will issue an asynchronous write.
219  *
220  * If flush is 2 this function waits until all I/O has completed and
221  * disassociates the bp from the IO before returning, unless there
222  * are still other references.
223  */
224 void
225 hammer_io_release(struct hammer_io *io, int flush)
226 {
227         struct buf *bp;
228
229         if ((bp = io->bp) == NULL)
230                 return;
231
232 #if 0
233         /*
234          * If flush is 2 wait for dependancies
235          */
236         while (flush == 2 && TAILQ_FIRST(&io->deplist)) {
237                 hammer_io_wait(TAILQ_FIRST(&io->deplist));
238         }
239 #endif
240
241         /*
242          * Try to flush a dirty IO to disk if asked to by the caller
243          * or if the kernel tried to flush the buffer in the past.
244          *
245          * The flush will fail if any dependancies are present.
246          */
247         if (io->modified && (flush || bp->b_flags & B_LOCKED))
248                 hammer_io_flush(io);
249
250         /*
251          * If flush is 2 we wait for the IO to complete.
252          */
253         if (flush == 2 && io->running) {
254                 hammer_io_wait(io);
255         }
256
257         /*
258          * Actively or passively release the buffer.  Modified IOs with
259          * dependancies cannot be released.
260          */
261         if (flush && io->modified == 0 && io->running == 0) {
262                 KKASSERT(TAILQ_EMPTY(&io->deplist));
263                 if (io->released) {
264                         regetblk(bp);
265                         io->released = 0;
266                 }
267                 hammer_io_disassociate((hammer_io_structure_t)io, 1);
268         } else if (io->modified) {
269                 if (io->released == 0 && TAILQ_EMPTY(&io->deplist)) {
270                         io->released = 1;
271                         bdwrite(bp);
272                 }
273         } else if (io->released == 0) {
274                 io->released = 1;
275                 bqrelse(bp);
276         }
277 }
278
279 /*
280  * This routine is called with a locked IO when a flush is desired and
281  * no other references to the structure exists other then ours.  This
282  * routine is ONLY called when HAMMER believes it is safe to flush a
283  * potentially modified buffer out.
284  */
285 void
286 hammer_io_flush(struct hammer_io *io)
287 {
288         struct buf *bp;
289
290         /*
291          * Can't flush if the IO isn't modified or if it has dependancies.
292          */
293         if (io->modified == 0)
294                 return;
295         if (TAILQ_FIRST(&io->deplist))
296                 return;
297
298         KKASSERT(io->bp);
299
300         /*
301          * XXX - umount syncs buffers without referencing them, check for 0
302          * also.
303          */
304         KKASSERT(io->lock.refs == 0 || io->lock.refs == 1);
305
306         /*
307          * Reset modified to 0 here and re-check it after the IO completes.
308          * This is only legal when lock.refs == 1 (otherwise we might clear
309          * the modified bit while there are still users of the cluster
310          * modifying the data).
311          *
312          * NOTE: We have no dependancies so we don't have to worry about
313          * cluster-open's here.
314          *
315          * Do this before potentially blocking so any attempt to modify the
316          * ondisk while we are blocked blocks waiting for us.
317          */
318         io->modified = 0;
319         bp = io->bp;
320
321         /*
322          * If we are trying to flush a buffer we have to wait until the
323          * cluster header for the mark-OPEN has completed its I/O.
324          */
325         if (io->type == HAMMER_STRUCTURE_BUFFER) {
326                 hammer_io_structure_t iou = (void *)io;
327                 hammer_cluster_t cluster = iou->buffer.cluster;
328
329                 if (cluster->io.running) {
330                         kprintf("WAIT CLUSTER OPEN %d\n", cluster->clu_no);
331                         hammer_io_wait(&cluster->io);
332                         kprintf("WAIT CLUSTER OPEN OK\n");
333                 }
334         }
335         if (io->type == HAMMER_STRUCTURE_CLUSTER) {
336                 /*
337                  * Mark the cluster closed if we can
338                  */
339                 hammer_io_checkwrite(io->bp);
340         }
341         if (io->released) {
342                 regetblk(bp);
343                 /* BUF_KERNPROC(io->bp); */
344                 io->released = 0;
345         }
346         io->released = 1;
347         io->running = 1;
348         bawrite(bp);
349 }
350
351 /************************************************************************
352  *                              BUFFER DIRTYING                         *
353  ************************************************************************
354  *
355  * These routines deal with dependancies created when IO buffers get
356  * modified.  The caller must call hammer_modify_*() on a referenced
357  * HAMMER structure prior to modifying its on-disk data.
358  *
359  * Any intent to modify an IO buffer acquires the related bp and imposes
360  * various write ordering dependancies.
361  */
362
363 /*
364  * Ensure that the bp is acquired and return non-zero on a 0->1 transition
365  * of the modified bit.
366  */
367 static __inline
368 int
369 hammer_io_modify(hammer_io_t io, struct hammer_io_list *list)
370 {
371         int r = 0;
372
373         KKASSERT(io->lock.refs != 0 && io->bp != NULL);
374         if (io->modified == 0) {
375                 hammer_lock_ex(&io->lock);
376                 if (io->modified == 0) {
377                         if (io->released) {
378                                 regetblk(io->bp);
379                                 BUF_KERNPROC(io->bp);
380                                 io->released = 0;
381                         }
382                         io->modified = 1;
383                         io->entry_list = list;
384                         if (list)
385                                 TAILQ_INSERT_TAIL(list, io, entry);
386                         r = 1;
387                 }
388                 hammer_unlock(&io->lock);
389         } else if (io->released) {
390                 /*
391                  * Make sure no IO is occuring while we modify the contents
392                  * of the buffer. XXX should be able to avoid doing this.
393                  */
394                 hammer_lock_ex(&io->lock);
395                 if (io->released) {
396                         regetblk(io->bp);
397                         BUF_KERNPROC(io->bp);
398                         io->released = 0;
399                 }
400                 /*
401                  * The modified bit should still be set because we have
402                  * a ref on the structure, so the kernel's checkwrite
403                  * should not have cleared it.
404                  */
405                 KKASSERT(io->modified != 0);
406                 hammer_unlock(&io->lock);
407         }
408         return(r);
409 }
410
411 void
412 hammer_modify_volume(hammer_volume_t volume)
413 {
414         hammer_io_modify(&volume->io, NULL);
415 }
416
417 void
418 hammer_modify_supercl(hammer_supercl_t supercl)
419 {
420         hammer_io_modify(&supercl->io, &supercl->volume->io.deplist);
421 }
422
423 /*
424  * Caller intends to modify a cluster's ondisk structure. 
425  */
426 void
427 hammer_modify_cluster(hammer_cluster_t cluster)
428 {
429         hammer_io_modify(&cluster->io, &cluster->volume->io.deplist);
430 }
431
432 /*
433  * Caller intends to modify a buffer's ondisk structure.  The related
434  * cluster must be marked open prior to being able to flush the modified
435  * buffer so get that I/O going now.
436  */
437 void
438 hammer_modify_buffer(hammer_buffer_t buffer)
439 {
440         hammer_cluster_t cluster = buffer->cluster;
441
442         if (hammer_io_modify(&buffer->io, &cluster->io.deplist)) {
443                 hammer_modify_cluster(cluster);
444                 if ((cluster->ondisk->clu_flags & HAMMER_CLUF_OPEN) == 0) {
445                         hammer_lock_ex(&cluster->io.lock);
446                         if ((cluster->ondisk->clu_flags & HAMMER_CLUF_OPEN) == 0) {
447                                 KKASSERT(cluster->io.released == 0);
448                                 cluster->ondisk->clu_flags |= HAMMER_CLUF_OPEN;
449                                 cluster->io.released = 1;
450                                 cluster->io.running = 1;
451                                 bawrite(cluster->io.bp);
452                                 kprintf("OPEN CLUSTER %d:%d\n",
453                                         cluster->volume->vol_no,
454                                         cluster->clu_no);
455                         }
456                         hammer_unlock(&cluster->io.lock);
457                 }
458         }
459 }
460
461 /*
462  * Mark an entity as not being dirty any more -- this usually occurs when
463  * the governing a-list has freed the entire entity.
464  *
465  * XXX
466  */
467 void
468 hammer_io_clear_modify(struct hammer_io *io)
469 {
470 #if 0
471         struct buf *bp;
472
473         io->modified = 0;
474         if ((bp = io->bp) != NULL) {
475                 if (io->released) {
476                         regetblk(bp);
477                         /* BUF_KERNPROC(io->bp); */
478                 } else {
479                         io->released = 1;
480                 }
481                 if (io->modified == 0) {
482                         kprintf("hammer_io_clear_modify: cleared %p\n", io);
483                         bundirty(bp);
484                         bqrelse(bp);
485                 } else {
486                         bdwrite(bp);
487                 }
488         }
489 #endif
490 }
491
492 /************************************************************************
493  *                              HAMMER_BIOOPS                           *
494  ************************************************************************
495  *
496  */
497
498 /*
499  * Pre-IO initiation kernel callback - cluster build only
500  */
501 static void
502 hammer_io_start(struct buf *bp)
503 {
504 }
505
506 /*
507  * Post-IO completion kernel callback
508  *
509  * NOTE: HAMMER may modify a buffer after initiating I/O.  The modified bit
510  * may also be set if we were marking a cluster header open.  Only remove
511  * our dependancy if the modified bit is clear.
512  */
513 static void
514 hammer_io_complete(struct buf *bp)
515 {
516         union hammer_io_structure *iou = (void *)LIST_FIRST(&bp->b_dep);
517
518         KKASSERT(iou->io.released == 1);
519
520         /*
521          * If this was a write and the modified bit is still clear we can
522          * remove ourselves from the dependancy list.
523          *
524          * If no lock references remain and we can acquire the IO lock and
525          * someone at some point wanted us to flush (B_LOCKED test), then
526          * try to dispose of the IO.
527          */
528         if (iou->io.modified == 0 && iou->io.entry_list) {
529                 TAILQ_REMOVE(iou->io.entry_list, &iou->io, entry);
530                 iou->io.entry_list = NULL;
531         }
532         iou->io.running = 0;
533         if (iou->io.waiting) {
534                 iou->io.waiting = 0;
535                 wakeup(iou);
536         }
537
538         /*
539          * Someone wanted us to flush, try to clean out the buffer. 
540          */
541         if ((bp->b_flags & B_LOCKED) && iou->io.lock.refs == 0) {
542                 KKASSERT(iou->io.modified == 0);
543                 hammer_io_deallocate(bp);
544                 /* structure may be dead now */
545         }
546 }
547
548 /*
549  * Callback from kernel when it wishes to deallocate a passively
550  * associated structure.  This case can only occur with read-only
551  * bp's.
552  *
553  * If we cannot disassociate we set B_LOCKED to prevent the buffer
554  * from getting reused.
555  */
556 static void
557 hammer_io_deallocate(struct buf *bp)
558 {
559         hammer_io_structure_t iou = (void *)LIST_FIRST(&bp->b_dep);
560
561         KKASSERT((bp->b_flags & B_LOCKED) == 0 && iou->io.running == 0);
562         if (iou->io.modified) {
563                 bp->b_flags |= B_LOCKED;
564                 return;
565         }
566         hammer_ref(&iou->io.lock);
567         if (iou->io.lock.refs > 1 || iou->io.modified) {
568                 hammer_unref(&iou->io.lock);
569                 bp->b_flags |= B_LOCKED;
570         } else {
571                 hammer_io_disassociate(iou, 0);
572
573                 switch(iou->io.type) {
574                 case HAMMER_STRUCTURE_VOLUME:
575                         hammer_rel_volume(&iou->volume, 1);
576                         break;
577                 case HAMMER_STRUCTURE_SUPERCL:
578                         hammer_rel_supercl(&iou->supercl, 1);
579                         break;
580                 case HAMMER_STRUCTURE_CLUSTER:
581                         hammer_rel_cluster(&iou->cluster, 1);
582                         break;
583                 case HAMMER_STRUCTURE_BUFFER:
584                         hammer_rel_buffer(&iou->buffer, 1);
585                         break;
586                 }
587         }
588 }
589
590 static int
591 hammer_io_fsync(struct vnode *vp)
592 {
593         return(0);
594 }
595
596 /*
597  * NOTE: will not be called unless we tell the kernel about the
598  * bioops.  Unused... we use the mount's VFS_SYNC instead.
599  */
600 static int
601 hammer_io_sync(struct mount *mp)
602 {
603         return(0);
604 }
605
606 static void
607 hammer_io_movedeps(struct buf *bp1, struct buf *bp2)
608 {
609 }
610
611 /*
612  * I/O pre-check for reading and writing.  HAMMER only uses this for
613  * B_CACHE buffers so checkread just shouldn't happen, but if it does
614  * allow it.
615  *
616  * Writing is a different case.  We don't want the kernel to try to write
617  * out a buffer that HAMMER may be modifying passively or which has a
618  * dependancy.
619  *
620  * This code enforces the following write ordering: buffers, then cluster
621  * headers, then volume headers.
622  */
623 static int
624 hammer_io_checkread(struct buf *bp)
625 {
626         return(0);
627 }
628
629 static int
630 hammer_io_checkwrite(struct buf *bp)
631 {
632         union hammer_io_structure *iou = (void *)LIST_FIRST(&bp->b_dep);
633
634         /*
635          * A modified cluster with no dependancies can be closed.  It is
636          * possible for the cluster to have been modified by the recovery
637          * code without validation.  Only clear the open flag if the
638          * cluster is validated.
639          */
640         if (iou->io.type == HAMMER_STRUCTURE_CLUSTER && iou->io.modified) {
641                 hammer_cluster_t cluster = &iou->cluster;
642
643                 if (TAILQ_EMPTY(&cluster->io.deplist)) {
644                         kprintf("CLOSE CLUSTER %d:%d ",
645                                 cluster->volume->vol_no,
646                                 cluster->clu_no);
647                         if (cluster->ondisk->clu_flags & HAMMER_CLUF_OPEN) {
648                                 if (cluster->io.validated) {
649                                         cluster->ondisk->clu_flags &=
650                                                 ~HAMMER_CLUF_OPEN;
651                                         kprintf("(closed)\n");
652                                 } else {
653                                         kprintf("(leave-open)\n");
654                                 }
655                         } else {
656                                 kprintf("(header-only)\n");
657                         }
658                 }
659         }
660
661         /*
662          * We are called from the kernel on delayed-write buffers, and
663          * called from hammer_io_flush() on flush requests.  There should
664          * be no dependancies in either case.
665          *
666          * In the case of delayed-writes, the introduction of a dependancy
667          * will block until the bp can be reacquired, and the bp is then
668          * simply not released until the dependancy can be satisfied.
669          *
670          * We can only clear the modified bit when entered from the kernel
671          * if io.lock.refs == 0.
672          */
673         KKASSERT(TAILQ_EMPTY(&iou->io.deplist));
674         if (iou->io.lock.refs == 0) {
675                 iou->io.modified = 0;
676         }
677         return(0);
678 }
679
680 /*
681  * Return non-zero if the caller should flush the structure associated
682  * with this io sub-structure.
683  */
684 int
685 hammer_io_checkflush(struct hammer_io *io)
686 {
687         if (io->bp == NULL || (io->bp->b_flags & B_LOCKED)) {
688                 return(1);
689         }
690         return(0);
691 }
692
693 /*
694  * Return non-zero if we wish to delay the kernel's attempt to flush
695  * this buffer to disk.
696  */
697 static int
698 hammer_io_countdeps(struct buf *bp, int n)
699 {
700         return(0);
701 }
702
703 struct bio_ops hammer_bioops = {
704         .io_start       = hammer_io_start,
705         .io_complete    = hammer_io_complete,
706         .io_deallocate  = hammer_io_deallocate,
707         .io_fsync       = hammer_io_fsync,
708         .io_sync        = hammer_io_sync,
709         .io_movedeps    = hammer_io_movedeps,
710         .io_countdeps   = hammer_io_countdeps,
711         .io_checkread   = hammer_io_checkread,
712         .io_checkwrite  = hammer_io_checkwrite,
713 };
714