示例#1
0
文件: IoFlow.cs 项目: sibaoli/Moirai
 public void Enqueue(IRP irp)
 {
     lock (IrpList)
     {
         IrpList.Enqueue(irp);
     }
 }
示例#2
0
文件: IoFlow.cs 项目: sibaoli/Moirai
        public IRP Dequeue()
        {
            IRP irp = null;

            lock (IrpList)
            {
                irp = IrpList.Dequeue();
            }
            return(irp);
        }
示例#3
0
        public void FreeIrp(IRP irp)
        {
            if (irp.State != IrpState.Free)
            {
                throw new ApplicationException("FreeIrp() : Irp!=Free.");
            }
            irp.State = IrpState.Pool;

            lock (IrpPoolLock)
            {
                Debug.Assert(irp.Next == null, "FreeIrp expected single irp, got multi-irp chain");
                irp.Next    = FreeIrpPool;
                FreeIrpPool = irp;
                irp.IoFlow  = null;
                countFreeIrpList++;
            }
        }
示例#4
0
        //
        // Obtain one Irp object from free Irp list.
        //
        internal IRP AllocateIrp()
        {
            IRP irp = null;

            lock (IrpPoolLock)
            {
                if (FreeIrpPool != null)
                {
                    irp         = FreeIrpPool;
                    FreeIrpPool = FreeIrpPool.Next;
                    countFreeIrpList--;
                }
            }

            if (irp == null) // Expected to fail, with some diags.
            {
                throw new ApplicationException("Free Irp pool exhausted");
            }

            irp.Next  = irp.Prev = null;
            irp.State = IrpState.Free;
            return(irp);
        }
示例#5
0
        private PreWriteReturnCode PreWrite(IRP irp)
        {
            if (noisyOutput)
                Console.WriteLine("PreWrite {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("PreWrite {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 PreWriteReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
            return cache.CacheWriteIRP(irp);
            //return PreWriteReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
        }
示例#6
0
 private PreCreateReturnCode PreCreate(IRP irp)
 {
     return cache.CachePreCreate(irp);
     //return PreCreateReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
 }
示例#7
0
 private PreCleanupReturnCode PreCleanup(IRP irp)
 {
     //return PreCleanupReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
     return cache.CachePreCleanup(irp);
 }
示例#8
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;
            }
        }
示例#9
0
 private PostReadReturnCode InvalidPostRead(IRP irp)
 {
     throw new NotImplementedException(String.Format("FlowId {0} PostRead callback not registered.", FlowId));
 }
示例#10
0
文件: IoFlow.cs 项目: sibaoli/Moirai
 private PreLockControlReturnCode InvalidPreLockControl(IRP irp)
 {
     throw new NotImplementedException(String.Format("FlowId {0} PreLockControl callback not registered.", FlowId));
 }
示例#11
0
 public PreCreateReturnCode CachePreCreate(IRP irp)
 {
     return PreCreateReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
 }
