Print this page
    
NEX-20218 Backport Illumos #9474 txg_kick() fails to see that we are quiescing, forcing transactions to their next stages without leaving them accumulate changes
MFV illumos-gate@fa41d87de9ec9000964c605eb01d6dc19e4a1abe
    9464 txg_kick() fails to see that we are quiescing, forcing transactions to their next stages without leaving them accumulate changes
    Reviewed by: Matt Ahrens <matt@delphix.com>
    Reviewed by: Brad Lewis <brad.lewis@delphix.com>
    Reviewed by: Andriy Gapon <avg@FreeBSD.org>
    Approved by: Dan McDonald <danmcd@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/zfs/sys/txg_impl.h
          +++ new/usr/src/uts/common/fs/zfs/sys/txg_impl.h
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  
    | 
      ↓ open down ↓ | 
    17 lines elided | 
    
      ↑ open up ↑ | 
  
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*
  28      - * Copyright (c) 2013 by Delphix. All rights reserved.
       28 + * Copyright (c) 2013, 2017 by Delphix. All rights reserved.
  29   29   */
  30   30  
  31   31  #ifndef _SYS_TXG_IMPL_H
  32   32  #define _SYS_TXG_IMPL_H
  33   33  
  34   34  #include <sys/spa.h>
  35   35  #include <sys/txg.h>
  36   36  
  37   37  #ifdef  __cplusplus
  38   38  extern "C" {
  39   39  #endif
  40   40  
  41   41  /*
  42   42   * The tx_cpu structure is a per-cpu structure that is used to track
  43   43   * the number of active transaction holds (tc_count). As transactions
  44   44   * are assigned into a transaction group the appropriate tc_count is
  45   45   * incremented to indicate that there are pending changes that have yet
  46   46   * to quiesce. Consumers evenutally call txg_rele_to_sync() to decrement
  47   47   * the tc_count. A transaction group is not considered quiesced until all
  48   48   * tx_cpu structures have reached a tc_count of zero.
  49   49   *
  50   50   * This structure is a per-cpu structure by design. Updates to this structure
  51   51   * are frequent and concurrent. Having a single structure would result in
  52   52   * heavy lock contention so a per-cpu design was implemented. With the fanned
  53   53   * out mutex design, consumers only need to lock the mutex associated with
  54   54   * thread's cpu.
  55   55   *
  56   56   * The tx_cpu contains two locks, the tc_lock and tc_open_lock.
  57   57   * The tc_lock is used to protect all members of the tx_cpu structure with
  58   58   * the exception of the tc_open_lock. This lock should only be held for a
  59   59   * short period of time, typically when updating the value of tc_count.
  60   60   *
  61   61   * The tc_open_lock protects the tx_open_txg member of the tx_state structure.
  62   62   * This lock is used to ensure that transactions are only assigned into
  63   63   * the current open transaction group. In order to move the current open
  64   64   * transaction group to the quiesce phase, the txg_quiesce thread must
  65   65   * grab all tc_open_locks, increment the tx_open_txg, and drop the locks.
  66   66   * The tc_open_lock is held until the transaction is assigned into the
  67   67   * transaction group. Typically, this is a short operation but if throttling
  68   68   * is occuring it may be held for longer periods of time.
  69   69   */
  70   70  struct tx_cpu {
  71   71          kmutex_t        tc_open_lock;   /* protects tx_open_txg */
  72   72          kmutex_t        tc_lock;        /* protects the rest of this struct */
  73   73          kcondvar_t      tc_cv[TXG_SIZE];
  74   74          uint64_t        tc_count[TXG_SIZE];     /* tx hold count on each txg */
  75   75          list_t          tc_callbacks[TXG_SIZE]; /* commit cb list */
  76   76          char            tc_pad[8];              /* pad to fill 3 cache lines */
  77   77  };
  78   78  
  79   79  /*
  80   80   * The tx_state structure maintains the state information about the different
  81   81   * stages of the pool's transcation groups. A per pool tx_state structure
  82   82   * is used to track this information. The tx_state structure also points to
  83   83   * an array of tx_cpu structures (described above). Although the tx_sync_lock
  84   84   * is used to protect the members of this structure, it is not used to
  
    | 
      ↓ open down ↓ | 
    46 lines elided | 
    
      ↑ open up ↑ | 
  
  85   85   * protect the tx_open_txg. Instead a special lock in the tx_cpu structure
  86   86   * is used. Readers of tx_open_txg must grab the per-cpu tc_open_lock.
  87   87   * Any thread wishing to update tx_open_txg must grab the tc_open_lock on
  88   88   * every cpu (see txg_quiesce()).
  89   89   */
  90   90  typedef struct tx_state {
  91   91          tx_cpu_t        *tx_cpu;        /* protects access to tx_open_txg */
  92   92          kmutex_t        tx_sync_lock;   /* protects the rest of this struct */
  93   93  
  94   94          uint64_t        tx_open_txg;    /* currently open txg id */
       95 +        uint64_t        tx_quiescing_txg; /* currently quiescing txg id */
  95   96          uint64_t        tx_quiesced_txg; /* quiesced txg waiting for sync */
  96   97          uint64_t        tx_syncing_txg; /* currently syncing txg id */
  97   98          uint64_t        tx_synced_txg;  /* last synced txg id */
  98   99  
  99  100          hrtime_t        tx_open_time;   /* start time of tx_open_txg */
 100  101  
 101  102          uint64_t        tx_sync_txg_waiting; /* txg we're waiting to sync */
 102  103          uint64_t        tx_quiesce_txg_waiting; /* txg we're waiting to open */
 103  104  
 104  105          kcondvar_t      tx_sync_more_cv;
 105  106          kcondvar_t      tx_sync_done_cv;
 106  107          kcondvar_t      tx_quiesce_more_cv;
 107  108          kcondvar_t      tx_quiesce_done_cv;
 108  109          kcondvar_t      tx_timeout_cv;
 109  110          kcondvar_t      tx_exit_cv;     /* wait for all threads to exit */
 110  111  
 111  112          uint8_t         tx_threads;     /* number of threads */
 112  113          uint8_t         tx_exiting;     /* set when we're exiting */
 113  114  
 114  115          kthread_t       *tx_sync_thread;
 115  116          kthread_t       *tx_quiesce_thread;
 116  117  
 117  118          taskq_t         *tx_commit_cb_taskq; /* commit callback taskq */
 118  119  } tx_state_t;
 119  120  
 120  121  #ifdef  __cplusplus
 121  122  }
 122  123  #endif
 123  124  
 124  125  #endif  /* _SYS_TXG_IMPL_H */
  
    | 
      ↓ open down ↓ | 
    20 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX