Exemple #1
0
 private FileCacheElement getFileCacheElement(IoFlow InFlow, string InFileName, byte[] InData, UInt64 InFileOffset, uint copyOffset, uint InDataLength)
 {
     FileCacheElement elemReturn;
     bool reused = false;
     lock (this.freeFileCacheElements)
     {
         if (this.freeFileCacheElements.Count > 0){
             LinkedListNode<FileCacheElement> llNode = this.freeFileCacheElements.First;
             this.freeFileCacheElements.Remove(llNode);
             elemReturn = llNode.Value;
             reused=true;
         } else {
             elemReturn = new FileCacheElement(InFlow, InFileName, InData, InFileOffset, copyOffset, InDataLength);
         }
     }
     if (reused)
     {
         Debug.Assert(elemReturn.DataLength == InDataLength);
         elemReturn.fileName = InFileName;
         elemReturn.Flow = InFlow;
         // keep data elemReturn.Data = null;
         elemReturn.FileOffset = InFileOffset;
         elemReturn.DataLength = InDataLength;
         elemReturn.Dirty = false;
         elemReturn.nodeInList = null;
         elemReturn.nodeInDirtyList = null;
         if (InData != null)
         {
             Buffer.BlockCopy(InData, (int)copyOffset, elemReturn.Data, 0, (int)InDataLength);
         }
     }
     return elemReturn;
 }
        public LinkedListNode<FileCacheElement> nodeInList; // location in LRU linked list

        #endregion Fields

        #region Constructors

        //
        // Constructor.
        // Copies InData locally
        public FileCacheElement(IoFlow InFlow, string InFileName, byte[] InData, UInt64 InFileOffset, uint copyOffset, uint InDataLength)
        {
            LockObj     = new object();
            fileName = InFileName;
            Flow        = InFlow;
            Data        = null;
            FileOffset  = InFileOffset;
            DataLength  = InDataLength;
            Dirty = false;
            nodeInList = null;
            nodeInDirtyList = null;
            nodeInFreeFileCacheList = null;
            if (InData != null)
            {
                Data = new byte[InDataLength];
                Buffer.BlockCopy(InData, (int)copyOffset, Data, 0, (int)InDataLength);
                //Array.Copy(InData, copyOffset, Data, 0, InDataLength);
            }
        }