示例#12
0
        /// <summary>
        /// Iocp completion thread using GetQueuedCompletionStatus().
        /// </summary>
        /// <param name="o"></param>
        private void IocpThreadProc(object o)
        {
            //
            // Start the READ requests to minifilter driver.
            //
            for (int i = 0; i < Parameters.COUNT_IO_READ_MPL; i++)
            {
                IRP irp = AllocateIrp();
                irp.StartMiniFilterGetMessage();
            }

            while (!ShuttingDown)
            {
                uint   lpNumberOfBytes;
                uint   lpCompletionKey;
                IntPtr lpOverlapped;
                FLT_PREOP_CALLBACK_STATUS  PreOpResult  = FLT_PREOP_CALLBACK_STATUS.FLT_PREOP_SUCCESS_WITH_CALLBACK;
                FLT_POSTOP_CALLBACK_STATUS PostOpResult = FLT_POSTOP_CALLBACK_STATUS.FLT_POSTOP_FINISHED_PROCESSING;


                //
                // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364986(v=vs.85).aspx
                //
                if (!GetQueuedCompletionStatus(hCompletionPort,     // HANDLE CompletionPort
                                               out lpNumberOfBytes, // LPDWORD lpNumberOfBytes
                                               out lpCompletionKey, // PULONG_PTR lpCompletionKey
                                               out lpOverlapped,    // LPOVERLAPPED lpOverlapped
                                               WIN32_INFINITE))     // DWORD dwMilliseconds
                {
                    int HResult = Marshal.GetHRForLastWin32Error();

                    //
                    // Expect to get here when Close() has been called.
                    //
                    const uint THE_HANDLE_IS_INVALID  = 0x80070006; // Not an error.
                    const uint ERROR_ABANDONED_WAIT_0 = 0x800702DF; // Not an error.
                    if ((uint)HResult == THE_HANDLE_IS_INVALID || (uint)HResult == ERROR_ABANDONED_WAIT_0)
                    {
                        break;
                    }

                    //
                    // Unexpected error.
                    //
                    int LastWin32Error = Marshal.GetLastWin32Error();
                    Console.WriteLine("LastWin32Error {0} HResult {1:X8}", LastWin32Error, HResult);
                    Marshal.ThrowExceptionForHR((int)HResult);
                }

                //
                // Get from native addr of completing OVERLAPPED struct to the associated managed code IRP.
                //
                IRP irp = FindIrp[lpOverlapped];

                irp.CompleteMiniFilterGetMessage();

                //
                // Find the IoFlow for this IRP and call the user's callback function.
                //
                LockIoFlow.EnterReadLock();
                irp.IoFlow = DictIoFlow[irp.IoFlowHeader.FlowId];
                LockIoFlow.ExitReadLock();

                //
                // Indicate any late errors for earlier IO indicated on this flow.
                // These can happen if an error happens in the driver *after* the
                // filterMgr messaging API has indicated that the reply message has
                // been successfully delivered to the driver. In priciple the owning
                // app should also know due to IO failure.
                //
                if ((irp.IoFlowHeader.Flags & (uint)HeaderFlags.HeaderFlagLateIoError) != 0)
                {
                    string msg = "One or more errors reported for earlier IO on flowId ";
                    msg = string.Format("{0} {1} file {2}", msg, irp.IoFlow.FlowId, irp.IoFlow.FileName);
                    throw new ExceptionIoFlow(msg);
                }

                //
                // Throw iff the kmode IRP's buffer is too large for our k2u buffers.
                // In this case we see incomplete data so any ops on the data are invalid.
                //
                if (irp.DataLength > irp.MaxDataLength)
                {
                    string msg = string.Format("Err irp.DataLength({0}) > k2u buffer size({1})",
                                               irp.DataLength, irp.MaxDataLength);
                    throw new ExceptionIoFlow(msg);
                }

                //
                // Upcall to user-supplied callback routine.
                // Note the minifilter only sends IRPs for flows that have registered an appropriate callback routine.
                //
                bool IsPreOp = irp.IsPreOp, IsPostOp = !IsPreOp;
                switch (irp.MajorFunction)
                {
                case MajorFunction.IRP_MJ_CREATE:
                {
                    if (IsPreOp)
                    {
                        PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreCreate(irp);
                    }
                    else
                    {
                        PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostCreate(irp);
                    }
                    break;
                }

                case MajorFunction.IRP_MJ_READ:
                {
                    if (IsPreOp)
                    {
                        PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreRead(irp);
                    }
                    else
                    {
                        PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostRead(irp);
                    }
                    break;
                }

                case MajorFunction.IRP_MJ_WRITE:
                {
                    if (IsPreOp)
                    {
                        PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreWrite(irp);
                    }
                    else
                    {
                        PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostWrite(irp);
                    }
                    break;
                }

                case MajorFunction.IRP_MJ_CLEANUP:
                {
                    if (IsPreOp)
                    {
                        PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreCleanup(irp);
                    }
                    else
                    {
                        PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostCleanup(irp);
                    }
                    break;
                }

                case MajorFunction.IRP_MJ_LOCK_CONTROL:
                {
                    if (IsPreOp)
                    {
                        PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreLockControl(irp);
                    }
                    else
                    {
                        throw new NotImplementedException(String.Format("irp.IoFlow.FlowId {0} PostLockControl callback not supported.",
                                                                        irp.IoFlow.FlowId));
                    }
                    break;
                }

                default:
                    throw new ApplicationException("should never get here.");
                }

                irp.SetStateCallbackReturned();
                irp.IoFlowHeader.FilterReplyHeader.Status = 0;
                irp.IoFlowHeader.Resultcode = (irp.IsPreOp ? (uint)PreOpResult : (uint)PostOpResult);

#if UseReplyAndGetNext
                //
                // App is done with this IRP.
                // Send reply to minifilter driver and restart next upcall on same IRP.
                //
                irp.MiniFilterReplyAndGetNext(hDataAsyncPort, hControlPort);
#else // UseReplyAndGetNext
                //
                // Send reply to our minifilter driver.
                //
                irp.MiniFilterReplyMessage(hDataAsyncPort, hControlPort);

                //
                // The IRP is no longer in use by app - we can restart next upcall request on same IRP.
                //
                irp.StartMiniFilterGetMessage();
#endif // UseReplyAndGetNext
            }

            if (Interlocked.Decrement(ref CountIocpThreadsRunning) == 0)
            {
                LastThreadTerminated.Set();
            }
        }
