So now I see that such directories are created by zygote (by a forked process) with fs_prepare_dir call.
And then it is mounted to /storage/emulated/{userId}.
However, sometimes fs_prepare_dir fails with an error message
cutils : Failed to chmod(/mnt/shell/emulated/10, 0): No such file or directory
Interestingly, chmod is always performed either after a corresponding directory is created with mkdir or if already exists (checked with lstat). Hence, failure with an error message mentioned above might indicate some multi-process issues (and this seems to be plausible since all these operations on directories are performed by forked processes).
However, all the directory operations (lstat, mkdir, chmod) are wrapped with TEMP_FAILURE_RETRYmacro, and I'm not sure whether it should save us from issues that might happen with concurrent access to directories from multiple processes...
I do not understand how but the device gets stuck in a situation where mkdir reports that directory is already created but it's really not.
shell@flo:/mnt/shell/emulated # ls -la
drwxrwx--x root sdcard_r 2014-09-18 01:53 0
drwxrwx--x root sdcard_r 2014-09-18 01:53 legacy
drwxrwx--x root sdcard_r 2014-09-18 01:52 obb
shell@flo:/mnt/shell/emulated # mkdir 10
mkdir failed for 10, File exists
255|shell@flo:/mnt/shell/emulated # ls -la
drwxrwx--x root sdcard_r 2014-09-18 01:53 0
drwxrwx--x root sdcard_r 2014-09-18 01:53 legacy
drwxrwx--x root sdcard_r 2014-09-18 01:52 obbI seem to have found what is the reason of such a state.
Android framework reuses user IDs. For example if you create a user with id 10, then remove it, this id will be used again after user is considered to be completely removed.
Completely removed means stopped by activity manager (processes are killed), all the data directories (/data/user/{id}, /data/system/users/{id}, /mnt/shell/emulated/{id}) are deleted.
However, sometimes there is a process left running for this user id 10 after user is removed. The process can be rather random. Once it was gallery3d, another time com.google.android.googlequicksearchbox:search, yet another time our own launcher app. But it seem to be an app the uses external storage. In bugreport logs I see it sometimes keeping an open file at/storage/emulated/10/ where our /mnt/shell/emulated/10 is bind mounted. But keeping an open file is not necessary. It's sufficient to have a bind mounted directory.
As soon as this process is killed, apps for a newly created user with id 10 can be started.
The interesting thing is that files opened by this process are marked as (deleted) in lsof output if they are located at /data/user/{id}. But files at /storage/emulated/{id} are not marked as deleted.
So, activity manager seems to be guilty for not killing a process for a stopped user or allowing this process to be started after user is stopped.
--
You received this message because you are subscribed to a topic in the Google Groups "android-platform" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/android-platform/8BbzoSd2rAI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to android-platfo...@googlegroups.com.
To post to this group, send email to android-...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-platform.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and all its topics, send an email to android-platform+unsubscribe@googlegroups.com.
To post to this group, send email to android-platform@googlegroups.com.
Visit this group at http://groups.google.com/group/android-platform.
For more options, visit https://groups.google.com/d/optout.