#include "rx/rx_globals.h"
#include "token.h"
+extern int afs_rmtsys_enable;
struct VenusFid afs_rootFid;
afs_int32 afs_waitForever = 0;
short afs_waitForeverCount = 0;
DECL_PIOCTL(PGetCellStatus);
DECL_PIOCTL(PSetCellStatus);
DECL_PIOCTL(PFlushVolumeData);
+DECL_PIOCTL(PFlushAllVolumeData);
DECL_PIOCTL(PGetVnodeXStatus);
DECL_PIOCTL(PGetVnodeXStatus2);
DECL_PIOCTL(PSetSysName);
PBogus, /* 11 */
PPrecache, /* 12 */
PGetPAG, /* 13 */
+ PFlushAllVolumeData, /* 14 */
};
static pioctlFunction OpioctlSw[] = {
if (((uap->com >> 8) & 0xff) == 'V') {
struct afs_ioctl *datap;
AFS_GLOCK();
- datap =
- (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
+ datap = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
code=copyin_afs_ioctl((char *)uap->arg, datap);
if (code) {
osi_FreeSmallSpace(datap);
if (((uap->com >> 8) & 0xff) == 'V') {
struct afs_ioctl *datap;
AFS_GLOCK();
- datap =
- (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
+ datap = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
code=copyin_afs_ioctl((char *)uap->arg, datap);
if (code) {
osi_FreeSmallSpace(datap);
#if defined(AFS_NBSD50_ENV)
if ((fd = fd_getfile(SCARG(uap, fd))) == NULL)
return (EBADF);
+#elif defined(AFS_FBSD100_ENV)
+ if ((uap->fd >= fdp->fd_nfiles)
+ || ((fd = fdp->fd_ofiles[uap->fd].fde_file) == NULL))
+ return EBADF;
#else
if ((uap->fd >= fdp->fd_nfiles)
|| ((fd = fdp->fd_ofiles[uap->fd]) == NULL))
if (!ioctlDone) {
# if defined(AFS_FBSD_ENV)
+# if (__FreeBSD_version >= 900044)
+ return sys_ioctl(td, uap);
+# else
return ioctl(td, uap);
+# endif
# elif defined(AFS_OBSD_ENV)
code = sys_ioctl(p, uap, retval);
# elif defined(AFS_NBSD_ENV)
vp = (struct vnode *)dp->d_inode;
#else
code = gop_lookupname_user(path, AFS_UIOUSER, follow, &vp);
-#if defined(AFS_FBSD80_ENV) /* XXX check on 7x */
- if (vp != NULL)
- VN_HOLD(vp);
-#endif /* AFS_FBSD80_ENV */
#endif /* AFS_LINUX22_ENV */
#endif /* AFS_AIX41_ENV */
AFS_GLOCK();
#endif /* AFS_NEED_CLIENTCONTEXT */
if (vp) {
#ifdef AFS_LINUX22_ENV
+ /*
+ * Holding the global lock when calling dput can cause a deadlock
+ * when the kernel calls back into afs_dentry_iput
+ */
+ AFS_GUNLOCK();
dput(dp);
+ AFS_GLOCK();
#else
#if defined(AFS_FBSD80_ENV)
if (VOP_ISLOCKED(vp))
afs_ucred_t **acred)
{
struct vcache *avc;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
afs_int32 code;
afs_int32 function, device;
struct afs_pdata input, output;
ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
AFS_STATCNT(HandlePioctl);
- code = afs_InitReq(&treq, *acred);
+ code = afs_CreateReq(&treq, *acred);
if (code)
return code;
afs_InitFakeStat(&fakestate);
if (avc) {
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
+ code = afs_EvalFakeStat(&avc, &fakestate, treq);
if (code)
goto out;
}
copyOutput = output;
code =
- (*pioctlSw[function]) (avc, function, &treq, ©Input,
+ (*pioctlSw[function]) (avc, function, treq, ©Input,
©Output, acred);
outSize = copyOutput.ptr - output.ptr;
afs_pd_free(&output);
afs_PutFakeStat(&fakestate);
- return afs_CheckCode(code, &treq, 41);
+ code = afs_CheckCode(code, treq, 41);
+ afs_DestroyReq(treq);
+ return code;
}
/*!
char *stp;
char *cellName;
int stLen;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
afs_int32 flag, set_parent_pag = 0;
AFS_STATCNT(PSetTokens);
if (set_parent_pag) {
if (_settok_setParentPag(acred) == 0) {
- afs_InitReq(&treq, *acred);
- areq = &treq;
+ code = afs_CreateReq(&treq, *acred);
+ if (code) {
+ return code;
+ }
+ areq = treq;
}
}
afs_ResetUserConns(tu);
afs_NotifyUser(tu, UTokensObtained);
afs_PutUser(tu, WRITE_LOCK);
+ afs_DestroyReq(treq);
return 0;
}
AFS_STATCNT(PFlush);
if (!avc)
return EINVAL;
-#ifdef AFS_BOZONLOCK_ENV
- afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
ObtainWriteLock(&avc->lock, 225);
- afs_ResetVCache(avc, *acred);
+ afs_ResetVCache(avc, *acred, 0);
ReleaseWriteLock(&avc->lock);
-#ifdef AFS_BOZONLOCK_ENV
- afs_BozonUnlock(&avc->pvnLock, avc);
-#endif
return 0;
}
return 0;
}
-/*!
- * VIOC_FLUSHVOLUME (37) - Flush whole volume's data
- *
- * \ingroup pioctl
- *
- * \param[in] ain not in use (args in avc)
- * \param[out] aout not in use
- *
- * \retval EINVAL Error if some of the standard args aren't set
- * \retval EIO Error if the afs daemon hasn't started yet
- *
- * \post
- * Flush all cached contents of a volume. Exactly what stays and what
- * goes depends on the platform.
- *
- * \notes
- * Does not flush a file that a user has open and is using, because
- * it will be re-created on next write. Also purges the dnlc,
- * because things are screwed up.
- */
-DECL_PIOCTL(PFlushVolumeData)
+static void
+FlushVolumeData(struct VenusFid *afid, afs_ucred_t * acred)
{
afs_int32 i;
struct dcache *tdc;
struct vcache *tvc;
struct volume *tv;
- afs_int32 cell, volume;
+ afs_int32 all = 0;
+ afs_int32 cell = 0;
+ afs_int32 volume = 0;
struct afs_q *tq, *uq;
#ifdef AFS_DARWIN80_ENV
vnode_t vp;
#endif
- AFS_STATCNT(PFlushVolumeData);
- if (!avc)
- return EINVAL;
- if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
- return EIO; /* Inappropriate ioctl for device */
-
- volume = avc->f.fid.Fid.Volume; /* who to zap */
- cell = avc->f.fid.Cell;
+ if (!afid) {
+ all = 1;
+ } else {
+ volume = afid->Fid.Volume; /* who to zap */
+ cell = afid->Cell;
+ }
/*
* Clear stat'd flag from all vnodes from this volume; this will
*/
loop:
ObtainReadLock(&afs_xvcache);
- i = VCHashV(&avc->f.fid);
- for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
+ for (i = (afid ? VCHashV(afid) : 0); i < VCSIZE; i = (afid ? VCSIZE : i+1)) {
+ for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
uq = QPrev(tq);
tvc = QTOVH(tq);
- if (tvc->f.fid.Fid.Volume == volume && tvc->f.fid.Cell == cell) {
+ if (all || (tvc->f.fid.Fid.Volume == volume && tvc->f.fid.Cell == cell)) {
if (tvc->f.states & CVInit) {
ReleaseReadLock(&afs_xvcache);
afs_osi_Sleep(&tvc->f.states);
AFS_FAST_HOLD(tvc);
#endif
ReleaseReadLock(&afs_xvcache);
-#ifdef AFS_BOZONLOCK_ENV
- afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
ObtainWriteLock(&tvc->lock, 232);
-
- ObtainWriteLock(&afs_xcbhash, 458);
- afs_DequeueCallback(tvc);
- tvc->f.states &= ~(CStatd | CDirty);
- ReleaseWriteLock(&afs_xcbhash);
- if (tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
- osi_dnlc_purgedp(tvc);
- afs_TryToSmush(tvc, *acred, 1);
+ afs_ResetVCache(tvc, acred, 1);
ReleaseWriteLock(&tvc->lock);
-#ifdef AFS_BOZONLOCK_ENV
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
#ifdef AFS_DARWIN80_ENV
vnode_put(AFSTOV(tvc));
#endif
AFS_FAST_RELE(tvc);
}
}
+ }
ReleaseReadLock(&afs_xvcache);
for (i = 0; i < afs_cacheFiles; i++) {
if (!(afs_indexFlags[i] & IFEverUsed))
continue; /* never had any data */
- tdc = afs_GetDSlot(i, NULL);
+ tdc = afs_GetValidDSlot(i);
+ if (!tdc) {
+ continue;
+ }
if (tdc->refCount <= 1) { /* too high, in use by running sys call */
ReleaseReadLock(&tdc->tlock);
- if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
- if (!(afs_indexFlags[i] & IFDataMod)) {
+ if (all || (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell)) {
+ if (!(afs_indexFlags[i] & (IFDataMod | IFFree | IFDiscarded))) {
/* if the file is modified, but has a ref cnt of only 1,
* then someone probably has the file open and is writing
* into it. Better to skip flushing such a file, it will be
* brought back immediately on the next write anyway.
*
+ * Skip if already freed.
+ *
* If we *must* flush, then this code has to be rearranged
* to call afs_storeAllSegments() first */
afs_FlushDCache(tdc);
ReleaseWriteLock(&afs_xdcache);
ObtainReadLock(&afs_xvolume);
- for (i = 0; i < NVOLS; i++) {
+ for (i = all ? 0 : VHash(volume); i < NVOLS; i++) {
for (tv = afs_volumes[i]; tv; tv = tv->next) {
- if (tv->volume == volume) {
+ if (all || tv->volume == volume) {
afs_ResetVolumeInfo(tv);
- break;
+ if (!all)
+ goto last;
}
}
}
+ last:
ReleaseReadLock(&afs_xvolume);
/* probably, a user is doing this, probably, because things are screwed up.
* maybe it's the dnlc's fault? */
osi_dnlc_purge();
+}
+
+/*!
+ * VIOC_FLUSHVOLUME (37) - Flush whole volume's data
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use (args in avc)
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval EIO Error if the afs daemon hasn't started yet
+ *
+ * \post
+ * Flush all cached contents of a volume. Exactly what stays and what
+ * goes depends on the platform.
+ *
+ * \notes
+ * Does not flush a file that a user has open and is using, because
+ * it will be re-created on next write. Also purges the dnlc,
+ * because things are screwed up.
+ */
+DECL_PIOCTL(PFlushVolumeData)
+{
+ AFS_STATCNT(PFlushVolumeData);
+ if (!avc)
+ return EINVAL;
+ if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
+ return EIO; /* Inappropriate ioctl for device */
+
+ FlushVolumeData(&avc->f.fid, *acred);
return 0;
}
+/*!
+ * VIOC_FLUSHALL (14) - Flush whole volume's data for all volumes
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval EIO Error if the afs daemon hasn't started yet
+ *
+ * \post
+ * Flush all cached contents. Exactly what stays and what
+ * goes depends on the platform.
+ *
+ * \notes
+ * Does not flush a file that a user has open and is using, because
+ * it will be re-created on next write. Also purges the dnlc,
+ * because things are screwed up.
+ */
+DECL_PIOCTL(PFlushAllVolumeData)
+{
+ AFS_STATCNT(PFlushAllVolumeData);
+
+ if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
+ return EIO; /* Inappropriate ioctl for device */
+
+ FlushVolumeData(NULL, *acred);
+ return 0;
+}
/*!
* VIOCGETVCXSTATUS (41) - gets vnode x status
return EINVAL;
num = count;
}
- if (afs_cr_gid(*acred) == RMTUSER_REQ ||
- afs_cr_gid(*acred) == RMTUSER_REQ_PRIV) { /* Handles all exporters */
+ if (afs_rmtsys_enable && (afs_cr_gid(*acred) == RMTUSER_REQ ||
+ afs_cr_gid(*acred) == RMTUSER_REQ_PRIV)) { /* Handles all exporters */
if (allpags && afs_cr_gid(*acred) != RMTUSER_REQ_PRIV) {
return EPERM;
}
afs_uint32 temp = sp->host.s_addr;
srvr =
afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
- WRITE_LOCK, (afsUUID *) 0, 0);
+ WRITE_LOCK, (afsUUID *) 0, 0, NULL);
srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
afs_PutServer(srvr, WRITE_LOCK);
}
ssp = (struct setspref *)ainPtr;
if (ainSize < (sizeof(struct setspref)
- + sizeof(struct spref) * ssp->num_servers-1))
+ + sizeof(struct spref) * (ssp->num_servers-1)))
return EINVAL;
afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
code = EINVAL;
goto out;
}
-#ifdef AFS_BOZONLOCK_ENV
- afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
-#endif
ObtainWriteLock(&tvc->lock, 649);
ObtainWriteLock(&afs_xcbhash, 650);
afs_DequeueCallback(tvc);
tvc->linkData = NULL;
}
ReleaseWriteLock(&tvc->lock);
-#ifdef AFS_BOZONLOCK_ENV
- afs_BozonUnlock(&tvc->pvnLock, tvc);
-#endif
afs_PutVCache(tvc);
out:
if (sysState.allocked)
DECL_PIOCTL(PPrefetchFromTape)
{
- afs_int32 code, code1;
- afs_int32 bytes, outval;
+ afs_int32 code;
+ afs_int32 outval;
struct afs_conn *tc;
struct rx_call *tcall;
struct AFSVolSync tsync;
struct vcache *tvc;
struct rx_connection *rxconn;
- AFS_STATCNT(PSetAcl);
+ AFS_STATCNT(PPrefetchFromTape);
if (!avc)
return EINVAL;
StartRXAFS_FetchData(tcall, (struct AFSFid *)&tvc->f.fid.Fid, 0,
0);
if (!code) {
- bytes = rx_Read(tcall, (char *)&outval, sizeof(afs_int32));
+ rx_Read(tcall, (char *)&outval, sizeof(afs_int32));
code =
EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
}
- code1 = rx_EndCall(tcall, code);
+ code = rx_EndCall(tcall, code);
RX_AFS_GLOCK();
} else
code = -1;
cache_bypass_threshold = threshold;
afs_warn("Cache Bypass Threshold set to: %d\n", threshold);
/* TODO: move to separate pioctl, or enhance pioctl */
- cache_bypass_strategy = LARGE_FILES_BYPASS_CACHE;
+ if (threshold == AFS_CACHE_BYPASS_DISABLED)
+ cache_bypass_strategy = NEVER_BYPASS_CACHE;
+ else if (!threshold)
+ cache_bypass_strategy = ALWAYS_BYPASS_CACHE;
+ else
+ cache_bypass_strategy = LARGE_FILES_BYPASS_CACHE;
}
/* Return the current size threshold */
/* get a connection, even if host is down; bumps conn ref count */
tu = afs_GetUser(areq->uid, ts->cell->cellNum, SHARED_LOCK);
tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
- 1 /*force */ , 1 /*create */ , SHARED_LOCK, &rxconn);
+ 1 /*force */ , 1 /*create */ , SHARED_LOCK, 0, &rxconn);
afs_PutUser(tu, SHARED_LOCK);
if (!tc)
continue;
int i, cellNum, primaryFlag;
XDR xdrs;
struct unixuser *tu;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
struct ktc_setTokenData tokenSet;
struct ktc_tokenUnion decodedToken;
}
if (tokenSet.flags & AFSTOKEN_EX_SETPAG) {
+#if defined(AFS_LINUX26_ENV)
+ afs_ucred_t *old_cred = *acred;
+#endif
if (_settok_setParentPag(acred) == 0) {
- afs_InitReq(&treq, *acred);
- areq = &treq;
+#if defined(AFS_LINUX26_ENV)
+ /* setpag() may have changed our credentials */
+ *acred = crref();
+ crfree(old_cred);
+#endif
+ code = afs_CreateReq(&treq, *acred);
+ if (code) {
+ xdr_free((xdrproc_t) xdr_ktc_setTokenData, &tokenSet);
+ return code;
+ }
+ areq = treq;
}
}
out:
afs_ResetUserConns(tu);
afs_PutUser(tu, WRITE_LOCK);
+ afs_DestroyReq(treq);
return code;
}
DECL_PIOCTL(PGetTokens2)
{
- struct cell *cell;
+ struct cell *cell = NULL;
struct unixuser *tu = NULL;
afs_int32 iterator;
char *cellName = NULL;