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 <afs/afsutil.h>
20 #define UBIK_INTERNALS 1
24 * These routines are called via the proc ptr in the ubik_dbase structure. They provide access to
25 * the physical disk, by converting the file numbers being processed ( >= 0 for user data space, < 0
26 * for ubik system files, such as the log) to actual pathnames to open, read, write, truncate, sync,
31 static struct fdcache {
35 } fdcache[MAXFDCACHE];
37 static char pbuffer[1024];
40 * \warning Beware, when using this function, of the header in front of most files.
43 uphys_open(struct ubik_dbase *adbase, afs_int32 afid)
49 struct fdcache *bestfd;
51 /* initialize package */
55 for (i = 0; i < MAXFDCACHE; tfd++, i++) {
56 tfd->fd = -1; /* invalid value */
57 tfd->fileID = -10000; /* invalid value */
62 /* scan file descr cache */
63 for (tfd = fdcache, i = 0; i < MAXFDCACHE; i++, tfd++) {
64 if (afid == tfd->fileID && tfd->refCount == 0) { /* don't use open fd */
65 lseek(tfd->fd, 0, 0); /* reset ptr just like open would have */
71 /* not found, open it and try to enter in cache */
72 snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d", adbase->pathName,
73 (afid<0)?"SYS":"", (afid<0)?-afid:afid);
74 fd = open(pbuffer, O_CREAT | O_RDWR, 0600);
76 /* try opening read-only */
77 fd = open(pbuffer, O_RDONLY, 0);
82 /* enter it in the cache */
85 for (i = 0; i < MAXFDCACHE; i++, tfd++) { /* look for empty slot */
91 if (!bestfd) { /* look for reclaimable slot */
93 for (i = 0; i < MAXFDCACHE; i++, tfd++) {
94 if (tfd->refCount == 0) {
100 if (bestfd) { /* found a usable slot */
105 tfd->refCount = 1; /* us */
109 /* finally, we're done */
114 * \brief Close the file, maintaining ref count in cache structure.
125 for (i = 0; i < MAXFDCACHE; i++, tfd++) {
126 if (tfd->fd == afd) {
127 if (tfd->fileID != -10000) {
131 if (tfd->refCount > 0) {
133 if (tfd->refCount == 0) {
148 uphys_stat(struct ubik_dbase *adbase, afs_int32 afid, struct ubik_stat *astat)
154 fd = uphys_open(adbase, afid);
157 code = fstat(fd, &tstat);
162 code = tstat.st_size - HDRSIZE;
171 uphys_read(struct ubik_dbase *adbase, afs_int32 afile,
172 void *abuffer, afs_int32 apos, afs_int32 alength)
177 fd = uphys_open(adbase, afile);
180 code = lseek(fd, apos + HDRSIZE, 0);
185 code = read(fd, abuffer, alength);
191 uphys_write(struct ubik_dbase *adbase, afs_int32 afile,
192 void *abuffer, afs_int32 apos, afs_int32 alength)
198 fd = uphys_open(adbase, afile);
201 code = lseek(fd, apos + HDRSIZE, 0);
206 length = write(fd, abuffer, alength);
207 code = uphys_close(fd);
215 uphys_truncate(struct ubik_dbase *adbase, afs_int32 afile,
219 fd = uphys_open(adbase, afile);
222 code = ftruncate(fd, asize + HDRSIZE);
228 * \brief Get number of dbase files.
230 * \todo Really should scan dir for data.
233 uphys_getnfiles(struct ubik_dbase *adbase)
235 /* really should scan dir for data */
240 * \brief Get database label, with \p aversion in host order.
243 uphys_getlabel(struct ubik_dbase *adbase, afs_int32 afile,
244 struct ubik_version *aversion)
246 struct ubik_hdr thdr;
249 fd = uphys_open(adbase, afile);
252 code = read(fd, &thdr, sizeof(thdr));
253 if (code != sizeof(thdr)) {
257 aversion->epoch = ntohl(thdr.version.epoch);
258 aversion->counter = ntohl(thdr.version.counter);
264 * \brief Label database, with \p aversion in host order.
267 uphys_setlabel(struct ubik_dbase *adbase, afs_int32 afile,
268 struct ubik_version *aversion)
270 struct ubik_hdr thdr;
273 fd = uphys_open(adbase, afile);
277 memset(&thdr, 0, sizeof(thdr));
279 thdr.version.epoch = htonl(aversion->epoch);
280 thdr.version.counter = htonl(aversion->counter);
281 thdr.magic = htonl(UBIK_MAGIC);
282 thdr.size = htons(HDRSIZE);
283 code = write(fd, &thdr, sizeof(thdr));
284 fsync(fd); /* preserve over crash */
286 if (code != sizeof(thdr)) {
293 uphys_sync(struct ubik_dbase *adbase, afs_int32 afile)
296 fd = uphys_open(adbase, afile);
303 uphys_invalidate(struct ubik_dbase *adbase, afs_int32 afid)
308 /* scan file descr cache */
309 for (tfd = fdcache, i = 0; i < MAXFDCACHE; i++, tfd++) {
310 if (afid == tfd->fileID) {
311 tfd->fileID = -10000;
312 if (tfd->fd >= 0 && tfd->refCount == 0) {