Loading fuse_sdcard_provider.cpp +11 −63 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ #include <stdio.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <sys/mount.h> #include <sys/stat.h> #include <unistd.h> Loading Loading @@ -60,81 +59,30 @@ static void close_file(void* cookie) { close(fd->fd); } struct token { pthread_t th; const char* path; int result; }; static void* run_sdcard_fuse(void* cookie) { token* t = reinterpret_cast<token*>(cookie); bool start_sdcard_fuse(const char* path) { struct stat sb; if (stat(t->path, &sb) < 0) { fprintf(stderr, "failed to stat %s: %s\n", t->path, strerror(errno)); t->result = -1; return NULL; if (stat(path, &sb) == -1) { fprintf(stderr, "failed to stat %s: %s\n", path, strerror(errno)); return false; } struct file_data fd; struct provider_vtab vtab; fd.fd = open(t->path, O_RDONLY); if (fd.fd < 0) { fprintf(stderr, "failed to open %s: %s\n", t->path, strerror(errno)); t->result = -1; return NULL; file_data fd; fd.fd = open(path, O_RDONLY); if (fd.fd == -1) { fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); return false; } fd.file_size = sb.st_size; fd.block_size = 65536; provider_vtab vtab; vtab.read_block = read_block_file; vtab.close = close_file; t->result = run_fuse_sideload(&vtab, &fd, fd.file_size, fd.block_size); return NULL; } // How long (in seconds) we wait for the fuse-provided package file to // appear, before timing out. #define SDCARD_INSTALL_TIMEOUT 10 void* start_sdcard_fuse(const char* path) { token* t = new token; t->path = path; pthread_create(&(t->th), NULL, run_sdcard_fuse, t); struct stat st; int i; for (i = 0; i < SDCARD_INSTALL_TIMEOUT; ++i) { if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) { if (errno == ENOENT && i < SDCARD_INSTALL_TIMEOUT-1) { sleep(1); continue; } else { return NULL; } } } // The installation process expects to find the sdcard unmounted. // Unmount it with MNT_DETACH so that our open file continues to // work but new references see it as unmounted. umount2("/sdcard", MNT_DETACH); return t; } void finish_sdcard_fuse(void* cookie) { if (cookie == NULL) return; token* t = reinterpret_cast<token*>(cookie); // Calling stat() on this magic filename signals the fuse // filesystem to shut down. struct stat st; stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st); pthread_join(t->th, NULL); delete t; return run_fuse_sideload(&vtab, &fd, fd.file_size, fd.block_size) == 0; } fuse_sdcard_provider.h +1 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ #ifndef __FUSE_SDCARD_PROVIDER_H #define __FUSE_SDCARD_PROVIDER_H void* start_sdcard_fuse(const char* path); void finish_sdcard_fuse(void* token); bool start_sdcard_fuse(const char* path); #endif recovery.cpp +57 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <sys/klog.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> Loading Loading @@ -833,6 +834,10 @@ static void choose_recovery_file(Device* device) { } } // How long (in seconds) we wait for the fuse-provided package file to // appear, before timing out. #define SDCARD_INSTALL_TIMEOUT 10 static int apply_from_sdcard(Device* device, bool* wipe_cache) { modified_flash = true; Loading @@ -850,14 +855,62 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) { ui->Print("\n-- Install %s ...\n", path); set_sdcard_update_bootloader_message(); void* token = start_sdcard_fuse(path); int status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, // We used to use fuse in a thread as opposed to a process. Since accessing // through fuse involves going from kernel to userspace to kernel, it leads // to deadlock when a page fault occurs. (Bug: 26313124) pid_t child; if ((child = fork()) == 0) { bool status = start_sdcard_fuse(path); _exit(status ? EXIT_SUCCESS : EXIT_FAILURE); } // FUSE_SIDELOAD_HOST_PATHNAME will start to exist once the fuse in child // process is ready. int result = INSTALL_ERROR; int status; bool waited = false; for (int i = 0; i < SDCARD_INSTALL_TIMEOUT; ++i) { if (waitpid(child, &status, WNOHANG) == -1) { result = INSTALL_ERROR; waited = true; break; } struct stat sb; if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &sb) == -1) { if (errno == ENOENT && i < SDCARD_INSTALL_TIMEOUT-1) { sleep(1); continue; } else { LOGE("Timed out waiting for the fuse-provided package.\n"); result = INSTALL_ERROR; kill(child, SIGKILL); break; } } result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, TEMPORARY_INSTALL_FILE, false); break; } if (!waited) { // Calling stat() on this magic filename signals the fuse // filesystem to shut down. struct stat sb; stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &sb); waitpid(child, &status, 0); } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("Error exit from the fuse process: %d\n", WEXITSTATUS(status)); } finish_sdcard_fuse(token); ensure_path_unmounted(SDCARD_ROOT); return status; return result; } // Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION Loading Loading
fuse_sdcard_provider.cpp +11 −63 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ #include <stdio.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <sys/mount.h> #include <sys/stat.h> #include <unistd.h> Loading Loading @@ -60,81 +59,30 @@ static void close_file(void* cookie) { close(fd->fd); } struct token { pthread_t th; const char* path; int result; }; static void* run_sdcard_fuse(void* cookie) { token* t = reinterpret_cast<token*>(cookie); bool start_sdcard_fuse(const char* path) { struct stat sb; if (stat(t->path, &sb) < 0) { fprintf(stderr, "failed to stat %s: %s\n", t->path, strerror(errno)); t->result = -1; return NULL; if (stat(path, &sb) == -1) { fprintf(stderr, "failed to stat %s: %s\n", path, strerror(errno)); return false; } struct file_data fd; struct provider_vtab vtab; fd.fd = open(t->path, O_RDONLY); if (fd.fd < 0) { fprintf(stderr, "failed to open %s: %s\n", t->path, strerror(errno)); t->result = -1; return NULL; file_data fd; fd.fd = open(path, O_RDONLY); if (fd.fd == -1) { fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno)); return false; } fd.file_size = sb.st_size; fd.block_size = 65536; provider_vtab vtab; vtab.read_block = read_block_file; vtab.close = close_file; t->result = run_fuse_sideload(&vtab, &fd, fd.file_size, fd.block_size); return NULL; } // How long (in seconds) we wait for the fuse-provided package file to // appear, before timing out. #define SDCARD_INSTALL_TIMEOUT 10 void* start_sdcard_fuse(const char* path) { token* t = new token; t->path = path; pthread_create(&(t->th), NULL, run_sdcard_fuse, t); struct stat st; int i; for (i = 0; i < SDCARD_INSTALL_TIMEOUT; ++i) { if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) { if (errno == ENOENT && i < SDCARD_INSTALL_TIMEOUT-1) { sleep(1); continue; } else { return NULL; } } } // The installation process expects to find the sdcard unmounted. // Unmount it with MNT_DETACH so that our open file continues to // work but new references see it as unmounted. umount2("/sdcard", MNT_DETACH); return t; } void finish_sdcard_fuse(void* cookie) { if (cookie == NULL) return; token* t = reinterpret_cast<token*>(cookie); // Calling stat() on this magic filename signals the fuse // filesystem to shut down. struct stat st; stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st); pthread_join(t->th, NULL); delete t; return run_fuse_sideload(&vtab, &fd, fd.file_size, fd.block_size) == 0; }
fuse_sdcard_provider.h +1 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ #ifndef __FUSE_SDCARD_PROVIDER_H #define __FUSE_SDCARD_PROVIDER_H void* start_sdcard_fuse(const char* path); void finish_sdcard_fuse(void* token); bool start_sdcard_fuse(const char* path); #endif
recovery.cpp +57 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <sys/klog.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> Loading Loading @@ -833,6 +834,10 @@ static void choose_recovery_file(Device* device) { } } // How long (in seconds) we wait for the fuse-provided package file to // appear, before timing out. #define SDCARD_INSTALL_TIMEOUT 10 static int apply_from_sdcard(Device* device, bool* wipe_cache) { modified_flash = true; Loading @@ -850,14 +855,62 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) { ui->Print("\n-- Install %s ...\n", path); set_sdcard_update_bootloader_message(); void* token = start_sdcard_fuse(path); int status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, // We used to use fuse in a thread as opposed to a process. Since accessing // through fuse involves going from kernel to userspace to kernel, it leads // to deadlock when a page fault occurs. (Bug: 26313124) pid_t child; if ((child = fork()) == 0) { bool status = start_sdcard_fuse(path); _exit(status ? EXIT_SUCCESS : EXIT_FAILURE); } // FUSE_SIDELOAD_HOST_PATHNAME will start to exist once the fuse in child // process is ready. int result = INSTALL_ERROR; int status; bool waited = false; for (int i = 0; i < SDCARD_INSTALL_TIMEOUT; ++i) { if (waitpid(child, &status, WNOHANG) == -1) { result = INSTALL_ERROR; waited = true; break; } struct stat sb; if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &sb) == -1) { if (errno == ENOENT && i < SDCARD_INSTALL_TIMEOUT-1) { sleep(1); continue; } else { LOGE("Timed out waiting for the fuse-provided package.\n"); result = INSTALL_ERROR; kill(child, SIGKILL); break; } } result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, TEMPORARY_INSTALL_FILE, false); break; } if (!waited) { // Calling stat() on this magic filename signals the fuse // filesystem to shut down. struct stat sb; stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &sb); waitpid(child, &status, 0); } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("Error exit from the fuse process: %d\n", WEXITSTATUS(status)); } finish_sdcard_fuse(token); ensure_path_unmounted(SDCARD_ROOT); return status; return result; } // Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION Loading