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"
24 #endif /* AFS_OSF_ENV */
25 #include "afsincludes.h" /* Afs-based standard headers */
26 #include "afs/afs_stats.h" /* statistics */
28 /* memory cache routines */
29 static struct memCacheEntry *memCache;
30 static int memCacheBlkSize = 8192;
31 static int memMaxBlkNumber = 0;
32 static int memAllocMaySleep = 0;
34 extern int cacheDiskType;
37 afs_InitMemCache(int blkCount, int blkSize, int flags)
41 AFS_STATCNT(afs_InitMemCache);
43 memCacheBlkSize = blkSize;
45 memMaxBlkNumber = blkCount;
46 memCache = (struct memCacheEntry *)
47 afs_osi_Alloc(memMaxBlkNumber * sizeof(struct memCacheEntry));
48 if (flags & AFSCALL_INIT_MEMCACHE_SLEEP) {
52 for (index = 0; index < memMaxBlkNumber; index++) {
54 (memCache + index)->size = 0;
55 (memCache + index)->dataSize = memCacheBlkSize;
56 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
57 if (memAllocMaySleep) {
58 blk = afs_osi_Alloc(memCacheBlkSize);
60 blk = afs_osi_Alloc_NoSleep(memCacheBlkSize);
64 (memCache + index)->data = blk;
65 memset((memCache + index)->data, 0, memCacheBlkSize);
67 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS)
68 afs_InitDualFSCacheOps((struct vnode *)0);
74 printf("afsd: memCache allocation failure at %d KB.\n",
75 (index * memCacheBlkSize) / 1024);
76 while (--index >= 0) {
77 afs_osi_Free((memCache + index)->data, memCacheBlkSize);
78 (memCache + index)->data = NULL;
85 afs_MemCacheClose(struct osi_file *file)
91 afs_MemCacheOpen(afs_dcache_id_t *ainode)
93 struct memCacheEntry *mep;
95 if (ainode->mem < 0 || ainode->mem > memMaxBlkNumber) {
96 osi_Panic("afs_MemCacheOpen: invalid block #");
98 mep = (memCache + ainode->mem);
99 afs_Trace3(afs_iclSetp, CM_TRACE_MEMOPEN, ICL_TYPE_INT32, ainode->mem,
100 ICL_TYPE_POINTER, mep, ICL_TYPE_POINTER, mep ? mep->data : 0);
105 * this routine simulates a read in the Memory Cache
108 afs_MemReadBlk(register struct osi_file *fP, int offset, void *dest,
111 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
114 MObtainReadLock(&mceP->afs_memLock);
115 AFS_STATCNT(afs_MemReadBlk);
117 MReleaseReadLock(&mceP->afs_memLock);
120 /* use min of bytes in buffer or requested size */
121 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
125 memcpy(dest, mceP->data + offset, bytesRead);
130 MReleaseReadLock(&mceP->afs_memLock);
135 * this routine simulates a readv in the Memory Cache
138 afs_MemReadvBlk(register struct memCacheEntry *mceP, int offset,
139 struct iovec *iov, int nio, int size)
145 MObtainReadLock(&mceP->afs_memLock);
146 AFS_STATCNT(afs_MemReadBlk);
148 MReleaseReadLock(&mceP->afs_memLock);
151 /* use min of bytes in buffer or requested size */
152 bytesRead = (size < mceP->size - offset) ? size : mceP->size - offset;
155 for (i = 0, size = bytesRead; i < nio && size > 0; i++) {
156 bytesToRead = (size < iov[i].iov_len) ? size : iov[i].iov_len;
158 memcpy(iov[i].iov_base, mceP->data + offset, bytesToRead);
160 offset += bytesToRead;
167 MReleaseReadLock(&mceP->afs_memLock);
172 afs_MemReadUIO(afs_dcache_id_t *ainode, struct uio *uioP)
174 register struct memCacheEntry *mceP =
175 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
176 int length = mceP->size - AFS_UIO_OFFSET(uioP);
179 AFS_STATCNT(afs_MemReadUIO);
180 MObtainReadLock(&mceP->afs_memLock);
181 length = (length < AFS_UIO_RESID(uioP)) ? length : AFS_UIO_RESID(uioP);
182 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), length, UIO_READ, uioP, code);
183 MReleaseReadLock(&mceP->afs_memLock);
187 /*XXX: this extends a block arbitrarily to support big directories */
189 afs_MemWriteBlk(register struct osi_file *fP, int offset, void *src,
192 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
193 AFS_STATCNT(afs_MemWriteBlk);
194 MObtainWriteLock(&mceP->afs_memLock, 560);
195 if (size + offset > mceP->dataSize) {
196 char *oldData = mceP->data;
198 if (memAllocMaySleep) {
199 mceP->data = afs_osi_Alloc(size + offset);
201 mceP->data = afs_osi_Alloc_NoSleep(size + offset);
203 if (mceP->data == NULL) { /* no available memory */
204 mceP->data = oldData; /* revert back change that was made */
205 MReleaseWriteLock(&mceP->afs_memLock);
206 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
211 /* may overlap, but this is OK */
213 memcpy(mceP->data, oldData, mceP->size);
215 afs_osi_Free(oldData, mceP->dataSize);
216 mceP->dataSize = size + offset;
219 if (mceP->size < offset)
220 memset(mceP->data + mceP->size, 0, offset - mceP->size);
221 memcpy(mceP->data + offset, src, size);
223 mceP->size = (size + offset < mceP->size) ? mceP->size : size + offset;
225 MReleaseWriteLock(&mceP->afs_memLock);
229 /*XXX: this extends a block arbitrarily to support big directories */
231 afs_MemWritevBlk(register struct memCacheEntry *mceP, int offset,
232 struct iovec *iov, int nio, int size)
237 AFS_STATCNT(afs_MemWriteBlk);
238 MObtainWriteLock(&mceP->afs_memLock, 561);
239 if (offset + size > mceP->dataSize) {
240 char *oldData = mceP->data;
242 mceP->data = afs_osi_Alloc(size + offset);
243 if (mceP->data == NULL) { /* no available memory */
244 mceP->data = oldData; /* revert back change that was made */
245 MReleaseWriteLock(&mceP->afs_memLock);
246 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
251 /* may overlap, but this is OK */
253 memcpy(mceP->data, oldData, mceP->size);
255 afs_osi_Free(oldData, mceP->dataSize);
256 mceP->dataSize = size + offset;
259 if (mceP->size < offset)
260 memset(mceP->data + mceP->size, 0, offset - mceP->size);
261 for (bytesWritten = 0, i = 0; i < nio && size > 0; i++) {
262 bytesToWrite = (size < iov[i].iov_len) ? size : iov[i].iov_len;
263 memcpy(mceP->data + offset, iov[i].iov_base, bytesToWrite);
264 offset += bytesToWrite;
265 bytesWritten += bytesToWrite;
266 size -= bytesToWrite;
268 mceP->size = (offset < mceP->size) ? mceP->size : offset;
271 MReleaseWriteLock(&mceP->afs_memLock);
276 afs_MemWriteUIO(afs_dcache_id_t *ainode, struct uio *uioP)
278 register struct memCacheEntry *mceP =
279 (struct memCacheEntry *)afs_MemCacheOpen(ainode);
282 AFS_STATCNT(afs_MemWriteUIO);
283 MObtainWriteLock(&mceP->afs_memLock, 312);
284 if (AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP) > mceP->dataSize) {
285 char *oldData = mceP->data;
287 mceP->data = afs_osi_Alloc(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
288 if (mceP->data == NULL) { /* no available memory */
289 mceP->data = oldData; /* revert back change that was made */
290 MReleaseWriteLock(&mceP->afs_memLock);
291 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
292 AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP));
297 memcpy(mceP->data, oldData, mceP->size);
300 afs_osi_Free(oldData, mceP->dataSize);
301 mceP->dataSize = AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP);
303 if (mceP->size < AFS_UIO_OFFSET(uioP))
304 memset(mceP->data + mceP->size, 0,
305 (int)(AFS_UIO_OFFSET(uioP) - mceP->size));
306 AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), AFS_UIO_RESID(uioP), UIO_WRITE,
308 if (AFS_UIO_OFFSET(uioP) > mceP->size)
309 mceP->size = AFS_UIO_OFFSET(uioP);
311 MReleaseWriteLock(&mceP->afs_memLock);
316 afs_MemCacheTruncate(register struct osi_file *fP, int size)
318 register struct memCacheEntry *mceP = (struct memCacheEntry *)fP;
319 AFS_STATCNT(afs_MemCacheTruncate);
321 MObtainWriteLock(&mceP->afs_memLock, 313);
322 /* old directory entry; g.c. */
323 if (size == 0 && mceP->dataSize > memCacheBlkSize) {
324 char *oldData = mceP->data;
325 mceP->data = afs_osi_Alloc(memCacheBlkSize);
326 if (mceP->data == NULL) { /* no available memory */
327 mceP->data = oldData;
328 MReleaseWriteLock(&mceP->afs_memLock);
329 afs_warn("afs: afs_MemWriteBlk mem alloc failure (%d bytes)\n",
332 afs_osi_Free(oldData, mceP->dataSize);
333 mceP->dataSize = memCacheBlkSize;
337 if (size < mceP->size)
340 MReleaseWriteLock(&mceP->afs_memLock);
346 shutdown_memcache(void)
350 if (cacheDiskType != AFS_FCACHE_TYPE_MEM)
352 memCacheBlkSize = 8192;
353 for (index = 0; index < memMaxBlkNumber; index++) {
354 LOCK_INIT(&((memCache + index)->afs_memLock), "afs_memLock");
355 afs_osi_Free((memCache + index)->data, (memCache + index)->dataSize);
357 afs_osi_Free((char *)memCache,
358 memMaxBlkNumber * sizeof(struct memCacheEntry));