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 #include "afsincludes.h" /* Afs-based standard headers */
16 #include "afs/afs_stats.h" /* statistics */
18 /* memory cache routines */
19 static struct memCacheEntry *memCache;
20 static int memCacheBlkSize = 8192;
21 static int memMaxBlkNumber = 0;
23 extern int cacheDiskType;
26 afs_InitMemCache(int blkCount, int blkSize, int flags)
30 AFS_STATCNT(afs_InitMemCache);
32 memCacheBlkSize = blkSize;
34 memMaxBlkNumber = blkCount;
36 afs_osi_Alloc(memMaxBlkNumber * sizeof(struct memCacheEntry));
37 osi_Assert(memCache != NULL);
39 for (index = 0; index < memMaxBlkNumber; index++) {
41 (memCache + index)->size = 0;
42 (memCache + index)->dataSize = memCacheBlkSize;
43 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
44 blk = afs_osi_Alloc(memCacheBlkSize);
47 (memCache + index)->data = blk;
48 memset((memCache + index)->data, 0, memCacheBlkSize);
50 #if defined(AFS_HAVE_VXFS)
51 afs_InitDualFSCacheOps((struct vnode *)0);
53 for (index = 0; index < blkCount; index++)
54 afs_InitCacheFile(NULL, 0);
58 afs_warn("afsd: memCache allocation failure at %d KB.\n",
59 (index * memCacheBlkSize) / 1024);
60 while (--index >= 0) {
61 afs_osi_Free((memCache + index)->data, memCacheBlkSize);
62 (memCache + index)->data = NULL;
69 afs_MemCacheClose(struct osi_file *file)
75 afs_MemCacheOpen(afs_dcache_id_t *ainode)
77 struct memCacheEntry *mep;
79 if (ainode->mem < 0 || ainode->mem > memMaxBlkNumber) {
80 osi_Panic("afs_MemCacheOpen: invalid block #");
82 mep = (memCache + ainode->mem);
83 afs_Trace3(afs_iclSetp, CM_TRACE_MEMOPEN, ICL_TYPE_INT32, ainode->mem,
84 ICL_TYPE_POINTER, mep, ICL_TYPE_POINTER, mep ? mep->data : 0);
89 * this routine simulates a read in the Memory Cache
92 afs_MemReadBlk(struct osi_file *fP, int offset, void *dest,
95 struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
98 ObtainReadLock(&mceP->afs_memLock);
99 AFS_STATCNT(afs_MemReadBlk);
101 ReleaseReadLock(&mceP->afs_memLock);
104 /* use min of bytes in buffer or requested size */
105 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
109 memcpy(dest, mceP->data + offset, bytesRead);
114 ReleaseReadLock(&mceP->afs_memLock);
119 * this routine simulates a readv in the Memory Cache
122 afs_MemReadvBlk(struct memCacheEntry *mceP, int offset,
123 struct iovec *iov, int nio, int size)
129 ObtainReadLock(&mceP->afs_memLock);
130 AFS_STATCNT(afs_MemReadBlk);
132 ReleaseReadLock(&mceP->afs_memLock);
135 /* use min of bytes in buffer or requested size */
136 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
139 for (i = 0, size = bytesRead; i < nio && size > 0; i++) {
140 bytesToRead = (size < iov[i].iov_len) ? size : iov[i].iov_len;
142 memcpy(iov[i].iov_base, mceP->data + offset, bytesToRead);
144 offset += bytesToRead;
151 ReleaseReadLock(&mceP->afs_memLock);
156 afs_MemReadUIO(afs_dcache_id_t *ainode, struct uio *uioP)
158 struct memCacheEntry *mceP =
159 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
160 int length = mceP->size - AFS_UIO_OFFSET(uioP);
163 AFS_STATCNT(afs_MemReadUIO);
164 ObtainReadLock(&mceP->afs_memLock);
165 length = (length < AFS_UIO_RESID(uioP)) ? length : AFS_UIO_RESID(uioP);
166 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), length, UIO_READ, uioP, code);
167 ReleaseReadLock(&mceP->afs_memLock);
172 _afs_MemExtendEntry(struct memCacheEntry *mceP, afs_uint32 size)
174 if (size > mceP->dataSize) {
175 char *oldData = mceP->data;
177 mceP->data = afs_osi_Alloc(size);
178 if (mceP->data == NULL) { /* no available memory */
179 mceP->data = oldData; /* revert back change that was made */
180 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n", size);
184 /* may overlap, but this is OK */
186 memcpy(mceP->data, oldData, mceP->size);
188 afs_osi_Free(oldData, mceP->dataSize);
189 mceP->dataSize = size;
195 afs_MemWriteBlk(struct osi_file *fP, int offset, void *src,
198 struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
203 return afs_MemWritevBlk(mceP, offset, &tiov, 1, size);
206 /*XXX: this extends a block arbitrarily to support big directories */
208 afs_MemWritevBlk(struct memCacheEntry *mceP, int offset,
209 struct iovec *iov, int nio, int size)
214 AFS_STATCNT(afs_MemWriteBlk);
215 ObtainWriteLock(&mceP->afs_memLock, 561);
216 bytesWritten = _afs_MemExtendEntry(mceP, (offset + size));
217 if (bytesWritten != 0)
220 if (mceP->size < offset)
221 memset(mceP->data + mceP->size, 0, offset - mceP->size);
222 for (bytesWritten = 0, i = 0; i < nio && size > 0; i++) {
223 bytesToWrite = (size < iov[i].iov_len) ? size : iov[i].iov_len;
224 memcpy(mceP->data + offset, iov[i].iov_base, bytesToWrite);
225 offset += bytesToWrite;
226 bytesWritten += bytesToWrite;
227 size -= bytesToWrite;
229 mceP->size = (offset < mceP->size) ? mceP->size : offset;
232 ReleaseWriteLock(&mceP->afs_memLock);
237 afs_MemWriteUIO(struct vcache *avc, afs_dcache_id_t *ainode, struct uio *uioP)
239 struct memCacheEntry *mceP =
240 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
243 AFS_STATCNT(afs_MemWriteUIO);
244 ObtainWriteLock(&mceP->afs_memLock, 312);
245 if (AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP) > mceP->dataSize) {
246 char *oldData = mceP->data;
248 mceP->data = afs_osi_Alloc(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
249 if (mceP->data == NULL) { /* no available memory */
250 mceP->data = oldData; /* revert back change that was made */
251 ReleaseWriteLock(&mceP->afs_memLock);
252 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%ld bytes)\n",
253 (long)(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP)));
258 memcpy(mceP->data, oldData, mceP->size);
261 afs_osi_Free(oldData, mceP->dataSize);
262 mceP->dataSize = AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP);
264 if (mceP->size < AFS_UIO_OFFSET(uioP))
265 memset(mceP->data + mceP->size, 0,
266 (int)(AFS_UIO_OFFSET(uioP) - mceP->size));
267 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), AFS_UIO_RESID(uioP), UIO_WRITE,
269 if (AFS_UIO_OFFSET(uioP) > mceP->size)
270 mceP->size = AFS_UIO_OFFSET(uioP);
272 ReleaseWriteLock(&mceP->afs_memLock);
277 afs_MemCacheTruncate(struct osi_file *fP, int size)
279 struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
280 AFS_STATCNT(afs_MemCacheTruncate);
282 ObtainWriteLock(&mceP->afs_memLock, 313);
283 /* old directory entry; g.c. */
284 if (size == 0 && mceP->dataSize > memCacheBlkSize) {
285 char *oldData = mceP->data;
286 mceP->data = afs_osi_Alloc(memCacheBlkSize);
287 if (mceP->data == NULL) { /* no available memory */
288 mceP->data = oldData;
289 ReleaseWriteLock(&mceP->afs_memLock);
290 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
293 afs_osi_Free(oldData, mceP->dataSize);
294 mceP->dataSize = memCacheBlkSize;
298 if (size < mceP->size)
301 ReleaseWriteLock(&mceP->afs_memLock);
306 shutdown_memcache(void)
310 if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
312 memCacheBlkSize = 8192;
313 for (index = 0; index < memMaxBlkNumber; index++) {
314 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
315 afs_osi_Free((memCache + index)->data, (memCache + index)->dataSize);
317 afs_osi_Free((char *)memCache,
318 memMaxBlkNumber * sizeof(struct memCacheEntry));