NTSTATUS LspWorkaroundCleanupLock( PLANSCSI_SESSION LSS, ULONG LockNo, PLARGE_INTEGER TimeOut ){ NTSTATUS status; LONG i; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; PLANSCSI_SESSION tempLSS; LONG maxConn; UCHAR bindingBuffer[(FIELD_OFFSET(TA_ADDRESS, Address) + TDI_ADDRESS_LENGTH_LPX)]; UCHAR targetBuffer[(FIELD_OFFSET(TA_ADDRESS, Address) + TDI_ADDRESS_LENGTH_LPX)]; PTA_ADDRESS BindingAddress = (PTA_ADDRESS)bindingBuffer; PTA_ADDRESS TargetAddress = (PTA_ADDRESS)targetBuffer; LSSLOGIN_INFO loginInfo; LSPROTO_TYPE LSProto; ULONG cleaned; // // Parameter check // // Perform clean-up only for NDAS 2.0 rev 0. // if((LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && LSS->HWRevision == LANSCSIIDE_VER20_REV_1G_ORIGINAL)) { // Get maximum connections excluding the current session/connection. maxConn = LANSCSIIDE_MAX_CONNECTION_VER11 - 1; } else { return STATUS_SUCCESS; } tempLSS = ExAllocatePoolWithTag( NonPagedPool, maxConn * sizeof(LANSCSI_SESSION), LSS_POOLTAG); if(tempLSS == NULL) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(tempLSS, maxConn * sizeof(LANSCSI_SESSION)); // // Init variables // status = STATUS_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Param8[3] = (UCHAR)LockNo; pduDesc.TimeOut = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut); LspGetAddresses(LSS, BindingAddress, TargetAddress); cleaned = 0; // // Try to make connections to fill up connection pool of the NDAS device. // So, we can clear invalid acquisition of the locks. // KDPrintM(DBG_LURN_ERROR,("Try to clean up lock\n")); for (i=0 ; i < maxConn; i++) { tempLSS[i].DefaultTimeOut.QuadPart = IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut)->QuadPart; // // Connect and log in with read-only access. // // connect status = LspConnect( &tempLSS[i], BindingAddress, TargetAddress, NULL, NULL, NULL, NULL ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspConnect(), Can't Connect to the LS node. STATUS:0x%08x\n", status)); break; } } for (i=0; i < maxConn; i++) { if(!LspIsConnected(&tempLSS[i])) { continue; } KDPrintM(DBG_LURN_TRACE, ("Con#%u\n", i)); cleaned++; // extract login information from the existing LSS. LspBuildLoginInfo(LSS, &loginInfo); status = LspLookupProtocol(loginInfo.HWType, loginInfo.HWVersion, &LSProto); if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("Wrong hardware version.\n")); continue; } // Log in with read-only access. loginInfo.UserID &= 0x0000ffff; status = LspLogin( &tempLSS[i], &loginInfo, LSProto, NULL, FALSE ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspLogin() failed. STATUS:0x%08x\n", status)); LspDisconnect(&tempLSS[i]); continue; } // Do need to acquire the lock to release. // NDAS chip 2.0 original allow to release the lock // regardless of the ownership if the connection number // in the lock information of NDAS chip 2.0 // is same. #if 0 // // Acquire the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_SET_MUTEX; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Acquiring lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } #endif // // Release the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_FREE_MUTEX; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } // // Log out and disconnect. // LspLogout( &tempLSS[i], NULL ); LspDisconnect( &tempLSS[i] ); // // Init PDU // pduDesc.Retransmits = 0; pduDesc.PacketLoss = 0; } KDPrintM(DBG_LURN_INFO, ("Cleaned #%u\n", cleaned)); ExFreePool(tempLSS); return status; }
NTSTATUS LspCleanupLock( PLANSCSI_SESSION LSS, UCHAR LockNo ){ NTSTATUS status; LONG i; LANSCSI_PDUDESC pduDesc; BYTE pduResponse; PLANSCSI_SESSION tempLSS; LONG maxConn; LARGE_INTEGER GenericTimeOut; TA_LSTRANS_ADDRESS BindingAddress, TargetAddress; LSSLOGIN_INFO loginInfo; LSPROTO_TYPE LSProto; ULONG cleaned; // // Parameter check // if(LSS->HWProtoVersion <= LSIDEPROTO_VERSION_1_0) { return STATUS_NOT_SUPPORTED; } if(LSS->HWVersion >= 1) { maxConn = LANSCSIIDE_MAX_CONNECTION_VER11 - 1; } else { return STATUS_NOT_SUPPORTED; } tempLSS = ExAllocatePoolWithTag( NonPagedPool, maxConn * sizeof(LANSCSI_SESSION), LSS_POOLTAG); RtlZeroMemory(tempLSS, maxConn * sizeof(LANSCSI_SESSION)); // // Init variables // status = STATUS_SUCCESS; RtlZeroMemory(&pduDesc, sizeof(LANSCSI_PDUDESC)); pduDesc.Param64 = ((UINT64)(LockNo & 0x3)) << 32; // Lock number: 32~33 bit. LspGetAddresses(LSS, &BindingAddress, &TargetAddress); GenericTimeOut.QuadPart = NANO100_PER_SEC * 5; cleaned = 0; // // Try to make connections to fill up connection pool of the NDAS device. // So, we can clear invalid acquisition of the locks. // KDPrintM(DBG_LURN_ERROR,("Try to clean up lock\n")); for (i=0 ; i < maxConn; i++) { // // Connect and log in with read-only access. // // connect LspSetTimeOut(&tempLSS[i], &GenericTimeOut); status = LspConnect( &tempLSS[i], &BindingAddress, &TargetAddress ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspConnect(), Can't Connect to the LS node. STATUS:0x%08x\n", status)); break; } } for (i=0; i < maxConn; i++) { if(!LspIsConnected(&tempLSS[i])) { continue; } KDPrintM(DBG_LURN_TRACE, ("Con#%u\n", i)); cleaned++; // extract login information from the existing LSS. LspBuildLoginInfo(LSS, &loginInfo); status = LspLookupProtocol(loginInfo.HWType, loginInfo.HWVersion, &LSProto); if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("Wrong hardware version.\n")); continue; } // Log in with read-only access. loginInfo.UserID &= 0x0000ffff; status = LspLogin( &tempLSS[i], &loginInfo, LSProto, FALSE ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_LURN_ERROR, ("LspLogin() failed. STATUS:0x%08x\n", status)); LspDisconnect(&tempLSS[i]); ASSERT(FALSE); continue; } // // Acquire the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_SET_SEMA; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Acquiring lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } // // Release the lock on the NDAS device. // pduDesc.Command = VENDOR_OP_FREE_SEMA; status = LspVendorRequest( &tempLSS[i], &pduDesc, &pduResponse ); if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_LURN_ERROR, ("Releasing lock #%u denied by NDAS device\n", LockNo)); } if(!NT_SUCCESS(status)) { LspDisconnect(&tempLSS[i]); KDPrintM(DBG_LURN_ERROR, ("LspVendorRequest() failed. STATUS=%08lx\n", status)); continue; } // // Log out and disconnect. // LspLogout( &tempLSS[i] ); LspDisconnect( &tempLSS[i] ); } KDPrintM(DBG_LURN_INFO, ("Cleaned #%u\n", cleaned)); ExFreePool(tempLSS); return status; }