示例#1
0
 private PreReadReturnCode PreRead(IRP irp)
 {
     if (noisyOutput)
     {
         Console.WriteLine("PreRead {0}: Got Offset={1} Length={2} Align={3}",
                           Thread.CurrentThread.ManagedThreadId, irp.FileOffset, irp.DataLength, cache.AlignedBlockSize);
     }
     if (irp.DataLength % cache.AlignedBlockSize != 0 ||
         irp.FileOffset % cache.AlignedBlockSize != 0)
     {
         Console.WriteLine("PreRead {0}: Got UNALIGNED Offset={1} Length={2} Align={3}",
                           Thread.CurrentThread.ManagedThreadId, irp.FileOffset, irp.DataLength, cache.AlignedBlockSize);
     }
     //Console.WriteLine("OFFSETS,LENGTHS,{0},{1}", irp.FileOffset, irp.DataLength);
     //return PreReadReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
     return(cache.CacheIRP(irp));
     //return PreReadReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
 }
示例#2
0
 private PreCleanupReturnCode PreCleanup(IRP irp)
 {
     return(cache.CachePreCleanup(irp));
 }
示例#3
0
 private PostWriteReturnCode PostWrite(IRP irp)
 {
     return(cache.CacheWriteIRPCompleted(irp));
 }
示例#4
0
 private PreWriteReturnCode PreWrite(IRP irp)
 {
     return(cache.CacheWriteIRP(irp));
 }
示例#5
0
 private PostReadReturnCode PostRead(IRP irp)
 {
     return(cache.CacheIRPCompleted(irp));
 }
示例#6
0
 private PreReadReturnCode PreRead(IRP irp)
 {
     return(this.cache.CacheIRP(irp));
 }
示例#7
0
 private PreCreateReturnCode PreCreate(IRP irp)
 {
     return(this.cache.CachePreCreate(irp));
 }
示例#8
0
 private PreCleanupReturnCode PreCleanup(IRP irp)
 {
     //return PreCleanupReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
     return(cache.CachePreCleanup(irp));
 }
示例#9
0
 private PostWriteReturnCode PostWrite(IRP irp)
 {
     //return PostWriteReturnCode.FLT_POSTOP_FINISHED_PROCESSING;
     return(cache.CacheWriteIRPCompleted(irp));
     //return PostWriteReturnCode.FLT_POSTOP_FINISHED_PROCESSING;
 }
示例#10
0
 public PreCleanupReturnCode CachePreCleanup(IRP irp)
 {
     return(PreCleanupReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK);
 }
示例#11
0
 private PreCreateReturnCode PreCreate(IRP irp)
 {
     return(cache.CachePreCreate(irp));
     //return PreCreateReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
 }
示例#12
0
 public PreCreateReturnCode CachePreCreate(IRP irp)
 {
     return(PreCreateReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK);
 }