示例#13
0
 private PreCleanupReturnCode PreCleanup(IRP irp)
 {
     return cache.CachePreCleanup(irp);
 }
示例#14
0
 private PreCreateReturnCode PreCreate(IRP irp)
 {
     return this.cache.CachePreCreate(irp);
 }
示例#15
0
 private PostWriteReturnCode PostWrite(IRP irp)
 {
     return cache.CacheWriteIRPCompleted(irp);
 }
示例#16
0
 private PostReadReturnCode PostRead(IRP irp)
 {
     return cache.CacheIRPCompleted(irp);
 }
示例#17
0
 public PreCleanupReturnCode CachePreCleanup(IRP irp)
 {
     return PreCleanupReturnCode.FLT_PREOP_SUCCESS_NO_CALLBACK;
 }
示例#18
0
        private void IoFlowRuntimeInternal(uint maxIocpThreads, bool useIocpEx)
        {
            Console.WriteLine("IoFlowRuntime created with {0} iocp threads", maxIocpThreads);

            this.countIocpThreads = maxIocpThreads;

            LockIoFlow = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

            if (this.countIocpThreads < System.Environment.ProcessorCount)
            {
                Console.WriteLine("IoFlowRuntime: Warning: MPL {0} < ProcessorCount {1}",
                                  this.countIocpThreads, System.Environment.ProcessorCount);
            }
            uint HResult;

            TenantId = (uint)Process.GetCurrentProcess().Id;

            //
            // Open FltMgr comms port for asynchronous data exchange with IoFlowUser minifilter driver.
            //
            string strDataPortName = Parameters.DATA_PORT_NAME;

            HResult = FilterConnectCommunicationPort(strDataPortName,     // LPCWSTR lpPortName,
                                                     0,                   // DWORD dwOptions,
                                                     IntPtr.Zero,         // LPCVOID lpContext,
                                                     0,                   // WORD dwSizeOfContext
                                                     IntPtr.Zero,         // LP_SECURITY_ATTRIBUTES lpSecurityAttributes
                                                     out hDataAsyncPort); // HANDLE *hPort

            if (HResult != S_OK)
            {
                Console.WriteLine("IoFlowRuntime failed to contact IoFlow minifilter driver async: check the driver is loaded.");
                Marshal.ThrowExceptionForHR((int)HResult);
            }

            //
            // Open FltMgr comms port for control messages to IoFlowUser minifilter driver.
            // We open the control port for synchronous I/O because we required calls to
            // FilterReplyMessage to complete synchronously when pending IRPs to kernel-mode
            // cancelsafe queue *before* the app calls CompletePendedPreOp() or
            // CompletePendedPostOp() in the days when we supported pending ops.
            //
            string strControlPortName = Parameters.CONTROL_PORT_NAME;

            HResult = FilterConnectCommunicationPort(strControlPortName, // LPCWSTR lpPortName,
                                                     0,                  // DWORD dwOptions,
                                                     IntPtr.Zero,        // LPCVOID lpContext,
                                                     0,                  // WORD dwSizeOfContext
                                                     IntPtr.Zero,        // LP_SECURITY_ATTRIBUTES lpSecurityAttributes
                                                     out hControlPort);  // HANDLE *hPort

            if (HResult != S_OK)
            {
                Marshal.ThrowExceptionForHR((int)HResult);
            }

            //
            // Purge any old state from the minifilter driver.
            //
            DriverReset();

            //
            // Dictionary implements lookup func f(FlowId)=>IoFlow
            //
            DictIoFlow = new Dictionary <uint, IoFlow>();

            //
            // Open I/O completion port for completing async I/O to the minifilter driver.
            //
            hCompletionPort = CreateIoCompletionPort(hDataAsyncPort,
                                                     hCompletionPort,       // HANDLE ExistingCompletionPort
                                                     IntPtr.Zero,           // ULONG_PTR CompletionKey
                                                     (uint)maxIocpThreads); // DWORD NumberOfConcurrentThreads
            if (hCompletionPort == IntPtr.Zero)
            {
                int err = Marshal.GetHRForLastWin32Error();
                Console.WriteLine("CreateIoCompletionPort err={0:X8}", err);
                Marshal.ThrowExceptionForHR(err);
            }

            //
            // Init dict for translating friendly drive names to unfriendly device names.
            // For example on my dev machine "D:" => "\Device\HarddiskVolume4"
            // No .NET support for discovering this, so we scan stdout from "fltmc volume".
            //
            DriveNameToVolumeName = new Dictionary <string, string>();
            Process process = new Process();

            process.StartInfo = new ProcessStartInfo("fltmc.exe", "volumes");
            process.StartInfo.UseShellExecute        = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();
            string s1 = null;

            string[] separators = new string[] { " ", "\t" };
            while ((s1 = process.StandardOutput.ReadLine()) != null)
            {
                if (s1.Length > 1 && s1.Contains(@":"))
                {
                    string[] toks = s1.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                    if (toks.Length > 1 &&
                        toks[0].Length == 2 &&
                        toks[0].Substring(1, 1).Equals(@":") &&
                        toks[1].Length > DeviceHarddiskVolume.Length &&
                        toks[1].ToLower().StartsWith(DeviceHarddiskVolume))
                    {
                        DriveNameToVolumeName.Add(toks[0].ToLower(), toks[1].ToLower());
                    }
                }
            }
            process.WaitForExit();

            VolumeNameToDriveName = DriveNameToVolumeName.ToDictionary(x => x.Value, x => x.Key); //gets the reverse dictionary (this assumes no duplicate values)

            //
            // Allocate pool of statically allocated Irp objects for I/O to/from minifilter driver.
            //
            int countIrps = Parameters.IRP_POOL_SIZE * (int)maxIocpThreads;

            FindIrp  = new Dictionary <IntPtr, IRP>(countIrps);
            irpArray = new IRP[countIrps];
            for (int i = 0; i < irpArray.Length; i++)
            {
                IRP irp = new IRP(this, hDataAsyncPort);
                FindIrp.Add(irp.addrOverlapped, irp);
                irpArray[i] = irp;
                irp.State   = IrpState.Free;
                FreeIrp(irp);
            }

            //
            // Prep the requested number of IO completion worker threads.
            //
            arrayIocpThreads = new Thread[countIocpThreads];
            for (int i = 0; i < countIocpThreads; i++)
            {
                if (useIocpEx)
                {
                    arrayIocpThreads[i] = new Thread(IocpThreadProcEx);
                }
                else
                {
                    arrayIocpThreads[i] = new Thread(IocpThreadProc);
                }
            }

            //
            // Iff a local oktofsagent exists try for a connection for fast sid lookup.
            // Assumes oktofsagent is listening on its default TCP port.
            //
            bridgeOktofsAgent = new BridgeOktofsAgent();
            if (bridgeOktofsAgent.Connect() && bridgeOktofsAgent.SendMessageRegister())
            {
                Console.WriteLine("Registered with local oktofsAgent for fast (account,SID) lookup.");
            }
            else
            {
                bridgeOktofsAgent = null;
            }
        }
