[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [win-pv-devel] [PATCH v2] Handle QueryRemoveFailed



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of Owen Smith
> Sent: 19 October 2018 15:18
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith <owen.smith@xxxxxxxxxx>
> Subject: [win-pv-devel] [PATCH v2] Handle QueryRemoveFailed
> 
> Its possible for the QueryRemove to fail, in which case, the xenagent
> should re-open the device and inform the client code.
> This allows a the XenIface device to re-write the control/feature-*
> flags if XenIface failed the QueryRemove
> 
> Also replaces Tabs with 4 spaces.
> 
> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>

Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx>

> ---
>  src/xenagent/devicelist.cpp | 187 +++++++++++++++++++++++++++++----------
> -----
>  src/xenagent/devicelist.h   |  13 +--
>  2 files changed, 132 insertions(+), 68 deletions(-)
> 
> diff --git a/src/xenagent/devicelist.cpp b/src/xenagent/devicelist.cpp
> index e0583f9..4acf532 100644
> --- a/src/xenagent/devicelist.cpp
> +++ b/src/xenagent/devicelist.cpp
> @@ -36,6 +36,8 @@
> 
>  #include "devicelist.h"
> 
> +#define BUFFER_SIZE 127
> +
>  // deal with SetupApi and RegisterDeviceNotification using different
> string types
>  static std::wstring Convert(const char* str)
>  {
> @@ -50,6 +52,19 @@ static std::wstring Convert(const wchar_t* wstr)
>      return std::wstring(wstr);
>  }
> 
> +static void DebugPrint(const wchar_t* fmt, ...)
> +{
> +    wchar_t buffer[BUFFER_SIZE + 1];
> +    va_list args;
> +
> +    va_start(args, fmt);
> +    _vsnwprintf(buffer, BUFFER_SIZE, fmt, args);
> +    va_end(args);
> +
> +    buffer[BUFFER_SIZE] = 0;
> +    OutputDebugStringW(buffer);
> +}
> +
>  CDevice::CDevice(const wchar_t* path) :
>      m_handle(INVALID_HANDLE_VALUE), m_path(path), m_notify(NULL)
>  {
> @@ -58,6 +73,7 @@ CDevice::CDevice(const wchar_t* path) :
>  /*virtual*/ CDevice::~CDevice()
>  {
>      Close();
> +    Unregister();
>  }
> 
>  const wchar_t* CDevice::Path() const
> @@ -65,7 +81,7 @@ const wchar_t* CDevice::Path() const
>      return m_path.c_str();
>  }
> 
> -HANDLE CDevice::Open(HANDLE svc)
> +bool CDevice::Open()
>  {
>      Close();
> 
> @@ -76,8 +92,21 @@ HANDLE CDevice::Open(HANDLE svc)
>                             OPEN_EXISTING,
>                             0,
>                             NULL);
> +
> +    return (m_handle != INVALID_HANDLE_VALUE);
> +}
> +
> +void CDevice::Close()
> +{
>      if (m_handle == INVALID_HANDLE_VALUE)
> -        return INVALID_HANDLE_VALUE;
> +        return;
> +    CloseHandle(m_handle);
> +    m_handle = INVALID_HANDLE_VALUE;
> +}
> +
> +HDEVNOTIFY CDevice::Register(HANDLE svc)
> +{
> +    Unregister();
> 
>      DEV_BROADCAST_HANDLE devhdl = { 0 };
>      devhdl.dbch_size = sizeof(devhdl);
> @@ -85,20 +114,16 @@ HANDLE CDevice::Open(HANDLE svc)
>      devhdl.dbch_handle = m_handle;
> 
>      m_notify = RegisterDeviceNotification(svc, &devhdl,
> DEVICE_NOTIFY_SERVICE_HANDLE);
> -    if (m_notify == NULL) {
> -        Close();
> -        return INVALID_HANDLE_VALUE;
> -    }
> -
> -    return m_handle;
> +    return m_notify;
>  }
> 
> -void CDevice::Close()
> +void CDevice::Unregister()
>  {
> -    if (m_handle == INVALID_HANDLE_VALUE)
> +    if (m_notify == NULL)
>          return;
> -    CloseHandle(m_handle);
> -    m_handle = INVALID_HANDLE_VALUE;
> +
> +    UnregisterDeviceNotification(m_notify);
> +    m_notify = NULL;
>  }
> 
>  bool CDevice::Write(void *buf, DWORD bufsz, DWORD *bytes /* = NULL*/)
> @@ -198,9 +223,9 @@ bool CDeviceList::Start(HANDLE handle, IDeviceCreator*
> impl)
>                                              len,
>                                              NULL,
>                                              NULL)) {
> -            OnDeviceAdded(Convert((const char*)detail->DevicePath));
> +            DeviceArrival(Convert((const char*)detail->DevicePath));
>          }
> -        delete [] detail;
> +        delete[] detail;
>          itf.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
>      }
>      SetupDiDestroyDeviceInfoList(info);
> @@ -216,8 +241,8 @@ void CDeviceList::Stop()
>      m_notify = NULL;
> 
>      for (DeviceMap::iterator it = m_devs.begin();
> -            it != m_devs.end();
> -            ++it) {
> +         it != m_devs.end();
> +         ++it) {
>          if (m_impl)
>              m_impl->OnDeviceRemoved(it->second);
>          delete it->second;
> @@ -234,26 +259,33 @@ void CDeviceList::OnDeviceEvent(DWORD evt, LPVOID
> data)
>      hdr = (PDEV_BROADCAST_HDR)data;
>      switch (evt) {
>      case DBT_DEVICEARRIVAL:
> -        if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
> -            itf = (PDEV_BROADCAST_DEVICEINTERFACE)hdr;
> -            if (itf->dbcc_classguid == m_guid)
> -                OnDeviceAdded(Convert((const wchar_t*)itf->dbcc_name));
> -        }
> +        if (hdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
> +            break;
> +        itf = (PDEV_BROADCAST_DEVICEINTERFACE)hdr;
> +        if (itf->dbcc_classguid != m_guid)
> +            break;
> +        DeviceArrival(Convert((const wchar_t*)itf->dbcc_name));
> +        break;
> +
> +    case DBT_DEVICEREMOVEPENDING:
> +        if (hdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
> +            break;
> +        hdl = (PDEV_BROADCAST_HANDLE)hdr;
> +        DeviceRemoved(hdl->dbch_hdevnotify);
>          break;
> 
>      case DBT_DEVICEQUERYREMOVE:
> -        if (hdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
> -            hdl = (PDEV_BROADCAST_HANDLE)hdr;
> -            OnDeviceQueryRemove(hdl->dbch_handle);
> -        }
> +        if (hdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
> +            break;
> +        hdl = (PDEV_BROADCAST_HANDLE)hdr;
> +        DeviceRemovePending(hdl->dbch_hdevnotify);
>          break;
> 
> -    case DBT_DEVICEREMOVEPENDING:
> -        if (hdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
> -            hdl = (PDEV_BROADCAST_HANDLE)hdr;
> -            UnregisterDeviceNotification(hdl->dbch_hdevnotify);
> -            OnDeviceRemoved(hdl->dbch_handle);
> -        }
> +    case DBT_DEVICEQUERYREMOVEFAILED:
> +        if (hdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
> +            break;
> +        hdl = (PDEV_BROADCAST_HANDLE)hdr;
> +        DeviceRemoveFailed(hdl->dbch_hdevnotify);
>          break;
> 
>      default:
> @@ -267,18 +299,18 @@ void CDeviceList::OnPowerEvent(DWORD evt, LPVOID
> data)
> 
>      switch (evt) {
>      case PBT_APMRESUMESUSPEND:
> -    for (DeviceMap::iterator it = m_devs.begin();
> -         it != m_devs.end();
> -         ++it)
> -        m_impl->OnDeviceResume(it->second);
> -    break;
> +        for (DeviceMap::iterator it = m_devs.begin();
> +             it != m_devs.end();
> +             ++it)
> +            m_impl->OnDeviceResume(it->second);
> +        break;
> 
>      case PBT_APMSUSPEND:
> -    for (DeviceMap::iterator it = m_devs.begin();
> -         it != m_devs.end();
> -         ++it)
> -        m_impl->OnDeviceSuspend(it->second);
> -    break;
> +        for (DeviceMap::iterator it = m_devs.begin();
> +             it != m_devs.end();
> +             ++it)
> +            m_impl->OnDeviceSuspend(it->second);
> +        break;
> 
>      default:
>          break;
> @@ -293,52 +325,81 @@ CDevice* CDeviceList::GetFirstDevice()
>      return it->second;
>  }
> 
> -void CDeviceList::OnDeviceAdded(const std::wstring& path)
> +void CDeviceList::DeviceArrival(const std::wstring& path)
>  {
> +    DebugPrint(L"DeviceArrival(%ws)\n", path.c_str());
>      CDevice* dev;
> -    if (m_impl == NULL)
> -        dev = new CDevice(path.c_str());
> -    else
> +    if (m_impl)
>          dev = m_impl->Create(path.c_str());
> +    else
> +        dev = new CDevice(path.c_str());
>      if (dev == NULL)
> -        return; // create failed
> +        goto fail1;
> 
> -    HANDLE handle = dev->Open(m_handle);
> -    if (handle == INVALID_HANDLE_VALUE) {
> -        delete dev;
> -        return; // open failed
> -    }
> +    if (!dev->Open())
> +        goto fail2;
> 
> -    DeviceMap::iterator it = m_devs.find(handle);
> -    if (it != m_devs.end()) {
> -        delete dev;
> -        return;
> -    }
> +    HDEVNOTIFY nfy = dev->Register(m_handle);
> +    if (nfy == NULL)
> +        goto fail3;
> +
> +    m_devs[nfy] = dev;
> 
> -    m_devs[handle] = dev;
>      if (m_impl)
>          m_impl->OnDeviceAdded(dev);
> +
> +    return;
> +
> +fail3:
> +    DebugPrint(L"fail3\n");
> +fail2:
> +    DebugPrint(L"fail2\n");
> +    delete dev; // handles close() and unregister()
> +fail1:
> +    DebugPrint(L"fail1\n");
> +    return;
>  }
> 
> -void CDeviceList::OnDeviceQueryRemove(HANDLE handle)
> +void CDeviceList::DeviceRemoved(HDEVNOTIFY nfy)
>  {
> -    DeviceMap::iterator it = m_devs.find(handle);
> +    DeviceMap::iterator it = m_devs.find(nfy);
>      if (it == m_devs.end())
>          return; // spurious event?
> 
>      CDevice* dev = it->second;
> +    DebugPrint(L"DeviceRemoved(%ws)\n", dev->Path());
> +
> +    delete dev; // handles unregister()
> +    m_devs.erase(it);
> +}
> +
> +void CDeviceList::DeviceRemovePending(HDEVNOTIFY nfy)
> +{
> +    DeviceMap::iterator it = m_devs.find(nfy);
> +    if (it == m_devs.end())
> +        return; // spurious event?
> +
> +    CDevice* dev = it->second;
> +    DebugPrint(L"DeviceRemovePending(%ws)\n", dev->Path());
> +
>      if (m_impl)
>          m_impl->OnDeviceRemoved(dev);
> +
>      dev->Close();
>  }
> 
> -void CDeviceList::OnDeviceRemoved(HANDLE handle)
> +void CDeviceList::DeviceRemoveFailed(HDEVNOTIFY nfy)
>  {
> -    DeviceMap::iterator it = m_devs.find(handle);
> +    DeviceMap::iterator it = m_devs.find(nfy);
>      if (it == m_devs.end())
>          return; // spurious event?
> 
>      CDevice* dev = it->second;
> -    delete dev;
> -    m_devs.erase(it);
> +    DebugPrint(L"DeviceRemoveFailed(%ws)\n", dev->Path());
> +
> +    if (!dev->Open())
> +        DeviceRemoved(nfy);
> +
> +    if (m_impl)
> +        m_impl->OnDeviceAdded(dev);
>  }
> diff --git a/src/xenagent/devicelist.h b/src/xenagent/devicelist.h
> index 5535ad5..e96df56 100644
> --- a/src/xenagent/devicelist.h
> +++ b/src/xenagent/devicelist.h
> @@ -45,8 +45,10 @@ public:
> 
>      const wchar_t* Path() const;
> 
> -    HANDLE Open(HANDLE svc);
> +    bool Open();
>      void Close();
> +    HDEVNOTIFY Register(HANDLE svc);
> +    void Unregister();
> 
>  protected:
>      bool Write(void *buf, DWORD bufsz, DWORD *bytes = NULL);
> @@ -81,11 +83,12 @@ public:
>      CDevice* GetFirstDevice();
> 
>  private:
> -    void OnDeviceAdded(const std::wstring& path);
> -    void OnDeviceQueryRemove(HANDLE handle);
> -    void OnDeviceRemoved(HANDLE dev);
> +    void DeviceArrival(const std::wstring& path);
> +    void DeviceRemoved(HDEVNOTIFY nfy);
> +    void DeviceRemovePending(HDEVNOTIFY nfy);
> +    void DeviceRemoveFailed(HDEVNOTIFY nfy);
> 
> -    typedef std::map< HANDLE, CDevice* > DeviceMap;
> +    typedef std::map< HDEVNOTIFY, CDevice* > DeviceMap;
> 
>      GUID        m_guid;
>      DeviceMap   m_devs;
> --
> 2.16.2.windows.1
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.