code: func (detacher *rbdDetacher) UnmountDevice(deviceMountPath string) error {
  	if pathExists, pathErr := mount.PathExists(deviceMountPath); pathErr != nil {
  		return fmt.Errorf("Error checking if path exists: %v", pathErr)
  	} else if !pathExists {
  		klog.Warningf("Warning: Unmount skipped because path does not exist: %v", deviceMountPath)
  		return nil
  	}
  	devicePath, _, err := mount.GetDeviceNameFromMount(detacher.mounter, deviceMountPath)
  	if err != nil {
  		return err
  	}
  	// Unmount the device from the device mount point.
  	klog.V(4).Infof("rbd: unmouting device mountpoint %s", deviceMountPath)
  	if err = detacher.mounter.Unmount(deviceMountPath); err != nil {
  		return err
  	}
  	klog.V(3).Infof("rbd: successfully umount device mountpath %s", deviceMountPath)
  
  	klog.V(4).Infof("rbd: detaching device %s", devicePath)
  	err = detacher.manager.DetachDisk(detacher.plugin, deviceMountPath, devicePath)
  	if err != nil {
  		return err
  	}
  	klog.V(3).Infof("rbd: successfully detach device %s", devicePath)
  	err = os.Remove(deviceMountPath)
  	if err != nil {
  		return err
  	}
  	klog.V(3).Infof("rbd: successfully remove device mount point %s", deviceMountPath)
  	return nil
  }
docs: // UnmountDevice implements Detacher.UnmountDevice. It unmounts the global
  // mount of the RBD image. This is called once all bind mounts have been
  // unmounted.
  // Internally, it does four things:
  //  - Unmount device from deviceMountPath.
  //  - Detach device from the node.
  //  - Remove lock if found. (No need to check volume readonly or not, because
  //  device is not on the node anymore, it's safe to remove lock.)
  //  - Remove the deviceMountPath at last.
  // This method is idempotent, callers are responsible for retrying on failure.