示例#19
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;
 }
示例#20
0
 private PreReadReturnCode PreRead(IRP irp)
 {
     return this.cache.CacheIRP(irp);
 }
示例#21
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)
        }
示例#22
0
        /// <summary>
        /// Iocp completion thread using GetQueuedCompletionStatusEx().
        /// You would expect to get benefit from this over GetQueuedCompletionStatus() but in tests
        /// we've not seen that, at least not yet, but you can select it at ctor time hoping we
        /// can find a way to unlock its perf in future.
        /// </summary>
        /// <param name="o"></param>
        private void IocpThreadProcEx(object o)
        {
            try
            {
                Console.WriteLine("IoFlowRuntime: using experimental GetQueuedCompletionStatusEx() thread.");
                //
                // IOCP thread init: start multiple concurrent READ IRPS to driver.
                // Note all I/O must originate on this thread for Win32 CancelIo to work.
                //
                for (int i = 0; i < Parameters.COUNT_IO_READ_MPL; i++)
                {
                    IRP irp = AllocateIrp();
                    irp.StartMiniFilterGetMessage();
                }

                ThreadPriority oldThreadPriority = Thread.CurrentThread.Priority;
                Thread.CurrentThread.Priority = ThreadPriority.Highest;

                //
                // Prep for GetQueuedCompletionStatusEx().
                //
                IntPtr                     lpOverlapped;
                uint                       lpNumberOfBytes;
                uint                       lpCompletionKey;
                OVERLAPPED_ENTRY[]         ArrayOverlappedEntry     = new OVERLAPPED_ENTRY[IocpSizeofOverlappedArray];
                GCHandle                   gcArrayOverlappedEntry   = GCHandle.Alloc(ArrayOverlappedEntry, GCHandleType.Pinned);
                IntPtr                     addrArrayOverlappedEntry = gcArrayOverlappedEntry.AddrOfPinnedObject();
                uint                       NumEntriesRemoved        = 1;
                FLT_PREOP_CALLBACK_STATUS  PreOpResult  = FLT_PREOP_CALLBACK_STATUS.FLT_PREOP_SUCCESS_WITH_CALLBACK;
                FLT_POSTOP_CALLBACK_STATUS PostOpResult = FLT_POSTOP_CALLBACK_STATUS.FLT_POSTOP_FINISHED_PROCESSING;

                //
                // IOCP main loop: think -- {completePrior; flow.Callback(IRP); startNext}.
                //
                while (ShuttingDown == false) // IOCP main loop.
                {
                    //
                    // Block until IoCompletionPort indicates a) I/O completion or b) some signal.
                    //
                    if (GetQueuedCompletionStatusEx(hCompletionPort,
                                                    addrArrayOverlappedEntry,
                                                    IocpSizeofOverlappedArray,
                                                    out NumEntriesRemoved,
                                                    Parameters.IocpTimeoutInfinite, // Parameters.IocpTimeoutMSecs, //WIN32_INFINITE,
                                                    false) == false)
                    {
                        int HResult        = Marshal.GetHRForLastWin32Error();
                        int LastWin32Error = Marshal.GetLastWin32Error();

                        //
                        // Expect to get here when Close() has been called.
                        //
                        const uint THE_HANDLE_IS_INVALID  = 0x80070006; // Not an error.
                        const uint ERROR_ABANDONED_WAIT_0 = 0x800702DF; // Not an error.
                        if ((uint)HResult == THE_HANDLE_IS_INVALID || (uint)HResult == ERROR_ABANDONED_WAIT_0)
                        {
                            break;
                        }

                        //
                        // In absence of I/O load, iocp timeout opt triggers polled queued I/O support.
                        //
                        if (LastWin32Error == WIN32_WAIT_TIMEOUT)
                        {
                            continue;
                        }

                        //
                        // Handle I/O failures. Non-fatal iff timeout or if media disconnected.
                        //
                        if (LastWin32Error == WIN32_ERROR_GEN_FAILURE)
                        {
                            Console.WriteLine("warning: ignored iocp tx status ERROR_GEN_FAILURE");
                            continue;
                        }

                        //
                        // Unexpected error.
                        //
                        Console.WriteLine("LastWin32Error {0} HResult {1:X8}", LastWin32Error, HResult);
                        Marshal.ThrowExceptionForHR((int)HResult);
                    }

                    //
                    // One iteration per entry in array returned from I/O completion port.
                    //
                    for (int i = 0; i < (int)NumEntriesRemoved; i++)
                    {
                        lpOverlapped    = ArrayOverlappedEntry[i].addrOverlapped;
                        lpCompletionKey = (uint)ArrayOverlappedEntry[i].lpCompletionKey.ToInt32();

                        //
                        // Get from native addr of completing OVERLAPPED struct to the associated managed code IRP.
                        //
                        IRP irp = FindIrp[lpOverlapped];

                        irp.CompleteMiniFilterGetMessage();

                        //
                        // Find the IoFlow for this IRP and call the user's callback function.
                        //
                        LockIoFlow.EnterReadLock();
                        irp.IoFlow = DictIoFlow[irp.IoFlowHeader.FlowId];
                        LockIoFlow.ExitReadLock();

                        //
                        // Indicate any late errors for earlier IO indicated on this flow.
                        // These can happen if an error happens in the driver *after* the
                        // filterMgr messaging API has indicated that the reply message has
                        // been successfully delivered to the driver. In priciple the owning
                        // app should also know due to IO failure.
                        //
                        if ((irp.IoFlowHeader.Flags & (uint)HeaderFlags.HeaderFlagLateIoError) != 0)
                        {
                            string msg = "One or more errors reported for earlier IO on flowId ";
                            msg = string.Format("{0} {1} file {2}", msg, irp.IoFlow.FlowId, irp.IoFlow.FileName);
                            throw new ExceptionIoFlow(msg);
                        }

                        //
                        // Throw iff the kmode IRP's buffer is too large for our k2u buffers.
                        // In this case we see incomplete data so any ops on the data are invalid.
                        //
                        if (irp.DataLength > irp.MaxDataLength)
                        {
                            string msg = string.Format("Err irp.DataLength({0}) > k2u buffer size({1})",
                                                       irp.DataLength, irp.MaxDataLength);
                            throw new ExceptionIoFlow(msg);
                        }

                        //
                        // Upcall to user-supplied callback routine.
                        // Note the minifilter only sends IRPs for flows that have registered an appropriate callback routine.
                        //
                        bool IsPreOp = irp.IsPreOp, IsPostOp = !IsPreOp;
                        switch (irp.MajorFunction)
                        {
                        case MajorFunction.IRP_MJ_CREATE:
                        {
                            if (IsPreOp)
                            {
                                PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreCreate(irp);
                            }
                            else
                            {
                                PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostCreate(irp);
                            }
                            break;
                        }

                        case MajorFunction.IRP_MJ_READ:
                        {
                            if (IsPreOp)
                            {
                                PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreRead(irp);
                            }
                            else
                            {
                                PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostRead(irp);
                            }
                            break;
                        }

                        case MajorFunction.IRP_MJ_WRITE:
                        {
                            if (IsPreOp)
                            {
                                PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreWrite(irp);
                            }
                            else
                            {
                                PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostWrite(irp);
                            }
                            break;
                        }

                        case MajorFunction.IRP_MJ_CLEANUP:
                        {
                            if (IsPreOp)
                            {
                                PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreCleanup(irp);
                            }
                            else
                            {
                                PostOpResult = (FLT_POSTOP_CALLBACK_STATUS)irp.IoFlow.PostCleanup(irp);
                            }
                            break;
                        }

                        case MajorFunction.IRP_MJ_LOCK_CONTROL:
                        {
                            if (IsPreOp)
                            {
                                PreOpResult = (FLT_PREOP_CALLBACK_STATUS)irp.IoFlow.PreLockControl(irp);
                            }
                            else
                            {
                                throw new NotImplementedException(String.Format("irp.IoFlow.FlowId {0} PostLockControl callback not supported.",
                                                                                irp.IoFlow.FlowId));
                            }
                            break;
                        }

                        default:
                            throw new ApplicationException("should never get here.");
                        }

                        irp.SetStateCallbackReturned();
                        irp.IoFlowHeader.FilterReplyHeader.Status = 0;
                        irp.IoFlowHeader.Resultcode = (irp.IsPreOp ? (uint)PreOpResult : (uint)PostOpResult);

#if UseReplyAndGetNext
                        //
                        // App is done with this IRP.
                        // Send reply to minifilter driver and restart next upcall on same IRP.
                        //
                        irp.MiniFilterReplyAndGetNext(hDataAsyncPort, hControlPort);
#else // UseReplyAndGetNext
                        //
                        // Send reply to our minifilter driver.
                        //
                        irp.MiniFilterReplyMessage(hDataAsyncPort, hControlPort);

                        //
                        // The IRP is no longer in use by app - we can restart next upcall request on same IRP.
                        //
                        irp.StartMiniFilterGetMessage();
#endif // UseReplyAndGetNext
                    } //for (int i = 0; i < (int)NumEntriesRemoved; i++)
                } // while (ShuttingDown == false) // IOCP main loop.

                //
                // Shut down.
                //
                CancelIo(hDataAsyncPort);
            }
            catch (ThreadInterruptedException CaughtException)
            {
                if (Interlocked.Decrement(ref CountIocpThreadsRunning) == 0)
                {
                    LastThreadTerminated.Set();
                }
                if (ShuttingDown)
                {
                    return;
                }
                throw new ThreadInterruptedException(null, CaughtException);
            }
            if (Interlocked.Decrement(ref CountIocpThreadsRunning) == 0)
            {
                LastThreadTerminated.Set();
            }
        }
