const NDAS_CONTENT_ENCRYPT* CNdasLogicalDevice::GetContentEncrypt() { CRefObjPtr<CNdasUnitDevice> pPrimaryUnitDevice = GetUnitDevice(0); if (NULL == pPrimaryUnitDevice.p) { return NULL; } if (NDAS_UNITDEVICE_TYPE_DISK != pPrimaryUnitDevice->GetType()) { return NULL; } CNdasUnitDiskDevice* pUnitDiskDevice = reinterpret_cast<CNdasUnitDiskDevice*>(pPrimaryUnitDevice.p); m_contentEncrypt = pUnitDiskDevice->GetEncryption(); return &m_contentEncrypt; }
BOOL CNdasLogicalDevice::PlugIn(ACCESS_MASK requestingAccess) { ximeta::CAutoLock autolock(this); BOOL fPSWriteShare = IsPSWriteShareCapable(); BOOL fSuccess = cpCheckPlugInCondition(requestingAccess); if (!fSuccess) { return FALSE; } // // Plug In // - NDAS Controller // CRefObjPtr<CNdasUnitDevice> pPrimaryUnitDevice = GetUnitDevice(0); if (NULL == pPrimaryUnitDevice.p) { SetLastDeviceError(NDAS_LOGICALDEVICE_ERROR_MISSING_MEMBER); ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_MEMBER_MISSING); return FALSE; } CRefObjPtr<CNdasDevice> pDevice = pPrimaryUnitDevice->GetParentDevice(); if (NULL == pDevice.p) { SetLastDeviceError(NDAS_LOGICALDEVICE_ERROR_MISSING_MEMBER); ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_MEMBER_MISSING); } // // Max DVD Instance (Global Instance) Constraint // // Do not allow local host to have multiple DVD devices // with Write Access. // I-O Data's request? // #if NDAS_FEATURE_DONOT_ALLOW_MULTIPLE_DVD_RW_INSTANCES if (NDAS_LOGICALDEVICE_TYPE_DVD == GetType()) { fSuccess = cpCheckPlugInCondForDVD(requestingAccess); if (!fSuccess) { // SetLastError is set by the pCheckPlugInCondForDVD return FALSE; } } #endif // // Resetting an event always succeeds if the handle is valid // fSuccess = ::ResetEvent(m_hDisconnectedEvent); _ASSERTE(fSuccess); fSuccess = ::ResetEvent(m_hAlarmEvent); _ASSERTE(fSuccess); // // Add Target // - Add a disk device to the NDAS controller // SIZE_T cbAddTargetDataSize = sizeof(LANSCSI_ADD_TARGET_DATA) - sizeof(LSBUS_UNITDISK) + GetUnitDeviceCount() * sizeof(LSBUS_UNITDISK); PLANSCSI_ADD_TARGET_DATA pAddTargetData = (PLANSCSI_ADD_TARGET_DATA) ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, cbAddTargetDataSize); if (NULL == pAddTargetData) { // TODO: Out of memory return FALSE; } // automatically free the heap when it goes out of the scope AutoProcessHeap autoHeap = pAddTargetData; UCHAR ucTargetType = pConvertToLSBusTargetType(m_logicalDeviceGroup.Type); pAddTargetData->ulSize = cbAddTargetDataSize; pAddTargetData->ulSlotNo = m_NdasScsiLocation.SlotNo; pAddTargetData->ulTargetBlocks = 0; // initialization and will be added pAddTargetData->DesiredAccess = requestingAccess; pAddTargetData->ulNumberOfUnitDiskList = GetUnitDeviceCount(); pAddTargetData->ucTargetType = ucTargetType; // if PSWriteShare is not capable, we should specify the LUROption // to turn off the PSWriteShare explicitly. DWORD dwLUROptions = 0; { BOOL fConfigured = _NdasSystemCfg.GetValueEx( _T("ndassvc"), _T("LUROptions"), &dwLUROptions); if (!fConfigured) { // revert to default for safety dwLUROptions = 0; } } if (!fPSWriteShare) { dwLUROptions |= LUROPTION_OFF_WRITESHARE_PS; dwLUROptions &= ~(LUROPTION_ON_WRITESHARE_PS); } pAddTargetData->LurOptions = dwLUROptions; // Set Content Encryption from the primary unit device // (Only for Disk Devices) if (NDAS_UNITDEVICE_TYPE_DISK == pPrimaryUnitDevice->GetType()) { CNdasUnitDiskDevice* pUnitDiskDevice = reinterpret_cast<CNdasUnitDiskDevice*>(pPrimaryUnitDevice.p); CONST NDAS_CONTENT_ENCRYPT& encrypt = pUnitDiskDevice->GetEncryption(); pAddTargetData->CntEcrKeyLength = encrypt.KeyLength; pAddTargetData->CntEcrMethod = encrypt.Method; ::CopyMemory( pAddTargetData->CntEcrKey, encrypt.Key, encrypt.KeyLength); } if (NDASSCSI_TYPE_DISK_RAID1 == ucTargetType || NDASSCSI_TYPE_DISK_RAID4 == ucTargetType) { CNdasUnitDiskDevice* pUnitDiskDevice = reinterpret_cast<CNdasUnitDiskDevice*>(pPrimaryUnitDevice.p); _ASSERTE(NULL != pUnitDiskDevice->GetAddTargetInfo()); ::CopyMemory( &pAddTargetData->RAID_Info, pUnitDiskDevice->GetAddTargetInfo(), sizeof(INFO_RAID)); if (0 == pAddTargetData->RAID_Info.SectorsPerBit) { ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_INVALID_BIND_INFORMATION); return FALSE; } } for (DWORD i = 0; i < GetUnitDeviceCount(); ++i) { CRefObjPtr<CNdasUnitDevice> pUnitDevice = GetUnitDevice(i); if (NULL == pUnitDevice.p) { SetLastDeviceError(NDAS_LOGICALDEVICE_ERROR_MISSING_MEMBER); ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_MEMBER_MISSING); return FALSE; } CRefObjPtr<CNdasDevice> pDevice = pUnitDevice->GetParentDevice(); _ASSERTE(NULL != pDevice.p); PLSBUS_UNITDISK pud = &pAddTargetData->UnitDiskList[i]; ::CopyMemory( pud->Address.Node, pDevice->GetRemoteLpxAddress().Node, sizeof(pud->Address.Node)); pud->Address.Port = htons(NDAS_DEVICE_LPX_PORT); C_ASSERT( sizeof(pud->NICAddr.Node) == sizeof(pDevice->GetLocalLpxAddress().Node)); ::CopyMemory( pud->NICAddr.Node, pDevice->GetLocalLpxAddress().Node, sizeof(pud->NICAddr.Node)); pud->NICAddr.Port = htons(0); // should be zero pud->iUserID = pUnitDevice->GetDeviceUserID(requestingAccess); pud->iPassword = pUnitDevice->GetDevicePassword(); pud->ulUnitBlocks = pUnitDevice->GetUserBlockCount(); pud->ulPhysicalBlocks = pUnitDevice->GetPhysicalBlockCount(); pud->ucUnitNumber = pUnitDevice->GetUnitNo(); pud->ucHWType = pDevice->GetHWType(); pud->ucHWVersion = pDevice->GetHWVersion(); pud->IsWANConnection = FALSE; // // Set Reconnect Retry Count, Retry Interval // if overridden by the user // // default: // ReconnTrial = 19, ReconnInterval = 3000 // // reddotnet: (will be set by the installer) // ReconnTrial = 2, ReconnInterval = 3000 // { BOOL fOverride = FALSE; BOOL fConfigured = _NdasSystemCfg.GetValueEx( _T("ndassvc"), _T("OverrideLogDevReconnect"), &fOverride); if (!fConfigured) { fOverride = FALSE; } if (fOverride) { static const DWORD LOGDEV_RECONNECT_DEFAULT = 19; static const DWORD LOGDEV_RECONNECT_MAX = 19; DWORD dwReconnect = LOGDEV_RECONNECT_DEFAULT; fConfigured = _NdasSystemCfg.GetValueEx( _T("ndassvc"), _T("LogDevReconnect"), &dwReconnect); if (!fConfigured || dwReconnect > LOGDEV_RECONNECT_MAX) { dwReconnect = LOGDEV_RECONNECT_DEFAULT; } static const DWORD LOGDEV_RECONNECT_INTERVAL_DEFAULT = 3000; static const DWORD LOGDEV_RECONNECT_INTERVAL_MAX = 60000; DWORD dwReconnectInterval = LOGDEV_RECONNECT_INTERVAL_DEFAULT; fConfigured = _NdasSystemCfg.GetValueEx( _T("ndassvc"), _T("LogDevReconnectInterval"), &dwReconnectInterval); if (!fConfigured || dwReconnectInterval > LOGDEV_RECONNECT_INTERVAL_MAX) { dwReconnectInterval = LOGDEV_RECONNECT_INTERVAL_DEFAULT; } pud->LurnOptions |= LURNOPTION_SET_RECONNECTION; pud->ReconnTrial = dwReconnect; pud->ReconnInterval = dwReconnectInterval; } } // // Add Target Info // /* if (NDASSCSI_TYPE_DISK_RAID1 == ucTargetType) { CNdasUnitDiskDevice* pUnitDiskDevice = reinterpret_cast<CNdasUnitDiskDevice*>(pUnitDevice.p); _ASSERTE(NULL != pUnitDiskDevice->GetAddTargetInfo()); ::CopyMemory( &pud->RAID_Info, pUnitDiskDevice->GetAddTargetInfo(), sizeof(INFO_RAID)); if (0 == pud->RAID_Info.SectorsPerBit) { ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_INVALID_BIND_INFORMATION); return FALSE; } } else if(NDASSCSI_TYPE_DISK_RAID4 == ucTargetType) { CNdasUnitDiskDevice* pUnitDiskDevice = reinterpret_cast<CNdasUnitDiskDevice*>(pUnitDevice.p); _ASSERTE(NULL != pUnitDiskDevice->GetAddTargetInfo()); ::CopyMemory( &pud->RAID_Info, pUnitDiskDevice->GetAddTargetInfo(), sizeof(INFO_RAID)); if (0 == pud->RAID_Info.SectorsPerBit) { ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_INVALID_BIND_INFORMATION); return FALSE; } } */ if (NDAS_UNITDEVICE_TYPE_DISK == pUnitDevice->GetType()) { CNdasUnitDiskDevice* pUnitDiskDevice = reinterpret_cast<CNdasUnitDiskDevice*>(pUnitDevice.p); // // check if last DIB information is same with current one // if(!pUnitDiskDevice->HasSameDIBInfo()) { pDevice->InvalidateUnitDevice(pUnitDevice->GetUnitNo()); ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_MODIFIED_BIND_INFORMATION); return FALSE; } // // check if bitmap status in RAID 1, 4. Do not plug in // #ifdef __DO_NOT_MOUNT_CORRUPTED_RAID__ // now driver supports recover on mount if (NDAS_UNITDEVICE_DISK_TYPE_RAID1 == pUnitDiskDevice->GetSubType().DiskDeviceType || NDAS_UNITDEVICE_DISK_TYPE_RAID4 == pUnitDiskDevice->GetSubType().DiskDeviceType) { if (!pUnitDiskDevice->IsBitmapClean()) { ::SetLastError(NDASHLPSVC_ERROR_NDAS_LOGICALDEVICE_CORRUPTED_BIND_INFORMATION); return FALSE; } } #endif // // Done checking plug in condition // } } // // Check Multiple Write Access Compatibility // if (GENERIC_WRITE & requestingAccess) { DWORD dwMaxNDFSCompatCheck = 1; if (m_fDisconnected) { // On disconnection (other than power failure), // they may exist an inactive R/W connection at the NDAS device. // In such case, no host will reply to NDFS Compatibility Check. // As an workaround for that we try NDFS Compatibility Check // more than once if failed. static const DWORD MAX_NDFS_COMPAT_CHECK_DEFAULT = 10; static const DWORD MAX_NDFS_COMPAT_CHECK_MAX = 60; fSuccess = _NdasSystemCfg.GetValueEx( _T("ndassvc"), _T("MaxWriteAccessCheck"), &dwMaxNDFSCompatCheck); if (!fSuccess || dwMaxNDFSCompatCheck > MAX_NDFS_COMPAT_CHECK_MAX) { dwMaxNDFSCompatCheck = MAX_NDFS_COMPAT_CHECK_DEFAULT; } } for (DWORD i = 0; i < dwMaxNDFSCompatCheck; ++i) { fSuccess = IsWriteAccessAllowed(fPSWriteShare, pPrimaryUnitDevice); if (fSuccess) { break; } } if (!fSuccess) { return FALSE; } } // After this, we used up a Disconnected flag, so we can clear it. m_fDisconnected = FALSE; pAddTargetData->ulTargetBlocks = GetUserBlockCount(); DWORD dwMaxRequestBlocksPerUnit = cpGetMaxRequestBlocks(); DWORD dwMaxRequestBlocks; // use max of MBR switch(GetType()) { case NDAS_LOGICALDEVICE_TYPE_DISK_RAID0: dwMaxRequestBlocks = dwMaxRequestBlocksPerUnit * GetUnitDeviceCountInRaid(); break; case NDAS_LOGICALDEVICE_TYPE_DISK_RAID4: dwMaxRequestBlocks = dwMaxRequestBlocksPerUnit * (GetUnitDeviceCountInRaid() -1); break; default: dwMaxRequestBlocks = dwMaxRequestBlocksPerUnit; break; } DBGPRT_INFO( _FT("LsBusCtlPlugInEx2(SlotNo %d, MaxReqBlock %d, DisEvt %p, RecEvt %p).)\n"), m_NdasScsiLocation.SlotNo, dwMaxRequestBlocks, m_hDisconnectedEvent, m_hAlarmEvent); SetReconnectFlag(FALSE); BOOL fVolatileRegister = IsVolatile(); fSuccess = LsBusCtlPlugInEx2( m_NdasScsiLocation.SlotNo, dwMaxRequestBlocks, m_hDisconnectedEvent, m_hAlarmEvent, fVolatileRegister); if (!fSuccess) { DBGPRT_ERR_EX(_FT("LsBusCtlPlugInEx2 failed: \n")); _ASSERTE(fSuccess && "PlugIn failure"); return FALSE; } DBGPRT_INFO(_FT("LsBusCtlPluginEx succeeded.\n")); BEGIN_DBGPRT_BLOCK_INFO() DBGPRT_INFO(_FT("LsBusCtlAddTarget(pAddTargetData)\n")); DPType(XDebug::OL_INFO, pAddTargetData, cbAddTargetDataSize); END_DBGPRT_BLOCK() fSuccess = LsBusCtlAddTarget(pAddTargetData); if (!fSuccess) { DBGPRT_ERR_EX(_FT("AddTarget failed.\n")); ::Sleep(1000); LsBusCtlEject(m_NdasScsiLocation.SlotNo); _ASSERTE(fSuccess); return FALSE; } DBGPRT_INFO(_FT("LsBusCtlAddTarget succeeded.\n")); // // Set the status // SetMountedAccess(requestingAccess); // // Set the status as pending, actual mount completion is // reported from PNP event handler to call OnMounted() // to complete this process // SetStatus(NDAS_LOGICALDEVICE_STATUS_MOUNT_PENDING); // // Attach or detach from the event monitor // CNdasEventMonitor* pEventMon = pGetNdasEventMonitor(); pEventMon->Attach(this); DBGPRT_INFO(_FT("Plugged in successfully at %s.\n"), m_NdasScsiLocation.ToString()); return TRUE; }
DWORD CNdasLogicalDevice::GetUserBlockCount() { ximeta::CAutoLock autolock(this); if (!IsComplete()) { return 0; } if (!IS_NDAS_LOGICALDEVICE_TYPE_DISK_GROUP(m_logicalDeviceGroup.Type)) { _ASSERTE(1 == GetUnitDeviceCount()); CRefObjPtr<CNdasUnitDevice> pUnitDevice = GetUnitDevice(0); _ASSERTE(NULL != pUnitDevice.p); if (NULL == pUnitDevice.p) { return 0; } return pUnitDevice->GetUserBlockCount(); } DWORD dwBlocks = 0; for (DWORD i = 0; i < GetUnitDeviceCount(); i++) { CRefObjPtr<CNdasUnitDevice> pUnitDevice = GetUnitDevice(i); _ASSERTE(NULL != pUnitDevice.p); if (NULL == pUnitDevice.p) { return 0; } _ASSERTE(pUnitDevice->GetType() == NDAS_UNITDEVICE_TYPE_DISK); CNdasUnitDiskDevice* pUnitDisk = reinterpret_cast<CNdasUnitDiskDevice*>(pUnitDevice.p); // dwBlocks += pUnitDisk->GetBlocks(); _ASSERTE(IS_NDAS_LOGICALDEVICE_TYPE_DISK_GROUP(m_logicalDeviceGroup.Type)); switch (m_logicalDeviceGroup.Type) { case NDAS_LOGICALDEVICE_TYPE_DISK_MIRRORED: if (0 == i) { dwBlocks = pUnitDisk->GetUserBlockCount(); } break; case NDAS_LOGICALDEVICE_TYPE_DISK_AGGREGATED: case NDAS_LOGICALDEVICE_TYPE_DISK_RAID0: dwBlocks += pUnitDisk->GetUserBlockCount(); break; case NDAS_LOGICALDEVICE_TYPE_DISK_RAID1: if (i % 2) { dwBlocks += pUnitDisk->GetUserBlockCount(); } break; case NDAS_LOGICALDEVICE_TYPE_DISK_RAID4: if (i != GetUnitDeviceCount() - 1) { // // do not count parity disk // dwBlocks += pUnitDisk->GetUserBlockCount(); } break; case NDAS_LOGICALDEVICE_TYPE_DISK_SINGLE: dwBlocks = pUnitDisk->GetUserBlockCount(); break; default: // not implemented yet : DVD, VDVD, MO, FLASH ... _ASSERTE(FALSE); break; } } return dwBlocks; }