title: Python Hivex Issue - Device or resource is busy
body: <p>I'm trying to do following:</p>
  
  <ol>
  <li>Mount root partition (C: drive) of Windows RAW image (.img) to a mount point say <code>/mnt/mnt-swapniku</code></li>
  <li>Register a RunOnce service into registry</li>
  <li>Then <code>umount /mnt/mnt-swapniku</code> and free up loop device </li>
  </ol>
  
  <p>Sample code is given below. Everything works fine until unmounting operation. <code>kpartx -d</code> and <code>losetup -d</code> operations fail.</p>
  
  <p>The same issue is discussed here: <a href="http://www.redhat.com/archives/libguestfs/2011-July/msg00007.html" rel="nofollow">http://www.redhat.com/archives/libguestfs/2011-July/msg00007.html</a></p>
  
  <p>This issue was fixed in Hivex back in 2011. Unfortunately, it doesn't seem to be working on my machine. Suprisingly, when I perform <code>kpartx -d /dev/loop0</code> and <code>losetup -d /dev/loop0</code> manually on the terminal, it works fine. Initially, I thought Hivex takes some time to free up resources, hence I introduced delay as well. But no avail.</p>
  
  <p>Can anyone help me with this issue in Python? </p>
  
  <hr>
  
  <p>Environment:</p>
  
  <pre><code>CentOs 6.5 + hivex-1.3.3-4.2.el6.x86_64 + python-hivex-1.3.3-4.2.el6.x86_64
  </code></pre>
  
  <hr>
  
  <p>Code (runonce_registry.py) :</p>
  
  <pre><code>import hivex
  import os
  import time
  
  cfg_root = '/mnt/mnt-swapniku/'
  
  win_install_run_once_service_reg_keys = [
      {'key':"Foo Service", 't':1, 'value':"C:\Windows\Temp\foo.exe\0".encode('utf-16le')}
  ]
  
  def win_add_run_once_service(config_root, service_keys, silent = False):
      '''
      Add RunOnce Windows service registry
  
      config_root:
          Path of the C drive
      silent:
          Set True/False for logging info
  
      Ref - http://libguestfs.org/hivex.3.html
  
      '''
      try:        
          h = hivex.Hivex(config_root + '/Windows/System32/config/SOFTWARE', write = True)
          key = h.root()
  
          for child in ('Microsoft', 'Windows', 'CurrentVersion'):
              key = h.node_get_child(key, child)
              runonce = h.node_get_child(key, "RunOnce")
  
          if runonce is None:
              runonce = h.node_add_child(key, "RunOnce")
  
          h.node_set_values(runonce, service_keys)
  
          h.commit(None)
  
          if not silent:
              print("Added Windows RunOnce service")
  
          # Hivex cleanup
          del h # or h.close()
  
          time.sleep(1)
  
      except RuntimeError:
          print("Hivex encountered RuntimeError while adding Windows RunOnce service")
          return False
  
      return True
  
  if __name__ == '__main__':
      win_add_run_once_service(cfg_root, win_install_run_once_service_reg_keys)
      os.system('umount ' + cfg_root)
      os.system('kpartx -d /dev/loop0')
      os.system('losetup -d /dev/loop0')
  </code></pre>
  
  <hr>
  
  <p>Output:</p>
  
  <pre><code>[root@dhcp-xxx-xx-xx-xx Windows_Registry]# losetup /dev/loop0 win2k8r2.x86_64.img
  [root@dhcp-xxx-xx-xx-xx Windows_Registry]# kpartx -a /dev/loop0
  [root@dhcp-xxx-xx-xx-xx Windows_Registry]# mount /dev/mapper/loop0p2 /mnt/mnt-swapniku/
  [root@dhcp-xxx-xx-xx-xx Windows_Registry]# python runonce_registry.py
  Added Windows RunOnce service
  device-mapper: remove ioctl on loop0p2 failed: Device or resource busy
  loop: can't delete device /dev/loop0: Device or resource busy
  </code></pre>