/** * add an entry to the volume group cache. * * @param[in] dp disk partition object * @param[in] parent parent volume id * @param[in] child child volume id * @param[out] newvg if non-NULL, *newvg is 1 if adding this added a * new VG, 0 if we added to an existing VG * * @return operation status * @retval 0 success */ int VVGCache_entry_add(struct DiskPartition64 * dp, VolumeId parent, VolumeId child, afs_int32 *newvg) { int code = 0; VOL_LOCK; VVGCache_entry_add_r(dp, parent, child, newvg); VOL_UNLOCK; return code; }
/** * flush thread-local scan table to the global VG cache. * * @param[in] tbl scan table * @param[in] dp disk partition object * * @pre VOL_LOCK is NOT held * * @return operation status * @retval 0 success * @retval nonzero a VVGCache_entry_add_r operation failed during a * flush of the thread-local table * * @internal */ static int _VVGC_scan_table_flush(VVGCache_scan_table_t * tbl, struct DiskPartition64 * dp) { int code = 0, res, i; afs_int32 newvg = 0; unsigned long newvols, newvgs; newvols = tbl->newvols; newvgs = tbl->newvgs; VOL_LOCK; for (i = 0; i < tbl->idx; i++) { /* * We need to check the 'to-delete' list and prevent adding any entries * that are on it. The volser could potentially create a volume in one * VG, then delete it and put it on another VG. If we are doing a scan * when that happens, tbl->entries could have the entries for trying to * put the vol on both VGs, though at least one of them will also be on * the dlist. If we put everything in tbl->entries on the VGC then try * to delete afterwards, putting one entry on the VGC cause an error, * and we'll fail to add it. So instead, avoid adding any new VGC * entries if it is on the dlist. */ if (_VVGC_dlist_lookup_r(dp, tbl->entries[i].parent, tbl->entries[i].volid)) { continue; } res = VVGCache_entry_add_r(dp, tbl->entries[i].parent, tbl->entries[i].volid, &newvg); if (res) { code = res; } else { newvols++; newvgs += newvg; } } /* flush the to-delete list while we're here. We don't need to preserve * the list across the entire scan, and flushing it each time we flush * a scan table will keep the size of the dlist down */ _VVGC_flush_dlist(dp); VOL_UNLOCK; ViceLog(125, ("VVGC_scan_table_flush: flushed %d entries from " "scan table to global VG cache\n", tbl->idx)); ViceLog(125, ("VVGC_scan_table_flush: %s total: %lu vols, %lu groups\n", VPartitionPath(dp), newvols, newvgs)); res = _VVGC_scan_table_init(tbl); if (res) { code = res; } tbl->newvols = newvols; tbl->newvgs = newvgs; return code; }