event = field->u.perf_counter->e[ctx->cpu];
if (likely(event)) {
- event->pmu->read(event);
- value = local64_read(&event->count);
+ if (unlikely(event->state == PERF_EVENT_STATE_ERROR)) {
+ value = 0;
+ } else {
+ event->pmu->read(event);
+ value = local64_read(&event->count);
+ }
} else {
/*
* Perf chooses not to be clever and not to support enabling a
cpu, NULL, overflow_callback);
if (!pevent || IS_ERR(pevent))
return NOTIFY_BAD;
+ if (pevent->state == PERF_EVENT_STATE_ERROR) {
+ perf_event_release_kernel(pevent);
+ return NOTIFY_BAD;
+ }
barrier(); /* Create perf counter before setting event */
events[cpu] = pevent;
break;
ret = -EINVAL;
goto counter_error;
}
+ if (events[cpu]->state == PERF_EVENT_STATE_ERROR) {
+ ret = -EBUSY;
+ goto counter_busy;
+ }
}
put_online_cpus();
wrapper_vmalloc_sync_all();
return 0;
+counter_busy:
counter_error:
for_each_online_cpu(cpu) {
if (events[cpu] && !IS_ERR(events[cpu]))