aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Bao2016-01-13 17:05:20 -0600
committerTao Bao2016-01-13 23:29:20 -0600
commitcdcf28f54f085520a96f4f9e480b8df324c5decb (patch)
treec6184ee0a3460cbcdb054f0680187a786c2cfdb9 /fuse_sdcard_provider.cpp
parentab9db5284ec6113c7d84f70f805dca21c3e6efd7 (diff)
downloadplatform-bootable-recovery-cdcf28f54f085520a96f4f9e480b8df324c5decb.tar.gz
platform-bootable-recovery-cdcf28f54f085520a96f4f9e480b8df324c5decb.tar.xz
platform-bootable-recovery-cdcf28f54f085520a96f4f9e480b8df324c5decb.zip
recovery: Fork a process for fuse when sideloading from SD card.
For applying update from SD card, we used to use a thread to serve the file with fuse. Since accessing through fuse involves going from kernel to userspace to kernel, it may run into deadlock (e.g. for mmap_sem) when a page fault occurs. Switch to using a process instead. Bug: 23783099 Bug: 26313124 Change-Id: Iac0f55b1bdb078cadb520cfe1133e70fbb26eadd
Diffstat (limited to 'fuse_sdcard_provider.cpp')
-rw-r--r--fuse_sdcard_provider.cpp74
1 files changed, 11 insertions, 63 deletions
diff --git a/fuse_sdcard_provider.cpp b/fuse_sdcard_provider.cpp
index eb6454f1..df963127 100644
--- a/fuse_sdcard_provider.cpp
+++ b/fuse_sdcard_provider.cpp
@@ -18,7 +18,6 @@
18#include <stdio.h> 18#include <stdio.h>
19#include <string.h> 19#include <string.h>
20#include <errno.h> 20#include <errno.h>
21#include <pthread.h>
22#include <sys/mount.h> 21#include <sys/mount.h>
23#include <sys/stat.h> 22#include <sys/stat.h>
24#include <unistd.h> 23#include <unistd.h>
@@ -60,81 +59,30 @@ static void close_file(void* cookie) {
60 close(fd->fd); 59 close(fd->fd);
61} 60}
62 61
63struct token { 62bool start_sdcard_fuse(const char* path) {
64 pthread_t th;
65 const char* path;
66 int result;
67};
68
69static void* run_sdcard_fuse(void* cookie) {
70 token* t = reinterpret_cast<token*>(cookie);
71
72 struct stat sb; 63 struct stat sb;
73 if (stat(t->path, &sb) < 0) { 64 if (stat(path, &sb) == -1) {
74 fprintf(stderr, "failed to stat %s: %s\n", t->path, strerror(errno)); 65 fprintf(stderr, "failed to stat %s: %s\n", path, strerror(errno));
75 t->result = -1; 66 return false;
76 return NULL;
77 } 67 }
78 68
79 struct file_data fd; 69 file_data fd;
80 struct provider_vtab vtab; 70 fd.fd = open(path, O_RDONLY);
81 71 if (fd.fd == -1) {
82 fd.fd = open(t->path, O_RDONLY); 72 fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno));
83 if (fd.fd < 0) { 73 return false;
84 fprintf(stderr, "failed to open %s: %s\n", t->path, strerror(errno));
85 t->result = -1;
86 return NULL;
87 } 74 }
88 fd.file_size = sb.st_size; 75 fd.file_size = sb.st_size;
89 fd.block_size = 65536; 76 fd.block_size = 65536;
90 77
78 provider_vtab vtab;
91 vtab.read_block = read_block_file; 79 vtab.read_block = read_block_file;
92 vtab.close = close_file; 80 vtab.close = close_file;
93 81
94 t->result = run_fuse_sideload(&vtab, &fd, fd.file_size, fd.block_size);
95 return NULL;
96}
97
98// How long (in seconds) we wait for the fuse-provided package file to
99// appear, before timing out.
100#define SDCARD_INSTALL_TIMEOUT 10
101
102void* start_sdcard_fuse(const char* path) {
103 token* t = new token;
104
105 t->path = path;
106 pthread_create(&(t->th), NULL, run_sdcard_fuse, t);
107
108 struct stat st;
109 int i;
110 for (i = 0; i < SDCARD_INSTALL_TIMEOUT; ++i) {
111 if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) {
112 if (errno == ENOENT && i < SDCARD_INSTALL_TIMEOUT-1) {
113 sleep(1);
114 continue;
115 } else {
116 return NULL;
117 }
118 }
119 }
120
121 // The installation process expects to find the sdcard unmounted. 82 // The installation process expects to find the sdcard unmounted.
122 // Unmount it with MNT_DETACH so that our open file continues to 83 // Unmount it with MNT_DETACH so that our open file continues to
123 // work but new references see it as unmounted. 84 // work but new references see it as unmounted.
124 umount2("/sdcard", MNT_DETACH); 85 umount2("/sdcard", MNT_DETACH);
125 86
126 return t; 87 return run_fuse_sideload(&vtab, &fd, fd.file_size, fd.block_size) == 0;
127}
128
129void finish_sdcard_fuse(void* cookie) {
130 if (cookie == NULL) return;
131 token* t = reinterpret_cast<token*>(cookie);
132
133 // Calling stat() on this magic filename signals the fuse
134 // filesystem to shut down.
135 struct stat st;
136 stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
137
138 pthread_join(t->th, NULL);
139 delete t;
140} 88}