Loading init/reboot.cpp +14 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <dirent.h> #include <fcntl.h> #include <linux/f2fs.h> #include <linux/fs.h> #include <linux/loop.h> #include <mntent.h> Loading Loading @@ -218,7 +219,7 @@ static void LogShutdownTime(UmountStat stat, Timer* t) { << stat; } static bool IsDataMounted() { static bool IsDataMounted(const std::string& fstype) { std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent); if (fp == nullptr) { PLOG(ERROR) << "Failed to open /proc/mounts"; Loading @@ -227,7 +228,7 @@ static bool IsDataMounted() { mntent* mentry; while ((mentry = getmntent(fp.get())) != nullptr) { if (mentry->mnt_dir == "/data"s) { return true; return fstype == "*" || mentry->mnt_type == fstype; } } return false; Loading Loading @@ -633,7 +634,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to // worry about unmounting it. if (!IsDataMounted()) { if (!IsDataMounted("*")) { sync(); RebootSystem(cmd, reboot_target); abort(); Loading Loading @@ -758,6 +759,16 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str sem_post(&reboot_semaphore); // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it. if (IsDataMounted("f2fs")) { uint32_t flag = F2FS_GOING_DOWN_FULLSYNC; unique_fd fd(TEMP_FAILURE_RETRY(open("/data", O_RDONLY))); int ret = ioctl(fd, F2FS_IOC_SHUTDOWN, &flag); if (ret) { PLOG(ERROR) << "Shutdown /data: "; } else { LOG(INFO) << "Shutdown /data"; } } RebootSystem(cmd, reboot_target); abort(); } Loading init/service.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -289,6 +289,10 @@ void Service::Reap(const siginfo_t& siginfo) { if (flags_ & SVC_EXEC) UnSetExec(); if (name_ == "zygote" || name_ == "zygote64") { removeAllEmptyProcessGroups(); } if (flags_ & SVC_TEMPORARY) return; pid_ = 0; Loading libprocessgroup/include/processgroup/processgroup.h +1 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInByte bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes); void removeAllProcessGroups(void); void removeAllEmptyProcessGroups(void); // Provides the path for an attribute in a specific process group // Returns false in case of error, true in case of success Loading libprocessgroup/processgroup.cpp +28 −5 Original line number Diff line number Diff line Loading @@ -200,7 +200,7 @@ static int RemoveProcessGroup(const char* cgroup, uid_t uid, int pid, unsigned i return ret; } static bool RemoveUidProcessGroups(const std::string& uid_path) { static bool RemoveUidProcessGroups(const std::string& uid_path, bool empty_only) { std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path.c_str()), closedir); bool empty = true; if (uid != NULL) { Loading @@ -215,6 +215,21 @@ static bool RemoveUidProcessGroups(const std::string& uid_path) { } auto path = StringPrintf("%s/%s", uid_path.c_str(), dir->d_name); if (empty_only) { struct stat st; auto procs_file = StringPrintf("%s/%s", path.c_str(), PROCESSGROUP_CGROUP_PROCS_FILE); if (stat(procs_file.c_str(), &st) == -1) { PLOG(ERROR) << "Failed to get stats for " << procs_file; continue; } if (st.st_size > 0) { // skip non-empty groups LOG(VERBOSE) << "Skipping non-empty group " << path; empty = false; continue; } } LOG(VERBOSE) << "Removing " << path; if (rmdir(path.c_str()) == -1) { if (errno != EBUSY) { Loading @@ -227,9 +242,7 @@ static bool RemoveUidProcessGroups(const std::string& uid_path) { return empty; } void removeAllProcessGroups() { LOG(VERBOSE) << "removeAllProcessGroups()"; void removeAllProcessGroupsInternal(bool empty_only) { std::vector<std::string> cgroups; std::string path, memcg_apps_path; Loading @@ -256,7 +269,7 @@ void removeAllProcessGroups() { } auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name); if (!RemoveUidProcessGroups(path)) { if (!RemoveUidProcessGroups(path, empty_only)) { LOG(VERBOSE) << "Skip removing " << path; continue; } Loading @@ -269,6 +282,16 @@ void removeAllProcessGroups() { } } void removeAllProcessGroups() { LOG(VERBOSE) << "removeAllProcessGroups()"; removeAllProcessGroupsInternal(false); } void removeAllEmptyProcessGroups() { LOG(VERBOSE) << "removeAllEmptyProcessGroups()"; removeAllProcessGroupsInternal(true); } /** * Process groups are primarily created by the Zygote, meaning that uid/pid groups are created by * the user root. Ownership for the newly created cgroup and all of its files must thus be Loading rootdir/init.rc +3 −0 Original line number Diff line number Diff line Loading @@ -1099,6 +1099,9 @@ on boot write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50 write /dev/sys/fs/by-name/userdata/iostat_enable 1 # set readahead multiplier for POSIX_FADV_SEQUENTIAL files write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16 # limit discard size to 128MB in order to avoid long IO latency # for filesystem tuning first (dm or sda) # this requires enabling selinux entry for sda/mmcblk0 in vendor side Loading Loading
init/reboot.cpp +14 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <dirent.h> #include <fcntl.h> #include <linux/f2fs.h> #include <linux/fs.h> #include <linux/loop.h> #include <mntent.h> Loading Loading @@ -218,7 +219,7 @@ static void LogShutdownTime(UmountStat stat, Timer* t) { << stat; } static bool IsDataMounted() { static bool IsDataMounted(const std::string& fstype) { std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent); if (fp == nullptr) { PLOG(ERROR) << "Failed to open /proc/mounts"; Loading @@ -227,7 +228,7 @@ static bool IsDataMounted() { mntent* mentry; while ((mentry = getmntent(fp.get())) != nullptr) { if (mentry->mnt_dir == "/data"s) { return true; return fstype == "*" || mentry->mnt_type == fstype; } } return false; Loading Loading @@ -633,7 +634,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to // worry about unmounting it. if (!IsDataMounted()) { if (!IsDataMounted("*")) { sync(); RebootSystem(cmd, reboot_target); abort(); Loading Loading @@ -758,6 +759,16 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str sem_post(&reboot_semaphore); // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it. if (IsDataMounted("f2fs")) { uint32_t flag = F2FS_GOING_DOWN_FULLSYNC; unique_fd fd(TEMP_FAILURE_RETRY(open("/data", O_RDONLY))); int ret = ioctl(fd, F2FS_IOC_SHUTDOWN, &flag); if (ret) { PLOG(ERROR) << "Shutdown /data: "; } else { LOG(INFO) << "Shutdown /data"; } } RebootSystem(cmd, reboot_target); abort(); } Loading
init/service.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -289,6 +289,10 @@ void Service::Reap(const siginfo_t& siginfo) { if (flags_ & SVC_EXEC) UnSetExec(); if (name_ == "zygote" || name_ == "zygote64") { removeAllEmptyProcessGroups(); } if (flags_ & SVC_TEMPORARY) return; pid_ = 0; Loading
libprocessgroup/include/processgroup/processgroup.h +1 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInByte bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes); void removeAllProcessGroups(void); void removeAllEmptyProcessGroups(void); // Provides the path for an attribute in a specific process group // Returns false in case of error, true in case of success Loading
libprocessgroup/processgroup.cpp +28 −5 Original line number Diff line number Diff line Loading @@ -200,7 +200,7 @@ static int RemoveProcessGroup(const char* cgroup, uid_t uid, int pid, unsigned i return ret; } static bool RemoveUidProcessGroups(const std::string& uid_path) { static bool RemoveUidProcessGroups(const std::string& uid_path, bool empty_only) { std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path.c_str()), closedir); bool empty = true; if (uid != NULL) { Loading @@ -215,6 +215,21 @@ static bool RemoveUidProcessGroups(const std::string& uid_path) { } auto path = StringPrintf("%s/%s", uid_path.c_str(), dir->d_name); if (empty_only) { struct stat st; auto procs_file = StringPrintf("%s/%s", path.c_str(), PROCESSGROUP_CGROUP_PROCS_FILE); if (stat(procs_file.c_str(), &st) == -1) { PLOG(ERROR) << "Failed to get stats for " << procs_file; continue; } if (st.st_size > 0) { // skip non-empty groups LOG(VERBOSE) << "Skipping non-empty group " << path; empty = false; continue; } } LOG(VERBOSE) << "Removing " << path; if (rmdir(path.c_str()) == -1) { if (errno != EBUSY) { Loading @@ -227,9 +242,7 @@ static bool RemoveUidProcessGroups(const std::string& uid_path) { return empty; } void removeAllProcessGroups() { LOG(VERBOSE) << "removeAllProcessGroups()"; void removeAllProcessGroupsInternal(bool empty_only) { std::vector<std::string> cgroups; std::string path, memcg_apps_path; Loading @@ -256,7 +269,7 @@ void removeAllProcessGroups() { } auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name); if (!RemoveUidProcessGroups(path)) { if (!RemoveUidProcessGroups(path, empty_only)) { LOG(VERBOSE) << "Skip removing " << path; continue; } Loading @@ -269,6 +282,16 @@ void removeAllProcessGroups() { } } void removeAllProcessGroups() { LOG(VERBOSE) << "removeAllProcessGroups()"; removeAllProcessGroupsInternal(false); } void removeAllEmptyProcessGroups() { LOG(VERBOSE) << "removeAllEmptyProcessGroups()"; removeAllProcessGroupsInternal(true); } /** * Process groups are primarily created by the Zygote, meaning that uid/pid groups are created by * the user root. Ownership for the newly created cgroup and all of its files must thus be Loading
rootdir/init.rc +3 −0 Original line number Diff line number Diff line Loading @@ -1099,6 +1099,9 @@ on boot write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50 write /dev/sys/fs/by-name/userdata/iostat_enable 1 # set readahead multiplier for POSIX_FADV_SEQUENTIAL files write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16 # limit discard size to 128MB in order to avoid long IO latency # for filesystem tuning first (dm or sda) # this requires enabling selinux entry for sda/mmcblk0 in vendor side Loading