From e42a066da153750077b154e27249b5b4862724db Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 26 Jan 2009 15:50:46 +0000 Subject: [PATCH] windows-btree-dir-enum-20090126 LICENSE MIT Modify the cm_BPlusDirEnum interface: * add the cm_scache_t * of the directory being enumerated to the cm_direnum_t object * remove the cm_scache_t * from the cm_BPlusDirEnumBulkStat call now that it is part of the cm_direnum_t object * maintain a reference to the cm_scache_t for the life of the cm_direnum_t object. This ensures that the object cannot be recycled while the enumeration is in use. --- src/WINNT/afsd/cm_btree.c | 19 +++++++++++++++++-- src/WINNT/afsd/cm_btree.h | 5 +++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/WINNT/afsd/cm_btree.c b/src/WINNT/afsd/cm_btree.c index 88bd06e81..ec5c853b2 100644 --- a/src/WINNT/afsd/cm_btree.c +++ b/src/WINNT/afsd/cm_btree.c @@ -2186,6 +2186,12 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, afs_uint32 locked, if (!locked) lock_ObtainRead(&scp->dirlock); + /* + * Hold a reference to the directory so that it wont' be + * recycled while the enumeration is active. + */ + cm_HoldSCache(scp); + if (scp->dirBplus == NULL) { osi_Log0(afsd_logp, "cm_BPlusDirEnumerate No BPlus Tree"); rc = CM_ERROR_WOULDBLOCK; @@ -2285,6 +2291,8 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, afs_uint32 locked, nextLeafNode = getnextnode(leafNode); } + enump->dscp = scp; + done: if (!locked) lock_ReleaseRead(&scp->dirlock); @@ -2292,7 +2300,10 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, afs_uint32 locked, /* if we failed, cleanup any mess */ if (rc != 0) { osi_Log0(afsd_logp, "cm_BPlusDirEnumerate rc != 0"); - if (enump) { + + /* release the directory because we failed to generate an enumeration object */ + cm_ReleaseSCache(scp); + if (enump) { for ( count = 0; count < enump->count && enump->entry[count].name; count++ ) { free(enump->entry[count].name); } @@ -2307,8 +2318,9 @@ cm_BPlusDirEnumerate(cm_scache_t *scp, afs_uint32 locked, } long -cm_BPlusDirEnumBulkStat(cm_scache_t *dscp, cm_direnum_t *enump, cm_user_t *userp, cm_req_t *reqp) +cm_BPlusDirEnumBulkStat(cm_direnum_t *enump, cm_user_t *userp, cm_req_t *reqp) { + cm_scache_t *dscp = enump->dscp; cm_bulkStat_t *bsp; afs_uint32 count; afs_uint32 code; @@ -2387,6 +2399,9 @@ cm_BPlusDirFreeEnumeration(cm_direnum_t *enump) osi_Log0(afsd_logp, "cm_BPlusDirFreeEnumeration"); if (enump) { + /* Release the directory object */ + cm_ReleaseSCache(enump->dscp); + for ( count = 0; count < enump->count && enump->entry[count].name; count++ ) { free(enump->entry[count].name); } diff --git a/src/WINNT/afsd/cm_btree.h b/src/WINNT/afsd/cm_btree.h index 161e8763d..5989dfd81 100644 --- a/src/WINNT/afsd/cm_btree.h +++ b/src/WINNT/afsd/cm_btree.h @@ -159,16 +159,17 @@ typedef struct cm_direnum_entry { } cm_direnum_entry_t; typedef struct cm_direnum { + cm_scache_t *dscp; afs_uint32 count; afs_uint32 next; cm_direnum_entry_t entry[1]; } cm_direnum_t; -long cm_BPlusDirEnumerate(cm_scache_t *scp, afs_uint32 locked, clientchar_t *maskp, cm_direnum_t **enumpp); +long cm_BPlusDirEnumerate(cm_scache_t *dscp, afs_uint32 locked, clientchar_t *maskp, cm_direnum_t **enumpp); long cm_BPlusDirNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entrypp); long cm_BPlusDirFreeEnumeration(cm_direnum_t *enump); long cm_BPlusDirEnumTest(cm_scache_t * dscp, afs_uint32 locked); -long cm_BPlusDirEnumBulkStat(cm_scache_t *dscp, cm_direnum_t *enump, cm_user_t *userp, cm_req_t *reqp); +long cm_BPlusDirEnumBulkStat(cm_direnum_t *enump, cm_user_t *userp, cm_req_t *reqp); long cm_InitBPlusDir(void); -- 2.39.5