DEVEL15-windows-vioc-path-availability-20070414
authorJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 14 Apr 2007 19:49:36 +0000 (19:49 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 14 Apr 2007 19:49:36 +0000 (19:49 +0000)
add a new Windows only pioctl VIOC_PATH_AVAILABILITY that is used
to query the server status for a specified path.  Return values
include:
  online
  offline
  all busy
  all down
  not afs

(cherry picked from commit 5bc88af797eeb8db631e6ad8e9d56d39a687dd96)

src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c

index 23d617a..59de205 100644 (file)
@@ -642,8 +642,8 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
 #endif /* DJGPP */        
 
     if (serversp == NULL) {
-       osi_Log1(afsd_logp, "cm_ConnByMServers returning 0x%x", CM_ERROR_NOSUCHVOLUME);
-       return CM_ERROR_NOSUCHVOLUME;
+       osi_Log1(afsd_logp, "cm_ConnByMServers returning 0x%x", CM_ERROR_ALLDOWN);
+       return CM_ERROR_ALLDOWN;
     }
 
     *connpp = NULL;
index b490993..dca5037 100644 (file)
@@ -2768,3 +2768,96 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
   
     return 0;
 }
+
+
+static long 
+cm_CheckServersStatus(cm_serverRef_t *serversp)
+{
+    long code = 0;
+    cm_serverRef_t *tsrp;
+    cm_server_t *tsp;
+    int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
+
+    if (serversp == NULL) {
+       osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
+       return CM_ERROR_ALLDOWN;
+    }
+
+    lock_ObtainRead(&cm_serverLock);
+    for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
+        if (tsp = tsrp->server) {
+            cm_GetServerNoLock(tsp);
+            lock_ReleaseRead(&cm_serverLock);
+            if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
+                allDown = 0;
+                if (tsrp->status == busy) {
+                    allOffline = 0;
+                    someBusy = 1;
+                } else if (tsrp->status == offline) {
+                    allBusy = 0;
+                    someOffline = 1;
+                } else {
+                    allOffline = 0;
+                    allBusy = 0;
+                    cm_PutServer(tsp);
+                    goto done;
+                }
+            }
+            lock_ObtainRead(&cm_serverLock);
+            cm_PutServerNoLock(tsp);
+        }
+    }   
+    lock_ReleaseRead(&cm_serverLock);
+
+    if (allDown) 
+        code = CM_ERROR_ALLDOWN;
+    else if (allBusy) 
+        code = CM_ERROR_ALLBUSY;
+    else if (allOffline || (someBusy && someOffline))
+        code = CM_ERROR_ALLOFFLINE;
+
+  done:
+    osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", code);
+    return code;
+}
+
+
+long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp)
+{
+    long code;
+    cm_scache_t *scp;
+    cm_cell_t *cellp;
+    cm_volume_t *tvp;
+    cm_serverRef_t **tsrpp;
+    unsigned long volume;
+    cm_req_t req;
+
+    cm_InitReq(&req);
+
+    code = cm_ParseIoctlPath(ioctlp, userp, &req, &scp);
+    if (code) 
+        return code;
+        
+    volume = scp->fid.volume;
+
+    cellp = cm_FindCellByID(scp->fid.cell);
+
+    cm_ReleaseSCache(scp);
+
+    if (!cellp)
+       return CM_ERROR_NOSUCHCELL;
+
+    code = cm_GetVolumeByID(cellp, volume, userp, &req, &tvp);
+    if (code) 
+        return code;
+       
+    lock_ObtainMutex(&tvp->mx);
+    tsrpp = cm_GetVolServers(tvp, volume);
+    code = cm_CheckServersStatus(*tsrpp);
+    cm_FreeServerList(tsrpp);
+    lock_ReleaseMutex(&tvp->mx);
+    cm_PutVolume(tvp);
+    return 0;
+}       
+
+
index 6753cb3..01c7b7d 100644 (file)
@@ -164,6 +164,8 @@ extern long cm_IoctlRxStatPeer(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp);
 
