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

Commit 4b567487 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Clear cached files on external storage." into oc-dev

parents 0e04fe47 d712f0cc
Loading
Loading
Loading
Loading
+26 −7
Original line number Original line Diff line number Diff line
@@ -67,6 +67,7 @@ std::string CacheItem::buildPath() {
}
}


int CacheItem::purge() {
int CacheItem::purge() {
    int res = 0;
    auto path = buildPath();
    auto path = buildPath();
    if (directory) {
    if (directory) {
        FTS *fts;
        FTS *fts;
@@ -88,29 +89,47 @@ int CacheItem::purge() {
                break;
                break;
            case FTS_F:
            case FTS_F:
                if (p->fts_parent->fts_number) {
                if (p->fts_parent->fts_number) {
                    truncate(p->fts_path, 0);
                    if (truncate(p->fts_path, 0) != 0) {
                        PLOG(WARNING) << "Failed to truncate " << p->fts_path;
                        res = -1;
                    }
                } else {
                } else {
                    unlink(p->fts_path);
                    if (unlink(p->fts_path) != 0) {
                        PLOG(WARNING) << "Failed to unlink " << p->fts_path;
                        res = -1;
                    }
                }
                }
                break;
                break;
            case FTS_DEFAULT:
            case FTS_DEFAULT:
            case FTS_SL:
            case FTS_SL:
            case FTS_SLNONE:
            case FTS_SLNONE:
                unlink(p->fts_path);
                if (unlink(p->fts_path) != 0) {
                    PLOG(WARNING) << "Failed to unlink " << p->fts_path;
                    res = -1;
                }
                break;
                break;
            case FTS_DP:
            case FTS_DP:
                rmdir(p->fts_path);
                if (rmdir(p->fts_path) != 0) {
                    PLOG(WARNING) << "Failed to rmdir " << p->fts_path;
                    res = -1;
                }
                break;
                break;
            }
            }
        }
        }
        return 0;
    } else {
    } else {
        if (tombstone) {
        if (tombstone) {
            return truncate(path.c_str(), 0);
            if (truncate(path.c_str(), 0) != 0) {
                PLOG(WARNING) << "Failed to truncate " << path;
                res = -1;
            }
        } else {
        } else {
            return unlink(path.c_str());
            if (unlink(path.c_str()) != 0) {
                PLOG(WARNING) << "Failed to unlink " << path;
                res = -1;
            }
        }
        }
    }
    }
    return res;
}
}


}  // namespace installd
}  // namespace installd
+35 −15
Original line number Original line Diff line number Diff line
@@ -51,22 +51,12 @@ void CacheTracker::addDataPath(const std::string& dataPath) {
}
}


void CacheTracker::loadStats() {
void CacheTracker::loadStats() {
    int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
    if (cacheGid != -1 && !mQuotaDevice.empty()) {
    ATRACE_BEGIN("loadStats quota");
    ATRACE_BEGIN("loadStats quota");
        struct dqblk dq;
    cacheUsed = 0;
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
    if (loadQuotaStats()) {
                reinterpret_cast<char*>(&dq)) != 0) {
            ATRACE_END();
            if (errno != ESRCH) {
                PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
            }
        } else {
            cacheUsed = dq.dqb_curspace;
            ATRACE_END();
        return;
        return;
    }
    }
    }
    ATRACE_END();


    ATRACE_BEGIN("loadStats tree");
    ATRACE_BEGIN("loadStats tree");
    cacheUsed = 0;
    cacheUsed = 0;
@@ -79,6 +69,36 @@ void CacheTracker::loadStats() {
    ATRACE_END();
    ATRACE_END();
}
}


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;
        } else {
            cacheUsed += dq.dqb_curspace;
        }

        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;
        } else {
            cacheUsed += dq.dqb_curspace;
        }
        return true;
    } else {
        return false;
    }
}

