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

Commit ad253001 authored by Risan's avatar Risan Committed by Gerrit Code Review
Browse files

Merge "Refactor quota ops to a separate utils"

parents f4d39e21 5f30826c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ cc_defaults {
        "CacheItem.cpp",
        "CacheTracker.cpp",
        "InstalldNativeService.cpp",
        "QuotaUtils.cpp",
        "dexopt.cpp",
        "globals.cpp",
        "utils.cpp",
+16 −20
Original line number Diff line number Diff line
@@ -19,13 +19,13 @@
#include "CacheTracker.h"

#include <fts.h>
#include <sys/quota.h>
#include <sys/xattr.h>
#include <utils/Trace.h>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "QuotaUtils.h"
#include "utils.h"

using android::base::StringPrintf;
@@ -33,9 +33,13 @@ using android::base::StringPrintf;
namespace android {
namespace installd {

CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice) :
        cacheUsed(0), cacheQuota(0), mUserId(userId), mAppId(appId), mQuotaDevice(quotaDevice),
        mItemsLoaded(false) {
CacheTracker::CacheTracker(userid_t userId, appid_t appId, const std::string& uuid)
      : cacheUsed(0),
        cacheQuota(0),
        mUserId(userId),
        mAppId(appId),
        mItemsLoaded(false),
        mUuid(uuid) {
}

CacheTracker::~CacheTracker() {
@@ -72,26 +76,18 @@ void CacheTracker::loadStats() {
bool CacheTracker::loadQuotaStats() {
    int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
    int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
    if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
        struct dqblk dq;
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
            }
            return false;
    if (IsQuotaSupported(mUuid) && cacheGid != -1 && extCacheGid != -1) {
        int64_t space;
        if ((space = GetOccupiedSpaceForGid(mUuid, cacheGid)) != -1) {
            cacheUsed += space;
        } else {
            cacheUsed += dq.dqb_curspace;
            return false;
        }

        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
            }
            return false;
        if ((space = GetOccupiedSpaceForGid(mUuid, extCacheGid)) != -1) {
            cacheUsed += space;
        } else {
            cacheUsed += dq.dqb_curspace;
            return false;
        }
        return true;
    } else {
+2 −2
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ namespace installd {
 */
class CacheTracker {
public:
    CacheTracker(userid_t userId, appid_t appId, const std::string& quotaDevice);
    CacheTracker(userid_t userId, appid_t appId, const std::string& uuid);
    ~CacheTracker();

    std::string toString();
@@ -61,8 +61,8 @@ public:
private:
    userid_t mUserId;
    appid_t mAppId;
    std::string mQuotaDevice;
    bool mItemsLoaded;
    const std::string& mUuid;

    std::vector<std::string> mDataPaths;

+50 −150
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/quota.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
@@ -64,6 +63,7 @@

#include "CacheTracker.h"
#include "MatchExtensionGen.h"
#include "QuotaUtils.h"

#ifndef LOG_TAG
#define LOG_TAG "installd"
@@ -266,11 +266,6 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */
        for (const auto& n : mStorageMounts) {
            out << "    " << n.first << " = " << n.second << endl;
        }

        out << endl << "Quota reverse mounts:" << endl;
        for (const auto& n : mQuotaReverseMounts) {
            out << "    " << n.first << " = " << n.second << endl;
        }
    }

    {
@@ -950,9 +945,9 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
    CHECK_ARGUMENT_UUID(uuid);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    auto uuidString = uuid ? *uuid : "";
    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    auto data_path = create_data_path(uuid_);
    auto device = findQuotaDeviceForUuid(uuid);
    auto noop = (flags & FLAG_FREE_CACHE_NOOP);

    int64_t free = data_disk_free(data_path);
@@ -999,7 +994,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
                        search->second->addDataPath(p->fts_path);
                    } else {
                        auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker(
                                multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
                                multiuser_get_user_id(uid), multiuser_get_app_id(uid), uuidString));
                        tracker->addDataPath(p->fts_path);
                        {
                            std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
@@ -1164,53 +1159,26 @@ static std::string toString(std::vector<int64_t> values) {
}
#endif

static void collectQuotaStats(const std::string& device, int32_t userId,
static void collectQuotaStats(const std::string& uuid, int32_t userId,
        int32_t appId, struct stats* stats, struct stats* extStats) {
    if (device.empty()) return;

    struct dqblk dq;

    int64_t space;
    if (stats != nullptr) {
        uid_t uid = multiuser_get_uid(userId, appId);
        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
            }
        } else {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
#endif
            stats->dataSize += dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
            stats->dataSize += space;
        }

        int cacheGid = multiuser_get_cache_gid(userId, appId);
        if (cacheGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
                    reinterpret_cast<char*>(&dq)) != 0) {
                if (errno != ESRCH) {
                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
                }
            } else {
#if MEASURE_DEBUG
                LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
#endif
                stats->cacheSize += dq.dqb_curspace;
            if ((space = GetOccupiedSpaceForGid(uuid, cacheGid)) != -1) {
                stats->cacheSize += space;
            }
        }

        int sharedGid = multiuser_get_shared_gid(0, appId);
        if (sharedGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
                    reinterpret_cast<char*>(&dq)) != 0) {
                if (errno != ESRCH) {
                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
                }
            } else {
#if MEASURE_DEBUG
                LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
#endif
                stats->codeSize += dq.dqb_curspace;
            if ((space = GetOccupiedSpaceForGid(uuid, sharedGid)) != -1) {
                stats->codeSize += space;
            }
        }
    }
@@ -1218,32 +1186,16 @@ static void collectQuotaStats(const std::string& device, int32_t userId,
    if (extStats != nullptr) {
        int extGid = multiuser_get_ext_gid(userId, appId);
        if (extGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
                    reinterpret_cast<char*>(&dq)) != 0) {
                if (errno != ESRCH) {
                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extGid;
                }
            } else {
#if MEASURE_DEBUG
                LOG(DEBUG) << "quotactl() for GID " << extGid << " " << dq.dqb_curspace;
#endif
                extStats->dataSize += dq.dqb_curspace;
            if ((space = GetOccupiedSpaceForGid(uuid, extGid)) != -1) {
                extStats->dataSize += space;
            }
        }

        int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
        if (extCacheGid != -1) {
            if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extCacheGid,
                    reinterpret_cast<char*>(&dq)) != 0) {
                if (errno != ESRCH) {
                    PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << extCacheGid;
                }
            } else {
#if MEASURE_DEBUG
                LOG(DEBUG) << "quotactl() for GID " << extCacheGid << " " << dq.dqb_curspace;
#endif
                extStats->dataSize += dq.dqb_curspace;
                extStats->cacheSize += dq.dqb_curspace;
            if ((space = GetOccupiedSpaceForGid(uuid, extCacheGid)) != -1) {
                extStats->dataSize += space;
                extStats->cacheSize += space;
            }
        }
    }
@@ -1407,10 +1359,10 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri
    memset(&stats, 0, sizeof(stats));
    memset(&extStats, 0, sizeof(extStats));

    auto uuidString = uuid ? *uuid : "";
    const char* uuid_ = uuid ? uuid->c_str() : nullptr;

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
    if (!IsQuotaSupported(uuidString)) {
        flags &= ~FLAG_USE_QUOTA;
    }

@@ -1430,7 +1382,7 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri
        ATRACE_END();

        ATRACE_BEGIN("quota");
        collectQuotaStats(device, userId, appId, &stats, &extStats);
        collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
        ATRACE_END();
    } else {
        ATRACE_BEGIN("code");
@@ -1513,27 +1465,19 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
    memset(&stats, 0, sizeof(stats));
    memset(&extStats, 0, sizeof(extStats));

    auto uuidString = uuid ? *uuid : "";
    const char* uuid_ = uuid ? uuid->c_str() : nullptr;

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
    if (!IsQuotaSupported(uuidString)) {
        flags &= ~FLAG_USE_QUOTA;
    }

    if (flags & FLAG_USE_QUOTA) {
        struct dqblk dq;
        int64_t space;

        ATRACE_BEGIN("obb");
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << AID_MEDIA_OBB;
            }
        } else {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
#endif
            extStats.codeSize += dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
            extStats.codeSize += space;
        }
        ATRACE_END();

@@ -1559,16 +1503,8 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str

        ATRACE_BEGIN("external");
        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
            }
        } else {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
#endif
            extStats.dataSize += dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
            extStats.dataSize += space;
        }
        ATRACE_END();

@@ -1585,7 +1521,7 @@ binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::str
        int64_t dataSize = extStats.dataSize;
        for (auto appId : appIds) {
            if (appId >= AID_APP_START) {
                collectQuotaStats(device, userId, appId, &stats, &extStats);
                collectQuotaStats(uuidString, userId, appId, &stats, &extStats);

#if MEASURE_DEBUG
                // Sleep to make sure we don't lose logs
@@ -1667,6 +1603,7 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
    LOG(INFO) << "Measuring external " << userId;
#endif

    auto uuidString = uuid ? *uuid : "";
    const char* uuid_ = uuid ? uuid->c_str() : nullptr;

    int64_t totalSize = 0;
@@ -1676,58 +1613,33 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
    int64_t appSize = 0;
    int64_t obbSize = 0;

    auto device = findQuotaDeviceForUuid(uuid);
    if (device.empty()) {
    if (!IsQuotaSupported(uuidString)) {
        flags &= ~FLAG_USE_QUOTA;
    }

    if (flags & FLAG_USE_QUOTA) {
        struct dqblk dq;
        int64_t space;

        ATRACE_BEGIN("quota");
        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
                reinterpret_cast<char*>(&dq)) != 0) {
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
            }
        } else {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
#endif
            totalSize = dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
            totalSize = space;
        }

        gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
                reinterpret_cast<char*>(&dq)) == 0) {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
#endif
            audioSize = dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForGid(uuidString, audioGid)) != -1) {
            audioSize = space;
        }
        gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
                reinterpret_cast<char*>(&dq)) == 0) {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
#endif
            videoSize = dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForGid(uuidString, videoGid)) != -1) {
            videoSize = space;
        }
        gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
                reinterpret_cast<char*>(&dq)) == 0) {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
#endif
            imageSize = dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForGid(uuidString, imageGid)) != -1) {
            imageSize = space;
        }
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
                reinterpret_cast<char*>(&dq)) == 0) {
#if MEASURE_DEBUG
            LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
#endif
            obbSize = dq.dqb_curspace;
        if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
            obbSize = space;
        }
        ATRACE_END();

