~n-muench/open-vm-tools/devel

« back to all changes in this revision

Viewing changes to modules/linux/vmci/common/vmciResource.c

  • Committer: Nate Muench
  • Date: 2011-05-05 00:27:16 UTC
  • Revision ID: nowiwilldestroyabydos@gmail.com-20110505002716-f87n4uvh2hg3crrk
Merge with Natty, Enable shared folders

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2006 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License as published by the
 
6
 * Free Software Foundation version 2 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
11
 * for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * vmciResource.c --
 
21
 *
 
22
 *     Implementation of the VMCI Resource Access Control API.
 
23
 */
 
24
 
 
25
#include "vmci_kernel_if.h"
 
26
#include "vm_assert.h"
 
27
#include "vmci_defs.h"
 
28
#include "vmci_infrastructure.h"
 
29
#include "vmciCommonInt.h"
 
30
#include "vmciHashtable.h"
 
31
#include "vmciResource.h"
 
32
#if defined(VMKERNEL)
 
33
#  include "vmciVmkInt.h"
 
34
#  include "vm_libc.h"
 
35
#  include "helper_ext.h"
 
36
#  include "vmciDriver.h"
 
37
#else
 
38
#  include "vmciDriver.h"
 
39
#endif
 
40
 
 
41
#define LGPFX "VMCIResource: "
 
42
 
 
43
/* 0 through VMCI_RESERVED_RESOURCE_ID_MAX are reserved. */
 
44
static uint32 resourceID = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
 
45
static VMCILock resourceIdLock;
 
46
 
 
47
static void VMCIResourceDoRemove(VMCIResource *resource);
 
48
 
 
49
static VMCIHashTable *resourceTable = NULL;
 
50
 
 
51
 
 
52
/* Public Resource Access Control API. */
 
53
 
 
54
/*
 
55
 *------------------------------------------------------------------------------
 
56
 *
 
57
 * VMCIResource_Init --
 
58
 *
 
59
 *      Initializes the VMCI Resource Access Control API. Creates a hashtable
 
60
 *      to hold all resources, and registers vectors and callbacks for
 
61
 *      hypercalls.
 
62
 *
 
63
 * Results:
 
64
 *      None.
 
65
 *
 
66
 * Side effects:
 
67
 *      None.
 
68
 *
 
69
 *------------------------------------------------------------------------------
 
70
 */
 
71
 
 
72
int
 
73
VMCIResource_Init(void)
 
74
{
 
75
   resourceTable = VMCIHashTable_Create(128);
 
76
   if (resourceTable == NULL) {
 
77
      VMCI_WARNING((LGPFX"Failed creating a resource hash table for VMCI.\n"));
 
78
      return VMCI_ERROR_NO_MEM;
 
79
   }
 
80
 
 
81
   VMCI_InitLock(&resourceIdLock, "VMCIRIDLock", VMCI_LOCK_RANK_HIGHEST);
 
82
 
 
83
   return VMCI_SUCCESS;
 
84
}
 
85
 
 
86
 
 
87
/*
 
88
 *------------------------------------------------------------------------------
 
89
 *
 
90
 * VMCIResource_Exit --
 
91
 *
 
92
 *      Cleans up resources.
 
93
 *
 
94
 * Results:
 
95
 *      None.
 
96
 *
 
97
 * Side effects:
 
98
 *      None.
 
99
 *
 
100
 *------------------------------------------------------------------------------
 
101
 */
 
102
 
 
103
void
 
104
VMCIResource_Exit(void)
 
105
{
 
106
   /* Cleanup resources.*/
 
107
   VMCI_CleanupLock(&resourceIdLock);
 
108
 
 
109
   if (resourceTable) {
 
110
      VMCIHashTable_Destroy(resourceTable);
 
111
   }
 
112
}
 
113
 
 
114
 
 
115
/*
 
116
 *------------------------------------------------------------------------------
 
117
 *
 
118
 *  VMCIResource_GetID --
 
119
 *
 
120
 *     Return resource ID. The first VMCI_RESERVED_RESOURCE_ID_MAX are
 
121
 *     reserved so we start from its value + 1.
 
122
 *
 
123
 *  Result:
 
124
 *     VMCI resource id on success, VMCI_INVALID_ID on failure.
 
125
 *
 
126
 *  Side effects:
 
127
 *     None.
 
128
 *
 
129
 *
 
130
 *------------------------------------------------------------------------------
 
131
 */
 
132
 
 
133
VMCIId
 
134
VMCIResource_GetID(VMCIId contextID)
 
