1. 11 Apr, 2022 12 commits
    • Alexander Aring's avatar
      srcu: Use export for srcu_struct defined by DEFINE_STATIC_SRCU() · db8f1471
      Alexander Aring authored
      If an srcu_struct structure defined by tree SRCU's DEFINE_STATIC_SRCU()
      is used by a module, sparse will give the following diagnostic:
      
      sparse: symbol '__srcu_struct_nodes_srcu' was not declared. Should it be static?
      
      The problem is that a within-module DEFINE_STATIC_SRCU() must define
      a non-static srcu_struct because it is exported by referencing it in a
      special '__section("___srcu_struct_ptrs")'.  This reference is needed
      so that module load and unloading can invoke init_srcu_struct() and
      cleanup_srcu_struct(), respectively.  Unfortunately, sparse is unaware of
      '__section("___srcu_struct_ptrs")', resulting in the above false-positive
      diagnostic.  To avoid this false positive, this commit therefore creates
      a prototype of the srcu_struct with an "extern" keyword.
      Signed-off-by: default avatarAlexander Aring <aahringo@redhat.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      db8f1471
    • Paul E. McKenney's avatar
      srcu: Add boot-time control over srcu_node array allocation · c69a00a1
      Paul E. McKenney authored
      This commit adds an srcu_tree.convert_to_big kernel parameter that either
      refuses to convert at all (0), converts immediately at init_srcu_struct()
      time (1), or lets rcutorture convert it (2).  An addition contention-based
      dynamic conversion choice will be added, along with documentation.
      
      [ paulmck: Apply callback-scanning feedback from Neeraj Upadhyay. ]
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      c69a00a1
    • Neeraj Upadhyay's avatar
      srcu: Ensure snp nodes tree is fully initialized before traversal · 0b56f953
      Neeraj Upadhyay authored
      For configurations where snp node tree is not initialized at
      init time (added in subsequent commits), srcu_funnel_gp_start()
      and srcu_funnel_exp_start() can potential traverse and observe
      the snp nodes' transient (uninitialized) states. This can potentially
      happen, when init_srcu_struct_nodes() initialization of sdp->mynode
      races with srcu_funnel_gp_start() and srcu_funnel_exp_start()
      
      Consider the case below where srcu_funnel_gp_start() observes
      sdp->mynode to be not NULL and uses an uninitialized sdp->grpmask
      
                P1                                  P2
      
      init_srcu_struct_nodes()           void srcu_funnel_gp_start(...)
      {
      for_each_possible_cpu(cpu) {
        ...
        sdp->mynode = &snp_first[...];
        for (snp = sdp->mynode;...)       struct srcu_node *snp_leaf =
                                             smp_load_acquire(&sdp->mynode)
          ...                             if (snp_leaf) {
                                            for (snp = snp_leaf; ...)
                                              ...
      					if (snp == snp_leaf)
                                               snp->srcu_data_have_cbs[idx] |=
                                                 sdp->grpmask;
          sdp->grpmask =
            1 << (cpu - sdp->mynode->grplo);
        }
      }
      
      Similarly, init_srcu_struct_nodes() and srcu_funnel_exp_start() can
      race, where srcu_funnel_exp_start() could observe state of snp lock
      before spin_lock_init().
      
                P1                                      P2
      
      init_srcu_struct_nodes()               void srcu_funnel_exp_start(...)
      {
        srcu_for_each_node_breadth_first(ssp, snp) {      for (; ...) {
                                                            spin_lock_...(snp, )
      	spin_lock_init(&ACCESS_PRIVATE(snp, lock));
          ...
        }
        for_each_possible_cpu(cpu) {
          ...
          sdp->mynode = &snp_first[...];
      
      To avoid these issues, ensure that snp node tree initialization is
      complete i.e. after SRCU_SIZE_WAIT_BARRIER srcu_size_state is reached,
      before traversing the tree. Given that srcu_funnel_gp_start() and
      srcu_funnel_exp_start() are called within SRCU read side critical
      sections, this check is safe, in the sense that all callbacks are
      enqueued on CPU0 srcu_cblist until SRCU_SIZE_WAIT_CALL is entered,
      and these read side critical sections (containing srcu_funnel_gp_start()
      and srcu_funnel_exp_start()) need to complete, before SRCU_SIZE_WAIT_CALL
      is reached.
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      0b56f953
    • Paul E. McKenney's avatar
      srcu: Use invalid initial value for srcu_node GP sequence numbers · cbdc98e9
      Paul E. McKenney authored
      Currently, tree SRCU relies on the srcu_node structures being initialized
      at the same time that the srcu_struct itself is initialized, and thus
      use the initial grace-period sequence number as the initial value for
      the srcu_node structure's ->srcu_have_cbs[] and ->srcu_gp_seq_needed_exp
      fields.  Although this has a high probability of also working when the
      srcu_node array is allocated and initialized at some random later time,
      it would be better to avoid leaving such things to chance.
      
      This commit therefore initializes these fields with 0x2, which is a
      recognizable invalid value.  It then adds the required checks for this
      invalid value in order to avoid confusion on long-running kernels
      (especially those on 32-bit systems) that allocate and initialize
      srcu_node arrays late in life.
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      cbdc98e9
    • Paul E. McKenney's avatar
      srcu: Compute snp_seq earlier in srcu_funnel_gp_start() · aeb9b39b
      Paul E. McKenney authored
      Currently, srcu_funnel_gp_start() tests snp->srcu_have_cbs[idx] and then
      separately assigns it to the snp_seq local variable.  This commit does
      the assignment earlier to simplify the code a bit.  While in the area,
      this commit also takes advantage of the 100-character line limit to put
      the call to srcu_schedule_cbs_sdp() on a single line.
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      aeb9b39b
    • Paul E. McKenney's avatar
      srcu: Make rcutorture dump the SRCU size state · 3bedebcf
      Paul E. McKenney authored
      This commit adds the numeric and string version of ->srcu_size_state to
      the Tree-SRCU-specific portion of the rcutorture output.
      
      [ paulmck: Apply feedback from kernel test robot and Dan Carpenter. ]
      [ quic_neeraju: Apply feedback from Jiapeng Chong. ]
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      3bedebcf
    • Paul E. McKenney's avatar
      srcu: Add size-state transitioning code · e2f63836
      Paul E. McKenney authored
      This is just dead code at the moment, and will be used once
      the state-transition code is activated.
      
      Because srcu_barrier() must be aware of transition before call_srcu(), the
      state machine waits for an SRCU grace period before callbacks are queued
      to the non-CPU-0 queues.  This requres that portions of srcu_barrier()
      be enclosed in an SRCU read-side critical section.
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      e2f63836
    • Paul E. McKenney's avatar
      srcu: Dynamically allocate srcu_node array · 2ec30311
      Paul E. McKenney authored
      This commit shrinks the srcu_struct structure by converting its ->node
      field from a fixed-size compile-time array to a pointer to a dynamically
      allocated array.  In kernels built with large values of NR_CPUS that boot
      on systems with smaller numbers of CPUs, this can save significant memory.
      
      [ paulmck: Apply kernel test robot feedback. ]
      
      Reported-by: A cast of thousands
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      2ec30311
    • Paul E. McKenney's avatar
      srcu: Make Tree SRCU able to operate without snp_node array · 994f7068
      Paul E. McKenney authored
      This commit makes Tree SRCU able to operate without an snp_node
      array, that is, when the srcu_data structures' ->mynode pointers
      are NULL.  This can result in high contention on the srcu_struct
      structure's ->lock, but only when there are lots of call_srcu(),
      synchronize_srcu(), and synchronize_srcu_expedited() calls.
      
      Note that when there is no snp_node array, all SRCU callbacks use
      CPU 0's callback queue.  This is optimal in the common case of low
      update-side load because it removes the need to search each CPU
      for the single callback that made the grace period happen.
      Co-developed-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarNeeraj Upadhyay <quic_neeraju@quicinc.com>
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      994f7068
    • Paul E. McKenney's avatar
      srcu: Make srcu_funnel_gp_start() cache ->mynode in snp_leaf · 7b9e9b58
      Paul E. McKenney authored
      Currently, the srcu_funnel_gp_start() walks its local variable snp up the
      tree and reloads sdp->mynode whenever it is necessary to check whether
      it is still at the leaf srcu_node level.  This works, but is a bit more
      obtuse than absolutely necessary.  In addition, upcoming commits will
      dynamically size srcu_struct structures, in which case sdp->mynode will
      no longer necessarily be a constant, and this commit helps prepare for
      that dynamic sizing.
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      7b9e9b58
    • Paul E. McKenney's avatar
      srcu: Fix s/is/if/ typo in srcu_node comment · 95ebe80d
      Paul E. McKenney authored
      This commit fixed a typo in the srcu_node structure's ->srcu_have_cbs
      comment.  While in the area, redo a couple of comments to take advantage
      of 100-character line lengths.
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      95ebe80d
    • Paul E. McKenney's avatar
      srcu: Tighten cleanup_srcu_struct() GP checks · 8ed00760
      Paul E. McKenney authored
      Currently, cleanup_srcu_struct() checks for a grace period in progress,
      but it does not check for a grace period that has not yet started but
      which might start at any time.  Such a situation could result in a
      use-after-free bug, so this commit adds a check for a grace period that
      is needed but not yet started to cleanup_srcu_struct().
      Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
      8ed00760
  2. 03 Apr, 2022 8 commits
  3. 02 Apr, 2022 20 commits