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;
38 memCache = (struct memCacheEntry *)
39 afs_osi_Alloc(memMaxBlkNumber * sizeof(struct memCacheEntry));
41 for (index = 0; index < memMaxBlkNumber; index++) {
43 (memCache + index)->size = 0;
44 (memCache + index)->dataSize = memCacheBlkSize;
45 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
46 blk = afs_osi_Alloc(memCacheBlkSize);
49 (memCache + index)->data = blk;
50 memset((memCache + index)->data, 0, memCacheBlkSize);
52 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS)
53 afs_InitDualFSCacheOps((struct vnode *)0);
59 printf("afsd: memCache allocation failure at %d KB.\n",
60 (index * memCacheBlkSize) / 1024);
61 while (--index >= 0) {
62 afs_osi_Free((memCache + index)->data, memCacheBlkSize);
63 (memCache + index)->data = NULL;
70 afs_MemCacheClose(struct osi_file *file)
76 afs_MemCacheOpen(afs_dcache_id_t *ainode)
78 struct memCacheEntry *mep;
80 if (ainode->mem < 0 || ainode->mem > memMaxBlkNumber) {
81 osi_Panic("afs_MemCacheOpen: invalid block #");
83 mep = (memCache + ainode->mem);
84 afs_Trace3(afs_iclSetp, CM_TRACE_MEMOPEN, ICL_TYPE_INT32, ainode->mem,
85 ICL_TYPE_POINTER, mep, ICL_TYPE_POINTER, mep ? mep->data : 0);
90 * this routine simulates a read in the Memory Cache
93 afs_MemReadBlk(register struct osi_file *fP, int offset, void *dest,
96 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
99 ObtainReadLock(&mceP->afs_memLock);
100 AFS_STATCNT(afs_MemReadBlk);
102 ReleaseReadLock(&mceP->afs_memLock);
105 /* use min of bytes in buffer or requested size */
106 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
110 memcpy(dest, mceP->data + offset, bytesRead);
115 ReleaseReadLock(&mceP->afs_memLock);
120 * this routine simulates a readv in the Memory Cache
123 afs_MemReadvBlk(register struct memCacheEntry *mceP, int offset,
124 struct iovec *iov, int nio, int size)
130 ObtainReadLock(&mceP->afs_memLock);
131 AFS_STATCNT(afs_MemReadBlk);
133 ReleaseReadLock(&mceP->afs_memLock);
136 /* use min of bytes in buffer or requested size */
137 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
140 for (i = 0, size = bytesRead; i < nio && size > 0; i++) {
141 bytesToRead = (size < iov[i].iov_len) ? size : iov[i].iov_len;
143 memcpy(iov[i].iov_base, mceP->data + offset, bytesToRead);
145 offset += bytesToRead;
152 ReleaseReadLock(&mceP->afs_memLock);
157 afs_MemReadUIO(afs_dcache_id_t *ainode, struct uio *uioP)
159 register struct memCacheEntry *mceP =
160 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
161 int length = mceP->size - AFS_UIO_OFFSET(uioP);
164 AFS_STATCNT(afs_MemReadUIO);
165 ObtainReadLock(&mceP->afs_memLock);
166 length = (length < AFS_UIO_RESID(uioP)) ? length : AFS_UIO_RESID(uioP);
167 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), length, UIO_READ, uioP, code);
168 ReleaseReadLock(&mceP->afs_memLock);
172 /*XXX: this extends a block arbitrarily to support big directories */
174 afs_MemWriteBlk(register struct osi_file *fP, int offset, void *src,
177 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
178 AFS_STATCNT(afs_MemWriteBlk);
179 ObtainWriteLock(&mceP->afs_memLock, 560);
180 if (size + offset > mceP->dataSize) {
181 char *oldData = mceP->data;
183 mceP->data = afs_osi_Alloc(size + offset);
184 if (mceP->data == NULL) { /* no available memory */
185 mceP->data = oldData; /* revert back change that was made */
186 ReleaseWriteLock(&mceP->afs_memLock);
187 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
192 /* may overlap, but this is OK */
194 memcpy(mceP->data, oldData, mceP->size);
196 afs_osi_Free(oldData, mceP->dataSize);
197 mceP->dataSize = size + offset;
200 if (mceP->size < offset)
201 memset(mceP->data + mceP->size, 0, offset - mceP->size);
202 memcpy(mceP->data + offset, src, size);
204 mceP->size = (size + offset < mceP->size) ? mceP->size : size + offset;
206 ReleaseWriteLock(&mceP->afs_memLock);
210 /*XXX: this extends a block arbitrarily to support big directories */
212 afs_MemWritevBlk(register struct memCacheEntry *mceP, int offset,
213 struct iovec *iov, int nio, int size)
218 AFS_STATCNT(afs_MemWriteBlk);
219 ObtainWriteLock(&mceP->afs_memLock, 561);
220 if (offset + size > mceP->dataSize) {
221 char *oldData = mceP->data;
223 mceP->data = afs_osi_Alloc(size + offset);
224 if (mceP->data == NULL) { /* no available memory */
225 mceP->data = oldData; /* revert back change that was made */
226 ReleaseWriteLock(&mceP->afs_memLock);
227 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
232 /* may overlap, but this is OK */
234 memcpy(mceP->data, oldData, mceP->size);
236 afs_osi_Free(oldData, mceP->dataSize);
237 mceP->dataSize = size + offset;
240 if (mceP->size < offset)
241 memset(mceP->data + mceP->size, 0, offset - mceP->size);
242 for (bytesWritten = 0, i = 0; i < nio && size > 0; i++) {
243 bytesToWrite = (size < iov[i].iov_len) ? size : iov[i].iov_len;
244 memcpy(mceP->data + offset, iov[i].iov_base, bytesToWrite);
245 offset += bytesToWrite;
246 bytesWritten += bytesToWrite;
247 size -= bytesToWrite;
249 mceP->size = (offset < mceP->size) ? mceP->size : offset;
252 ReleaseWriteLock(&mceP->afs_memLock);
257 afs_MemWriteUIO(afs_dcache_id_t *ainode, struct uio *uioP)
259 register struct memCacheEntry *mceP =
260 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
263 AFS_STATCNT(afs_MemWriteUIO);
264 ObtainWriteLock(&mceP->afs_memLock, 312);
265 if (AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP) > mceP->dataSize) {
266 char *oldData = mceP->data;
268 mceP->data = afs_osi_Alloc(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
269 if (mceP->data == NULL) { /* no available memory */
270 mceP->data = oldData; /* revert back change that was made */
271 ReleaseWriteLock(&mceP->afs_memLock);
272 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
273 AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
278 memcpy(mceP->data, oldData, mceP->size);
281 afs_osi_Free(oldData, mceP->dataSize);
282 mceP->dataSize = AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP);
284 if (mceP->size < AFS_UIO_OFFSET(uioP))
285 memset(mceP->data + mceP->size, 0,
286 (int)(AFS_UIO_OFFSET(uioP) - mceP->size));
287 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), AFS_UIO_RESID(uioP), UIO_WRITE,
289 if (AFS_UIO_OFFSET(uioP) > mceP->size)
290 mceP->size = AFS_UIO_OFFSET(uioP);
292 ReleaseWriteLock(&mceP->afs_memLock);
297 afs_MemCacheTruncate(register struct osi_file *fP, int size)
299 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
300 AFS_STATCNT(afs_MemCacheTruncate);
302 ObtainWriteLock(&mceP->afs_memLock, 313);
303 /* old directory entry; g.c. */
304 if (size == 0 && mceP->dataSize > memCacheBlkSize) {
305 char *oldData = mceP->data;
306 mceP->data = afs_osi_Alloc(memCacheBlkSize);
307 if (mceP->data == NULL) { /* no available memory */
308 mceP->data = oldData;
309 ReleaseWriteLock(&mceP->afs_memLock);
310 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
313 afs_osi_Free(oldData, mceP->dataSize);
314 mceP->dataSize = memCacheBlkSize;
318 if (size < mceP->size)
321 ReleaseWriteLock(&mceP->afs_memLock);
327 shutdown_memcache(void)
331 if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
333 memCacheBlkSize = 8192;
334 for (index = 0; index < memMaxBlkNumber; index++) {
335 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
336 afs_osi_Free((memCache + index)->data, (memCache + index)->dataSize);
338 afs_osi_Free((char *)memCache,
339 memMaxBlkNumber * sizeof(struct memCacheEntry));