From: Marc Dionne Date: Sat, 21 Jan 2012 19:42:01 +0000 (-0500) Subject: vol: Allow VAllocVnode of specific vnodes X-Git-Tag: upstream/1.8.0_pre1^2~2551 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=74e5f32aaca5313f153f13c7ce9442527b758a0a;p=packages%2Fo%2Fopenafs.git vol: Allow VAllocVnode of specific vnodes Add parameters to VAllocVnode to allow the caller to specifiy the vnode and unique numbers to use. This will be used by the RW replication code to keep vnode numbers in sync between the master volume and the replicas. Adapted from code by Vishal Powar and Derrick Brashear. Change-Id: Ibaf79aad2b3e7a52802f5e01f7e4c7730c3f5090 Reviewed-on: http://gerrit.openafs.org/6672 Reviewed-by: Derrick Brashear Tested-by: BuildBot --- diff --git a/src/viced/afsfileprocs.c b/src/viced/afsfileprocs.c index c2658ff9e..43039f445 100644 --- a/src/viced/afsfileprocs.c +++ b/src/viced/afsfileprocs.c @@ -1806,7 +1806,7 @@ Alloc_NewVnode(Vnode * parentptr, DirHandle * dir, Volume * volptr, return VSALVAGE; } - *targetptr = VAllocVnode(&errorCode, volptr, FileType); + *targetptr = VAllocVnode(&errorCode, volptr, FileType, 0, 0); if (errorCode != 0) { VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0); return (errorCode); diff --git a/src/vol/vnode.c b/src/vol/vnode.c index 37b697f45..39e797835 100644 --- a/src/vol/vnode.c +++ b/src/vol/vnode.c @@ -556,11 +556,11 @@ VLookupVnode(Volume * vp, VnodeId vnodeId) Vnode * -VAllocVnode(Error * ec, Volume * vp, VnodeType type) +VAllocVnode(Error * ec, Volume * vp, VnodeType type, VnodeId in_vnode, Unique in_unique) { Vnode *retVal; VOL_LOCK; - retVal = VAllocVnode_r(ec, vp, type); + retVal = VAllocVnode_r(ec, vp, type, in_vnode, in_unique); VOL_UNLOCK; return retVal; } @@ -571,6 +571,8 @@ VAllocVnode(Error * ec, Volume * vp, VnodeType type) * @param[out] ec error code return * @param[in] vp volume object pointer * @param[in] type desired vnode type + * @param[in] type desired vnode ID (optional) + * @param[in] type desired vnode Unique (optional) * * @return vnode object pointer * @@ -580,7 +582,7 @@ VAllocVnode(Error * ec, Volume * vp, VnodeType type) * @post vnode allocated and returned */ Vnode * -VAllocVnode_r(Error * ec, Volume * vp, VnodeType type) +VAllocVnode_r(Error * ec, Volume * vp, VnodeType type, VnodeId in_vnode, Unique in_unique) { Vnode *vnp; VnodeId vnodeNumber; @@ -588,6 +590,9 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type) struct VnodeClassInfo *vcp; VnodeClass class; Unique unique; + struct vnodeIndex *index; + unsigned int offset; + #ifdef AFS_DEMAND_ATTACH_FS VolState vol_state_save; #endif @@ -624,10 +629,6 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type) return NULL; } - unique = vp->nextVnodeUnique++; - if (!unique) - unique = vp->nextVnodeUnique++; - if (vp->nextVnodeUnique > V_uniquifier(vp)) { VUpdateVolume_r(ec, vp, 0); if (*ec) @@ -640,12 +641,63 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type) return NULL; } - /* Find a slot in the bit map */ - bitNumber = VAllocBitmapEntry_r(ec, vp, &vp->vnodeIndex[class], - VOL_ALLOC_BITMAP_WAIT); - if (*ec) - return NULL; - vnodeNumber = bitNumberToVnodeNumber(bitNumber, class); + /* + * If in_vnode and in_unique are specified, we are asked to + * allocate a specifc vnode slot. Used by RW replication to + * keep vnode IDs consistent with the master. + */ + + if (!in_vnode) { + unique = vp->nextVnodeUnique++; + if (!unique) + unique = vp->nextVnodeUnique++; + + if (vp->nextVnodeUnique > V_uniquifier(vp)) { + VUpdateVolume_r(ec, vp, 0); + if (*ec) + return NULL; + } + + /* Find a slot in the bit map */ + bitNumber = VAllocBitmapEntry_r(ec, vp, &vp->vnodeIndex[class], + VOL_ALLOC_BITMAP_WAIT); + + if (*ec) + return NULL; + vnodeNumber = bitNumberToVnodeNumber(bitNumber, class); + } else { + index = &vp->vnodeIndex[class]; + if (!in_unique) { + *ec = VNOVNODE; + return NULL; + } + /* Catch us up to where the master is */ + if (in_unique > vp->nextVnodeUnique) + vp->nextVnodeUnique = in_unique+1; + + if (vp->nextVnodeUnique > V_uniquifier(vp)) { + VUpdateVolume_r(ec, vp, 0); + if (*ec) + return NULL; + } + + unique = in_unique; + bitNumber = vnodeIdToBitNumber(in_vnode); + offset = bitNumber >> 3; + + /* Mark vnode in use. Grow bitmap if needed. */ + if ((offset >= index->bitmapSize) + || ((*(index->bitmap + offset) & (1 << (bitNumber & 0x7))) == 0)) + VGrowBitmap(index); + /* Should not happen */ + if (*(index->bitmap + offset) & (1 << (bitNumber & 0x7))) { + *ec = VNOVNODE; + return NULL; + } + + *(index->bitmap + offset) |= (1 << (bitNumber & 0x7)); + vnodeNumber = in_vnode; + } /* * DAFS: diff --git a/src/vol/vnode.h b/src/vol/vnode.h index a374258c3..d0f2c1dd8 100644 --- a/src/vol/vnode.h +++ b/src/vol/vnode.h @@ -271,8 +271,11 @@ extern void VPutVnode(Error * ec, Vnode * vnp); extern void VPutVnode_r(Error * ec, Vnode * vnp); extern int VVnodeWriteToRead(Error * ec, Vnode * vnp); extern int VVnodeWriteToRead_r(Error * ec, Vnode * vnp); -extern Vnode *VAllocVnode(Error * ec, struct Volume *vp, VnodeType type); -extern Vnode *VAllocVnode_r(Error * ec, struct Volume *vp, VnodeType type); +extern Vnode *VAllocVnode(Error * ec, struct Volume *vp, VnodeType type, + VnodeId in_vnode, Unique in_unique); +extern Vnode *VAllocVnode_r(Error * ec, struct Volume *vp, VnodeType type, + VnodeId in_vnode, Unique in_unique); + /*extern VFreeVnode();*/ extern Vnode *VGetFreeVnode_r(struct VnodeClassInfo *vcp, struct Volume *vp, VnodeId vnodeNumber); diff --git a/src/vol/volume.c b/src/vol/volume.c index d84609245..4dd86589c 100644 --- a/src/vol/volume.c +++ b/src/vol/volume.c @@ -180,9 +180,6 @@ pthread_t vol_glock_holder = 0; #endif -#define VOLUME_BITMAP_GROWSIZE 16 /* bytes, => 128vnodes */ - /* Must be a multiple of 4 (1 word) !! */ - /* this parameter needs to be tunable at runtime. * 128 was really inadequate for largish servers -- at 16384 volumes this * puts average chain length at 128, thus an average 65 deref's to find a volptr. @@ -6201,6 +6198,25 @@ VChildProcReconnectFS(void) /* volume bitmap routines */ /***************************************************/ +/* + * Grow the bitmap by the defined increment + */ +void +VGrowBitmap(struct vnodeIndex *index) +{ + byte *bp; + + bp = realloc(index->bitmap, index->bitmapSize + VOLUME_BITMAP_GROWSIZE); + osi_Assert(bp != NULL); + index->bitmap = bp; + bp += index->bitmapSize; + memset(bp, 0, VOLUME_BITMAP_GROWSIZE); + index->bitmapOffset = index->bitmapSize; + index->bitmapSize += VOLUME_BITMAP_GROWSIZE; + + return; +} + /** * allocate a vnode bitmap number for the vnode * @@ -6322,14 +6338,8 @@ VAllocBitmapEntry_r(Error * ec, Volume * vp, bp += sizeof(bit32) /* i.e. 4 */ ; } /* No bit map entry--must grow bitmap */ - bp = (byte *) - realloc(index->bitmap, index->bitmapSize + VOLUME_BITMAP_GROWSIZE); - osi_Assert(bp != NULL); - index->bitmap = bp; - bp += index->bitmapSize; - memset(bp, 0, VOLUME_BITMAP_GROWSIZE); - index->bitmapOffset = index->bitmapSize; - index->bitmapSize += VOLUME_BITMAP_GROWSIZE; + VGrowBitmap(index); + bp = index->bitmap; *bp = 1; ret = index->bitmapOffset * 8; #ifdef AFS_DEMAND_ATTACH_FS diff --git a/src/vol/volume.h b/src/vol/volume.h index f9b647300..f5f24e51c 100644 --- a/src/vol/volume.h +++ b/src/vol/volume.h @@ -807,6 +807,7 @@ extern Volume *VCreateVolume(Error * ec, char *partname, VolId volumeId, VolId parentId); extern Volume *VCreateVolume_r(Error * ec, char *partname, VolId volumeId, VolId parentId); +extern void VGrowBitmap(struct vnodeIndex *index); extern int VAllocBitmapEntry(Error * ec, Volume * vp, struct vnodeIndex *index); extern int VAllocBitmapEntry_r(Error * ec, Volume * vp, @@ -1021,6 +1022,8 @@ extern int VWalkVolumeHeaders(struct DiskPartition64 *dp, const char *partpath, #define VOL_SALVAGE_NO_OFFLINE 0x1 /* we do not need to wait to offline the volume; it has * not been fully attached */ +#define VOLUME_BITMAP_GROWSIZE 16 /* bytes, => 128vnodes */ + /* Must be a multiple of 4 (1 word) !! */ #if defined(NEARINODE_HINT) #define V_pref(vp,nearInode) nearInodeHash(V_id(vp),(nearInode)); (nearInode) %= V_partition(vp)->f_files