dir: fileserver leaks names of file and directories
[openafs.git] / src / dir / buffer.c
index f25bb1c..1a8da8f 100644 (file)
 #include <afs/param.h>
 
 #include <roken.h>
+#include <afs/opr.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;
@@ -35,7 +38,11 @@ struct buffer {
     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;
 
@@ -50,7 +57,7 @@ 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 */
@@ -69,7 +76,7 @@ int nbuffers;
 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 ...
@@ -79,14 +86,13 @@ struct buffer *newslot(afs_int32 *afid, afs_int32 apage,
  * 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)
@@ -105,7 +111,7 @@ DStat(int *abuffers, int *acalls, int *aios)
  * @return operation status
  *    @retval 0 success
  */
-int
+void
 DInit(int abuffers)
 {
     /* Initialize the venus buffer system. */
@@ -116,9 +122,9 @@ DInit(int abuffers)
     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;
@@ -129,14 +135,14 @@ DInit(int 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;
 }
 
 /**
@@ -148,16 +154,18 @@ DInit(int abuffers)
  * @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
@@ -168,34 +176,40 @@ DRead(afs_int32 *fid, int page)
      * 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;
@@ -214,19 +228,22 @@ DRead(afs_int32 *fid, int page)
     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)
 {
@@ -244,7 +261,7 @@ 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 */
@@ -252,7 +269,7 @@ FixupBucket(struct buffer *ap)
 }
 
 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;
@@ -288,14 +305,15 @@ newslot(afs_int32 *afid, afs_int32 apage, struct buffer *lp)
      * 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;
 
@@ -307,15 +325,13 @@ newslot(afs_int32 *afid, afs_int32 apage, struct buffer *lp)
 /* 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)
@@ -323,30 +339,26 @@ DRelease(void *loc, int 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);
        }
@@ -361,15 +373,15 @@ DFlushVolume(afs_int32 vid)
     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);
@@ -377,7 +389,7 @@ DFlushVolume(afs_int32 vid)
 }
 
 int
-DFlushEntry(afs_int32 *fid)
+DFlushEntry(dir_file_t fid)
 {
     /* Flush pages modified by one entry. */
     struct buffer *tb;
@@ -385,10 +397,10 @@ DFlushEntry(afs_int32 *fid)
 
     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);
@@ -419,7 +431,7 @@ DFlush(void)
            (*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) {
@@ -435,21 +447,28 @@ DFlush(void)
     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;
 }