afs: Set DWriting when truncating a dcache entry
[openafs.git] / src / afs / afs_segments.c
index 8ae6680..192a3d4 100644 (file)
@@ -253,6 +253,11 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
            if ((afs_indexFlags[index] & IFDataMod)
                && (afs_indexUnique[index] == avc->f.fid.Fid.Unique)) {
                tdc = afs_GetValidDSlot(index); /* refcount+1. */
+               if (!tdc) {
+                   ReleaseWriteLock(&afs_xdcache);
+                   code = EIO;
+                   goto done;
+               }
                ReleaseReadLock(&tdc->tlock);
                if (!FidCmp(&tdc->f.fid, &avc->f.fid) && tdc->f.chunk >= minj) {
                    off = tdc->f.chunk - minj;
@@ -315,6 +320,7 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
        minj += NCHUNKSATONCE;
     } while (!code && moredata);
 
+ done:
     UpgradeSToWLock(&avc->lock, 29);
 
     /* send a trivial truncation store if did nothing else */
@@ -357,6 +363,7 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
 
                if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
                    tdc = afs_GetValidDSlot(index);
+                   if (!tdc) osi_Panic("afs_StoreAllSegments tdc dv");
                    ReleaseReadLock(&tdc->tlock);
 
                    if (!FidCmp(&tdc->f.fid, &avc->f.fid)
@@ -411,6 +418,9 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
                        UpgradeSToWLock(&tdc->lock, 678);
                        hset(tdc->f.versionNo, avc->f.m.DataVersion);
                        tdc->dflags |= DFEntryMod;
+                       /* DWriting may not have gotten cleared above, if all
+                        * we did was a StoreMini */
+                       tdc->f.states &= ~DWriting;
                        ConvertWToSLock(&tdc->lock);
                    }
                }
@@ -521,6 +531,7 @@ afs_InvalidateAllSegments(struct vcache *avc)
     for (index = afs_dvhashTbl[hash]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_InvalidateAllSegments tdc count");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid))
                dcListMax++;
@@ -535,6 +546,7 @@ afs_InvalidateAllSegments(struct vcache *avc)
     for (index = afs_dvhashTbl[hash]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_InvalidateAllSegments tdc store");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
                /* same file? we'll zap it */
@@ -713,6 +725,11 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
     for (index = afs_dvhashTbl[code]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) {
+               ReleaseWriteLock(&afs_xdcache);
+               code = EIO;
+               goto done;
+           }
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid))
                dcCount++;
@@ -731,6 +748,7 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
     for (index = afs_dvhashTbl[code]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_TruncateAllSegments tdc");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
                /* same file, and modified, we'll store it back */
@@ -760,6 +778,7 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
        ObtainSharedLock(&tdc->lock, 672);
        if (newSize < tdc->f.chunkBytes && newSize < MAX_AFS_UINT32) {
            UpgradeSToWLock(&tdc->lock, 673);
+           tdc->f.states |= DWriting;
            tfile = afs_CFileOpen(&tdc->f.inode);
            afs_CFileTruncate(tfile, (afs_int32)newSize);
            afs_CFileClose(tfile);
@@ -778,6 +797,9 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
 
     osi_Free(tdcArray, dcCount * sizeof(struct dcache *));
 
+    code = 0;
+
+ done:
 #if    (defined(AFS_SUN5_ENV))
     ObtainWriteLock(&avc->vlock, 547);
     if (--avc->activeV == 0 && (avc->vstates & VRevokeWait)) {
@@ -787,5 +809,5 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
     ReleaseWriteLock(&avc->vlock);
 #endif
 
-    return 0;
+    return code;
 }