forked from openafs/openafs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb_alloc.c
250 lines (211 loc) · 6.31 KB
/
db_alloc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
*
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
#include <afsconfig.h>
#include <afs/param.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif
#include <string.h>
#include <sys/types.h>
#include <afs/stds.h>
#include <ubik.h>
#include <afs/bubasics.h>
#include "budb_errs.h"
#include "database.h"
#include "budb_internal.h"
/* block and structure allocation routines */
static int nEntries[NBLOCKTYPES];
static int sizeEntries[NBLOCKTYPES];
afs_int32
InitDBalloc(void)
{
nEntries[0] = 0;
sizeEntries[0] = 0;
nEntries[volFragment_BLOCK] = NvolFragmentS;
nEntries[volInfo_BLOCK] = NvolInfoS;
nEntries[tape_BLOCK] = NtapeS;
nEntries[dump_BLOCK] = NdumpS;
sizeEntries[volFragment_BLOCK] = sizeof(((struct vfBlock *) NULL)->a[0]);
sizeEntries[volInfo_BLOCK] = sizeof(((struct viBlock *) NULL)->a[0]);
sizeEntries[tape_BLOCK] = sizeof(((struct tBlock *) NULL)->a[0]);
sizeEntries[dump_BLOCK] = sizeof(((struct dBlock *) NULL)->a[0]);
return 0;
}
/* AllocBlock
* allocate a (basic) database block. Extends the database if
* no free blocks are available.
* exit:
* 0 - aP points to a cleared block
* n - error
*/
afs_int32
AllocBlock(struct ubik_trans *ut,
struct block *block, /* copy of data */
dbadr *aP) /* db addr of block */
{
dbadr a;
if (db.h.freePtrs[0] == 0) {
/* if there are no free blocks, extend the database */
LogDebug(2, "AllocBlock: extending db\n");
a = ntohl(db.h.eofPtr);
if (set_header_word(ut, eofPtr, htonl(a + BLOCKSIZE)))
return BUDB_IO;
} else {
a = ntohl(db.h.freePtrs[0]);
if (dbread(ut, a, (char *)block, sizeof(block->h)) /* read hdr */
||set_header_word(ut, freePtrs[0], block->h.next) /* set next */
)
return BUDB_IO;
}
/* clear and return the block */
memset(block, 0, sizeof(*block));
*aP = a;
return 0;
}
/* FreeBlock
* Free a basic block
* entry:
* bh - block header ptr. Memory copy of the block header.
* a - disk address of the block
*/
afs_int32
FreeBlock(struct ubik_trans *ut,
struct blockHeader *bh, /* copy of data */
dbadr a) /* db address of block */
{
if (a != BlockBase(a))
db_panic("Block addr no good");
memset(bh, 0, sizeof(*bh));
bh->next = db.h.freePtrs[0];
if (set_header_word(ut, freePtrs[0], htonl(a))
|| dbwrite(ut, a, (char *)bh, sizeof(*bh)))
return BUDB_IO;
return 0;
}
/* AllocStructure
* entry:
* type - type of structure to allocate
* related - address of related block
* saP - db addr of structure
* s - structure data
*/
afs_int32
AllocStructure(struct ubik_trans *ut, char type, dbadr related, dbadr *saP, void *s)
{
dbadr a; /* block addr */
struct block b; /* copy of data */
int i; /* block structure array index */
afs_int32 *bs; /* ptr to first word of structure */
int nFree;
if ((type == 0)
|| (type > MAX_STRUCTURE_BLOCK_TYPE)
) {
db_panic("bad structure type");
}
bs = (afs_int32 *) b.a; /* ptr to first structure of block */
if (db.h.freePtrs[(int) type] == 0) {
/* no free items of specified type */
if (AllocBlock(ut, &b, &a)
|| set_header_word(ut, freePtrs[(int) type], htonl(a))
) {
return BUDB_IO;
}
b.h.next = 0;
b.h.type = type;
b.h.flags = 0;
b.h.nFree = ntohs(nEntries[(int) type] - 1);
*bs = 1; /* not free anymore */
if (dbwrite(ut, a, (char *)&b, sizeof(b)))
return BUDB_IO;
LogDebug(2, "AllocStructure: allocated new block\n");
} else {
int count = 10;
/* Only do 10 (or so) at a time, to avoid transactions which modify
* many buffer.
*/
while (1) {
a = ntohl(db.h.freePtrs[(int) type]);
if (dbread(ut, a, (char *)&b, sizeof(b)))
return BUDB_IO;
nFree = ntohs(b.h.nFree);
if (nFree == 0)
db_panic("nFree is zero");
/* Completely empty blocks go to generic free list if there are
* more blocks on this free list
*/
if (b.h.next && (nFree == nEntries[(int) type]) && (count-- > 0)) {
if (set_header_word(ut, freePtrs[(int) type], b.h.next)
|| FreeBlock(ut, &b.h, a)
) {
return BUDB_IO;
}
LogDebug(2, "AllocStrucure: add to free block list\n");
} else {
/* we found a free structure */
if (nFree == 1) {
/* if last free one: unthread block */
if (set_header_word(ut, freePtrs[(int) type], b.h.next))
return BUDB_IO;
}
break;
}
}
/* find the free structure - arbitrarily uses first word as
* allocated/free status. PA.
*/
i = 0;
while (*bs) {
i++;
bs = (afs_int32 *) ((char *)bs + sizeEntries[(int) type]);
}
if (i >= nEntries[(int) type])
db_panic("free count inconsistent with block");
b.h.nFree = htons(nFree - 1);
if (dbwrite(ut, a, (char *)&b, sizeof(b.h)))
return BUDB_IO;
}
*(afs_int32 *) s = 1; /* make sure structure is not free */
*saP = a + ((char *)bs - (char *)&b);
LogDebug(3, "allocated at %d, block at %d, offset %ld\n", *saP, a,
(long int)((char *)bs - (char *)&b));
/* caller must write back at least first word of structure */
return 0;
}
afs_int32
FreeStructure(struct ubik_trans *ut,
char type, /* type of structure to allocate */
dbadr sa) /* db addr of structure */
{
struct blockHeader bh; /* header of containing block */
dbadr a; /* db address of block */
int nFree; /* new free structures count */
afs_int32 freeWord;
if ((type == 0) || (type > MAX_STRUCTURE_BLOCK_TYPE))
db_panic("bad structure type");
a = BlockBase(sa);
if (dbread(ut, a, (char *)&bh, sizeof(bh)))
return BUDB_IO;
if (type != bh.type)
db_panic("block and structure of different types");
bh.nFree = htons(nFree = ntohs(bh.nFree) + 1);
if (nFree > nEntries[(int) type])
db_panic("free count too large");
if (nFree == 1) { /* add to free list for type */
bh.next = db.h.freePtrs[(int) type];
if (set_header_word(ut, freePtrs[(int) type], htonl(a)))
return BUDB_IO;
}
/* mark the structure as free, and write out block header */
if (set_word_offset(ut, sa, &freeWord, 0, 0)
|| dbwrite(ut, a, (char *)&bh, sizeof(bh)))
return BUDB_IO;
return 0;
}