From d9e682c2bec7651a6b36fc834480e2f4e8fc05b8 Mon Sep 17 00:00:00 2001 From: Shadichy Date: Thu, 24 Apr 2025 14:31:09 +0700 Subject: [PATCH 1/3] btrfs-progs: Add `pthread_cancel` implementation for bionic Created `pthread/btrfs_pthread.h` and `pthread/btrfs_pthread.c` to allow Android and bionic libc emulating `pthread_setcanceltype`, `pthread_setcancelstate`, `pthread_cancel` and some other definitions. Since Android NDK does not support `pthread_cancel()`, this workaround method uses `pthread_kill()` instead. Signed-off-by: Shadichy --- Makefile | 4 +++- cmds/rescue-chunk-recover.c | 2 +- cmds/scrub.c | 2 +- cmds/send.c | 2 +- common/task-utils.c | 2 +- common/task-utils.h | 2 +- convert/main.c | 2 +- convert/source-ext2.c | 2 +- convert/source-fs.h | 2 +- image/image-create.c | 2 +- image/image-restore.c | 2 +- image/metadump.h | 2 +- mkfs/main.c | 2 +- pthread/btrfs_pthread.c | 40 +++++++++++++++++++++++++++++++++++++ pthread/btrfs_pthread.h | 24 ++++++++++++++++++++++ pthread/pthread.sym | 8 ++++++++ 16 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 pthread/btrfs_pthread.c create mode 100644 pthread/btrfs_pthread.h create mode 100644 pthread/pthread.sym diff --git a/Makefile b/Makefile index 7e36aa4257..6fbc27e1d7 100644 --- a/Makefile +++ b/Makefile @@ -215,6 +215,7 @@ objects = \ kernel-shared/uuid-tree.o \ kernel-shared/volumes.o \ kernel-shared/zoned.o \ + pthread/btrfs_pthread.o \ common/array.o \ common/cpu-utils.o \ common/device-scan.o \ @@ -292,7 +293,7 @@ tune_objects = tune/main.o tune/seeding.o tune/change-uuid.o tune/change-metadat all_objects = $(objects) $(cmds_objects) $(libbtrfs_objects) $(convert_objects) \ $(mkfs_objects) $(image_objects) $(tune_objects) $(libbtrfsutil_objects) -tags_files = $(addsuffix /*.[ch], . check cmds common convert crypto image include mkfs tune \ +tags_files = $(addsuffix /*.[ch], . check cmds common convert crypto image include mkfs pthread tune \ kernel-lib kernel-shared kernel-shared/uapi \ libbtrfs libbtrfsutil libbtrfsutil/python tests) @@ -928,6 +929,7 @@ clean: $(CLEANDIRS) libbtrfs/*.o libbtrfs/.deps/*.o.d \ libbtrfsutil/*.o libbtrfsutil/.deps/*.o.d \ mkfs/*.o mkfs/.deps/*.o.d \ + pthread/*.o pthread/.deps/*.o.d \ tune/*.o tune/.deps/*.o.d $(Q)$(RM) -fd -- .deps */.deps */*/.deps @echo "Cleaning test targets" diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c index 60a705817c..d00ecfd309 100644 --- a/cmds/rescue-chunk-recover.c +++ b/cmds/rescue-chunk-recover.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include diff --git a/cmds/scrub.c b/cmds/scrub.c index b1d2f731b1..d910b06e20 100644 --- a/cmds/scrub.c +++ b/cmds/scrub.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include diff --git a/cmds/send.c b/cmds/send.c index 4fc6f07dd6..16023215a5 100644 --- a/cmds/send.c +++ b/cmds/send.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include diff --git a/common/task-utils.c b/common/task-utils.c index 5bcbfb239e..29423a448b 100644 --- a/common/task-utils.c +++ b/common/task-utils.c @@ -15,7 +15,7 @@ */ #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include diff --git a/common/task-utils.h b/common/task-utils.h index 624d0f94a1..9660372040 100644 --- a/common/task-utils.h +++ b/common/task-utils.h @@ -19,7 +19,7 @@ #include "kerncompat.h" #include -#include +#include "pthread/btrfs_pthread.h" struct periodic_info { int timer_fd; diff --git a/convert/main.c b/convert/main.c index 0dc75c9eb1..4ee881764f 100644 --- a/convert/main.c +++ b/convert/main.c @@ -88,7 +88,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include diff --git a/convert/source-ext2.c b/convert/source-ext2.c index fde3fff044..bc3fa93a7e 100644 --- a/convert/source-ext2.c +++ b/convert/source-ext2.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include diff --git a/convert/source-fs.h b/convert/source-fs.h index b26e184294..37e6ed9315 100644 --- a/convert/source-fs.h +++ b/convert/source-fs.h @@ -19,7 +19,7 @@ #include "kerncompat.h" #include -#include +#include "pthread/btrfs_pthread.h" #include "kernel-shared/uapi/btrfs_tree.h" #include "convert/common.h" diff --git a/image/image-create.c b/image/image-create.c index bfe6c93f6f..6d6c6853f5 100644 --- a/image/image-create.c +++ b/image/image-create.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include "kernel-lib/list.h" #include "kernel-lib/rbtree.h" diff --git a/image/image-restore.c b/image/image-restore.c index 667b981123..5655d24e51 100644 --- a/image/image-restore.c +++ b/image/image-restore.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include "kernel-lib/list.h" #include "kernel-lib/rbtree.h" diff --git a/image/metadump.h b/image/metadump.h index a4c5d05ed1..17ec4afa32 100644 --- a/image/metadump.h +++ b/image/metadump.h @@ -18,7 +18,7 @@ #define __BTRFS_IMAGE_METADUMP_H__ #include "kerncompat.h" -#include +#include "pthread/btrfs_pthread.h" #include "kernel-lib/list.h" #include "kernel-lib/sizes.h" #include "kernel-shared/ctree.h" diff --git a/mkfs/main.c b/mkfs/main.c index 4c2ce98c78..53429a8784 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include "pthread/btrfs_pthread.h" #include #include #include "kernel-lib/list.h" diff --git a/pthread/btrfs_pthread.c b/pthread/btrfs_pthread.c new file mode 100644 index 0000000000..6d644d0bb6 --- /dev/null +++ b/pthread/btrfs_pthread.c @@ -0,0 +1,40 @@ +#include "include/config.h" + +#ifdef __ANDROID__ + +/* Workaround for `pthread_cancel()` in Android, using `pthread_kill()` instead, + * as Android NDK does not support `pthread_cancel()`. + */ + +#include +#include +#include "btrfs_pthread.h" + +int pthread_setcanceltype(int type, int *oldtype) { return 0; } +int pthread_setcancelstate(int state, int *oldstate) { return 0; } +int pthread_cancel(pthread_t thread_id) { + int status; + if ((status = btrfs_set_thread_exit_handler()) == 0) { + status = pthread_kill(thread_id, SIGUSR1); + } + return status; +} + +void btrfs_thread_exit_handler(int sig) { + pthread_exit(0); +} + +int btrfs_set_thread_exit_handler() { + int rc; + struct sigaction actions; + + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = btrfs_thread_exit_handler; + + rc = sigaction(SIGUSR1, &actions, NULL); + return rc; +} + +#endif diff --git a/pthread/btrfs_pthread.h b/pthread/btrfs_pthread.h new file mode 100644 index 0000000000..b177d79c4d --- /dev/null +++ b/pthread/btrfs_pthread.h @@ -0,0 +1,24 @@ +#include "include/config.h" + +#include + +#ifdef __ANDROID__ + +/* Adding missing `pthread` related definitions in Android. + */ + +#define PTHREAD_CANCELED ((void *) -1) + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 0 +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 0 + +int pthread_setcanceltype(int type, int *oldtype); +int pthread_setcancelstate(int state, int *oldstate); +int pthread_cancel(pthread_t thread_id); + +int btrfs_set_thread_exit_handler(); +void btrfs_thread_exit_handler(int sig); + +#endif diff --git a/pthread/pthread.sym b/pthread/pthread.sym new file mode 100644 index 0000000000..f5142ae21f --- /dev/null +++ b/pthread/pthread.sym @@ -0,0 +1,8 @@ +PTHREAD_0.1 { +global: + pthread_setcanceltype; /* used */ + pthread_setcancelstate; /* used */ + pthread_cancel; /* used */ +local: + *; +}; From fd3959cef01a7c64aa467f15f5525af5a57ebfe3 Mon Sep 17 00:00:00 2001 From: Shadichy Date: Thu, 24 Apr 2025 14:33:42 +0700 Subject: [PATCH 2/3] btrfs-progs: rescue-chunk-recover: Added `atomic` patch This patch is from termux/termux-packages Signed-off-by: Shadichy --- cmds/rescue-chunk-recover.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c index d00ecfd309..b9b53bef86 100644 --- a/cmds/rescue-chunk-recover.c +++ b/cmds/rescue-chunk-recover.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef __ANDROID__ +#include +#endif #include "kernel-lib/list.h" #include "kernel-shared/accessors.h" #include "kernel-shared/extent-io-tree.h" @@ -82,6 +85,9 @@ struct device_scan { struct btrfs_device *dev; int fd; u64 bytenr; +#ifdef __ANDROID__ + atomic_flag thread_running; +#endif }; static struct extent_record *btrfs_new_extent_record(struct extent_buffer *eb) @@ -761,8 +767,12 @@ static int scan_one_device(void *dev_scan_struct) return 1; buf = malloc(sizeof(*buf) + rc->nodesize); - if (!buf) + if (!buf) { +#ifdef __ANDROID__ + atomic_flag_clear(&dev_scan->thread_running); +#endif return -ENOMEM; + } buf->len = rc->nodesize; bytenr = 0; @@ -823,6 +833,9 @@ static int scan_one_device(void *dev_scan_struct) out: close(fd); free(buf); +#ifdef __ANDROID__ + atomic_flag_clear(&dev_scan->thread_running); +#endif return ret; } @@ -869,6 +882,9 @@ static int scan_devices(struct recover_control *rc) dev_scans[devidx].dev = dev; dev_scans[devidx].fd = fd; dev_scans[devidx].bytenr = -1; +#ifdef __ANDROID__ + atomic_flag_test_and_set(&dev_scans[devidx].thread_running); +#endif devidx++; } @@ -887,8 +903,15 @@ static int scan_devices(struct recover_control *rc) for (i = 0; i < devidx; i++) { if (dev_scans[i].bytenr == -1) continue; +#ifdef __ANDROID__ + if (atomic_flag_test_and_set(&dev_scans[i].thread_running)) + ret = EBUSY; + else + ret = pthread_join(t_scans[i], (void **)&t_rets[i]); +#else ret = pthread_tryjoin_np(t_scans[i], (void **)&t_rets[i]); +#endif if (ret == EBUSY) { all_done = false; continue; From ad58f7421e72d906c24f665adb59f84c9b860d98 Mon Sep 17 00:00:00 2001 From: Shadichy Date: Thu, 24 Apr 2025 14:40:10 +0700 Subject: [PATCH 3/3] btrfs-progs: list-chunks: Workarounds for replacing `qsort_r` when targeting Android Android NDK does not support `qsort_r`, this workaround first add a list of `id` to struct `compare`, and then reverse the list, and finally do the sorting stuffs using `qsort`. This helps preserve the sorting order without `qsort_r` Signed-off-by: Shadichy --- cmds/inspect.c | 20 +++++++++++++++++++- common/sort-utils.c | 3 +++ common/sort-utils.h | 3 +++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cmds/inspect.c b/cmds/inspect.c index d689e08570..3e951b6ca1 100644 --- a/cmds/inspect.c +++ b/cmds/inspect.c @@ -878,9 +878,27 @@ static int print_list_chunks(struct list_chunks_ctx *ctx, const char *sortmode, } /* Skip additional sort if nothing defined by user. */ - if (comp.count > 0) + if (comp.count > 0) { +#ifdef __ANDROID__ + for (i = comp.count - 1; i >= 0; i--) { + if (comp.id[i] == CHUNK_SORT_PSTART) { + qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_cmp_t)cmp_cse_pstart); + } + else if (comp.id[i] == CHUNK_SORT_LSTART) { + qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_cmp_t)cmp_cse_lstart); + } + else if (comp.id[i] == CHUNK_SORT_USAGE) { + qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_cmp_t)cmp_cse_usage); + } + else if (comp.id[i] == CHUNK_SORT_LENGTH) { + qsort(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_cmp_t)cmp_cse_length); + } + } +#else qsort_r(ctx->stats, ctx->length, sizeof(ctx->stats[0]), (sort_r_cmp_t)compare_cmp_multi, &comp); +#endif + } col_count = 9; /* Two rows for header and separator. */ diff --git a/common/sort-utils.c b/common/sort-utils.c index 39c5d252c3..7ea75d5172 100644 --- a/common/sort-utils.c +++ b/common/sort-utils.c @@ -78,6 +78,9 @@ int compare_add_sort_id(struct compare *comp, int id) if (comp->sortdef[i].name == NULL) return -1; if (comp->sortdef[i].id == id) { +#ifdef __ANDROID__ + comp->id[comp->count] = id; +#endif comp->comp[comp->count] = comp->sortdef[i].comp; comp->count++; break; diff --git a/common/sort-utils.h b/common/sort-utils.h index 09be7b7d06..4d5f6cc2f3 100644 --- a/common/sort-utils.h +++ b/common/sort-utils.h @@ -89,6 +89,9 @@ struct compare { unsigned long invert_map; int count; const struct sortdef *sortdef; +#ifdef __ANDROID__ + int id[SORT_MAX_KEYS]; +#endif }; int compare_init(struct compare *comp, const struct sortdef *sortdef);