[enable Demand Attach Fileserver (please see documentation)])],
,
[enable_demand_attach_fs="no"])
-AC_ARG_ENABLE([disconnected],
- [AS_HELP_STRING([--enable-disconnected],
- [enable disconnected support in cache manager (experimental)])],
- ,
- [enable_disconnected="no"])
AC_ARG_ENABLE([unix-sockets],
[AS_HELP_STRING([--disable-unix-sockets],
[disable use of unix domain sockets for fssync (defaults to enabled)])],
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"
AFS_GLOCK();
if (!haveVlock)
ObtainWriteLock(&afs_xvcache, 901);
-#ifndef AFS_DISCON_ENV
- code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
-#else
/* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
code = afs_FlushVS(avc);
-#endif
if (!haveVlock)
ReleaseWriteLock(&afs_xvcache);
if (!haveGlock)
}
AFS_GLOCK();
-#ifdef AFS_DISCON_ENV
/* initialize the vcache entries before we start using them */
/* XXX find a better place for this if possible */
init_vcache_entries();
-#endif
afs_globalVFS = mp;
mp->mnt_stat.f_bsize = 8192;
mp->mnt_stat.f_frsize = 8192;
extern int sys_ioctl(), sys_setgroups();
AFS_STATCNT(afs_unmount);
-#ifdef AFS_DISCON_ENV
give_up_cbs();
-#endif
if (afs_globalVFS == NULL) {
printf("afs already unmounted\n");
return 0;
afs_sync(struct mount *mp, int waitfor, kauth_cred_t cred, struct lwp *l)
{
AFS_STATCNT(afs_sync);
-#if defined(AFS_DISCON_ENV)
/* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
store_dirty_vcaches();
-#endif
return 0;
}
#include "afs/nfsclient.h"
#include "afs/afs_osidnlc.h"
-#ifdef AFS_DISCON_ENV
extern int afs_FlushVS(struct vcache *tvc);
-#endif
#define M_AFSNODE (M_TEMP-1) /* XXX */
AFS_GLOCK();
if (!haveVlock)
ObtainWriteLock(&afs_xvcache, 901);
-#ifndef AFS_DISCON_ENV
- code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
-#else
/* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
code = afs_FlushVS(avc);
-#endif
if (!haveVlock)
ReleaseWriteLock(&afs_xvcache);
if (!haveGlock)
AFS_STATCNT(afs_mount);
AFS_GLOCK();
-#ifdef AFS_DISCON_ENV
/* initialize the vcache entries before we start using them */
/* XXX find a better place for this if possible */
init_vcache_entries();
-#endif
afs_globalVFS = mp;
mp->osi_vfs_bsize = 8192;
mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */
}
AFS_STATCNT(afs_unmount);
-#ifdef AFS_DISCON_ENV
give_up_cbs();
-#endif
if (afs_globalVFS == NULL) {
printf("afs already unmounted\n");
return 0;
afs_sync(struct osi_vfs *afsp)
{
AFS_STATCNT(afs_sync);
-#if defined(AFS_DISCON_ENV) && !defined(AFS_OBSD_ENV)
+#if !defined(AFS_OBSD27_ENV)
/* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
store_dirty_vcaches();
#endif
#include "afs/nfsclient.h"
#include "afs/afs_osidnlc.h"
-#ifdef AFS_DISCON_ENV
extern int afs_FlushVS(struct vcache *tvc);
-#endif
#define M_AFSNODE (M_TEMP-1) /* XXX */
AFS_GLOCK();
if (!haveVlock)
ObtainWriteLock(&afs_xvcache, 901);
-#ifndef AFS_DISCON_ENV
- code = afs_FlushVCache(avc, &slept); /* tosses our stuff from vnode */
-#else
/* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
code = afs_FlushVS(avc);
-#endif
if (!haveVlock)
ReleaseWriteLock(&afs_xvcache);
if (!haveGlock)
osi_dnlc_purgedp(avc);
/* error? erase any changes we made to vcache entry */
}
-
-#if defined(AFS_DISCON_ENV)
} else {
-
ObtainSharedLock(&avc->lock, 712);
/* Write changes locally. */
code = afs_WriteVCacheDiscon(avc, &astat, attrs);
ReleaseSharedLock(&avc->lock);
-#endif
} /* if (!AFS_IS_DISCONNECTED) */
#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
}
} else {
-#if defined(AFS_DISCON_ENV)
/* Generate a fake FID for disconnected mode. */
newFid.Cell = adp->f.fid.Cell;
newFid.Fid.Volume = adp->f.fid.Fid.Volume;
afs_GenFakeFid(&newFid, VREG, 1);
-#endif
} /* if (!AFS_IS_DISCON_RW) */
/* otherwise, we should see if we can make the change to the dir locally */
}
ReleaseWriteLock(&afs_xcbhash);
if (AFS_IS_DISCON_RW) {
-#if defined(AFS_DISCON_ENV)
afs_DisconAddDirty(tvc, VDisconCreate, 0);
afs_GenDisconStatus(adp, tvc, &newFid, attrs, &treq, VREG);
-#endif
} else {
afs_ProcessFS(tvc, &OutFidStatus, &treq);
}
register struct afs_conn *tc;
struct VenusFid newFid;
register struct dcache *tdc;
-#ifdef AFS_DISCON_ENV
struct dcache *new_dc;
-#endif
afs_size_t offset, len;
register struct vcache *tvc;
struct AFSStoreStatus InStatus;
}
} else {
-#if defined(AFS_DISCON_ENV)
/* Disconnected. */
/* We have the dir entry now, we can use it while disconnected. */
/* Operations with the actual dir's cache entry are further
* down, where the dir entry gets created.
*/
-#endif
} /* if (!AFS_IS_DISCON_RW) */
/* otherwise, we should see if we can make the change to the dir locally */
newFid.Fid.Volume = adp->f.fid.Fid.Volume;
ReleaseWriteLock(&adp->lock);
if (AFS_IS_DISCON_RW) {
-#if defined(AFS_DISCON_ENV)
/* When disconnected, we have to create the full dir here. */
/* Generate a new vcache and fill it. */
afs_DisconAddDirty(tvc, VDisconCreate, 1);
ReleaseWriteLock(&tvc->lock);
-#endif /* #ifdef AFS_DISCON_ENV */
} else {
/* now we're done with parent dir, create the real dir's cache entry */
tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
adp->f.m.LinkCount = OutDirStatus.LinkCount;
} else {
-#if defined(AFS_DISCON_ENV)
/* Disconnected. */
if (!tdc) {
}
adp->f.m.LinkCount--;
-#endif /* #ifdef AFS_DISCON_ENV */
} /* if (!AFS_IS_DISCON_RW) */
if (tdc)
if (tvc) {
ObtainWriteLock(&tvc->lock, 155);
tvc->f.states &= ~CUnique; /* For the dfs xlator */
-#if defined(AFS_DISCON_ENV)
if (AFS_IS_DISCON_RW) {
if (tvc->f.ddirty_flags & VDisconCreate) {
/* If we we were created whilst disconnected, removal doesn't
afs_DisconAddDirty(tvc, VDisconRemove, 1);
}
}
-#endif
ReleaseWriteLock(&tvc->lock);
afs_PutVCache(tvc);
}
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);
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)) {
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
}
}
-#if defined(AFS_DISCON_ENV)
if (AFS_IS_DISCON_RW) {
if (!adp->f.shadow.vnode && !(adp->f.ddirty_flags & VDisconCreate)) {
/* Make shadow copy of parent dir. */
if (tdc)
ObtainSharedLock(&tdc->lock, 714);
}
-#endif
if (tvc && osi_Active(tvc)) {
/* about to delete whole file, prefetch it first */
}
tvc->uncred = acred;
tvc->f.states |= CUnlinked;
-#if defined(AFS_DISCON_ENV)
/* if rename succeeded, remove should not */
ObtainWriteLock(&tvc->lock, 715);
if (tvc->f.ddirty_flags & VDisconRemove) {
tvc->f.ddirty_flags &= ~VDisconRemove;
}
ReleaseWriteLock(&tvc->lock);
-#endif
} else {
osi_FreeSmallSpace(unlname);
}
SHARED_LOCK, NULL));
} else {
-#if defined(AFS_DISCON_ENV)
/* Disconnected. */
/* Seek moved file vcache. */
} else {
code = ENOENT;
} /* if (tvc) */
-#endif
} /* if !(AFS_IS_DISCON_RW)*/
returnCode = code; /* remember for later */
tdc1 = afs_FindDCache(tvc, (afs_size_t) 0);
if (tdc1) {
if (AFS_IS_DISCON_RW) {
-#if defined(AFS_DISCON_ENV)
/* If disconnected, we need to fix (not discard) the "..".*/
afs_dir_ChangeFid(tdc1,
"..",
&aodp->f.fid.Fid.Vnode,
&andp->f.fid.Fid.Vnode);
-#endif
} else {
ObtainWriteLock(&tdc1->lock, 648);
ZapDCE(tdc1); /* mark as unknown */
* is just a performance hit.
*/
-#ifdef AFS_DISCON_ENV
static int
afs_DisconCreateSymlink(struct vcache *avc, char *aname,
struct vrequest *areq) {
ReleaseWriteLock(&tdc->lock);
return 0;
}
-#endif
/* don't set CDirty in here because RPC is called synchronously */
int
(tc, code, &adp->f.fid, &treq, AFS_STATS_FS_RPCIDX_SYMLINK,
SHARED_LOCK, NULL));
} else {
-#ifdef AFS_DISCON_ENV
newFid.Cell = adp->f.fid.Cell;
newFid.Fid.Volume = adp->f.fid.Fid.Volume;
afs_GenFakeFid(&newFid, VREG, 0);
-#endif
}
ObtainWriteLock(&afs_xvcache, 40);
ReleaseWriteLock(&afs_xcbhash);
if (AFS_IS_DISCON_RW) {
-#ifdef AFS_DISCON_ENV
attrs->va_mode = InStatus.UnixModeBits;
afs_GenDisconStatus(adp, tvc, &newFid, attrs, &treq, VLNK);
code = afs_DisconCreateSymlink(tvc, atargetName, &treq);
goto done;
}
afs_DisconAddDirty(tvc, VDisconCreate, 0);
-#endif
} else {
afs_ProcessFS(tvc, &OutFidStatus, &treq);
}
osi_Assert(filePos <= avc->f.m.Length);
#else
if (filePos > avc->f.m.Length) {
-#if defined(AFS_DISCON_ENV)
if (AFS_IS_DISCON_RW)
afs_PopulateDCache(avc, filePos, &treq);
-#endif
afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
__FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_OFFSET,
osi_Assert(filePos <= avc->f.m.Length);
#else
if (filePos > avc->f.m.Length) {
-#if defined(AFS_DISCON_ENV)
if (AFS_IS_DISCON_RW)
afs_PopulateDCache(avc, filePos, &treq);
-#endif
afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
__FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_OFFSET,
ObtainSharedLock(&avc->lock, 18);
code = 0;
if (avc->execsOrWriters > 0) {
-
if (!AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
- /* Your average flush. */
-
- /* put the file back */
- UpgradeSToWLock(&avc->lock, 41);
- code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
- ConvertWToSLock(&avc->lock);
-
-#if defined(AFS_DISCON_ENV)
+ /* Your average flush. */
+
+ /* put the file back */
+ UpgradeSToWLock(&avc->lock, 41);
+ code = afs_StoreAllSegments(avc, &treq, AFS_SYNC);
+ ConvertWToSLock(&avc->lock);
} else {
-
UpgradeSToWLock(&avc->lock, 711);
afs_DisconAddDirty(avc, VDisconWriteFlush, 1);
ConvertWToSLock(&avc->lock);
-#endif
} /* if not disconnected */
} /* if (avc->execsOrWriters > 0) */
#define VRevokeWait 0x1
#define VPageCleaning 0x2 /* Solaris - Cache Trunc Daemon sez keep out */
-#if defined(AFS_DISCON_ENV)
-
/* Dirty disconnected vcache flags. */
#define VDisconSetTime 0x00000001 /* set time. */
#define VDisconSetMode 0x00000002 /* set mode. */
#define VDisconRenameSameDir 0x00020000 /* Rename in same dir. */
/*... to be continued ... */
-#endif
#if defined(AFS_CACHE_BYPASS)
/* vcache (file) cachingStates bits */
/*! state bits */
afs_uint32 states;
-#if defined(AFS_DISCON_ENV)
/*! Disconnected flags for this vcache element. */
afs_uint32 ddirty_flags;
/*! Shadow vnode + unique keep the shadow dir location. */
struct afs_vnuniq shadow;
/*! The old parent FID for renamed vnodes */
struct afs_vnuniq oldParent;
-#endif
};
/* INVARIANTs: (vlruq.next != NULL) == (vlruq.prev != NULL)
#endif
struct vcache *hnext; /* Hash next */
struct afs_q vhashq; /* Hashed per-volume list */
-#if defined(AFS_DISCON_ENV)
/*! Queue of dirty vcaches. Lock with afs_disconDirtyLock */
struct afs_q dirtyq;
/*! Queue of vcaches with shadow entries. Lock with afs_disconDirtyLock */
struct afs_q metadirty;
/*! Vcaches slot number in the disk backup. Protected by tvc->lock */
afs_uint32 diskSlot;
-#endif
struct fvcache f;
afs_rwlock_t lock; /* The lock on the vcache contents. */
#if defined(AFS_SUN5_ENV)
"afs_xvreclaim", (char *)&afs_xvreclaim},
{ "afsdb_client_lock", (char *)&afsdb_client_lock},
{ "afsdb_req_lock", (char *)&afsdb_req_lock},
-#ifdef AFS_DISCON_ENV
{ "afs_discon_lock", (char *)&afs_discon_lock},
{ "afs_disconDirtyLock", (char *)&afs_disconDirtyLock},
{ "afs_discon_vc_dirty", (char *)&afs_xvcdirty},
-#endif
};
unsigned long lastCallBack_vnode;
unsigned int lastCallBack_dv;
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;
}
return tdc;
}
-#if defined(AFS_DISCON_ENV)
-
/*!
* Make a shadow copy of a dir's dcache. It's used for disconnected
* operations like remove/create/rename to keep the original directory data.
start++;
}
}
-
-#endif
#include "afs/lock.h"
#include "afs/afs_cbqueue.h"
-#ifdef AFS_DISCON_ENV
-
#define dv_match(vc, fstat) \
((vc->f.m.DataVersion.low == fstat.DataVersion) && \
(vc->f.m.DataVersion.high == fstat.dataVersionHigh))
avc->f.states |= CStatd;
avc->f.states &= ~CBulkFetching;
}
-#endif
#if defined(AFS_XBSD_ENV)
static struct vnode *volumeVnode;
#endif
-#if defined(AFS_DISCON_ENV)
afs_rwlock_t afs_discon_lock;
extern afs_rwlock_t afs_disconDirtyLock;
-#endif
#if defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_STRUCT_HAS_CRED)
const struct cred *cache_creds;
#endif
LOCK_INIT(&afs_ftf, "afs_ftf");
AFS_RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
-#ifdef AFS_DISCON_ENV
AFS_RWLOCK_INIT(&afs_discon_lock, "afs_discon_lock");
AFS_RWLOCK_INIT(&afs_disconDirtyLock, "afs_disconDirtyLock");
QInit(&afs_disconDirty);
QInit(&afs_disconShadow);
-#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_discon_rw;
/* On reconnection, turn this knob on until it finishes,
* then turn it off.
*/
afs_int32 afs_in_sync = 0;
-#endif
struct afs_pdata {
char *ptr;
DECL_PIOCTL(PDiscon)
{
-#ifdef AFS_DISCON_ENV
static afs_int32 mode = 1; /* Start up in 'off' */
afs_int32 force = 0;
int code = 0;
return code;
return afs_pd_putInt(aout, mode);
-#else
- return EINVAL;
-#endif
}
DECL_PIOCTL(PNFSNukeCreds)
#endif /* AFS_SGI64_ENV */
/* Exported variables */
-#ifdef AFS_DISCON_ENV
afs_rwlock_t afs_xvcdirty; /*Lock: discon vcache dirty list mgmt */
-#endif
afs_rwlock_t afs_xvcache; /*Lock: alloc new stat cache entries */
afs_rwlock_t afs_xvreclaim; /*Lock: entries reclaimed, not on free list */
afs_lock_t afs_xvcb; /*Lock: fids on which there are callbacks */
/* Disk backed vcache definitions
* Both protected by xvcache */
-#ifdef AFS_DISCON_ENV
static int afs_nextVcacheSlot = 0;
static struct afs_slotlist *afs_freeSlotList = NULL;
-#endif
/* Forward declarations */
static afs_int32 afs_QueueVCB(struct vcache *avc);
afs_stats_cmperf.vcacheXAllocs++; /* count in case we have a leak */
-#ifdef AFS_DISCON_ENV
/* If we create a new inode, we either give it a new slot number,
* or if one's available, use a slot number from the slot free list
*/
} else {
tvc->diskSlot = afs_nextVcacheSlot++;
}
-#endif
return tvc;
}
afs_PrePopulateVCache(struct vcache *avc, struct VenusFid *afid,
struct server *serverp) {
-#if defined(AFS_DISCON_ENV)
afs_uint32 slot;
slot = avc->diskSlot;
-#endif
osi_PrePopulateVCache(avc);
-#if defined(AFS_DISCON_ENV)
avc->diskSlot = slot;
QZero(&avc->metadirty);
-#endif
AFS_RWLOCK_INIT(&avc->lock, "vcache lock");
return code;
} /*afs_WriteVCache */
-#if defined(AFS_DISCON_ENV)
/*!
* Store status info only locally, set the proper disconnection flags
return code;
}
-#endif
-
/*!
* Copy astat block into vcache info
*
#ifndef _DISCON_H
#define _DISCON_H
-#ifndef AFS_DISCON_ENV
-#define AFS_IS_DISCONNECTED 0
-#define AFS_IS_DISCON_RW 0
-#define AFS_IN_SYNC 0
-#define AFS_DISCON_LOCK()
-#define AFS_DISCON_UNLOCK()
-
-#define afs_DisconAddDirty(x, y, z)
-
-#else
-
#if !defined(inline) && !defined(__GNUC__)
#define inline
#endif
avc->f.ddirty_flags = 0;
afs_PutVCache(avc);
}
-#endif /* AFS_DISCON_ENV */
#endif /* _DISCON_H */