Skip to content

Commit 0567461

Browse files
eggonleagregkh
authored andcommitted
binder: return pending info for frozen async txns
An async transaction to a frozen process will still be successfully put in the queue. But this pending async transaction won't be processed until the target process is unfrozen at an unspecified time in the future. Pass this important information back to the user space caller by returning BR_TRANSACTION_PENDING_FROZEN. Signed-off-by: Li Li <[email protected]> Acked-by: Carlos Llamas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7feb35b commit 0567461

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

drivers/android/binder.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,7 +2728,10 @@ binder_find_outdated_transaction_ilocked(struct binder_transaction *t,
27282728
*
27292729
* Return: 0 if the transaction was successfully queued
27302730
* BR_DEAD_REPLY if the target process or thread is dead
2731-
* BR_FROZEN_REPLY if the target process or thread is frozen
2731+
* BR_FROZEN_REPLY if the target process or thread is frozen and
2732+
* the sync transaction was rejected
2733+
* BR_TRANSACTION_PENDING_FROZEN if the target process is frozen
2734+
* and the async transaction was successfully queued
27322735
*/
27332736
static int binder_proc_transaction(struct binder_transaction *t,
27342737
struct binder_proc *proc,
@@ -2738,6 +2741,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
27382741
bool oneway = !!(t->flags & TF_ONE_WAY);
27392742
bool pending_async = false;
27402743
struct binder_transaction *t_outdated = NULL;
2744+
bool frozen = false;
27412745

27422746
BUG_ON(!node);
27432747
binder_node_lock(node);
@@ -2751,15 +2755,16 @@ static int binder_proc_transaction(struct binder_transaction *t,
27512755

27522756
binder_inner_proc_lock(proc);
27532757
if (proc->is_frozen) {
2758+
frozen = true;
27542759
proc->sync_recv |= !oneway;
27552760
proc->async_recv |= oneway;
27562761
}
27572762

2758-
if ((proc->is_frozen && !oneway) || proc->is_dead ||
2763+
if ((frozen && !oneway) || proc->is_dead ||
27592764
(thread && thread->is_dead)) {
27602765
binder_inner_proc_unlock(proc);
27612766
binder_node_unlock(node);
2762-
return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY;
2767+
return frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY;
27632768
}
27642769

27652770
if (!thread && !pending_async)
@@ -2770,7 +2775,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
27702775
} else if (!pending_async) {
27712776
binder_enqueue_work_ilocked(&t->work, &proc->todo);
27722777
} else {
2773-
if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) {
2778+
if ((t->flags & TF_UPDATE_TXN) && frozen) {
27742779
t_outdated = binder_find_outdated_transaction_ilocked(t,
27752780
&node->async_todo);
27762781
if (t_outdated) {
@@ -2807,6 +2812,9 @@ static int binder_proc_transaction(struct binder_transaction *t,
28072812
binder_stats_deleted(BINDER_STAT_TRANSACTION);
28082813
}
28092814

2815+
if (oneway && frozen)
2816+
return BR_TRANSACTION_PENDING_FROZEN;
2817+
28102818
return 0;
28112819
}
28122820

@@ -3607,9 +3615,17 @@ static void binder_transaction(struct binder_proc *proc,
36073615
} else {
36083616
BUG_ON(target_node == NULL);
36093617
BUG_ON(t->buffer->async_transaction != 1);
3610-
binder_enqueue_thread_work(thread, tcomplete);
36113618
return_error = binder_proc_transaction(t, target_proc, NULL);
3612-
if (return_error)
3619+
/*
3620+
* Let the caller know when async transaction reaches a frozen
3621+
* process and is put in a pending queue, waiting for the target
3622+
* process to be unfrozen.
3623+
*/
3624+
if (return_error == BR_TRANSACTION_PENDING_FROZEN)
3625+
tcomplete->type = BINDER_WORK_TRANSACTION_PENDING;
3626+
binder_enqueue_thread_work(thread, tcomplete);
3627+
if (return_error &&
3628+
return_error != BR_TRANSACTION_PENDING_FROZEN)
36133629
goto err_dead_proc_or_thread;
36143630
}
36153631
if (target_thread)
@@ -4440,10 +4456,13 @@ static int binder_thread_read(struct binder_proc *proc,
44404456
binder_stat_br(proc, thread, cmd);
44414457
} break;
44424458
case BINDER_WORK_TRANSACTION_COMPLETE:
4459+
case BINDER_WORK_TRANSACTION_PENDING:
44434460
case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
44444461
if (proc->oneway_spam_detection_enabled &&
44454462
w->type == BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
44464463
cmd = BR_ONEWAY_SPAM_SUSPECT;
4464+
else if (w->type == BINDER_WORK_TRANSACTION_PENDING)
4465+
cmd = BR_TRANSACTION_PENDING_FROZEN;
44474466
else
44484467
cmd = BR_TRANSACTION_COMPLETE;
44494468
binder_inner_proc_unlock(proc);
@@ -6159,6 +6178,7 @@ static const char * const binder_return_strings[] = {
61596178
"BR_FAILED_REPLY",
61606179
"BR_FROZEN_REPLY",
61616180
"BR_ONEWAY_SPAM_SUSPECT",
6181+
"BR_TRANSACTION_PENDING_FROZEN"
61626182
};
61636183

61646184
static const char * const binder_command_strings[] = {

drivers/android/binder_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ enum binder_stat_types {
133133
};
134134

135135
struct binder_stats {
136-
atomic_t br[_IOC_NR(BR_ONEWAY_SPAM_SUSPECT) + 1];
136+
atomic_t br[_IOC_NR(BR_TRANSACTION_PENDING_FROZEN) + 1];
137137
atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
138138
atomic_t obj_created[BINDER_STAT_COUNT];
139139
atomic_t obj_deleted[BINDER_STAT_COUNT];
@@ -152,6 +152,7 @@ struct binder_work {
152152
enum binder_work_type {
153153
BINDER_WORK_TRANSACTION = 1,
154154
BINDER_WORK_TRANSACTION_COMPLETE,
155+
BINDER_WORK_TRANSACTION_PENDING,
155156
BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT,
156157
BINDER_WORK_RETURN_ERROR,
157158
BINDER_WORK_NODE,

include/uapi/linux/android/binder.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ enum binder_driver_return_protocol {
450450

451451
BR_FROZEN_REPLY = _IO('r', 18),
452452
/*
453-
* The target of the last transaction (either a bcTRANSACTION or
453+
* The target of the last sync transaction (either a bcTRANSACTION or
454454
* a bcATTEMPT_ACQUIRE) is frozen. No parameters.
455455
*/
456456

@@ -460,6 +460,11 @@ enum binder_driver_return_protocol {
460460
* asynchronous transaction makes the allocated async buffer size exceed
461461
* detection threshold. No parameters.
462462
*/
463+
464+
BR_TRANSACTION_PENDING_FROZEN = _IO('r', 20),
465+
/*
466+
* The target of the last async transaction is frozen. No parameters.
467+
*/
463468
};
464469

465470
enum binder_driver_command_protocol {

0 commit comments

Comments
 (0)