#include <afsconfig.h>
#include <afs/param.h>
+#include <roken.h>
-#include <stdlib.h>
#include <lock.h>
+#include "dir.h"
+
#ifdef AFS_64BIT_IOPS_ENV
-#define BUFFER_FID_SIZE (9 + 2*sizeof(char*)/sizeof(int))
+#define BUFFER_FID_SIZE (9*sizeof(int) + 2*sizeof(char*))
#else
-#define BUFFER_FID_SIZE (6 + 2*sizeof(char*)/sizeof(int))
+#define BUFFER_FID_SIZE (6*sizeof(int) + 2*sizeof(char*))
#endif
struct buffer {
/* fid is used for Unique cache key + i/o addressing.
* fid size is based on 4 + size of inode and size of pointer
*/
- afs_int32 fid[BUFFER_FID_SIZE];
+ char fid[BUFFER_FID_SIZE];
afs_int32 page;
afs_int32 accesstime;
struct buffer *hashNext;
struct Lock lock;
};
-#include "dir.h"
+static_inline dir_file_t
+bufferDir(struct buffer *b)
+{
+ return (dir_file_t) &b->fid;
+}
struct Lock afs_bufferLock;
* based on the volume id. This means this macro is dependent upon the
* layout of DirHandle in viced/viced.h, vol/salvage.h and volser/salvage.h.
*/
-#define pHash(fid) ((fid)[0] & (PHSIZE-1))
+#define pHash(fid) (((afs_int32 *)fid)[0] & (PHSIZE-1))
#define vHash(vid) (vid & (PHSIZE-1))
/* admittedly system dependent, this is the maximum signed 32-bit value */
int timecounter;
static int calls = 0, ios = 0;
-struct buffer *newslot(afs_int32 *afid, afs_int32 apage,
+struct buffer *newslot(dir_file_t dir, afs_int32 apage,
struct buffer *lp);
/* XXX - This sucks. The correct prototypes for these functions are ...
* extern int ReallyRead(DirHandle *a, int block, char *data);
*/
-extern void FidZero(afs_int32 *file);
-extern int FidEq(afs_int32 *a, afs_int32 *b);
-extern int ReallyRead(afs_int32 *file, int block, char *data);
-extern int ReallyWrite(afs_int32 *file, int block, char *data);
-extern void FidZap(afs_int32 *file);
-extern int FidVolEq(afs_int32 *file, afs_int32 vid);
-extern void FidCpy(afs_int32 *tofile, afs_int32 *fromfile);
-extern void Die(char *msg);
+extern void FidZero(dir_file_t);
+extern int FidEq(dir_file_t, dir_file_t);
+extern int ReallyRead(dir_file_t, int block, char *data);
+extern int ReallyWrite(dir_file_t, int block, char *data);
+extern void FidZap(dir_file_t);
+extern int FidVolEq(dir_file_t, afs_int32 vid);
+extern void FidCpy(dir_file_t, dir_file_t fromfile);
int
DStat(int *abuffers, int *acalls, int *aios)
return 0;
}
-int
+/**
+ * initialize the directory package.
+ *
+ * @param[in] abuffers size of directory buffer cache
+ *
+ * @return operation status
+ * @retval 0 success
+ */
+void
DInit(int abuffers)
{
/* Initialize the venus buffer system. */
- register int i, tsize;
- register struct buffer *tb;
- register char *tp;
+ int i, tsize;
+ struct buffer *tb;
+ char *tp;
Lock_Init(&afs_bufferLock);
/* Align each element of Buffers on a doubleword boundary */
tb = (struct buffer *)tp;
Buffers[i] = tb;
tp += tsize;
- FidZero(tb->fid);
+ FidZero(bufferDir(tb));
tb->accesstime = tb->lockers = 0;
tb->data = &BufferData[BUFFER_PAGE_SIZE * i];
tb->hashIndex = 0;
tb->dirty = 0;
Lock_Init(&tb->lock);
}
- return 0;
+ return;
}
-void *
-DRead(register afs_int32 *fid, register int page)
+/**
+ * read a page out of a directory object.
+ *
+ * @param[in] fid directory object fid
+ * @param[in] page page in hash table to be read
+ *
+ * @return pointer to requested page in directory cache
+ * @retval NULL read failed
+ */
+int
+DRead(dir_file_t fid, int page, struct DirBuffer *entry)
{
/* Read a page from the disk. */
- register struct buffer *tb, *tb2, **bufhead;
+ struct buffer *tb, *tb2, **bufhead;
+
+ memset(entry, 0, sizeof(struct DirBuffer));
ObtainWriteLock(&afs_bufferLock);
calls++;
-#define bufmatch(tb) (tb->page == page && FidEq(tb->fid, fid))
+#define bufmatch(tb,fid) (tb->page == page && FidEq(bufferDir(tb), fid))
#define buf_Front(head,parent,p) {(parent)->hashNext = (p)->hashNext; (p)->hashNext= *(head);*(head)=(p);}
/* this apparently-complicated-looking code is simply an example of
* probably obsolete.
*/
if ((tb = phTable[pHash(fid)])) { /* ASSMT HERE */
- if (bufmatch(tb)) {
+ if (bufmatch(tb, fid)) {
ObtainWriteLock(&tb->lock);
tb->lockers++;
ReleaseWriteLock(&afs_bufferLock);
tb->accesstime = ++timecounter;
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
+ return 0;
} else {
bufhead = &(phTable[pHash(fid)]);
while ((tb2 = tb->hashNext)) {
- if (bufmatch(tb2)) {
+ if (bufmatch(tb2, fid)) {
buf_Front(bufhead, tb, tb2);
ObtainWriteLock(&tb2->lock);
tb2->lockers++;
ReleaseWriteLock(&afs_bufferLock);
tb2->accesstime = ++timecounter;
ReleaseWriteLock(&tb2->lock);
- return tb2->data;
+ entry->buffer = tb2;
+ entry->data = tb2->data;
+ return 0;
}
if ((tb = tb2->hashNext)) { /* ASSIGNMENT HERE! */
- if (bufmatch(tb)) {
+ if (bufmatch(tb, fid)) {
buf_Front(bufhead, tb2, tb);
ObtainWriteLock(&tb->lock);
tb->lockers++;
ReleaseWriteLock(&afs_bufferLock);
tb->accesstime = ++timecounter;
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
+ return 0;
}
} else
break;
ObtainWriteLock(&tb->lock);
tb->lockers++;
ReleaseWriteLock(&afs_bufferLock);
- if (ReallyRead(tb->fid, tb->page, tb->data)) {
+ if (ReallyRead(bufferDir(tb), tb->page, tb->data)) {
tb->lockers--;
- FidZap(tb->fid); /* disaster */
+ FidZap(bufferDir(tb)); /* disaster */
ReleaseWriteLock(&tb->lock);
- return 0;
+ return EIO;
}
/* Note that findslot sets the page field in the buffer equal to
* what it is searching for.
*/
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
+ return 0;
}
+
static int
-FixupBucket(register struct buffer *ap)
+FixupBucket(struct buffer *ap)
{
- register struct buffer **lp, *tp;
- register int i;
+ struct buffer **lp, *tp;
+ int i;
/* first try to get it out of its current hash bucket, in which it might not be */
i = ap->hashIndex;
lp = &tp->hashNext;
}
/* now figure the new hash bucket */
- i = pHash(ap->fid);
+ i = pHash(ap);
ap->hashIndex = i; /* remember where we are for deletion */
ap->hashNext = phTable[i]; /* add us to the list */
phTable[i] = ap; /* at the front, since it's LRU */
}
struct buffer *
-newslot(afs_int32 *afid, afs_int32 apage, register struct buffer *lp)
+newslot(dir_file_t dir, afs_int32 apage, struct buffer *lp)
{
/* Find a usable buffer slot */
- register afs_int32 i;
+ afs_int32 i;
afs_int32 lt;
- register struct buffer **tbp;
+ struct buffer **tbp;
if (lp && (lp->lockers == 0)) {
lt = lp->accesstime;
* and the afs_bufferLock prevents other threads from zapping this
* buffer while we are writing it out */
if (lp->dirty) {
- if (ReallyWrite(lp->fid, lp->page, lp->data))
+ if (ReallyWrite(bufferDir(lp), lp->page, lp->data))
Die("writing bogus buffer");
lp->dirty = 0;
}
/* Now fill in the header. */
- FidZap(lp->fid);
- FidCpy(lp->fid, afid); /* set this */
+ FidZap(bufferDir(lp));
+ FidCpy(bufferDir(lp), dir); /* set this */
lp->page = apage;
lp->accesstime = ++timecounter;
return lp;
}
+/* Release a buffer, specifying whether or not the buffer has been modified
+ * by the locker. */
void
-DRelease(register struct buffer *bp, int flag)
+DRelease(struct DirBuffer *entry, int flag)
{
- /* Release a buffer, specifying whether or not the buffer has been modified by the locker. */
- register int index;
+ struct buffer *bp;
- if (!bp)
+ bp = (struct buffer *) entry->buffer;
+ if (bp == NULL)
return;
- index = ((char *)bp - BufferData) >> LOGPS;
- bp = Buffers[index];
ObtainWriteLock(&bp->lock);
bp->lockers--;
if (flag)
ReleaseWriteLock(&bp->lock);
}
+/* Return the byte within a file represented by a buffer pointer. */
int
-DVOffset(register void *ap)
+DVOffset(struct DirBuffer *entry)
{
- /* Return the byte within a file represented by a buffer pointer. */
- register struct buffer *bp = ap;
- register int index;
-
- index = ((char *)bp - BufferData) >> LOGPS;
- if (index < 0 || index >= nbuffers)
- return -1;
- bp = Buffers[index];
- return BUFFER_PAGE_SIZE * bp->page + (char *)ap - (char *)bp->data;
+ struct buffer *bp;
+
+ bp = entry->buffer;
+ return BUFFER_PAGE_SIZE * bp->page + (char *)entry->data - (char *)bp->data;
}
void
-DZap(register afs_int32 *fid)
+DZap(dir_file_t dir)
{
/* Destroy all buffers pertaining to a particular fid. */
- register struct buffer *tb;
+ struct buffer *tb;
ObtainReadLock(&afs_bufferLock);
- for (tb = phTable[pHash(fid)]; tb; tb = tb->hashNext)
- if (FidEq(tb->fid, fid)) {
+ for (tb = phTable[pHash(dir)]; tb; tb = tb->hashNext)
+ if (FidEq(bufferDir(tb), dir)) {
ObtainWriteLock(&tb->lock);
- FidZap(tb->fid);
+ FidZap(bufferDir(tb));
tb->dirty = 0;
ReleaseWriteLock(&tb->lock);
}
}
int
-DFlushVolume(register afs_int32 vid)
+DFlushVolume(afs_int32 vid)
{
/* Flush all data and release all inode handles for a particular volume */
- register struct buffer *tb;
- register int code, rcode = 0;
+ struct buffer *tb;
+ int code, rcode = 0;
ObtainReadLock(&afs_bufferLock);
for (tb = phTable[vHash(vid)]; tb; tb = tb->hashNext)
- if (FidVolEq(tb->fid, vid)) {
+ if (FidVolEq(bufferDir(tb), vid)) {
ObtainWriteLock(&tb->lock);
if (tb->dirty) {
- code = ReallyWrite(tb->fid, tb->page, tb->data);
+ code = ReallyWrite(bufferDir(tb), tb->page, tb->data);
if (code && !rcode)
rcode = code;
tb->dirty = 0;
}
- FidZap(tb->fid);
+ FidZap(bufferDir(tb));
ReleaseWriteLock(&tb->lock);
}
ReleaseReadLock(&afs_bufferLock);
}
int
-DFlushEntry(register afs_int32 *fid)
+DFlushEntry(dir_file_t fid)
{
/* Flush pages modified by one entry. */
- register struct buffer *tb;
+ struct buffer *tb;
int code;
ObtainReadLock(&afs_bufferLock);
for (tb = phTable[pHash(fid)]; tb; tb = tb->hashNext)
- if (FidEq(tb->fid, fid) && tb->dirty) {
+ if (FidEq(bufferDir(tb), fid) && tb->dirty) {
ObtainWriteLock(&tb->lock);
if (tb->dirty) {
- code = ReallyWrite(tb->fid, tb->page, tb->data);
+ code = ReallyWrite(bufferDir(tb), tb->page, tb->data);
if (code) {
ReleaseWriteLock(&tb->lock);
ReleaseReadLock(&afs_bufferLock);
DFlush(void)
{
/* Flush all the modified buffers. */
- register int i;
- register struct buffer **tbp;
+ int i;
+ struct buffer **tbp;
afs_int32 code, rcode;
rcode = 0;
(*tbp)->lockers++;
ReleaseReadLock(&afs_bufferLock);
if ((*tbp)->dirty) {
- code = ReallyWrite((*tbp)->fid, (*tbp)->page, (*tbp)->data);
+ code = ReallyWrite(bufferDir(*tbp), (*tbp)->page, (*tbp)->data);
if (!code)
(*tbp)->dirty = 0; /* Clear the dirty flag */
if (code && !rcode) {
return rcode;
}
-void *
-DNew(register afs_int32 *fid, register int page)
+/* Same as read, only do *not* even try to read the page,
+ * since it probably doesn't exist.
+ */
+int
+DNew(dir_file_t dir, int page, struct DirBuffer *entry)
{
- /* Same as read, only do *not* even try to read the page,
- * since it probably doesn't exist.
- */
- register struct buffer *tb;
+ struct buffer *tb;
+
+ memset(entry,0, sizeof(struct DirBuffer));
+
ObtainWriteLock(&afs_bufferLock);
- if ((tb = newslot(fid, page, 0)) == 0) {
+ if ((tb = newslot(dir, page, 0)) == 0) {
ReleaseWriteLock(&afs_bufferLock);
- return 0;
+ return EIO;
}
ObtainWriteLock(&tb->lock);
tb->lockers++;
ReleaseWriteLock(&afs_bufferLock);
ReleaseWriteLock(&tb->lock);
- return tb->data;
+
+ entry->buffer = tb;
+ entry->data = tb->data;
+
+ return 0;
}