HAMMER 16/many - Recovery infrastructure, misc bug fixes
[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.13 2008/01/09 00:46:22 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 /*
56  * Helper routine to disassociate a buffer cache buffer from an I/O
57  * structure.
58  */
59 static void
60 hammer_io_disassociate(union hammer_io_structure *io)
61 {
62         struct buf *bp = io->io.bp;
63
64         KKASSERT(io->io.released && io->io.modified == 0);
65         buf_dep_init(bp);
66         io->io.bp = NULL;
67         bp->b_flags &= ~B_LOCKED;
68
69         switch(io->io.type) {
70         case HAMMER_STRUCTURE_VOLUME:
71                 io->volume.ondisk = NULL;
72                 io->volume.alist.meta = NULL;
73                 break;
74         case HAMMER_STRUCTURE_SUPERCL:
75                 io->supercl.ondisk = NULL;
76                 io->supercl.alist.meta = NULL;
77                 break;
78         case HAMMER_STRUCTURE_CLUSTER:
79                 /*KKASSERT((io->cluster.ondisk->clu_flags & HAMMER_CLUF_OPEN) == 0);*/
80                 io->cluster.ondisk = NULL;
81                 io->cluster.alist_master.meta = NULL;
82                 io->cluster.alist_btree.meta = NULL;
83                 io->cluster.alist_record.meta = NULL;
84                 io->cluster.alist_mdata.meta = NULL;
85                 break;
86         case HAMMER_STRUCTURE_BUFFER:
87                 io->buffer.ondisk = NULL;
88                 io->buffer.alist.meta = NULL;
89                 break;
90         }
91 }
92
93 /*
94  * Mark a cluster as being closed.  This is done as late as possible,
95  * only when we are asked to flush the cluster
96  */
97 static void
98 hammer_close_cluster(hammer_cluster_t cluster)
99 {
100         while (cluster->state == HAMMER_CLUSTER_ASYNC)
101                 tsleep(cluster, 0, "hmrdep", 0);
102         if (cluster->state == HAMMER_CLUSTER_OPEN) {
103                 cluster->state = HAMMER_CLUSTER_IDLE;
104                 hammer_modify_cluster(cluster);
105                 cluster->ondisk->clu_flags &= ~HAMMER_CLUF_OPEN;
106                 hammer_modify_cluster_done(cluster);
107                 kprintf("CLOSE CLUSTER\n");
108         }
109 }
110
111 /*
112  * Hack XXX - called from kernel syncer via hammer_io_checkwrite() when it
113  * wants to flush buffer.  Because we disassociate after this call and
114  * because the kernel is already intending to write out the buffer, don't
115  * set the io.modified bit.
116  */
117 static void
118 hammer_close_cluster_quick(hammer_cluster_t cluster)
119 {
120         if (cluster->state == HAMMER_CLUSTER_OPEN) {
121                 cluster->state = HAMMER_CLUSTER_IDLE;
122                 cluster->ondisk->clu_flags &= ~HAMMER_CLUF_OPEN;
123                 kprintf("CLOSE CLUSTER ON KERNEL WRITE\n");
124         }
125 }
126
127
128 /*
129  * Load bp for a HAMMER structure.
130  */
131 int
132 hammer_io_read(struct vnode *devvp, struct hammer_io *io)
133 {
134         struct buf *bp;
135         int error;
136
137         if ((bp = io->bp) == NULL) {
138                 error = bread(devvp, io->offset, HAMMER_BUFSIZE, &io->bp);
139                 if (error == 0) {
140                         bp = io->bp;
141                         bp->b_ops = &hammer_bioops;
142                         LIST_INSERT_HEAD(&bp->b_dep, &io->worklist, node);
143                         BUF_KERNPROC(bp);
144                 }
145                 io->modified = 0;       /* no new modifications yet */
146                 io->released = 0;       /* we hold an active lock on bp */
147         } else {
148                 error = 0;
149         }
150         return(error);
151 }
152
153 /*
154  * Similar to hammer_io_read() but returns a zero'd out buffer instead.
155  * vfs_bio_clrbuf() is kinda nasty, enforce serialization against background
156  * I/O so we can call it.
157  */
158 int
159 hammer_io_new(struct vnode *devvp, struct hammer_io *io)
160 {
161         struct buf *bp;
162
163         if ((bp = io->bp) == NULL) {
164                 io->bp = getblk(devvp, io->offset, HAMMER_BUFSIZE, 0, 0);
165                 bp = io->bp;
166                 bp->b_ops = &hammer_bioops;
167                 LIST_INSERT_HEAD(&bp->b_dep, &io->worklist, node);
168                 io->released = 0;       /* we hold an active lock on bp */
169                 BUF_KERNPROC(bp);
170         } else {
171                 if (io->released) {
172                         regetblk(bp);
173                         BUF_KERNPROC(bp);
174                         io->released = 0;
175                 }
176         }
177         io->modified = 1;
178         vfs_bio_clrbuf(bp);
179         return(0);
180 }
181
182 /*
183  * This routine is called when a buffer within a cluster is modified.  We
184  * mark the cluster open and immediately initiate asynchronous I/O.  Any
185  * related hammer_buffer write I/O blocks until our async write completes.
186  * This guarentees (inasmuch as the OS can) that the cluster recovery code
187  * will see a cluster marked open if a crash occured while the filesystem
188  * still had dirty buffers associated with that cluster.
189  *
190  * XXX
191  */
192 void
193 hammer_io_notify_cluster(hammer_cluster_t cluster)
194 {
195         struct hammer_io *io = &cluster->io;
196
197         if (cluster->state == HAMMER_CLUSTER_IDLE) {
198                 hammer_lock_ex(&cluster->io.lock);
199                 if (cluster->state == HAMMER_CLUSTER_IDLE) {
200                         if (io->released)
201                                 regetblk(io->bp);
202                         else
203                                 io->released = 1;
204                         kprintf("MARK CLUSTER OPEN\n");
205                         cluster->ondisk->clu_flags |= HAMMER_CLUF_OPEN;
206                         cluster->state = HAMMER_CLUSTER_ASYNC;
207                         cluster->io.modified = 1;
208                         bawrite(io->bp);
209                 }
210                 hammer_unlock(&cluster->io.lock);
211         }
212 }
213
214 /*
215  * This routine is called on the last reference to a hammer structure.
216  * Regardless of the state io->modified must be cleared when we return.
217  *
218  * If flush is non-zero we have to completely disassociate the bp from the
219  * structure (which may involve blocking).  Otherwise we can leave the bp
220  * passively associated with the structure.
221  *
222  * The caller is holding io->lock exclusively.
223  */
224 void
225 hammer_io_release(struct hammer_io *io, int flush)
226 {
227         union hammer_io_structure *iou = (void *)io;
228         hammer_cluster_t cluster;
229         struct buf *bp;
230         int modified;
231
232         if ((bp = io->bp) != NULL) {
233                 /*
234                  * If neither we nor the kernel want to flush the bp, we can
235                  * stop here.  Make sure the bp is passively released
236                  * before returning.  Even though we are still holding it,
237                  * we want to be notified when the kernel wishes to flush
238                  * it out so make sure B_DELWRI is properly set if we had
239                  * made modifications.
240                  */
241                 if (flush == 0 && (bp->b_flags & B_LOCKED) == 0) {
242                         if ((bp->b_flags & B_DELWRI) == 0 && io->modified) {
243                                 if (io->released)
244                                         regetblk(bp);
245                                 else
246                                         io->released = 1;
247                                 io->modified = 0;
248                                 bdwrite(bp);
249                         } else if (io->released == 0) {
250                                 /* buffer write state already synchronized */
251                                 io->modified = 0;
252                                 io->released = 1;
253                                 bqrelse(bp);
254                         } else {
255                                 /* buffer write state already synchronized */
256                                 io->modified = 0;
257                         }
258                         return;
259                 }
260
261                 /*
262                  * Either we want to flush the buffer or the kernel tried to
263                  * flush the buffer.
264                  *
265                  * If this is a hammer_buffer we may have to wait for the
266                  * cluster header write to complete.
267                  */
268                 if (iou->io.type == HAMMER_STRUCTURE_BUFFER &&
269                     (io->modified || (bp->b_flags & B_DELWRI))) {
270                         cluster = iou->buffer.cluster;
271                         while (cluster->state == HAMMER_CLUSTER_ASYNC)
272                                 tsleep(iou->buffer.cluster, 0, "hmrdep", 0);
273                 }
274
275                 /*
276                  * If we have an open cluster header, close it
277                  */
278                 if (iou->io.type == HAMMER_STRUCTURE_CLUSTER) {
279                         hammer_close_cluster(&iou->cluster);
280                 }
281
282                 /*
283                  * Gain ownership of the buffer.  Nothing can take it away
284                  * from the io structure while we have it locked, so we
285                  * can safely reget.
286                  *
287                  * Once our thread owns the buffer we can disassociate it
288                  * from the io structure.
289                  */
290                 if (io->released)
291                         regetblk(bp);
292                 else
293                         io->released = 1;
294                 modified = io->modified;
295                 io->modified = 0;
296                 hammer_io_disassociate(iou);
297
298                 /*
299                  * Now dispose of the buffer.  Someone tried to flush, so
300                  * issue the I/O immediately.
301                  */
302                 if (modified || (bp->b_flags & B_DELWRI))
303                         bawrite(bp);
304                 else
305                         bqrelse(bp);
306         }
307 }
308
309 /*
310  * Flush dirty data, if any.
311  */
312 void
313 hammer_io_flush(struct hammer_io *io, struct hammer_sync_info *info)
314 {
315         struct buf *bp;
316         int error;
317
318 again:
319         if ((bp = io->bp) == NULL)
320                 return;
321         if (bp->b_flags & B_DELWRI)
322                 io->modified = 1;
323
324         /*
325          * We can't initiate a write while the buffer is being modified
326          * by someone.
327          */
328         while (io->lock.modifying) {
329                 io->lock.wanted = 1;
330                 kprintf("DELAYING IO FLUSH BP %p TYPE %d REFS %d modifying %d\n",
331                         bp, io->type, io->lock.refs, io->lock.modifying);
332                 tsleep(&io->lock, 0, "hmrfls", 0);
333         }
334         hammer_lock_ex(&io->lock);
335         if (io->lock.modifying || io->bp == NULL) {
336                 hammer_unlock(&io->lock);
337                 goto again;
338         }
339
340         /*
341          * Acquire ownership of the buffer cache buffer so we can flush it
342          * out.
343          */
344         if (io->released) {
345                 if (io->modified == 0)
346                         goto done;
347                 regetblk(bp);
348         } else {
349                 io->released = 1;
350         }
351
352         /*
353          * Return the bp to the system, issuing I/O if necessary.  The
354          * system will issue a callback to us when it actually wants to
355          * throw the bp away.
356          */
357         if (io->modified == 0) {
358                 bqrelse(bp);
359         } else if (info->waitfor & MNT_WAIT) {
360                 io->modified = 0;
361                 error = bwrite(bp);
362                 if (error)
363                         info->error = error;
364         } else {
365                 io->modified = 0;
366                 bawrite(bp);
367         }
368 done:
369         hammer_unlock(&io->lock);
370 }
371
372 /*
373  * Called prior to any modifications being made to ondisk data.  This
374  * forces the caller to wait for any writes to complete.  We explicitly
375  * avoid the write-modify race.
376  *
377  * This routine is only called on hammer structures which are already
378  * actively referenced.
379  */
380 void
381 hammer_io_intend_modify(struct hammer_io *io)
382 {
383         KKASSERT(io->lock.refs != 0 && io->bp != NULL);
384         if (io->released) {
385                 hammer_lock_ex(&io->lock);
386                 if (io->released) {
387                         regetblk(io->bp);
388                         BUF_KERNPROC(io->bp);
389                         io->released = 0;
390                 }
391                 hammer_unlock(&io->lock);
392         }
393 }
394
395 void
396 hammer_io_modify_done(struct hammer_io *io)
397 {
398         KKASSERT(io->lock.modifying > 0);
399         --io->lock.modifying;
400         if (io->lock.wanted && io->lock.modifying == 0) {
401                 io->lock.wanted = 0;
402                 wakeup(&io->lock);
403         }
404 }
405
406 /*
407  * Mark an entity as not being dirty any more -- usually occurs when
408  * the governing a-list has freed the entire entity.
409  */
410 void
411 hammer_io_clear_modify(struct hammer_io *io)
412 {
413         struct buf *bp;
414
415         io->modified = 0;
416         if ((bp = io->bp) != NULL) {
417                 if (io->released)
418                         regetblk(bp);
419                 else
420                         io->released = 1;
421                 if (io->modified == 0) {
422                         kprintf("hammer_io_clear_modify: cleared %p\n", io);
423                         bundirty(bp);
424                         bqrelse(bp);
425                 } else {
426                         bdwrite(bp);
427                 }
428         }
429 }
430
431 /*
432  * HAMMER_BIOOPS
433  */
434
435 /*
436  * Pre and post I/O callbacks.
437  */
438 static void hammer_io_deallocate(struct buf *bp);
439
440 static void
441 hammer_io_start(struct buf *bp)
442 {
443 #if 0
444         union hammer_io_structure *io = (void *)LIST_FIRST(&bp->b_dep);
445
446         if (io->io.type == HAMMER_STRUCTURE_BUFFER) {
447                 while (io->buffer.cluster->io_in_progress) {
448                         kprintf("hammer_io_start: wait for cluster\n");
449                         tsleep(io->buffer.cluster, 0, "hmrdep", 0);
450                         kprintf("hammer_io_start: wait for cluster done\n");
451                 }
452         }
453 #endif
454 }
455
456 static void
457 hammer_io_complete(struct buf *bp)
458 {
459         union hammer_io_structure *io = (void *)LIST_FIRST(&bp->b_dep);
460
461         if (io->io.type == HAMMER_STRUCTURE_CLUSTER) {
462                 if (io->cluster.state == HAMMER_CLUSTER_ASYNC) {
463                         io->cluster.state = HAMMER_CLUSTER_OPEN;
464                         wakeup(&io->cluster);
465                 }
466         }
467 }
468
469 /*
470  * Callback from kernel when it wishes to deallocate a passively
471  * associated structure.  This can only occur if the buffer is
472  * passively associated with the structure.  The kernel has locked
473  * the buffer.
474  *
475  * If we cannot disassociate we set B_LOCKED to prevent the buffer
476  * from getting reused.
477  */
478 static void
479 hammer_io_deallocate(struct buf *bp)
480 {
481         union hammer_io_structure *io = (void *)LIST_FIRST(&bp->b_dep);
482
483         /* XXX memory interlock, spinlock to sync cpus */
484
485         /*
486          * Since the kernel is passing us a locked buffer, the HAMMER
487          * structure had better not believe it has a lock on the buffer.
488          */
489         KKASSERT(io->io.released);
490         crit_enter();
491
492         /*
493          * First, ref the structure to prevent either the buffer or the
494          * structure from going away or being unexpectedly flushed.
495          */
496         hammer_ref(&io->io.lock);
497
498         /*
499          * Buffers can have active references from cached hammer_node's,
500          * even if those nodes are themselves passively cached.  Attempt
501          * to clean them out.  This may not succeed.
502          *
503          * We have to do some magic with io.released because
504          * hammer_io_intend_modify() can be called indirectly from the
505          * flush code, otherwise we might panic with a recursive bp lock.
506          */
507         if (io->io.type == HAMMER_STRUCTURE_BUFFER &&
508             hammer_lock_ex_try(&io->io.lock) == 0) {
509                 io->io.released = 0;
510                 hammer_flush_buffer_nodes(&io->buffer);
511                 KKASSERT(io->io.released == 0);
512                 io->io.released = 1;
513                 hammer_unlock(&io->io.lock);
514         }
515
516         if (hammer_islastref(&io->io.lock)) {
517                 /*
518                  * If we are the only ref left we can disassociate the I/O.
519                  * It had better still be in a released state because the
520                  * kernel is holding a lock on the buffer.  Any passive
521                  * modifications should have already been synchronized with
522                  * the buffer.
523                  */
524                 KKASSERT(io->io.modified == 0);
525                 hammer_io_disassociate(io);
526
527                 /*
528                  * Perform final rights on the structure.  This can cause
529                  * a chain reaction - e.g. last buffer -> last cluster ->
530                  * last supercluster -> last volume.
531                  */
532                 switch(io->io.type) {
533                 case HAMMER_STRUCTURE_VOLUME:
534                         hammer_rel_volume(&io->volume, 1);
535                         break;
536                 case HAMMER_STRUCTURE_SUPERCL:
537                         hammer_rel_supercl(&io->supercl, 1);
538                         break;
539                 case HAMMER_STRUCTURE_CLUSTER:
540                         hammer_rel_cluster(&io->cluster, 1);
541                         break;
542                 case HAMMER_STRUCTURE_BUFFER:
543                         hammer_rel_buffer(&io->buffer, 1);
544                         break;
545                 }
546         } else {
547                 /*
548                  * Otherwise tell the kernel not to destroy the buffer.
549                  * 
550                  * We have to unref the structure without performing any
551                  * final rights to it to avoid a deadlock.
552                  */
553                 bp->b_flags |= B_LOCKED;
554                 hammer_unref(&io->io.lock);
555         }
556         crit_exit();
557 }
558
559 static int
560 hammer_io_fsync(struct vnode *vp)
561 {
562         return(0);
563 }
564
565 /*
566  * NOTE: will not be called unless we tell the kernel about the
567  * bioops.  Unused... we use the mount's VFS_SYNC instead.
568  */
569 static int
570 hammer_io_sync(struct mount *mp)
571 {
572         return(0);
573 }
574
575 static void
576 hammer_io_movedeps(struct buf *bp1, struct buf *bp2)
577 {
578 }
579
580 /*
581  * I/O pre-check for reading and writing.  HAMMER only uses this for
582  * B_CACHE buffers so checkread just shouldn't happen, but if it does
583  * allow it.
584  *
585  * Writing is a different case.  We don't want the kernel to try to write
586  * out a buffer that HAMMER may be modifying passively or which has a
587  * dependancy.
588  *
589  * This code enforces the following write ordering: buffers, then cluster
590  * headers, then volume headers.
591  */
592 static int
593 hammer_io_checkread(struct buf *bp)
594 {
595         return(0);
596 }
597
598 static int
599 hammer_io_checkwrite(struct buf *bp)
600 {
601         union hammer_io_structure *iou = (void *)LIST_FIRST(&bp->b_dep);
602
603         if (iou->io.type == HAMMER_STRUCTURE_BUFFER &&
604             iou->buffer.cluster->state == HAMMER_CLUSTER_ASYNC) {
605                 /*
606                  * Cannot write out a cluster buffer if the cluster header
607                  * I/O opening the cluster has not completed.
608                  */
609                 bp->b_flags |= B_LOCKED;
610                 return(-1);
611         } else if (iou->io.lock.refs) {
612                 /*
613                  * Cannot write out a bp if its associated buffer has active
614                  * references.
615                  */
616                 bp->b_flags |= B_LOCKED;
617                 return(-1);
618         } else {
619                 /*
620                  * We're good, but before we can let the kernel proceed we
621                  * may have to make some adjustments.
622                  *
623                  * Since there are no refs on the io structure, HAMMER must
624                  * have already synchronized its modify state with the bp
625                  * so iou->io.modified should be 0.
626                  */
627                 if (iou->io.type == HAMMER_STRUCTURE_CLUSTER)
628                         hammer_close_cluster_quick(&iou->cluster);
629                 hammer_io_disassociate(iou);
630                 return(0);
631         }
632 }
633
634 /*
635  * Return non-zero if the caller should flush the structure associated
636  * with this io sub-structure.
637  */
638 int
639 hammer_io_checkflush(struct hammer_io *io)
640 {
641         if (io->bp == NULL || (io->bp->b_flags & B_LOCKED))
642                 return(1);
643         return(0);
644 }
645
646 /*
647  * Return non-zero if we wish to delay the kernel's attempt to flush
648  * this buffer to disk.
649  */
650 static int
651 hammer_io_countdeps(struct buf *bp, int n)
652 {
653         return(0);
654 }
655
656 struct bio_ops hammer_bioops = {
657         .io_start       = hammer_io_start,
658         .io_complete    = hammer_io_complete,
659         .io_deallocate  = hammer_io_deallocate,
660         .io_fsync       = hammer_io_fsync,
661         .io_sync        = hammer_io_sync,
662         .io_movedeps    = hammer_io_movedeps,
663         .io_countdeps   = hammer_io_countdeps,
664         .io_checkread   = hammer_io_checkread,
665         .io_checkwrite  = hammer_io_checkwrite,
666 };
667