diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 23d617a787..59de20591e 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -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; diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index b4909930df..dca5037dc2 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -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; +} + + diff --git a/src/WINNT/afsd/cm_ioctl.h b/src/WINNT/afsd/cm_ioctl.h index 6753cb334e..01c7b7de2a 100644 --- a/src/WINNT/afsd/cm_ioctl.h +++ b/src/WINNT/afsd/cm_ioctl.h @@ -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__ */ diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index 5b867244cf..3286dfd988 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -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; } diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index a1a66509e3..8676029a9c 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -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_ */ diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 7f30883568..54896f35dc 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -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 */