示例#23
0
 private PreWriteReturnCode PreWrite(IRP irp)
 {
     return cache.CacheWriteIRP(irp);
 }
示例#24
0
        private void IoFlowRuntimeInternal(uint maxIocpThreads, bool useIocpEx)
        {
            Console.WriteLine("IoFlowRuntime created with {0} iocp threads", maxIocpThreads);

            this.countIocpThreads = maxIocpThreads;

            LockIoFlow = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

            if (this.countIocpThreads < System.Environment.ProcessorCount)
                Console.WriteLine("IoFlowRuntime: Warning: MPL {0} < ProcessorCount {1}",
                    this.countIocpThreads, System.Environment.ProcessorCount);
            uint HResult;
            TenantId = (uint)Process.GetCurrentProcess().Id;

            //
            // Open FltMgr comms port for asynchronous data exchange with IoFlowUser minifilter driver.
            //
            string strDataPortName = Parameters.DATA_PORT_NAME;

            HResult = FilterConnectCommunicationPort(strDataPortName,      // LPCWSTR lpPortName,
                                                     0,                    // DWORD dwOptions,
                                                     IntPtr.Zero,          // LPCVOID lpContext,
                                                     0,                    // WORD dwSizeOfContext
                                                     IntPtr.Zero,          // LP_SECURITY_ATTRIBUTES lpSecurityAttributes
                                                     out hDataAsyncPort); // HANDLE *hPort

            if (HResult != S_OK)
            {
                Console.WriteLine("IoFlowRuntime failed to contact IoFlow minifilter driver async: check the driver is loaded.");
                Marshal.ThrowExceptionForHR((int)HResult);
            }

            //
            // Open FltMgr comms port for control messages to IoFlowUser minifilter driver.
            // We open the control port for synchronous I/O because we required calls to
            // FilterReplyMessage to complete synchronously when pending IRPs to kernel-mode
            // cancelsafe queue *before* the app calls CompletePendedPreOp() or
            // CompletePendedPostOp() in the days when we supported pending ops.
            //
            string strControlPortName = Parameters.CONTROL_PORT_NAME;

            HResult = FilterConnectCommunicationPort(strControlPortName, // LPCWSTR lpPortName,
                                                     0,                  // DWORD dwOptions,
                                                     IntPtr.Zero,        // LPCVOID lpContext,
                                                     0,                  // WORD dwSizeOfContext
                                                     IntPtr.Zero,        // LP_SECURITY_ATTRIBUTES lpSecurityAttributes
                                                     out hControlPort);  // HANDLE *hPort

            if (HResult != S_OK)
            {
                Marshal.ThrowExceptionForHR((int)HResult);
            }

            //
            // Purge any old state from the minifilter driver.
            //
            DriverReset();

            //
            // Dictionary implements lookup func f(FlowId)=>IoFlow
            //
            DictIoFlow = new Dictionary<uint, IoFlow>();

            //
            // Open I/O completion port for completing async I/O to the minifilter driver.
            //
            hCompletionPort = CreateIoCompletionPort(hDataAsyncPort,
                                                     hCompletionPort,         // HANDLE ExistingCompletionPort
                                                     IntPtr.Zero,             // ULONG_PTR CompletionKey
                                                     (uint)maxIocpThreads); // DWORD NumberOfConcurrentThreads
            if (hCompletionPort == IntPtr.Zero)
            {
                int err = Marshal.GetHRForLastWin32Error();
                Console.WriteLine("CreateIoCompletionPort err={0:X8}", err);
                Marshal.ThrowExceptionForHR(err);
            }

            //
            // Init dict for translating friendly drive names to unfriendly device names.
            // For example on my dev machine "D:" => "\Device\HarddiskVolume4"
            // No .NET support for discovering this, so we scan stdout from "fltmc volume".
            //
            DriveNameToVolumeName = new Dictionary<string, string>();
            Process process = new Process();
            process.StartInfo = new ProcessStartInfo("fltmc.exe", "volumes");
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();
            string s1 = null;
            string[] separators = new string[] { " ", "\t" };
            while ((s1 = process.StandardOutput.ReadLine()) != null)
            {
                if (s1.Length > 1 && s1.Contains(@":"))
                {
                    string[] toks = s1.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                    if (toks.Length > 1 &&
                        toks[0].Length == 2 &&
                        toks[0].Substring(1, 1).Equals(@":") &&
                        toks[1].Length > DeviceHarddiskVolume.Length &&
                        toks[1].ToLower().StartsWith(DeviceHarddiskVolume))
                    {
                        DriveNameToVolumeName.Add(toks[0].ToLower(), toks[1].ToLower());
                    }
                }
            }
            process.WaitForExit();

            VolumeNameToDriveName = DriveNameToVolumeName.ToDictionary(x => x.Value, x => x.Key); //gets the reverse dictionary (this assumes no duplicate values)

            //
            // Allocate pool of statically allocated Irp objects for I/O to/from minifilter driver.
            //
            int countIrps = Parameters.IRP_POOL_SIZE * (int)maxIocpThreads;
            FindIrp = new Dictionary<IntPtr, IRP>(countIrps);
            irpArray = new IRP[countIrps];
            for (int i = 0; i < irpArray.Length; i++)
            {
                IRP irp = new IRP(this, hDataAsyncPort);
                FindIrp.Add(irp.addrOverlapped, irp);
                irpArray[i] = irp;
                irp.State = IrpState.Free;
                FreeIrp(irp);
            }

            //
            // Prep the requested number of IO completion worker threads.
            //
            arrayIocpThreads = new Thread[countIocpThreads];
            for (int i = 0; i < countIocpThreads; i++)
            {
                if (useIocpEx)
                    arrayIocpThreads[i] = new Thread(IocpThreadProcEx);
                else
                    arrayIocpThreads[i] = new Thread(IocpThreadProc);
            }

            //
            // Iff a local oktofsagent exists try for a connection for fast sid lookup.
            // Assumes oktofsagent is listening on its default TCP port.
            //
            bridgeOktofsAgent = new BridgeOktofsAgent();
            if (bridgeOktofsAgent.Connect() && bridgeOktofsAgent.SendMessageRegister())
                Console.WriteLine("Registered with local oktofsAgent for fast (account,SID) lookup.");
            else
                bridgeOktofsAgent = null;

        }
