From ea9e5e8519dc486cfb019447ee5d695de104079d Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Thu, 18 Jul 2019 16:21:10 -0500 Subject: [PATCH] afs: Handle osi_NewVnode failures Currently, code inside afs_vcache.c assumes that osi_NewVnode always returns non-NULL, which means that osi_NewVnode must panic if it cannot create a new vnode. All of the callers of afs_GetVCache, afs_NewVCache, etc, already handle getting a NULL return, though (after all, the given fid may not exist or be inaccessible due to network errors, etc). So, just propagate NULL returns from osi_NewVnode up to our callers, to avoid panics in these situations. Modify osi_NewVnode on many arches to return an error on allocation failure, instead of panic'ing. Change-Id: Ib578b1747590bdf65327d4674e0849811ed999eb Reviewed-on: https://gerrit.openafs.org/13701 Reviewed-by: Benjamin Kaduk Reviewed-by: Yadavendra Yadav Tested-by: BuildBot --- src/afs/AIX/osi_vcache.c | 4 +++- src/afs/DARWIN/osi_vcache.c | 4 +++- src/afs/FBSD/osi_vcache.c | 3 +++ src/afs/IRIX/osi_vcache.c | 3 +++ src/afs/LINUX/osi_vcache.c | 9 +++++++-- src/afs/NBSD/osi_vcache.c | 3 +++ src/afs/OBSD/osi_vcache.c | 3 +++ src/afs/SOLARIS/osi_vcache.c | 4 +++- src/afs/afs_vcache.c | 9 +++++++++ 9 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/afs/AIX/osi_vcache.c b/src/afs/AIX/osi_vcache.c index eec57c9..351afbb 100644 --- a/src/afs/AIX/osi_vcache.c +++ b/src/afs/AIX/osi_vcache.c @@ -34,7 +34,9 @@ osi_NewVnode(void) struct vcache *tvc; tvc = afs_osi_Alloc(sizeof(struct vcache)); - osi_Assert(tvc != NULL); + if (tvc == NULL) { + return NULL; + } #ifdef KERNEL_HAVE_PIN pin((char *)tvc, sizeof(struct vcache)); /* XXX */ diff --git a/src/afs/DARWIN/osi_vcache.c b/src/afs/DARWIN/osi_vcache.c index 1d79224..26493e6 100644 --- a/src/afs/DARWIN/osi_vcache.c +++ b/src/afs/DARWIN/osi_vcache.c @@ -19,7 +19,9 @@ osi_NewVnode(void) struct vcache *tvc; tvc = afs_osi_Alloc(sizeof(struct vcache)); - osi_Assert(tvc != NULL); + if (tvc == NULL) { + return NULL; + } tvc->v = NULL; /* important to clean this, or use memset 0 */ return tvc; diff --git a/src/afs/FBSD/osi_vcache.c b/src/afs/FBSD/osi_vcache.c index 922d8c1..22ca8d4 100644 --- a/src/afs/FBSD/osi_vcache.c +++ b/src/afs/FBSD/osi_vcache.c @@ -70,6 +70,9 @@ osi_NewVnode(void) struct vcache *tvc; tvc = afs_osi_Alloc(sizeof(struct vcache)); + if (tvc == NULL) { + return NULL; + } tvc->v = NULL; /* important to clean this, or use memset 0 */ return tvc; diff --git a/src/afs/IRIX/osi_vcache.c b/src/afs/IRIX/osi_vcache.c index 522e8b5..5d1cea2 100644 --- a/src/afs/IRIX/osi_vcache.c +++ b/src/afs/IRIX/osi_vcache.c @@ -36,6 +36,9 @@ osi_NewVnode(void) char name[METER_NAMSZ]; avc = afs_osi_Alloc(sizeof(struct vcache)); + if (avc == NULL) { + return NULL; + } memset(avc, 0, sizeof(struct vcache)); avc->v.v_number = ++afsvnumbers; diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index e3be81a..0d810b1 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -146,13 +146,18 @@ osi_NewVnode(void) AFS_GUNLOCK(); ip = new_inode(afs_globalVFS); - if (!ip) - osi_Panic("afs_NewVCache: no more inodes"); AFS_GLOCK(); + if (ip == NULL) { + return NULL; + } #if defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE) tvc = VTOAFS(ip); #else tvc = afs_osi_Alloc(sizeof(struct vcache)); + if (tvc == NULL) { + iput(ip); + return NULL; + } ip->u.generic_ip = tvc; tvc->v = ip; #endif diff --git a/src/afs/NBSD/osi_vcache.c b/src/afs/NBSD/osi_vcache.c index 2f99075..5be3e1d 100644 --- a/src/afs/NBSD/osi_vcache.c +++ b/src/afs/NBSD/osi_vcache.c @@ -43,6 +43,9 @@ osi_NewVnode(void) struct vcache *tvc; tvc = afs_osi_Alloc(sizeof(struct vcache)); + if (tvc == NULL) { + return NULL; + } tvc->v = NULL; /* important to clean this, or use memset 0 */ return tvc; diff --git a/src/afs/OBSD/osi_vcache.c b/src/afs/OBSD/osi_vcache.c index 2798a5f..07416b1 100644 --- a/src/afs/OBSD/osi_vcache.c +++ b/src/afs/OBSD/osi_vcache.c @@ -40,6 +40,9 @@ osi_NewVnode(void) struct vcache *tvc; tvc = afs_osi_Alloc(sizeof(struct vcache)); + if (tvc == NULL) { + return NULL; + } tvc->v = NULL; /* important to clean this, or use memset 0 */ return tvc; diff --git a/src/afs/SOLARIS/osi_vcache.c b/src/afs/SOLARIS/osi_vcache.c index 7f0b9f6..e3cb9a4 100644 --- a/src/afs/SOLARIS/osi_vcache.c +++ b/src/afs/SOLARIS/osi_vcache.c @@ -33,7 +33,9 @@ osi_NewVnode(void) struct vcache *avc; avc = afs_osi_Alloc(sizeof(struct vcache)); - osi_Assert(avc != NULL); + if (avc == NULL) { + return NULL; + } return avc; } diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 407e5a6..465aa98 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -917,6 +917,9 @@ afs_AllocVCache(void) struct vcache *tvc; tvc = osi_NewVnode(); + if (tvc == NULL) { + return NULL; + } afs_vcount++; @@ -1050,6 +1053,9 @@ afs_NewVCache_int(struct VenusFid *afid, struct server *serverp, int seq) } } tvc = afs_AllocVCache(); + if (tvc == NULL) { + return NULL; + } #else /* AFS_LINUX22_ENV */ /* pull out a free cache entry */ if (!freeVCList) { @@ -1058,6 +1064,9 @@ afs_NewVCache_int(struct VenusFid *afid, struct server *serverp, int seq) if (!freeVCList) { tvc = afs_AllocVCache(); + if (tvc == NULL) { + return NULL; + } } else { tvc = freeVCList; /* take from free list */ freeVCList = tvc->nextfree; -- 1.9.4