2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
14 #include "afs/sysincludes.h" /* Standard vendor system headers */
15 #ifndef AFS_LINUX22_ENV
16 #include "rpc/types.h"
18 #include "afsincludes.h" /* Afs-based standard headers */
19 #include "afs/afs_stats.h" /* statistics */
21 /* memory cache routines */
22 static struct memCacheEntry *memCache;
23 static int memCacheBlkSize = 8192;
24 static int memMaxBlkNumber = 0;
25 static int memAllocMaySleep = 0;
27 extern int cacheDiskType;
30 afs_InitMemCache(int blkCount, int blkSize, int flags)
34 AFS_STATCNT(afs_InitMemCache);
36 memCacheBlkSize = blkSize;
38 memMaxBlkNumber = blkCount;
39 memCache = (struct memCacheEntry *)
40 afs_osi_Alloc(memMaxBlkNumber * sizeof(struct memCacheEntry));
41 if (flags & AFSCALL_INIT_MEMCACHE_SLEEP) {
45 for (index = 0; index < memMaxBlkNumber; index++) {
47 (memCache + index)->size = 0;
48 (memCache + index)->dataSize = memCacheBlkSize;
49 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
50 if (memAllocMaySleep) {
51 blk = afs_osi_Alloc(memCacheBlkSize);
53 blk = afs_osi_Alloc_NoSleep(memCacheBlkSize);
57 (memCache + index)->data = blk;
58 memset((memCache + index)->data, 0, memCacheBlkSize);
60 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS)
61 afs_InitDualFSCacheOps((struct vnode *)0);
67 printf("afsd: memCache allocation failure at %d KB.\n",
68 (index * memCacheBlkSize) / 1024);
69 while (--index >= 0) {
70 afs_osi_Free((memCache + index)->data, memCacheBlkSize);
71 (memCache + index)->data = NULL;
78 afs_MemCacheClose(struct osi_file *file)
84 afs_MemCacheOpen(afs_dcache_id_t *ainode)
86 struct memCacheEntry *mep;
88 if (ainode->mem < 0 || ainode->mem > memMaxBlkNumber) {
89 osi_Panic("afs_MemCacheOpen: invalid block #");
91 mep = (memCache + ainode->mem);
92 afs_Trace3(afs_iclSetp, CM_TRACE_MEMOPEN, ICL_TYPE_INT32, ainode->mem,
93 ICL_TYPE_POINTER, mep, ICL_TYPE_POINTER, mep ? mep->data : 0);
98 * this routine simulates a read in the Memory Cache
101 afs_MemReadBlk(register struct osi_file *fP, int offset, void *dest,
104 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
107 ObtainReadLock(&mceP->afs_memLock);
108 AFS_STATCNT(afs_MemReadBlk);
110 ReleaseReadLock(&mceP->afs_memLock);
113 /* use min of bytes in buffer or requested size */
114 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
118 memcpy(dest, mceP->data + offset, bytesRead);
123 ReleaseReadLock(&mceP->afs_memLock);
128 * this routine simulates a readv in the Memory Cache
131 afs_MemReadvBlk(register struct memCacheEntry *mceP, int offset,
132 struct iovec *iov, int nio, int size)
138 ObtainReadLock(&mceP->afs_memLock);
139 AFS_STATCNT(afs_MemReadBlk);
141 ReleaseReadLock(&mceP->afs_memLock);
144 /* use min of bytes in buffer or requested size */
145 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
148 for (i = 0, size = bytesRead; i < nio && size > 0; i++) {
149 bytesToRead = (size < iov[i].iov_len) ? size : iov[i].iov_len;
151 memcpy(iov[i].iov_base, mceP->data + offset, bytesToRead);
153 offset += bytesToRead;
160 ReleaseReadLock(&mceP->afs_memLock);
165 afs_MemReadUIO(afs_dcache_id_t *ainode, struct uio *uioP)
167 register struct memCacheEntry *mceP =
168 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
169 int length = mceP->size - AFS_UIO_OFFSET(uioP);
172 AFS_STATCNT(afs_MemReadUIO);
173 ObtainReadLock(&mceP->afs_memLock);
174 length = (length < AFS_UIO_RESID(uioP)) ? length : AFS_UIO_RESID(uioP);
175 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), length, UIO_READ, uioP, code);
176 ReleaseReadLock(&mceP->afs_memLock);
180 /*XXX: this extends a block arbitrarily to support big directories */
182 afs_MemWriteBlk(register struct osi_file *fP, int offset, void *src,
185 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
186 AFS_STATCNT(afs_MemWriteBlk);
187 ObtainWriteLock(&mceP->afs_memLock, 560);
188 if (size + offset > mceP->dataSize) {
189 char *oldData = mceP->data;
191 if (memAllocMaySleep) {
192 mceP->data = afs_osi_Alloc(size + offset);
194 mceP->data = afs_osi_Alloc_NoSleep(size + offset);
196 if (mceP->data == NULL) { /* no available memory */
197 mceP->data = oldData; /* revert back change that was made */
198 ReleaseWriteLock(&mceP->afs_memLock);
199 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
204 /* may overlap, but this is OK */
206 memcpy(mceP->data, oldData, mceP->size);
208 afs_osi_Free(oldData, mceP->dataSize);
209 mceP->dataSize = size + offset;
212 if (mceP->size < offset)
213 memset(mceP->data + mceP->size, 0, offset - mceP->size);
214 memcpy(mceP->data + offset, src, size);
216 mceP->size = (size + offset < mceP->size) ? mceP->size : size + offset;
218 ReleaseWriteLock(&mceP->afs_memLock);
222 /*XXX: this extends a block arbitrarily to support big directories */
224 afs_MemWritevBlk(register struct memCacheEntry *mceP, int offset,
225 struct iovec *iov, int nio, int size)
230 AFS_STATCNT(afs_MemWriteBlk);
231 ObtainWriteLock(&mceP->afs_memLock, 561);
232 if (offset + size > mceP->dataSize) {
233 char *oldData = mceP->data;
235 mceP->data = afs_osi_Alloc(size + offset);
236 if (mceP->data == NULL) { /* no available memory */
237 mceP->data = oldData; /* revert back change that was made */
238 ReleaseWriteLock(&mceP->afs_memLock);
239 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
244 /* may overlap, but this is OK */
246 memcpy(mceP->data, oldData, mceP->size);
248 afs_osi_Free(oldData, mceP->dataSize);
249 mceP->dataSize = size + offset;
252 if (mceP->size < offset)
253 memset(mceP->data + mceP->size, 0, offset - mceP->size);
254 for (bytesWritten = 0, i = 0; i < nio && size > 0; i++) {
255 bytesToWrite = (size < iov[i].iov_len) ? size : iov[i].iov_len;
256 memcpy(mceP->data + offset, iov[i].iov_base, bytesToWrite);
257 offset += bytesToWrite;
258 bytesWritten += bytesToWrite;
259 size -= bytesToWrite;
261 mceP->size = (offset < mceP->size) ? mceP->size : offset;
264 ReleaseWriteLock(&mceP->afs_memLock);
269 afs_MemWriteUIO(afs_dcache_id_t *ainode, struct uio *uioP)
271 register struct memCacheEntry *mceP =
272 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
275 AFS_STATCNT(afs_MemWriteUIO);
276 ObtainWriteLock(&mceP->afs_memLock, 312);
277 if (AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP) > mceP->dataSize) {
278 char *oldData = mceP->data;
280 mceP->data = afs_osi_Alloc(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
281 if (mceP->data == NULL) { /* no available memory */
282 mceP->data = oldData; /* revert back change that was made */
283 ReleaseWriteLock(&mceP->afs_memLock);
284 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
285 AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
290 memcpy(mceP->data, oldData, mceP->size);
293 afs_osi_Free(oldData, mceP->dataSize);
294 mceP->dataSize = AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP);
296 if (mceP->size < AFS_UIO_OFFSET(uioP))
297 memset(mceP->data + mceP->size, 0,
298 (int)(AFS_UIO_OFFSET(uioP) - mceP->size));
299 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), AFS_UIO_RESID(uioP), UIO_WRITE,
301 if (AFS_UIO_OFFSET(uioP) > mceP->size)
302 mceP->size = AFS_UIO_OFFSET(uioP);
304 ReleaseWriteLock(&mceP->afs_memLock);
309 afs_MemCacheTruncate(register struct osi_file *fP, int size)
311 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
312 AFS_STATCNT(afs_MemCacheTruncate);
314 ObtainWriteLock(&mceP->afs_memLock, 313);
315 /* old directory entry; g.c. */
316 if (size == 0 && mceP->dataSize > memCacheBlkSize) {
317 char *oldData = mceP->data;
318 mceP->data = afs_osi_Alloc(memCacheBlkSize);
319 if (mceP->data == NULL) { /* no available memory */
320 mceP->data = oldData;
321 ReleaseWriteLock(&mceP->afs_memLock);
322 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
325 afs_osi_Free(oldData, mceP->dataSize);
326 mceP->dataSize = memCacheBlkSize;
330 if (size < mceP->size)
333 ReleaseWriteLock(&mceP->afs_memLock);
339 shutdown_memcache(void)
343 if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
345 memCacheBlkSize = 8192;
346 for (index = 0; index < memMaxBlkNumber; index++) {
347 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
348 afs_osi_Free((memCache + index)->data, (memCache + index)->dataSize);
350 afs_osi_Free((char *)memCache,
351 memMaxBlkNumber * sizeof(struct memCacheEntry));