Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / sys / vfs / hammer / hammer_io.c
1 /*
2  * Copyright (c) 2007-2008 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.41 2008/06/14 01:42:13 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 destroy 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_modify(hammer_io_t io, int count);
56 static void hammer_io_deallocate(struct buf *bp);
57
58 /*
59  * Initialize a new, already-zero'd hammer_io structure, or reinitialize
60  * an existing hammer_io structure which may have switched to another type.
61  */
62 void
63 hammer_io_init(hammer_io_t io, hammer_mount_t hmp, enum hammer_io_type type)
64 {
65         io->hmp = hmp;
66         io->type = type;
67 }
68
69 /*
70  * Helper routine to disassociate a buffer cache buffer from an I/O
71  * structure.
72  *
73  * The io may have 0 or 1 references depending on who called us.  The
74  * caller is responsible for dealing with the refs.
75  *
76  * This call can only be made when no action is required on the buffer.
77  * HAMMER must own the buffer (released == 0) since we mess around with it.
78  */
79 static void
80 hammer_io_disassociate(hammer_io_structure_t iou, int elseit)
81 {
82         struct buf *bp = iou->io.bp;
83
84         KKASSERT(iou->io.modified == 0);
85         KKASSERT(LIST_FIRST(&bp->b_dep) == (void *)iou);
86         buf_dep_init(bp);
87         iou->io.bp = NULL;
88
89         /*
90          * If the buffer was locked someone wanted to get rid of it.
91          */
92         if (bp->b_flags & B_LOCKED) {
93                 --hammer_count_io_locked;
94                 bp->b_flags &= ~B_LOCKED;
95         }
96
97         /*
98          * elseit is 0 when called from the kernel path when the io
99          * might have no references.
100          */
101         if (elseit) {
102                 KKASSERT(iou->io.released == 0);
103                 iou->io.released = 1;
104                 if (iou->io.reclaim)
105                         bp->b_flags |= B_NOCACHE|B_RELBUF;
106                 bqrelse(bp);
107         } else {
108                 KKASSERT(iou->io.released);
109         }
110         iou->io.reclaim = 0;
111
112         switch(iou->io.type) {
113         case HAMMER_STRUCTURE_VOLUME:
114                 iou->volume.ondisk = NULL;
115                 break;
116         case HAMMER_STRUCTURE_DATA_BUFFER:
117         case HAMMER_STRUCTURE_META_BUFFER:
118         case HAMMER_STRUCTURE_UNDO_BUFFER:
119                 iou->buffer.ondisk = NULL;
120                 break;
121         }
122 }
123
124 /*
125  * Wait for any physical IO to complete
126  */
127 static void
128 hammer_io_wait(hammer_io_t io)
129 {
130         if (io->running) {
131                 crit_enter();
132                 tsleep_interlock(io);
133                 io->waiting = 1;
134                 for (;;) {
135                         tsleep(io, 0, "hmrflw", 0);
136                         if (io->running == 0)
137                                 break;
138                         tsleep_interlock(io);
139                         io->waiting = 1;
140                         if (io->running == 0)
141                                 break;
142                 }
143                 crit_exit();
144         }
145 }
146
147 /*
148  * Wait for all hammer_io-initated write I/O's to complete.  This is not
149  * supposed to count direct I/O's but some can leak through (for
150  * non-full-sized direct I/Os).
151  */
152 void
153 hammer_io_wait_all(hammer_mount_t hmp, const char *ident)
154 {
155         crit_enter();
156         while (hmp->io_running_count)
157                 tsleep(&hmp->io_running_count, 0, ident, 0);
158         crit_exit();
159 }
160
161 #define HAMMER_MAXRA    4
162
163 /*
164  * Load bp for a HAMMER structure.  The io must be exclusively locked by
165  * the caller.
166  *
167  * This routine is mostly used on meta-data and small-data blocks.  Generally
168  * speaking HAMMER assumes some locality of reference and will cluster 
169  * a 64K read.
170  *
171  * Note that clustering occurs at the device layer, not the logical layer.
172  * If the buffers do not apply to the current operation they may apply to
173  * some other.
174  */
175 int
176 hammer_io_read(struct vnode *devvp, struct hammer_io *io, hammer_off_t limit)
177 {
178         struct buf *bp;
179         int   error;
180
181         if ((bp = io->bp) == NULL) {
182                 ++hammer_count_io_running_read;
183                 error = cluster_read(devvp, limit, io->offset,
184                                      HAMMER_BUFSIZE,
185                                      HAMMER_CLUSTER_SIZE,
186                                      HAMMER_CLUSTER_BUFS, &io->bp);
187                 --hammer_count_io_running_read;
188                 if (error == 0) {
189                         bp = io->bp;
190                         bp->b_ops = &hammer_bioops;
191                         KKASSERT(LIST_FIRST(&bp->b_dep) == NULL);
192                         LIST_INSERT_HEAD(&bp->b_dep, &io->worklist, node);
193                         BUF_KERNPROC(bp);
194                 }
195                 KKASSERT(io->modified == 0);
196                 KKASSERT(io->running == 0);
197                 KKASSERT(io->waiting == 0);
198                 io->released = 0;       /* we hold an active lock on bp */
199         } else {
200                 error = 0;
201         }
202         return(error);
203 }
204
205 /*
206  * Similar to hammer_io_read() but returns a zero'd out buffer instead.
207  * Must be called with the IO exclusively locked.
208  *
209  * vfs_bio_clrbuf() is kinda nasty, enforce serialization against background
210  * I/O by forcing the buffer to not be in a released state before calling
211  * it.
212  *
213  * This function will also mark the IO as modified but it will not
214  * increment the modify_refs count.
215  */
216 int
217 hammer_io_new(struct vnode *devvp, struct hammer_io *io)
218 {
219         struct buf *bp;
220
221         if ((bp = io->bp) == NULL) {
222                 io->bp = getblk(devvp, io->offset, HAMMER_BUFSIZE, 0, 0);
223                 bp = io->bp;
224                 bp->b_ops = &hammer_bioops;
225                 KKASSERT(LIST_FIRST(&bp->b_dep) == NULL);
226                 LIST_INSERT_HEAD(&bp->b_dep, &io->worklist, node);
227                 io->released = 0;
228                 KKASSERT(io->running == 0);
229                 io->waiting = 0;
230                 BUF_KERNPROC(bp);
231         } else {
232                 if (io->released) {
233                         regetblk(bp);
234                         BUF_KERNPROC(bp);
235                         io->released = 0;
236                 }
237         }
238         hammer_io_modify(io, 0);
239         vfs_bio_clrbuf(bp);
240         return(0);
241 }
242
243 /*
244  * Remove potential device level aliases against buffers managed by high level
245  * vnodes.
246  */
247 void
248 hammer_io_inval(hammer_volume_t volume, hammer_off_t zone2_offset)
249 {
250         hammer_io_structure_t iou;
251         hammer_off_t phys_offset;
252         struct buf *bp;
253
254         phys_offset = volume->ondisk->vol_buf_beg +
255                       (zone2_offset & HAMMER_OFF_SHORT_MASK);
256         if (findblk(volume->devvp, phys_offset)) {
257                 bp = getblk(volume->devvp, phys_offset, HAMMER_BUFSIZE, 0, 0);
258                 if ((iou = (void *)LIST_FIRST(&bp->b_dep)) != NULL) {
259                         hammer_io_clear_modify(&iou->io);
260                         bundirty(bp);
261                         iou->io.reclaim = 1;
262                         hammer_io_deallocate(bp);
263                 } else {
264                         KKASSERT((bp->b_flags & B_LOCKED) == 0);
265                         bundirty(bp);
266                         bp->b_flags |= B_NOCACHE|B_RELBUF;
267                         brelse(bp);
268                 }
269         }
270 }
271
272 /*
273  * This routine is called on the last reference to a hammer structure.
274  * The io is usually locked exclusively (but may not be during unmount).
275  *
276  * This routine is responsible for the disposition of the buffer cache
277  * buffer backing the IO.  Only pure-data and undo buffers can be handed
278  * back to the kernel.  Volume and meta-data buffers must be retained
279  * by HAMMER until explicitly flushed by the backend.
280  */
281 void
282 hammer_io_release(struct hammer_io *io, int flush)
283 {
284         union hammer_io_structure *iou = (void *)io;
285         struct buf *bp;
286
287         if ((bp = io->bp) == NULL)
288                 return;
289
290         /*
291          * Try to flush a dirty IO to disk if asked to by the
292          * caller or if the kernel tried to flush the buffer in the past.
293          *
294          * Kernel-initiated flushes are only allowed for pure-data buffers.
295          * meta-data and volume buffers can only be flushed explicitly
296          * by HAMMER.
297          */
298         if (io->modified) {
299                 if (flush) {
300                         hammer_io_flush(io);
301                 } else if (bp->b_flags & B_LOCKED) {
302                         switch(io->type) {
303                         case HAMMER_STRUCTURE_DATA_BUFFER:
304                         case HAMMER_STRUCTURE_UNDO_BUFFER:
305                                 hammer_io_flush(io);
306                                 break;
307                         default:
308                                 break;
309                         }
310                 } /* else no explicit request to flush the buffer */
311         }
312
313         /*
314          * Wait for the IO to complete if asked to.
315          */
316         if (io->waitdep && io->running) {
317                 hammer_io_wait(io);
318         }
319
320         /*
321          * Return control of the buffer to the kernel (with the provisio
322          * that our bioops can override kernel decisions with regards to
323          * the buffer).
324          */
325         if ((flush || io->reclaim) && io->modified == 0 && io->running == 0) {
326                 /*
327                  * Always disassociate the bp if an explicit flush
328                  * was requested and the IO completed with no error
329                  * (so unmount can really clean up the structure).
330                  */
331                 if (io->released) {
332                         regetblk(bp);
333                         BUF_KERNPROC(bp);
334                         io->released = 0;
335                 }
336                 hammer_io_disassociate((hammer_io_structure_t)io, 1);
337         } else if (io->modified) {
338                 /*
339                  * Only certain IO types can be released to the kernel.
340                  * volume and meta-data IO types must be explicitly flushed
341                  * by HAMMER.
342                  */
343                 switch(io->type) {
344                 case HAMMER_STRUCTURE_DATA_BUFFER:
345                 case HAMMER_STRUCTURE_UNDO_BUFFER:
346                         if (io->released == 0) {
347                                 io->released = 1;
348                                 bdwrite(bp);
349                         }
350                         break;
351                 default:
352                         break;
353                 }
354         } else if (io->released == 0) {
355                 /*
356                  * Clean buffers can be generally released to the kernel.
357                  * We leave the bp passively associated with the HAMMER
358                  * structure and use bioops to disconnect it later on
359                  * if the kernel wants to discard the buffer.
360                  */
361                 if (bp->b_flags & B_LOCKED) {
362                         hammer_io_disassociate(iou, 1);
363                 } else {
364                         if (io->reclaim) {
365                                 hammer_io_disassociate(iou, 1);
366                         } else {
367                                 io->released = 1;
368                                 bqrelse(bp);
369                         }
370                 }
371         } else {
372                 /*
373                  * A released buffer is passively associate with our
374                  * hammer_io structure.  The kernel cannot destroy it
375                  * without making a bioops call.  If the kernel (B_LOCKED)
376                  * or we (reclaim) requested that the buffer be destroyed
377                  * we destroy it, otherwise we do a quick get/release to
378                  * reset its position in the kernel's LRU list.
379                  *
380                  * Leaving the buffer passively associated allows us to
381                  * use the kernel's LRU buffer flushing mechanisms rather
382                  * then rolling our own.
383                  */
384                 crit_enter();
385                 if (io->running == 0) {
386                         regetblk(bp);
387                         if ((bp->b_flags & B_LOCKED) || io->reclaim) {
388                                 io->released = 0;
389                                 hammer_io_disassociate(iou, 1);
390                         } else {
391                                 bqrelse(bp);
392                         }
393                 }
394                 crit_exit();
395         }
396 }
397
398 /*
399  * This routine is called with a locked IO when a flush is desired and
400  * no other references to the structure exists other then ours.  This
401  * routine is ONLY called when HAMMER believes it is safe to flush a
402  * potentially modified buffer out.
403  */
404 void
405 hammer_io_flush(struct hammer_io *io)
406 {
407         struct buf *bp;
408
409         /*
410          * Degenerate case - nothing to flush if nothing is dirty.
411          */
412         if (io->modified == 0) {
413                 return;
414         }
415
416         KKASSERT(io->bp);
417         KKASSERT(io->modify_refs <= 0);
418
419         /*
420          * Acquire ownership of the bp, particularly before we clear our
421          * modified flag.
422          *
423          * We are going to bawrite() this bp.  Don't leave a window where
424          * io->released is set, we actually own the bp rather then our
425          * buffer.
426          */
427         bp = io->bp;
428         if (io->released) {
429                 regetblk(bp);
430                 /* BUF_KERNPROC(io->bp); */
431                 /* io->released = 0; */
432                 KKASSERT(io->released);
433                 KKASSERT(io->bp == bp);
434         }
435         io->released = 1;
436
437         /*
438          * Acquire exclusive access to the bp and then clear the modified
439          * state of the buffer prior to issuing I/O to interlock any
440          * modifications made while the I/O is in progress.  This shouldn't
441          * happen anyway but losing data would be worse.  The modified bit
442          * will be rechecked after the IO completes.
443          *
444          * This is only legal when lock.refs == 1 (otherwise we might clear
445          * the modified bit while there are still users of the cluster
446          * modifying the data).
447          *
448          * Do this before potentially blocking so any attempt to modify the
449          * ondisk while we are blocked blocks waiting for us.
450          */
451         hammer_io_clear_modify(io);
452
453         /*
454          * Transfer ownership to the kernel and initiate I/O.
455          */
456         io->running = 1;
457         ++io->hmp->io_running_count;
458         ++hammer_count_io_running_write;
459         bawrite(bp);
460 }
461
462 /************************************************************************
463  *                              BUFFER DIRTYING                         *
464  ************************************************************************
465  *
466  * These routines deal with dependancies created when IO buffers get
467  * modified.  The caller must call hammer_modify_*() on a referenced
468  * HAMMER structure prior to modifying its on-disk data.
469  *
470  * Any intent to modify an IO buffer acquires the related bp and imposes
471  * various write ordering dependancies.
472  */
473
474 /*
475  * Mark a HAMMER structure as undergoing modification.  Meta-data buffers
476  * are locked until the flusher can deal with them, pure data buffers
477  * can be written out.
478  */
479 static
480 void
481 hammer_io_modify(hammer_io_t io, int count)
482 {
483         struct hammer_mount *hmp = io->hmp;
484
485         /*
486          * io->modify_refs must be >= 0
487          */
488         while (io->modify_refs < 0) {
489                 io->waitmod = 1;
490                 tsleep(io, 0, "hmrmod", 0);
491         }
492
493         /*
494          * Shortcut if nothing to do.
495          */
496         KKASSERT(io->lock.refs != 0 && io->bp != NULL);
497         io->modify_refs += count;
498         if (io->modified && io->released == 0)
499                 return;
500
501         hammer_lock_ex(&io->lock);
502         if (io->modified == 0) {
503                 KKASSERT(io->mod_list == NULL);
504                 switch(io->type) {
505                 case HAMMER_STRUCTURE_VOLUME:
506                         io->mod_list = &hmp->volu_list;
507                         ++hmp->locked_dirty_count;
508                         ++hammer_count_dirtybufs;
509                         break;
510                 case HAMMER_STRUCTURE_META_BUFFER:
511                         io->mod_list = &hmp->meta_list;
512                         ++hmp->locked_dirty_count;
513                         ++hammer_count_dirtybufs;
514                         break;
515                 case HAMMER_STRUCTURE_UNDO_BUFFER:
516                         io->mod_list = &hmp->undo_list;
517                         break;
518                 case HAMMER_STRUCTURE_DATA_BUFFER:
519                         io->mod_list = &hmp->data_list;
520                         break;
521                 }
522                 TAILQ_INSERT_TAIL(io->mod_list, io, mod_entry);
523                 io->modified = 1;
524         }
525         if (io->released) {
526                 regetblk(io->bp);
527                 BUF_KERNPROC(io->bp);
528                 io->released = 0;
529                 KKASSERT(io->modified != 0);
530         }
531         hammer_unlock(&io->lock);
532 }
533
534 static __inline
535 void
536 hammer_io_modify_done(hammer_io_t io)
537 {
538         KKASSERT(io->modify_refs > 0);
539         --io->modify_refs;
540         if (io->modify_refs == 0 && io->waitmod) {
541                 io->waitmod = 0;
542                 wakeup(io);
543         }
544 }
545
546 void
547 hammer_io_write_interlock(hammer_io_t io)
548 {
549         while (io->modify_refs != 0) {
550                 io->waitmod = 1;
551                 tsleep(io, 0, "hmrmod", 0);
552         }
553         io->modify_refs = -1;
554 }
555
556 void
557 hammer_io_done_interlock(hammer_io_t io)
558 {
559         KKASSERT(io->modify_refs == -1);
560         io->modify_refs = 0;
561         if (io->waitmod) {
562                 io->waitmod = 0;
563                 wakeup(io);
564         }
565 }
566
567 /*
568  * Caller intends to modify a volume's ondisk structure.
569  *
570  * This is only allowed if we are the flusher or we have a ref on the
571  * sync_lock.
572  */
573 void
574 hammer_modify_volume(hammer_transaction_t trans, hammer_volume_t volume,
575                      void *base, int len)
576 {
577         KKASSERT (trans == NULL || trans->sync_lock_refs > 0);
578
579         hammer_io_modify(&volume->io, 1);
580         if (len) {
581                 intptr_t rel_offset = (intptr_t)base - (intptr_t)volume->ondisk;
582                 KKASSERT((rel_offset & ~(intptr_t)HAMMER_BUFMASK) == 0);
583                 hammer_generate_undo(trans, &volume->io,
584                          HAMMER_ENCODE_RAW_VOLUME(volume->vol_no, rel_offset),
585                          base, len);
586         }
587 }
588
589 /*
590  * Caller intends to modify a buffer's ondisk structure.
591  *
592  * This is only allowed if we are the flusher or we have a ref on the
593  * sync_lock.
594  */
595 void
596 hammer_modify_buffer(hammer_transaction_t trans, hammer_buffer_t buffer,
597                      void *base, int len)
598 {
599         KKASSERT (trans == NULL || trans->sync_lock_refs > 0);
600
601         hammer_io_modify(&buffer->io, 1);
602         if (len) {
603                 intptr_t rel_offset = (intptr_t)base - (intptr_t)buffer->ondisk;
604                 KKASSERT((rel_offset & ~(intptr_t)HAMMER_BUFMASK) == 0);
605                 hammer_generate_undo(trans, &buffer->io,
606                                      buffer->zone2_offset + rel_offset,
607                                      base, len);
608         }
609 }
610
611 void
612 hammer_modify_volume_done(hammer_volume_t volume)
613 {
614         hammer_io_modify_done(&volume->io);
615 }
616
617 void
618 hammer_modify_buffer_done(hammer_buffer_t buffer)
619 {
620         hammer_io_modify_done(&buffer->io);
621 }
622
623 /*
624  * Mark an entity as not being dirty any more.
625  */
626 void
627 hammer_io_clear_modify(struct hammer_io *io)
628 {
629         if (io->modified) {
630                 KKASSERT(io->mod_list != NULL);
631                 if (io->mod_list == &io->hmp->volu_list ||
632                     io->mod_list == &io->hmp->meta_list) {
633                         --io->hmp->locked_dirty_count;
634                         --hammer_count_dirtybufs;
635                 }
636                 TAILQ_REMOVE(io->mod_list, io, mod_entry);
637                 io->mod_list = NULL;
638                 io->modified = 0;
639         }
640 }
641
642 /*
643  * Clear the IO's modify list.  Even though the IO is no longer modified
644  * it may still be on the lose_list.  This routine is called just before
645  * the governing hammer_buffer is destroyed.
646  */
647 void
648 hammer_io_clear_modlist(struct hammer_io *io)
649 {
650         if (io->mod_list) {
651                 crit_enter();   /* biodone race against list */
652                 KKASSERT(io->mod_list == &io->hmp->lose_list);
653                 TAILQ_REMOVE(io->mod_list, io, mod_entry);
654                 io->mod_list = NULL;
655                 crit_exit();
656         }
657 }
658
659 /************************************************************************
660  *                              HAMMER_BIOOPS                           *
661  ************************************************************************
662  *
663  */
664
665 /*
666  * Pre-IO initiation kernel callback - cluster build only
667  */
668 static void
669 hammer_io_start(struct buf *bp)
670 {
671 }
672
673 /*
674  * Post-IO completion kernel callback - MAY BE CALLED FROM INTERRUPT!
675  *
676  * NOTE: HAMMER may modify a buffer after initiating I/O.  The modified bit
677  * may also be set if we were marking a cluster header open.  Only remove
678  * our dependancy if the modified bit is clear.
679  */
680 static void
681 hammer_io_complete(struct buf *bp)
682 {
683         union hammer_io_structure *iou = (void *)LIST_FIRST(&bp->b_dep);
684
685         KKASSERT(iou->io.released == 1);
686
687         /*
688          * Deal with people waiting for I/O to drain
689          */
690         if (iou->io.running) {
691                 --hammer_count_io_running_write;
692                 if (--iou->io.hmp->io_running_count == 0)
693                         wakeup(&iou->io.hmp->io_running_count);
694                 KKASSERT(iou->io.hmp->io_running_count >= 0);
695                 iou->io.running = 0;
696         }
697
698         if (iou->io.waiting) {
699                 iou->io.waiting = 0;
700                 wakeup(iou);
701         }
702
703         /*
704          * If B_LOCKED is set someone wanted to deallocate the bp at some
705          * point, do it now if refs has become zero.
706          */
707         if ((bp->b_flags & B_LOCKED) && iou->io.lock.refs == 0) {
708                 KKASSERT(iou->io.modified == 0);
709                 --hammer_count_io_locked;
710                 bp->b_flags &= ~B_LOCKED;
711                 hammer_io_deallocate(bp);
712                 /* structure may be dead now */
713         }
714 }
715
716 /*
717  * Callback from kernel when it wishes to deallocate a passively
718  * associated structure.  This mostly occurs with clean buffers
719  * but it may be possible for a holding structure to be marked dirty
720  * while its buffer is passively associated.  The caller owns the bp.
721  *
722  * If we cannot disassociate we set B_LOCKED to prevent the buffer
723  * from getting reused.
724  *
725  * WARNING: Because this can be called directly by getnewbuf we cannot
726  * recurse into the tree.  If a bp cannot be immediately disassociated
727  * our only recourse is to set B_LOCKED.
728  *
729  * WARNING: This may be called from an interrupt via hammer_io_complete()
730  */
731 static void
732 hammer_io_deallocate(struct buf *bp)
733 {
734         hammer_io_structure_t iou = (void *)LIST_FIRST(&bp->b_dep);
735
736         KKASSERT((bp->b_flags & B_LOCKED) == 0 && iou->io.running == 0);
737         if (iou->io.lock.refs > 0 || iou->io.modified) {
738                 /*
739                  * It is not legal to disassociate a modified buffer.  This
740                  * case really shouldn't ever occur.
741                  */
742                 bp->b_flags |= B_LOCKED;
743                 ++hammer_count_io_locked;
744         } else {
745                 /*
746                  * Disassociate the BP.  If the io has no refs left we
747                  * have to add it to the loose list.
748                  */
749                 hammer_io_disassociate(iou, 0);
750                 if (iou->io.bp == NULL && 
751                     iou->io.type != HAMMER_STRUCTURE_VOLUME) {
752                         KKASSERT(iou->io.mod_list == NULL);
753                         crit_enter();   /* biodone race against list */
754                         iou->io.mod_list = &iou->io.hmp->lose_list;
755                         TAILQ_INSERT_TAIL(iou->io.mod_list, &iou->io, mod_entry);
756                         crit_exit();
757                 }
758         }
759 }
760
761 static int
762 hammer_io_fsync(struct vnode *vp)
763 {
764         return(0);
765 }
766
767 /*
768  * NOTE: will not be called unless we tell the kernel about the
769  * bioops.  Unused... we use the mount's VFS_SYNC instead.
770  */
771 static int
772 hammer_io_sync(struct mount *mp)
773 {
774         return(0);
775 }
776
777 static void
778 hammer_io_movedeps(struct buf *bp1, struct buf *bp2)
779 {
780 }
781
782 /*
783  * I/O pre-check for reading and writing.  HAMMER only uses this for
784  * B_CACHE buffers so checkread just shouldn't happen, but if it does
785  * allow it.
786  *
787  * Writing is a different case.  We don't want the kernel to try to write
788  * out a buffer that HAMMER may be modifying passively or which has a
789  * dependancy.  In addition, kernel-demanded writes can only proceed for
790  * certain types of buffers (i.e. UNDO and DATA types).  Other dirty
791  * buffer types can only be explicitly written by the flusher.
792  *
793  * checkwrite will only be called for bdwrite()n buffers.  If we return
794  * success the kernel is guaranteed to initiate the buffer write.
795  */
796 static int
797 hammer_io_checkread(struct buf *bp)
798 {
799         return(0);
800 }
801
802 static int
803 hammer_io_checkwrite(struct buf *bp)
804 {
805         hammer_io_t io = (void *)LIST_FIRST(&bp->b_dep);
806
807         /*
808          * This shouldn't happen under normal operation.
809          */
810         if (io->type == HAMMER_STRUCTURE_VOLUME ||
811             io->type == HAMMER_STRUCTURE_META_BUFFER) {
812                 if (!panicstr)
813                         panic("hammer_io_checkwrite: illegal buffer");
814                 if ((bp->b_flags & B_LOCKED) == 0) {
815                         bp->b_flags |= B_LOCKED;
816                         ++hammer_count_io_locked;
817                 }
818                 return(1);
819         }
820
821         /*
822          * We can only clear the modified bit if the IO is not currently
823          * undergoing modification.  Otherwise we may miss changes.
824          */
825         if (io->modify_refs == 0 && io->modified)
826                 hammer_io_clear_modify(io);
827
828         /*
829          * The kernel is going to start the IO, set io->running.
830          */
831         KKASSERT(io->running == 0);
832         io->running = 1;
833         ++io->hmp->io_running_count;
834         ++hammer_count_io_running_write;
835         return(0);
836 }
837
838 /*
839  * Return non-zero if we wish to delay the kernel's attempt to flush
840  * this buffer to disk.
841  */
842 static int
843 hammer_io_countdeps(struct buf *bp, int n)
844 {
845         return(0);
846 }
847
848 struct bio_ops hammer_bioops = {
849         .io_start       = hammer_io_start,
850         .io_complete    = hammer_io_complete,
851         .io_deallocate  = hammer_io_deallocate,
852         .io_fsync       = hammer_io_fsync,
853         .io_sync        = hammer_io_sync,
854         .io_movedeps    = hammer_io_movedeps,
855         .io_countdeps   = hammer_io_countdeps,
856         .io_checkread   = hammer_io_checkread,
857         .io_checkwrite  = hammer_io_checkwrite,
858 };
859
860 /************************************************************************
861  *                              DIRECT IO OPS                           *
862  ************************************************************************
863  *
864  * These functions operate directly on the buffer cache buffer associated
865  * with a front-end vnode rather then a back-end device vnode.
866  */
867
868 /*
869  * Read a buffer associated with a front-end vnode directly from the
870  * disk media.  The bio may be issued asynchronously.
871  *
872  * This function can takes a zone-2 or zone-X blockmap offset.
873  */
874 int
875 hammer_io_direct_read(hammer_mount_t hmp, hammer_off_t data_offset,
876                       struct bio *bio)
877 {
878         hammer_off_t zone2_offset;
879         hammer_volume_t volume;
880         struct buf *bp;
881         struct bio *nbio;
882         int vol_no;
883         int error;
884
885         if ((data_offset & HAMMER_OFF_ZONE_MASK) == HAMMER_ZONE_RAW_BUFFER) {
886                 zone2_offset = data_offset;
887                 error = 0;
888         } else {
889                 KKASSERT(data_offset >= HAMMER_ZONE_BTREE);
890                 KKASSERT((data_offset & HAMMER_BUFMASK) == 0);
891                 zone2_offset = hammer_blockmap_lookup(hmp, data_offset, &error);
892         }
893         if (error == 0) {
894                 vol_no = HAMMER_VOL_DECODE(zone2_offset);
895                 volume = hammer_get_volume(hmp, vol_no, &error);
896                 if (error == 0 && zone2_offset >= volume->maxbuf_off)
897                         error = EIO;
898                 if (error == 0) {
899                         zone2_offset &= HAMMER_OFF_SHORT_MASK;
900                         nbio = push_bio(bio);
901                         nbio->bio_offset = volume->ondisk->vol_buf_beg +
902                                            zone2_offset;
903                         vn_strategy(volume->devvp, nbio);
904                 }
905                 hammer_rel_volume(volume, 0);
906         }
907         if (error) {
908                 kprintf("hammer_direct_read: failed @ %016llx\n",
909                         data_offset);
910                 bp = bio->bio_buf;
911                 bp->b_error = error;
912                 bp->b_flags |= B_ERROR;
913                 biodone(bio);
914         }
915         return(error);
916 }
917
918 /*
919  * Write a buffer associated with a front-end vnode directly to the
920  * disk media.  The bio may be issued asynchronously.
921  */
922 int
923 hammer_io_direct_write(hammer_mount_t hmp, hammer_btree_leaf_elm_t leaf,
924                        struct bio *bio)
925 {
926         hammer_off_t buf_offset;
927         hammer_off_t zone2_offset;
928         hammer_volume_t volume;
929         hammer_buffer_t buffer;
930         struct buf *bp;
931         struct bio *nbio;
932         char *ptr;
933         int vol_no;
934         int error;
935
936         buf_offset = leaf->data_offset;
937
938         KKASSERT(buf_offset > HAMMER_ZONE_BTREE);
939         KKASSERT(bio->bio_buf->b_cmd == BUF_CMD_WRITE);
940
941         if ((buf_offset & HAMMER_BUFMASK) == 0 &&
942             leaf->data_len == HAMMER_BUFSIZE) {
943                 /*
944                  * We are using the vnode's bio to write directly to the
945                  * media, any hammer_buffer at the same zone-X offset will
946                  * now have stale data.
947                  */
948                 zone2_offset = hammer_blockmap_lookup(hmp, buf_offset, &error);
949                 vol_no = HAMMER_VOL_DECODE(zone2_offset);
950                 volume = hammer_get_volume(hmp, vol_no, &error);
951
952                 if (error == 0 && zone2_offset >= volume->maxbuf_off)
953                         error = EIO;
954                 if (error == 0) {
955                         hammer_del_buffers(hmp, buf_offset,
956                                            zone2_offset, HAMMER_BUFSIZE);
957                         bp = bio->bio_buf;
958                         KKASSERT(bp->b_bufsize == HAMMER_BUFSIZE);
959                         zone2_offset &= HAMMER_OFF_SHORT_MASK;
960
961                         nbio = push_bio(bio);
962                         nbio->bio_offset = volume->ondisk->vol_buf_beg +
963                                            zone2_offset;
964                         vn_strategy(volume->devvp, nbio);
965                 }
966                 hammer_rel_volume(volume, 0);
967         } else {
968                 KKASSERT(((buf_offset ^ (buf_offset + leaf->data_len - 1)) & ~HAMMER_BUFMASK64) == 0);
969                 buffer = NULL;
970                 ptr = hammer_bread(hmp, buf_offset, &error, &buffer);
971                 if (error == 0) {
972                         bp = bio->bio_buf;
973                         bp->b_flags |= B_AGE;
974                         hammer_io_modify(&buffer->io, 1);
975                         bcopy(bp->b_data, ptr, leaf->data_len);
976                         hammer_io_modify_done(&buffer->io);
977                         hammer_rel_buffer(buffer, 0);
978                         bp->b_resid = 0;
979                         biodone(bio);
980                 }
981         }
982         if (error) {
983                 kprintf("hammer_direct_write: failed @ %016llx\n",
984                         leaf->data_offset);
985                 bp = bio->bio_buf;
986                 bp->b_resid = 0;
987                 bp->b_error = EIO;
988                 bp->b_flags |= B_ERROR;
989                 biodone(bio);
990         }
991         return(error);
992 }
993
994