disksim_cachedev.c
来自「disksim是一个非常优秀的磁盘仿真工具」· C语言 代码 · 共 803 行 · 第 1/2 页
C
803 行
/* * DiskSim Storage Subsystem Simulation Environment (Version 4.0) * Revision Authors: John Bucy, Greg Ganger * Contributors: John Griffin, Jiri Schindler, Steve Schlosser * * Copyright (c) of Carnegie Mellon University, 2001-2008. * * This software is being provided by the copyright holders under the * following license. By obtaining, using and/or copying this software, * you agree that you have read, understood, and will comply with the * following terms and conditions: * * Permission to reproduce, use, and prepare derivative works of this * software is granted provided the copyright and "No Warranty" statements * are included with all reproductions and derivative works and associated * documentation. This software may also be redistributed without charge * provided that the copyright and "No Warranty" statements are included * in all redistributions. * * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. * COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE * OR DOCUMENTATION. * *//* * DiskSim Storage Subsystem Simulation Environment (Version 2.0) * Revision Authors: Greg Ganger * Contributors: Ross Cohen, John Griffin, Steve Schlosser * * Copyright (c) of Carnegie Mellon University, 1999. * * Permission to reproduce, use, and prepare derivative works of * this software for internal use is granted provided the copyright * and "No Warranty" statements are included with all reproductions * and derivative works. This software may also be redistributed * without charge provided that the copyright and "No Warranty" * statements are included in all redistributions. * * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. *//* * DiskSim Storage Subsystem Simulation Environment * Authors: Greg Ganger, Bruce Worthington, Yale Patt * * Copyright (C) 1993, 1995, 1997 The Regents of the University of Michigan * * This software is being provided by the copyright holders under the * following license. By obtaining, using and/or copying this software, * you agree that you have read, understood, and will comply with the * following terms and conditions: * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose and without fee or royalty is * hereby granted, provided that the full text of this NOTICE appears on * ALL copies of the software and documentation or portions thereof, * including modifications, that you make. * * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR * DOCUMENTATION. * * This software is provided AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESSED OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS * OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES, * INCLUDING SPECIAL , INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, * WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION WITH THE * USE OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS * BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES * * The names and trademarks of copyright holders or authors may NOT be * used in advertising or publicity pertaining to the software without * specific, written prior permission. Title to copyright in this software * and any associated documentation will at all times remain with copyright * holders. *//*************************************************************************** This is a fairly simple module for managing a device that is being used as a cache for another device. It does not have many functionalities that a real device-caching-device would have, such as 1. No actual "cache"-iness. That is, it simply maps given locations to the same locations on the cache device. This limits the max amount of real device space that can be cached, and misses opportunities for creating cache-device locality where none exists in the original workload. 2. No prefetching. 3. No optimization. For example, see #1. Also, no grouping of writes to cache-device. Also, no going to original device when cache-device is busy. 4. No locking. Specifically, requests for the same space can be in progress in parallel. This could cause inconsistencies, with unfortunate sequencing. 5. No buffer space limitations. Specifically, there is no limit on the amount of buffer space used at once for managing the cache and real devices.***************************************************************************/#define CACHE_DEVICE 2#include "modules/modules.h"#include "disksim_cachedev.h"static int cachedev_get_maxreqsize (struct cache_if *c){ struct cache_dev *cache = (struct cache_dev *)c; return(cache->maxreqsize);}static void cachedev_empty_donefunc (void *doneparam, ioreq_event *req){ addtoextraq((event *) req);}static void cachedev_add_ongoing_request (struct cache_dev *cache, void *crq){ struct cache_dev_event *cachereq = (struct cache_dev_event *)crq; cachereq->next = cache->ongoing_requests; cachereq->prev = NULL; if (cachereq->next) { cachereq->next->prev = cachereq; } cache->ongoing_requests = cachereq;}static void cachedev_remove_ongoing_request (struct cache_dev *cache, struct cache_dev_event *cachereq){ if (cachereq->next) { cachereq->next->prev = cachereq->prev; } if (cachereq->prev) { cachereq->prev->next = cachereq->next; } if (cache->ongoing_requests == cachereq) { cache->ongoing_requests = cachereq->next; }}static struct cache_dev_event * cachedev_find_ongoing_request (struct cache_dev *cache, ioreq_event *req){ struct cache_dev_event *tmp = cache->ongoing_requests; /* Is this enough to ensure equivalence?? */ while ((tmp != NULL) && ((req->opid != tmp->req->opid) || (req->blkno != tmp->req->blkno) || (req->bcount != tmp->req->bcount) || (req->buf != tmp->req->buf))) { tmp = tmp->next; } return (tmp);}/* Return a count of how many dirty blocks are on the cachedev. */static int cachedev_count_dirty_blocks (struct cache_dev *cache){ int dirtyblocks = 0; int i; for (i=0; i<cache->size; i++) { if (bit_test(cache->dirtymap,i)) { dirtyblocks++; } } return (dirtyblocks);}static void cachedev_setbits (bitstr_t *bitmap, ioreq_event *req){ bit_nset (bitmap, req->blkno, (req->blkno+req->bcount-1));}static void cachedev_clearbits (bitstr_t *bitmap, ioreq_event *req){ bit_nclear (bitmap, req->blkno, (req->blkno+req->bcount-1));}static int cachedev_isreadhit (struct cache_dev *cache, ioreq_event *req){ int lastblk = req->blkno + req->bcount; int i; if (lastblk >= cache->size) { return (0); } for (i=req->blkno; i<lastblk; i++) { if (bit_test(cache->validmap,i) == 0) { return (0); } } return (1);}static int cachedev_iswritehit (struct cache_dev *cache, ioreq_event *req){ if ((req->blkno+req->bcount) >= cache->size) { return (0); } return (1);}static int cachedev_find_dirty_cache_blocks (struct cache_dev *cache, int *blknoPtr, int *bcountPtr){ int blkno; bit_ffs (cache->dirtymap, cache->size, blknoPtr); if (*blknoPtr == -1) { return (0); } blkno = *blknoPtr; while (bit_test (cache->dirtymap, blkno) != 0) { blkno++; } *bcountPtr = blkno - *blknoPtr; return (1);}static void cachedev_periodic_callback (timer_event *timereq){ fprintf (stderr, "cachedev_periodic_callback not yet supported\n"); ASSERT (0); exit (0);}static void cachedev_idlework_callback (void *idleworkparam, int idledevno){ struct cache_dev *cache = idleworkparam; struct cache_dev_event *flushdesc; ioreq_event *flushreq; int blkno, bcount; struct ioq *queue; ASSERT (idledevno == cache->real_devno); queue = (*cache->queuefind)(cache->queuefindparam, cache->real_devno); if (ioqueue_get_number_in_queue (queue) != 0) { return; } queue = (*cache->queuefind)(cache->queuefindparam, cache->cache_devno); if (ioqueue_get_number_in_queue (queue) != 0) { return; } if (cachedev_find_dirty_cache_blocks (cache, &blkno, &bcount) == 0) { return; } /* Just assume that bufferspace is available */ cache->bufferspace += bcount; if (cache->bufferspace > cache->stat.maxbufferspace) { cache->stat.maxbufferspace = cache->bufferspace; } flushdesc = (struct cache_dev_event *) getfromextraq(); flushdesc->type = CACHE_EVENT_IDLEFLUSH_READ; flushreq = (ioreq_event *) getfromextraq(); flushreq->buf = flushdesc; flushreq->devno = cache->cache_devno; flushreq->blkno = blkno; flushreq->bcount = bcount; flushreq->type = IO_ACCESS_ARRIVE; flushreq->flags = READ; (*cache->issuefunc)(cache->issueparam, flushreq); cache->stat.destagereads++; cache->stat.destagereadblocks += bcount;}/* Gets the appropriate block, locked and ready to be accessed read or write */static int cachedev_get_block (struct cache_if *c, ioreq_event *req, void (**donefunc)(void *, ioreq_event *), void *doneparam){ struct cache_dev *cache = (struct cache_dev *)c; struct cache_dev_event *rwdesc = (struct cache_dev_event *) getfromextraq(); ioreq_event *fillreq; int devno; // fprintf (outputfile, "totalreqs = %d\n", disksim->totalreqs); // fprintf (outputfile, "%.5f: Entered cache_get_block: rw %d, devno %d, blkno %d, size %d\n", simtime, (req->flags & READ), req->devno, req->blkno, req->bcount); if (req->devno != cache->real_devno) { fprintf (stderr, "cachedev_get_block trying to cache blocks for wrong device (%d should be %d)\n", req->devno, cache->real_devno); ASSERT(0); exit(1); } /* Ignore request overlap and locking issues for now. */ /* Also ignore buffer space limitation issues for now. */ cache->bufferspace += req->bcount; if (cache->bufferspace > cache->stat.maxbufferspace) { cache->stat.maxbufferspace = cache->bufferspace; } rwdesc->type = (req->flags & READ) ? CACHE_EVENT_READ : CACHE_EVENT_WRITE; rwdesc->donefunc = donefunc; rwdesc->doneparam = doneparam; rwdesc->req = req; req->next = NULL; req->prev = NULL; rwdesc->flags = 0; cachedev_add_ongoing_request (cache, rwdesc); if (req->flags & READ) { cache->stat.reads++; cache->stat.readblocks += req->bcount; /* Send read straight to whichever device has it (preferably cachedev). */ if (cachedev_isreadhit (cache, req)) { devno = cache->cache_devno; cache->stat.readhitsfull++; } else { devno = cache->real_devno; cache->stat.readmisses++; } /* For now, just assume both device's store bits at same LBNs */ fillreq = ioreq_copy (req); fillreq->buf = rwdesc; fillreq->type = IO_ACCESS_ARRIVE; fillreq->devno = devno; // fprintf (outputfile, "fillreq: devno %d, blkno %d, buf %p\n", fillreq->devno, fillreq->blkno, fillreq->buf); (*cache->issuefunc)(cache->issueparam, fillreq); return (1); } else { /* Grab buffer space and let the controller fill in data to be written. */ /* (for now, just assume that there is buffer space available) */ (*donefunc)(doneparam, req); return (0); }}/* frees the block after access complete, block is clean so remove locks *//* and update lru */static void cachedev_free_block_clean (struct cache_if *c, ioreq_event *req){ struct cache_dev *cache = (struct cache_dev *)c; struct cache_dev_event *rwdesc; // fprintf (outputfile, "%.5f: Entered cache_free_block_clean: blkno %d, bcount %d, devno %d\n", simtime, req->blkno, req->bcount, req->devno); /* For now, just find relevant rwdesc and free it. */ /* Later, write it to the cache device (and update the cache map thusly. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?