135
{
 
136
   VMCIId oldRID = resourceID;
 
137
   VMCIId currentRID;
 
138
   Bool foundRID = FALSE;
 
139
 
 
140
   /*
 
141
    * Generate a unique resource ID.  Keep on trying until we wrap around
 
142
    * in the RID space.
 
143
    */
 
144
   ASSERT(oldRID > VMCI_RESERVED_RESOURCE_ID_MAX);
 
145
 
 
146
   do {
 
147
      VMCILockFlags flags;
 
148
      VMCIHandle handle;
 
149
 
 
150
      VMCI_GrabLock(&resourceIdLock, &flags);
 
151
      currentRID = resourceID;
 
152
      handle = VMCI_MAKE_HANDLE(contextID, currentRID);
 
153
      resourceID++;
 
154
      if (UNLIKELY(resourceID == VMCI_INVALID_ID)) {
 
155
         /*
 
156
          * Skip the reserved rids.
 
157
          */
 
158
 
 
159
         resourceID = VMCI_RESERVED_RESOURCE_ID_MAX + 1;
 
160
      }
 
161
      VMCI_ReleaseLock(&resourceIdLock, flags);
 
162
      foundRID = !VMCIHashTable_EntryExists(resourceTable, handle);
 
163
   } while (!foundRID && resourceID != oldRID);
 
164
 
 
165
   if (UNLIKELY(!foundRID)) {
 
166
      return VMCI_INVALID_ID;
 
167
   } else {
 
168
      return currentRID;
 
169
   }
 
170
}
 
171
 
 
172
 
 
173
/*
 
174
 *------------------------------------------------------------------------------
 
175
 *
 
176
 * VMCIResource_Add --
 
177
 *
 
178
 * Results:
 
179
 *      VMCI_SUCCESS if successful, error code if not.
 
180
 *
 
181
 * Side effects:
 
182
 *      None.
 
183
 *
 
184
 *------------------------------------------------------------------------------
 
185
 */
 
186
 
 
187
int
 
188
VMCIResource_Add(VMCIResource *resource,                // IN
 
189
                 VMCIResourceType resourceType,         // IN
 
190
                 VMCIHandle resourceHandle,             // IN
 
191
                 VMCIResourceFreeCB containerFreeCB,    // IN
 
192
                 void *containerObject)                 // IN
 
193
{
 
194
   int result;
 
195
 
 
196
   ASSERT(resource);
 
197
 
 
198
   if (VMCI_HANDLE_EQUAL(resourceHandle, VMCI_INVALID_HANDLE)) {
 
199
      VMCI_DEBUG_LOG(4, (LGPFX"Invalid argument resource (handle=0x%x:0x%x).\n",
 
200
                         resourceHandle.context, resourceHandle.resource));
 
201
      return VMCI_ERROR_INVALID_ARGS;
 
202
   }
 
203
 
 
204
   VMCIHashTable_InitEntry(&resource->hashEntry, resourceHandle);
 
205
   resource->type = resourceType;
 
206
   resource->containerFreeCB = containerFreeCB;
 
207
   resource->containerObject = containerObject;
 
208
   resource->handle = resourceHandle;
 
209
 
 
210
   /* Add resource to hashtable. */
 
211
   result = VMCIHashTable_AddEntry(resourceTable, &resource->hashEntry);
 
212
   if (result != VMCI_SUCCESS) {
 
213
      VMCI_DEBUG_LOG(4, (LGPFX"Failed to add entry to hash table "
 
214
                         "(result=%d).\n", result));
 
215
      return result;
 
216
   }
 
217
 
 
218
   return result;
 
219
}
 
220
 
 
221
 
 
222
/*
 
223
 *------------------------------------------------------------------------------
 
224
 *
 
225
 * VMCIResource_Remove --
 
226
 *
 
227
 * Results:
 
228
 *      None.
 
229
 *
 
230
 * Side effects:
 
231
 *      None.
 
232
 *
 
233
 *------------------------------------------------------------------------------
 
234
 */
 
235
 
 
236
void
 
237
VMCIResource_Remove(VMCIHandle resourceHandle,     // IN:
 
238
                    VMCIResourceType resourceType) // IN:
 
239
{
 
240
   VMCIResource *resource = VMCIResource_Get(resourceHandle, resourceType);
 
241
   if (resource == NULL) {
 
242
      return;
 
243
   }
 
244
 
 
245
   /* Remove resource from hashtable. */
 
246
   VMCIHashTable_RemoveEntry(resourceTable, &resource->hashEntry);
 
247
 
 
248
   VMCIResource_Release(resource);
 
249
   /* resource could be freed by now. */
 
250
}
 
