afs: Remove osi_GetuTime
[openafs.git] / src / afs / afs_fetchstore.c
index 99f9c51..06325b9 100644 (file)
@@ -11,9 +11,6 @@
 #include "afs/param.h"
 
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
-#ifndef AFS_LINUX22_ENV
-#include "rpc/types.h"
-#endif
 #ifdef AFS_ALPHA_ENV
 #undef kmem_alloc
 #undef kmem_free
@@ -28,15 +25,15 @@ extern int cacheDiskType;
 
 #ifndef AFS_NOSTATS
 static void
-FillStoreStats(int code, int idx, osi_timeval_t xferStartTime,
+FillStoreStats(int code, int idx, osi_timeval32_t xferStartTime,
               afs_size_t bytesToXfer, afs_size_t bytesXferred)
 {
     struct afs_stats_xferData *xferP;
-    osi_timeval_t xferStopTime;
-    osi_timeval_t elapsedTime;
+    osi_timeval32_t xferStopTime;
+    osi_timeval32_t elapsedTime;
 
     xferP = &(afs_stats_cmfullperf.rpc.fsXferTimes[idx]);
-    osi_GetuTime(&xferStopTime);
+    osi_GetTime(&xferStopTime);
     (xferP->numXfers)++;
     if (!code) {
        (xferP->numSuccesses)++;
@@ -240,18 +237,15 @@ rxfs_storeClose(void *r, struct AFSFetchStatus *OutStatus, int *doProcessFS)
 }
 
 afs_int32
-rxfs_storeDestroy(void **r, afs_int32 error)
+rxfs_storeDestroy(void **r, afs_int32 code)
 {
-    afs_int32 code = error;
     struct rxfs_storeVariables *v = (struct rxfs_storeVariables *)*r;
 
     *r = NULL;
     if (v->call) {
        RX_AFS_GUNLOCK();
-       code = rx_EndCall(v->call, error);
+       code = rx_EndCall(v->call, code);
        RX_AFS_GLOCK();
-       if (!code && error)
-           code = error;
     }
     if (v->tbuffer)
        osi_FreeLargeSpace(v->tbuffer);
@@ -276,6 +270,7 @@ afs_GenericStoreProc(struct storeOps *ops, void *rock,
     size = tdc->f.chunkBytes;
 
     tfile = afs_CFileOpen(&tdc->f.inode);
+    osi_Assert(tfile);
 
     while ( size > 0 ) {
        code = (*ops->prepare)(rock, size, &tlen);
@@ -329,12 +324,8 @@ struct storeOps rxfs_storeUfsOps = {
     .padd =    rxfs_storePadd,
     .close =   rxfs_storeClose,
     .destroy = rxfs_storeDestroy,
-#ifdef AFS_LINUX26_ENV
-    .storeproc = afs_linux_storeproc
-#else
     .storeproc = afs_GenericStoreProc
 #endif
-#endif
 };
 
 static
@@ -409,8 +400,8 @@ rxfs_storeInit(struct vcache *avc, struct afs_conn *tc,
        code = -1;
     RX_AFS_GLOCK();
     if (code) {
-       osi_FreeSmallSpace(v);
-        return code;
+        *rock = v;
+        return rxfs_storeDestroy(rock, code);
     }
     if (cacheDiskType == AFS_FCACHE_TYPE_UFS) {
        v->tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
@@ -424,19 +415,6 @@ rxfs_storeInit(struct vcache *avc, struct afs_conn *tc,
            osi_Panic
             ("rxfs_storeInit: osi_AllocSmallSpace for iovecs returned NULL\n");
        *ops = (struct storeOps *) &rxfs_storeMemOps;
-#ifdef notdef
-       /* do this at a higher level now -- it's a parameter */
-       /* for now, only do 'continue from close' code if file fits in one
-        * chunk.  Could clearly do better: if only one modified chunk
-        * then can still do this.  can do this on *last* modified chunk */
-       length = avc->f.m.Length - 1; /* byte position of last byte we'll store */
-       if (shouldWake) {
-           if (AFS_CHUNK(length) != 0)
-               *shouldWake = 0;
-           else
-               *shouldWake = 1;
-       }
-#endif /* notdef */
     }
 
     *rock = (void *)v;
@@ -470,7 +448,7 @@ afs_CacheStoreDCaches(struct vcache *avc, struct dcache **dclist,
     afs_size_t bytesXferred;
 
 #ifndef AFS_NOSTATS
-    osi_timeval_t xferStartTime;       /*FS xfer start time */
+    osi_timeval32_t xferStartTime;     /*FS xfer start time */
     afs_size_t bytesToXfer = 10000;    /* # bytes to xfer */
 #endif /* AFS_NOSTATS */
     XSTATS_DECLS;
@@ -514,7 +492,7 @@ afs_CacheStoreDCaches(struct vcache *avc, struct dcache **dclist,
         */
        bytesToXfer = size;
 
-       osi_GetuTime(&xferStartTime);
+       osi_GetTime(&xferStartTime);
 #endif /* AFS_NOSTATS */
        bytesXferred = 0;
 
@@ -811,7 +789,7 @@ afs_int32
 rxfs_fetchClose(void *r, struct vcache *avc, struct dcache * adc,
                struct afs_FetchOutput *o)
 {
-    afs_int32 code, code1 = 0;
+    afs_int32 code;
     struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)r;
 
     if (!v->call)
@@ -826,10 +804,8 @@ rxfs_fetchClose(void *r, struct vcache *avc, struct dcache * adc,
 #endif
         code = EndRXAFS_FetchData(v->call, &o->OutStatus, &o->CallBack,
                                &o->tsync);
-    code1 = rx_EndCall(v->call, code);
+    code = rx_EndCall(v->call, code);
     RX_AFS_GLOCK();
-    if (!code && code1)
-       code = code1;
 
     v->call = NULL;
 
@@ -837,18 +813,15 @@ rxfs_fetchClose(void *r, struct vcache *avc, struct dcache * adc,
 }
 
 afs_int32
-rxfs_fetchDestroy(void **r, afs_int32 error)
+rxfs_fetchDestroy(void **r, afs_int32 code)
 {
-    afs_int32 code = error;
     struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)*r;
 
     *r = NULL;
     if (v->call) {
         RX_AFS_GUNLOCK();
-       code = rx_EndCall(v->call, error);
+       code = rx_EndCall(v->call, code);
         RX_AFS_GLOCK();
-       if (error)
-           code = error;
     }
     if (v->tbuffer)
        osi_FreeLargeSpace(v->tbuffer);
@@ -914,7 +887,7 @@ rxfs_fetchInit(struct afs_conn *tc, struct rx_connection *rxconn,
               struct osi_file *fP, struct fetchOps **ops, void **rock)
 {
     struct rxfs_fetchVariables *v;
-    int code = 0, code1 = 0;
+    int code = 0;
 #ifdef AFS_64BIT_CLIENT
     afs_uint32 length_hi = 0;
 #endif
@@ -948,9 +921,8 @@ rxfs_fetchInit(struct afs_conn *tc, struct rx_connection *rxconn,
                if (bytes == sizeof(afs_int32)) {
                    length_hi = ntohl(length_hi);
                } else {
-                   code = rx_Error(v->call);
                    RX_AFS_GUNLOCK();
-                   code1 = rx_EndCall(v->call, code);
+                   code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
                    RX_AFS_GLOCK();
                    v->call = NULL;
                }
@@ -982,14 +954,49 @@ rxfs_fetchInit(struct afs_conn *tc, struct rx_connection *rxconn,
                length = ntohl(length);
            else {
                RX_AFS_GUNLOCK();
-               code = rx_Error(v->call);
-                code1 = rx_EndCall(v->call, code);
+                code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
                v->call = NULL;
                length = 0;
                RX_AFS_GLOCK();
            }
        }
        FillInt64(length64, length_hi, length);
+
+        if (!code) {
+            /* Check if the fileserver said our length is bigger than can fit
+             * in a signed 32-bit integer. If it is, we can't handle that, so
+             * error out. */
+           if (length64 > MAX_AFS_INT32) {
+                static int warned;
+                if (!warned) {
+                    warned = 1;
+                    afs_warn("afs: Warning: FetchData64 returned too much data "
+                             "(length64 %u.%u); this should not happen! "
+                             "Aborting fetch request.\n",
+                             length_hi, length);
+                }
+               RX_AFS_GUNLOCK();
+                code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
+               v->call = NULL;
+               length = 0;
+               RX_AFS_GLOCK();
+                code = code != 0 ? code : EIO;
+            }
+        }
+
+        if (!code) {
+            /* Check if the fileserver said our length was negative. If it
+             * is, just treat it as a 0 length, since some older fileservers
+             * returned negative numbers when they meant to return 0. Note
+             * that we must do this in this 64-bit-specific block, since
+             * length64 being negative will screw up our conversion to the
+             * 32-bit 'alength' below. */
+            if (length64 < 0) {
+                length_hi = length = 0;
+                FillInt64(length64, 0, 0);
+            }
+        }
+
        afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64LENG,
                   ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
                   ICL_TYPE_OFFSET,
@@ -1008,9 +1015,14 @@ rxfs_fetchInit(struct afs_conn *tc, struct rx_connection *rxconn,
            RX_AFS_GLOCK();
            if (bytes == sizeof(afs_int32)) {
                 *alength = ntohl(length);
+                if (*alength < 0) {
+                    /* Older fileservers can return a negative length when they
+                     * meant to return 0; just assume negative lengths were
+                     * meant to be 0 lengths. */
+                    *alength = 0;
+                }
            } else {
-               code = rx_Error(v->call);
-                code1 = rx_EndCall(v->call, code);
+                code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
                v->call = NULL;
            }
        }
@@ -1026,20 +1038,24 @@ rxfs_fetchInit(struct afs_conn *tc, struct rx_connection *rxconn,
         * requested. It shouldn't do that, and accepting that much data
         * can make us take up more cache space than we're supposed to,
         * so error. */
-       code = rx_Error(v->call);
+        static int warned;
+        if (!warned) {
+            warned = 1;
+            afs_warn("afs: Warning: FetchData64 returned more data than "
+                     "requested (requested %ld, got %ld); this should not "
+                     "happen! Aborting fetch request.\n",
+                     (long)size, (long)*alength);
+        }
        RX_AFS_GUNLOCK();
-       code1 = rx_EndCall(v->call, code);
+       code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
        RX_AFS_GLOCK();
        v->call = NULL;
        code = EIO;
     }
 
-    if (!code && code1)
-       code = code1;
-
     if (code) {
-       osi_FreeSmallSpace(v);
-        return code;
+        *rock = v;
+        return rxfs_fetchDestroy(rock, code);
     }
     if (cacheDiskType == AFS_FCACHE_TYPE_UFS) {
        v->tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
@@ -1098,7 +1114,7 @@ afs_CacheFetchProc(struct afs_conn *tc, struct rx_connection *rxconn,
 
     XSTATS_DECLS;
 #ifndef AFS_NOSTATS
-    osi_timeval_t xferStartTime;       /*FS xfer start time */
+    osi_timeval32_t xferStartTime;     /*FS xfer start time */
     afs_size_t bytesToXfer = 0, bytesXferred = 0;
 #endif
 
@@ -1116,16 +1132,20 @@ afs_CacheFetchProc(struct afs_conn *tc, struct rx_connection *rxconn,
                tc, rxconn, avc, base, size, &length, adc, fP, &ops, &rock);
 
 #ifndef AFS_NOSTATS
-    osi_GetuTime(&xferStartTime);
+    osi_GetTime(&xferStartTime);
 #endif /* AFS_NOSTATS */
 
     adc->validPos = base;
 
-    if ( !code ) do {
+    if (code) {
+        goto done;
+    }
+
+    do {
        if (avc->f.states & CForeign) {
            code = (*ops->more)(rock, &length, &moredata);
            if ( code )
-               break;
+               goto done;
        }
 #ifndef AFS_NOSTATS
        bytesToXfer += length;
@@ -1148,11 +1168,11 @@ afs_CacheFetchProc(struct afs_conn *tc, struct rx_connection *rxconn,
                           ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
                           ICL_TYPE_INT32, length);
                code = -34;
-               break;
+               goto done;
            }
            code = (*ops->write)(rock, fP, offset, bytesread, &byteswritten);
            if ( code )
-               break;
+               goto done;
            offset += bytesread;
            base += bytesread;
            length -= bytesread;
@@ -1165,6 +1185,7 @@ afs_CacheFetchProc(struct afs_conn *tc, struct rx_connection *rxconn,
        }
        code = 0;
     } while (moredata);
+ done:
     if (!code)
        code = (*ops->close)(rock, avc, adc, tsmall);
     if (ops)