diff options
author | Steve Kondik <steve@cyngn.com> | 2016-07-23 20:16:24 -0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2016-07-23 20:24:07 -0700 |
commit | d63e6757fa22fcb58653233fce035deed8036a1b (patch) | |
tree | 65f5d3a75350b7bef0d109842ab8add38da97819 | |
parent | 53bf23431d5e9f5b320d9e2adb7b10f650178dc9 (diff) | |
download | system_core-d63e6757fa22fcb58653233fce035deed8036a1b.zip system_core-d63e6757fa22fcb58653233fce035deed8036a1b.tar.gz system_core-d63e6757fa22fcb58653233fce035deed8036a1b.tar.bz2 |
sdcard: Add support for sdcardfs!
* sdcardfs is a kernel filesystem developed by Samsung and recently
seen in AOSP's common kernel branches. It entirely eliminates
the need to use FUSE for sdcard emulation and moves all the
wrapping logic to kernel. This vastly improves performance for
use cases which read/write to emulated as well as removable
cards.
Change-Id: I3e394a99e0a4b5beacaeddc0d4dd4855ff0cf082
-rw-r--r-- | sdcard/sdcard.c | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 98af250..c0f60ed 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -41,6 +41,7 @@ #include <cutils/hashmap.h> #include <cutils/log.h> #include <cutils/multiuser.h> +#include <cutils/properties.h> #include <private/android_filesystem_config.h> @@ -1776,24 +1777,39 @@ static int usage() { return 1; } -static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) { +static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask, bool use_sdcardfs) { char opts[256]; - fuse->fd = open("/dev/fuse", O_RDWR); - if (fuse->fd == -1) { - ERROR("failed to open fuse device: %s\n", strerror(errno)); - return -1; + if (use_sdcardfs) { + fuse->fd = open("/dev/fuse", O_RDWR); + if (fuse->fd == -1) { + ERROR("failed to open fuse device: %s\n", strerror(errno)); + return -1; + } } umount2(fuse->dest_path, MNT_DETACH); - snprintf(opts, sizeof(opts), - "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", - fuse->fd, fuse->global->uid, fuse->global->gid); - if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | - MS_NOATIME, opts) != 0) { - ERROR("failed to mount fuse filesystem: %s\n", strerror(errno)); - return -1; + if (use_sdcardfs) { + snprintf(opts, sizeof(opts), + "%sfsuid=%d,fsgid=%d,userid=%d,gid=%d,mask=%04o,reserved_mb=20", + (fuse->global->multi_user ? "multiuser," : ""), + fuse->global->uid, fuse->global->gid, + fuse->global->root.userid, gid, mask); + if (mount(fuse->global->source_path, fuse->dest_path, "sdcardfs", + MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts) != 0) { + ERROR("failed to mount sdcardfs filesystem: %s\n", strerror(errno)); + return -1; + } + } else { + snprintf(opts, sizeof(opts), + "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", + fuse->fd, fuse->global->uid, fuse->global->gid); + if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | + MS_NOATIME, opts) != 0) { + ERROR("failed to mount fuse filesystem: %s\n", strerror(errno)); + return -1; + } } fuse->gid = gid; @@ -1803,7 +1819,7 @@ static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) { } static void run(const char* source_path, const char* label, uid_t uid, - gid_t gid, userid_t userid, bool multi_user, bool full_write) { + gid_t gid, userid_t userid, bool multi_user, bool full_write, bool use_sdcardfs) { struct fuse_global global; struct fuse fuse_default; struct fuse fuse_read; @@ -1875,9 +1891,9 @@ static void run(const char* source_path, const char* label, uid_t uid, if (multi_user) { /* Multi-user storage is fully isolated per user, so "other" * permissions are completely masked off. */ - if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006) - || fuse_setup(&fuse_read, AID_EVERYBODY, 0027) - || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0027)) { + if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006, use_sdcardfs) + || fuse_setup(&fuse_read, AID_EVERYBODY, 0027, use_sdcardfs) + || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0027, use_sdcardfs)) { ERROR("failed to fuse_setup\n"); exit(1); } @@ -1885,14 +1901,19 @@ static void run(const char* source_path, const char* label, uid_t uid, /* Physical storage is readable by all users on device, but * the Android directories are masked off to a single user * deep inside attr_from_stat(). */ - if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006) - || fuse_setup(&fuse_read, AID_EVERYBODY, full_write ? 0027 : 0022) - || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0022)) { + if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006, use_sdcardfs) + || fuse_setup(&fuse_read, AID_EVERYBODY, full_write ? 0027 : 0022, use_sdcardfs) + || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0022, use_sdcardfs)) { ERROR("failed to fuse_setup\n"); exit(1); } } + // Nothing else for us to do if sdcardfs is in use! + if (use_sdcardfs) { + exit(0); + } + /* Drop privs */ if (setgroups(sizeof(kGroups) / sizeof(kGroups[0]), kGroups) < 0) { ERROR("cannot setgroups: %s\n", strerror(errno)); @@ -1995,6 +2016,8 @@ int sdcard_main(int argc, char **argv) { sleep(1); } - run(source_path, label, uid, gid, userid, multi_user, full_write); + bool use_sdcardfs = property_get_bool("ro.sdcardfs.enable", false); + + run(source_path, label, uid, gid, userid, multi_user, full_write, use_sdcardfs); return 1; } |