2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
19 #include <netinet/in.h>
22 #include <sys/types.h>
25 #include <afs/bubasics.h>
26 #include "budb_errs.h"
30 /* block and structure allocation routines */
32 static int nEntries[NBLOCKTYPES];
33 static int sizeEntries[NBLOCKTYPES];
41 nEntries[volFragment_BLOCK] = NvolFragmentS;
42 nEntries[volInfo_BLOCK] = NvolInfoS;
43 nEntries[tape_BLOCK] = NtapeS;
44 nEntries[dump_BLOCK] = NdumpS;
46 sizeEntries[volFragment_BLOCK] = sizeof(((struct vfBlock *) NULL)->a[0]);
47 sizeEntries[volInfo_BLOCK] = sizeof(((struct viBlock *) NULL)->a[0]);
48 sizeEntries[tape_BLOCK] = sizeof(((struct tBlock *) NULL)->a[0]);
49 sizeEntries[dump_BLOCK] = sizeof(((struct dBlock *) NULL)->a[0]);
55 * allocate a (basic) database block. Extends the database if
56 * no free blocks are available.
58 * 0 - aP points to a cleared block
63 AllocBlock(ut, block, aP)
64 struct ubik_trans *ut;
65 struct block *block; /* copy of data */
66 dbadr *aP; /* db addr of block */
70 if (db.h.freePtrs[0] == 0) {
71 /* if there are no free blocks, extend the database */
72 LogDebug(2, "AllocBlock: extending db\n");
74 a = ntohl(db.h.eofPtr);
75 if (set_header_word(ut, eofPtr, htonl(a + BLOCKSIZE)))
78 a = ntohl(db.h.freePtrs[0]);
79 if (dbread(ut, a, (char *)block, sizeof(block->h)) /* read hdr */
80 ||set_header_word(ut, freePtrs[0], block->h.next) /* set next */
85 /* clear and return the block */
86 memset(block, 0, sizeof(*block));
94 * bh - block header ptr. Memory copy of the block header.
95 * a - disk address of the block
100 struct ubik_trans *ut;
101 struct blockHeader *bh; /* copy of data */
102 dbadr a; /* db address of block */
104 if (a != BlockBase(a))
105 db_panic("Block addr no good");
106 memset(bh, 0, sizeof(*bh));
107 bh->next = db.h.freePtrs[0];
108 if (set_header_word(ut, freePtrs[0], htonl(a))
109 || dbwrite(ut, a, (char *)bh, sizeof(*bh)))
117 * type - type of structure to allocate
118 * related - address of related block
119 * saP - db addr of structure
124 AllocStructure(ut, type, related, saP, s)
125 struct ubik_trans *ut;
131 dbadr a; /* block addr */
132 struct block b; /* copy of data */
133 int i; /* block structure array index */
134 afs_int32 *bs; /* ptr to first word of structure */
138 || (type > MAX_STRUCTURE_BLOCK_TYPE)
140 db_panic("bad structure type");
142 bs = (afs_int32 *) b.a; /* ptr to first structure of block */
144 if (db.h.freePtrs[type] == 0) {
145 /* no free items of specified type */
147 if (AllocBlock(ut, &b, &a)
148 || set_header_word(ut, freePtrs[type], htonl(a))
156 b.h.nFree = ntohs(nEntries[type] - 1);
157 *bs = 1; /* not free anymore */
159 if (dbwrite(ut, a, (char *)&b, sizeof(b)))
161 LogDebug(2, "AllocStructure: allocated new block\n");
165 /* Only do 10 (or so) at a time, to avoid transactions which modify
170 a = ntohl(db.h.freePtrs[type]);
171 if (dbread(ut, a, (char *)&b, sizeof(b)))
174 nFree = ntohs(b.h.nFree);
176 db_panic("nFree is zero");
178 /* Completely empty blocks go to generic free list if there are
179 * more blocks on this free list
181 if (b.h.next && (nFree == nEntries[type]) && (count-- > 0)) {
182 if (set_header_word(ut, freePtrs[type], b.h.next)
183 || FreeBlock(ut, &b.h, a)
187 LogDebug(2, "AllocStrucure: add to free block list\n");
189 /* we found a free structure */
191 /* if last free one: unthread block */
192 if (set_header_word(ut, freePtrs[type], b.h.next))
199 /* find the free structure - arbitrarily uses first word as
200 * allocated/free status. PA.
205 bs = (afs_int32 *) ((char *)bs + sizeEntries[type]);
208 if (i >= nEntries[type])
209 db_panic("free count inconsistent with block");
211 b.h.nFree = htons(nFree - 1);
212 if (dbwrite(ut, a, (char *)&b, sizeof(b.h)))
215 *(afs_int32 *) s = 1; /* make sure structure is not free */
216 *saP = a + ((char *)bs - (char *)&b);
218 LogDebug(3, "allocated at %d, block at %d, offset %d\n", *saP, a,
219 ((char *)bs - (char *)&b));
220 /* caller must write back at least first word of structure */
227 FreeStructure(ut, type, sa)
228 struct ubik_trans *ut;
229 char type; /* type of structure to allocate */
230 dbadr sa; /* db addr of structure */
232 struct blockHeader bh; /* header of containing block */
233 dbadr a; /* db address of block */
234 int nFree; /* new free structures count */
237 if ((type == 0) || (type > MAX_STRUCTURE_BLOCK_TYPE))
238 db_panic("bad structure type");
241 if (dbread(ut, a, (char *)&bh, sizeof(bh)))
244 db_panic("block and structure of different types");
246 bh.nFree = htons(nFree = ntohs(bh.nFree) + 1);
247 if (nFree > nEntries[type])
248 db_panic("free count too large");
249 if (nFree == 1) { /* add to free list for type */
250 bh.next = db.h.freePtrs[type];
251 if (set_header_word(ut, freePtrs[type], htonl(a)))
255 /* mark the structure as free, and write out block header */
256 if (set_word_offset(ut, sa, &freeWord, 0, 0)
257 || dbwrite(ut, a, (char *)&bh, sizeof(bh)))