+extern long cm_IoctlPathAvailability(struct smb_ioctl * ioctlp, struct cm_user *userp);
+
 #endif /* __CM_IOCTL_INTERFACES_ONLY__ */
 
 #endif /*  __CM_IOCTL_H_ENV__ */
index 5b86724..3286dfd 100644 (file)
@@ -600,7 +600,7 @@ ParseAcl (char *astr)
 static int
 PrintStatus(VolumeStatus *status, char *name, char *motd, char *offmsg)
 {
-    printf("Volume status for vid = %u named %s\n",status->Vid, name);
+    printf("Volume status for vid = %u named %s is\n",status->Vid, name);
     if (*offmsg != 0)
        printf("Current offline message is %s\n",offmsg);
     if (*motd != 0)
@@ -611,7 +611,7 @@ PrintStatus(VolumeStatus *status, char *name, char *motd, char *offmsg)
     else 
         printf("unlimited\n");
     printf("Current blocks used are %d\n",status->BlocksInUse);
-    printf("The partition has %d blocks available out of %d\n\n",
+    printf("The partition has %d blocks available out of %d\n",
             status->PartBlocksAvail, status->PartMaxBlocks);
     return 0;
 }
@@ -1489,6 +1489,7 @@ ExamineCmd(struct cmd_syndesc *as, char *arock)
     struct cmd_item *ti;
     struct VolumeStatus *status;
     char *name, *offmsg, *motd;
+    long   online_state;
     int error = 0;
     
     SetDotDefault(&as->parms[0].items);
@@ -1525,21 +1526,38 @@ ExamineCmd(struct cmd_syndesc *as, char *arock)
            pr_SIdToName(owner[0], oname);
            printf("Owner %s (%u) Group %u\n", oname, owner[0], owner[1]);
         }
-       
+
        blob.out = space;
        blob.out_size = MAXSIZE;
        code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1);
-       if (code) {
-           Die(errno, ti->data);
-           error = 1;
-           continue;
-       }
-       status = (VolumeStatus *)space;
-       name = (char *)status + sizeof(*status);
-       offmsg = name + strlen(name) + 1;
-       motd = offmsg + strlen(offmsg) + 1;
+       if (code == 0) {
+            status = (VolumeStatus *)space;
+            name = (char *)status + sizeof(*status);
+            offmsg = name + strlen(name) + 1;
+            motd = offmsg + strlen(offmsg) + 1;
 
-       PrintStatus(status, name, motd, offmsg);
+            PrintStatus(status, name, motd, offmsg);
+        } else {
+            Die(errno, ti->data);
+        }
+        online_state = pioctl(ti->data, VIOC_PATH_AVAILABILITY, &blob, 1);
+        switch (online_state) {
+        case 0:
+            printf("Volume is online\n");
+            break;
+        case CM_ERROR_ALLOFFLINE:
+            printf("Volume offline\n");
+            break;
+        case CM_ERROR_ALLDOWN:
+            printf("All Volume servers are down\n");
+            break;
+        case CM_ERROR_ALLBUSY:
+            printf("All volume servers are busy\n");
+            break;
+        default:
+            Die(online_state, ti->data);
+        }
+        printf("\n");
     }
     return error;
 }
index a1a6650..8676029 100644 (file)
@@ -97,4 +97,5 @@ typedef struct cm_cacheParms {
 #define VIOC_RXSTAT_PROC                0x2e
 #define VIOC_RXSTAT_PEER                0x2f
 #define VIOC_UUIDCTL                    0x30
+#define VIOC_PATH_AVAILABILITY          0x31
 #endif /*  __SMB_IOCONS_H_ENV_ */
index 7f30883..54896f3 100644 (file)
@@ -84,6 +84,7 @@ void smb_InitIoctl(void)
         smb_ioctlProcsp[VIOC_RXSTAT_PROC] = cm_IoctlRxStatProcess;
         smb_ioctlProcsp[VIOC_RXSTAT_PEER] = cm_IoctlRxStatPeer;
         smb_ioctlProcsp[VIOC_UUIDCTL] = cm_IoctlUUIDControl;
+        smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = cm_IoctlPathAvailability;
 }
 
 /* called to make a fid structure into an IOCTL fid structure */