#include "h/param.h"
#include "h/types.h"
#include "h/time.h"
-#if defined(AFS_AIX31_ENV) || defined(AFS_DEC_ENV)
+#if defined(AFS_AIX31_ENV)
#include "h/limits.h"
#endif
#if !defined(AFS_AIX_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_SGI_ENV) && !defined(AFS_LINUX20_ENV)
#include "afs/dir.h"
#include "afs/afs_stats.h"
-#include "afs/longc_procs.h"
#include "afs/afs.h"
#ifndef BUF_TIME_MAX
/* page hash table size - this is pretty intertwined with pHash */
#define PHSIZE (PHPAGEMASK + PHFIDMASK + 1)
/* the pHash macro */
-#define pHash(fid,page) ((((afs_int32)((fid)[0])) & PHFIDMASK) \
+#define pHash(fid,page) ((((afs_int32)(fid)) & PHFIDMASK) \
| (page & PHPAGEMASK))
#ifdef dirty
static afs_int32 timecounter;
/* Prototypes for static routines */
-static struct buffer *afs_newslot(afs_inode_t * afid, afs_int32 apage,
+static struct buffer *afs_newslot(struct dcache *adc, afs_int32 apage,
register struct buffer *lp);
static int dinit_flag = 0;
/* Initialize the venus buffer system. */
register int i;
register struct buffer *tb;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
struct buf *tub; /* unix buffer for allocation */
#endif
if (dinit_flag)
return;
dinit_flag = 1;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
/* round up to next multiple of NPB, since we allocate multiple pages per chunk */
abuffers = ((abuffers - 1) | (NPB - 1)) + 1;
#endif
LOCK_INIT(&afs_bufferLock, "afs_bufferLock");
Buffers =
(struct buffer *)afs_osi_Alloc(abuffers * sizeof(struct buffer));
-#if !AFS_USEBUFFERS
+#if !defined(AFS_USEBUFFERS)
BufferData = (char *)afs_osi_Alloc(abuffers * AFS_BUFFER_PAGESIZE);
#endif
timecounter = 1;
for (i = 0; i < PHSIZE; i++)
phTable[i] = 0;
for (i = 0; i < abuffers; i++) {
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
if ((i & (NPB - 1)) == 0) {
/* time to allocate a fresh buffer */
tub = geteblk(AFS_BUFFER_PAGESIZE * NPB);
#endif
/* Fill in each buffer with an empty indication. */
tb = &Buffers[i];
- dirp_Zap(tb->fid);
+ tb->fid = NULLIDX;
+ tb->inode = 0;
tb->accesstime = 0;
tb->lockers = 0;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
if ((i & (NPB - 1)) == 0)
tb->bufp = tub;
else
}
void *
-DRead(register afs_inode_t * fid, register int page)
+DRead(register struct dcache *adc, register int page)
{
/* Read a page from the disk. */
register struct buffer *tb, *tb2;
AFS_STATCNT(DRead);
MObtainWriteLock(&afs_bufferLock, 256);
-#define bufmatch(tb) (tb->page == page && dirp_Eq(tb->fid, fid))
+#define bufmatch(tb) (tb->page == page && tb->fid == adc->index)
#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
* of larger code size. This could be simplified by better use of
* macros.
*/
- if ((tb = phTable[pHash(fid, page)])) {
+ if ((tb = phTable[pHash(adc->index, page)])) {
if (bufmatch(tb)) {
MObtainWriteLock(&tb->lock, 257);
ReleaseWriteLock(&afs_bufferLock);
return tb->data;
} else {
register struct buffer **bufhead;
- bufhead = &(phTable[pHash(fid, page)]);
+ bufhead = &(phTable[pHash(adc->index, page)]);
while ((tb2 = tb->hashNext)) {
if (bufmatch(tb2)) {
buf_Front(bufhead, tb, tb2);
* is at least the oldest buffer on one particular hash chain, so it's
* a pretty good place to start looking for the truly oldest buffer.
*/
- tb = afs_newslot(fid, page, (tb ? tb : tb2));
+ tb = afs_newslot(adc, page, (tb ? tb : tb2));
if (!tb) {
MReleaseWriteLock(&afs_bufferLock);
return NULL;
MObtainWriteLock(&tb->lock, 260);
MReleaseWriteLock(&afs_bufferLock);
tb->lockers++;
- tfile = afs_CFileOpen(fid[0]);
- if (page * AFS_BUFFER_PAGESIZE >= tfile->size) {
- dirp_Zap(tb->fid);
+ if (page * AFS_BUFFER_PAGESIZE >= adc->f.chunkBytes) {
+ tb->fid = NULLIDX;
+ tb->inode = 0;
tb->lockers--;
MReleaseWriteLock(&tb->lock);
- afs_CFileClose(tfile);
return NULL;
}
+ tfile = afs_CFileOpen(adc->f.inode);
code =
afs_CFileRead(tfile, tb->page * AFS_BUFFER_PAGESIZE, tb->data,
AFS_BUFFER_PAGESIZE);
afs_CFileClose(tfile);
if (code < AFS_BUFFER_PAGESIZE) {
- dirp_Zap(tb->fid);
+ tb->fid = NULLIDX;
+ tb->inode = 0;
tb->lockers--;
MReleaseWriteLock(&tb->lock);
return NULL;
/* lp is pointer to a fairly-old buffer */
static struct buffer *
-afs_newslot(afs_inode_t * afid, afs_int32 apage, register struct buffer *lp)
+afs_newslot(struct dcache *adc, afs_int32 apage, register struct buffer *lp)
{
/* Find a usable buffer slot */
register afs_int32 i;
}
if (lp->dirty) {
- tfile = afs_CFileOpen(lp->fid[0]);
+ /* see DFlush for rationale for not getting and locking the dcache */
+ tfile = afs_CFileOpen(lp->inode);
afs_CFileWrite(tfile, lp->page * AFS_BUFFER_PAGESIZE, lp->data,
AFS_BUFFER_PAGESIZE);
lp->dirty = 0;
}
/* Now fill in the header. */
- dirp_Cpy(lp->fid, afid); /* set this */
+ lp->fid = adc->index;
+ lp->inode = adc->f.inode;
lp->page = apage;
lp->accesstime = timecounter++;
FixupBucket(lp); /* move to the right hash bucket */
/* Release a buffer, specifying whether or not the buffer has been
* modified by the locker. */
register int index;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
register struct buffer *tp;
#endif
AFS_STATCNT(DRelease);
if (!bp)
return;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
/* look for buffer by scanning Unix buffers for appropriate address */
tp = Buffers;
for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
/* Return the byte within a file represented by a buffer pointer. */
register struct buffer *bp;
register int index;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
register struct buffer *tp;
#endif
AFS_STATCNT(DVOffset);
bp = ap;
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
/* look for buffer by scanning Unix buffers for appropriate address */
tp = Buffers;
for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
* method of DRead...
*/
void
-DZap(afs_inode_t * fid)
+DZap(struct dcache *adc)
{
register int i;
/* Destroy all buffers pertaining to a particular fid. */
MObtainReadLock(&afs_bufferLock);
for (i = 0; i <= PHPAGEMASK; i++)
- for (tb = phTable[pHash(fid, i)]; tb; tb = tb->hashNext)
- if (dirp_Eq(tb->fid, fid)) {
+ for (tb = phTable[pHash(adc->index, i)]; tb; tb = tb->hashNext)
+ if (tb->fid == adc->index) {
MObtainWriteLock(&tb->lock, 262);
- dirp_Zap(tb->fid);
+ tb->fid = NULLIDX;
+ tb->inode = 0;
tb->dirty = 0;
MReleaseWriteLock(&tb->lock);
}
tb->lockers++;
MReleaseReadLock(&afs_bufferLock);
if (tb->dirty) {
- tfile = afs_CFileOpen(tb->fid[0]);
+ /* it seems safe to do this I/O without having the dcache
+ * locked, since the only things that will update the data in
+ * a directory are the buffer package, which holds the relevant
+ * tb->lock while doing the write, or afs_GetDCache, which
+ * DZap's the directory while holding the dcache lock.
+ * It is not possible to lock the dcache or even call
+ * afs_GetDSlot to map the index to the dcache since the dir
+ * package's caller has some dcache object locked already (so
+ * we cannot lock afs_xdcache). In addition, we cannot obtain
+ * a dcache lock while holding the tb->lock of the same file
+ * since that can deadlock with DRead/DNew */
+ tfile = afs_CFileOpen(tb->inode);
afs_CFileWrite(tfile, tb->page * AFS_BUFFER_PAGESIZE,
tb->data, AFS_BUFFER_PAGESIZE);
tb->dirty = 0; /* Clear the dirty flag */
}
void *
-DNew(register afs_inode_t * fid, register int page)
+DNew(register struct dcache *adc, register int page)
{
/* Same as read, only do *not* even try to read the page, since it probably doesn't exist. */
register struct buffer *tb;
AFS_STATCNT(DNew);
MObtainWriteLock(&afs_bufferLock, 264);
- if ((tb = afs_newslot(fid, page, NULL)) == 0) {
+ if ((tb = afs_newslot(adc, page, NULL)) == 0) {
MReleaseWriteLock(&afs_bufferLock);
return 0;
}
+ /* extend the chunk, if needed */
+ /* Do it now, not in DFlush or afs_newslot when the data is written out,
+ * since now our caller has adc->lock writelocked, and we can't acquire
+ * that lock (or even map from a fid to a dcache) in afs_newslot or
+ * DFlush due to lock hierarchy issues */
+ if ((page + 1) * AFS_BUFFER_PAGESIZE > adc->f.chunkBytes) {
+ afs_AdjustSize(adc, (page + 1) * AFS_BUFFER_PAGESIZE);
+ afs_WriteDCache(adc, 1);
+ }
MObtainWriteLock(&tb->lock, 265);
MReleaseWriteLock(&afs_bufferLock);
tb->lockers++;
void
shutdown_bufferpackage(void)
{
-#if AFS_USEBUFFERS
+#if defined(AFS_USEBUFFERS)
register struct buffer *tp;
#endif
int i;
DFlush();
if (afs_cold_shutdown) {
dinit_flag = 0;
-#if !AFS_USEBUFFERS
+#if !defined(AFS_USEBUFFERS)
afs_osi_Free(BufferData, nbuffers * AFS_BUFFER_PAGESIZE);
#else
tp = Buffers;