From 5bc88af797eeb8db631e6ad8e9d56d39a687dd96 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 14 Apr 2007 19:46:22 +0000 Subject: [PATCH] windows-vioc-path-availability-20070414 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 --- src/WINNT/afsd/cm_conn.c | 4 +- src/WINNT/afsd/cm_ioctl.c | 93 +++++++++++++++++++++++++++++++++++++ src/WINNT/afsd/cm_ioctl.h | 2 + src/WINNT/afsd/fs.c | 44 ++++++++++++------ src/WINNT/afsd/smb_iocons.h | 1 + src/WINNT/afsd/smb_ioctl.c | 1 + 6 files changed, 130 insertions(+), 15 deletions(-) diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index d86862f79..986e672b2 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -610,8 +610,8 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp, long timeUsed, timeLeft, hardTimeLeft; 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 00dd5f3c4..4d314e4ab 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -2718,3 +2718,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 6753cb334..01c7b7de2 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 5b867244c..3286dfd98 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 a1a66509e..8676029a9 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 aa44d8f7b..24bfda60e 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -79,6 +79,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 */ -- 2.39.5