U盘不识别问题处理
1。U盘插入后,不被识别
进行U进行断开的时候,由于当时有其他的进程正在使用,没有正常的把umount 掉,导致下一次进行mount 的时候,导致 mount不成功。
U盘拔出的流程:
240 status_t PublicVolume::doUnmount() {
241 // Unmount the storage before we kill the FUSE process. If we kill
242 // the FUSE process first, most file system operations will return
243 // ENOTCONN until the unmount completes. This is an exotic and unusual
244 // error code and might cause broken behaviour in applications.
kill 正在使用U盘的进程
245 KillProcessesUsingPath(getPath());
246
调用ForceUnmount 进行umount2操作
247 ForceUnmount(kAsecPath);
248
249 ForceUnmount(mFuseDefault);
250 ForceUnmount(mFuseRead);
251 ForceUnmount(mFuseWrite);
252 ForceUnmount(mFuseFull);
253 ForceUnmount(mRawPath);
254
删除对应的文件夹
255 rmdir(mFuseDefault.c_str());
256 rmdir(mFuseRead.c_str());
257 rmdir(mFuseWrite.c_str());
258 rmdir(mFuseFull.c_str());
259 rmdir(mRawPath.c_str());
260
clear 文件节点
261 mFuseDefault.clear();
262 mFuseRead.clear();
263 mFuseWrite.clear();
264 mFuseFull.clear();
265 mRawPath.clear();
266
267 return OK;
268 }
根据目前的log 分析,已正常kill 正在使用的进程后,在其sleep 5s 的过程中,有新的进程来访问,导致umount 失败
针对ForceUnmount 原生的处理逻辑是,先kill 掉使用的进程,然后sleep 5s,最后进行umount 操作,
141 status_t ForceUnmount(const std::string& path) {
142 const char* cpath = path.c_str();
143 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
144 return OK;
145 }
146 // Apps might still be handling eject request, so wait before
147 // we start sending signals
148 if (sSleepOnUnmount) sleep(5);
149
//以下每个kill 完成后,都会进行sleep 5s,之后再umount
150 KillProcessesWithOpenFiles(path, SIGINT);
151 if (sSleepOnUnmount) sleep(5);
152 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
153 return OK;
154 }
155
156 KillProcessesWithOpenFiles(path, SIGTERM);
157 if (sSleepOnUnmount) sleep(5);
158 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
159 return OK;
160 }
161
162 KillProcessesWithOpenFiles(path, SIGKILL);
163 if (sSleepOnUnmount) sleep(5);
164 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
165 return OK;
166 }
167
168 PLOG(ERROR) << "ForceUnmount Failed: " << path;
169 return -errno;
170 }
解决方案:
在进行ForceUnmount 操作的时候,如果没有进程使用u盘,则直接进行umount 操作,不需要sleep 500ms
137 status_t ForceUnmount(const std::string& path) {
138 const char* cpath = path.c_str();
139 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
140 return OK;
141 }
142 // Apps might still be handling eject request, so wait before
143 // we start sending signals
144 if (sSleepOnUnmount) sleep(5);
145
//以下每个kill 完成后,会先判断当前有没有进程在使用,如果没有进程使用,直接umount,不会进行进行sleep 5s
146 if (KillProcessesWithOpenFiles(path, SIGINT) != 0) {
147 if (sSleepOnUnmount) sleep(5);
148 }
149 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
150 return OK;
151 } else {
152 PLOG(WARNING) << "umount2 failed with signal SIGINT, path: " << path <<"errno:"<<errno;
153 }
154
155 if (KillProcessesWithOpenFiles(path, SIGTERM) != 0) {
156 if (sSleepOnUnmount) sleep(5);
157 }
158 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
159 return OK;
160 } else {
161 PLOG(WARNING) << "umount2 failed with signal SIGTERM, path: " << path <<"errno:"<<errno;
162 }
163
164 if (KillProcessesWithOpenFiles(path, SIGKILL) != 0) {
165 if (sSleepOnUnmount) sleep(5);
166 }
167 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
168 return OK;
169 } else {
170 PLOG(WARNING) << "umount2 failed with signal SIGKILL, path: " << path <<"errno:"<<errno;
171 }
172
173 //加入log,是否还有进程占用设备节点
174 PLOG(ERROR) << "print pid for path: " << path;
175 if (KillProcessesWithOpenFiles(path, 0) == 0) {
176 PLOG(WARNING) << "no pid using path: " << path;
177 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
178 return OK;
179 } else {
180 PLOG(WARNING) << "umount2 failed with signal 0, path: " << path <<"errno:"<<errno;
181 }
182 }
183 PLOG(ERROR) << "Failed to ForceUnmount path: " << path <<"errno:"<<errno;
184 return -errno;
185 }