libafs: fs flushall for unix cm
authorMichael Meffie <mmeffie@sinenomine.net>
Thu, 7 Jun 2012 18:46:04 +0000 (14:46 -0400)
committerDerrick Brashear <shadow@your-file-system.com>
Thu, 24 Jan 2013 16:35:40 +0000 (08:35 -0800)
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>

doc/man-pages/pod1/fs_flushall.pod
src/afs/afs_pioctl.c
src/afs/afs_stats.h
src/config/vioc.h
src/venus/fs.c

index 92a621e..38a9144 100644 (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
index b6b2009..df194b5 100644 (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
index 11e242a..1c0feb3 100644 (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;
index caf140f..f6a40a3 100644 (file)
 #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 */
index 9dc26ba..c05bfe5 100644 (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");