none
Does chkdsk /r for VHDs make sense?

    Question

  • Hello!

    I had a RAID corruption on Hyper-V Server 2008 R2.

    I'm going to mount several dynamically expanding VHDs on the host in order to run chkdsk against them.

    Does it make any sense to run

    chkdsk driveletter: /f /r /x

    rather than

    chkdsk driveletter: /f /x

    since the physical sector condition is managed by the RAID controller and the Hyper-V host!?

    Thank you!

    L.

    Saturday, April 07, 2012 11:20 PM

Answers

All replies

  • Hi asklucas, since you mention you're going to mount several VHD's to the storage I suggest better to check within the VHD itself. Apart from that you can find more information from below mention article written by Ben Armstrong (http://blogs.msdn.com/b/virtual_pc_guy/archive/2009/01/07/how-do-i-fix-a-corrupted-virtual-hard-disk.aspx)

    Thanks,
    Susantha


    Sunday, April 08, 2012 12:51 AM
  • Hi,
     
    You can run chkdsk.
     
    By the way, you can also check the following post.
     
     

    Vincent Hu

    TechNet Community Support

    • Marked as answer by asklucas Tuesday, April 10, 2012 8:10 AM
    Monday, April 09, 2012 6:24 AM
  • Thank you for your help!

    It states:

    <quote>

    I would recommend that you run a full fledged chkdsk /r on the disk in case corruption is found.

    We can find corruption by running chkdsk <drive_letter> or check id the dirty bit is set using the command fsutil dirty query <drive_letter>.

    In case corruption is detected, I would recommend running a chkdsk /r. Why i would recommend this is simple, if chkdsk finds some files in lost clusters, it would attempt to recover them and would put them in a folder titled found.xxx where xxx=001,002 etc.

    </quote>
    Tuesday, April 10, 2012 8:12 AM

  • Thank you!

    Virtual PC Guy doesn't explain , which chkdsk parameters to use, but it's a very interesting post!

    I ended up running
    chkdsk driveletter: /f /r /x
    on the VHDs mounted in the parent partition.

    I created a quick-and-dirty script for that purpose, it also defrags and compacts the VHDs.

    Only use it for emergencies, as it's quick-and-dirty and relies on the diskpart list volume command to query (only the first!) drive letter of the attached disk.

    '	Hyper-V VHD Maintenance Script
    '	LPET
    '	2012-04-09
    
    Option Explicit
    
    Dim path_file_VHDs
    path_file_VHDs = Array( _
    	"D:\VHDs\firstdisk.vhd", _
    	"D:\VHDs\seconddisk.vhd", _
    	"D:\VHDs\thirddisk.vhd" _
    	)
    
    
    Main
    
    
    Sub Main
    
    	Dim path_file_VHD
    	For Each path_file_VHD In path_file_VHDs
    		
    		WScript.Echo( "==============================================================================")
    		WScript.Echo( "Processing VHD:")
    		WScript.Echo( path_file_VHD)
    		WScript.Echo( ISO_date( Now()) & " " & ISO_time( Now()))
    		WScript.Echo( "------------------------------------------------------------------------------")
    		
    		Dim attached_drive_letter
    		attached_drive_letter = attach_VHD( path_file_VHD)
    		check_VHD( attached_drive_letter)
    		defrag_VHD( attached_drive_letter)
    		detach_VHD( path_file_VHD)
    		
    		compact_VHD( path_file_VHD)
    		
    		attached_drive_letter = ""
    		
    	Next
    
    End Sub
    
    
    Function attach_VHD( vhd_path)
    	WScript.Echo( "attach_VHD( " & vhd_path & ")")
    
    	Dim oShell
    	Dim oScriptExec
    	Dim oStdOut
    	Dim oStdIn
    	Dim strElement
    	Dim sOut
    	Dim sLine
    
    	Set oShell = CreateObject( "WScript.Shell")
    	Set oScriptExec = oShell.Exec( "diskpart")
    	Set oStdOut = oScriptExec.StdOut
    	Set oStdIn = oScriptExec.StdIn
    
    	oStdIn.write vbCrLf
    	WScript.Echo "select vdisk file=" & vhd_path
    	oStdIn.write "select vdisk file=" & vhd_path & vbCrLf
    	WScript.Echo "attach vdisk"
    	oStdIn.write "attach vdisk" & vbCrLf
    	WScript.Sleep( 15000)
    	WScript.Echo "list volume"
    	oStdIn.write "list volume" & vbCrLf
    	WScript.Echo "exit"
    	oStdIn.write "exit" & vbCrLf
    
    	Do While Not oScriptExec.StdOut.AtEndOfStream
    		sLine = oScriptExec.StdOut.ReadLine
    		WScript.Echo sLine
    		If InStr( sLine, "Volume 5    ") Then
    			sOut = Trim( Right( Left( sLine, 18), 5)) & ":"
    		End If
    	Loop
    
    	WScript.Echo sOut
    
    	oStdIn.close()
    
    	attach_VHD = sOut
    
    End Function
    
    
    Function check_VHD( drive_letter)
    	WScript.Echo( "check_VHD( " & drive_letter & ")")
    
    	Dim oShell
    	Dim oScriptExec
    
    	Dim command_line
    	command_line = "chkdsk.exe " & drive_letter & " /f /r /x"
    
    	Set oShell = CreateObject( "WScript.Shell")
    	Set oScriptExec = oShell.Exec( command_line)
    
    	Do While Not oScriptExec.StdOut.AtEndOfStream
    		WScript.Echo( oScriptExec.StdOut.ReadLine)
    	Loop
    
    End Function
    
    
    Function defrag_VHD( drive_letter)
    	WScript.Echo( "defrag_VHD( " & drive_letter & ")")
    
    	Dim oShell
    	Dim oScriptExec
    
    	Dim command_line
    	command_line = "defrag.exe " & drive_letter & " /h /u /v"
    
    	Set oShell = CreateObject( "WScript.Shell")
    	Set oScriptExec = oShell.Exec( command_line)
    
    	Do While Not oScriptExec.StdOut.AtEndOfStream
    		WScript.Echo( oScriptExec.StdOut.ReadLine)
    	Loop
    
    End Function
    
    
    Function detach_VHD( vhd_path)
    	WScript.Echo( "detach_VHD( " & vhd_path & ")")
    
    	Dim oShell
    	Dim oScriptExec
    	Dim oStdOut
    	Dim oStdIn
    	Dim strElement
    	Dim sOut
    	Dim sLine
    
    	Set oShell = CreateObject( "WScript.Shell")
    	Set oScriptExec = oShell.Exec( "diskpart")
    	Set oStdOut = oScriptExec.StdOut
    	Set oStdIn = oScriptExec.StdIn
    
    	oStdIn.write vbCrLf
    	WScript.Echo "select vdisk file=" & vhd_path
    	oStdIn.write "select vdisk file=" & vhd_path & vbCrLf
    	WScript.Echo "detach vdisk"
    	oStdIn.write "detach vdisk" & vbCrLf
    	WScript.Echo "exit"
    	oStdIn.write "exit" & vbCrLf
    
    	Do While Not oScriptExec.StdOut.AtEndOfStream
    		sLine = oScriptExec.StdOut.ReadLine
    		WScript.Echo sLine
    		If instr( sLine, "successfully") Then
    			sOut = sLine & vbCrLf
    		End If
    	Loop
    
    	WScript.Echo sOut
    
    	oStdIn.close()
    
    End Function
    
    
    Function compact_VHD( VHDName)
    	WScript.Echo( "compact_VHD( " & VHDName & ")")
    
    	Dim HyperVServer
    	Dim Msvm_ImageManagementService
    	Dim Result
    	Dim Job
    	Dim InParam
    	Dim OutParam
    	Dim WMI_Service
    
    	'Set Hyper-V Server as being local
    	HyperVServer = "."
    
    	'Get an instance of the WMI Service in the virtualization namespace.
    	Set WMI_Service = GetObject( "winmgmts:\\" & HyperVServer & "\root\virtualization")
    
    	'Get the Msvm_ImageManagementService object
    	Set Msvm_ImageManagementService = WMI_Service.ExecQuery( "SELECT * FROM Msvm_ImageManagementService").ItemIndex(0)
    
    	'Setup the input parameter list
    	Set InParam = Msvm_ImageManagementService.Methods_( "CompactVirtualHardDisk").InParameters.SpawnInstance_()
    	InParam.Path = VHDName
    
    	'Execute the method and store the results in OutParam
    	Set OutParam = Msvm_ImageManagementService.ExecMethod_( "CompactVirtualHardDisk", InParam)
    
    	'Check to see If the job completed synchronously
    	If( OutParam.ReturnValue = 0 ) Then
    		Wscript.Echo "The virtual hard disk has been compacted."
    	ElseIf( OutParam.ReturnValue <> 4096 ) Then
    		Wscript.Echo "The virtual hard disk has not been compacted."
    	Else
    		'Get the job object
    		Set Job = WMI_Service.Get( OutParam.Job)
    		'Wait for the job to complete (3 == starting, 4 == running)
    		While ( Job.JobState = 3 ) Or ( Job.JobState = 4 )
    			Wscript.Echo "Compacting. " & Job.PercentComplete & " % complete"
    			WScript.Sleep( 20000)
    			'Refresh the job object
    			Set Job = WMI_Service.Get( OutParam.Job)
    		Wend
    		'Provide details If the job fails (7 == complete)
    		If( Job.JobState <> 7 ) Then
    			Wscript.Echo "The virtual hard disk has not been compacted."
    			Wscript.Echo "ErrorCode: " & Job.ErrorCode
    			Wscript.Echo "ErrorDescription: " & Job.ErrorDescription
    		Else
    			Wscript.Echo "The virtual hard disk has been compacted."
    		End If
    	End If
    
    End Function
    
    
    Function ISO_date( strNow)
    
    	Dim strDD, strMM, strYYYY
    	
    	strYYYY = DatePart( "yyyy", strNow)
    	strMM = Right( "0" & DatePart( "m", strNow), 2)
    	strDD = Right( "0" & DatePart( "d", strNow), 2)
    	
    	ISO_date = strYYYY & "-" & strMM & "-" & strDD
    
    End Function
    
    
    Function ISO_time( strNow)
    
    	ISO_time = Right( "0" & Hour( strNow), 2) & ":" & Right( "0" & Minute( strNow), 2) & ":" & Right( "0" & Second( strNow), 2)
    
    End Function
    


    Tuesday, April 10, 2012 8:22 AM
  • You  have to change the volume number depending on how many other (physical) disks are attached to the parent partition:

    	Do While Not oScriptExec.StdOut.AtEndOfStream
    		sLine = oScriptExec.StdOut.ReadLine
    		WScript.Echo sLine
    		If InStr( sLine, "Volume 5    ") Then
    			sOut = Trim( Right( Left( sLine, 18), 5)) & ":"
    		End If
    	Loop

    Tuesday, April 10, 2012 8:24 AM