void CacheTracker::loadItemsFrom(const std::string& path) {
void CacheTracker::loadItemsFrom(const std::string& path) {
    FTS *fts;
    FTS *fts;
    FTSENT *p;
    FTSENT *p;
+1 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ private:


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


    bool loadQuotaStats();
    void loadItemsFrom(const std::string& path);
    void loadItemsFrom(const std::string& path);


    DISALLOW_COPY_AND_ASSIGN(CacheTracker);
    DISALLOW_COPY_AND_ASSIGN(CacheTracker);
+49 −15
Original line number Original line Diff line number Diff line
@@ -205,15 +205,20 @@ status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */
    out << "installd is happy!" << endl;
    out << "installd is happy!" << endl;


    {
    {
        std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
        out << endl << "Devices with quota support:" << endl;
        out << endl << "Storage mounts:" << endl;
        for (const auto& n : mQuotaDevices) {
        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;
            out << "    " << n.first << " = " << n.second << endl;
        }
        }
    }
    }


    {
    {
        std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
        std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
        out << endl << "Per-UID cache quotas:" << endl;
        out << endl << "Per-UID cache quotas:" << endl;
        for (const auto& n : mCacheQuotas) {
        for (const auto& n : mCacheQuotas) {
            out << "    " << n.first << " = " << n.second << endl;
            out << "    " << n.first << " = " << n.second << endl;
@@ -901,7 +906,7 @@ binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std:
        if (delete_dir_contents_and_dir(path, true) != 0) {
        if (delete_dir_contents_and_dir(path, true) != 0) {
            res = error("Failed to delete " + path);
            res = error("Failed to delete " + path);
        }
        }
        path = create_data_media_path(uuid_, userId);
        path = findDataMediaPath(uuid, userId);
        if (delete_dir_contents_and_dir(path, true) != 0) {
        if (delete_dir_contents_and_dir(path, true) != 0) {
            res = error("Failed to delete " + path);
            res = error("Failed to delete " + path);
        }
        }
@@ -952,13 +957,19 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
            FTSENT *p;
            FTSENT *p;
            auto ce_path = create_data_user_ce_path(uuid_, user);
            auto ce_path = create_data_user_ce_path(uuid_, user);
            auto de_path = create_data_user_de_path(uuid_, user);
            auto de_path = create_data_user_de_path(uuid_, user);
            char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
            auto media_path = findDataMediaPath(uuid, user) + "/Android/data/";
            char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(),
                    (char*) media_path.c_str(), nullptr };
            if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
            if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
                return error("Failed to fts_open");
                return error("Failed to fts_open");
            }
            }
            while ((p = fts_read(fts)) != NULL) {
            while ((p = fts_read(fts)) != NULL) {
                if (p->fts_info == FTS_D && p->fts_level == 1) {
                if (p->fts_info == FTS_D && p->fts_level == 1) {
                    uid_t uid = p->fts_statp->st_uid;
                    uid_t uid = p->fts_statp->st_uid;
                    if (multiuser_get_app_id(uid) == AID_MEDIA_RW) {
                        uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START)
                                + AID_APP_START;
                    }
                    auto search = trackers.find(uid);
                    auto search = trackers.find(uid);
                    if (search != trackers.end()) {
                    if (search != trackers.end()) {
                        search->second->addDataPath(p->fts_path);
                        search->second->addDataPath(p->fts_path);
@@ -967,7 +978,7 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
                                multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
                                multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
                        tracker->addDataPath(p->fts_path);
                        tracker->addDataPath(p->fts_path);
                        {
                        {
                            std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
                            std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
                            tracker->cacheQuota = mCacheQuotas[uid];
                            tracker->cacheQuota = mCacheQuotas[uid];
                        }
                        }
                        if (tracker->cacheQuota == 0) {
                        if (tracker->cacheQuota == 0) {
@@ -1745,7 +1756,7 @@ binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr<std::str
        int32_t userId, int32_t appId, int64_t cacheQuota) {
        int32_t userId, int32_t appId, int64_t cacheQuota) {
    ENFORCE_UID(AID_SYSTEM);
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_UUID(uuid);
    CHECK_ARGUMENT_UUID(uuid);
    std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
    std::lock_guard<std::recursive_mutex> lock(mQuotasLock);


    int32_t uid = multiuser_get_uid(userId, appId);
    int32_t uid = multiuser_get_uid(userId, appId);
    mCacheQuotas[uid] = cacheQuota;
    mCacheQuotas[uid] = cacheQuota;
@@ -2219,9 +2230,10 @@ binder::Status InstalldNativeService::reconcileSecondaryDexFile(


binder::Status InstalldNativeService::invalidateMounts() {
binder::Status InstalldNativeService::invalidateMounts() {
    ENFORCE_UID(AID_SYSTEM);
    ENFORCE_UID(AID_SYSTEM);
    std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
    std::lock_guard<std::recursive_mutex> lock(mMountsLock);


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


    std::ifstream in("/proc/mounts");
    std::ifstream in("/proc/mounts");
    if (!in.is_open()) {
    if (!in.is_open()) {
@@ -2231,17 +2243,25 @@ binder::Status InstalldNativeService::invalidateMounts() {
    std::string source;
    std::string source;
    std::string target;
    std::string target;
    std::string ignored;
    std::string ignored;
    struct dqblk dq;
    while (!in.eof()) {
    while (!in.eof()) {
        std::getline(in, source, ' ');
        std::getline(in, source, ' ');
        std::getline(in, target, ' ');
        std::getline(in, target, ' ');
        std::getline(in, ignored);
        std::getline(in, ignored);


#if !BYPASS_SDCARDFS
        if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
            LOG(DEBUG) << "Found storage mount " << source << " at " << target;
            mStorageMounts[source] = target;
        }
#endif

#if !BYPASS_QUOTA
        if (source.compare(0, 11, "/dev/block/") == 0) {
        if (source.compare(0, 11, "/dev/block/") == 0) {
            struct dqblk dq;
            if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
            if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
                    reinterpret_cast<char*>(&dq)) == 0) {
                    reinterpret_cast<char*>(&dq)) == 0) {
                LOG(DEBUG) << "Found " << source << " with quota";
                LOG(DEBUG) << "Found quota mount " << source << " at " << target;
                mQuotaDevices[target] = source;
                mQuotaReverseMounts[target] = source;


                // ext4 only enables DQUOT_USAGE_ENABLED by default, so we
                // ext4 only enables DQUOT_USAGE_ENABLED by default, so we
                // need to kick it again to enable DQUOT_LIMITS_ENABLED.
                // need to kick it again to enable DQUOT_LIMITS_ENABLED.
@@ -2255,15 +2275,29 @@ binder::Status InstalldNativeService::invalidateMounts() {
                }
                }
            }
            }
        }
        }
#endif
    }
    }
    return ok();
    return ok();
}
}


std::string InstalldNativeService::findDataMediaPath(
        const std::unique_ptr<std::string>& uuid, userid_t userid) {
    std::lock_guard<std::recursive_mutex> lock(mMountsLock);
    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str());
    auto resolved = mStorageMounts[path];
    if (resolved.empty()) {
        LOG(WARNING) << "Failed to find storage mount for " << path;
        resolved = path;
    }
    return StringPrintf("%s/%u", resolved.c_str(), userid);
}

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


binder::Status InstalldNativeService::isQuotaSupported(
binder::Status InstalldNativeService::isQuotaSupported(
+8 −4
Original line number Original line Diff line number Diff line
@@ -121,14 +121,18 @@ public:
private:
private:
    std::recursive_mutex mLock;
    std::recursive_mutex mLock;


    std::recursive_mutex mQuotaDevicesLock;
    std::recursive_mutex mMountsLock;
    std::recursive_mutex mCacheQuotasLock;
    std::recursive_mutex mQuotasLock;

    /* 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 mount point to underlying device node */
    std::unordered_map<std::string, std::string> mQuotaDevices;
    /* Map from UID to cache quota size */
    /* Map from UID to cache quota size */
    std::unordered_map<uid_t, int64_t> mCacheQuotas;
    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);
    std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};
};


Loading