From 80f05473428969ff71d1791cda8cb09d30223724 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Wed, 21 Apr 2010 12:41:21 -0500 Subject: [PATCH] Recover from afs_GetVolSlot errors afs_GetVolSlot can panic in a few different ways, such as failing to read from or write to VolumeInfo. Instead of panic'ing, return an error to the application. Adjust callers to deal with getting a NULL volume returned. Based on a patch by Mike Meffie. Change-Id: Ibb301fed795ee9ee5906b8e7973945a06218b8f1 Reviewed-on: http://gerrit.openafs.org/1801 Tested-by: Andrew Deason Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/afs/afs_volume.c | 75 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/src/afs/afs_volume.c b/src/afs/afs_volume.c index 07c10a728..cdfe174fa 100644 --- a/src/afs/afs_volume.c +++ b/src/afs/afs_volume.c @@ -113,11 +113,13 @@ afs_int32 afs_FVIndex = -1; struct volume * afs_UFSGetVolSlot(void) { - register struct volume *tv, **lv; + register struct volume *tv = NULL, **lv; struct osi_file *tfile; - register afs_int32 i, code; + register afs_int32 i = -1, code; afs_int32 bestTime; - struct volume *bestVp, **bestLp; + struct volume *bestVp, *oldLp = NULL, **bestLp = NULL; + char *oldname = NULL; + afs_int32 oldvtix; AFS_STATCNT(afs_UFSGetVolSlot); if (!afs_freeVolList) { @@ -137,13 +139,19 @@ afs_UFSGetVolSlot(void) } } } - if (!bestVp) - osi_Panic("getvolslot none"); + if (!bestVp) { + afs_warn("afs_UFSGetVolSlot: no vol slots available\n"); + goto error; + } tv = bestVp; + + oldLp = *bestLp; *bestLp = tv->next; - if (tv->name) - afs_osi_Free(tv->name, strlen(tv->name) + 1); + + oldname = tv->name; tv->name = NULL; + + oldvtix = tv->vtix; /* now write out volume structure to file */ if (tv->vtix < 0) { tv->vtix = afs_volCounter++; @@ -161,9 +169,12 @@ afs_UFSGetVolSlot(void) code = afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix, &staticFVolume, sizeof(struct fvolume)); - if (code != sizeof(struct fvolume)) - osi_Panic("read volumeinfo"); osi_UFSClose(tfile); + if (code != sizeof(struct fvolume)) { + afs_warn("afs_UFSGetVolSlot: error %d reading volumeinfo\n", + (int)code); + goto error; + } afs_FVIndex = tv->vtix; } } @@ -178,15 +189,41 @@ afs_UFSGetVolSlot(void) code = afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex, &staticFVolume, sizeof(struct fvolume)); - if (code != sizeof(struct fvolume)) - osi_Panic("write volumeinfo"); osi_UFSClose(tfile); + if (code != sizeof(struct fvolume)) { + afs_warn("afs_UFSGetVolSlot: error %d writing volumeinfo\n", + (int)code); + goto error; + } + if (oldname) { + afs_osi_Free(oldname, strlen(oldname) + 1); + oldname = NULL; + } } else { tv = afs_freeVolList; afs_freeVolList = tv->next; } return tv; + error: + if (tv) { + if (oldname) { + tv->name = oldname; + oldname = NULL; + } + if (oldvtix < 0) { + afs_volCounter--; + fvTable[i] = staticFVolume.next; + } + if (bestLp) { + *bestLp = oldLp; + } + tv->vtix = oldvtix; + /* we messed with staticFVolume, so make sure someone else + * doesn't think it's fine to use */ + afs_FVIndex = -1; + } + return NULL; } /*afs_UFSGetVolSlot */ @@ -534,6 +571,10 @@ afs_SetupVolume(afs_int32 volid, char *aname, void *ve, struct cell *tcell, struct fvolume *tf = 0; tv = afs_GetVolSlot(); + if (!tv) { + ReleaseWriteLock(&afs_xvolume); + return NULL; + } memset(tv, 0, sizeof(struct volume)); tv->cell = tcell->cellNum; AFS_RWLOCK_INIT(&tv->lock, "volume lock"); @@ -799,22 +840,26 @@ afs_NewVolumeByName(char *aname, afs_int32 acell, int agood, else ve = (char *)tve; tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, areq); - if ((agood == 3) && tv->backVol) { + if ((agood == 3) && tv && tv->backVol) { /* * This means that very soon we'll ask for the BK volume so * we'll prefetch it (well we did already.) */ tv1 = afs_SetupVolume(tv->backVol, (char *)0, ve, tcell, 0, type, areq); - tv1->refCount--; + if (tv1) { + tv1->refCount--; + } } - if ((agood >= 2) && tv->roVol) { + if ((agood >= 2) && tv && tv->roVol) { /* * This means that very soon we'll ask for the RO volume so * we'll prefetch it (well we did already.) */ tv1 = afs_SetupVolume(tv->roVol, NULL, ve, tcell, 0, type, areq); - tv1->refCount--; + if (tv1) { + tv1->refCount--; + } } osi_FreeLargeSpace(tbuffer); afs_PutCell(tcell, READ_LOCK); -- 2.39.5