示例#25
0
        public void FreeIrp(IRP irp)
        {
            if (irp.State != IrpState.Free)
                throw new ApplicationException("FreeIrp() : Irp!=Free.");
            irp.State = IrpState.Pool;

            lock (IrpPoolLock)
            {
                Debug.Assert(irp.Next == null, "FreeIrp expected single irp, got multi-irp chain");
                irp.Next = FreeIrpPool;
                FreeIrpPool = irp;
                irp.IoFlow = null;
                countFreeIrpList++;
            }
        }
示例#26
0
文件: IoFlow.cs 项目: sibaoli/Moirai
 private PostCleanupReturnCode InvalidPostCleanup(IRP irp)
 {
     throw new NotImplementedException(String.Format("FlowId {0} PostCleanup callback not registered.", FlowId));
 }
示例#27
0
        //
        // Obtain one Irp object from free Irp list.
        //
        internal IRP AllocateIrp()
        {
            IRP irp = null;

            lock (IrpPoolLock)
            {
                if (FreeIrpPool != null)
                {
                    irp = FreeIrpPool;
                    FreeIrpPool = FreeIrpPool.Next;
                    countFreeIrpList--;
                }
            }

            if (irp == null) // Expected to fail, with some diags.
                throw new ApplicationException("Free Irp pool exhausted");

            irp.Next = irp.Prev = null;
            irp.State = IrpState.Free;
            return irp;
        }
示例#28
0
 public void Enqueue(IRP irp)
 {
     lock (IrpList)
     {
         IrpList.Enqueue(irp);
     }
 }
示例#29
0
 private PostWriteReturnCode PostWrite(IRP irp)
 {
     //return PostWriteReturnCode.FLT_POSTOP_FINISHED_PROCESSING;
     return cache.CacheWriteIRPCompleted(irp);
     //return PostWriteReturnCode.FLT_POSTOP_FINISHED_PROCESSING;
 }
示例#30
0
 private PreWriteReturnCode InvalidPreWrite(IRP irp)
 {
     throw new NotImplementedException(String.Format("FlowId {0} PreWrite callback not registered.", FlowId));
 }
示例#31
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;
        }