Skip to content
  1. Mar 18, 2020
    • Jason Gunthorpe's avatar
      RDMA/cm: Allow ib_send_cm_sidr_rep() to be done under lock · 6a8824a7
      Jason Gunthorpe authored
      
      
      The first thing ib_send_cm_sidr_rep() does is obtain the lock, so use the
      usual unlocked wrapper, locked actor pattern here.
      
      Get rid of the cm_reject_sidr_req() wrapper so each call site can call the
      locked or unlocked version as required.
      
      This avoids a sketchy lock/unlock sequence (which could allow state to
      change) during cm_destroy_id().
      
      Link: https://lore.kernel.org/r/20200310092545.251365-15-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      6a8824a7
    • Jason Gunthorpe's avatar
      RDMA/cm: Allow ib_send_cm_rej() to be done under lock · 81ddb41f
      Jason Gunthorpe authored
      
      
      The first thing ib_send_cm_rej() does is obtain the lock, so use the usual
      unlocked wrapper, locked actor pattern here.
      
      This avoids a sketchy lock/unlock sequence (which could allow state to
      change) during cm_destroy_id().
      
      While here simplify some of the logic in the implementation.
      
      Link: https://lore.kernel.org/r/20200310092545.251365-14-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      81ddb41f
    • Jason Gunthorpe's avatar
      RDMA/cm: Allow ib_send_cm_drep() to be done under lock · 87cabf3e
      Jason Gunthorpe authored
      
      
      The first thing ib_send_cm_drep() does is obtain the lock, so use the
      usual unlocked wrapper, locked actor pattern here.
      
      This avoids a sketchy lock/unlock sequence (which could allow state to
      change) during cm_destroy_id().
      
      Link: https://lore.kernel.org/r/20200310092545.251365-13-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      87cabf3e
    • Jason Gunthorpe's avatar
      RDMA/cm: Allow ib_send_cm_dreq() to be done under lock · e029fdc0
      Jason Gunthorpe authored
      
      
      The first thing ib_send_cm_dreq() does is obtain the lock, so use the
      usual unlocked wrapper, locked actor pattern here.
      
      This avoids a sketchy lock/unlock sequence (which could allow state to
      change) during cm_destroy_id().
      
      Link: https://lore.kernel.org/r/20200310092545.251365-12-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      e029fdc0
    • Jason Gunthorpe's avatar
      RDMA/cm: Add some lockdep assertions for cm_id_priv->lock · 00777a68
      Jason Gunthorpe authored
      
      
      These functions all touch state, so must be called under the lock.
      Inspection shows this is currently true.
      
      Link: https://lore.kernel.org/r/20200310092545.251365-11-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      00777a68
    • Jason Gunthorpe's avatar
      RDMA/cm: Add missing locking around id.state in cm_dup_req_handler · d1de9a88
      Jason Gunthorpe authored
      All accesses to id.state must be done under the spinlock.
      
      Fixes: a977049d
      
       ("[PATCH] IB: Add the kernel CM implementation")
      Link: https://lore.kernel.org/r/20200310092545.251365-10-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      d1de9a88
    • Jason Gunthorpe's avatar
      RDMA/cm: Make it clearer how concurrency works in cm_req_handler() · c206f8ba
      Jason Gunthorpe authored
      
      
      ib_crate_cm_id() immediately places the id in the xarray, and publishes it
      into the remote_id and remote_qpn rbtrees. This makes it visible to other
      threads before it is fully set up.
      
      It appears the thinking here was that the states IB_CM_IDLE and
      IB_CM_REQ_RCVD do not allow any MAD handler or lookup in the remote_id and
      remote_qpn rbtrees to advance.
      
      However, cm_rej_handler() does take an action on IB_CM_REQ_RCVD, which is
      not really expected by the design.
      
      Make the whole thing clearer:
       - Keep the new cm_id out of the xarray until it is completely set up.
         This directly prevents MAD handlers and all rbtree lookups from seeing
         the pointer.
       - Move all the trivial setup right to the top so it is obviously done
         before any concurrency begins
       - Move the mutation of the cm_id_priv out of cm_match_id() and into the
         caller so the state transition is obvious
       - Place the manipulation of the work_list at the end, under lock, after
         the cm_id is placed in the xarray. The work_count cannot change on an
         ID outside the xarray.
       - Add some comments
      
      Link: https://lore.kernel.org/r/20200310092545.251365-9-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      c206f8ba
    • Jason Gunthorpe's avatar
      RDMA/cm: Make it clear that there is no concurrency in cm_sidr_req_handler() · 083bfdbf
      Jason Gunthorpe authored
      
      
      ib_create_cm_id() immediately places the id in the xarray, so it is visible
      to network traffic.
      
      The state is initially set to IB_CM_IDLE and all the MAD handlers will
      test this state under lock and refuse to advance from IDLE, so adding to
      the xarray is harmless.
      
      Further, the set to IB_CM_SIDR_REQ_RCVD also excludes all MAD handlers.
      
      However, the local_id isn't even used for SIDR mode, and there will be no
      input MADs related to the newly created ID.
      
      So, make the whole flow simpler so it can be understood:
       - Do not put the SIDR cm_id in the xarray. This directly shows that there
         is no concurrency
       - Delete the confusing work_count and pending_list manipulations. This
         mechanism is only used by MAD handlers and timewait, neither of which
         apply to SIDR.
       - Add a few comments and rename 'cur_cm_id_priv' to 'listen_cm_id_priv'
       - Move other loose sets up to immediately after cm_id creation so that
         the cm_id is fully configured right away. This fixes an oversight where
         the service_id will not be returned back on a IB_SIDR_UNSUPPORTED
         reject.
      
      Link: https://lore.kernel.org/r/20200310092545.251365-8-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      083bfdbf
    • Jason Gunthorpe's avatar
      RDMA/cm: Read id.state under lock when doing pr_debug() · 153a2e43
      Jason Gunthorpe authored
      The lock should not be dropped before doing the pr_debug() print as it is
      accessing data protected by the lock, such as id.state.
      
      Fixes: 119bf817
      
       ("IB/cm: Add debug prints to ib_cm")
      Link: https://lore.kernel.org/r/20200310092545.251365-7-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      153a2e43
    • Jason Gunthorpe's avatar
      RDMA/cm: Simplify establishing a listen cm_id · 98f67156
      Jason Gunthorpe authored
      
      
      Any manipulation of cm_id->state must be done under the cm_id_priv->lock,
      the two routines that added listens did not follow this rule, because they
      never participate in any concurrent access around the state.
      
      However, since this exception makes the code hard to understand, simplify
      the flow so that it can be fully locked:
       - Move manipulation of listen_sharecount into cm_insert_listen() so it is
         trivially under the cm.lock without having to expose the cm.lock to the
         caller.
       - Push the cm.lock down into cm_insert_listen() and have the function
         increment the reference count before returning an existing pointer.
       - Split ib_cm_listen() into an cm_init_listen() and do not call
         ib_cm_listen() from ib_cm_insert_listen()
       - Make both ib_cm_listen() and ib_cm_insert_listen() directly call
         cm_insert_listen() under their cm_id_priv->lock which does both a
         collision detect and, if needed, the insert (atomically)
       - Enclose all state manipulation within the cm_id_priv->lock, notice this
         set can be done safely after cm_insert_listen() as no reader is allowed
         to read the state without holding the lock.
       - Do not set the listen cm_id in the xarray, as it is never correct to
         look it up. This makes the concurrency simpler to understand.
      
      Many needless error unwinds are removed in the process.
      
      Link: https://lore.kernel.org/r/20200310092545.251365-6-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      98f67156
    • Jason Gunthorpe's avatar
      RDMA/cm: Make the destroy_id flow more robust · 2305d686
      Jason Gunthorpe authored
      
      
      Too much of the destruction is very carefully sensitive to the state
      and various other things. Move more code to the unconditional path and
      add several WARN_ONs to check consistency.
      
      Link: https://lore.kernel.org/r/20200310092545.251365-5-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      2305d686
    • Jason Gunthorpe's avatar
      RDMA/cm: Remove a race freeing timewait_info · bede86a3
      Jason Gunthorpe authored
      When creating a cm_id during REQ the id immediately becomes visible to the
      other MAD handlers, and shortly after the state is moved to IB_CM_REQ_RCVD
      
      This allows cm_rej_handler() to run concurrently and free the work:
      
              CPU 0                                CPU1
       cm_req_handler()
        ib_create_cm_id()
        cm_match_req()
          id_priv->state = IB_CM_REQ_RCVD
                                             cm_rej_handler()
                                               cm_acquire_id()
                                               spin_lock(&id_priv->lock)
                                               switch (id_priv->state)
        					   case IB_CM_REQ_RCVD:
                                                  cm_reset_to_idle()
                                                   kfree(id_priv->timewait_info);
         goto destroy
        destroy:
          kfree(id_priv->timewait_info);
                                                   id_priv->timewait_info = NULL
      
      Causing a double free or worse.
      
      Do not free the timewait_info without also holding the
      id_priv->lock. Simplify this entire flow by making the free unconditional
      during cm_destroy_id() and removing the confusing special case error
      unwind during creation of the timewait_info.
      
      This also fixes a leak of the timewait if cm_destroy_id() is called in
      IB_CM_ESTABLISHED with an XRC TGT QP. The state machine will be left in
      ESTABLISHED while it needed to transition through IB_CM_TIMEWAIT to
      release the timewait pointer.
      
      Also fix a leak of the timewait_info if the caller mis-uses the API and
      does ib_send_cm_reqs().
      
      Fixes: a977049d
      
       ("[PATCH] IB: Add the kernel CM implementation")
      Link: https://lore.kernel.org/r/20200310092545.251365-4-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      bede86a3
    • Jason Gunthorpe's avatar
      RDMA/cm: Fix checking for allowed duplicate listens · ca21cb7f
      Jason Gunthorpe authored
      The test here typod the cm_id_priv to use, it used the one that was
      freshly allocated. By definition the allocated one has the matching
      cm_handler and zero context, so the condition was always true.
      
      Instead check that the existing listening ID is compatible with the
      proposed handler so that it can be shared, as was originally intended.
      
      Fixes: 067b171b
      
       ("IB/cm: Share listening CM IDs")
      Link: https://lore.kernel.org/r/20200310092545.251365-3-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      ca21cb7f
    • Jason Gunthorpe's avatar
      RDMA/cm: Fix ordering of xa_alloc_cyclic() in ib_create_cm_id() · e8dc4e88
      Jason Gunthorpe authored
      xa_alloc_cyclic() is a SMP release to be paired with some later acquire
      during xa_load() as part of cm_acquire_id().
      
      As such, xa_alloc_cyclic() must be done after the cm_id is fully
      initialized, in particular, it absolutely must be after the
      refcount_set(), otherwise the refcount_inc() in cm_acquire_id() may not
      see the set.
      
      As there are several cases where a reader will be able to use the
      id.local_id after cm_acquire_id in the IB_CM_IDLE state there needs to be
      an unfortunate split into a NULL allocate and a finalizing xa_store.
      
      Fixes: a977049d
      
       ("[PATCH] IB: Add the kernel CM implementation")
      Link: https://lore.kernel.org/r/20200310092545.251365-2-leon@kernel.org
      Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
      Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
      e8dc4e88
  2. Mar 13, 2020
  3. Mar 11, 2020
  4. Mar 10, 2020