示例#13
0
        /// <summary>
        /// Intercepts a write request, caches it, then sends it down if doing write-through, or returns success and writes it out later if doing write-back
        /// XXXET: shares a lot of functionality with cacheIRP. Probably should be 1 function
        /// </summary>
        /// <param name="irp"></param>
        /// <returns></returns>
        public PreWriteReturnCode CacheWriteIRP(IRP irp)
        {
            Dictionary <string, Dictionary <uint, FileCacheElement> > f = null;
            Dictionary <uint, FileCacheElement> b = null;
            FileCacheElement ce                = null;
            FlowSLA          sla               = null;
            bool             blockUpdated      = false;
            bool             anyBlockUpdated   = false;
            ulong            savedFileOffset   = irp.FileOffset;
            uint             savedDataLength   = irp.DataLength;
            uint             dataOffset        = irp.DataOffset;
            ulong            fileOffset        = savedFileOffset;
            bool             writeHit          = false;
            bool             canSatisfyRequest = false;

            Debug.Assert(irp.IoFlowHeader.MajorFunction == MajorFunction.IRP_MJ_WRITE);


            if ((int)irp.IoFlowHeader.ProcessID != CacheProcessID) //don't intercept traffic we generated
            {
                if (noisyOutput)
                {
                    Console.WriteLine("CacheWriteIRP {0}: Attempting to lock cache on Offset={1} Length={2}",
                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                }
                Monitor.Enter(cacheLock);
                if (noisyOutput)
                {
                    Console.WriteLine("CacheWriteIRP {0}: Locked cache on Offset={1} Length={2}",
                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                }

                //string tempFileNameChunking = irp.IoFlowRuntime.getDriveLetterFileName(irp.IoFlow.FileName); //save file name here once, so we don't do multiple calls to this

                // iterate over all blocks
                // it's a hit if all blocks are a hit, otherwise its a miss for the entire IRP
                do
                {
                    uint blockid = (uint)(fileOffset / ALIGNED_BLOCK_SIZE);

                    //Get the flow stats list
                    if (!FlowStats.TryGetValue(irp.FlowId, out sla))
                    {
                        //sla = new FlowSLA();
                        //FlowStats[irp.FlowId] = sla;
                        Debug.Assert(0 == 1); //XXXIS let's only deal with explicitly declared flows right now
                    }

                    if (!Cache.TryGetValue(irp.FlowId, out f))
                    {
                        Cache[irp.FlowId] = new Dictionary <string, Dictionary <uint, FileCacheElement> >();
                        f = Cache[irp.FlowId];
                    }
                    if (!f.TryGetValue(irp.IoFlow.FileName, out b))
                    {
                        f[irp.IoFlow.FileName] = new Dictionary <uint, FileCacheElement>();
                        b = f[irp.IoFlow.FileName];
                    }

                    if (!b.TryGetValue(blockid, out ce))                // block is not currently cached
                    {
                        if (this.cacheWrites == CacheWriteBuffer.Cache) // only cache the block if write caching is turned on
                        {
                            //b[blockid] = new FileCacheElement(irp.IoFlow, irp.IoFlowRuntime.getDriveLetterFileName(irp.IoFlow.FileName), null,
                            //    fileOffset, dataOffset, ALIGNED_BLOCK_SIZE /* copying data only */);
                            b[blockid] = getFileCacheElement(irp.IoFlow, irp.IoFlow.FileName, null, fileOffset, dataOffset, ALIGNED_BLOCK_SIZE /* copying data only */);

                            ce = b[blockid];

                            //Might need to evict if we don't have enough space for the new entry
                            Evict(irp.FlowId);


                            ce.UpdateNodeList(sla.cacheEntries.AddLast(ce)); //Just create the cache entry
                            cacheSizeUsedBytes         += ALIGNED_BLOCK_SIZE;
                            sla.FlowCacheSizeUsedBytes += ALIGNED_BLOCK_SIZE;
                        }
                    }

                    // block is in the cache; only update if the block has data in flight (eg: a read), or if write caching is turned on
                    if ((this.cacheWrites == CacheWriteBuffer.noCache && ce != null) || this.cacheWrites == CacheWriteBuffer.Cache)
                    {
                        {
                            lock (ce.LockObj)
                            {
                                if (noisyOutput)
                                {
                                    Console.WriteLine("CacheWriteIRP {0}: Locked ce on Offset={1} Length={2}",
                                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                }
                                if (noisyOutput)
                                {
                                    Console.WriteLine("CacheWriteIRP {0}: Caching write on Offset={1} Length={2}",
                                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                }

                                ce.UpdateData(irp.GetDataReadOnly(), dataOffset, ALIGNED_BLOCK_SIZE /* copying data */);
                                blockUpdated = true;



                                //Move to the front of the LRU list
                                Debug.Assert(ce.nodeInList != null);
                                sla.cacheEntries.Remove(ce.nodeInList);
                                sla.cacheEntries.AddLast(ce.nodeInList);



                                //XXXIS: send all writes to ghost cache
                                if (sla.FlowSLAHasGhostCache())
                                {
                                    sla.GhostCache.CacheReadReference(ce.fileName + Convert.ToString(blockid)); //Forward the reference to the ghost cache
                                }
                            }
                        }
                    }
                    fileOffset += ALIGNED_BLOCK_SIZE;
                    dataOffset += ALIGNED_BLOCK_SIZE;


                    if (blockUpdated == true)
                    {
                        anyBlockUpdated = true;
                    }
                } while (fileOffset < savedFileOffset + savedDataLength);


                sla.CacheAccessesTotal++; //update total number of ops that passed through this cache
                sla.FlowBytesAccessed += irp.DataLength;

                if (writeHit)
                {
                    sla.CacheAccessesHits++;
                }

                Monitor.Exit(cacheLock);
                if (noisyOutput)
                {
                    Console.WriteLine("CacheWriteIRP {0}: UnLocked cache on Offset={1} Length={2}",
                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                }

                if (this.writePolicy == CacheWritePolicy.WriteThrough || anyBlockUpdated == true) //if write-through, or waiting for disk to reply on a read for some block we wrote
                {
                    return(PreWriteReturnCode.FLT_PREOP_SUCCESS_WITH_CALLBACK);                   //send it down
                }
                else
                {
                    Debug.Assert(0 == 1); //we shouldn't be in this case
                }
            }
            return(PreWriteReturnCode.FLT_PREOP_COMPLETE); //return complete (ignore traffic we generated)
        }
示例#14
0
 /// <summary>
 /// Intercepts callback after a write succeeds on write-through
 /// </summary>
 /// <param name="irp"></param>
 /// <returns></returns>
 public PostWriteReturnCode CacheWriteIRPCompleted(IRP irp)
 {
     return(PostWriteReturnCode.FLT_POSTOP_FINISHED_PROCESSING);
 }
示例#15
0
        /// <summary>
        /// Caches a given IRP on the way down
        /// </summary>
        /// <param name="irp"></param>
        /// <returns></returns>
        public PreReadReturnCode CacheIRP(IRP irp)
        {
            // lookup if IRP is already cached
            Dictionary <string, Dictionary <uint, FileCacheElement> > f = null;

            Dictionary <uint, FileCacheElement> b = null;
            FileCacheElement ce                = null;
            bool             hit               = false;
            bool             anyMisses         = false;
            FlowSLA          sla               = null;
            ulong            savedFileOffset   = irp.FileOffset;
            uint             savedDataLength   = irp.DataLength;
            uint             dataOffset        = irp.DataOffset;
            ulong            fileOffset        = savedFileOffset;
            bool             canSatisfyRequest = false;

            Debug.Assert(irp.IoFlowHeader.MajorFunction == MajorFunction.IRP_MJ_READ);

            if (noisyOutput)
            {
                Console.WriteLine("CacheIRP {0}: Attempting to lock cache on Offset={1} Length={2}",
                                  Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
            }


            Monitor.Enter(cacheLock);


            sla = FlowStats[irp.FlowId];
            Debug.Assert(sla != null); //Only deal with explicitly declared flows

            //Do we have enough cache space available to satisfy this request?
            if (sla.FlowCacheSize > irp.DataLength)
            {
                canSatisfyRequest = true;
            }

            if (noisyOutput)
            {
                Console.WriteLine("CacheIRP {0}: Locked cache on Offset={1} Length={2}",
                                  Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
            }

            if (canSatisfyRequest)
            {
                // iterate over all blocks
                // it's a hit if all blocks are a hit, otherwise its a miss for the entire IRP
                do
                {
                    uint blockid = (uint)(fileOffset / ALIGNED_BLOCK_SIZE);
                    hit = false; //block isn't a hit yet
                    {
                        if (Cache.TryGetValue(irp.FlowId, out f))
                        {
                            if (f.TryGetValue(irp.IoFlow.FileName, out b))
                            {
                                if (b.TryGetValue(blockid, out ce))
                                {
                                    // cache entry exists
                                    if (noisyOutput)
                                    {
                                        Console.WriteLine("CacheIRP {0}: Attempting to lock ce on Offset={1} Length={2}",
                                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                    }
                                    lock (ce.LockObj)
                                    {
                                        if (noisyOutput)
                                        {
                                            Console.WriteLine("CacheIRP {0}: Locked ce on Offset={1} Length={2}",
                                                              Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                        }
                                        if (ce.Data != null)
                                        {
                                            // real hit ; cache entry has data being read
                                            sla = FlowStats[irp.FlowId];
                                            Debug.Assert(sla != null); //We should always have a valid sla entry if we have a hit

                                            hit = true;
                                            byte[] irpData = irp.GetDataReadWrite();
                                            Debug.Assert(ce.DataLength == ALIGNED_BLOCK_SIZE);
                                            Buffer.BlockCopy(ce.Data, 0, irpData, (int)dataOffset, (int)ALIGNED_BLOCK_SIZE);



                                            Debug.Assert(ce.nodeInList != null);
                                            Debug.Assert(ce.nodeInList != null);
                                            sla.cacheEntries.Remove(ce.nodeInList); //Assumes no duplicate ce's in the list, which should be true...
                                            //ce.UpdateNodeList(sla.cacheEntries.AddLast(ce));
                                            sla.cacheEntries.AddLast(ce.nodeInList);


                                            if (sla.FlowSLAHasGhostCache())
                                            {
                                                sla.GhostCache.CacheReadReference(ce.fileName + Convert.ToString(blockid)); //Forward the reference to the ghost cache
                                            }
                                        }
                                        else
                                        {
                                            // cache entry exists, BUT data is still in-flight from storage medium
                                            hit = false;
                                        }
                                    }
                                    if (noisyOutput)
                                    {
                                        Console.WriteLine("CacheIRP {0}: UnLocked ce on Offset={1} Length={2}",
                                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                    }
                                }
                            }
                        }

                        if (!hit)
                        {
                            // evict first
                            Evict(irp.FlowId);

                            // then insert
                            if (f == null)
                            {
                                Cache[irp.FlowId] = new Dictionary <string, Dictionary <uint, FileCacheElement> >();
                                f = Cache[irp.FlowId];
                            }

                            if (b == null)
                            {
                                f[irp.IoFlow.FileName] = new Dictionary <uint, FileCacheElement>();
                                b = f[irp.IoFlow.FileName];
                            }
                            if (ce == null)
                            {
                                //b[blockid] = new FileCacheElement(irp.IoFlow, irp.IoFlowRuntime.getDriveLetterFileName(irp.IoFlow.FileName), null,
                                //    fileOffset, dataOffset, ALIGNED_BLOCK_SIZE /* copying data only */);
                                //string tempFileNameChunking = irp.IoFlowRuntime.getDriveLetterFileName(irp.IoFlow.FileName); //save file name here once, so we don't do multiple calls to this

                                b[blockid] = getFileCacheElement(irp.IoFlow, irp.IoFlow.FileName, null, fileOffset, dataOffset, ALIGNED_BLOCK_SIZE /* copying data only */);

                                ce = b[blockid];

                                // insert element into list
                                if (false == FlowStats.TryGetValue(irp.FlowId, out sla))
                                {
                                    //sla = new FlowSLA();
                                    //FlowStats[irp.FlowId] = sla;
                                    Debug.Assert(0 == 1); //XXXIS let's only deal with explicitly declared flows right now
                                }
                                ce.UpdateNodeList(sla.cacheEntries.AddLast(ce));
                                cacheSizeUsedBytes         += ALIGNED_BLOCK_SIZE;
                                sla.FlowCacheSizeUsedBytes += ALIGNED_BLOCK_SIZE;

                                if (sla.FlowSLAHasGhostCache())
                                {
                                    sla.GhostCache.CacheReadReference(ce.fileName + Convert.ToString(blockid)); //Forward the reference to the ghost cache
                                }
                            }
                        }
                    }
                    if (noisyOutput)
                    {
                        Console.WriteLine("CacheIRP {0}: UnLock cache on Offset={1} Length={2}",
                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                    }

                    fileOffset += ALIGNED_BLOCK_SIZE;
                    dataOffset += ALIGNED_BLOCK_SIZE;

                    if (hit == false)
                    {
                        anyMisses = true;
                    }
                } while (fileOffset < savedFileOffset + savedDataLength);


                if (false == FlowStats.TryGetValue(irp.FlowId, out sla))
                {
                    Debug.Assert(0 == 1); //XXXIS let's only deal with explicitly declared flows right now
                }
                if (!anyMisses)
                {
                    sla.CacheAccessesHits++; //Increment the number of hits in the cache
                }
            }

            sla.CacheAccessesTotal++; //increment all the accesses to this cache
            sla.FlowBytesAccessed += irp.DataLength;

            Monitor.Exit(cacheLock);

            // deal with MISSES
            // Let IRP go through and intercept POST operation (with payload)
            //
            if (anyMisses == true || !canSatisfyRequest)
            {
                //Console.WriteLine("MISS: {0}", irp.FileOffset);
                if (noisyOutput)
                {
                    Console.WriteLine("CacheIRP {0}: PreRead MISS Offset={1} Length={2}",
                                      Thread.CurrentThread.ManagedThreadId, irp.FileOffset, irp.DataLength);
                }
                return(PreReadReturnCode.FLT_PREOP_SUCCESS_WITH_CALLBACK);
            }
            else
            {
                //Console.WriteLine("HIT: {0}", irp.FileOffset);
                if (noisyOutput)
                {
                    Console.WriteLine("CacheIRP {0}: PreRead HIT Offset={1} Length={2}",
                                      Thread.CurrentThread.ManagedThreadId, irp.FileOffset, irp.DataLength);
                }
                return(PreReadReturnCode.FLT_PREOP_COMPLETE);
            }
        }
示例#16
0
        /// <summary>
        /// Receives a completed IRP, e.g., a completed read
        /// </summary>
        /// <param name="irp"></param>
        /// <returns></returns>
        public PostReadReturnCode CacheIRPCompleted(IRP irp)
        {
            // lookup if IRP is already cached. Assert if so
            Dictionary <string, Dictionary <uint, FileCacheElement> > f = null;
            ulong savedFileOffset = irp.FileOffset;
            uint  savedDataLength = irp.DataLength;
            uint  dataOffset      = irp.DataOffset;
            ulong fileOffset      = savedFileOffset;
            Dictionary <uint, FileCacheElement> b = null;
            FileCacheElement ce = null;


            Debug.Assert(irp.IoFlowHeader.MajorFunction == MajorFunction.IRP_MJ_READ);


            if (noisyOutput)
            {
                Console.WriteLine("CacheIRPCompleted {0}: Attempting to lock cache on Offset={1} Length={2}",
                                  Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
            }

            lock (cacheLock)
            {
                do
                {
                    uint blockid = (uint)(fileOffset / ALIGNED_BLOCK_SIZE);


                    if (noisyOutput)
                    {
                        Console.WriteLine("CacheIRPCompleted {0}: Locked cache on Offset={1} Length={2}",
                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                    }


                    if (Cache.TryGetValue(irp.FlowId, out f))
                    {
                        if (f.TryGetValue(irp.IoFlow.FileName, out b))
                        {
                            if (b.TryGetValue(blockid, out ce))
                            {
                                // real hit
                                if (noisyOutput)
                                {
                                    Console.WriteLine("CacheIRPCompleted {0}: Attempting to lock ce on Offset={1} Length={2}",
                                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                }

                                lock (ce.LockObj)
                                {
                                    if (noisyOutput)
                                    {
                                        Console.WriteLine("CacheIRPCompleted {0}: Locked ce on Offset={1} Length={2}",
                                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                    }

                                    if (ce.Data != null)
                                    {
                                        if (noisyOutput)
                                        {
                                            Console.WriteLine("CacheIRPCompleted {0}: Thought we had a miss. Now hit? {1} Length={2}",
                                                              Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                        }
                                        //Debug.Assert(0 == 1);
                                    }
                                    //else
                                    //{
                                    ce.UpdateData(irp.GetDataReadOnly(), dataOffset, ALIGNED_BLOCK_SIZE /* copying data */);
                                    ce.Dirty = false;

                                    if (noisyOutput)
                                    {
                                        Console.WriteLine("CacheIRPCompleted {0}: Waking up all on Offset={1} Length={2}",
                                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                    }

                                    // Monitor.PulseAll(ce.LockObj); // wake up anyone waiting on this object
                                    //}
                                }
                                if (noisyOutput)
                                {
                                    Console.WriteLine("CacheIRPCompleted {0}: UnLocked ce on Offset={1} Length={2}",
                                                      Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                                }
                            }
                        }
                    }

                    if (noisyOutput)
                    {
                        Console.WriteLine("CacheIRPCompleted {0}: Cached Offset={1} Length={2}",
                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                    }


                    if (noisyOutput)
                    {
                        Console.WriteLine("CacheIRPCompleted {0}: UnLocked cache on Offset={1} Length={2}",
                                          Thread.CurrentThread.ManagedThreadId, fileOffset, ALIGNED_BLOCK_SIZE);
                    }
                    fileOffset += ALIGNED_BLOCK_SIZE;
                    dataOffset += ALIGNED_BLOCK_SIZE;
                } while (fileOffset < savedFileOffset + savedDataLength);
            }

            return(PostReadReturnCode.FLT_POSTOP_FINISHED_PROCESSING);
        }