diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-27 03:13:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-27 03:13:04 -0400 |
commit | 57c0eabbd57e1a0872122525f6eeefe1f6529c33 (patch) | |
tree | 788d036bfbc9c92fb7663588033f50d2d6f5c828 /drivers/hv | |
parent | 392910cf3f8a0161d3da45d02ea17f2910d9193b (diff) | |
parent | c02ed2e75ef4c74e41e421acb4ef1494671585e8 (diff) |
Merge 4.11-rc4 into char-misc-next
We want the char-misc fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv')
-rw-r--r-- | drivers/hv/channel.c | 25 | ||||
-rw-r--r-- | drivers/hv/channel_mgmt.c | 27 | ||||
-rw-r--r-- | drivers/hv/hv_fcopy.c | 4 | ||||
-rw-r--r-- | drivers/hv/hv_kvp.c | 4 | ||||
-rw-r--r-- | drivers/hv/hv_snapshot.c | 4 | ||||
-rw-r--r-- | drivers/hv/hv_util.c | 2 | ||||
-rw-r--r-- | drivers/hv/hv_utils_transport.c | 12 | ||||
-rw-r--r-- | drivers/hv/hv_utils_transport.h | 1 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 6 |
9 files changed, 33 insertions, 52 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 5c1aa1c09064..736ac76d2a6a 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c | |||
@@ -502,12 +502,15 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) | |||
502 | 502 | ||
503 | wait_for_completion(&info->waitevent); | 503 | wait_for_completion(&info->waitevent); |
504 | 504 | ||
505 | if (channel->rescind) { | ||
506 | ret = -ENODEV; | ||
507 | goto post_msg_err; | ||
508 | } | ||
509 | |||
510 | post_msg_err: | 505 | post_msg_err: |
506 | /* | ||
507 | * If the channel has been rescinded; | ||
508 | * we will be awakened by the rescind | ||
509 | * handler; set the error code to zero so we don't leak memory. | ||
510 | */ | ||
511 | if (channel->rescind) | ||
512 | ret = 0; | ||
513 | |||
511 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 514 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
512 | list_del(&info->msglistentry); | 515 | list_del(&info->msglistentry); |
513 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); | 516 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
@@ -530,15 +533,13 @@ static int vmbus_close_internal(struct vmbus_channel *channel) | |||
530 | int ret; | 533 | int ret; |
531 | 534 | ||
532 | /* | 535 | /* |
533 | * vmbus_on_event(), running in the tasklet, can race | 536 | * vmbus_on_event(), running in the per-channel tasklet, can race |
534 | * with vmbus_close_internal() in the case of SMP guest, e.g., when | 537 | * with vmbus_close_internal() in the case of SMP guest, e.g., when |
535 | * the former is accessing channel->inbound.ring_buffer, the latter | 538 | * the former is accessing channel->inbound.ring_buffer, the latter |
536 | * could be freeing the ring_buffer pages. | 539 | * could be freeing the ring_buffer pages, so here we must stop it |
537 | * | 540 | * first. |
538 | * To resolve the race, we can serialize them by disabling the | ||
539 | * tasklet when the latter is running here. | ||
540 | */ | 541 | */ |
541 | hv_event_tasklet_disable(channel); | 542 | tasklet_disable(&channel->callback_event); |
542 | 543 | ||
543 | /* | 544 | /* |
544 | * In case a device driver's probe() fails (e.g., | 545 | * In case a device driver's probe() fails (e.g., |
@@ -605,8 +606,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) | |||
605 | get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); | 606 | get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); |
606 | 607 | ||
607 | out: | 608 | out: |
608 | hv_event_tasklet_enable(channel); | ||
609 | |||
610 | return ret; | 609 | return ret; |
611 | } | 610 | } |
612 | 611 | ||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index c1ba440a4987..735f9363f2e4 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -350,7 +350,8 @@ static struct vmbus_channel *alloc_channel(void) | |||
350 | static void free_channel(struct vmbus_channel *channel) | 350 | static void free_channel(struct vmbus_channel *channel) |
351 | { | 351 | { |
352 | tasklet_kill(&channel->callback_event); | 352 | tasklet_kill(&channel->callback_event); |
353 | kfree(channel); | 353 | |
354 | kfree_rcu(channel, rcu); | ||
354 | } | 355 | } |
355 | 356 | ||
356 | static void percpu_channel_enq(void *arg) | 357 | static void percpu_channel_enq(void *arg) |
@@ -359,14 +360,14 @@ static void percpu_channel_enq(void *arg) | |||
359 | struct hv_per_cpu_context *hv_cpu | 360 | struct hv_per_cpu_context *hv_cpu |
360 | = this_cpu_ptr(hv_context.cpu_context); | 361 | = this_cpu_ptr(hv_context.cpu_context); |
361 | 362 | ||
362 | list_add_tail(&channel->percpu_list, &hv_cpu->chan_list); | 363 | list_add_tail_rcu(&channel->percpu_list, &hv_cpu->chan_list); |
363 | } | 364 | } |
364 | 365 | ||
365 | static void percpu_channel_deq(void *arg) | 366 | static void percpu_channel_deq(void *arg) |
366 | { | 367 | { |
367 | struct vmbus_channel *channel = arg; | 368 | struct vmbus_channel *channel = arg; |
368 | 369 | ||
369 | list_del(&channel->percpu_list); | 370 | list_del_rcu(&channel->percpu_list); |
370 | } | 371 | } |
371 | 372 | ||
372 | 373 | ||
@@ -381,19 +382,6 @@ static void vmbus_release_relid(u32 relid) | |||
381 | true); | 382 | true); |
382 | } | 383 | } |
383 | 384 | ||
384 | void hv_event_tasklet_disable(struct vmbus_channel *channel) | ||
385 | { | ||
386 | tasklet_disable(&channel->callback_event); | ||
387 | } | ||
388 | |||
389 | void hv_event_tasklet_enable(struct vmbus_channel *channel) | ||
390 | { | ||
391 | tasklet_enable(&channel->callback_event); | ||
392 | |||
393 | /* In case there is any pending event */ | ||
394 | tasklet_schedule(&channel->callback_event); | ||
395 | } | ||
396 | |||
397 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) | 385 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) |
398 | { | 386 | { |
399 | unsigned long flags; | 387 | unsigned long flags; |
@@ -402,7 +390,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) | |||
402 | BUG_ON(!channel->rescind); | 390 | BUG_ON(!channel->rescind); |
403 | BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex)); | 391 | BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex)); |
404 | 392 | ||
405 | hv_event_tasklet_disable(channel); | ||
406 | if (channel->target_cpu != get_cpu()) { | 393 | if (channel->target_cpu != get_cpu()) { |
407 | put_cpu(); | 394 | put_cpu(); |
408 | smp_call_function_single(channel->target_cpu, | 395 | smp_call_function_single(channel->target_cpu, |
@@ -411,7 +398,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) | |||
411 | percpu_channel_deq(channel); | 398 | percpu_channel_deq(channel); |
412 | put_cpu(); | 399 | put_cpu(); |
413 | } | 400 | } |
414 | hv_event_tasklet_enable(channel); | ||
415 | 401 | ||
416 | if (channel->primary_channel == NULL) { | 402 | if (channel->primary_channel == NULL) { |
417 | list_del(&channel->listentry); | 403 | list_del(&channel->listentry); |
@@ -505,7 +491,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) | |||
505 | 491 | ||
506 | init_vp_index(newchannel, dev_type); | 492 | init_vp_index(newchannel, dev_type); |
507 | 493 | ||
508 | hv_event_tasklet_disable(newchannel); | ||
509 | if (newchannel->target_cpu != get_cpu()) { | 494 | if (newchannel->target_cpu != get_cpu()) { |
510 | put_cpu(); | 495 | put_cpu(); |
511 | smp_call_function_single(newchannel->target_cpu, | 496 | smp_call_function_single(newchannel->target_cpu, |
@@ -515,7 +500,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) | |||
515 | percpu_channel_enq(newchannel); | 500 | percpu_channel_enq(newchannel); |
516 | put_cpu(); | 501 | put_cpu(); |
517 | } | 502 | } |
518 | hv_event_tasklet_enable(newchannel); | ||
519 | 503 | ||
520 | /* | 504 | /* |
521 | * This state is used to indicate a successful open | 505 | * This state is used to indicate a successful open |
@@ -565,7 +549,6 @@ err_deq_chan: | |||
565 | list_del(&newchannel->listentry); | 549 | list_del(&newchannel->listentry); |
566 | mutex_unlock(&vmbus_connection.channel_mutex); | 550 | mutex_unlock(&vmbus_connection.channel_mutex); |
567 | 551 | ||
568 | hv_event_tasklet_disable(newchannel); | ||
569 | if (newchannel->target_cpu != get_cpu()) { | 552 | if (newchannel->target_cpu != get_cpu()) { |
570 | put_cpu(); | 553 | put_cpu(); |
571 | smp_call_function_single(newchannel->target_cpu, | 554 | smp_call_function_single(newchannel->target_cpu, |
@@ -574,7 +557,6 @@ err_deq_chan: | |||
574 | percpu_channel_deq(newchannel); | 557 | percpu_channel_deq(newchannel); |
575 | put_cpu(); | 558 | put_cpu(); |
576 | } | 559 | } |
577 | hv_event_tasklet_enable(newchannel); | ||
578 | 560 | ||
579 | vmbus_release_relid(newchannel->offermsg.child_relid); | 561 | vmbus_release_relid(newchannel->offermsg.child_relid); |
580 | 562 | ||
@@ -814,6 +796,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) | |||
814 | /* Allocate the channel object and save this offer. */ | 796 | /* Allocate the channel object and save this offer. */ |
815 | newchannel = alloc_channel(); | 797 | newchannel = alloc_channel(); |
816 | if (!newchannel) { | 798 | if (!newchannel) { |
799 | vmbus_release_relid(offer->child_relid); | ||
817 | pr_err("Unable to allocate channel object\n"); | 800 | pr_err("Unable to allocate channel object\n"); |
818 | return; | 801 | return; |
819 | } | 802 | } |
diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c index 3ce7559d7b41..daa75bd41f86 100644 --- a/drivers/hv/hv_fcopy.c +++ b/drivers/hv/hv_fcopy.c | |||
@@ -71,7 +71,6 @@ static DECLARE_WORK(fcopy_send_work, fcopy_send_data); | |||
71 | static const char fcopy_devname[] = "vmbus/hv_fcopy"; | 71 | static const char fcopy_devname[] = "vmbus/hv_fcopy"; |
72 | static u8 *recv_buffer; | 72 | static u8 *recv_buffer; |
73 | static struct hvutil_transport *hvt; | 73 | static struct hvutil_transport *hvt; |
74 | static struct completion release_event; | ||
75 | /* | 74 | /* |
76 | * This state maintains the version number registered by the daemon. | 75 | * This state maintains the version number registered by the daemon. |
77 | */ | 76 | */ |
@@ -329,7 +328,6 @@ static void fcopy_on_reset(void) | |||
329 | 328 | ||
330 | if (cancel_delayed_work_sync(&fcopy_timeout_work)) | 329 | if (cancel_delayed_work_sync(&fcopy_timeout_work)) |
331 | fcopy_respond_to_host(HV_E_FAIL); | 330 | fcopy_respond_to_host(HV_E_FAIL); |
332 | complete(&release_event); | ||
333 | } | 331 | } |
334 | 332 | ||
335 | int hv_fcopy_init(struct hv_util_service *srv) | 333 | int hv_fcopy_init(struct hv_util_service *srv) |
@@ -337,7 +335,6 @@ int hv_fcopy_init(struct hv_util_service *srv) | |||
337 | recv_buffer = srv->recv_buffer; | 335 | recv_buffer = srv->recv_buffer; |
338 | fcopy_transaction.recv_channel = srv->channel; | 336 | fcopy_transaction.recv_channel = srv->channel; |
339 | 337 | ||
340 | init_completion(&release_event); | ||
341 | /* | 338 | /* |
342 | * When this driver loads, the user level daemon that | 339 | * When this driver loads, the user level daemon that |
343 | * processes the host requests may not yet be running. | 340 | * processes the host requests may not yet be running. |
@@ -359,5 +356,4 @@ void hv_fcopy_deinit(void) | |||
359 | fcopy_transaction.state = HVUTIL_DEVICE_DYING; | 356 | fcopy_transaction.state = HVUTIL_DEVICE_DYING; |
360 | cancel_delayed_work_sync(&fcopy_timeout_work); | 357 | cancel_delayed_work_sync(&fcopy_timeout_work); |
361 | hvutil_transport_destroy(hvt); | 358 | hvutil_transport_destroy(hvt); |
362 | wait_for_completion(&release_event); | ||
363 | } | 359 | } |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index b0a36e8a7268..e99ff2ddad40 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -101,7 +101,6 @@ static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); | |||
101 | static const char kvp_devname[] = "vmbus/hv_kvp"; | 101 | static const char kvp_devname[] = "vmbus/hv_kvp"; |
102 | static u8 *recv_buffer; | 102 | static u8 *recv_buffer; |
103 | static struct hvutil_transport *hvt; | 103 | static struct hvutil_transport *hvt; |
104 | static struct completion release_event; | ||
105 | /* | 104 | /* |
106 | * Register the kernel component with the user-level daemon. | 105 | * Register the kernel component with the user-level daemon. |
107 | * As part of this registration, pass the LIC version number. | 106 | * As part of this registration, pass the LIC version number. |
@@ -712,7 +711,6 @@ static void kvp_on_reset(void) | |||
712 | if (cancel_delayed_work_sync(&kvp_timeout_work)) | 711 | if (cancel_delayed_work_sync(&kvp_timeout_work)) |
713 | kvp_respond_to_host(NULL, HV_E_FAIL); | 712 | kvp_respond_to_host(NULL, HV_E_FAIL); |
714 | kvp_transaction.state = HVUTIL_DEVICE_INIT; | 713 | kvp_transaction.state = HVUTIL_DEVICE_INIT; |
715 | complete(&release_event); | ||
716 | } | 714 | } |
717 | 715 | ||
718 | int | 716 | int |
@@ -721,7 +719,6 @@ hv_kvp_init(struct hv_util_service *srv) | |||
721 | recv_buffer = srv->recv_buffer; | 719 | recv_buffer = srv->recv_buffer; |
722 | kvp_transaction.recv_channel = srv->channel; | 720 | kvp_transaction.recv_channel = srv->channel; |
723 | 721 | ||
724 | init_completion(&release_event); | ||
725 | /* | 722 | /* |
726 | * When this driver loads, the user level daemon that | 723 | * When this driver loads, the user level daemon that |
727 | * processes the host requests may not yet be running. | 724 | * processes the host requests may not yet be running. |
@@ -745,5 +742,4 @@ void hv_kvp_deinit(void) | |||
745 | cancel_delayed_work_sync(&kvp_timeout_work); | 742 | cancel_delayed_work_sync(&kvp_timeout_work); |
746 | cancel_work_sync(&kvp_sendkey_work); | 743 | cancel_work_sync(&kvp_sendkey_work); |
747 | hvutil_transport_destroy(hvt); | 744 | hvutil_transport_destroy(hvt); |
748 | wait_for_completion(&release_event); | ||
749 | } | 745 | } |
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index 216d02277759..6831efd73394 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c | |||
@@ -79,7 +79,6 @@ static int dm_reg_value; | |||
79 | static const char vss_devname[] = "vmbus/hv_vss"; | 79 | static const char vss_devname[] = "vmbus/hv_vss"; |
80 | static __u8 *recv_buffer; | 80 | static __u8 *recv_buffer; |
81 | static struct hvutil_transport *hvt; | 81 | static struct hvutil_transport *hvt; |
82 | static struct completion release_event; | ||
83 | 82 | ||
84 | static void vss_timeout_func(struct work_struct *dummy); | 83 | static void vss_timeout_func(struct work_struct *dummy); |
85 | static void vss_handle_request(struct work_struct *dummy); | 84 | static void vss_handle_request(struct work_struct *dummy); |
@@ -359,13 +358,11 @@ static void vss_on_reset(void) | |||
359 | if (cancel_delayed_work_sync(&vss_timeout_work)) | 358 | if (cancel_delayed_work_sync(&vss_timeout_work)) |
360 | vss_respond_to_host(HV_E_FAIL); | 359 | vss_respond_to_host(HV_E_FAIL); |
361 | vss_transaction.state = HVUTIL_DEVICE_INIT; | 360 | vss_transaction.state = HVUTIL_DEVICE_INIT; |
362 | complete(&release_event); | ||
363 | } | 361 | } |
364 | 362 | ||
365 | int | 363 | int |
366 | hv_vss_init(struct hv_util_service *srv) | 364 | hv_vss_init(struct hv_util_service *srv) |
367 | { | 365 | { |
368 | init_completion(&release_event); | ||
369 | if (vmbus_proto_version < VERSION_WIN8_1) { | 366 | if (vmbus_proto_version < VERSION_WIN8_1) { |
370 | pr_warn("Integration service 'Backup (volume snapshot)'" | 367 | pr_warn("Integration service 'Backup (volume snapshot)'" |
371 | " not supported on this host version.\n"); | 368 | " not supported on this host version.\n"); |
@@ -398,5 +395,4 @@ void hv_vss_deinit(void) | |||
398 | cancel_delayed_work_sync(&vss_timeout_work); | 395 | cancel_delayed_work_sync(&vss_timeout_work); |
399 | cancel_work_sync(&vss_handle_request_work); | 396 | cancel_work_sync(&vss_handle_request_work); |
400 | hvutil_transport_destroy(hvt); | 397 | hvutil_transport_destroy(hvt); |
401 | wait_for_completion(&release_event); | ||
402 | } | 398 | } |
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 3042eaa13062..186b10083c55 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
@@ -590,6 +590,8 @@ static int hv_timesync_init(struct hv_util_service *srv) | |||
590 | if (!hyperv_cs) | 590 | if (!hyperv_cs) |
591 | return -ENODEV; | 591 | return -ENODEV; |
592 | 592 | ||
593 | spin_lock_init(&host_ts.lock); | ||
594 | |||
593 | INIT_WORK(&wrk.work, hv_set_host_time); | 595 | INIT_WORK(&wrk.work, hv_set_host_time); |
594 | 596 | ||
595 | /* | 597 | /* |
diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c index c235a9515267..4402a71e23f7 100644 --- a/drivers/hv/hv_utils_transport.c +++ b/drivers/hv/hv_utils_transport.c | |||
@@ -182,10 +182,11 @@ static int hvt_op_release(struct inode *inode, struct file *file) | |||
182 | * connects back. | 182 | * connects back. |
183 | */ | 183 | */ |
184 | hvt_reset(hvt); | 184 | hvt_reset(hvt); |
185 | mutex_unlock(&hvt->lock); | ||
186 | 185 | ||
187 | if (mode_old == HVUTIL_TRANSPORT_DESTROY) | 186 | if (mode_old == HVUTIL_TRANSPORT_DESTROY) |
188 | hvt_transport_free(hvt); | 187 | complete(&hvt->release); |
188 | |||
189 | mutex_unlock(&hvt->lock); | ||
189 | 190 | ||
190 | return 0; | 191 | return 0; |
191 | } | 192 | } |
@@ -304,6 +305,7 @@ struct hvutil_transport *hvutil_transport_init(const char *name, | |||
304 | 305 | ||
305 | init_waitqueue_head(&hvt->outmsg_q); | 306 | init_waitqueue_head(&hvt->outmsg_q); |
306 | mutex_init(&hvt->lock); | 307 | mutex_init(&hvt->lock); |
308 | init_completion(&hvt->release); | ||
307 | 309 | ||
308 | spin_lock(&hvt_list_lock); | 310 | spin_lock(&hvt_list_lock); |
309 | list_add(&hvt->list, &hvt_list); | 311 | list_add(&hvt->list, &hvt_list); |
@@ -351,6 +353,8 @@ void hvutil_transport_destroy(struct hvutil_transport *hvt) | |||
351 | if (hvt->cn_id.idx > 0 && hvt->cn_id.val > 0) | 353 | if (hvt->cn_id.idx > 0 && hvt->cn_id.val > 0) |
352 | cn_del_callback(&hvt->cn_id); | 354 | cn_del_callback(&hvt->cn_id); |
353 | 355 | ||
354 | if (mode_old != HVUTIL_TRANSPORT_CHARDEV) | 356 | if (mode_old == HVUTIL_TRANSPORT_CHARDEV) |
355 | hvt_transport_free(hvt); | 357 | wait_for_completion(&hvt->release); |
358 | |||
359 | hvt_transport_free(hvt); | ||
356 | } | 360 | } |
diff --git a/drivers/hv/hv_utils_transport.h b/drivers/hv/hv_utils_transport.h index d98f5225c3e6..79afb626e166 100644 --- a/drivers/hv/hv_utils_transport.h +++ b/drivers/hv/hv_utils_transport.h | |||
@@ -41,6 +41,7 @@ struct hvutil_transport { | |||
41 | int outmsg_len; /* its length */ | 41 | int outmsg_len; /* its length */ |
42 | wait_queue_head_t outmsg_q; /* poll/read wait queue */ | 42 | wait_queue_head_t outmsg_q; /* poll/read wait queue */ |
43 | struct mutex lock; /* protects struct members */ | 43 | struct mutex lock; /* protects struct members */ |
44 | struct completion release; /* synchronize with fd release */ | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | struct hvutil_transport *hvutil_transport_init(const char *name, | 47 | struct hvutil_transport *hvutil_transport_init(const char *name, |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 8b272d389ce5..0087b49095eb 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -937,8 +937,10 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) | |||
937 | if (relid == 0) | 937 | if (relid == 0) |
938 | continue; | 938 | continue; |
939 | 939 | ||
940 | rcu_read_lock(); | ||
941 | |||
940 | /* Find channel based on relid */ | 942 | /* Find channel based on relid */ |
941 | list_for_each_entry(channel, &hv_cpu->chan_list, percpu_list) { | 943 | list_for_each_entry_rcu(channel, &hv_cpu->chan_list, percpu_list) { |
942 | if (channel->offermsg.child_relid != relid) | 944 | if (channel->offermsg.child_relid != relid) |
943 | continue; | 945 | continue; |
944 | 946 | ||
@@ -954,6 +956,8 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) | |||
954 | tasklet_schedule(&channel->callback_event); | 956 | tasklet_schedule(&channel->callback_event); |
955 | } | 957 | } |
956 | } | 958 | } |
959 | |||
960 | rcu_read_unlock(); | ||
957 | } | 961 | } |
958 | } | 962 | } |
959 | 963 | ||