static void BalloonPageFree(Balloon *b, // IN/OUT int isLargePage) // IN { BalloonChunkList *chunkList = &b->pages[isLargePage]; BalloonChunk *chunk; PageHandle page; ASSERT(DblLnkLst_IsLinked(&chunkList->chunks)); chunk = DblLnkLst_Container(chunkList->chunks.next, BalloonChunk, node); /* deallocate last page */ page = chunk->entries[--chunk->nEntries]; /* deallocate page */ OS_ReservedPageFree(page, isLargePage); STATS_INC(b->stats.primFree[isLargePage]); /* update balloon size */ b->nPages--; /* reclaim chunk, if empty */ BalloonChunkDestroyEmpty(b, chunk, isLargePage); }
static Bool HgfsServerPolicyEnumSharesGet(void *data, // IN: Callback data char const **name, // OUT: Share name size_t *len, // OUT: Name length Bool *done) // OUT: Completion status { GetSharesState *that; HgfsSharedFolder *share; that = (GetSharesState *)data; ASSERT(that); ASSERT(name); ASSERT(len); ASSERT(done); if (that->next == &myState.shares) { /* No more shares */ *done = TRUE; return TRUE; } share = DblLnkLst_Container(that->next, HgfsSharedFolder, links); ASSERT(share); that->next = share->links.next; *name = share->name; *len = share->nameLen; LOG(4, ("HgfsServerPolicyEnumSharesGet: Share name is \"%s\"\n", *name)); *done = FALSE; return TRUE; }
static BalloonChunk * BalloonGetChunk(Balloon *b, // IN/OUT int isLargePage) // IN { BalloonChunk *chunk; BalloonChunkList *chunkList = &b->pages[isLargePage]; /* Get first chunk from the list */ if (DblLnkLst_IsLinked(&chunkList->chunks)) { chunk = DblLnkLst_Container(chunkList->chunks.next, BalloonChunk, node); if (chunk->nEntries < BALLOON_CHUNK_ENTRIES) { /* This chunk has free slots, use it */ return chunk; } } /* create new chunk */ chunk = BalloonChunk_Create(); if (chunk != NULL) { DblLnkLst_LinkFirst(&chunkList->chunks, &chunk->node); /* update stats */ chunkList->nChunks++; } return chunk; }
/* Dump a circular list */ void dump_circular(const member *c) // IN { const member *current; printf("forward: "); current = c; do { printf("%d ", current->i); current = DblLnkLst_Container(current->l.next, member, l); } while (current != c); printf("backward: "); do { printf("%d ", current->i); current = DblLnkLst_Container(current->l.prev, member, l); } while (current != c); printf("\n"); }
/* Dump an anchored list */ void dump_anchored(const DblLnkLst_Links *h) // IN { DblLnkLst_Links *cur_l; printf("forward: "); for (cur_l = h->next; cur_l != h; cur_l = cur_l->next) { member *current; current = DblLnkLst_Container(cur_l, member, l); printf("%d ", current->i); } printf("backward: "); for (cur_l = h->prev; cur_l != h; cur_l = cur_l->prev) { member *current; current = DblLnkLst_Container(cur_l, member, l); printf("%d ", current->i); } printf("\n"); }
static void HgfsServerPolicyDestroyShares(DblLnkLst_Links *head) // IN { ASSERT(head); while (head->next != head) { HgfsSharedFolder *share; share = DblLnkLst_Container(head->next, HgfsSharedFolder, links); ASSERT(share); DblLnkLst_Unlink1(&share->links); HgfsServerPolicyDestroyShare(share); } }
void HgfsDebugPrintReqList(DblLnkLst_Links *listAnchor) // IN: Anchor of list to print { DblLnkLst_Links *currNode; HgfsReq *currReq; ASSERT(listAnchor); DEBUG(VM_DEBUG_STRUCT, "Request List:\n"); DEBUG(VM_DEBUG_STRUCT, " anchor: %p\n", listAnchor); for (currNode = listAnchor->next; currNode != listAnchor; currNode = currNode->next) { currReq = DblLnkLst_Container(currNode, HgfsReq, listNode); DEBUG(VM_DEBUG_STRUCT, " address: %p (id=%d)\n", currReq, currReq->id); } DEBUG(VM_DEBUG_STRUCT, "--DONE--\n"); }
static HgfsSharedFolder * HgfsServerPolicyGetShare(HgfsServerPolicyState *state, // IN char const *nameIn, // IN: Name to check size_t nameInLen) // IN: Length of nameIn { DblLnkLst_Links *l; ASSERT(state); ASSERT(nameIn); /* * First try to find a share that matches the given name exactly. * This is to handle the case where 2 share names differ in case only. */ for (l = state->shares.next; l != &state->shares; l = l->next) { HgfsSharedFolder *share; share = DblLnkLst_Container(l, HgfsSharedFolder, links); ASSERT(share); if (nameInLen == share->nameLen && !memcmp(nameIn, share->name, nameInLen)) { return share; } } /* * There was no match. As a fall back try a case insensitive match. * This is because some Windows applications uppercase or lowercase the * entire path before sending the request. */ for (l = state->shares.next; l != &state->shares; l = l->next) { HgfsSharedFolder *share; char *tempName; /* * Null terminate the input name before a case insensitive comparison. * This is just to protect against bad implementations of strnicmp. */ if (!(tempName = (char *)malloc(nameInLen + 1))) { LOG(4, ("HgfsServerPolicyGetShare: couldn't allocate tempName\n")); return NULL; } memcpy(tempName, nameIn, nameInLen); tempName[nameInLen] = 0; share = DblLnkLst_Container(l, HgfsSharedFolder, links); ASSERT(share); if (nameInLen == share->nameLen && #ifdef _WIN32 !strnicmp(tempName, share->name, nameInLen)) { #else !strncasecmp(tempName, share->name, nameInLen)) { #endif free(tempName); return share; } free(tempName); } return NULL; }
static void BalloonDeflateInt(Balloon *b, // IN/OUT uint32 target, // IN int isLargePages) // IN { int status = BALLOON_SUCCESS; uint32 nPages, deallocations = 0; BalloonChunk *chunk = NULL; BalloonChunkList *chunkList = &b->pages[isLargePages]; if (chunkList->nChunks == 0) { return; } nPages = 0; while (chunkList->nChunks > 0 && b->nPages > target && nPages < b->nPages - target) { PageHandle lockedHandle; if (chunk == NULL) { /* * The chunk should never be empty. If it is, then there is a * deviation between the guest balloon size, and tracked * pages... */ ASSERT(DblLnkLst_IsLinked(&chunkList->chunks)); chunk = DblLnkLst_Container(chunkList->chunks.next, BalloonChunk, node); } lockedHandle = chunk->entries[--chunk->nEntries]; if (!chunk->nEntries) { DblLnkLst_Unlink1(&chunk->node); /* * Do not free the chunk, we may need it if the UNLOCK cmd fails */ b->fallbackChunk = chunk; chunkList->nChunks--; chunk = NULL; } deallocations++; b->balloonOps->addPage(b, nPages++, lockedHandle); if (nPages == b->batchMaxEntries) { status = b->balloonOps->unlock(b, nPages, isLargePages, &target); nPages = 0; if (status != BALLOON_SUCCESS) { break; } } if (deallocations >= b->rateFree) { /* We released enough pages, let's take a break. */ break; } } if (nPages) { b->balloonOps->unlock(b, nPages, isLargePages, NULL); } if (BALLOON_RATE_ADAPT) { if (status == BALLOON_SUCCESS) { /* slowly increase rate if no errors */ b->rateFree = MIN(b->rateFree + BALLOON_RATE_FREE_INC, BALLOON_RATE_FREE_MAX); } else { /* quickly decrease rate if error */ b->rateFree = MAX(b->rateFree / 2, BALLOON_RATE_FREE_MIN); } } }