libafs: fs flushall for unix cm

Implement the fs flushall command on the unix cache manager to flush
all volume data.  Uses a new common pioctl code point VIOC_FLUSHALL (14),
registered with the grand.central.org assigned numbers.

Change-Id: I214d8c762573b308d79fa7122a91d48ddd403eb9
Reviewed-on: http://gerrit.openafs.org/7540
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
This commit is contained in:
Michael Meffie 2012-06-07 14:46:04 -04:00 committed by Derrick Brashear
parent 9c07dd592a
commit 4197bbecd9
5 changed files with 105 additions and 41 deletions

View File

@ -18,10 +18,6 @@ B<fs flusha> [B<-h>]
The B<fs flushall> command flushes all data from the AFS cache.
=head1 CAUTIONS
This command is only available on Windows.
=head1 OPTIONS
=over 4

View File

@ -277,6 +277,7 @@ DECL_PIOCTL(PRemoveMount);
DECL_PIOCTL(PGetCellStatus);
DECL_PIOCTL(PSetCellStatus);
DECL_PIOCTL(PFlushVolumeData);
DECL_PIOCTL(PFlushAllVolumeData);
DECL_PIOCTL(PGetVnodeXStatus);
DECL_PIOCTL(PGetVnodeXStatus2);
DECL_PIOCTL(PSetSysName);
@ -420,6 +421,7 @@ static pioctlFunction CpioctlSw[] = {
PBogus, /* 11 */
PPrecache, /* 12 */
PGetPAG, /* 13 */
PFlushAllVolumeData, /* 14 */
};
static pioctlFunction OpioctlSw[] = {
@ -3442,46 +3444,27 @@ DECL_PIOCTL(PSetCellStatus)
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
@ -3489,11 +3472,11 @@ DECL_PIOCTL(PFlushVolumeData)
*/
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);
@ -3522,7 +3505,7 @@ DECL_PIOCTL(PFlushVolumeData)
afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
#endif
ObtainWriteLock(&tvc->lock, 232);
afs_ResetVCache(tvc, *acred, 1);
afs_ResetVCache(tvc, acred, 1);
ReleaseWriteLock(&tvc->lock);
#ifdef AFS_BOZONLOCK_ENV
afs_BozonUnlock(&tvc->pvnLock, tvc);
@ -3536,6 +3519,7 @@ DECL_PIOCTL(PFlushVolumeData)
AFS_FAST_RELE(tvc);
}
}
}
ReleaseReadLock(&afs_xvcache);
@ -3549,7 +3533,7 @@ DECL_PIOCTL(PFlushVolumeData)
}
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 (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
@ -3573,7 +3557,7 @@ DECL_PIOCTL(PFlushVolumeData)
ObtainReadLock(&afs_xvolume);
for (i = 0; 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;
}
@ -3584,9 +3568,70 @@ DECL_PIOCTL(PFlushVolumeData)
/* 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

View File

@ -656,7 +656,8 @@ struct afs_MeanStats {
AFS_CS(BPrefetchNoCache) /* afs_daemons.c */ \
AFS_CS(afs_ReadNoCache) /* osi_vnodeops.c */ \
AFS_CS(PSetTokens2) /* afs_pioctl.c */ \
AFS_CS(PPrefetchFromTape) /* afs_pioctl.c */
AFS_CS(PPrefetchFromTape) /* afs_pioctl.c */ \
AFS_CS(PFlushAllVolumeData) /* afs_pioctl.c */
struct afs_CMCallStats {
#define AFS_CS(call) afs_int32 C_ ## call;

View File

@ -104,6 +104,7 @@
#define VIOC_NEWUUID _CVICEIOCTL(9) /* new uuid */
#define VIOCPRECACHE _CVICEIOCTL(12) /* precache size */
#define VIOC_GETPAG _CVICEIOCTL(13) /* get pag value */
#define VIOC_FLUSHALL _CVICEIOCTL(14) /* flush all volume data */
/* OpenAFS-specific 'O' pioctl's */
#define VIOC_NFS_NUKE_CREDS _OVICEIOCTL(1) /* nuke creds for all PAG's */

View File

@ -1314,6 +1314,25 @@ FlushVolumeCmd(struct cmd_syndesc *as, void *arock)
return error;
}
static int
FlushAllVolumesCmd(struct cmd_syndesc *as, void *arock)
{
afs_int32 code;
struct ViceIoctl blob;
int error = 0;
blob.in_size = 0;
blob.out_size = AFS_PIOCTL_MAXSIZE;
blob.out = space;
code = pioctl(NULL, VIOC_FLUSHALL, &blob, 0);
if (code) {
fprintf(stderr, "Error flushing all volumes\n");
error = 1;
}
return error;
}
/*
* The Windows version of UuidCmd displays the UUID.
* When the UNIX version is updated to do the same
@ -3869,6 +3888,8 @@ defect 3069
"flush all data in volume");
cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
cmd_CreateSyntax("flushall", FlushAllVolumesCmd, NULL, "flush all data from the cache");
ts = cmd_CreateSyntax("sysname", SysNameCmd, NULL,
"get/set sysname (i.e. @sys) value");
cmd_AddParm(ts, "-newsys", CMD_LIST, CMD_OPTIONAL, "new sysname");