libafs: Set tvcp->callback before BulkStatus
authorAndrew Deason <adeason@sinenomine.net>
Thu, 12 Aug 2010 19:38:55 +0000 (14:38 -0500)
committerDerrick Brashear <shadow@dementia.org>
Mon, 6 Dec 2010 18:50:16 +0000 (10:50 -0800)
When we call InlineBulkStatus or BulkStatus, we currently do not touch
tvcp->callback for any of the vcaches before making the call. This can
cause us to not notice an InitCallBackState issued by the fileserver
before the BulkStatus call returns, since the InitCallBackState
handler looks at tvcp->callback to determine what vcaches to clear
callbacks for. In turn, this can cause us to think we have a callback
agreement with the fileserver on one of the BulkStatus'd files, when
the fileserver does not actually have such a callback agreement.

So, set tvcp->callback to the server we are contacting, so if we get
an InitCallBackState call from that fileserver, the CBulkFetching
state will be cleared, and we will correctly discard the callback
information for that vcache.

Change-Id: Ib8790c8f9621d7a9da12588ea6115f9cb3ff9022
Reviewed-on: http://gerrit.openafs.org/2548
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/afs/VNOPS/afs_vnop_lookup.c

index 609403c..759abfe 100644 (file)
@@ -929,6 +929,36 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        tcp = afs_Conn(&adp->f.fid, areqp, SHARED_LOCK);
        if (tcp) {
            hostp = tcp->parent->srvr->server;
+
+           for (i = 0; i < fidIndex; i++) {
+               /* we must set tvcp->callback before the BulkStatus call, so
+                * we can detect concurrent InitCallBackState's */
+
+               afid.Cell = adp->f.fid.Cell;
+               afid.Fid.Volume = adp->f.fid.Fid.Volume;
+               afid.Fid.Vnode = fidsp[i].Vnode;
+               afid.Fid.Unique = fidsp[i].Unique;
+
+               do {
+                   retry = 0;
+                   ObtainReadLock(&afs_xvcache);
+                   tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */);
+                   ReleaseReadLock(&afs_xvcache);
+               } while (tvcp && retry);
+
+               if (!tvcp) {
+                   continue;
+               }
+
+               if ((tvcp->f.states & CBulkFetching) &&
+                    (tvcp->f.m.Length == statSeqNo)) {
+                   tvcp->callback = hostp;
+               }
+
+               afs_PutVCache(tvcp);
+               tvcp = NULL;
+           }
+
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_BULKSTATUS);
 
            if (!(tcp->parent->srvr->server->flags & SNO_INLINEBULK)) {