@@ -1736,7 +1648,7 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std:
        memset(&extStats, 0, sizeof(extStats));
        for (auto appId : appIds) {
            if (appId >= AID_APP_START) {
                collectQuotaStats(device, userId, appId, nullptr, &extStats);
                collectQuotaStats(uuidString, userId, appId, nullptr, &extStats);
            }
        }
        appSize = extStats.dataSize;
@@ -2524,7 +2436,12 @@ binder::Status InstalldNativeService::invalidateMounts() {
    std::lock_guard<std::recursive_mutex> lock(mMountsLock);

    mStorageMounts.clear();
    mQuotaReverseMounts.clear();

#if !BYPASS_QUOTA
    if (!InvalidateQuotaMounts()) {
        return error("Failed to read mounts");
    }
#endif

    std::ifstream in("/proc/mounts");
    if (!in.is_open()) {
@@ -2545,17 +2462,6 @@ binder::Status InstalldNativeService::invalidateMounts() {
            mStorageMounts[source] = target;
        }
#endif

#if !BYPASS_QUOTA
        if (source.compare(0, 11, "/dev/block/") == 0) {
            struct dqblk dq;
            if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
                    reinterpret_cast<char*>(&dq)) == 0) {
                LOG(DEBUG) << "Found quota mount " << source << " at " << target;
                mQuotaReverseMounts[target] = source;
            }
        }
