Windows: Apply MAX_FID_COUNT to AFS Redirector
[openafs.git] / src / WINNT / afsd / cm_vnodeops.c
index c857a5f..36cefd4 100644 (file)
@@ -12,6 +12,7 @@
 #include <roken.h>
 
 #include <afs/stds.h>
+#include <afs/unified_afs.h>
 
 #include <windows.h>
 #include <winsock2.h>
@@ -905,7 +906,7 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
     if (scp->mountRootFid.cell != 0 && scp->mountRootGen >= cm_data.mountRootGen) {
         tfid = scp->mountRootFid;
         lock_ReleaseWrite(&scp->rw);
-        code = cm_GetSCache(&tfid, outScpp, userp, reqp);
+        code = cm_GetSCache(&tfid, NULL, outScpp, userp, reqp);
         lock_ObtainWrite(&scp->rw);
         return code;
     }
@@ -1022,7 +1023,7 @@ long cm_FollowMountPoint(cm_scache_t *scp, cm_scache_t *dscp, cm_user_t *userp,
 
         tfid = scp->mountRootFid;
         lock_ReleaseWrite(&scp->rw);
-        code = cm_GetSCache(&tfid, outScpp, userp, reqp);
+        code = cm_GetSCache(&tfid, NULL, outScpp, userp, reqp);
         lock_ObtainWrite(&scp->rw);
     }
 
@@ -1267,7 +1268,7 @@ notfound:
     if ( !tscp )    /* we did not find it in the dnlc */
     {
         dnlcHit = 0;
-        code = cm_GetSCache(&rock.fid, &tscp, userp, reqp);
+        code = cm_GetSCache(&rock.fid, &dscp->fid, &tscp, userp, reqp);
         if (code)
             goto done;
     }
