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>
28 #include <sys/types.h>
31 #include <afs/bubasics.h>
32 #include "budb_errs.h"
36 /* block and structure allocation routines */
38 static int nEntries[NBLOCKTYPES];
39 static int sizeEntries[NBLOCKTYPES];
47 nEntries[volFragment_BLOCK] = NvolFragmentS;
48 nEntries[volInfo_BLOCK] = NvolInfoS;
49 nEntries[tape_BLOCK] = NtapeS;
50 nEntries[dump_BLOCK] = NdumpS;
52 sizeEntries[volFragment_BLOCK] = sizeof(((struct vfBlock *) NULL)->a[0]);
53 sizeEntries[volInfo_BLOCK] = sizeof(((struct viBlock *) NULL)->a[0]);
54 sizeEntries[tape_BLOCK] = sizeof(((struct tBlock *) NULL)->a[0]);
55 sizeEntries[dump_BLOCK] = sizeof(((struct dBlock *) NULL)->a[0]);
61 * allocate a (basic) database block. Extends the database if
62 * no free blocks are available.
64 * 0 - aP points to a cleared block
69 AllocBlock(ut, block, aP)
70 struct ubik_trans *ut;
71 struct block *block; /* copy of data */
72 dbadr *aP; /* db addr of block */
76 if (db.h.freePtrs[0] == 0) {
77 /* if there are no free blocks, extend the database */
78 LogDebug(2, "AllocBlock: extending db\n");
80 a = ntohl(db.h.eofPtr);
81 if (set_header_word(ut, eofPtr, htonl(a + BLOCKSIZE)))
84 a = ntohl(db.h.freePtrs[0]);
85 if (dbread(ut, a, (char *)block, sizeof(block->h)) /* read hdr */
86 ||set_header_word(ut, freePtrs[0], block->h.next) /* set next */
91 /* clear and return the block */
92 memset(block, 0, sizeof(*block));
100 * bh - block header ptr. Memory copy of the block header.
101 * a - disk address of the block
106 struct ubik_trans *ut;
107 struct blockHeader *bh; /* copy of data */
108 dbadr a; /* db address of block */
110 if (a != BlockBase(a))
111 db_panic("Block addr no good");
112 memset(bh, 0, sizeof(*bh));
113 bh->next = db.h.freePtrs[0];
114 if (set_header_word(ut, freePtrs[0], htonl(a))
115 || dbwrite(ut, a, (char *)bh, sizeof(*bh)))
123 * type - type of structure to allocate
124 * related - address of related block
125 * saP - db addr of structure
130 AllocStructure(ut, type, related, saP, s)
131 struct ubik_trans *ut;
137 dbadr a; /* block addr */
138 struct block b; /* copy of data */
139 int i; /* block structure array index */
140 afs_int32 *bs; /* ptr to first word of structure */
144 || (type > MAX_STRUCTURE_BLOCK_TYPE)
146 db_panic("bad structure type");
148 bs = (afs_int32 *) b.a; /* ptr to first structure of block */
150 if (db.h.freePtrs[type] == 0) {
151 /* no free items of specified type */
153 if (AllocBlock(ut, &b, &a)
154 || set_header_word(ut, freePtrs[type], htonl(a))
162 b.h.nFree = ntohs(nEntries[type] - 1);
163 *bs = 1; /* not free anymore */
165 if (dbwrite(ut, a, (char *)&b, sizeof(b)))
167 LogDebug(2, "AllocStructure: allocated new block\n");
171 /* Only do 10 (or so) at a time, to avoid transactions which modify
176 a = ntohl(db.h.freePtrs[type]);
177 if (dbread(ut, a, (char *)&b, sizeof(b)))
180 nFree = ntohs(b.h.nFree);
182 db_panic("nFree is zero");
184 /* Completely empty blocks go to generic free list if there are
185 * more blocks on this free list
187 if (b.h.next && (nFree == nEntries[type]) && (count-- > 0)) {
188 if (set_header_word(ut, freePtrs[type], b.h.next)
189 || FreeBlock(ut, &b.h, a)
193 LogDebug(2, "AllocStrucure: add to free block list\n");
195 /* we found a free structure */
197 /* if last free one: unthread block */
198 if (set_header_word(ut, freePtrs[type], b.h.next))
205 /* find the free structure - arbitrarily uses first word as
206 * allocated/free status. PA.
211 bs = (afs_int32 *) ((char *)bs + sizeEntries[type]);
214 if (i >= nEntries[type])
215 db_panic("free count inconsistent with block");
217 b.h.nFree = htons(nFree - 1);
218 if (dbwrite(ut, a, (char *)&b, sizeof(b.h)))
221 *(afs_int32 *) s = 1; /* make sure structure is not free */
222 *saP = a + ((char *)bs - (char *)&b);
224 LogDebug(3, "allocated at %d, block at %d, offset %d\n", *saP, a,
225 ((char *)bs - (char *)&b));
226 /* caller must write back at least first word of structure */
233 FreeStructure(ut, type, sa)
234 struct ubik_trans *ut;
235 char type; /* type of structure to allocate */
236 dbadr sa; /* db addr of structure */
238 struct blockHeader bh; /* header of containing block */
239 dbadr a; /* db address of block */
240 int nFree; /* new free structures count */
243 if ((type == 0) || (type > MAX_STRUCTURE_BLOCK_TYPE))
244 db_panic("bad structure type");
247 if (dbread(ut, a, (char *)&bh, sizeof(bh)))
250 db_panic("block and structure of different types");
252 bh.nFree = htons(nFree = ntohs(bh.nFree) + 1);
253 if (nFree > nEntries[type])
254 db_panic("free count too large");
255 if (nFree == 1) { /* add to free list for type */
256 bh.next = db.h.freePtrs[type];
257 if (set_header_word(ut, freePtrs[type], htonl(a)))
261 /* mark the structure as free, and write out block header */
262 if (set_word_offset(ut, sa, &freeWord, 0, 0)
263 || dbwrite(ut, a, (char *)&bh, sizeof(bh)))