1. 09 Sep, 2010 40 commits
    • Chris Mason's avatar
      RDS: use delayed work for the FMR flushes · 7a0ff5db
      Chris Mason authored
      Using a delayed work queue helps us make sure a healthy number of FMRs
      have queued up over the limit.  It makes for a large improvement in RDMA
      iops.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      7a0ff5db
    • Chris Mason's avatar
      rds: more FMRs are faster · eabb7322
      Chris Mason authored
      When we add more FMRs, we flush them less often and so we go faster.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      eabb7322
    • Chris Mason's avatar
      rds: recycle FMRs through lockless lists · 6fa70da6
      Chris Mason authored
      FRM allocation and recycling is performance critical and fairly lock
      intensive.  The current code has a per connection lock that all
      processes bang on and it becomes a major bottleneck on large systems.
      
      This changes things to use a number of cmpxchg based lists instead,
      allowing us to go through the whole FMR lifecycle without locking inside
      RDS.
      
      Zach Brown pointed out that our usage of cmpxchg for xlist removal is
      racey if someone manages to remove and add back an FMR struct into the list
      while another CPU can see the FMR's address at the head of the list.
      
      The second CPU might assume the list hasn't changed when in fact any
      number of operations might have happened in between the deletion and
      reinsertion.
      
      This commit maintains a per cpu count of CPUs that are currently
      in xlist removal, and establishes a grace period to make sure that
      nobody can see an entry we have just removed from the list.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      6fa70da6
    • Zach Brown's avatar
      rds: fix rds_send_xmit() serialization · 0f4b1c7e
      Zach Brown authored
      rds_send_xmit() was changed to hold an interrupt masking spinlock instead of a
      mutex so that it could be called from the IB receive tasklet path.  This broke
      the TCP transport because its xmit method can block and masks and unmasks
      interrupts.
      
      This patch serializes callers to rds_send_xmit() with a simple bit instead of
      the current spinlock or previous mutex.  This enables rds_send_xmit() to be
      called from any context and to call functions which block.  Getting rid of the
      c_send_lock exposes the bare c_lock acquisitions which are changed to block
      interrupts.
      
      A waitqueue is added so that rds_conn_shutdown() can wait for callers to leave
      rds_send_xmit() before tearing down partial send state.  This lets us get rid
      of c_senders.
      
      rds_send_xmit() is changed to check the conn state after acquiring the
      RDS_IN_XMIT bit to resolve races with the shutdown path.  Previously both
      worked with the conn state and then the lock in the same order, allowing them
      to race and execute the paths concurrently.
      
      rds_send_reset() isn't racing with rds_send_xmit() now that rds_conn_shutdown()
      properly ensures that rds_send_xmit() can't start once the conn state has been
      changed.  We can remove its previous use of the spinlock.
      
      Finally, c_send_generation is redundant.  Callers can race to test the c_flags
      bit by simply retrying instead of racing to test the c_send_generation atomic.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      0f4b1c7e
    • Zach Brown's avatar
      rds: block ints when acquiring c_lock in rds_conn_message_info() · 501dcccd
      Zach Brown authored
      conn->c_lock is acquired in interrupt context.  rds_conn_message_info() is
      called from user context and was acquiring c_lock without blocking interrupts,
      leading to possible deadlocks.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      501dcccd
    • Zach Brown's avatar
      rds: remove unused rds_send_acked_before() · 671202f3
      Zach Brown authored
      rds_send_acked_before() wasn't blocking interrupts when acquiring c_lock from
      user context but nothing calls it.  Rather than fix its use of c_lock we just
      remove the function.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      671202f3
    • Chris Mason's avatar
      RDS: use friendly gfp masks for prefill · 037f18a3
      Chris Mason authored
      When prefilling the rds frags, we end up doing a lot of allocations.
      We're not in atomic context here, and so there's no reason to dip into
      atomic reserves.  This changes the prefills to use masks that allow
      waiting.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      037f18a3
    • Chris Mason's avatar
      RDS/IB: Add caching of frags and incs · 33244125
      Chris Mason authored
      This patch is based heavily on an initial patch by Chris Mason.
      Instead of freeing slab memory and pages, it keeps them, and
      funnels them back to be reused.
      
      The lock minimization strategy uses xchg and cmpxchg atomic ops
      for manipulation of pointers to list heads. We anchor the lists with a
      pointer to a list_head struct instead of a static list_head struct.
      We just have to carefully use the existing primitives with
      the difference between a pointer and a static head struct.
      
      For example, 'list_empty()' means that our anchor pointer points to a list with
      a single item instead of meaning that our static head element doesn't point to
      any list items.
      
      Original patch by Chris, with significant mods and fixes by Andy and Zach.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      33244125
    • Andy Grover's avatar
      RDS/IB: Remove ib_recv_unmap_page() · fc24f780
      Andy Grover authored
      All it does is call unmap_sg(), so just call that directly.
      
      The comment above unmap_page also may be incorrect, so we
      shouldn't hold on to it, either.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      fc24f780
    • Andy Grover's avatar
      RDS: Assume recv->r_frag is always NULL in refill_one() · 3427e854
      Andy Grover authored
      refill_one() should never be called on a recv struct that
      doesn't need a new r_frag allocated. Add a WARN and remove
      conditional around r_frag alloc code.
      
      Also, add a comment to explain why r_ibinc may or may not
      need refilling.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      3427e854
    • Andy Grover's avatar
      RDS: Use page_remainder_alloc() for recv bufs · 0b088e00
      Andy Grover authored
      Instead of splitting up a page into RDS_FRAG_SIZE chunks
      ourselves, ask rds_page_remainder_alloc() to do it. While it
      is possible PAGE_SIZE > FRAG_SIZE, on x86en it isn't, so having
      duplicate "carve up a page into buffers" code seems excessive.
      
      The other modification this spawns is the use of a single
      struct scatterlist in rds_page_frag instead of a bare page ptr.
      This causes verbosity to increase in some places, and decrease
      in others.
      
      Finally, I decided to unify the lifetimes and alloc/free of
      rds_page_frag and its page. This is a nice simplification in itself,
      but will be extra-nice once we come to adding cmason's recycling
      patch.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      0b088e00
    • Zach Brown's avatar
      RDS/IB: disconnect when IB devices are removed · fc19de38
      Zach Brown authored
      Currently IB device removal destroys connections which are associated with the
      device.  This prevents connections from being re-established when replacement
      devices are added.
      
      Instead we'll queue shutdown work on the connections as their devices are
      removed.  When we see that devices are added we triger connection attempts on
      all connections that don't currently have a device.
      
      The result is that RDS sockets can resume device-independent work (bcopy, not
      RDMA) across IB device removal and restoration.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      fc19de38
    • Zach Brown's avatar
      RDS: introduce rds_conn_connect_if_down() · f3c6808d
      Zach Brown authored
      A few paths had the same block of code to queue a connection's connect work if
      it was in the right state.  Let's move this in to a helper function.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      f3c6808d
    • Zach Brown's avatar
      RDS/IB: add refcount tracking to struct rds_ib_device · 3e0249f9
      Zach Brown authored
      The RDS IB client .remove callback used to free the rds_ibdev for the given
      device unconditionally.  This could race other users of the struct.  This patch
      adds refcounting so that we only free the rds_ibdev once all of its users are
      done.
      
      Many rds_ibdev users are tied to connections.  We give the connection a
      reference and change these users to reference the device in the connection
      instead of looking it up in the IB client data.  The only user of the IB client
      data remaining is the first lookup of the device as connections are built up.
      
      Incrementing the reference count of a device found in the IB client data could
      race with final freeing so we use an RCU grace period to make sure that freeing
      won't happen until those lookups are done.
      
      MRs need the rds_ibdev to get at the pool that they're freed in to.  They exist
      outside a connection and many MRs can reference different devices from one
      socket, so it was natural to have each MR hold a reference.  MR refs can be
      dropped from interrupt handlers and final device teardown can block so we push
      it off to a work struct.  Pool teardown had to be fixed to cancel its pending
      work instead of deadlocking waiting for all queued work, including itself, to
      finish.
      
      MRs get their reference from the global device list, which gets a reference.
      It is left unprotected by locks and remains racy.  A simple global lock would
      be a significant bottleneck.  More scalable (complicated) locking should be
      done carefully in a later patch.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      3e0249f9
    • Zach Brown's avatar
      RDS/IB: get the xmit max_sge from the RDS IB device on the connection · 89bf9d41
      Zach Brown authored
      rds_ib_xmit_rdma() was calling ib_get_client_data() to get at the rds_ibdevice
      just to get the max_sge for the transmit.  This patch instead has it get it
      directly off the rds_ibdev which is stored on the connection.
      
      The current code won't free the rds_ibdev until all the IB connections that use
      it are freed.  So it's safe to reference the rds_ibdev this way.  In the future
      it also makes it easier to support proper reference counting of the rds_ibdev
      struct.
      
      As an additional bonus, this gets rid of the performance hit of calling in to
      the IB stack to look up the rds_ibdev.  The current implementation in the IB
      stack acquires an interrupt blocking spinlock to protect the registration of
      client callback data.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      89bf9d41
    • Zach Brown's avatar
      RDS/IB: rds_ib_cm_handle_connect() forgot to unlock c_cm_lock · a46ca94e
      Zach Brown authored
      rds_ib_cm_handle_connect() could return without unlocking the c_conn_lock if
      rds_setup_qp() failed.  Rather than adding another imbalanced mutex_unlock() to
      this error path we only unlock the mutex once as we exit the function, reducing
      the likelyhood of making this same mistake in the future.  We remove the
      previous mulitple return sites, leaving one unambigious return path.
      Signed-off-by: default avatarZach Brown <zach.brown@oracle.com>
      a46ca94e
    • Chris Mason's avatar
      rds: Fix reference counting on the for xmit_atomic and xmit_rdma · 1cc2228c
      Chris Mason authored
      This makes sure we have the proper number of references in
      rds_ib_xmit_atomic and rds_ib_xmit_rdma.  We also consistently
      drop references the same way for all message types as the IOs end.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      1cc2228c
    • Chris Mason's avatar
      rds: use RCU to protect the connection hash · bcf50ef2
      Chris Mason authored
      The connection hash was almost entirely RCU ready, this
      just makes the final couple of changes to use RCU instead
      of spinlocks for everything.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      bcf50ef2
    • Chris Mason's avatar
      RDS: use locking on the connection hash list · abf45439
      Chris Mason authored
      rds_conn_destroy really needs locking while it changes the
      connection hash.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      abf45439
    • Chris Mason's avatar
      rds: Fix RDMA message reference counting · c9e65383
      Chris Mason authored
      The RDS send_xmit code was trying to get fancy with message
      counting and was dropping the final reference on the RDMA messages
      too early.  This resulted in memory corruption and oopsen.
      
      The fix here is to always add a ref as the parts of the message passes
      through rds_send_xmit, and always drop a ref as the parts of the message
      go through completion handling.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      c9e65383
    • Chris Mason's avatar
      rds: don't let RDS shutdown a connection while senders are present · 7e3f2952
      Chris Mason authored
      This is the first in a long line of patches that tries to fix races
      between RDS connection shutdown and RDS traffic.
      
      Here we are maintaining a count of active senders to make sure
      the connection doesn't go away while they are using it.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      7e3f2952
    • Chris Mason's avatar
      rds: Use RCU for the bind lookup searches · 38a4e5e6
      Chris Mason authored
      The RDS bind lookups are somewhat expensive in terms of CPU
      time and locking overhead.  This commit changes them into a
      faster RCU based hash tree instead of the rbtrees they were using
      before.
      
      On large NUMA systems it is a significant improvement.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      38a4e5e6
    • Andy Grover's avatar
      RDS/IB: add _to_node() macros for numa and use {k,v}malloc_node() · e4c52c98
      Andy Grover authored
      Allocate send/recv rings in memory that is node-local to the HCA.
      This significantly helps performance.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      e4c52c98
    • Andy Grover's avatar
      4a81802b
    • Chris Mason's avatar
      rds: rcu-ize rds_ib_get_device() · 764f2dd9
      Chris Mason authored
      rds_ib_get_device is called very often as we turn an
      ip address into a corresponding device structure.  It currently
      take a global spinlock as it walks different lists to find active
      devices.
      
      This commit changes the lists over to RCU, which isn't very complex
      because they are not updated very often at all.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      764f2dd9
    • Chris Mason's avatar
      rds: per-rm flush_wait waitq · c83188dc
      Chris Mason authored
      This removes a global waitqueue used to wait for rds messages
      and replaces it with a waitqueue inside the rds_message struct.
      
      The global waitqueue turns into a global lock and significantly
      bottlenecks operations on large machines.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      c83188dc
    • Chris Mason's avatar
      rds: switch to rwlock on bind_lock · 976673ee
      Chris Mason authored
      The bind_lock is almost entirely readonly, but it gets
      hammered during normal operations and is a major bottleneck.
      
      This commit changes it to an rwlock, which takes it from 80%
      of the system time on a big numa machine down to much lower
      numbers.
      
      A better fix would involve RCU, which is done in a later commit
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      976673ee
    • Andy Grover's avatar
      RDS: Update comments in rds_send_xmit() · ce47f52f
      Andy Grover authored
      Update comments to reflect changes in previous commit.
      
      Keeping as separate commits due to different authorship.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      ce47f52f
    • Chris Mason's avatar
      RDS: Use a generation counter to avoid rds_send_xmit loop · 9e29db0e
      Chris Mason authored
      rds_send_xmit is required to loop around after it releases the lock
      because someone else could done a trylock, found someone working on the
      list and backed off.
      
      But, once we drop our lock, it is possible that someone else does come
      in and make progress on the list.  We should detect this and not loop
      around if another process is actually working on the list.
      
      This patch adds a generation counter that is bumped every time we
      get the lock and do some send work.  If the retry notices someone else
      has bumped the generation counter, it does not need to loop around and
      continue working.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      9e29db0e
    • Andy Grover's avatar
      RDS: Get pong working again · acfcd4d4
      Andy Grover authored
      Call send_xmit() directly from pong()
      
      Set pongs as op_active
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      acfcd4d4
    • Andy Grover's avatar
      RDS: Do wait_event_interruptible instead of wait_event · a40aa923
      Andy Grover authored
      Can't see a reason not to allow signals to interrupt the wait.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      a40aa923
    • Andy Grover's avatar
      RDS: Remove send_quota from send_xmit() · fcc5450c
      Andy Grover authored
      The purpose of the send quota was really to give fairness
      when different connections were all using the same
      workq thread to send backlogged msgs -- they could only send
      so many before another connection could make progress.
      
      Now that each connection is pushing the backlog from its
      completion handler, they are all guaranteed to make progress
      and the quota isn't needed any longer.
      
      A thread *will* have to send all previously queued data, as well
      as any further msgs placed on the queue while while c_send_lock
      was held. In a pathological case a single process can get
      roped into doing this for long periods while other threads
      get off free. But, since it can only do this until the transport
      reports full, this is a bounded scenario.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      fcc5450c
    • Andy Grover's avatar
    • Andy Grover's avatar
      RDS: rds_message_unmapped() doesn't need to check if queue active · ab1a6926
      Andy Grover authored
      If the queue has nobody on it, then wake_up does nothing.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      ab1a6926
    • Andy Grover's avatar
      RDS: Fix locking in send on m_rs_lock · cf4b7389
      Andy Grover authored
      Do not nest m_rs_lock under c_lock
      
      Disable interrupts in {rdma,atomic}_send_complete
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      cf4b7389
    • Andy Grover's avatar
      RDS: Use NOWAIT in message_map_pages() · f2ec76f2
      Andy Grover authored
      Can no longer block, so use NOWAIT.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      f2ec76f2
    • Andy Grover's avatar
      RDS: Bypass workqueue when queueing cong updates · 2fa57129
      Andy Grover authored
      Now that rds_send_xmit() does not block, we can call it directly
      instead of going through the helper thread.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      2fa57129
    • Andy Grover's avatar
      RDS: Call rds_send_xmit() directly from sendmsg() · a7d3a281
      Andy Grover authored
      rds_sendmsg() is calling the send worker function to
      send the just-queued datagrams, presumably because it wants
      the behavior where anything not sent will re-call the send
      worker. We now ensure all queued datagrams are sent by retrying
      from the send completion handler, so this isn't needed any more.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      a7d3a281
    • Andy Grover's avatar
      RDS: rds_send_xmit() locking/irq fixes · 2ad8099b
      Andy Grover authored
      rds_message_put() cannot be called with irqs off, so move it after
      irqs are re-enabled.
      
      Spinlocks throughout the function do not to use _irqsave because
      the lock of c_send_lock at top already disabled irqs.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      2ad8099b
    • Andy Grover's avatar
      RDS: Change send lock from a mutex to a spinlock · 049ee3f5
      Andy Grover authored
      This change allows us to call rds_send_xmit() from a tasklet,
      which is crucial to our new operating model.
      
      * Change c_send_lock to a spinlock
      * Update stats fields "sem_" to "_lock"
      * Remove unneeded rds_conn_is_sending()
      
      About locking between shutdown and send -- send checks if the
      connection is up. Shutdown puts the connection into
      DISCONNECTING. After this, all threads entering send will exit
      immediately. However, a thread could be *in* send_xmit(), so
      shutdown acquires the c_send_lock to ensure everyone is out
      before proceeding with connection shutdown.
      Signed-off-by: default avatarAndy Grover <andy.grover@oracle.com>
      049ee3f5