@@ -1483,7 +1484,7 @@ long cm_EvaluateVolumeReference(clientchar_t * namep, long flags, cm_user_t * us
 
     cm_SetFid(&fid, cellp->cellID, volume, 1, 1);
 
-    code = cm_GetSCache(&fid, outScpp, userp, reqp);
+    code = cm_GetSCache(&fid, NULL, outScpp, userp, reqp);
 
   _exit_cleanup:
     if (fnamep)
@@ -1968,7 +1969,6 @@ long cm_NameI(cm_scache_t *rootSCachep, clientchar_t *pathp, long flags,
     int symlinkCount;          /* count of # of symlinks traversed */
     int extraFlag;             /* avoid chasing mt pts for dir cmd */
     int phase = 1;             /* 1 = tidPathp, 2 = pathp */
-#define MAX_FID_COUNT 512
     cm_fid_t fids[MAX_FID_COUNT]; /* array of fids processed in this path walk */
     int fid_count = 0;          /* number of fids processed in this path walk */
     int i;
@@ -2350,7 +2350,7 @@ long cm_TryBulkProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
     if (tscp) {
         if (lock_TryWrite(&tscp->rw)) {
             /* we have an entry that we can look at */
-            if (!(tscp->flags & CM_SCACHEFLAG_EACCESS) && cm_HaveCallback(tscp)) {
+            if (!cm_EAccesFindEntry(bsp->userp, &tscp->fid) && cm_HaveCallback(tscp)) {
                 /* we have a callback on it.  Don't bother
                  * fetching this stat entry, since we're happy
                  * with the info we have.
@@ -2374,7 +2374,7 @@ long cm_TryBulkProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
           !(tfid.vnode==0x1 && tfid.unique==0x1) )
     {
         osi_Log0(afsd_logp, "cm_TryBulkProc Freelance calls cm_SCache on root.afs mountpoint");
-        return cm_GetSCache(&tfid, &tscp, NULL, NULL);
+        return cm_GetSCache(&tfid, NULL, &tscp, NULL, NULL);
     }
 #endif /* AFS_FREELANCE_CLIENT */
 
@@ -2516,8 +2516,15 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
             if (inlinebulk && (&bbp->stats[j])->errorCode) {
                 cm_req_t treq = *reqp;
                 cm_Analyze(NULL, userp, &treq, &tfid, 0, &volSync, NULL, &cbReq, (&bbp->stats[j])->errorCode);
+                switch ((&bbp->stats[j])->errorCode) {
+                case EACCES:
+                case UAEACCES:
+                case EPERM:
+                case UAEPERM:
+                    cm_EAccesAddEntry(userp, &tfid, &dscp->fid);
+                }
             } else {
-                code = cm_GetSCache(&tfid, &scp, userp, reqp);
+                code = cm_GetSCache(&tfid, &dscp->fid, &scp, userp, reqp);
                 if (code != 0)
                     continue;
 
@@ -2547,7 +2554,7 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
                 if ((scp->cbServerp == NULL &&
                      !(scp->flags & (CM_SCACHEFLAG_FETCHING | CM_SCACHEFLAG_STORING | CM_SCACHEFLAG_SIZESTORING))) ||
                      (scp->flags & CM_SCACHEFLAG_PURERO) ||
-                     (scp->flags & CM_SCACHEFLAG_EACCESS))
+                     cm_EAccesFindEntry(userp, &scp->fid))
                 {
                     lock_ConvertRToW(&scp->rw);
                     lostRace = cm_EndCallbackGrantingCall(scp, &cbReq,
@@ -2589,6 +2596,7 @@ cm_TryBulkStat(cm_scache_t *dscp, osi_hyper_t *offsetp, cm_user_t *userp,
 
     bbp = malloc(sizeof(cm_bulkStat_t));
     memset(bbp, 0, sizeof(cm_bulkStat_t));
+    bbp->userp = userp;
     bbp->bufOffset = *offsetp;
 
     lock_ReleaseWrite(&dscp->rw);
@@ -2649,6 +2657,73 @@ void cm_StatusFromAttr(AFSStoreStatus *statusp, cm_scache_t *scp, cm_attr_t *att
     statusp->Mask = mask;
 }
 
+int
+cm_IsSpaceAvailable(cm_fid_t * fidp, osi_hyper_t *sizep, cm_user_t *userp, cm_req_t *reqp)
+{
+    int spaceAvail = 1;
+    afs_uint32  code;
+    cm_conn_t *connp;
+    struct rx_connection * rxconnp;
+    AFSFetchVolumeStatus volStat;
+    cm_volume_t *volp = NULL;
+    afs_uint32   volType;
+    char *Name;
+    char *OfflineMsg;
+    char *MOTD;
+    char volName[32]="(unknown)";
+    char offLineMsg[256]="server temporarily inaccessible";
+    char motd[256]="server temporarily inaccessible";
+    osi_hyper_t freespace;
+
+    if (fidp->cell==AFS_FAKE_ROOT_CELL_ID &&
+        fidp->volume==AFS_FAKE_ROOT_VOL_ID)
+    {
+        goto _done;
+    }
+
+    volp = cm_GetVolumeByFID(fidp);
+    if (!volp) {
+        spaceAvail = 0;
+        goto _done;
+    }
+    volType = cm_VolumeType(volp, fidp->volume);
+    if (volType == ROVOL || volType == BACKVOL) {
+        spaceAvail = 0;
+        goto _done;
+    }
+
+    Name = volName;
+    OfflineMsg = offLineMsg;
+    MOTD = motd;
+
+    do {
+        code = cm_ConnFromFID(fidp, userp, reqp, &connp);
+        if (code) continue;
+
+        rxconnp = cm_GetRxConn(connp);
+        code = RXAFS_GetVolumeStatus(rxconnp, fidp->volume,
+                                     &volStat, &Name, &OfflineMsg, &MOTD);
+        rx_PutConnection(rxconnp);
+
+    } while (cm_Analyze(connp, userp, reqp, fidp, 0, NULL, NULL, NULL, code));
+    code = cm_MapRPCError(code, reqp);
+    if (code == 0) {
+        if (volStat.MaxQuota) {
+            freespace.QuadPart = 1024 * (afs_int64)min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
+        } else {
+            freespace.QuadPart = 1024 * (afs_int64)volStat.PartBlocksAvail;
+        }
+        spaceAvail = LargeIntegerGreaterThanOrEqualTo(freespace, *sizep);
+    }
+    /* the rpc failed, assume there is space and we can fail it later. */
+
+  _done:
+    if (volp)
+        cm_PutVolume(volp);
+
+    return spaceAvail;
+}
+
 /* set the file size, and make sure that all relevant buffers have been
  * truncated.  Ensure that any partially truncated buffers have been zeroed
  * to the end of the buffer.
@@ -2730,13 +2805,20 @@ long cm_SetLength(cm_scache_t *scp, osi_hyper_t *sizep, cm_user_t *userp,
     }
     else if (LargeIntegerGreaterThan(*sizep, scp->length)) {
         /* really extending the file */
-        scp->length = *sizep;
-        scp->mask |= CM_SCACHEMASK_LENGTH;
+        /* Check to see if we have sufficient quota */
+        if (cm_IsSpaceAvailable(&scp->fid, sizep, userp, reqp)) {
+            scp->length = *sizep;
+            scp->mask |= CM_SCACHEMASK_LENGTH;
+        } else {
+            code = CM_ERROR_SPACE;
+            goto syncopdone;
+        }
     }
 
     /* done successfully */
     code = 0;
 
+  syncopdone:
     cm_SyncOpDone(scp, NULL,
                   CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS
                   | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_SETSIZE);
@@ -2953,7 +3035,7 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
      * info.
      */
     if (code == 0) {
-        code = cm_GetSCache(&newFid, &scp, userp, reqp);
+        code = cm_GetSCache(&newFid, &dscp->fid, &scp, userp, reqp);
         if (code == 0) {
             lock_ObtainWrite(&scp->rw);
            scp->creator = userp;               /* remember who created it */
@@ -3145,7 +3227,7 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
      * info.
      */
     if (code == 0) {
-        code = cm_GetSCache(&newFid, &scp, userp, reqp);
+        code = cm_GetSCache(&newFid, &dscp->fid, &scp, userp, reqp);
         if (code == 0) {
             lock_ObtainWrite(&scp->rw);
             if (!cm_HaveCallback(scp)) {
@@ -3396,7 +3478,7 @@ long cm_SymLink(cm_scache_t *dscp, clientchar_t *cnamep, fschar_t *contentsp, lo
      * info.
      */
     if (code == 0) {
-        code = cm_GetSCache(&newFid, &scp, userp, reqp);
+        code = cm_GetSCache(&newFid, &dscp->fid, &scp, userp, reqp);
         if (code == 0) {
             lock_ObtainWrite(&scp->rw);
             if (!cm_HaveCallback(scp)) {
@@ -4527,13 +4609,19 @@ long cm_IntSetLock(cm_scache_t * scp, cm_user_t * userp, int lockType,
 
     osi_Log2(afsd_logp, "CALL SetLock scp 0x%p for lock %d", scp, lockType);
 
-       if ((lockType != LOCKING_ANDX_SHARED_LOCK && scp->fsLockCount != 0) ||
-               (lockType == LOCKING_ANDX_SHARED_LOCK && scp->fsLockCount < 0))
-       {
-               code = CM_ERROR_LOCK_NOT_GRANTED;
+#if 0
+    /*
+     * The file server prior to 1.6.2 does not report an accurate value
+     * and callbacks are not issued if the lock is dropped due to expiration.
+     */
+    if ((lockType != LOCKING_ANDX_SHARED_LOCK && scp->fsLockCount != 0) ||
+         (lockType == LOCKING_ANDX_SHARED_LOCK && scp->fsLockCount < 0))
+    {
+        code = CM_ERROR_LOCK_NOT_GRANTED;
         osi_Log2(afsd_logp, "CALL SetLock FAILURE, fsLockCount %d code 0x%x", scp->fsLockCount, code);
-               return code;
-       }
+        return code;
+    }
+#endif
 
     memset(&volSync, 0, sizeof(volSync));