return;
}
+/*!
+ * Read and return the requested directory page.
+ *
+ * \param[in] adc pointer to directory dcache
+ * \param[in] page number of the desired directory page
+ * \param[out] entry buffer to return requested page
+ * \param[out] physerr (optional) pointer to return errno, if any
+ *
+ * \retval 0 success
+ * \retval non-zero invalid directory or internal IO error;
+ * if physerr is supplied by caller, it will be set:
+ * 0 logical error
+ * errno physical error
+ */
int
-DRead(struct dcache *adc, int page, struct DirBuffer *entry)
+DReadWithErrno(struct dcache *adc, int page, struct DirBuffer *entry, int *physerr)
{
/* Read a page from the disk. */
struct buffer *tb, *tb2;
AFS_STATCNT(DRead);
+ if (physerr != NULL)
+ *physerr = 0;
+
memset(entry, 0, sizeof(struct DirBuffer));
+ if (adc->f.chunk == 0 && adc->f.chunkBytes == 0) {
+ /* The directory blob is empty, apparently. This is not a valid dir
+ * blob, so throw an error. */
+ return EIO;
+ }
+ if (page * AFS_BUFFER_PAGESIZE >= adc->f.chunkBytes) {
+ return ENOENT; /* past the end */
+ }
+
ObtainWriteLock(&afs_bufferLock, 256);
#define bufmatch(tb) (tb->page == page && tb->fid == adc->index)
ObtainWriteLock(&tb->lock, 260);
tb->lockers++;
ReleaseWriteLock(&afs_bufferLock);
- code = 0;
- if (adc->f.chunk == 0 && adc->f.chunkBytes == 0) {
- /* The directory blob is empty, apparently. This is not a valid dir
- * blob, so throw an error. */
- code = EIO;
- } else if (page * AFS_BUFFER_PAGESIZE >= adc->f.chunkBytes) {
- code = ENOENT; /* past the end */
- }
- if (code) {
- tb->fid = NULLIDX;
- afs_reset_inode(&tb->inode);
- tb->lockers--;
- ReleaseWriteLock(&tb->lock);
- return code;
- }
tfile = afs_CFileOpen(&adc->f.inode);
- osi_Assert(tfile);
+ if (!tfile) {
+ code = EIO;
+ goto error;
+ }
code =
afs_CFileRead(tfile, tb->page * AFS_BUFFER_PAGESIZE, tb->data,
AFS_BUFFER_PAGESIZE);
afs_CFileClose(tfile);
if (code < AFS_BUFFER_PAGESIZE) {
- tb->fid = NULLIDX;
- afs_reset_inode(&tb->inode);
- tb->lockers--;
- ReleaseWriteLock(&tb->lock);
- return EIO;
+ if (code < 0 && physerr != NULL)
+ *physerr = -code;
+ code = EIO;
+ goto error;
}
/* Note that findslot sets the page field in the buffer equal to
* what it is searching for. */
entry->buffer = tb;
entry->data = tb->data;
return 0;
+
+ error:
+ tb->fid = NULLIDX;
+ afs_reset_inode(&tb->inode);
+ tb->lockers--;
+ ReleaseWriteLock(&tb->lock);
+ return code;
+}
+
+/*!
+ * Read and return the requested directory page.
+ *
+ * \param[in] adc pointer to directory dcache
+ * \param[in] page number of the desired directory page
+ * \param[out] entry buffer to return requested page
+ *
+ * \retval 0 success
+ * \retval non-zero invalid directory or internal IO error;
+ */
+int
+DRead(struct dcache *adc, int page, struct DirBuffer *entry)
+{
+ return DReadWithErrno(adc, page, entry, NULL);
}
static void
if (lp->dirty) {
/* see DFlush for rationale for not getting and locking the dcache */
tfile = afs_CFileOpen(&lp->inode);
- osi_Assert(tfile);
+ if (!tfile)
+ return NULL; /* Callers will flag as EIO */
+
afs_CFileWrite(tfile, lp->page * AFS_BUFFER_PAGESIZE, lp->data,
AFS_BUFFER_PAGESIZE);
lp->dirty = 0;
if (tp == NULL)
return;
- tp = entry->buffer;
ObtainWriteLock(&tp->lock, 261);
tp->lockers--;
if (flag)