From 2bffe725c5ebb785257555286567f128e0911cb7 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 5 Dec 2009 10:53:03 -0500 Subject: [PATCH] Windows: cm_BPlusDirBuildTree can fail It is possible that cm_BPlusDirBuildTree can fail. For example, the server could be marked down after a callback is obtained but before all of the directory data buffers have been fetched. cm_BeginDirOp must check for the failure, destroy the tree, and return the failure code to the caller. Otherwise, a tree with no entries may be created and marked with the current data version. LICENSE MIT Change-Id: I26fbfceaf68389a1906797b12721c49172b027ec Reviewed-on: http://gerrit.openafs.org/893 Reviewed-by: Derrick Brashear Tested-by: Jeffrey Altman Reviewed-by: Jeffrey Altman --- src/WINNT/afsd/cm_dir.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/WINNT/afsd/cm_dir.c b/src/WINNT/afsd/cm_dir.c index c28edef8a..ac55aed30 100644 --- a/src/WINNT/afsd/cm_dir.c +++ b/src/WINNT/afsd/cm_dir.c @@ -1068,24 +1068,31 @@ cm_BeginDirOp(cm_scache_t * scp, cm_user_t * userp, cm_req_t * reqp, lock_ReleaseWrite(&scp->rw); mxheld = 0; } - cm_BPlusDirBuildTree(scp, userp, reqp); + code = cm_BPlusDirBuildTree(scp, userp, reqp); if (!mxheld) { lock_ObtainWrite(&scp->rw); mxheld = 1; } - if (op->dataVersion != scp->dataVersion) { - /* We lost the race, therefore we must update the - * dirop state and retry to build the tree. - */ - op->length = scp->length; - op->newLength = op->length; - op->dataVersion = scp->dataVersion; - op->newDataVersion = op->dataVersion; - goto repeat; + if (code) { + bplus_free_tree++; + freeBtree(scp->dirBplus); + scp->dirBplus = NULL; + scp->dirDataVersion = CM_SCACHE_VERSION_BAD; + } else { + if (op->dataVersion != scp->dataVersion) { + /* We lost the race, therefore we must update the + * dirop state and retry to build the tree. + */ + op->length = scp->length; + op->newLength = op->length; + op->dataVersion = scp->dataVersion; + op->newDataVersion = op->dataVersion; + goto repeat; + } + + if (scp->dirBplus) + scp->dirDataVersion = scp->dataVersion; } - - if (scp->dirBplus) - scp->dirDataVersion = scp->dataVersion; } } -- 2.39.5