Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb48d31d authored by T.J. Mercier's avatar T.J. Mercier
Browse files

libprocessgroup: Mount cpuset v1 with cpuset_v2_mode

The Android kernel used to carry a patch to restore cpuset masks upon
CPU hotplug onlining, however this was reverted before 6.1. [1] So
devices running kernels >= 6.1 currently suffer from a problem where
cpusets do not include CPUs that they should when CPU hotplugging
occurs.

Fix this by switching from the cpuset filesystem type to cgroup, and by
mounting with the cpuset_v2_mode option which fixes the behavior. It is
possible to use cpuset_v2_mode with the cpuset filesystem type with
kernels that have [2], but deploying this kernel update to already
shipped devices would require waiting 1+ year before we could make this
platform update (and retain the current cpuset filesystem type).

Note that the release_agent option is now intentionally omitted, as it
is unused on Android.

[1] https://r.android.com/2251493
[2] https://lore.kernel.org/all/20250416211752.945849-1-tjmercier@google.com/

Bug: 409240872
Change-Id: I8e39c2831db06d65b6cbbe82f3199272fa85d637
parent a4a1f0a8
Loading
Loading
Loading
Loading
+11 −14
Original line number Diff line number Diff line
@@ -189,22 +189,19 @@ static bool MountV1CgroupController(const CgroupDescriptor& descriptor) {
        return false;
    }

    // Unfortunately historically cpuset controller was mounted using a mount command
    // different from all other controllers. This results in controller attributes not
    // to be prepended with controller name. For example this way instead of
    // /dev/cpuset/cpuset.cpus the attribute becomes /dev/cpuset/cpus which is what
    // the system currently expects.
    int res;
    std::string options = controller->name();

    if (!strcmp(controller->name(), "cpuset")) {
        // mount cpuset none /dev/cpuset nodev noexec nosuid
        res = mount("none", controller->path(), controller->name(),
                    MS_NODEV | MS_NOEXEC | MS_NOSUID, nullptr);
    } else {
        // mount cgroup none <path> nodev noexec nosuid <controller>
        res = mount("none", controller->path(), "cgroup", MS_NODEV | MS_NOEXEC | MS_NOSUID,
                    controller->name());
        // Android depends on the noprefix option for cpuset so that cgroupfs files are not prefixed
        // with the controller name. For example /dev/cpuset/cpus instead of
        //                                       /dev/cpuset/cpuset.cpus.
        // cpuset_v2_mode is required to restore the original cpu mask after a cpu is offlined, and
        // then onlined in cgroup v1.
        options += ",noprefix,cpuset_v2_mode";
    }
    if (res != 0) {

    if (mount("none", controller->path(), "cgroup", MS_NODEV | MS_NOEXEC | MS_NOSUID,
              options.c_str())) {
        if (IsOptionalController(controller)) {
            PLOG(INFO) << "Failed to mount optional controller " << controller->name();
            return true;