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

Commit da58bf4b authored by Jeff Sharkey's avatar Jeff Sharkey Committed by android-build-merger
Browse files

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

am: 4b567487

Change-Id: Ib979f876c37632b723e6a982dc48ec746aaef290
parents 8dcba286 4b567487
Loading
Loading
Loading
Loading
+26 −7
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ std::string CacheItem::buildPath() {
}

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

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

void CacheTracker::loadStats() {
    int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
    if (cacheGid != -1 && !mQuotaDevice.empty()) {
    ATRACE_BEGIN("loadStats quota");
        struct dqblk dq;
        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
                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();
    cacheUsed = 0;
    if (loadQuotaStats()) {
        return;
    }
    }
    ATRACE_END();

    ATRACE_BEGIN("loadStats tree");
    cacheUsed = 0;
@@ -79,6 +69,36 @@ void CacheTracker::loadStats() {
    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) {
    FTS *fts;
    FTSENT *p;
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ private:

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

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

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

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

    {
        std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
        std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
        out << endl << "Per-UID cache quotas:" << endl;
        for (const auto& n : mCacheQuotas) {
            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) {
            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) {
            res = error("Failed to delete " + path);
        }
@@ -952,13 +957,19 @@ binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::strin
            FTSENT *p;
            auto ce_path = create_data_user_ce_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))) {
                return error("Failed to fts_open");
            }
            while ((p = fts_read(fts)) != NULL) {
                if (p->fts_info == FTS_D && p->fts_level == 1) {
                    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);
                    if (search != trackers.end()) {
                        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));
                        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];
                        }
                        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) {
    ENFORCE_UID(AID_SYSTEM);
    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);
    mCacheQuotas[uid] = cacheQuota;
@@ -2219,9 +2230,10 @@ binder::Status InstalldNativeService::reconcileSecondaryDexFile(

binder::Status InstalldNativeService::invalidateMounts() {
    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");
    if (!in.is_open()) {
@@ -2231,17 +2243,25 @@ binder::Status InstalldNativeService::invalidateMounts() {
    std::string source;
    std::string target;
    std::string ignored;
    struct dqblk dq;
    while (!in.eof()) {
        std::getline(in, source, ' ');
        std::getline(in, target, ' ');
        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) {
            struct dqblk dq;
            if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
                    reinterpret_cast<char*>(&dq)) == 0) {
                LOG(DEBUG) << "Found " << source << " with quota";
                mQuotaDevices[target] = source;
                LOG(DEBUG) << "Found quota mount " << source << " at " << target;
                mQuotaReverseMounts[target] = source;

                // ext4 only enables DQUOT_USAGE_ENABLED by default, so we
                // need to kick it again to enable DQUOT_LIMITS_ENABLED.
@@ -2255,15 +2275,29 @@ binder::Status InstalldNativeService::invalidateMounts() {
                }
            }
        }
#endif
    }
    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(
        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);
    return mQuotaDevices[path];
    return mQuotaReverseMounts[path];
}

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

    std::recursive_mutex mQuotaDevicesLock;
    std::recursive_mutex mCacheQuotasLock;
    std::recursive_mutex mMountsLock;
    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 */
    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);
};

Loading