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;
26 extern int cacheDiskType;
29 afs_InitMemCache(int blkCount, int blkSize, int flags)
33 AFS_STATCNT(afs_InitMemCache);
35 memCacheBlkSize = blkSize;
37 memMaxBlkNumber = blkCount;
39 afs_osi_Alloc(memMaxBlkNumber * sizeof(struct memCacheEntry));
40 osi_Assert(memCache != NULL);
42 for (index = 0; index < memMaxBlkNumber; index++) {
44 (memCache + index)->size = 0;
45 (memCache + index)->dataSize = memCacheBlkSize;
46 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
47 blk = afs_osi_Alloc(memCacheBlkSize);
50 (memCache + index)->data = blk;
51 memset((memCache + index)->data, 0, memCacheBlkSize);
53 #if defined(AFS_HAVE_VXFS)
54 afs_InitDualFSCacheOps((struct vnode *)0);
56 for (index = 0; index < blkCount; index++)
57 afs_InitCacheFile(NULL, 0);
61 afs_warn("afsd: memCache allocation failure at %d KB.\n",
62 (index * memCacheBlkSize) / 1024);
63 while (--index >= 0) {
64 afs_osi_Free((memCache + index)->data, memCacheBlkSize);
65 (memCache + index)->data = NULL;
72 afs_MemCacheClose(struct osi_file *file)
78 afs_MemCacheOpen(afs_dcache_id_t *ainode)
80 struct memCacheEntry *mep;
82 if (ainode->mem < 0 || ainode->mem > memMaxBlkNumber) {
83 osi_Panic("afs_MemCacheOpen: invalid block #");
85 mep = (memCache + ainode->mem);
86 afs_Trace3(afs_iclSetp, CM_TRACE_MEMOPEN, ICL_TYPE_INT32, ainode->mem,
87 ICL_TYPE_POINTER, mep, ICL_TYPE_POINTER, mep ? mep->data : 0);
92 * this routine simulates a read in the Memory Cache
95 afs_MemReadBlk(struct osi_file *fP, int offset, void *dest,
98 struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
101 ObtainReadLock(&mceP->afs_memLock);
102 AFS_STATCNT(afs_MemReadBlk);
104 ReleaseReadLock(&mceP->afs_memLock);
107 /* use min of bytes in buffer or requested size */
108 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
112 memcpy(dest, mceP->data + offset, bytesRead);
117 ReleaseReadLock(&mceP->afs_memLock);
122 * this routine simulates a readv in the Memory Cache
125 afs_MemReadvBlk(struct memCacheEntry *mceP, int offset,
126 struct iovec *iov, int nio, int size)
132 ObtainReadLock(&mceP->afs_memLock);
133 AFS_STATCNT(afs_MemReadBlk);
135 ReleaseReadLock(&mceP->afs_memLock);
138 /* use min of bytes in buffer or requested size */
139 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
142 for (i = 0, size = bytesRead; i < nio && size > 0; i++) {
143 bytesToRead = (size < iov[i].iov_len) ? size : iov[i].iov_len;
145 memcpy(iov[i].iov_base, mceP->data + offset, bytesToRead);
147 offset += bytesToRead;
154 ReleaseReadLock(&mceP->afs_memLock);
159 afs_MemReadUIO(afs_dcache_id_t *ainode, struct uio *uioP)
161 struct memCacheEntry *mceP =
162 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
163 int length = mceP->size - AFS_UIO_OFFSET(uioP);
166 AFS_STATCNT(afs_MemReadUIO);
167 ObtainReadLock(&mceP->afs_memLock);
168 length = (length < AFS_UIO_RESID(uioP)) ? length : AFS_UIO_RESID(uioP);
169 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), length, UIO_READ, uioP, code);
170 ReleaseReadLock(&mceP->afs_memLock);
175 _afs_MemExtendEntry(struct memCacheEntry *mceP, afs_uint32 size)
177 if (size > mceP->dataSize) {
178 char *oldData = mceP->data;
180 mceP->data = afs_osi_Alloc(size);
181 if (mceP->data == NULL) { /* no available memory */
182 mceP->data = oldData; /* revert back change that was made */
183 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n", size);
187 /* may overlap, but this is OK */
189 memcpy(mceP->data, oldData, mceP->size);
191 afs_osi_Free(oldData, mceP->dataSize);
192 mceP->dataSize = size;
198 afs_MemWriteBlk(struct osi_file *fP, int offset, void *src,
201 struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
206 return afs_MemWritevBlk(mceP, offset, &tiov, 1, size);
209 /*XXX: this extends a block arbitrarily to support big directories */
211 afs_MemWritevBlk(struct memCacheEntry *mceP, int offset,
212 struct iovec *iov, int nio, int size)
217 AFS_STATCNT(afs_MemWriteBlk);
218 ObtainWriteLock(&mceP->afs_memLock, 561);
219 bytesWritten = _afs_MemExtendEntry(mceP, (offset + size));
220 if (bytesWritten != 0)
223 if (mceP->size < offset)
224 memset(mceP->data + mceP->size, 0, offset - mceP->size);
225 for (bytesWritten = 0, i = 0; i < nio && size > 0; i++) {
226 bytesToWrite = (size < iov[i].iov_len) ? size : iov[i].iov_len;
227 memcpy(mceP->data + offset, iov[i].iov_base, bytesToWrite);
228 offset += bytesToWrite;
229 bytesWritten += bytesToWrite;
230 size -= bytesToWrite;
232 mceP->size = (offset < mceP->size) ? mceP->size : offset;
235 ReleaseWriteLock(&mceP->afs_memLock);
240 afs_MemWriteUIO(struct vcache *avc, afs_dcache_id_t *ainode, struct uio *uioP)
242 struct memCacheEntry *mceP =
243 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
246 AFS_STATCNT(afs_MemWriteUIO);
247 ObtainWriteLock(&mceP->afs_memLock, 312);
248 if (AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP) > mceP->dataSize) {
249 char *oldData = mceP->data;
251 mceP->data = afs_osi_Alloc(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
252 if (mceP->data == NULL) { /* no available memory */
253 mceP->data = oldData; /* revert back change that was made */
254 ReleaseWriteLock(&mceP->afs_memLock);
255 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%ld bytes)\n",
256 (long)(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP)));
261 memcpy(mceP->data, oldData, mceP->size);
264 afs_osi_Free(oldData, mceP->dataSize);
265 mceP->dataSize = AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP);
267 if (mceP->size < AFS_UIO_OFFSET(uioP))
268 memset(mceP->data + mceP->size, 0,
269 (int)(AFS_UIO_OFFSET(uioP) - mceP->size));
270 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), AFS_UIO_RESID(uioP), UIO_WRITE,
272 if (AFS_UIO_OFFSET(uioP) > mceP->size)
273 mceP->size = AFS_UIO_OFFSET(uioP);
275 ReleaseWriteLock(&mceP->afs_memLock);
280 afs_MemCacheTruncate(struct osi_file *fP, int size)
282 struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
283 AFS_STATCNT(afs_MemCacheTruncate);
285 ObtainWriteLock(&mceP->afs_memLock, 313);
286 /* old directory entry; g.c. */
287 if (size == 0 && mceP->dataSize > memCacheBlkSize) {
288 char *oldData = mceP->data;
289 mceP->data = afs_osi_Alloc(memCacheBlkSize);
290 if (mceP->data == NULL) { /* no available memory */
291 mceP->data = oldData;
292 ReleaseWriteLock(&mceP->afs_memLock);
293 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
296 afs_osi_Free(oldData, mceP->dataSize);
297 mceP->dataSize = memCacheBlkSize;
301 if (size < mceP->size)
304 ReleaseWriteLock(&mceP->afs_memLock);
309 afs_MemExtendEntry(struct memCacheEntry *mceP, afs_uint32 size)
312 ObtainWriteLock(&mceP->afs_memLock, 560);
313 code = _afs_MemExtendEntry(mceP, size);
314 ReleaseWriteLock(&mceP->afs_memLock);
319 shutdown_memcache(void)
323 if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
325 memCacheBlkSize = 8192;
326 for (index = 0; index < memMaxBlkNumber; index++) {
327 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
328 afs_osi_Free((memCache + index)->data, (memCache + index)->dataSize);
330 afs_osi_Free((char *)memCache,
331 memMaxBlkNumber * sizeof(struct memCacheEntry));