hammer2 - more indirect block work, add advlock
[dragonfly.git] / sys / vfs / hammer2 / hammer2_freemap.c
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name of The DragonFly Project nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific, prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/fcntl.h>
39 #include <sys/buf.h>
40 #include <sys/proc.h>
41 #include <sys/namei.h>
42 #include <sys/mount.h>
43 #include <sys/vnode.h>
44 #include <sys/mountctl.h>
45
46 #include "hammer2.h"
47
48 int
49 hammer2_freemap_bytes_to_radix(size_t bytes)
50 {
51         int radix;
52
53         if (bytes < HAMMER2_MIN_ALLOC)
54                 bytes = HAMMER2_MIN_ALLOC;
55         if (bytes == HAMMER2_PBUFSIZE)
56                 radix = HAMMER2_PBUFRADIX;
57         else if (bytes >= 1024)
58                 radix = 10;
59         else
60                 radix = HAMMER2_MIN_RADIX;
61
62         while (((size_t)1 << radix) < bytes)
63                 ++radix;
64         return (radix);
65 }
66
67 /*
68  * Allocate media space, returning a combined data offset and radix.
69  *
70  * XXX when diving a new full block create a clean empty buffer and bqrelse()
71  *     it, so small data structures do not have to issue read-IO when they
72  *     do the read-modify-write on the backing store.
73  */
74 hammer2_off_t
75 hammer2_freemap_alloc(hammer2_mount_t *hmp, size_t bytes)
76 {
77         hammer2_off_t data_off;
78         hammer2_off_t data_next;
79         int radix;
80
81         /*
82          * Figure out the base 2 radix of the allocation (rounded up)
83          */
84         radix = hammer2_freemap_bytes_to_radix(bytes);
85         bytes = 1 << radix;
86
87         if (radix < HAMMER2_MAX_RADIX && hmp->freecache[radix]) {
88                 /*
89                  * Allocate from our packing cache
90                  */
91                 data_off = hmp->freecache[radix];
92                 hmp->freecache[radix] += bytes;
93                 if ((hmp->freecache[radix] & HAMMER2_PBUFMASK) == 0)
94                         hmp->freecache[radix] = 0;
95         } else {
96                 /*
97                  * Allocate from the allocation iterator using a PBUFSIZE
98                  * aligned block and reload the packing cache if possible.
99                  */
100                 data_off = hmp->voldata.allocator_beg;
101                 data_off = (data_off + HAMMER2_PBUFMASK64) &
102                            ~HAMMER2_PBUFMASK64;
103                 data_next = data_off + bytes;
104
105                 if ((data_next & HAMMER2_PBUFMASK) == 0) {
106                         hmp->voldata.allocator_beg = data_next;
107                 } else {
108                         KKASSERT(radix < HAMMER2_MAX_RADIX);
109                         hmp->voldata.allocator_beg =
110                                         (data_next + HAMMER2_PBUFMASK64) &
111                                         ~HAMMER2_PBUFMASK64;
112                         hmp->freecache[radix] = data_next;
113                 }
114         }
115         if (hammer2_debug & 0x0001) {
116                 kprintf("hammer2: allocate %016jx: %zd\n",
117                         (intmax_t)data_off, bytes);
118         }
119         return (data_off | radix);
120 }
121
122 #if 0
123 /*
124  * Allocate media space, returning a combined data offset and radix.
125  * Also return the related (device) buffer cache buffer.
126  */
127 hammer2_off_t
128 hammer2_freemap_alloc_bp(hammer2_mount_t *hmp, size_t bytes, struct buf **bpp)
129 {
130 }
131
132 #endif