int offset;
int dirpos;
struct DirEntry *de;
+ struct DirBuffer entry;
ino_t ino;
int len;
afs_size_t origOffset, tlen;
if (!dirpos)
break;
- de = afs_dir_GetBlob(tdc, dirpos);
- if (!de)
+ code = afs_dir_GetBlob(tdc, dirpos, &entry);
+ if (code)
break;
+ de = (struct DirEntry *)entry.data;
ino = afs_calc_inum (avc->f.fid.Fid.Volume, ntohl(de->fid.vnode));
else {
printf("afs_linux_readdir: afs_dir_GetBlob failed, null name (inode %lx, dirpos %d)\n",
(unsigned long)&tdc->f.inode, dirpos);
- DRelease(de, 0);
+ DRelease(&entry, 0);
ReleaseSharedLock(&avc->lock);
afs_PutDCache(tdc);
code = -ENOENT;
code = (*filldir) (dirbuf, de->name, len, offset, ino, type);
AFS_GLOCK();
}
- DRelease(de, 0);
+ DRelease(&entry, 0);
if (code)
break;
offset = dirpos + 1 + ((len + 16) >> 5);
if (!dirpos)
break;
- de = afs_dir_GetBlob(tdc, dirpos);
- if (!de)
+ code = afs_dir_GetBlob(tdc, dirpos, &entry);
+ if (code)
break;
+ de = (struct DirEntry *)entry.data;
ino = afs_calc_inum (avc->f.fid.Fid.Volume, ntohl(de->fid.vnode));
afs_size_t statSeqNo = 0; /* Valued of file size to detect races */
int code; /* error code */
long newIndex; /* new index in the dir */
+ struct DirBuffer entry; /* Buffer for dir manipulation */
struct DirEntry *dirEntryp; /* dir entry we are examining */
int i;
struct VenusFid afid; /* file ID we are using now */
dirCookie = newIndex << 5;
/* get a ptr to the dir entry */
- dirEntryp =
- (struct DirEntry *)afs_dir_GetBlob(dcp, newIndex);
- if (!dirEntryp)
+ code = afs_dir_GetBlob(dcp, newIndex, &entry);
+ if (code)
break;
+ dirEntryp = (struct DirEntry *)entry.data;
/* dont copy more than we have room for */
if (fidIndex >= nentries) {
- DRelease(dirEntryp, 0);
+ DRelease(&entry, 0);
break;
}
}
if (!tvcp)
{
- DRelease(dirEntryp, 0);
+ DRelease(&entry, 0);
ReleaseReadLock(&dcp->lock);
ReleaseReadLock(&adp->lock);
afs_PutDCache(dcp);
* used by this dir entry.
*/
temp = afs_dir_NameBlobs(dirEntryp->name) << 5;
- DRelease(dirEntryp, 0);
+ DRelease(&entry, 0);
if (temp <= 0)
break;
dirCookie += temp;
afs_int32 relativeBlob;
afs_int32 pageBlob;
struct PageHeader *tpe;
+ struct DirBuffer headerbuf;
afs_int32 i;
+ int code;
AFS_STATCNT(BlobScan);
/* advance ablob over free and header blobs */
while (1) {
pageBlob = ablob & ~(EPP - 1); /* base blob in same page */
- tpe = (struct PageHeader *)afs_dir_GetBlob(afile, pageBlob);
- if (!tpe)
- return 0; /* we've past the end */
+ code = afs_dir_GetBlob(afile, pageBlob, &headerbuf);
+ if (code)
+ return 0;
+ tpe = (struct PageHeader *)headerbuf.data;
+
relativeBlob = ablob - pageBlob; /* relative to page's first blob */
/* first watch for headers */
if (pageBlob == 0) { /* first dir page has extra-big header */
}
/* now relativeBlob is the page-relative first allocated blob,
* or EPP (if there are none in this page). */
- DRelease(tpe, 0);
+ DRelease(&headerbuf, 0);
if (i != EPP)
return i + pageBlob;
ablob = pageBlob + EPP; /* go around again */
afs_size_t origOffset, tlen;
afs_int32 len;
int code = 0;
+ struct DirBuffer oldEntry, nextEntry;
struct DirEntry *ode = 0, *nde = 0;
int o_slen = 0, n_slen = 0;
afs_uint32 us;
*/
AFS_STATCNT(afs_readdir);
+ memset(&oldEntry, 0, sizeof(struct DirBuffer));
+ memset(&nextEntry, 0, sizeof(struct DirBuffer));
+
#if defined(AFS_SGI53_ENV)
#ifdef AFS_SGI61_ENV
#ifdef AFS_SGI62_ENV
/* scan for the next interesting entry scan for in-use blob otherwise up point at
* this blob note that ode, if non-zero, also represents a held dir page */
if (!(us = BlobScan(tdc, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(tdc, us))) {
+ || (afs_dir_GetBlob(tdc, us, &nextEntry) != 0)) {
/* failed to setup nde, return what we've got, and release ode */
if (len) {
/* something to hand over. */
if (eofp)
*eofp = 1; /* Set it properly */
#endif
- if (ode)
- DRelease(ode, 0);
+ DRelease(&oldEntry, 0);
goto dirend;
}
- /* by here nde is set */
+ nde = (struct DirEntry *)nextEntry.data;
+
/* Do we have enough user space to carry out our mission? */
#if defined(AFS_SGI_ENV)
n_slen = strlen(nde->name) + 1; /* NULL terminate */
if (DIRSIZ_LEN(n_slen) >= (AFS_UIO_RESID(auio) - len)) {
#endif /* AFS_SGI53_ENV */
/* No can do no more now; ya know... at this time */
- DRelease(nde, 0); /* can't use this one. */
+ DRelease(&nextEntry, 0); /* can't use this one. */
if (len) {
#ifdef AFS_HPUX_ENV
sdirEntry->d_fileno =
*/
code = EINVAL;
}
- if (ode)
- DRelease(ode, 0);
+ DRelease(&oldEntry, 0);
goto dirend;
}
#else
len = DIRSIZ_LEN(o_slen = n_slen);
#endif /* AFS_SGI53_ENV */
- if (ode)
- DRelease(ode, 0);
+
+ DRelease(&oldEntry, 0);
ode = nde;
AFS_UIO_SETOFFSET(auio, (afs_int32) ((us + afs_dir_NameBlobs(nde->name)) << 5));
}
- if (ode)
- DRelease(ode, 0);
+
+ DRelease(&oldEntry, 0);
dirend:
ReleaseReadLock(&tdc->lock);
return code;
}
-#if defined(AFS_HPUX_ENV)
-int
-afs1_readdir(struct vcache *avc, struct uio *auio, afs_ucred_t *acred)
-{
- struct vrequest treq;
- struct dcache *tdc;
- afs_size_t origOffset, len;
- int code = 0;
- struct DirEntry *ode = 0, *nde = 0;
- int o_slen = 0, n_slen = 0;
- afs_uint32 us;
- /*
- * XXX All the hacks for alloced sdirEntry and inlining of
- * afs_readdir_move instead of calling it is necessary for hpux due to
- * stack problems that seem to occur when coming thru the nfs
- * translator side XXX
- */
- struct minnfs_direct *sdirEntry = (struct minnfs_direct *)
- osi_AllocSmallSpace(sizeof(struct min_direct));
- afs_int32 rlen;
-
- struct afs_fakestat_state fakestate;
-
- AFS_STATCNT(afs_readdir);
- if (code = afs_InitReq(&treq, acred)) {
- osi_FreeSmallSpace((char *)sdirEntry);
- return code;
- }
- afs_InitFakeStat(&fakestate);
- AFS_DISCON_LOCK();
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code) {
- osi_FreeSmallSpace((char *)sdirEntry);
- AFS_DISCON_UNLOCK();
- afs_PutFakeStat(&fakestate);
- return code;
- }
- /* update the cache entry */
- tagain:
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- goto done;
- /* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &len, 1);
- if (!tdc) {
- code = ENOENT;
- goto done;
- }
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
-
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((avc->f.states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (!(avc->f.states & CStatd)
- || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_PutDCache(tdc);
- goto tagain;
- }
-
- len = 0;
- auio->uio_fpflags = 0;
- while (code == 0) {
- origOffset = AFS_UIO_OFFSET(auio);
-
- /* scan for the next interesting entry scan for in-use blob
- * otherwise up point at this blob note that ode, if non-zero,
- * also represents a held dir page */
- if (!(us = BlobScan(tdc, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(tdc, us))) {
- /* failed to setup nde, return what we've got, and release ode */
- if (len) {
- /* something to hand over. */
- sdirEntry->d_fileno =
- (avc->f.fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = AFS_UIO_RESID(auio);
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0) {
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- }
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
- AFS_UIO_SETRESID(auio, 0);
- } else {
- /* nothin to hand over */
- }
- if (ode)
- DRelease(ode, 0);
- goto dirend;
- }
- /* by here nde is set */
-
- /* Do we have enough user space to carry out our mission? */
- n_slen = strlen(nde->name);
- if (NDIRSIZ_LEN(n_slen) >= (AFS_UIO_RESID(auio) - len)) {
- /* No can do no more now; ya know... at this time */
- DRelease(nde, 0); /* can't use this one. */
- if (len) {
- sdirEntry->d_fileno =
- (avc->f.fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = AFS_UIO_RESID(auio);
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
- /* this next line used to be AFSVFS40 or AIX 3.1, but is really generic */
- AFS_UIO_SETOFFSET(auio, origOffset);
- AFS_UIO_SETRESID(auio, 0);
- } else { /* trouble, can't give anything to the user! */
- /* even though he has given us a buffer,
- * even though we have something to give us,
- * Looks like we lost something somewhere.
- */
- code = EINVAL;
- }
- if (ode)
- DRelease(ode, 0);
- goto dirend;
- }
-
- /*
- * In any event, we move out the LAST de entry, getting ready
- * to set up for the next one.
- */
- if (len) {
- sdirEntry->d_fileno =
- (avc->f.fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = len;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
- code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
- }
- len = NDIRSIZ_LEN(o_slen = n_slen);
- if (ode)
- DRelease(ode, 0);
- ode = nde;
- AFS_UIO_OFFSET(auio) = ((us + afs_dir_NameBlobs(nde->name)) << 5);
- }
- if (ode)
- DRelease(ode, 0);
-
- dirend:
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- ReleaseReadLock(&avc->lock);
-
- done:
- osi_FreeSmallSpace((char *)sdirEntry);
- AFS_DISCON_UNLOCK();
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 29);
- return code;
-}
-
-#endif
#endif /* !AFS_LINUX20_ENV */
return;
}
-void *
-DRead(struct dcache *adc, int page)
+int
+DRead(struct dcache *adc, int page, struct DirBuffer *entry)
{
/* Read a page from the disk. */
struct buffer *tb, *tb2;
int code;
AFS_STATCNT(DRead);
+
+ memset(entry, 0, sizeof(struct DirBuffer));
+
ObtainWriteLock(&afs_bufferLock, 256);
#define bufmatch(tb) (tb->page == page && tb->fid == adc->index)
tb->accesstime = timecounter++;
AFS_STATS(afs_stats_cmperf.bufHits++);
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
+ return 0;
} else {
struct buffer **bufhead;
bufhead = &(phTable[pHash(adc->index, page)]);
tb2->accesstime = timecounter++;
AFS_STATS(afs_stats_cmperf.bufHits++);
ReleaseWriteLock(&tb2->lock);
- return tb2->data;
+ entry->buffer = tb2;
+ entry->data = tb2->data;
+ return 0;
}
if ((tb = tb2->hashNext)) {
if (bufmatch(tb)) {
tb->accesstime = timecounter++;
AFS_STATS(afs_stats_cmperf.bufHits++);
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
}
} else
break;
tb = afs_newslot(adc, page, (tb ? tb : tb2));
if (!tb) {
ReleaseWriteLock(&afs_bufferLock);
- return NULL;
+ return EIO;
}
ObtainWriteLock(&tb->lock, 260);
tb->lockers++;
afs_reset_inode(&tb->inode);
tb->lockers--;
ReleaseWriteLock(&tb->lock);
- return NULL;
+ return EIO;
}
tfile = afs_CFileOpen(&adc->f.inode);
code =
afs_reset_inode(&tb->inode);
tb->lockers--;
ReleaseWriteLock(&tb->lock);
- return NULL;
+ 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 void
}
void
-DRelease(void *loc, int flag)
+DRelease(struct DirBuffer *entry, int flag)
{
- /* Release a buffer, specifying whether or not the buffer has been
- * modified by the locker. */
- struct buffer *bp = (struct buffer *)loc;
- int index;
struct buffer *tp;
AFS_STATCNT(DRelease);
- if (!bp)
+
+ tp = entry->buffer;
+ if (tp == NULL)
return;
- /* look for buffer by scanning Unix buffers for appropriate address */
- /* careful: despite the declaration above at this point bp is still simply
- * an address inside the buffer, not a pointer to the buffer header */
- tp = Buffers;
- for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
- if ( (char *) bp >= (char *) tp->data &&
- (char *) bp < (char *) tp->data + AFS_BUFFER_PAGESIZE * NPB) {
- /* we found the right range */
- index += ((char *) bp - (char *) tp->data) >> LOGPS;
- break;
- }
- }
- tp = &(Buffers[index]);
+
+ tp = entry->buffer;
ObtainWriteLock(&tp->lock, 261);
tp->lockers--;
if (flag)
}
int
-DVOffset(void *ap)
+DVOffset(struct DirBuffer *entry)
{
- /* Return the byte within a file represented by a buffer pointer. */
- int index;
- struct buffer *tp;
+ struct buffer *bp;
+
AFS_STATCNT(DVOffset);
- /* look for buffer by scanning Unix buffers for appropriate address */
- /* see comment in DRelease about the meaning of ap/bp */
- tp = Buffers;
- for (index = 0; index < nbuffers; index += NPB, tp += NPB) {
- if ( (char *) ap >= (char *) tp->data &&
- (char *) ap < (char *) tp->data + AFS_BUFFER_PAGESIZE * NPB) {
- /* we found the right range */
- index += ((char *) ap - (char *) tp->data) >> LOGPS;
- break;
- }
- }
- if (index < 0 || index >= nbuffers)
- return -1;
- tp = &(Buffers[index]);
- return AFS_BUFFER_PAGESIZE * tp->page + (int)(((char *)ap) - tp->data);
+
+ bp = entry->buffer;
+ return AFS_BUFFER_PAGESIZE * bp->page
+ + (char *)entry->data - (char *)bp->data;
}
/*!
ReleaseReadLock(&afs_bufferLock);
}
-void *
-DNew(struct dcache *adc, int page)
+int
+DNew(struct dcache *adc, int page, struct DirBuffer *entry)
{
- /* Same as read, only do *not* even try to read the page, since it probably doesn't exist. */
+ /* Same as read, only do *not* even try to read the page, since it
+ * probably doesn't exist. */
struct buffer *tb;
AFS_STATCNT(DNew);
+
ObtainWriteLock(&afs_bufferLock, 264);
if ((tb = afs_newslot(adc, page, NULL)) == 0) {
ReleaseWriteLock(&afs_bufferLock);
- return 0;
+ return EIO;
}
/* extend the chunk, if needed */
/* Do it now, not in DFlush or afs_newslot when the data is written out,
tb->lockers++;
ReleaseWriteLock(&afs_bufferLock);
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
+
+ return 0;
}
void
extern void shutdown_xscache(void);
/* afs_buffer.c */
+struct DirBuffer;
extern void DInit(int abuffers);
-extern void *DRead(struct dcache * fid, int page);
-extern int DVOffset(void *ap);
+extern int DRead(struct dcache * fid, int page, struct DirBuffer *);
+extern int DVOffset(struct DirBuffer *);
extern void DZap(struct dcache * fid);
extern void DFlush(void);
extern void DFlushDCache(struct dcache *);
-extern void *DNew(struct dcache * fid, int page);
+extern int DNew(struct dcache * fid, int page, struct DirBuffer *);
extern void shutdown_bufferpackage(void);
/* afs_call.c */
test:
cd test; $(MAKE)
-buffer.o: buffer.c
+buffer.o: buffer.c dir.h
dir.o: dir.c dir.h
* @return pointer to requested page in directory cache
* @retval NULL read failed
*/
-void *
-DRead(afs_int32 *fid, int page)
+int
+DRead(afs_int32 *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++;
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)) {
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)) {
ReleaseWriteLock(&afs_bufferLock);
tb->accesstime = ++timecounter;
ReleaseWriteLock(&tb->lock);
- return tb->data;
+ entry->buffer = tb;
+ entry->data = tb->data;
}
} else
break;
tb->lockers--;
FidZap(tb->fid); /* 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)
{
/* 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
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(afs_int32 *fid, 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) {
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;
}
# ifndef AFS_LINUX20_ENV
# include "netinet/in.h"
# endif
-
-/* afs_buffer.c */
-/* These are needed because afs_prototypes.h is not included here */
-struct dcache;
-extern void *DRead(struct dcache *adc, int page);
-extern void *DNew(struct dcache *adc, int page);
-
# else /* !defined(UKERNEL) */
# include "afs/stds.h"
# include "afs/sysincludes.h"
+# endif /* !defined(UKERNEL) */
/* afs_buffer.c */
/* These are needed because afs_prototypes.h is not included here */
-extern void *DRead(afs_int32 *fid, int page);
-extern void *DNew(afs_int32 *fid, int page);
+struct dcache;
+struct DirBuffer;
+extern int DRead(struct dcache *adc, int page, struct DirBuffer *);
+extern int DNew(struct dcache *adc, int page, struct DirBuffer *);
-# endif /* !defined(UKERNEL) */
# include "afs/afs_osi.h"
# include "afs/dir.h"
afs_int32 DErrno;
/* Local static prototypes */
-static struct DirEntry *FindItem(void *dir, char *ename,
- unsigned short **previtem);
-
+static int FindItem(void *dir, char *ename, struct DirBuffer *,
+ struct DirBuffer *);
/* Find out how many entries are required to store a name. */
int
afs_int32 *vfid = (afs_int32 *) voidfid;
int blobs, firstelt;
int i;
+ struct DirBuffer entrybuf, prevbuf, headerbuf;
struct DirEntry *ep;
- unsigned short *pp = NULL;
struct DirHeader *dhp;
/* check name quality */
if (*entry == 0)
return EINVAL;
+
/* First check if file already exists. */
- ep = FindItem(dir, entry, &pp);
- if (ep) {
- DRelease(ep, 0);
- DRelease(pp, 0);
+ if (FindItem(dir, entry, &prevbuf, &entrybuf) == 0) {
+ DRelease(&entrybuf, 0);
+ DRelease(&prevbuf, 0);
+ printf("Exists ...\n");
return EEXIST;
}
+
blobs = NameBlobs(entry); /* number of entries required */
firstelt = FindBlobs(dir, blobs);
if (firstelt < 0)
return EFBIG; /* directory is full */
+
/* First, we fill in the directory entry. */
- ep = GetBlob(dir, firstelt);
- if (ep == 0)
+ if (GetBlob(dir, firstelt, &entrybuf) != 0)
return EIO;
+ ep = (struct DirEntry *)entrybuf.data;
+
ep->flag = FFIRST;
ep->fid.vnode = htonl(vfid[1]);
ep->fid.vunique = htonl(vfid[2]);
strcpy(ep->name, entry);
+
/* Now we just have to thread it on the hash table list. */
- dhp = (struct DirHeader *)DRead(dir, 0);
- if (!dhp) {
- DRelease(ep, 1);
+ if (DRead(dir, 0, &headerbuf) != 0) {
+ DRelease(&entrybuf, 1);
return EIO;
}
+ dhp = (struct DirHeader *)headerbuf.data;
+
i = DirHash(entry);
ep->next = dhp->hashTable[i];
dhp->hashTable[i] = htons(firstelt);
- DRelease(dhp, 1);
- DRelease(ep, 1);
+ DRelease(&headerbuf, 1);
+ DRelease(&entrybuf, 1);
return 0;
}
Length(void *dir)
{
int i, ctr;
+ struct DirBuffer headerbuf;
struct DirHeader *dhp;
- dhp = (struct DirHeader *)DRead(dir, 0);
- if (!dhp)
+
+ if (DRead(dir, 0, &headerbuf) != 0)
return 0;
+ dhp = (struct DirHeader *)headerbuf.data;
+
if (dhp->header.pgcount != 0)
ctr = ntohs(dhp->header.pgcount);
else {
if (dhp->alloMap[i] != EPP)
ctr++;
}
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return ctr * AFS_PAGESIZE;
}
int
Delete(void *dir, char *entry)
{
- /* Delete an entry from a directory, including update of all free entry descriptors. */
+ /* Delete an entry from a directory, including update of all free entry
+ * descriptors. */
int nitems, index;
+ struct DirBuffer entrybuf, prevbuf;
struct DirEntry *firstitem;
unsigned short *previtem;
- firstitem = FindItem(dir, entry, &previtem);
- if (firstitem == 0)
+
+ if (FindItem(dir, entry, &prevbuf, &entrybuf) != 0)
return ENOENT;
+
+ firstitem = (struct DirEntry *)entrybuf.data;
+ previtem = (unsigned short *)prevbuf.data;
+
*previtem = firstitem->next;
- DRelease(previtem, 1);
- index = DVOffset(firstitem) / 32;
+ DRelease(&prevbuf, 1);
+ index = DVOffset(&entrybuf) / 32;
nitems = NameBlobs(firstitem->name);
- DRelease(firstitem, 0);
+ DRelease(&entrybuf, 0);
FreeBlobs(dir, index, nitems);
return 0;
}
/* Find a bunch of contiguous entries; at least nblobs in a row. */
int i, j, k;
int failed = 0;
+ struct DirBuffer headerbuf, pagebuf;
struct DirHeader *dhp;
struct PageHeader *pp;
int pgcount;
- dhp = (struct DirHeader *)DRead(dir, 0); /* read the dir header in first. */
- if (!dhp)
+ /* read the dir header in first. */
+ if (DRead(dir, 0, &headerbuf) != 0)
return -1;
+ dhp = (struct DirHeader *)headerbuf.data;
+
for (i = 0; i < BIGMAXPAGES; i++) {
if (i >= MAXPAGES || dhp->alloMap[i] >= nblobs) {
/* if page could contain enough entries */
dhp->alloMap[i] = EPP - 1;
dhp->header.pgcount = htons(i + 1);
}
- pp = (struct PageHeader *)DRead(dir, i); /* read the page in. */
- if (!pp) {
- DRelease(dhp, 1);
+
+ /* read the page in. */
+ if (DRead(dir, i, &pagebuf) != 0) {
+ DRelease(&headerbuf, 1);
break;
}
+ pp = (struct PageHeader *)pagebuf.data;
for (j = 0; j <= EPP - nblobs; j++) {
failed = 0;
for (k = 0; k < nblobs; k++)
* and free up any resources we've got allocated. */
if (i < MAXPAGES)
dhp->alloMap[i] -= nblobs;
- DRelease(dhp, 1);
+ DRelease(&headerbuf, 1);
for (k = 0; k < nblobs; k++)
pp->freebitmap[(j + k) >> 3] |= 1 << ((j + k) & 7);
- DRelease(pp, 1);
+ DRelease(&pagebuf, 1);
return j + i * EPP;
}
- DRelease(pp, 0); /* This dir page is unchanged. */
+ DRelease(&pagebuf, 0); /* This dir page is unchanged. */
}
}
/* If we make it here, the directory is full. */
- DRelease(dhp, 1);
+ DRelease(&headerbuf, 1);
return -1;
}
{ /* Add a page to a directory. */
int i;
struct PageHeader *pp;
+ struct DirBuffer pagebuf;
+
+ /* Get a new buffer labelled dir,pageno */
+ DNew(dir, pageno, &pagebuf);
+ pp = (struct PageHeader *)pagebuf.data;
- pp = (struct PageHeader *)DNew(dir, pageno); /* Get a new buffer labelled dir,pageno */
pp->tag = htons(1234);
if (pageno > 0)
pp->pgcount = 0;
pp->freebitmap[0] = 0x01;
for (i = 1; i < EPP / 8; i++) /* It's a constant */
pp->freebitmap[i] = 0;
- DRelease(pp, 1);
+ DRelease(&pagebuf, 1);
}
/* Free a whole bunch of directory entries. */
{
int i;
int page;
+ struct DirBuffer headerbuf, pagehdbuf;
struct DirHeader *dhp;
struct PageHeader *pp;
page = firstblob / EPP;
firstblob -= EPP * page; /* convert to page-relative entry */
- dhp = (struct DirHeader *)DRead(dir, 0);
- if (!dhp)
+
+ if (DRead(dir, 0, &headerbuf) != 0)
return;
+ dhp = (struct DirHeader *)headerbuf.data;
+
if (page < MAXPAGES)
dhp->alloMap[page] += nblobs;
- DRelease(dhp, 1);
- pp = (struct PageHeader *)DRead(dir, page);
- if (pp)
- for (i = 0; i < nblobs; i++)
- pp->freebitmap[(firstblob + i) >> 3] &=
- ~(1 << ((firstblob + i) & 7));
- DRelease(pp, 1);
+
+ DRelease(&headerbuf, 1);
+
+ if (DRead(dir, page, &pagehdbuf) != 0)
+ return;
+ pp = (struct PageHeader *)pagehdbuf.data;
+
+ for (i = 0; i < nblobs; i++)
+ pp->freebitmap[(firstblob + i) >> 3] &= ~(1 << ((firstblob + i) & 7));
+
+ DRelease(&pagehdbuf, 1);
}
/*
MakeDir(void *dir, afs_int32 * me, afs_int32 * parent)
{
int i;
+ struct DirBuffer buffer;
struct DirHeader *dhp;
- dhp = (struct DirHeader *)DNew(dir, 0);
+
+ DNew(dir, 0, &buffer);
+ dhp = (struct DirHeader *)buffer.data;
+
dhp->header.pgcount = htons(1);
dhp->header.tag = htons(1234);
dhp->header.freecount = (EPP - DHE - 1);
dhp->alloMap[i] = EPP;
for (i = 0; i < NHASHENT; i++)
dhp->hashTable[i] = 0;
- DRelease(dhp, 1);
+ DRelease(&buffer, 1);
Create(dir, ".", me);
Create(dir, "..", parent); /* Virtue is its own .. */
return 0;
Lookup(void *dir, char *entry, void *voidfid)
{
afs_int32 *fid = (afs_int32 *) voidfid;
+ struct DirBuffer firstbuf, prevbuf;
struct DirEntry *firstitem;
- unsigned short *previtem;
- firstitem = FindItem(dir, entry, &previtem);
- if (firstitem == 0)
+ if (FindItem(dir, entry, &prevbuf, &firstbuf) != 0)
return ENOENT;
- DRelease(previtem, 0);
+ DRelease(&prevbuf, 0);
+ firstitem = (struct DirEntry *)firstbuf.data;
+
fid[1] = ntohl(firstitem->fid.vnode);
fid[2] = ntohl(firstitem->fid.vunique);
- DRelease(firstitem, 0);
+ DRelease(&firstbuf, 0);
return 0;
}
LookupOffset(void *dir, char *entry, void *voidfid, long *offsetp)
{
afs_int32 *fid = (afs_int32 *) voidfid;
+ struct DirBuffer firstbuf, prevbuf;
struct DirEntry *firstitem;
- unsigned short *previtem;
- firstitem = FindItem(dir, entry, &previtem);
- if (firstitem == 0)
+ if (FindItem(dir, entry, &prevbuf, &firstbuf) != 0)
return ENOENT;
- DRelease(previtem, 0);
+ DRelease(&prevbuf, 0);
+ firstitem = (struct DirEntry *)firstbuf.data;
+
fid[1] = ntohl(firstitem->fid.vnode);
fid[2] = ntohl(firstitem->fid.vunique);
if (offsetp)
- *offsetp = DVOffset(firstitem);
- DRelease(firstitem, 0);
+ *offsetp = DVOffset(&firstbuf);
+ DRelease(&firstbuf, 0);
return 0;
}
+/*
+ * Enumerate the contents of a directory. Break when hook function
+ * returns non 0.
+ */
+
int
EnumerateDir(void *dir, int (*hookproc) (void *dir, char *name,
afs_int32 vnode, afs_int32 unique),
void *hook)
{
- /* Enumerate the contents of a directory.
- * Break when hook function returns non 0.
- */
int i;
int num;
+ struct DirBuffer headerbuf, entrybuf;
struct DirHeader *dhp;
struct DirEntry *ep;
int code = 0;
- dhp = (struct DirHeader *)DRead(dir, 0);
- if (!dhp)
- return EIO; /* first page should be there */
+ if (DRead(dir, 0, &headerbuf) != 0)
+ return EIO;
+ dhp = (struct DirHeader *)headerbuf.data;
for (i = 0; i < NHASHENT; i++) {
/* For each hash chain, enumerate everyone on the list. */
while (num != 0) {
/* Walk down the hash table list. */
DErrno = 0;
- ep = GetBlob(dir, num);
- if (!ep) {
+ if (GetBlob(dir, num, &entrybuf) != 0) {
if (DErrno) {
/* we failed, return why */
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return DErrno;
}
break;
}
+ ep = (struct DirEntry *)entrybuf.data;
num = ntohs(ep->next);
code = (*hookproc) (hook, ep->name, ntohl(ep->fid.vnode),
ntohl(ep->fid.vunique));
- DRelease(ep, 0);
+ DRelease(&entrybuf, 0);
if (code)
break;
}
}
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
/* Enumerate the contents of a directory. */
int i;
int num;
+ struct DirBuffer headerbuf, entrybuf;
struct DirHeader *dhp;
struct DirEntry *ep;
- dhp = (struct DirHeader *)DRead(dir, 0);
- if (!dhp)
+
+ if (DRead(dir, 0, &headerbuf) != 0)
return 0;
+ dhp = (struct DirHeader *)headerbuf.data;
+
for (i = 0; i < NHASHENT; i++) {
/* For each hash chain, enumerate everyone on the list. */
num = ntohs(dhp->hashTable[i]);
while (num != 0) {
/* Walk down the hash table list. */
- ep = GetBlob(dir, num);
- if (!ep)
- break;
+ if (GetBlob(dir, num, &entrybuf) != 0);
+ break;
+ ep = (struct DirEntry *)entrybuf.data;
if (strcmp(ep->name, "..") && strcmp(ep->name, ".")) {
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 1;
}
num = ntohs(ep->next);
- DRelease(ep, 0);
+ DRelease(&entrybuf, 0);
}
}
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
-struct DirEntry *
-GetBlob(void *dir, afs_int32 blobno)
+int
+GetBlob(void *dir, afs_int32 blobno, struct DirBuffer *buffer)
{
- /* Return a pointer to an entry, given its number. */
- struct DirEntry *ep;
- ep = DRead(dir, blobno >> LEPP);
- if (!ep)
- return 0;
- return (struct DirEntry *)(((long)ep) + 32 * (blobno & (EPP - 1)));
+ int code;
+
+ memset(buffer, 0, sizeof(struct DirBuffer));
+
+ code = DRead(dir, blobno >> LEPP, buffer);
+ if (code)
+ return code;
+
+ buffer->data = (void *)(((long)buffer->data) + 32 * (blobno & (EPP - 1)));
+
+ return 0;
}
int
* found, however, no items are left locked, and a null pointer is
* returned instead. */
-static struct DirEntry *
-FindItem(void *dir, char *ename, unsigned short **previtem)
+static int
+FindItem(void *dir, char *ename, struct DirBuffer *prevbuf,
+ struct DirBuffer *itembuf )
{
- int i;
+ int i, code;
+ struct DirBuffer curr, prev;
struct DirHeader *dhp;
- unsigned short *lp;
struct DirEntry *tp;
+
+ memset(prevbuf, 0, sizeof(struct DirBuffer));
+ memset(itembuf, 0, sizeof(struct DirBuffer));
+
+ code = DRead(dir, 0, &prev);
+ if (code)
+ return code;
+ dhp = (struct DirHeader *)prev.data;
+
i = DirHash(ename);
- dhp = (struct DirHeader *)DRead(dir, 0);
- if (!dhp)
- return 0;
if (dhp->hashTable[i] == 0) {
/* no such entry */
- DRelease(dhp, 0);
- return 0;
+ DRelease(&prev, 0);
+ return ENOENT;
}
- tp = GetBlob(dir, (u_short) ntohs(dhp->hashTable[i]));
- if (!tp) {
- DRelease(dhp, 0);
- return 0;
+
+ code = GetBlob(dir, (u_short) ntohs(dhp->hashTable[i]), &curr);
+ if (code) {
+ DRelease(&prev, 0);
+ return code;
}
- lp = &(dhp->hashTable[i]);
+
+ prev.data = &(dhp->hashTable[i]);
+
while (1) {
- /* Look at each hash conflict entry. */
+ /* Look at each entry on the hash chain */
+ tp = (struct DirEntry *)curr.data;
if (!strcmp(ename, tp->name)) {
- /* Found our entry. */
- *previtem = lp;
- return tp;
+ /* Found it! */
+ *prevbuf = prev;
+ *itembuf = curr;
+ return 0;
}
- DRelease(lp, 0);
- lp = &(tp->next);
+ DRelease(&prev, 0);
if (tp->next == 0) {
/* The end of the line */
- DRelease(lp, 0); /* Release all locks. */
- return 0;
+ DRelease(&curr, 0);
+ return ENOENT;
}
- tp = GetBlob(dir, (u_short) ntohs(tp->next));
- if (!tp) {
- DRelease(lp, 0);
- return 0;
+
+ prev = curr;
+ prev.data = &(tp->next);
+
+ code = GetBlob(dir, (u_short) ntohs(tp->next), &curr);
+ if (code) {
+ DRelease(&prev, 0);
+ return code;
}
}
+ /* Never reached */
}
-static struct DirEntry *
-FindFid (void *dir, afs_uint32 vnode, afs_uint32 unique)
+static int
+FindFid (void *dir, afs_uint32 vnode, afs_uint32 unique,
+ struct DirBuffer *itembuf)
{
/* Find a directory entry, given the vnode and uniquifier of a object.
* This entry returns a pointer to a locked buffer. If no entry is found,
* however, no items are left locked, and a null pointer is returned
* instead.
*/
- int i;
+ int i, code;
+ unsigned short next;
+ struct DirBuffer curr, header;
struct DirHeader *dhp;
- unsigned short *lp;
struct DirEntry *tp;
- dhp = (struct DirHeader *) DRead(dir,0);
- if (!dhp) return 0;
+
+ memset(itembuf, 0, sizeof(struct DirBuffer));
+
+ code = DRead(dir, 0, &header);
+ if (code)
+ return code;
+ dhp = (struct DirHeader *)header.data;
+
for (i=0; i<NHASHENT; i++) {
if (dhp->hashTable[i] != 0) {
- tp = GetBlob(dir,(u_short)ntohs(dhp->hashTable[i]));
- if (!tp) { /* should not happen */
- DRelease(dhp, 0);
- return 0;
+ code = GetBlob(dir, (u_short)ntohs(dhp->hashTable[i]),
+ &curr);
+ if (code) {
+ DRelease(&header, 0);
+ return code;
}
- while(tp) {
+
+ while (curr.data != NULL) {
+ tp = (struct DirEntry *)curr.data;
+
if (vnode == ntohl(tp->fid.vnode)
&& unique == ntohl(tp->fid.vunique)) {
- DRelease(dhp, 0);
- return tp;
+ DRelease(&header, 0);
+ *itembuf = curr;
+ return 0;
}
- lp = &(tp->next);
- if (tp->next == 0)
+
+ next = tp->next;
+ DRelease(&curr, 0);
+
+ if (next == 0)
break;
- tp = GetBlob(dir,(u_short)ntohs(tp->next));
- DRelease(lp, 0);
+
+ code = GetBlob(dir, (u_short)ntohs(next), &curr);
+ if (code) {
+ DRelease(&header, 0);
+ return code;
+ }
}
- DRelease(lp, 0);
}
}
- DRelease(dhp, 0);
- return NULL;
+ DRelease(&header, 0);
+ return ENOENT;
}
int
afs_uint32 length)
{
/* Look for the name pointing to given vnode and unique in a directory */
+ struct DirBuffer entrybuf;
struct DirEntry *entry;
int code = 0;
- entry = FindFid(dir, vnode, unique);
- if (!entry)
+ if (FindFid(dir, vnode, unique, &entrybuf) != 0)
return ENOENT;
+ entry = (struct DirEntry *)entrybuf.data;
+
if (strlen(entry->name) >= length)
code = E2BIG;
else
strcpy(name, entry->name);
- DRelease(entry, 0);
+ DRelease(&entrybuf, 0);
return code;
}
afs_uint32 *old_fid,
afs_uint32 *new_fid)
{
+ struct DirBuffer prevbuf, entrybuf;
struct DirEntry *firstitem;
- unsigned short *previtem;
struct MKFid *fid_old = (struct MKFid *) old_fid;
struct MKFid *fid_new = (struct MKFid *) new_fid;
/* Find entry. */
- firstitem = FindItem(dir, entry, &previtem);
- if (firstitem == 0) {
+ if (FindItem(dir, entry, &prevbuf, &entrybuf) != 0)
return ENOENT;
- }
- DRelease(previtem, 1);
+ firstitem = (struct DirEntry *)entrybuf.data;
+ DRelease(&prevbuf, 1);
+
/* Replace fid. */
if (!old_fid ||
((htonl(fid_old->vnode) == firstitem->fid.vnode) &&
firstitem->fid.vunique = htonl(fid_new->vunique);
}
- DRelease(firstitem, 1);
+ DRelease(&entrybuf, 1);
return 0;
}
char padding[32 - (5 + EPP / 8)];
};
+struct DirBuffer {
+ void *buffer;
+ void *data;
+};
+
struct DirHeader {
/* A directory header object. */
struct PageHeader header;
* user space code. One implementation is in afs/afs_buffer.c; the
* other is in dir/buffer.c.
*/
-extern int DVOffset(void *ap);
+extern int DVOffset(struct DirBuffer *);
/* This is private to buffer.c */
afs_int32 vnode, afs_int32 unique),
void *hook);
extern int IsEmpty(void *dir);
-extern struct DirEntry *GetBlob(void *dir, afs_int32 blobno);
+extern int GetBlob(void *dir, afs_int32 blobno, struct DirBuffer *);
extern int DirHash(char *string);
extern int DStat(int *abuffers, int *acalls, int *aios);
-extern void DRelease(void *loc, int flag);
-extern int DVOffset(void *ap);
+extern void DRelease(struct DirBuffer *loc, int flag);
extern int DFlushVolume(afs_int32 vid);
extern int DFlushEntry(afs_int32 *fid);
extern int InverseLookup (void *dir, afs_uint32 vnode, afs_uint32 unique,
in afs_prototypes.h */
#ifndef KERNEL
extern int DInit(int abuffers);
-extern void *DRead(afs_int32 *fid, int page);
+extern int DRead(afs_int32 *fid, int page, struct DirBuffer *);
extern int DFlush(void);
-extern void *DNew(afs_int32 *fid, int page);
+extern int DNew(afs_int32 *fid, int page, struct DirBuffer *);
extern void DZap(afs_int32 *fid);
/* salvage.c */
extern int afs_dir_IsEmpty(void *dir);
extern int afs_dir_ChangeFid(void *dir, char *entry, afs_uint32 *old_fid,
afs_uint32 *new_fid);
-extern struct DirEntry *afs_dir_GetBlob(void *dir, afs_int32 blobno);
+extern int afs_dir_GetBlob(void *dir, afs_int32 blobno, struct DirBuffer *);
#endif
#endif /* !defined(__AFS_DIR_H) */
struct DirHeader *dhp;
struct PageHeader *pp;
struct DirEntry *ep;
+ struct DirBuffer headerbuf, pagebuf, entrybuf;
int i, j, k, up;
int havedot = 0, havedotdot = 0;
int usedPages, count, entry;
int eaSize;
afs_int32 entcount, maxents;
unsigned short ne;
+ int code;
eaSize = BIGMAXPAGES * EPP / 8;
/* Read the directory header */
- dhp = (struct DirHeader *)DRead(file, 0);
- if (!dhp) {
+ code = DRead(file,0, &headerbuf);
+ if (code) {
/* if DErrno is 0, then we know that the read worked, but was short,
* and the damage is permanent. Otherwise, we got an I/O or programming
* error. Claim the dir is OK, but log something.
printf("First page in directory does not exist.\n");
return 0;
}
+ dhp = (struct DirHeader *)headerbuf.data;
/* Check magic number for first page */
if (dhp->header.tag != htons(1234)) {
printf("Bad first pageheader magic number.\n");
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
* two must exist for "." and ".."
*/
printf("The dir header alloc map for page %d is bad.\n", i);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
} else {
if ((j < 0) || (j > EPP)) {
printf("The dir header alloc map for page %d is bad.\n", i);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
}
printf
("A partially-full page occurs in slot %d, after the dir end.\n",
i);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
} else if (j == EPP) { /* is this the last page */
if (usedPages < up) {
printf
("Count of used directory pages does not match count in directory header\n");
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
*/
for (i = 0; i < usedPages; i++) {
/* Read the page header */
- pp = (struct PageHeader *)DRead(file, i);
- if (!pp) {
- DRelease(dhp, 0);
+ code = DRead(file, i, &pagebuf);
+ if (code) {
+ DRelease(&headerbuf, 0);
if (DErrno != 0) {
/* couldn't read page, but not because it wasn't there permanently */
printf("Failed to read dir page %d (errno %d)\n", i, DErrno);
printf("Directory shorter than alloMap indicates (page %d)\n", i);
return 0;
}
+ pp = (struct PageHeader *)pagebuf.data;
/* check the tag field */
if (pp->tag != htons(1234)) {
printf("Directory page %d has a bad magic number.\n", i);
- DRelease(pp, 0);
- DRelease(dhp, 0);
+ DRelease(&pagebuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
printf
("Header alloMap count doesn't match count in freebitmap for page %d.\n",
i);
- DRelease(pp, 0);
- DRelease(dhp, 0);
+ DRelease(&pagebuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
- DRelease(pp, 0);
+ DRelease(&pagebuf, 0);
}
/* Initialize the in-memory freebit map for all pages. */
/* Verify that the entry is within range */
if (entry < 0 || entry >= maxents) {
printf("Out-of-range hash id %d in chain %d.\n", entry, i);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
/* Read the directory entry */
DErrno = 0;
- ep = GetBlob(file, entry);
- if (!ep) {
+ code = GetBlob(file, entry, &entrybuf);
+ if (code) {
if (DErrno != 0) {
/* something went wrong reading the page, but it wasn't
* really something wrong with the dir that we can fix.
*/
printf("Could not get dir blob %d (errno %d)\n", entry,
DErrno);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
Die("dirok3");
}
printf("Invalid hash id %d in chain %d.\n", entry, i);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
+ ep = (struct DirEntry *)entrybuf.data;
+
ne = ntohs(ep->next);
/* There can't be more than maxents entries */
if (++entcount >= maxents) {
printf("Directory's hash chain %d is circular.\n", i);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
if (ep->name[0] == '\000') {
printf("Dir entry %"AFS_PTR_FMT
" in chain %d has bogus (null) name.\n", ep, i);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
if (ep->flag != FFIRST) {
printf("Dir entry %"AFS_PTR_FMT
" in chain %d has bogus flag field.\n", ep, i);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
if (j >= MAXENAME) { /* MAXENAME counts the null */
printf("Dir entry %"AFS_PTR_FMT
" in chain %d has too-long name.\n", ep, i);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
printf("Dir entry %"AFS_PTR_FMT
" should be in hash bucket %d but IS in %d.\n",
ep, j, i);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
("Dir entry %"AFS_PTR_FMT
", index 13 has name '%s' should be '.'\n",
ep, ep->name);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
}
("Dir entry %"AFS_PTR_FMT
", index 14 has name '%s' should be '..'\n",
ep, ep->name);
- DRelease(ep, 0);
- DRelease(dhp, 0);
+ DRelease(&entrybuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
}
/* CHECK FOR DUPLICATE NAMES? */
- DRelease(ep, 0);
+ DRelease(&entrybuf, 0);
}
}
if (!havedot || !havedotdot) {
printf
("Directory entry '.' or '..' does not exist or is in the wrong index.\n");
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
* Note that if this matches, alloMap has already been checked against it.
*/
for (i = 0; i < usedPages; i++) {
- pp = DRead(file, i);
- if (!pp) {
+ code = DRead(file, i, &pagebuf);
+ if (code) {
printf
("Failed on second attempt to read dir page %d (errno %d)\n",
i, DErrno);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
/* if DErrno is 0, then the dir is really bad, and we return dir *not* OK.
* otherwise, we want to return true (1), meaning the dir isn't known
* to be bad (we can't tell, since I/Os are failing.
else
return 0; /* dir is really shorter */
}
+ pp = (struct PageHeader *)pagebuf.data;
count = i * (EPP / 8);
for (j = 0; j < EPP / 8; j++) {
printf
("Entry freebitmap error, page %d, map offset %d, %x should be %x.\n",
i, j, pp->freebitmap[j], eaMap[count + j]);
- DRelease(pp, 0);
- DRelease(dhp, 0);
+ DRelease(&pagebuf, 0);
+ DRelease(&headerbuf, 0);
return 0;
}
}
- DRelease(pp, 0);
+ DRelease(&pagebuf, 0);
}
/* Finally cleanup and return. */
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 1;
}
char tname[256];
int i;
char *tp;
+ struct DirBuffer headerbuf, entrybuf;
struct DirHeader *dhp;
struct DirEntry *ep;
int entry;
/* Find out how many pages are valid, using stupid heuristic since DRead
* never returns null.
*/
- dhp = (struct DirHeader *)DRead(fromFile, 0);
- if (!dhp) {
+ code = DRead(fromFile, 0, &headerbuf);
+ if (code) {
printf("Failed to read first page of fromDir!\n");
/* if DErrno != 0, then our call failed and we should let our
* caller know that there's something wrong with the new dir. If not,
*/
return DErrno;
}
+ dhp = (struct DirHeader *)headerbuf.data;
usedPages = ComputeUsedPages(dhp);
("Warning: bogus hash table entry encountered, ignoring.\n");
break;
}
+
DErrno = 0;
- ep = GetBlob(fromFile, entry);
- if (!ep) {
+ code = GetBlob(fromFile, entry, &entrybuf);
+ if (code) {
if (DErrno) {
printf
("can't continue down hash chain (entry %d, errno %d)\n",
entry, DErrno);
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return DErrno;
}
printf
("Warning: bogus hash chain encountered, switching to next.\n");
break;
}
+ ep = (struct DirEntry *)entrybuf.data;
+
strncpy(tname, ep->name, MAXENAME);
tname[MAXENAME - 1] = '\000'; /* just in case */
tp = tname;
printf
("Create of %s returned code %d, skipping to next hash chain.\n",
tname, code);
- DRelease(ep, 0);
+ DRelease(&entrybuf, 0);
break;
}
}
- DRelease(ep, 0);
+ DRelease(&entrybuf, 0);
}
}
/* Clean up things. */
- DRelease(dhp, 0);
+ DRelease(&headerbuf, 0);
return 0;
}