afs: Return to userspace after AFS_NEW_BKG reqs
[openafs.git] / src / afs / afs_daemons.c
index 538dd59..8913958 100644 (file)
@@ -136,7 +136,6 @@ afs_Daemon(void)
     afs_int32 last3MinCheck, last10MinCheck, last60MinCheck, lastNMinCheck;
     afs_int32 last1MinCheck, last5MinCheck;
     afs_uint32 lastCBSlotBump;
-    char cs_warned = 0;
 
     AFS_STATCNT(afs_Daemon);
 
@@ -190,14 +189,11 @@ afs_Daemon(void)
        if (last1MinCheck + 60 < now) {
            /* things to do every minute */
            DFlush();           /* write out dir buffers */
-           afs_WriteThroughDSlots();   /* write through cacheinfo entries */
+           (void)afs_WriteThroughDSlots();     /* write through cacheinfo entries */
            ObtainWriteLock(&afs_xvcache, 736);
            afs_FlushReclaimedVcaches();
            ReleaseWriteLock(&afs_xvcache);
            afs_FlushActiveVcaches(1);  /* keep flocks held & flush nfs writes */
-#if 0
-           afs_StoreDirtyVcaches();
-#endif
            last1MinCheck = now;
        }
 
@@ -220,11 +216,6 @@ afs_Daemon(void)
         }
 
        if (!afs_CheckServerDaemonStarted) {
-           /* Do the check here if the correct afsd is not installed. */
-           if (!cs_warned) {
-               cs_warned = 1;
-               afs_warn("Please install afsd with check server daemon.\n");
-           }
            if (lastNMinCheck + afs_probe_interval < now) {
                /* only check down servers */
                afs_CheckServers(1, NULL);
@@ -312,7 +303,7 @@ afs_Daemon(void)
 int
 afs_CheckRootVolume(void)
 {
-    char rootVolName[32];
+    char rootVolName[MAXROOTVOLNAMELEN];
     struct volume *tvp = NULL;
     int usingDynroot = afs_GetDynrootEnable();
     int localcell;
@@ -357,71 +348,14 @@ afs_CheckRootVolume(void)
                 * count to zero and fs checkv is executed when the current
                 * directory is /afs.
                 */
-#ifdef AFS_LINUX20_ENV
-               {
-                   struct vrequest *treq = NULL;
-                   struct vattr vattr;
-                   cred_t *credp;
-                   struct dentry *dp;
-                   struct vcache *vcp;
-
-                   afs_rootFid.Fid.Volume = volid;
-                   afs_rootFid.Fid.Vnode = 1;
-                   afs_rootFid.Fid.Unique = 1;
-
-                   credp = crref();
-                   if (afs_CreateReq(&treq, credp))
-                       goto out;
-                   vcp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL);
-                   if (!vcp)
-                       goto out;
-                   afs_getattr(vcp, &vattr, credp);
-                   afs_fill_inode(AFSTOV(vcp), &vattr);
-
-                   dp = d_find_alias(AFSTOV(afs_globalVp));
-
-#if defined(AFS_LINUX24_ENV)
-#if defined(HAVE_DCACHE_LOCK)
-                   spin_lock(&dcache_lock);
-#else
-                   spin_lock(&AFSTOV(vcp)->i_lock);
-#endif
-#if defined(AFS_LINUX26_ENV)
-                   spin_lock(&dp->d_lock);
-#endif
-#endif
-#if defined(D_ALIAS_IS_HLIST)
-                   hlist_del_init(&dp->d_alias);
-                   hlist_add_head(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
-#else
-                   list_del_init(&dp->d_alias);
-                   list_add(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
-#endif
-                   dp->d_inode = AFSTOV(vcp);
-#if defined(AFS_LINUX24_ENV)
-#if defined(AFS_LINUX26_ENV)
-                   spin_unlock(&dp->d_lock);
-#endif
-#if defined(HAVE_DCACHE_LOCK)
-                   spin_unlock(&dcache_lock);
-#else
-                   spin_unlock(&AFSTOV(vcp)->i_lock);
-#endif
-#endif
-                   dput(dp);
-
-                   AFS_FAST_RELE(afs_globalVp);
-                   afs_globalVp = vcp;
-               out:
-                   crfree(credp);
-                   afs_DestroyReq(treq);
-               }
+#ifdef AFS_LINUX22_ENV
+               osi_ResetRootVCache(volid);
 #else
-#ifdef AFS_DARWIN80_ENV
+# ifdef AFS_DARWIN80_ENV
                afs_PutVCache(afs_globalVp);
-#else
+# else
                AFS_FAST_RELE(afs_globalVp);
-#endif
+# endif
                afs_globalVp = 0;
 #endif
            }
@@ -661,6 +595,26 @@ BPartialStore(struct brequest *ab)
     afs_DestroyReq(treq);
 }
 
+static void
+BInvalidateSegments(struct brequest *ab)
+{
+    int code;
+    struct vcache *tvc = ab->vc;
+    osi_Assert(WriteLocked(&tvc->lock));
+
+    code = afs_InvalidateAllSegments_once(tvc);
+
+    /* Set return code, and wakeup anyone waiting. */
+    if ((ab->flags & BUVALID) == 0) {
+       ab->code_raw = ab->code_checkcode = code;
+       ab->flags |= BUVALID;
+       if ((ab->flags & BUWAIT)) {
+           ab->flags &= ~BUWAIT;
+           afs_osi_Wakeup(ab);
+       }
+    }
+}
+
 /* release a held request buffer */
 void
 afs_BRelease(struct brequest *ab)
@@ -712,7 +666,7 @@ afs_BQueue(short aopcode, struct vcache *avc,
                crhold(tb->cred);
            }
            if (avc) {
-               AFS_FAST_HOLD(avc);
+               osi_Assert(osi_vnhold(avc) == 0);
            }
            tb->refCount = ause + 1;
            tb->size_parm[0] = asparm0;
@@ -1052,6 +1006,44 @@ brequest_release(struct brequest *tb)
 }
 
 #ifdef AFS_NEW_BKG
+static_inline int
+should_do_noop(int foundAny, int n_processed)
+{
+    if (!foundAny && n_processed > 0) {
+       /* If there aren't any requests right now, and we've processed
+        * at least one request, do a noop. */
+       return 1;
+    } else if (foundAny && n_processed > 100) {
+       /* If we've processed over 100 requests in a row, do a noop. */
+       return 1;
+    }
+    return 0;
+}
+#endif
+
+/**
+ * Entry point for background daemon processes.
+ *
+ * For old-style background daemons (non-AFS_NEW_BKG), a background daemon afsd
+ * process will end up in this function, and it will stay in here forever
+ * processing in-kernel bkg requests until the client shuts down.
+ *
+ * For new-style background daemons (AFS_NEW_BKG), we can pass data back to
+ * afsd to perform some background operations in userspace, by populating
+ * 'uspc' with the operation to perform and then returning. When the afsd
+ * process enters this function again, the return code for that operation is
+ * also provided in 'uspc'.
+ *
+ * @param[inout] uspc   Userspace operation data. If uspc->ts is non-negative
+ *                      on entry, the related background request has finished,
+ *                      and we're providing the return code. On return,
+ *                      contains the userspace operation to perform.
+ * @param[inout] param1 Operation-specific pointer.
+ * @param[inout] param2 Operation-specific pointer.
+ *
+ * @return  Always returns 0.
+ */
+#ifdef AFS_NEW_BKG
 int
 afs_BackgroundDaemon(struct afs_uspc_param *uspc, void *param1, void *param2)
 #else
@@ -1061,6 +1053,7 @@ afs_BackgroundDaemon(void)
 {
     struct brequest *tb;
     int i, foundAny;
+    int n_processed = 0;
 
     AFS_STATCNT(afs_BackgroundDaemon);
     /* initialize subsystem */
@@ -1069,14 +1062,18 @@ afs_BackgroundDaemon(void)
        afs_BackgroundDaemon_once();
 
 #ifdef AFS_NEW_BKG
-    /* If it's a re-entering syscall, complete the request and release */
-    if (uspc->ts > -1) {
+    if (uspc->reqtype == AFS_USPC_NOOP) {
+       /* The daemon is re-entering from a noop, not actually returning data;
+        * don't look for an existing request. */
+       /* noop */
+
+    } else if (uspc->ts > -1) {
+       /* If it's a re-entering syscall, complete the request and release */
         tb = afs_brs;
         for (i = 0; i < NBRS; i++, tb++) {
             if (tb->ts == uspc->ts) {
                 /* copy the userspace status back in */
-                ((struct afs_uspc_param *) tb->ptr_parm[0])->retval =
-                    uspc->retval;
+                tb->code_raw = tb->code_checkcode = uspc->retval;
                 /* mark it valid and notify our caller */
                 tb->flags |= BUVALID;
                 if (tb->flags & BUWAIT) {
@@ -1107,7 +1104,9 @@ afs_BackgroundDaemon(void)
            ReleaseWriteLock(&afs_xbrs);
            afs_osi_Wakeup(&afs_termState);
 #ifdef AFS_NEW_BKG
-           return -2;
+           memset(uspc, 0, sizeof(*uspc));
+           uspc->reqtype = AFS_USPC_SHUTDOWN;
+           return 0;
 #else
            return;
 #endif
@@ -1131,6 +1130,7 @@ afs_BackgroundDaemon(void)
            tb->flags |= BSTARTED;
            ReleaseWriteLock(&afs_xbrs);
            foundAny = 1;
+           n_processed++;
            afs_Trace1(afs_iclSetp, CM_TRACE_BKG1, ICL_TYPE_INT32,
                       tb->opcode);
            if (tb->opcode == BOP_FETCH)
@@ -1158,11 +1158,23 @@ afs_BackgroundDaemon(void)
 #endif
            else if (tb->opcode == BOP_PARTIAL_STORE)
                BPartialStore(tb);
+           else if (tb->opcode == BOP_INVALIDATE_SEGMENTS)
+               BInvalidateSegments(tb);
            else
                panic("background bop");
            brequest_release(tb);
            ObtainWriteLock(&afs_xbrs, 305);
        }
+
+#ifdef AFS_NEW_BKG
+       if (should_do_noop(foundAny, n_processed)) {
+           ReleaseWriteLock(&afs_xbrs);
+           memset(uspc, 0, sizeof(*uspc));
+           uspc->reqtype = AFS_USPC_NOOP;
+           return 0;
+       }
+#endif
+
        if (!foundAny) {
            /* wait for new request */
            afs_brsDaemons++;