vn_reinit(AFSTOV(avc));
#endif
afs_FreeAllAxs(&(avc->Access));
- if (!afs_shuttingdown)
- afs_QueueVCB(avc, slept);
ObtainWriteLock(&afs_xcbhash, 460);
afs_DequeueCallback(avc); /* remove it from queued callbacks list */
avc->f.states &= ~(CStatd | CUnique);
else
osi_dnlc_purgevp(avc);
+ if (!afs_shuttingdown)
+ afs_QueueVCB(avc, slept);
+
/*
* Next, keep track of which vnodes we've deleted for create's
* optimistic synchronization algorithm
struct AFSFetchStatus *astat, struct vrequest *areq)
{
afs_size_t length;
-#ifdef AFS_DARWIN80_ENV
- int fixup = 0;
-#endif
AFS_STATCNT(afs_ProcessFS);
#ifdef AFS_64BIT_CLIENT
avc->f.m.Group = astat->Group;
avc->f.m.LinkCount = astat->LinkCount;
if (astat->FileType == File) {
-#ifdef AFS_DARWIN80_ENV
- if (avc->f.m.Type != VREG)
- fixup = 1;
-#endif
vSetType(avc, VREG);
avc->f.m.Mode |= S_IFREG;
} else if (astat->FileType == Directory) {
-#ifdef AFS_DARWIN80_ENV
- if (avc->f.m.Type != VDIR)
- fixup = 1;
-#endif
vSetType(avc, VDIR);
avc->f.m.Mode |= S_IFDIR;
} else if (astat->FileType == SymbolicLink) {
if (afs_fakestat_enable && (avc->f.m.Mode & 0111) == 0) {
-#ifdef AFS_DARWIN80_ENV
- if (avc->f.m.Type != VDIR)
- fixup = 1;
-#endif
vSetType(avc, VDIR);
avc->f.m.Mode |= S_IFDIR;
} else {
-#ifdef AFS_DARWIN80_ENV
- if (avc->f.m.Type != VLNK)
- fixup = 1;
-#endif
vSetType(avc, VLNK);
avc->f.m.Mode |= S_IFLNK;
}
avc->mvstat = 1;
}
}
-#ifdef AFS_DARWIN80_ENV
- if (fixup)
- printf("found mistyped vnode!\n");
-#endif
avc->f.anyAccess = astat->AnonymousAccess;
#ifdef badidea
if ((astat->CallerAccess & ~astat->AnonymousAccess))
afs_PutVolume(volp, READ_LOCK);
}
+void
+afs_BadFetchStatus(struct afs_conn *tc)
+{
+ int addr = ntohl(tc->parent->srvr->sa_ip);
+ afs_warn("afs: Invalid AFSFetchStatus from server %u.%u.%u.%u\n",
+ (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff,
+ (addr) & 0xff);
+ afs_warn("afs: This suggests the server may be sending bad data that "
+ "can lead to availability issues or data corruption. The "
+ "issue has been avoided for now, but it may not always be "
+ "detectable. Please upgrade the server if possible.\n");
+}
+
+/**
+ * Check if a given AFSFetchStatus structure is sane.
+ *
+ * @param[in] tc The server from which we received the status
+ * @param[in] status The status we received
+ *
+ * @return whether the given structure is valid or not
+ * @retval 0 the structure is fine
+ * @retval nonzero the structure looks like garbage; act as if we received
+ * the returned error code from the server
+ */
+int
+afs_CheckFetchStatus(struct afs_conn *tc, struct AFSFetchStatus *status)
+{
+ if (status->errorCode ||
+ status->InterfaceVersion != 1 ||
+ !(status->FileType > Invalid && status->FileType <= SymbolicLink) ||
+ status->ParentVnode == 0 || status->ParentUnique == 0) {
+
+ afs_warn("afs: FetchStatus ec %u iv %u ft %u pv %u pu %u\n",
+ (unsigned)status->errorCode, (unsigned)status->InterfaceVersion,
+ (unsigned)status->FileType, (unsigned)status->ParentVnode,
+ (unsigned)status->ParentUnique);
+ afs_BadFetchStatus(tc);
+
+ return VBUSY;
+ }
+ return 0;
+}
+
/*!
* Must be called with avc write-locked
* don't absolutely have to invalidate the hint unless the dv has
XSTATS_END_TIME;
+ if (code == 0) {
+ code = afs_CheckFetchStatus(tc, Outsp);
+ }
+
} else
code = -1;
} while (afs_Analyze
*
* \param avc Pointer to the cache entry to reset
* \param acred
+ * \param skipdnlc skip the dnlc purge for this vnode
*
* \note avc must be write locked on entry
+ *
+ * \note The caller should purge the dnlc when skipdnlc is set.
*/
void
-afs_ResetVCache(struct vcache *avc, afs_ucred_t *acred)
+afs_ResetVCache(struct vcache *avc, afs_ucred_t *acred, afs_int32 skipdnlc)
{
ObtainWriteLock(&afs_xcbhash, 456);
afs_DequeueCallback(avc);
ReleaseWriteLock(&afs_xcbhash);
/* now find the disk cache entries */
afs_TryToSmush(avc, acred, 1);
- osi_dnlc_purgedp(avc);
+ if (!skipdnlc) {
+ osi_dnlc_purgedp(avc);
+ }
if (avc->linkData && !(avc->f.states & CCore)) {
afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
avc->linkData = NULL;