diff options
| author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-04-14 11:00:36 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-04-14 11:00:36 -0400 |
| commit | 277a163c83d7ba93fba1e8980d29a9f8bfcfba6c (patch) | |
| tree | ccfd357d152292958957b6b8a993892e7a8cc95f /kernel/rcu/tree.c | |
| parent | a83b93a7480441a47856dc9104bea970e84cda87 (diff) | |
| parent | c9eaa447e77efe77b7fa4c953bd62de8297fd6c5 (diff) | |
Merge tag 'v3.15-rc1' into patchwork
Linux 3.15-rc1
* tag 'v3.15-rc1': (12180 commits)
Linux 3.15-rc1
mm: Initialize error in shmem_file_aio_read()
cifs: Use min_t() when comparing "size_t" and "unsigned long"
sym53c8xx_2: Set DID_REQUEUE return code when aborting squeue
powerpc: Don't try to set LPCR unless we're in hypervisor mode
futex: update documentation for ordering guarantees
ceph: fix pr_fmt() redefinition
vti: don't allow to add the same tunnel twice
gre: don't allow to add the same tunnel twice
drivers: net: xen-netfront: fix array initialization bug
missing bits of "splice: fix racy pipe->buffers uses"
cifs: fix the race in cifs_writev()
ceph_sync_{,direct_}write: fix an oops on ceph_osdc_new_request() failure
pktgen: be friendly to LLTX devices
r8152: check RTL8152_UNPLUG
net: sun4i-emac: add promiscuous support
net/apne: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
blackfin: cleanup board files
bf609: clock: drop unused clock bit set/clear functions
Blackfin: bf537: rename "CONFIG_ADT75"
...
Diffstat (limited to 'kernel/rcu/tree.c')
| -rw-r--r-- | kernel/rcu/tree.c | 80 |
1 files changed, 66 insertions, 14 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index b3d116cd072d..0c47e300210a 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
| 13 | * | 13 | * |
| 14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, you can access it online at |
| 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * http://www.gnu.org/licenses/gpl-2.0.html. |
| 17 | * | 17 | * |
| 18 | * Copyright IBM Corporation, 2008 | 18 | * Copyright IBM Corporation, 2008 |
| 19 | * | 19 | * |
| @@ -58,8 +58,6 @@ | |||
| 58 | #include <linux/suspend.h> | 58 | #include <linux/suspend.h> |
| 59 | 59 | ||
| 60 | #include "tree.h" | 60 | #include "tree.h" |
| 61 | #include <trace/events/rcu.h> | ||
| 62 | |||
| 63 | #include "rcu.h" | 61 | #include "rcu.h" |
| 64 | 62 | ||
| 65 | MODULE_ALIAS("rcutree"); | 63 | MODULE_ALIAS("rcutree"); |
| @@ -837,7 +835,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp, | |||
| 837 | * to the next. Only do this for the primary flavor of RCU. | 835 | * to the next. Only do this for the primary flavor of RCU. |
| 838 | */ | 836 | */ |
| 839 | if (rdp->rsp == rcu_state && | 837 | if (rdp->rsp == rcu_state && |
| 840 | ULONG_CMP_GE(ACCESS_ONCE(jiffies), rdp->rsp->jiffies_resched)) { | 838 | ULONG_CMP_GE(jiffies, rdp->rsp->jiffies_resched)) { |
| 841 | rdp->rsp->jiffies_resched += 5; | 839 | rdp->rsp->jiffies_resched += 5; |
| 842 | resched_cpu(rdp->cpu); | 840 | resched_cpu(rdp->cpu); |
| 843 | } | 841 | } |
| @@ -847,7 +845,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp, | |||
| 847 | 845 | ||
| 848 | static void record_gp_stall_check_time(struct rcu_state *rsp) | 846 | static void record_gp_stall_check_time(struct rcu_state *rsp) |
| 849 | { | 847 | { |
| 850 | unsigned long j = ACCESS_ONCE(jiffies); | 848 | unsigned long j = jiffies; |
| 851 | unsigned long j1; | 849 | unsigned long j1; |
| 852 | 850 | ||
| 853 | rsp->gp_start = j; | 851 | rsp->gp_start = j; |
| @@ -1005,7 +1003,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) | |||
| 1005 | 1003 | ||
| 1006 | if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp)) | 1004 | if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp)) |
| 1007 | return; | 1005 | return; |
| 1008 | j = ACCESS_ONCE(jiffies); | 1006 | j = jiffies; |
| 1009 | 1007 | ||
| 1010 | /* | 1008 | /* |
| 1011 | * Lots of memory barriers to reject false positives. | 1009 | * Lots of memory barriers to reject false positives. |
| @@ -1423,13 +1421,14 @@ static int rcu_gp_init(struct rcu_state *rsp) | |||
| 1423 | 1421 | ||
| 1424 | /* Advance to a new grace period and initialize state. */ | 1422 | /* Advance to a new grace period and initialize state. */ |
| 1425 | record_gp_stall_check_time(rsp); | 1423 | record_gp_stall_check_time(rsp); |
| 1426 | smp_wmb(); /* Record GP times before starting GP. */ | 1424 | /* Record GP times before starting GP, hence smp_store_release(). */ |
| 1427 | rsp->gpnum++; | 1425 | smp_store_release(&rsp->gpnum, rsp->gpnum + 1); |
| 1428 | trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start")); | 1426 | trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start")); |
| 1429 | raw_spin_unlock_irq(&rnp->lock); | 1427 | raw_spin_unlock_irq(&rnp->lock); |
| 1430 | 1428 | ||
| 1431 | /* Exclude any concurrent CPU-hotplug operations. */ | 1429 | /* Exclude any concurrent CPU-hotplug operations. */ |
| 1432 | mutex_lock(&rsp->onoff_mutex); | 1430 | mutex_lock(&rsp->onoff_mutex); |
| 1431 | smp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */ | ||
| 1433 | 1432 | ||
| 1434 | /* | 1433 | /* |
| 1435 | * Set the quiescent-state-needed bits in all the rcu_node | 1434 | * Set the quiescent-state-needed bits in all the rcu_node |
| @@ -1557,10 +1556,11 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) | |||
| 1557 | } | 1556 | } |
| 1558 | rnp = rcu_get_root(rsp); | 1557 | rnp = rcu_get_root(rsp); |
| 1559 | raw_spin_lock_irq(&rnp->lock); | 1558 | raw_spin_lock_irq(&rnp->lock); |
| 1560 | smp_mb__after_unlock_lock(); | 1559 | smp_mb__after_unlock_lock(); /* Order GP before ->completed update. */ |
| 1561 | rcu_nocb_gp_set(rnp, nocb); | 1560 | rcu_nocb_gp_set(rnp, nocb); |
| 1562 | 1561 | ||
| 1563 | rsp->completed = rsp->gpnum; /* Declare grace period done. */ | 1562 | /* Declare grace period done. */ |
| 1563 | ACCESS_ONCE(rsp->completed) = rsp->gpnum; | ||
| 1564 | trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end")); | 1564 | trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end")); |
| 1565 | rsp->fqs_state = RCU_GP_IDLE; | 1565 | rsp->fqs_state = RCU_GP_IDLE; |
| 1566 | rdp = this_cpu_ptr(rsp->rda); | 1566 | rdp = this_cpu_ptr(rsp->rda); |
| @@ -2304,7 +2304,7 @@ static void force_quiescent_state(struct rcu_state *rsp) | |||
| 2304 | if (rnp_old != NULL) | 2304 | if (rnp_old != NULL) |
| 2305 | raw_spin_unlock(&rnp_old->fqslock); | 2305 | raw_spin_unlock(&rnp_old->fqslock); |
| 2306 | if (ret) { | 2306 | if (ret) { |
| 2307 | rsp->n_force_qs_lh++; | 2307 | ACCESS_ONCE(rsp->n_force_qs_lh)++; |
| 2308 | return; | 2308 | return; |
| 2309 | } | 2309 | } |
| 2310 | rnp_old = rnp; | 2310 | rnp_old = rnp; |
| @@ -2316,7 +2316,7 @@ static void force_quiescent_state(struct rcu_state *rsp) | |||
| 2316 | smp_mb__after_unlock_lock(); | 2316 | smp_mb__after_unlock_lock(); |
| 2317 | raw_spin_unlock(&rnp_old->fqslock); | 2317 | raw_spin_unlock(&rnp_old->fqslock); |
| 2318 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { | 2318 | if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { |
| 2319 | rsp->n_force_qs_lh++; | 2319 | ACCESS_ONCE(rsp->n_force_qs_lh)++; |
| 2320 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); | 2320 | raw_spin_unlock_irqrestore(&rnp_old->lock, flags); |
| 2321 | return; /* Someone beat us to it. */ | 2321 | return; /* Someone beat us to it. */ |
| 2322 | } | 2322 | } |
| @@ -2639,6 +2639,58 @@ void synchronize_rcu_bh(void) | |||
| 2639 | } | 2639 | } |
| 2640 | EXPORT_SYMBOL_GPL(synchronize_rcu_bh); | 2640 | EXPORT_SYMBOL_GPL(synchronize_rcu_bh); |
| 2641 | 2641 | ||
| 2642 | /** | ||
| 2643 | * get_state_synchronize_rcu - Snapshot current RCU state | ||
| 2644 | * | ||
| 2645 | * Returns a cookie that is used by a later call to cond_synchronize_rcu() | ||
| 2646 | * to determine whether or not a full grace period has elapsed in the | ||
| 2647 | * meantime. | ||
| 2648 | */ | ||
| 2649 | unsigned long get_state_synchronize_rcu(void) | ||
| 2650 | { | ||
| 2651 | /* | ||
| 2652 | * Any prior manipulation of RCU-protected data must happen | ||
| 2653 | * before the load from ->gpnum. | ||
| 2654 | */ | ||
| 2655 | smp_mb(); /* ^^^ */ | ||
| 2656 | |||
| 2657 | /* | ||
| 2658 | * Make sure this load happens before the purportedly | ||
| 2659 | * time-consuming work between get_state_synchronize_rcu() | ||
| 2660 | * and cond_synchronize_rcu(). | ||
| 2661 | */ | ||
| 2662 | return smp_load_acquire(&rcu_state->gpnum); | ||
| 2663 | } | ||
| 2664 | EXPORT_SYMBOL_GPL(get_state_synchronize_rcu); | ||
| 2665 | |||
| 2666 | /** | ||
| 2667 | * cond_synchronize_rcu - Conditionally wait for an RCU grace period | ||
| 2668 | * | ||
| 2669 | * @oldstate: return value from earlier call to get_state_synchronize_rcu() | ||
| 2670 | * | ||
| 2671 | * If a full RCU grace period has elapsed since the earlier call to | ||
| 2672 | * get_state_synchronize_rcu(), just return. Otherwise, invoke | ||
| 2673 | * synchronize_rcu() to wait for a full grace period. | ||
| 2674 | * | ||
| 2675 | * Yes, this function does not take counter wrap into account. But | ||
| 2676 | * counter wrap is harmless. If the counter wraps, we have waited for | ||
| 2677 | * more than 2 billion grace periods (and way more on a 64-bit system!), | ||
| 2678 | * so waiting for one additional grace period should be just fine. | ||
| 2679 | */ | ||
| 2680 | void cond_synchronize_rcu(unsigned long oldstate) | ||
| 2681 | { | ||
| 2682 | unsigned long newstate; | ||
| 2683 | |||
| 2684 | /* | ||
| 2685 | * Ensure that this load happens before any RCU-destructive | ||
| 2686 | * actions the caller might carry out after we return. | ||
| 2687 | */ | ||
| 2688 | newstate = smp_load_acquire(&rcu_state->completed); | ||
| 2689 | if (ULONG_CMP_GE(oldstate, newstate)) | ||
| 2690 | synchronize_rcu(); | ||
| 2691 | } | ||
| 2692 | EXPORT_SYMBOL_GPL(cond_synchronize_rcu); | ||
| 2693 | |||
| 2642 | static int synchronize_sched_expedited_cpu_stop(void *data) | 2694 | static int synchronize_sched_expedited_cpu_stop(void *data) |
| 2643 | { | 2695 | { |
| 2644 | /* | 2696 | /* |
| @@ -2880,7 +2932,7 @@ static int rcu_pending(int cpu) | |||
| 2880 | * non-NULL, store an indication of whether all callbacks are lazy. | 2932 | * non-NULL, store an indication of whether all callbacks are lazy. |
| 2881 | * (If there are no callbacks, all of them are deemed to be lazy.) | 2933 | * (If there are no callbacks, all of them are deemed to be lazy.) |
| 2882 | */ | 2934 | */ |
| 2883 | static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy) | 2935 | static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy) |
| 2884 | { | 2936 | { |
| 2885 | bool al = true; | 2937 | bool al = true; |
| 2886 | bool hc = false; | 2938 | bool hc = false; |
