[ --enable-bitmap-later enable fast startup of file server by not reading bitmap till needed],, enable_bitmap_later="no")
AC_ARG_ENABLE( demand-attach-fs,
[ --enable-demand-attach-fs enable Demand Attach Fileserver (please see documentation)],, enable_demand_attach_fs="no")
+AC_ARG_ENABLE( disconnected,
+[ --enable-disconnected enable disconnected support in cache manager (experimental)],, enable_disconnected="no")
AC_ARG_ENABLE( unix-sockets,
[ --enable-unix-sockets enable use of unix domain sockets for fssync],, enable_unix_sockets="yes")
AC_ARG_ENABLE( full-vos-listvol-switch,
fi
AC_SUBST(DEMAND_ATTACH)
+if test "$enable_disconnected" = "yes"; then
+ AC_DEFINE(AFS_DISCON_ENV, 1, [define if you want support for disconnected operation])
+fi
+
if test "$enable_unix_sockets" = "yes"; then
AC_DEFINE(USE_UNIX_SOCKETS, 1, [define if you want to use UNIX sockets for fssync.])
USE_UNIX_SOCKETS="yes"
#include "afs/icl.h"
#include "afs/afs_stats.h"
#include "afs/afs_prototypes.h"
+#include "afs/discon.h"
if ((code = afs_InitReq(&treq, acred)))
return code;
+ AFS_DISCON_LOCK();
+
if (afs_fakestat_enable && avc->mvstat == 1) {
code = afs_TryEvalFakeStat(&avc, &fakestate, &treq);
if (code == 0 && avc->mvstat == 1) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return 0;
}
} else {
if (code) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return code;
}
code = afs_VerifyVCache(avc, &treq);
if (code) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
code = afs_CheckCode(code, &treq, 16);
return code;
}
/* if we're looking for write access and we have a read-only file system, report it */
if ((amode & VWRITE) && (avc->states & CRO)) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return EROFS;
}
+
+ /* If we're looking for write access, and we're disconnected without logging, forget it */
+ if ((amode & VWRITE) && (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING)) {
+ afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
+ /*printf("Network is down in afs_vnop_access\n");*/
+ return ENETDOWN;
+ }
+
code = 1; /* Default from here on in is access ok. */
if (avc->states & CForeign) {
/* In the dfs xlator the EXEC bit is mapped to LOOKUP */
}
}
afs_PutFakeStat(&fakestate);
+
+ AFS_DISCON_UNLOCK();
+
if (code) {
return 0; /* if access is ok */
} else {
}
#endif
+ AFS_DISCON_LOCK();
+
#ifdef AFS_BOZONLOCK_ENV
afs_BozonLock(&avc->pvnLock, avc);
#endif
}
}
}
+
+ AFS_DISCON_UNLOCK();
+
if (!code)
return 0;
code = afs_CheckCode(code, &treq, 14);
if ((code = afs_InitReq(&treq, acred)))
return code;
+ AFS_DISCON_LOCK();
+
afs_InitFakeStat(&fakestate);
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
if (code)
}
}
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ code = ENETDOWN;
+ goto done;
+ }
+
afs_VAttrToAS(avc, attrs, &astat); /* interpret request */
code = 0;
#ifdef AFS_BOZONLOCK_ENV
hzero(avc->flushDV);
osi_FlushText(avc); /* do this after releasing all locks */
}
- if (code == 0) {
- ObtainSharedLock(&avc->lock, 16); /* lock entry */
- code = afs_WriteVCache(avc, &astat, &treq); /* send request */
- ReleaseSharedLock(&avc->lock); /* release lock */
- }
- if (code) {
- ObtainWriteLock(&afs_xcbhash, 487);
- afs_DequeueCallback(avc);
- avc->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- /* error? erase any changes we made to vcache entry */
+
+ if (!AFS_IS_DISCONNECTED) {
+ if (code == 0) {
+ ObtainSharedLock(&avc->lock, 16); /* lock entry */
+ code = afs_WriteVCache(avc, &astat, &treq); /* send request */
+ ReleaseSharedLock(&avc->lock); /* release lock */
+ }
+ if (code) {
+ ObtainWriteLock(&afs_xcbhash, 487);
+ afs_DequeueCallback(avc);
+ avc->states &= ~CStatd;
+ ReleaseWriteLock(&afs_xcbhash);
+ if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
+ osi_dnlc_purgedp(avc);
+ /* error? erase any changes we made to vcache entry */
+ }
+ } else {
+ /* Must be logging - but not implemented yet ... */
+ code = ENETDOWN;
}
#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
if (AFS_NFSXLATORREQ(acred)) {
#endif
done:
afs_PutFakeStat(&fakestate);
+
+ AFS_DISCON_UNLOCK();
code = afs_CheckCode(code, &treq, 15);
return code;
}
if (strlen(aname) > AFSNAMEMAX) {
code = ENAMETOOLONG;
- goto done;
+ goto done3;
}
if (!afs_ENameOK(aname)) {
code = EINVAL;
- goto done;
+ goto done3;
}
switch (attrs->va_type) {
case VBLK:
case VFIFO:
/* We don't support special devices or FIFOs */
code = EINVAL;
- goto done;
+ goto done3;
default:
;
}
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
if (code)
goto done;
goto done;
}
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ code = ENETDOWN;
+ goto done;
+ }
+
tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
ObtainWriteLock(&adp->lock, 135);
if (tdc)
goto done;
}
}
+
+ if (AFS_IS_DISCONNECTED) {
+ /* XXX - If we get here, logging must be enabled (as we bypassed the
+ * earlier check. So - do that logging thang, then return */
+ }
/* if we create the file, we don't do any access checks, since
* that's how O_CREAT is supposed to work */
ReleaseWriteLock(&afs_xvcache);
done:
+ AFS_DISCON_UNLOCK();
+
+ done3:
if (volp)
afs_PutVolume(volp, READ_LOCK);
if (strlen(aname) > AFSNAMEMAX) {
code = ENAMETOOLONG;
- goto done;
+ goto done3;
}
if (!afs_ENameOK(aname)) {
code = EINVAL;
- goto done;
+ goto done3;
}
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
if (code)
goto done;
code = EROFS;
goto done;
}
+
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ /*printf("Network is down in afs_mkdir\n");*/
+ code = ENETDOWN;
+ }
InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
InStatus.ClientModTime = osi_Time();
} else
code = ENOENT;
done:
+ AFS_DISCON_UNLOCK();
+ done3:
afs_PutFakeStat(&fakestate);
code = afs_CheckCode(code, &treq, 26);
done2:
goto done;
}
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
if (code)
goto done;
goto done;
}
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ code = ENETDOWN;
+ goto done;
+ }
+
tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
ObtainWriteLock(&adp->lock, 154);
if (tdc)
code = 0;
done:
+ AFS_DISCON_UNLOCK();
+ done3:
afs_PutFakeStat(&fakestate);
code = afs_CheckCode(code, &treq, 27);
done2:
94.04.13 add "force" parameter. If a child explicitly unlocks a
file, I guess we'll permit it. however, we don't want simple,
innocent closes by children to unlock files in the parent process.
+
+ If called when disconnected support is unabled, the discon_lock must
+ be held
*/
/* clid - nonzero on sgi sunos osf1 only */
int
avc->slocks = 0;
}
if (avc->flockCount == 0) {
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
- RX_AFS_GUNLOCK();
- code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
- &avc->fid.Fid, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
+ if (!AFS_IS_DISCONNECTED) {
+ do {
+ tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+ if (tc) {
+ XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
+ RX_AFS_GUNLOCK();
+ code = RXAFS_ReleaseLock(tc->id, (struct AFSFid *)
+ &avc->fid.Fid, &tsync);
+ RX_AFS_GLOCK();
+ XSTATS_END_TIME;
+ } else
code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
+ } while (afs_Analyze
+ (tc, code, &avc->fid, areq,
+ AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK, NULL));
+ } else {
+ /*printf("Network is dooooooowwwwwwwnnnnnnn\n");*/
+ code = ENETDOWN;
+ }
}
} else {
while (1) { /* set a new lock */
}
}
if (!code && avc->flockCount == 0) {
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME
- (AFS_STATS_FS_RPCIDX_RELEASELOCK);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_ReleaseLock(tc->id,
- (struct AFSFid *)&avc->fid.
- Fid, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
- NULL));
+ if (!AFS_IS_DISCONNECTED) {
+ do {
+ tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+ if (tc) {
+ XSTATS_START_TIME
+ (AFS_STATS_FS_RPCIDX_RELEASELOCK);
+ RX_AFS_GUNLOCK();
+ code =
+ RXAFS_ReleaseLock(tc->id,
+ (struct AFSFid *)&avc->
+ fid.Fid, &tsync);
+ RX_AFS_GLOCK();
+ XSTATS_END_TIME;
+ } else
+ code = -1;
+ } while (afs_Analyze
+ (tc, code, &avc->fid, areq,
+ AFS_STATS_FS_RPCIDX_RELEASELOCK, SHARED_LOCK,
+ NULL));
+ }
}
} else if (avc->flockCount == -1 && (acom & LOCK_EX)) {
if (lockIdcmp2(&flock, avc, NULL, 1, clid)) {
if (avc->flockCount == 0) {
/* we're the first on our block, send the call through */
lockType = ((acom & LOCK_EX) ? LockWrite : LockRead);
- do {
- tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
- RX_AFS_GUNLOCK();
- code = RXAFS_SetLock(tc->id, (struct AFSFid *)
- &avc->fid.Fid, lockType,
- &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &avc->fid, areq,
- AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
- NULL));
+ if (!AFS_IS_DISCONNECTED) {
+ do {
+ tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+ if (tc) {
+ XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
+ RX_AFS_GUNLOCK();
+ code = RXAFS_SetLock(tc->id, (struct AFSFid *)
+ &avc->fid.Fid, lockType,
+ &tsync);
+ RX_AFS_GLOCK();
+ XSTATS_END_TIME;
+ } else
+ code = -1;
+ } while (afs_Analyze
+ (tc, code, &avc->fid, areq,
+ AFS_STATS_FS_RPCIDX_SETLOCK, SHARED_LOCK,
+ NULL));
+ } else
+ /* XXX - Should probably try and log this when we're
+ * XXX - running with logging enabled. But it's horrid
+ */
+ code = 0; /* pretend we worked - ick!!! */
} else
code = 0; /* otherwise, pretend things worked */
}
if ((code = afs_InitReq(&treq, acred)))
return code;
afs_InitFakeStat(&fakestate);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
if (code) {
- afs_PutFakeStat(&fakestate);
- return code;
+ goto done;
}
#ifdef AFS_OSF_ENV
if (flag & VNOFLCK) {
- afs_PutFakeStat(&fakestate);
- return 0;
+ code = 0;
+ goto done;
}
if (flag & CLNFLCK) {
acmd = LOCK_UN;
if (acmd == F_GETLK) {
#endif
if (af->l_type == F_UNLCK) {
- afs_PutFakeStat(&fakestate);
- return 0;
+ code = 0;
+ goto done;
}
#ifndef AFS_OSF_ENV /* getlock is a no-op for osf (for now) */
code = HandleGetLock(avc, af, &treq, clid);
#endif
code = afs_CheckCode(code, &treq, 2); /* defeat buggy AIX optimz */
- afs_PutFakeStat(&fakestate);
- return code;
+ goto done;
} else if ((acmd == F_SETLK) || (acmd == F_SETLKW)
#if (defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)) && !defined(AFS_SUN58_ENV)
|| (acmd == F_RSETLK) || (acmd == F_RSETLKW)) {
* even when they should block */
if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
DoLockWarning();
- afs_PutFakeStat(&fakestate);
- return 0;
+ code = 0;
+ goto done;
}
/* otherwise we can turn this into a whole-file flock */
if (af->l_type == F_RDLCK)
code = HandleFlock(avc, code, &treq, 0, 0 /*!onlymine */ );
#endif
code = afs_CheckCode(code, &treq, 3); /* defeat AIX -O bug */
- afs_PutFakeStat(&fakestate);
- return code;
+ goto done;
}
+ code = EINVAL;
+done:
afs_PutFakeStat(&fakestate);
- return EINVAL;
+ AFS_DISCON_UNLOCK();
+ return code;
}
temp = areq->flags & O_NONBLOCK;
areq->flags |= O_NONBLOCK;
+ /* If we're disconnected, lie and say that we've got no locks. Ick */
+ if (AFS_IS_DISCONNECTED)
+ return 0;
+
do {
tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
if (tc) {
afs_PutFakeStat(&fakestate);
return flockDone;
}
+
+ AFS_DISCON_LOCK();
+
/* first determine whether this is any sort of vnode */
if (fd->f_type == DTYPE_VNODE) {
/* good, this is a vnode; next see if it is an AFS vnode */
/* This is an AFS vnode, so do the work */
code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
if (code) {
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
return code;
}
#else
FP_UNREF(fd);
#endif
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
return code;
#else /* AFS_OSF_ENV */
#else
flock();
#endif
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
return;
#endif
afs_InitFakeStat(&vfakestate);
afs_InitFakeStat(&dfakestate);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&avc, &vfakestate, &treq);
if (code)
goto done;
code = EROFS;
goto done;
}
+
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ code = ENETDOWN;
+ goto done;
+ }
tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
ObtainWriteLock(&adp->lock, 145);
code = afs_CheckCode(code, &treq, 24);
afs_PutFakeStat(&vfakestate);
afs_PutFakeStat(&dfakestate);
+ AFS_DISCON_UNLOCK();
done2:
return code;
}
volnamep = data;
tcell = afs_GetCell(cellnum, READ_LOCK);
} else {
+ /*printf("No cellname %s , or cellnum %d , returning ENODEV\n",
+ data, cellnum);*/
return ENODEV;
}
- if (!tcell)
+ if (!tcell) {
+ /*printf("Lookup failed, returning ENODEV\n");*/
return ENODEV;
+ }
cellidx = tcell->cellIndex;
mtptCell = tcell->cellNum; /* The cell for the mountpoint */
tfid.Fid.Volume = volid; /* remember BK volume */
tfid.Cell = mtptCell;
tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK); /* get the new one */
- if (!tvp)
+ if (!tvp) {
+ /*printf("afs_GetVolume failed - returning ENODEV");*/
return ENODEV; /* oops, can't do it */
+ }
goto done;
}
* ".backup" in it, this will get the volume struct for the RW volume.
* The RO volume will be prefetched if requested (but not returned).
*/
+ /*printf("Calling GetVolumeByName\n");*/
tvp = afs_GetVolumeByName(volnamep, mtptCell, prefetch, areq, WRITE_LOCK);
/* If no volume was found in this cell, try the associated linked cell */
osi_FreeSmallSpace(buf);
}
- if (!tvp)
+ if (!tvp) {
+ /*printf("Couldn't find the volume\n");*/
return ENODEV; /* Couldn't find the volume */
+ }
/* Don't cross mountpoint from a BK to a BK volume */
if ((states & CBackup) && (tvp->states & VBackup)) {
AFS_STATCNT(afs_lookup);
afs_InitFakeStat(&fakestate);
+ AFS_DISCON_LOCK();
+
+ /*printf("Looking up %s\n", aname);*/
+
if ((code = afs_InitReq(&treq, acred)))
goto done;
code = afs_TryEvalFakeStat(&adp, &fakestate, &treq);
else
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
+
+ /*printf("Code is %d\n", code);*/
+
if (tryEvalOnly && adp->mvstat == 1)
code = ENOENT;
if (code)
goto done;
}
/* otherwise we have the fid here, so we use it */
+ /*printf("Getting vcache\n");*/
tvc = afs_GetVCache(adp->mvid, &treq, NULL, NULL);
afs_Trace3(afs_iclSetp, CM_TRACE_GETVCDOTDOT, ICL_TYPE_FID, adp->mvid,
ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, code);
/* prefetch some entries, if the dir is currently open. The variable
* dirCookie tells us where to start prefetching from.
*/
- if (AFSDOBULK && adp->opens > 0 && !(adp->states & CForeign)
+ if (!AFS_IS_DISCONNECTED &&
+ AFSDOBULK && adp->opens > 0 && !(adp->states & CForeign)
&& !afs_IsDynroot(adp) && !afs_InReadDir(adp)) {
afs_int32 retry;
/* if the entry is not in the cache, or is in the cache,
* be located (a Multics "connection failure"). If the volume is
* read-only, we try flushing this entry from the cache and trying
* again. */
- if (pass == 0) {
- struct volume *tv;
- tv = afs_GetVolume(&adp->fid, &treq, READ_LOCK);
- if (tv) {
- if (tv->states & VRO) {
- pass = 1; /* try this *once* */
- ObtainWriteLock(&afs_xcbhash, 495);
- afs_DequeueCallback(adp);
- /* re-stat to get later version */
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ if (!AFS_IS_DISCONNECTED) {
+ if (pass == 0) {
+ struct volume *tv;
+ tv = afs_GetVolume(&adp->fid, &treq, READ_LOCK);
+ if (tv) {
+ if (tv->states & VRO) {
+ pass = 1; /* try this *once* */
+ ObtainWriteLock(&afs_xcbhash, 495);
+ afs_DequeueCallback(adp);
+ /* re-stat to get later version */
+ adp->states &= ~CStatd;
+ ReleaseWriteLock(&afs_xcbhash);
+ osi_dnlc_purgedp(adp);
+ afs_PutVolume(tv, READ_LOCK);
+ goto redo;
+ }
afs_PutVolume(tv, READ_LOCK);
- goto redo;
- }
- afs_PutVolume(tv, READ_LOCK);
+ }
}
+ code = ENOENT;
+ } else {
+ /*printf("Network down in afs_lookup\n");*/
+ code = ENETDOWN;
}
- code = ENOENT;
}
done:
code = afs_VerifyVCache(tvc, &treq);
#else
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return 0; /* can't have been any errors if hit and !code */
#endif
}
}
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return code;
}
afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
ICL_TYPE_INT32, aflags);
afs_InitFakeStat(&fakestate);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
if (code)
goto done;
code = afs_VerifyVCache(tvc, &treq);
if (code)
goto done;
+
+ ObtainReadLock(&tvc->lock);
+
+#ifdef AFS_DISCON_ENV
+ if (AFS_IS_DISCONNECTED && (afs_DCacheMissingChunks(tvc) != 0)) {
+ ReleaseReadLock(&tvc->lock);
+ /*printf("Network is down in afs_open: missing chunks\n");*/
+ code = ENETDOWN;
+ goto done;
+ }
+#endif
+
+ ReleaseReadLock(&tvc->lock);
+
if (aflags & (FWRITE | FTRUNC))
writing = 1;
else
}
done:
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
+
code = afs_CheckCode(code, &treq, 4); /* avoid AIX -O bug */
afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
ReleaseReadLock(&adc->lock);
tdc = afs_GetDCache(avc, offset, areq, &j1, &j2, 2); /* type 2 never returns 0 */
+#ifdef AFS_DISCON_ENV
+ /*
+ * In disconnected mode, type 2 can return 0 because it doesn't
+ * make any sense to allocate a dcache we can never fill
+ */
+ if (tdc == NULL)
+ return;
+#endif /* AFS_DISCON_ENV */
+
ObtainSharedLock(&tdc->mflock, 651);
if (!(tdc->mflags & DFFetchReq)) {
/* ask the daemon to do the work */
if (avc && avc->vc_error)
return EIO;
+ AFS_DISCON_LOCK();
+
/* check that we have the latest status info in the vnode cache */
if ((code = afs_InitReq(&treq, acred)))
return code;
code = afs_VerifyVCache(avc, &treq);
if (code) {
code = afs_CheckCode(code, &treq, 11); /* failed to get it */
+ AFS_DISCON_UNLOCK();
return code;
}
}
if (!afs_AccessOK
(avc, PRSFS_READ, &treq,
CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
+ AFS_DISCON_UNLOCK();
return afs_CheckCode(EACCES, &treq, 12);
}
}
afs_PutDCache(tdc); /* before reusing tdc */
}
tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
+#ifdef AFS_DISCON_ENV
+ if (!tdc) {
+ /*printf("Network down in afs_read");*/
+ error = ENETDOWN;
+ break;
+ }
+#endif /* AFS_DISCON_ENV */
+
ObtainReadLock(&tdc->lock);
/* now, first try to start transfer, if we'll need the data. If
* data already coming, we don't need to do this, obviously. Type
#else
osi_FreeSmallSpace(tvec);
#endif
+ AFS_DISCON_UNLOCK();
error = afs_CheckCode(error, &treq, 13);
return error;
}
}
/* update the cache entry */
afs_InitFakeStat(&fakestate);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
if (code)
goto done;
#ifdef AFS_HPUX_ENV
osi_FreeSmallSpace((char *)sdirEntry);
#endif
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
code = afs_CheckCode(code, &treq, 28);
return code;
return code;
}
afs_InitFakeStat(&fakestate);
+ AFS_DISCON_LOCK();
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
if (code) {
#ifdef AFS_HPUX_ENV
osi_FreeSmallSpace((char *)sdirEntry);
#endif
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
return code;
}
#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
osi_FreeSmallSpace((char *)sdirEntry);
#endif
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
code = afs_CheckCode(code, &treq, 29);
return code;
register struct vcache *tvc, char *aname, struct AFS_UCRED *acred,
struct vrequest *treqp)
{
- register afs_int32 code;
+ register afs_int32 code = 0;
register struct conn *tc;
struct AFSFetchStatus OutDirStatus;
struct AFSVolSync tsync;
XSTATS_DECLS;
- do {
- tc = afs_Conn(&adp->fid, treqp, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
- RX_AFS_GUNLOCK();
- code =
- RXAFS_RemoveFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
- aname, &OutDirStatus, &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
- } while (afs_Analyze
- (tc, code, &adp->fid, treqp, AFS_STATS_FS_RPCIDX_REMOVEFILE,
- SHARED_LOCK, NULL));
+
+ if (!AFS_IS_DISCONNECTED) {
+ do {
+ tc = afs_Conn(&adp->fid, treqp, SHARED_LOCK);
+ if (tc) {
+ XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
+ RX_AFS_GUNLOCK();
+ code =
+ RXAFS_RemoveFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
+ aname, &OutDirStatus, &tsync);
+ RX_AFS_GLOCK();
+ XSTATS_END_TIME;
+ } else
+ code = -1;
+ } while (afs_Analyze
+ (tc, code, &adp->fid, treqp, AFS_STATS_FS_RPCIDX_REMOVEFILE,
+ SHARED_LOCK, NULL));
+ }
osi_dnlc_remove(adp, aname, tvc);
return code;
}
+ /* If we're running disconnected without logging, go no further... */
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+#ifdef AFS_OSF_ENV
+ afs_PutVCache(tvc);
+#endif
+ code = ENETDOWN;
+ afs_PutFakeStat(&fakestate);
+ return code;
+ }
+
tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
ObtainWriteLock(&adp->lock, 142);
if (tdc)
code = 0;
goto done;
}
+
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ code = ENETDOWN;
+ goto done;
+ }
+
ObtainWriteLock(&andp->lock, 147);
tdc1 = afs_GetDCache(aodp, (afs_size_t) 0, areq, &offset, &len, 0);
if (!tdc1) {
goto done;
}
- /* locks are now set, proceed to do the real work */
do {
tc = afs_Conn(&aodp->fid, areq, SHARED_LOCK);
if (tc) {
return code;
afs_InitFakeStat(&ofakestate);
afs_InitFakeStat(&nfakestate);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&aodp, &ofakestate, &treq);
if (code)
goto done;
done:
afs_PutFakeStat(&ofakestate);
afs_PutFakeStat(&nfakestate);
+
+ AFS_DISCON_UNLOCK();
+
code = afs_CheckCode(code, &treq, 25);
return code;
}
goto done2;
afs_InitFakeStat(&fakestate);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&adp, &fakestate, &treq);
if (code)
goto done;
goto done;
}
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+ code = ENETDOWN;
+ goto done;
+ }
+
InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE;
InStatus.ClientModTime = osi_Time();
alen = strlen(atargetName); /* we want it to include the null */
afs_PutFakeStat(&fakestate);
if (volp)
afs_PutVolume(volp, READ_LOCK);
+ AFS_DISCON_UNLOCK();
code = afs_CheckCode(code, &treq, 31);
done2:
return code;
ICL_TYPE_POINTER, tdc, ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(avc->m.Length));
if (!tdc) {
- return EIO;
+ if (AFS_IS_DISCONNECTED)
+ return ENETDOWN;
+ else
+ return EIO;
}
/* otherwise we have the data loaded, go for it */
if (len > 1024) {
if ((code = afs_InitReq(&treq, acred)))
return code;
afs_InitFakeStat(&fakestat);
+
+ AFS_DISCON_LOCK();
+
code = afs_EvalFakeStat(&avc, &fakestat, &treq);
if (code)
goto done;
ReleaseWriteLock(&avc->lock);
done:
afs_PutFakeStat(&fakestat);
+ AFS_DISCON_UNLOCK();
code = afs_CheckCode(code, &treq, 32);
return code;
}
if (avc->vc_error)
return avc->vc_error;
+ if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING)
+ return ENETDOWN;
+
startDate = osi_Time();
if ((code = afs_InitReq(&treq, acred)))
return code;
struct afs_stats_RPCErrors *aerrP;
afs_int32 markeddown;
+
+ if (AFS_IS_DISCONNECTED) {
+ /* SXW - This may get very tired after a while. We should try and
+ * intercept all RPCs before they get here ... */
+ /*printf("afs_Analyze: disconnected\n");*/
+ afs_FinalizeReq(areq);
+ if (aconn) {
+ /* SXW - I suspect that this will _never_ happen - we shouldn't
+ * get a connection because we're disconnected !!!*/
+ afs_PutConn(aconn, locktype);
+ }
+ return 0;
+ }
+
AFS_STATCNT(afs_Analyze);
afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
ReleaseSharedLock(&afs_xconn);
return NULL;
}
+
+ if (AFS_IS_DISCONNECTED) {
+ afs_warnuser("afs_ConnBySA: disconnected\n");
+ ReleaseSharedLock(&afs_xconn);
+ return NULL;
+ }
if (!tc) {
/* No such connection structure exists. Create one and splice it in.
struct srvAddr *sa = 0;
AFS_STATCNT(afs_ConnByHost);
+
+ if (AFS_IS_DISCONNECTED) {
+ afs_warnuser("afs_ConnByHost: disconnected\n");
+ return NULL;
+ }
+
/*
1. look for an existing connection
2. create a connection at an address believed to be up
afs_FlushReclaimedVcaches();
ReleaseWriteLock(&afs_xvcache);
afs_FlushActiveVcaches(1); /* keep flocks held & flush nfs writes */
+#if 0
#ifdef AFS_DISCON_ENV
afs_StoreDirtyVcaches();
#endif
+#endif
afs_CheckRXEpoch();
last1MinCheck = now;
}
#endif
MReleaseWriteLock(&afs_xdcache);
/*
- * It's treated like a callback so that when we do lookups we'll invalidate the unique bit if any
+ * It's treated like a callback so that when we do lookups we'll
+ * invalidate the unique bit if any
* trytoSmush occured during the lookup call
*/
afs_allCBs++;
}
/*
+ * afs_DCacheMissingChunks
+ *
+ * Description
+ * Given the cached info for a file, return the number of chunks that
+ * are not available from the dcache.
+ *
+ * Parameters:
+ * avc: Pointer to the (held) vcache entry to look in.
+ *
+ * Returns:
+ * The number of chunks which are not currently cached.
+ *
+ * Environment:
+ * The vcache entry is held upon entry.
+ */
+
+int
+afs_DCacheMissingChunks(struct vcache *avc)
+{
+ int i, index;
+ afs_size_t totalLength;
+ afs_uint32 totalChunks;
+ struct dcache *tdc;
+
+ totalLength = avc->m.Length;
+ if (avc->truncPos < totalLength)
+ totalLength = avc->truncPos;
+
+ totalChunks = AFS_CHUNK(totalLength) + 1;
+
+ /*printf("Should have %d chunks for %d bytes\n", totalChunks, totalLength);*/
+
+ i = DVHash(&avc->fid);
+ MObtainWriteLock(&afs_xdcache, 1001);
+ for (index = afs_dvhashTbl[i]; index != NULLIDX; index = i) {
+ i = afs_dvnextTbl[index];
+ if (afs_indexUnique[index] == avc->fid.Fid.Unique) {
+ tdc = afs_GetDSlot(index, NULL);
+ if (!FidCmp(&tdc->f.fid, &avc->fid)) {
+ totalChunks--;
+ }
+ ReleaseReadLock(&tdc->tlock);
+ afs_PutDCache(tdc);
+ }
+ }
+ MReleaseWriteLock(&afs_xdcache);
+
+ /*printf("Missing %d chunks\n", totalChunks);*/
+
+ return (totalChunks);
+}
+
+/*
* afs_FindDCache
*
* Description:
* If we didn't find the entry, we'll create one.
*/
if (index == NULLIDX) {
+ /* If we're disconnected, we can't do anything */
+ if (AFS_IS_DISCONNECTED) {
+ MReleaseWriteLock(&afs_xdcache);
+ if (setLocks) {
+ if (slowPass)
+ ReleaseWriteLock(&avc->lock);
+ else
+ ReleaseReadLock(&avc->lock);
+ }
+ return NULL;
+ }
/*
* Locks held:
* avc->lock(R) if setLocks
/*
* Version number mismatch.
*/
+ /*
+ * If we are disconnected, then we can't do much of anything
+ * because the data doesn't match the file.
+ */
+ if (AFS_IS_DISCONNECTED) {
+ ReleaseSharedLock(&tdc->lock);
+ if (setLocks) {
+ if (slowPass)
+ ReleaseWriteLock(&avc->lock);
+ else
+ ReleaseReadLock(&avc->lock);
+ }
+ /* Flush the Dcache */
+ afs_PutDCache(tdc);
+
+ return NULL;
+ }
UpgradeSToWLock(&tdc->lock, 609);
/*
--- /dev/null
+/*
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+RCSID("$Header$");
+
+#include "afs/sysincludes.h"
+#include "afsincludes.h"
+
+#ifdef AFS_DISCON_ENV
+
+/* Nothing here any more. Remove from the build unless stuff comes back! */
+#endif
#if defined(AFS_XBSD_ENV)
static struct vnode *volumeVnode;
#endif
+#if defined(AFS_DISCON_ENV)
+afs_rwlock_t afs_discon_lock;
+#endif
/*
* Initialization order is important. Must first call afs_CacheInit,
LOCK_INIT(&afs_ftf, "afs_ftf");
RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
+#ifdef AFS_DISCON_ENV
+ RWLOCK_INIT(&afs_discon_lock, "afs_discon_lock");
+#endif
osi_dnlc_init();
/*
short afs_waitForeverCount = 0;
afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
+#ifdef AFS_DISCON_ENV
+afs_int32 afs_is_disconnected;
+afs_int32 afs_is_logging;
+#endif
+
#define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
struct AFS_UCRED **acred)
DECL_PIOCTL(PPrefetchFromTape);
DECL_PIOCTL(PResidencyCmd);
DECL_PIOCTL(PCallBackAddr);
+DECL_PIOCTL(PDiscon);
DECL_PIOCTL(PNFSNukeCreds);
DECL_PIOCTL(PNewUuid);
DECL_PIOCTL(PPrecache);
PListAliases, /* 2 -- list cell aliases */
PCallBackAddr, /* 3 -- request addr for callback rxcon */
PBogus, /* 4 */
- PBogus, /* 5 */
+ PDiscon, /* 5 */
PBogus, /* 6 */
PBogus, /* 7 */
PBogus, /* 8 */
return 0;
}
+DECL_PIOCTL(PDiscon)
+{
+#ifdef AFS_DISCON_ENV
+ static afs_int32 mode = 4; /* Start up in 'full' */
+
+ if (ainSize == sizeof(afs_int32)) {
+
+ if (!afs_osi_suser(*acred))
+ return EPERM;
+
+ memcpy(&mode, ain, sizeof(afs_int32));
+
+ /*
+ * All of these numbers are hard coded in fs.c. If they
+ * change here, they should change there and vice versa
+ */
+ switch (mode) {
+ case 0: /* Disconnect, breaking all callbacks */
+ if (!AFS_IS_DISCONNECTED) {
+ ObtainWriteLock(&afs_discon_lock, 999);
+ afs_DisconGiveUpCallbacks();
+ afs_RemoveAllConns();
+ afs_is_disconnected = 1;
+ ReleaseWriteLock(&afs_discon_lock);
+ }
+ break;
+ case 4: /* Fully connected */
+ ObtainWriteLock(&afs_discon_lock, 998);
+ afs_is_disconnected = 0;
+ ReleaseWriteLock(&afs_discon_lock);
+ break;
+ default:
+ return EINVAL;
+ }
+ } else {
+ return EINVAL;
+ }
+
+ memcpy(aout, &mode, sizeof(afs_int32));
+ *aoutSize = sizeof(afs_int32);
+ return 0;
+#else
+ return EINVAL;
+#endif
+}
+
DECL_PIOCTL(PNFSNukeCreds)
{
afs_uint32 addr, code;
extern int afs_WriteDCache(register struct dcache *adc, int atime);
extern int afs_wakeup(register struct vcache *avc);
extern int afs_InitCacheFile(char *afile, ino_t ainode);
+extern int afs_DCacheHasAllChunks(struct vcache *avc);
+/* afs_disconnected.c */
/* afs_dynroot.c */
extern int afs_IsDynrootFid(struct VenusFid *fid);
#endif
extern int afs_HaveCallBacksFrom(struct server *aserver);
extern void shutdown_server(void);
-
+extern void afs_RemoveAllConns(void);
/* afs_osidnlc.c */
struct VenusFid *afid);
extern void afs_vcacheInit(int astatSize);
extern void shutdown_vcache(void);
+extern void afs_DisconGiveUpCallbacks(void);
/* VNOPS/afs_vnop_access.c */
#endif
osi_VM_StoreAllSegments(avc);
}
-
+ if (AFS_IS_DISCONNECTED) {
+ if (!AFS_IS_LOGGING) {
+ /* This will probably make someone sad ... */
+ /*printf("Net down in afs_StoreSegments\n");*/
+ return ENETDOWN;
+ }
+ }
ConvertWToSLock(&avc->lock);
/*
AFS_STATCNT(afs_CheckServers);
+ /*
+ * No sense in doing the server checks if we are running in disconnected
+ * mode
+ */
+ if (AFS_IS_DISCONNECTED)
+ return;
+
conns = (struct conn **)0;
rxconns = (struct rx_connection **) 0;
conntimer = 0;
}
}
+#ifdef AFS_DISCON_ENV
+
+void afs_RemoveAllConns()
+{
+ int i;
+ struct server *ts, *nts;
+ struct srvAddr *sa;
+ struct conn *tc, *ntc;
+
+ ObtainReadLock(&afs_xserver);
+ ObtainWriteLock(&afs_xconn, 1001);
+
+ /*printf("Destroying connections ... ");*/
+ for (i = 0; i < NSERVERS; i++) {
+ for (ts = afs_servers[i]; ts; ts = nts) {
+ nts = ts->next;
+ for (sa = ts->addr; sa; sa = sa->next_sa) {
+ if (sa->conns) {
+ tc = sa->conns;
+ while (tc) {
+ ntc = tc->next;
+ AFS_GUNLOCK();
+ rx_DestroyConnection(tc->id);
+ AFS_GLOCK();
+ afs_osi_Free(tc, sizeof(struct conn));
+ tc = ntc;
+ }
+ sa->conns = NULL;
+ }
+ }
+ }
+ }
+ /*printf("done\n");*/
+
+ ReleaseWriteLock(&afs_xconn);
+ ReleaseReadLock(&afs_xserver);
+
+}
+
+#endif /* AFS_DISCON_ENV */
void shutdown_server()
{
struct AFSFetchStatus OutDirStatus;
XSTATS_DECLS;
if (!name)
- name = ""; /* XXX */
+ name = ""; /* XXX */
do {
tc = afs_Conn(afid, areq, SHARED_LOCK);
if (tc) {
tvc->parentUnique = OutStatus.ParentUnique;
code = 0;
} else {
- code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
+ /* If we've got here and we're disconnected, then we can go
+ * no further
+ */
+ if (AFS_IS_DISCONNECTED) {
+ code = ENETDOWN;
+ /*printf("Network is down in afs_GetCache");*/
+ } else
+ code = afs_FetchStatus(tvc, afid, areq, &OutStatus);
+
/* For the NFS translator's benefit, make sure
* non-directory vnodes always have their parent FID set
* correctly, even when created as a result of decoding an
nfid = *afid;
now = osi_Time();
origCBs = afs_allCBs; /* if anything changes, we don't have a cb */
- code =
- afs_RemoteLookup(&adp->fid, areq, aname, &nfid, &OutStatus, &CallBack,
- &serverp, &tsync);
+
+ if (AFS_IS_DISCONNECTED) {
+ /*printf("Network is down in afs_LookupVcache\n");*/
+ code = ENETDOWN;
+ } else
+ code =
+ afs_RemoteLookup(&adp->fid, areq, aname, &nfid, &OutStatus,
+ &CallBack, &serverp, &tsync);
#if defined(AFS_SGI_ENV) && !defined(AFS_SGI53_ENV)
loop2:
for(i = 0; i < VCSIZE; ++i)
QInit(&afs_vhashTV[i]);
}
+
+#ifdef AFS_DISCON_ENV
+void afs_DisconGiveUpCallbacks() {
+ int i;
+ struct vcache *tvc;
+ int nq=0;
+
+ ObtainWriteLock(&afs_xvcache, 1002); /* XXX - should be a unique number */
+
+ /* Somehow, walk the set of vcaches, with each one coming out as tvc */
+ for (i = 0; i < VCSIZE; i++) {
+ for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
+ if ((tvc->states & CRO) == 0 && tvc->callback) {
+ /* XXX - should we check if the callback has expired here? */
+ afs_QueueVCB(tvc);
+ tvc->callback = NULL;
+ tvc->states &- ~(CStatd | CUnique);
+ nq++;
+ }
+ }
+ }
+ /*printf("%d callbacks to be discarded. queued ... ", nq);*/
+ afs_FlushVCBs(0);
+
+ ReleaseWriteLock(&afs_xvcache);
+ /*printf("gone\n");*/
+}
+
+#endif
ReleaseWriteLock(&afs_xvolume);
+ if (AFS_IS_DISCONNECTED)
+ return NULL;
+
tv = afs_NewVolumeByName(aname, acell, agood, areq, locktype);
return (tv);
}
#include "afs/icl.h"
#include "afs/afs_stats.h"
#include "afs/afs_prototypes.h"
+#include "afs/discon.h"
#if defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
#include "osi_machdep.h"
#endif
--- /dev/null
+#ifndef _DISCON_H
+#define _DISCON_H
+
+#ifndef AFS_DISCON_ENV
+#define AFS_IS_DISCONNECTED 0
+#define AFS_IS_LOGGING 0
+#define AFS_DISCON_LOCK()
+#define AFS_DISCON_UNLOCK()
+
+#else
+
+extern afs_int32 afs_is_disconnected;
+extern afs_int32 afs_is_logging;
+extern afs_rwlock_t afs_discon_lock;
+
+#define AFS_IS_DISCONNECTED (afs_is_disconnected)
+#define AFS_IS_LOGGING (afs_is_logging)
+#define AFS_DISCON_LOCK() ObtainReadLock(&afs_discon_lock)
+#define AFS_DISCON_UNLOCK() ReleaseReadLock(&afs_discon_lock)
+
+#endif /* AFS_DISCON_ENV */
+#endif /* _DISCON_H */
afs_daemons.o \
afs_dcache.o \
afs_dir.o \
+ afs_disconnected.o \
afs_dynroot.o \
afs_error.o \
afs_icl.o \
$(CRULE_OPT)
afs_dcache.o: $(TOP_SRC_AFS)/afs_dcache.c
$(CRULE_OPT)
+afs_disconnected.o: $(TOP_SRC_AFS)/afs_disconnected.c
+ $(CRULE_OPT)
afs_dynroot.o: $(TOP_SRC_AFS)/afs_dynroot.c
$(CRULE_OPT)
afs_error.o: $(TOP_SRC_AFS)/afs_error.c
$(UOBJ)/afs_daemons.o \
$(UOBJ)/afs_dcache.o \
$(UOBJ)/afs_dir.o \
+ $(UOBJ)/afs_disconnected.o \
$(UOBJ)/afs_dynroot.o \
$(UOBJ)/afs_icl.o \
$(UOBJ)/afs_init.o \
$(WEBOBJ)/afs_daemons.o \
$(WEBOBJ)/afs_dcache.o \
$(WEBOBJ)/afs_dir.o \
+ $(WEBOBJ)/afs_disconnected.o \
$(WEBOBJ)/afs_dynroot.o \
$(WEBOBJ)/afs_icl.o \
$(WEBOBJ)/afs_init.o \
$(WEBOBJ)/afs_dcache.o \
$(WEBOBJ)/afs_dir.o \
$(WEBOBJ)/afs_dynroot.o \
+ $(WEBOBJ)/afs_disconnected.o \
$(WEBOBJ)/afs_icl.o \
$(WEBOBJ)/afs_init.o \
$(WEBOBJ)/afs_lock.o \
$(JUAFS)/afs_dcache.o \
$(JUAFS)/afs_dir.o \
$(JUAFS)/afs_dynroot.o \
+ $(JUAFS)/afs_disconnected.o \
$(JUAFS)/afs_icl.o \
$(JUAFS)/afs_init.o \
$(JUAFS)/afs_lock.o \
$(CRULE1)
$(UOBJ)/afs_dynroot.o: $(TOP_SRC_AFS)/afs_dynroot.c
$(CRULE1)
+$(UOBJ)/afs_disconnected.o: $(TOP_SRC_AFS)/afs_disconnected.c
+ $(CRULE1)
$(UOBJ)/afs_error.o: $(TOP_SRC_AFS)/afs_error.c
$(CRULE1)
$(UOBJ)/afs_init.o: $(TOP_SRC_AFS)/afs_init.c
$(CRULE2)
$(WEBOBJ)/afs_dcache.o: $(TOP_SRC_AFS)/afs_dcache.c
$(CRULE2)
+$(WEBOBJ)/afs_disconnected.o: $(TOP_SRC_AFS)/afs_disconnected.c
+ $(CRULE2)
$(WEBOBJ)/afs_dynroot.o: $(TOP_SRC_AFS)/afs_dynroot.c
$(CRULE2)
$(WEBOBJ)/afs_error.o: $(TOP_SRC_AFS)/afs_error.c
$(CRULE1)
$(JUAFS)/afs_dcache.o: $(TOP_SRC_AFS)/afs_dcache.c
$(CRULE1)
+$(JUAFS)/afs_disconnected.o: $(TOP_SRC_AFS)/afs_disconnected.c
+ $(CRULE1)
$(JUAFS)/afs_dynroot.o: $(TOP_SRC_AFS)/afs_dynroot.c
$(CRULE1)
$(JUAFS)/afs_error.o: $(TOP_SRC_AFS)/afs_error.c
#ifdef AFS_DISCON_ENV
static char *modenames[] = {
- "discon",
- "fetchonly",
- "partial",
+ "readonly",
+ "fetchonly", /* Not currently supported */
+ "partial", /* Not currently supported */
"nat",
"full",
NULL
#ifdef AFS_DISCON_ENV
ts = cmd_CreateSyntax("discon", DisconCmd, NULL,
"disconnection mode");
- cmd_AddParm(ts, "-mode", CMD_SINGLE, CMD_OPTIONAL, "nat | full");
+ cmd_AddParm(ts, "-mode", CMD_SINGLE, CMD_OPTIONAL, "readonly | nat | full");
#endif
ts = cmd_CreateSyntax("nukenfscreds", NukeNFSCredsCmd, NULL, "nuke credentials for NFS client");