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>
18 #include <netinet/in.h>
21 #include <sys/types.h>
24 #include <afs/bubasics.h>
25 #include "budb_errs.h"
27 #include "budb_internal.h"
29 /* block and structure allocation routines */
31 static int nEntries[NBLOCKTYPES];
32 static int sizeEntries[NBLOCKTYPES];
40 nEntries[volFragment_BLOCK] = NvolFragmentS;
41 nEntries[volInfo_BLOCK] = NvolInfoS;
42 nEntries[tape_BLOCK] = NtapeS;
43 nEntries[dump_BLOCK] = NdumpS;
45 sizeEntries[volFragment_BLOCK] = sizeof(((struct vfBlock *) NULL)->a[0]);
46 sizeEntries[volInfo_BLOCK] = sizeof(((struct viBlock *) NULL)->a[0]);
47 sizeEntries[tape_BLOCK] = sizeof(((struct tBlock *) NULL)->a[0]);
48 sizeEntries[dump_BLOCK] = sizeof(((struct dBlock *) NULL)->a[0]);
54 * allocate a (basic) database block. Extends the database if
55 * no free blocks are available.
57 * 0 - aP points to a cleared block
62 AllocBlock(struct ubik_trans *ut,
63 struct block *block, /* copy of data */
64 dbadr *aP) /* db addr of block */
68 if (db.h.freePtrs[0] == 0) {
69 /* if there are no free blocks, extend the database */
70 LogDebug(2, "AllocBlock: extending db\n");
72 a = ntohl(db.h.eofPtr);
73 if (set_header_word(ut, eofPtr, htonl(a + BLOCKSIZE)))
76 a = ntohl(db.h.freePtrs[0]);
77 if (dbread(ut, a, (char *)block, sizeof(block->h)) /* read hdr */
78 ||set_header_word(ut, freePtrs[0], block->h.next) /* set next */
83 /* clear and return the block */
84 memset(block, 0, sizeof(*block));
92 * bh - block header ptr. Memory copy of the block header.
93 * a - disk address of the block
97 FreeBlock(struct ubik_trans *ut,
98 struct blockHeader *bh, /* copy of data */
99 dbadr a) /* db address of block */
101 if (a != BlockBase(a))
102 db_panic("Block addr no good");
103 memset(bh, 0, sizeof(*bh));
104 bh->next = db.h.freePtrs[0];
105 if (set_header_word(ut, freePtrs[0], htonl(a))
106 || dbwrite(ut, a, (char *)bh, sizeof(*bh)))
114 * type - type of structure to allocate
115 * related - address of related block
116 * saP - db addr of structure
121 AllocStructure(struct ubik_trans *ut, char type, dbadr related, dbadr *saP, void *s)
123 dbadr a; /* block addr */
124 struct block b; /* copy of data */
125 int i; /* block structure array index */
126 afs_int32 *bs; /* ptr to first word of structure */
130 || (type > MAX_STRUCTURE_BLOCK_TYPE)
132 db_panic("bad structure type");
134 bs = (afs_int32 *) b.a; /* ptr to first structure of block */
136 if (db.h.freePtrs[(int) type] == 0) {
137 /* no free items of specified type */
139 if (AllocBlock(ut, &b, &a)
140 || set_header_word(ut, freePtrs[(int) type], htonl(a))
148 b.h.nFree = ntohs(nEntries[(int) type] - 1);
149 *bs = 1; /* not free anymore */
151 if (dbwrite(ut, a, (char *)&b, sizeof(b)))
153 LogDebug(2, "AllocStructure: allocated new block\n");
157 /* Only do 10 (or so) at a time, to avoid transactions which modify
162 a = ntohl(db.h.freePtrs[(int) type]);
163 if (dbread(ut, a, (char *)&b, sizeof(b)))
166 nFree = ntohs(b.h.nFree);
168 db_panic("nFree is zero");
170 /* Completely empty blocks go to generic free list if there are
171 * more blocks on this free list
173 if (b.h.next && (nFree == nEntries[(int) type]) && (count-- > 0)) {
174 if (set_header_word(ut, freePtrs[(int) type], b.h.next)
175 || FreeBlock(ut, &b.h, a)
179 LogDebug(2, "AllocStrucure: add to free block list\n");
181 /* we found a free structure */
183 /* if last free one: unthread block */
184 if (set_header_word(ut, freePtrs[(int) type], b.h.next))
191 /* find the free structure - arbitrarily uses first word as
192 * allocated/free status. PA.
197 bs = (afs_int32 *) ((char *)bs + sizeEntries[(int) type]);
200 if (i >= nEntries[(int) type])
201 db_panic("free count inconsistent with block");
203 b.h.nFree = htons(nFree - 1);
204 if (dbwrite(ut, a, (char *)&b, sizeof(b.h)))
207 *(afs_int32 *) s = 1; /* make sure structure is not free */
208 *saP = a + ((char *)bs - (char *)&b);
210 LogDebug(3, "allocated at %d, block at %d, offset %ld\n", *saP, a,
211 (long int)((char *)bs - (char *)&b));
212 /* caller must write back at least first word of structure */
219 FreeStructure(struct ubik_trans *ut,
220 char type, /* type of structure to allocate */
221 dbadr sa) /* db addr of structure */
223 struct blockHeader bh; /* header of containing block */
224 dbadr a; /* db address of block */
225 int nFree; /* new free structures count */
228 if ((type == 0) || (type > MAX_STRUCTURE_BLOCK_TYPE))
229 db_panic("bad structure type");
232 if (dbread(ut, a, (char *)&bh, sizeof(bh)))
235 db_panic("block and structure of different types");
237 bh.nFree = htons(nFree = ntohs(bh.nFree) + 1);
238 if (nFree > nEntries[(int) type])
239 db_panic("free count too large");
240 if (nFree == 1) { /* add to free list for type */
241 bh.next = db.h.freePtrs[(int) type];
242 if (set_header_word(ut, freePtrs[(int) type], htonl(a)))
246 /* mark the structure as free, and write out block header */
247 if (set_word_offset(ut, sa, &freeWord, 0, 0)
248 || dbwrite(ut, a, (char *)&bh, sizeof(bh)))