Exemple #3
0
        /// <summary>
        /// Creates an IoFlow structure in runtime and corresponding structures (Flow and RAP)
        /// in the driver.
        /// </summary>
        /// <param name="accountName">A valid NT security account of form EUROPE\gregos.</param>
        /// <param name="fileName">A valid file name of form C:\tmp\gregos.txt or \Device\HarddiskVolumen\tmp\gregos.txt</param>
        /// <param name="callbackPreCreate">Callback func to invoke for IRPs on PreCreate path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostCreate">Callback func to invoke for IRPs on PostCreate path.
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="callbackPreRead">Callback func to invoke for IRPs on PreRead path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostRead">Callback func to invoke for IRPs on PostRead path
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="callbackPreWrite">Callback func to invoke for IRPs on PreWrite path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostWrite">Callback func to invoke for IRPs on PostWrite path.
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="callbackPreCleanup">Callback func to invoke for IRPs on PreCleanup path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostCreate">Callback func to invoke for IRPs on PostCleanup path.
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="context">Some object reference of your own for additional state associated with thie IoFlow</param>
        /// <returns></returns>
        public IoFlow CreateFlow(
            uint flowId,
            string accountName,
            string fileName,
            CallbackPreCreate callbackPreCreate,
            CallbackPostCreate callbackPostCreate,
            CallbackPreRead callbackPreRead,
            CallbackPostRead callbackPostRead,
            CallbackPreWrite callbackPreWrite,
            CallbackPostWrite callbackPostWrite,
            CallbackPreCleanup callbackPreCleanup,
            CallbackPostCleanup callbackPostCleanup,
            CallbackPreLockControl callbackPreLockControl,
            object context)
        {
            IoFlow ioFlow = null;

            //
            // Validate fileName, transforming drive letters to volume names.
            //
            fileName = fileName.ToLower();
            string origFilename = fileName;

            if (string.IsNullOrEmpty(fileName) || string.IsNullOrWhiteSpace(fileName))
            {
                throw new ArgumentNullException("fileName");
            }
            else if (fileName.Length < 2)
            {
                throw new ArgumentOutOfRangeException("fileName", "too short");
            }

            else if (fileName.Substring(1, 1).Equals(@":"))
            {
                string driveName  = fileName.Substring(0, 2); // think "C:"
                string deviceName = "";
                if (DriveNameToVolumeName.TryGetValue(driveName, out deviceName))
                {
                    fileName = deviceName + fileName.Substring(2);
                }
            }
            if (fileName.ToLower().StartsWith(DeviceMup.ToLower()))
            {
                Debug.Assert(0 == 1); //XXXIS: don't use \device\mup in the paths in the config file
            }
            else if (fileName.ToLower().StartsWith(RemoteDeviceSlash.ToLower()))
            {
                fileName = DeviceMup + fileName;
            }
            else if (fileName.ToLower().StartsWith(RemoteDeviceDoubleSlash.ToLower()))
            {
                fileName = DeviceMup + fileName.Substring(1);
            }
            else if (!fileName.ToLower().StartsWith(DeviceHarddiskVolume))
            {
                throw new ArgumentException(@"must be format e.g. C: or \Device\HarddiskVolume", "fileName");
            }

#if gregos // "XXXET: not used, just for testing" crashes on launch due to FileToBlock.dll not found
            // for lock drives, test physical offset code
            // XXXET: not used, just for testing
            if (fileName.Substring(1, 1).Equals(@":") ||
                origFilename.ToLower().StartsWith(DeviceHarddiskVolume))
            {
                if (origFilename.ToLower().StartsWith(DeviceHarddiskVolume))
                {
                    origFilename = getDriveLetterFileName(origFilename);
                }
                Int64 poffset = FileToBlock.GetPhysicalOffset(origFilename);
                Console.WriteLine("File {0} starts in physical offset {1}", origFilename, poffset);
            }
#endif
            //
            // Get SID for the given account name.
            //
            SecurityIdentifier sid = SidLookup(accountName);

            //
            // Create IoFlow object.
            //
            LockIoFlow.EnterWriteLock();
            try
            {
                ioFlow = new IoFlow(flowId, context, accountName, sid, fileName,
                                    callbackPreCreate, callbackPostCreate,
                                    callbackPreRead, callbackPostRead,
                                    callbackPreWrite, callbackPostWrite,
                                    callbackPreCleanup, callbackPostCleanup,
                                    callbackPreLockControl);
                DictIoFlow.Add(flowId, ioFlow);
                Driver.CreateFlow.Request(hControlPort, TenantId, flowId, ioFlow.Flags);
                Driver.CreateRap.Request(hControlPort, TenantId, flowId, accountName, sid, fileName);
            }
            catch (ExceptionIoFlow)
            {
                DriverReset();
                throw;
            }
            LockIoFlow.ExitWriteLock();

            return(ioFlow);
        }
        /// <summary>
        /// Creates an IoFlow structure in runtime and corresponding structures (Flow and RAP)
        /// in the driver.
        /// </summary>
        /// <param name="accountName">A valid NT security account of form EUROPE\gregos.</param>
        /// <param name="fileName">A valid file name of form C:\tmp\gregos.txt or \Device\HarddiskVolumen\tmp\gregos.txt</param>
        /// <param name="callbackPreCreate">Callback func to invoke for IRPs on PreCreate path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostCreate">Callback func to invoke for IRPs on PostCreate path.
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="callbackPreRead">Callback func to invoke for IRPs on PreRead path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostRead">Callback func to invoke for IRPs on PostRead path
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="callbackPreWrite">Callback func to invoke for IRPs on PreWrite path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostWrite">Callback func to invoke for IRPs on PostWrite path.
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="callbackPreCleanup">Callback func to invoke for IRPs on PreCleanup path.
        /// Corresponds to an IFS Minifilter PRE_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551109(v=vs.85).aspx</param>
        /// <param name="callbackPostCreate">Callback func to invoke for IRPs on PostCleanup path.
        /// Corresponds to an IFS Minifilter POST_OPERATION callback ref http://msdn.microsoft.com/en-us/library/windows/hardware/ff551107(v=vs.85).aspx</param>
        /// <param name="context">Some object reference of your own for additional state associated with thie IoFlow</param>
        /// <returns></returns>
        public IoFlow CreateFlow(
            uint flowId,
            string accountName,
            string fileName,
            CallbackPreCreate callbackPreCreate,
            CallbackPostCreate callbackPostCreate,
            CallbackPreRead callbackPreRead,
            CallbackPostRead callbackPostRead,
            CallbackPreWrite callbackPreWrite,
            CallbackPostWrite callbackPostWrite,
            CallbackPreCleanup callbackPreCleanup,
            CallbackPostCleanup callbackPostCleanup,
            CallbackPreLockControl callbackPreLockControl,
            object context)
        {
            IoFlow ioFlow = null;

            //
            // Validate fileName, transforming drive letters to volume names.
            //
            fileName = fileName.ToLower();
            string origFilename = fileName;
            if (string.IsNullOrEmpty(fileName) || string.IsNullOrWhiteSpace(fileName))
                throw new ArgumentNullException("fileName");
            else if (fileName.Length < 2)
                throw new ArgumentOutOfRangeException("fileName", "too short");

            else if (fileName.Substring(1, 1).Equals(@":"))
            {
                string driveName = fileName.Substring(0, 2);  // think "C:"
                string deviceName = "";
                if (DriveNameToVolumeName.TryGetValue(driveName, out deviceName))
                    fileName = deviceName + fileName.Substring(2);
            }
            if (fileName.ToLower().StartsWith(DeviceMup.ToLower()))
            {
                Debug.Assert(0 == 1); //XXXIS: don't use \device\mup in the paths in the config file   
            }
            else if (fileName.ToLower().StartsWith(RemoteDeviceSlash.ToLower()))
            {
                fileName = DeviceMup + fileName;
            }
            else if (fileName.ToLower().StartsWith(RemoteDeviceDoubleSlash.ToLower()))
            {
                fileName = DeviceMup + fileName.Substring(1);
            }
            else if (!fileName.ToLower().StartsWith(DeviceHarddiskVolume))
                throw new ArgumentException(@"must be format e.g. C: or \Device\HarddiskVolume", "fileName");

#if gregos // "XXXET: not used, just for testing" crashes on launch due to FileToBlock.dll not found
            // for lock drives, test physical offset code
            // XXXET: not used, just for testing
            if (fileName.Substring(1, 1).Equals(@":") ||
                origFilename.ToLower().StartsWith(DeviceHarddiskVolume))
            {
                if (origFilename.ToLower().StartsWith(DeviceHarddiskVolume))
                {
                    origFilename = getDriveLetterFileName(origFilename);
                }
                Int64 poffset = FileToBlock.GetPhysicalOffset(origFilename);
                Console.WriteLine("File {0} starts in physical offset {1}", origFilename, poffset);
            }
#endif
            //
            // Get SID for the given account name.
            //
            SecurityIdentifier sid = SidLookup(accountName);

            //
            // Create IoFlow object.
            //
            LockIoFlow.EnterWriteLock();
            try
            {
                ioFlow = new IoFlow(flowId, context, accountName, sid, fileName,
                                    callbackPreCreate, callbackPostCreate,
                                    callbackPreRead, callbackPostRead,
                                    callbackPreWrite, callbackPostWrite,
                                    callbackPreCleanup, callbackPostCleanup,
                                    callbackPreLockControl);
                DictIoFlow.Add(flowId, ioFlow);
                Driver.CreateFlow.Request(hControlPort, TenantId, flowId, ioFlow.Flags);
                Driver.CreateRap.Request(hControlPort, TenantId, flowId, accountName, sid, fileName);
            }
            catch (ExceptionIoFlow)
            {
                DriverReset();
                throw;
            }
            LockIoFlow.ExitWriteLock();

            return ioFlow;
        }
        private void parseControllerCommandString(IoFlow flow, string controllerCommand)
        {
            string[] commandStringSeparators = new string[] { " ", "\t" };
            char[] tokenSeparator = new char[] { '=' };
            string[] commandTokens = controllerCommand.Split(commandStringSeparators, StringSplitOptions.RemoveEmptyEntries);

            if (commandTokens.Length > 0)
            {
                Console.WriteLine("CallbackMessageIoFlowUpdate({0},{1})", flow.FlowId, controllerCommand);
                foreach (string token in commandTokens)
                {
                    string param = token.Split(tokenSeparator)[0];
                    string value = token.Split(tokenSeparator)[1];

                    //Switch to the appropriate handler
                    switch (param)
                    {
                        case "changeCacheSize":
                            this.cache.CacheSetFlowSize(flow.FlowId, Convert.ToUInt64(value));
                            break;
                        case "changeWritePolicy":
                            switch (value)
                            {
                                case "write-through":
                                    this.cache.SetCacheWritePolicy(CacheWritePolicy.WriteThrough);
                                    break;
                                default:
                                    Console.WriteLine("Command value invalid");
                                    Debug.Assert(0 == 1);
                                    break;
                            }
                            break;
                        case "changeOpPolicy":
                            string op = value.Split(',')[0];
                            string policy = value.Split(',')[1];
                            switch (op)
                            {
                                case "W":
                                    switch (policy)
                                    {
                                        case "yes":
                                            this.cache.SetCacheWriteBuffering(CacheWriteBuffer.Cache); //Cache writes
                                            break;
                                        case "no":
                                            this.cache.SetCacheWriteBuffering(CacheWriteBuffer.noCache); //Don't cache writes
                                            break;
                                        default:
                                            Console.WriteLine("Command value invalid");
                                            Debug.Assert(0 == 1);
                                            break;
                                    }
                                    break;
                                case "R":
                                    //Nothing for now; add fine-grained control to cache/not cache reads here
                                    break;
                                default:
                                    Console.WriteLine("Command value invalid");
                                    Debug.Assert(0 == 1);
                                    break;
                            }
                            break;
                        default:
                            Console.WriteLine("Controller command invalid");
                            Debug.Assert(0 == 1);
                            break;
                    }
                }
            }
        }