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>
17 #include <afs/bubasics.h>
19 #include "budb_errs.h"
21 #include "budb_internal.h"
23 /* block and structure allocation routines */
25 static int nEntries
[NBLOCKTYPES
];
26 static int sizeEntries
[NBLOCKTYPES
];
34 nEntries
[volFragment_BLOCK
] = NvolFragmentS
;
35 nEntries
[volInfo_BLOCK
] = NvolInfoS
;
36 nEntries
[tape_BLOCK
] = NtapeS
;
37 nEntries
[dump_BLOCK
] = NdumpS
;
39 sizeEntries
[volFragment_BLOCK
] = sizeof(struct vfBlock_frag
);
40 sizeEntries
[volInfo_BLOCK
] = sizeof(struct viBlock_info
);
41 sizeEntries
[tape_BLOCK
] = sizeof(struct tBlock_tape
);
42 sizeEntries
[dump_BLOCK
] = sizeof(struct dBlock_dump
);
48 * allocate a (basic) database block. Extends the database if
49 * no free blocks are available.
51 * 0 - aP points to a cleared block
56 AllocBlock(struct ubik_trans
*ut
,
57 struct block
*block
, /* copy of data */
58 dbadr
*aP
) /* db addr of block */
62 if (db
.h
.freePtrs
[0] == 0) {
63 /* if there are no free blocks, extend the database */
64 LogDebug(2, "AllocBlock: extending db\n");
66 a
= ntohl(db
.h
.eofPtr
);
67 if (set_header_word(ut
, eofPtr
, htonl(a
+ BLOCKSIZE
)))
70 a
= ntohl(db
.h
.freePtrs
[0]);
71 if (dbread(ut
, a
, (char *)block
, sizeof(block
->h
)) /* read hdr */
72 ||set_header_word(ut
, freePtrs
[0], block
->h
.next
) /* set next */
77 /* clear and return the block */
78 memset(block
, 0, sizeof(*block
));
86 * bh - block header ptr. Memory copy of the block header.
87 * a - disk address of the block
91 FreeBlock(struct ubik_trans
*ut
,
92 struct blockHeader
*bh
, /* copy of data */
93 dbadr a
) /* db address of block */
95 if (a
!= BlockBase(a
))
96 db_panic("Block addr no good");
97 memset(bh
, 0, sizeof(*bh
));
98 bh
->next
= db
.h
.freePtrs
[0];
99 if (set_header_word(ut
, freePtrs
[0], htonl(a
))
100 || dbwrite(ut
, a
, (char *)bh
, sizeof(*bh
)))
108 * type - type of structure to allocate
109 * related - address of related block
110 * saP - db addr of structure
115 AllocStructure(struct ubik_trans
*ut
, char type
, dbadr related
, dbadr
*saP
, void *s
)
117 dbadr a
; /* block addr */
118 struct block b
; /* copy of data */
119 int i
; /* block structure array index */
120 afs_int32
*bs
; /* ptr to first word of structure */
124 || (type
> MAX_STRUCTURE_BLOCK_TYPE
)
126 db_panic("bad structure type");
128 bs
= (afs_int32
*) b
.a
; /* ptr to first structure of block */
130 if (db
.h
.freePtrs
[(int) type
] == 0) {
131 /* no free items of specified type */
133 if (AllocBlock(ut
, &b
, &a
)
134 || set_header_word(ut
, freePtrs
[(int) type
], htonl(a
))
142 b
.h
.nFree
= ntohs(nEntries
[(int) type
] - 1);
143 *bs
= 1; /* not free anymore */
145 if (dbwrite(ut
, a
, (char *)&b
, sizeof(b
)))
147 LogDebug(2, "AllocStructure: allocated new block\n");
151 /* Only do 10 (or so) at a time, to avoid transactions which modify
156 a
= ntohl(db
.h
.freePtrs
[(int) type
]);
157 if (dbread(ut
, a
, (char *)&b
, sizeof(b
)))
160 nFree
= ntohs(b
.h
.nFree
);
162 db_panic("nFree is zero");
164 /* Completely empty blocks go to generic free list if there are
165 * more blocks on this free list
167 if (b
.h
.next
&& (nFree
== nEntries
[(int) type
]) && (count
-- > 0)) {
168 if (set_header_word(ut
, freePtrs
[(int) type
], b
.h
.next
)
169 || FreeBlock(ut
, &b
.h
, a
)
173 LogDebug(2, "AllocStrucure: add to free block list\n");
175 /* we found a free structure */
177 /* if last free one: unthread block */
178 if (set_header_word(ut
, freePtrs
[(int) type
], b
.h
.next
))
185 /* find the free structure - arbitrarily uses first word as
186 * allocated/free status. PA.
191 bs
= (afs_int32
*) ((char *)bs
+ sizeEntries
[(int) type
]);
194 if (i
>= nEntries
[(int) type
])
195 db_panic("free count inconsistent with block");
197 b
.h
.nFree
= htons(nFree
- 1);
198 if (dbwrite(ut
, a
, (char *)&b
, sizeof(b
.h
)))
201 *(afs_int32
*) s
= 1; /* make sure structure is not free */
202 *saP
= a
+ ((char *)bs
- (char *)&b
);
204 LogDebug(3, "allocated at %d, block at %d, offset %ld\n", *saP
, a
,
205 (long int)((char *)bs
- (char *)&b
));
206 /* caller must write back at least first word of structure */
213 FreeStructure(struct ubik_trans
*ut
,
214 char type
, /* type of structure to allocate */
215 dbadr sa
) /* db addr of structure */
217 struct blockHeader bh
; /* header of containing block */
218 dbadr a
; /* db address of block */
219 int nFree
; /* new free structures count */
222 if ((type
== 0) || (type
> MAX_STRUCTURE_BLOCK_TYPE
))
223 db_panic("bad structure type");
226 if (dbread(ut
, a
, (char *)&bh
, sizeof(bh
)))
229 db_panic("block and structure of different types");
231 bh
.nFree
= htons(nFree
= ntohs(bh
.nFree
) + 1);
232 if (nFree
> nEntries
[(int) type
])
233 db_panic("free count too large");
234 if (nFree
== 1) { /* add to free list for type */
235 bh
.next
= db
.h
.freePtrs
[(int) type
];
236 if (set_header_word(ut
, freePtrs
[(int) type
], htonl(a
)))
240 /* mark the structure as free, and write out block header */
241 if (set_word_offset(ut
, sa
, &freeWord
, 0, 0)
242 || dbwrite(ut
, a
, (char *)&bh
, sizeof(bh
)))