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