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

Commit bcd6e3b9 authored by Jin Qian's avatar Jin Qian
Browse files

storaged: monitor per-uid IO usage

Add uid_monitor class to query /proc/uid_io/stats periodically.
Add a log tag to record any UID that exceeds IO threshold.

Test: adb shell storaged -u
Bug: 34198239
Change-Id: I53568c30dbefe2f4bdb18054d3dedb30b4133d8b
parent 933d0281
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -2,14 +2,16 @@

LOCAL_PATH := $(call my-dir)

LIBSTORAGED_SHARED_LIBRARIES := libbinder libbase libutils libcutils liblog libsysutils libcap
LIBSTORAGED_SHARED_LIBRARIES := libbinder libbase libutils libcutils liblog libsysutils libcap libpackagelistparser

include $(CLEAR_VARS)

LOCAL_SRC_FILES := storaged.cpp \
                  storaged_service.cpp \
                  storaged_utils.cpp \
                  storaged_uid_monitor.cpp \
                  EventLogTags.logtags

LOCAL_MODULE := libstoraged
LOCAL_CFLAGS := -Werror
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/googletest/googletest/include
+2 −0
Original line number Diff line number Diff line
@@ -37,3 +37,5 @@
2732 storaged_disk_stats (type|3),(start_time|2|3),(end_time|2|3),(read_ios|2|1),(read_merges|2|1),(read_sectors|2|1),(read_ticks|2|3),(write_ios|2|1),(write_merges|2|1),(write_sectors|2|1),(write_ticks|2|3),(o_in_flight|2|1),(io_ticks|2|3),(io_in_queue|2|1)

2733 storaged_emmc_info (mmc_ver|3),(eol|1),(lifetime_a|1),(lifetime_b|1)

2734 storaged_uid_io_alert (name|3),(read|2),(write|2),(interval|2)
 No newline at end of file
+19 −1
Original line number Diff line number Diff line
@@ -17,13 +17,17 @@
#ifndef _STORAGED_H_
#define _STORAGED_H_

#include <queue>
#include <semaphore.h>
#include <stdint.h>
#include <time.h>

#include <queue>
#include <string>
#include <unordered_map>
#include <vector>

#include "storaged_uid_monitor.h"

#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test

@@ -165,6 +169,8 @@ public:
#define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat"
#define SDA_DISK_STATS_PATH "/sys/block/sda/stat"
#define EMMC_ECSD_PATH "/d/mmc0/mmc0:0001/ext_csd"
#define UID_IO_STATS_PATH "/proc/uid_io/stats"

class disk_stats_monitor {
private:
    FRIEND_TEST(storaged_test, disk_stats_monitor);
@@ -260,12 +266,15 @@ public:
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH ( 86400 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_ALERT ( 3600 )

struct storaged_config {
    int periodic_chores_interval_unit;
    int periodic_chores_interval_disk_stats_publish;
    int periodic_chores_interval_emmc_info_publish;
    int periodic_chores_interval_uid_io;
    bool proc_taskio_readable;  // are /proc/[pid]/{io, comm, cmdline, stat} all readable
    bool proc_uid_io_available;      // whether uid_io is accessible
    bool emmc_available;        // whether eMMC est_csd file is readable
    bool diskstats_available;   // whether diskstats is accessible
};
@@ -278,6 +287,7 @@ private:
    disk_stats_monitor mDsm;
    emmc_info_t mEmmcInfo;
    tasks_t mTasks;
    uid_monitor mUidm;
    time_t mStarttime;
public:
    storaged_t(void);
@@ -295,6 +305,9 @@ public:
    void set_emmc_interval(int emmc_info) {
        mConfig.periodic_chores_interval_emmc_info_publish = emmc_info;
    }
    void set_uid_io_interval(int uid_io) {
        mUidm.set_periodic_chores_interval(uid_io);
    }
    std::vector<struct task_info> get_tasks(void) {
        // There could be a race when get_tasks() and the main thread is updating at the same time
        // While update_running_tasks() is updating the critical sections at the end of the function
@@ -312,11 +325,16 @@ public:
    time_t get_starttime(void) {
        return mStarttime;
    }

    std::unordered_map<uint32_t, struct uid_info> get_uids(void) {
        return mUidm.get_uids();
    }
};

// Eventlog tag
// The content must match the definition in EventLogTags.logtags
#define EVENTLOGTAG_DISKSTATS ( 2732 )
#define EVENTLOGTAG_EMMCINFO ( 2733 )
#define EVENTLOGTAG_UID_IO_ALERT ( 2734 )

#endif /* _STORAGED_H_ */
+4 −0
Original line number Diff line number Diff line
@@ -31,9 +31,11 @@ class IStoraged : public IInterface {
public:
    enum {
        DUMPTASKS = IBinder::FIRST_CALL_TRANSACTION,
        DUMPUIDS  = IBinder::FIRST_CALL_TRANSACTION + 1,
    };
    // Request the service to run the test function
    virtual std::vector<struct task_info> dump_tasks(const char* option) = 0;
    virtual std::vector<struct uid_info> dump_uids(const char* option) = 0;

    DECLARE_META_INTERFACE(Storaged);
};
@@ -43,6 +45,7 @@ class BpStoraged : public BpInterface<IStoraged> {
public:
    BpStoraged(const sp<IBinder>& impl) : BpInterface<IStoraged>(impl){};
    virtual std::vector<struct task_info> dump_tasks(const char* option);
    virtual std::vector<struct uid_info> dump_uids(const char* option);
};

// Server
@@ -52,6 +55,7 @@ class BnStoraged : public BnInterface<IStoraged> {

class Storaged : public BnStoraged {
    virtual std::vector<struct task_info> dump_tasks(const char* option);
    virtual std::vector<struct uid_info> dump_uids(const char* option);
};

sp<IStoraged> get_storaged_service();
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _STORAGED_UID_MONITOR_H_
#define _STORAGED_UID_MONITOR_H_

#include <stdint.h>

#include <string>
#include <unordered_map>

enum {
    UID_FOREGROUND = 0,
    UID_BACKGROUND = 1,
    UID_STATS_SIZE = 2
};

struct uid_io_stats {
    uint64_t rchar;                 // characters read
    uint64_t wchar;                 // characters written
    uint64_t read_bytes;            // bytes read (from storage layer)
    uint64_t write_bytes;           // bytes written (to storage layer)
};

struct uid_info {
    uint32_t uid;                   // user id
    std::string name;               // package name
    struct uid_io_stats io[UID_STATS_SIZE];      // [0]:foreground [1]:background

};

class uid_monitor {
private:
    std::unordered_map<uint32_t, struct uid_info> last_uids;
    void set_last_uids(std::unordered_map<uint32_t, struct uid_info>&& uids, uint64_t ts);
    int interval; // monitor interval in seconds
    uint64_t last_report_ts; // timestamp of last report in nsec
public:
    uid_monitor();
    void set_periodic_chores_interval(int t) { interval = t; }
    int get_periodic_chores_interval() { return interval; }
    std::unordered_map<uint32_t, struct uid_info> get_uids();
    void report();
};

#endif /* _STORAGED_UID_MONITOR_H_ */
Loading