#endif
    }
    return ok();
}
@@ -2573,16 +2479,10 @@ std::string InstalldNativeService::findDataMediaPath(
    return StringPrintf("%s/%u", resolved.c_str(), userid);
}

std::string InstalldNativeService::findQuotaDeviceForUuid(
        const std::unique_ptr<std::string>& uuid) {
    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
    auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
    return mQuotaReverseMounts[path];
}

binder::Status InstalldNativeService::isQuotaSupported(
        const std::unique_ptr<std::string>& volumeUuid, bool* _aidl_return) {
    *_aidl_return = !findQuotaDeviceForUuid(volumeUuid).empty();
        const std::unique_ptr<std::string>& uuid, bool* _aidl_return) {
    auto uuidString = uuid ? *uuid : "";
    *_aidl_return = IsQuotaSupported(uuidString);
    return ok();
}

+0 −3
Original line number Diff line number Diff line
@@ -150,14 +150,11 @@ private:

    /* Map of all storage mounts from source to target */
    std::unordered_map<std::string, std::string> mStorageMounts;
    /* Map of all quota mounts from target to source */
    std::unordered_map<std::string, std::string> mQuotaReverseMounts;

    /* Map from UID to cache quota size */
    std::unordered_map<uid_t, int64_t> mCacheQuotas;

    std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid);
    std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};

}  // namespace installd
Loading