251
 
 
252
 
 
253
/*
 
254
 *------------------------------------------------------------------------------
 
255
 *
 
256
 * VMCIResource_Get --
 
257
 *
 
258
 * Results:
 
259
 *      Resource is successful. Otherwise NULL.
 
260
 *
 
261
 * Side effects:
 
262
 *      None.
 
263
 *
 
264
 *------------------------------------------------------------------------------
 
265
 */
 
266
 
 
267
VMCIResource *
 
268
VMCIResource_Get(VMCIHandle resourceHandle,     // IN
 
269
                 VMCIResourceType resourceType) // IN
 
270
{
 
271
   VMCIResource *resource;
 
272
   VMCIHashEntry *entry = VMCIHashTable_GetEntry(resourceTable, resourceHandle);
 
273
   if (entry == NULL) {
 
274
      return NULL;
 
275
   }
 
276
   resource = RESOURCE_CONTAINER(entry, VMCIResource, hashEntry);
 
277
   if (resourceType == VMCI_RESOURCE_TYPE_ANY ||
 
278
       resource->type == resourceType) {
 
279
      return resource;
 
280
   }
 
281
   VMCIHashTable_ReleaseEntry(resourceTable, entry);
 
282
   return NULL;
 
283
}
 
284
 
 
285
 
 
286
/*
 
287
 *------------------------------------------------------------------------------
 
288
 *
 
289
 * VMCIResource_Hold --
 
290
 *
 
291
 *      Hold the given resource.  This will hold the hashtable entry.  This
 
292
 *      is like doing a Get() but without having to lookup the resource by
 
293
 *      handle.
 
294
 *
 
295
 * Results:
 
296
 *      None.
 
297
 *
 
298
 * Side effects:
 
299
 *      None.
 
300
 *
 
301
 *------------------------------------------------------------------------------
 
302
 */
 
303
 
 
304
void
 
305
VMCIResource_Hold(VMCIResource *resource)
 
306
{
 
307
   ASSERT(resource);
 
308
   VMCIHashTable_HoldEntry(resourceTable, &resource->hashEntry);
 
309
}
 
310
 
 
311
 
 
312
/*
 
313
 *------------------------------------------------------------------------------
 
314
 *
 
315
 * VMCIResourceDoRemove --
 
316
 *
 
317
 *      Deallocates data structures associated with the given resource
 
318
 *      and invoke any call back registered for the resource.
 
319
 *
 
320
 * Results:
 
321
 *      None.
 
322
 *
 
323
 * Side effects:
 
324
 *      May deallocate memory and invoke a callback for the removed resource.
 
325
 *
 
326
 *------------------------------------------------------------------------------
 
327
 */
 
328
 
 
329
static void INLINE
 
330
VMCIResourceDoRemove(VMCIResource *resource)
 
331
{
 
332
   ASSERT(resource);
 
333
 
 
334
   if (resource->containerFreeCB) {
 
335
      resource->containerFreeCB(resource->containerObject);
 
336
      /* Resource has been freed don't dereference it. */
 
337
   }
 
338
}
 
339
 
 
340
 
 
341
/*
 
342
 *------------------------------------------------------------------------------
 
343
 *
 
344
 * VMCIResource_Release --
 
345
 *
 
346
 * Results:
 
347
 *      None.
 
348
 *
 
349
 * Side effects:
 
350
 *      resource's containerFreeCB will get called if last reference.
 
351
 *
 
352
 *------------------------------------------------------------------------------
 
353
 */
 
354
 
 
355
int
 
356
VMCIResource_Release(VMCIResource *resource)
 
357
{
 
358
   int result;
 
359
 
 
360
   ASSERT(resource);
 
361
 
 
362
   result = VMCIHashTable_ReleaseEntry(resourceTable, &resource->hashEntry);
 
363
   if (result == VMCI_SUCCESS_ENTRY_DEAD) {
 
364
      VMCIResourceDoRemove(resource);
 
365
   }
 
366
 
 
367
   /*
 
368
    * We propagate the information back to caller in case it wants to know
 
369
    * whether entry was freed.
 
370
    */
 
371
   return result;
 
372
}
 
373
 
 
374
 
 
375
/*
 
376
 *------------------------------------------------------------------------------
 
377
 *
 
378
 * VMCIResource_Sync --
 
379
 *
 
380
 *      Use this as a synchronization point when setting globals, for example,
 
381
 *      during device shutdown.
 
382
 *
 
383
 * Results:
 
384
 *      None.
 
385
 *
 
386
 * Side effects:
 
387
 *      None.
 
388
 *
 
389
 *------------------------------------------------------------------------------
 
390
 */
 
391
 
 
392
void
 
393
VMCIResource_Sync(void)
 
394
{
 
395
   VMCIHashTable_Sync(resourceTable);
 
396
}