#include <afs/param.h>
#include <roken.h>
+#include <afs/opr.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 operation status
* @retval 0 success
*/
-int
+void
DInit(int abuffers)
{
/* Initialize the venus buffer system. */
Lock_Init(&afs_bufferLock);
/* Align each element of Buffers on a doubleword boundary */
tsize = (sizeof(struct buffer) + 7) & ~7;
- tp = (char *)malloc(abuffers * tsize);
- Buffers = (struct buffer **)malloc(abuffers * sizeof(struct buffer *));
- BufferData = (char *)malloc(abuffers * BUFFER_PAGE_SIZE);
+ tp = malloc(abuffers * tsize);
+ Buffers = malloc(abuffers * sizeof(struct buffer *));
+ BufferData = malloc(abuffers * BUFFER_PAGE_SIZE);
timecounter = 0;
LastBuffer = (struct buffer *)tp;
nbuffers = abuffers;
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;
}
/**
* @return pointer to requested page in directory cache
* @retval NULL read failed
*/
-void *
-DRead(afs_int32 *fid, int page)
+int
+DRead(dir_file_t fid, int page, struct DirBuffer *entry)
{
/* Read a page from the disk. */
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(struct buffer *ap)
{
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, struct buffer *lp)
+newslot(dir_file_t dir, afs_int32 apage, struct buffer *lp)
{
/* Find a usable buffer slot */
afs_int32 i;
* 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 */
+ memset(lp->data, 0, BUFFER_PAGE_SIZE); /* Don't leak stale data. */
lp->page = apage;
lp->accesstime = ++timecounter;
/* Release a buffer, specifying whether or not the buffer has been modified
* by the locker. */
void
-DRelease(void *loc, int flag)
+DRelease(struct DirBuffer *entry, int flag)
{
- struct buffer *bp = (struct buffer *)loc;
- 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(void *ap)
+DVOffset(struct DirBuffer *entry)
{
- /* Return the byte within a file represented by a buffer pointer. */
- struct buffer *bp = ap;
- 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(afs_int32 *fid)
+DZap(dir_file_t dir)
{
/* Destroy all buffers pertaining to a particular fid. */
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 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(afs_int32 *fid)
+DFlushEntry(dir_file_t fid)
{
/* Flush pages modified by one entry. */
struct buffer *tb;
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);
(*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(afs_int32 *fid, 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.
- */
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;
}