Merge "libbase: add O_CLOEXEC to <android-base/file.h>."
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index ad77064..6960345 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -293,6 +293,9 @@
struct passwd pwent;
struct passwd* result;
int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (pwent_max == -1) {
+ pwent_max = 16384;
+ }
std::vector<char> buf(pwent_max);
int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
if (rc == 0 && result) {
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 3124852..b5bed28 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -204,8 +204,8 @@
" sideload OTAPACKAGE sideload the given full OTA package\n"
" root restart adbd with root permissions\n"
" unroot restart adbd without root permissions\n"
- " usb restart adb server listening on USB\n"
- " tcpip PORT restart adb server listening on TCP on PORT\n"
+ " usb restart adbd listening on USB\n"
+ " tcpip PORT restart adbd listening on TCP on PORT\n"
"\n"
"internal debugging:\n"
" start-server ensure that there is a server running\n"
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index 1748665..5abf514 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -75,46 +75,6 @@
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
-// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
-// but can be used on anonymous types or types defined inside
-// functions. It's less safe than arraysize as it accepts some
-// (although not all) pointers. Therefore, you should use arraysize
-// whenever possible.
-//
-// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
-// size_t.
-//
-// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error
-//
-// "warning: division by zero in ..."
-//
-// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
-// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
-//
-// The following comments are on the implementation details, and can
-// be ignored by the users.
-//
-// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
-// the array) and sizeof(*(arr)) (the # of bytes in one array
-// element). If the former is divisible by the latter, perhaps arr is
-// indeed an array, in which case the division result is the # of
-// elements in the array. Otherwise, arr cannot possibly be an array,
-// and we generate a compiler error to prevent the code from
-// compiling.
-//
-// Since the size of bool is implementation-defined, we need to cast
-// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
-// result has type size_t.
-//
-// This macro is not perfect as it wrongfully accepts certain
-// pointers, namely where the pointer size is divisible by the pointee
-// size. Since all our code has to go through a 32-bit compiler,
-// where a pointer is 4 bytes, this means all pointers to a type whose
-// size is 3 or greater than 4 will be (righteously) rejected.
-#define ARRAYSIZE_UNSAFE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
- static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)
// Changing this definition will cause you a lot of pain. A majority of
@@ -153,23 +113,23 @@
// case 42:
// ...
//
-// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
-// followed by a semicolon. It is designed to mimic control-flow statements
-// like 'break;', so it can be placed in most places where 'break;' can, but
-// only if there are no statements on the execution path between it and the
-// next switch label.
+// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+// followed by a semicolon. It is designed to mimic control-flow statements
+// like 'break;', so it can be placed in most places where 'break;' can, but
+// only if there are no statements on the execution path between it and the
+// next switch label.
//
-// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
-// [[clang::fallthrough]] attribute, which is analysed when performing switch
-// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
-// documentation on language extensions for details:
-// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
+// [[clang::fallthrough]] attribute, which is analysed when performing switch
+// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
+// documentation on language extensions for details:
+// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
//
-// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
-// effect on diagnostics.
+// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+// effect on diagnostics.
//
-// In either case this macro has no effect on runtime behavior and performance
-// of code.
+// In either case this macro has no effect on runtime behavior and performance
+// of code.
#ifndef FALLTHROUGH_INTENDED
#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT
#endif
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 64e9fb4..ad488a9 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -590,6 +590,7 @@
// Mount kScratchMountPoint
bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type) {
+ if (!fs_mgr_rw_access(device_path)) return false;
if (setfscreatecon(kOverlayfsFileContext)) {
PERROR << "setfscreatecon " << kOverlayfsFileContext;
}
@@ -826,6 +827,19 @@
if (change) *change = false;
mount_point = fs_mgr_mount_point(mount_point);
auto ret = true;
+ // If scratch exists, but is not mounted, lets gain access to clean
+ // specific override entries.
+ if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
+ auto scratch_device = fs_mgr_overlayfs_scratch_device();
+ if (scratch_device.empty()) {
+ auto slot_number = fs_mgr_overlayfs_slot_number();
+ auto super_device = fs_mgr_overlayfs_super_device(slot_number);
+ const auto partition_name = android::base::Basename(kScratchMountPoint);
+ CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s,
+ &scratch_device);
+ }
+ fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type());
+ }
for (const auto& overlay_mount_point : kOverlayMountPoints) {
ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
}
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h
index e8f51da..e72d159 100644
--- a/lmkd/include/lmkd.h
+++ b/lmkd/include/lmkd.h
@@ -31,6 +31,7 @@
LMK_PROCPRIO, /* Register a process and set its oom_adj_score */
LMK_PROCREMOVE, /* Unregister a process */
LMK_PROCPURGE, /* Purge all registered processes */
+ LMK_GETKILLCNT, /* Get number of kills */
};
/*
@@ -152,6 +153,44 @@
return sizeof(int);
}
+/* LMK_GETKILLCNT packet payload */
+struct lmk_getkillcnt {
+ int min_oomadj;
+ int max_oomadj;
+};
+
+/*
+ * For LMK_GETKILLCNT packet get its payload.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
+ struct lmk_getkillcnt *params) {
+ params->min_oomadj = ntohl(packet[1]);
+ params->max_oomadj = ntohl(packet[2]);
+}
+
+/*
+ * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
+ struct lmk_getkillcnt *params) {
+ packet[0] = htonl(LMK_GETKILLCNT);
+ packet[1] = htonl(params->min_oomadj);
+ packet[2] = htonl(params->max_oomadj);
+ return 3 * sizeof(int);
+}
+
+/*
+ * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
+ packet[0] = htonl(LMK_GETKILLCNT);
+ packet[1] = htonl(kill_cnt);
+ return 2 * sizeof(int);
+}
+
__END_DECLS
#endif /* _LMKD_H_ */
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 0a469e8..e3c4ccc 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -313,7 +313,20 @@
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
-static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1];
+#define ADJTOSLOT_COUNT (ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1)
+static struct adjslot_list procadjslot_list[ADJTOSLOT_COUNT];
+
+#define MAX_DISTINCT_OOM_ADJ 32
+#define KILLCNT_INVALID_IDX 0xFF
+/*
+ * Because killcnt array is sparse a two-level indirection is used
+ * to keep the size small. killcnt_idx stores index of the element in
+ * killcnt array. Index KILLCNT_INVALID_IDX indicates an unused slot.
+ */
+static uint8_t killcnt_idx[ADJTOSLOT_COUNT];
+static uint16_t killcnt[MAX_DISTINCT_OOM_ADJ];
+static int killcnt_free_idx = 0;
+static uint32_t killcnt_total = 0;
/* PAGE_SIZE / 1024 */
static long page_k;
@@ -644,6 +657,67 @@
memset(&pidhash[0], 0, sizeof(pidhash));
}
+static void inc_killcnt(int oomadj) {
+ int slot = ADJTOSLOT(oomadj);
+ uint8_t idx = killcnt_idx[slot];
+
+ if (idx == KILLCNT_INVALID_IDX) {
+ /* index is not assigned for this oomadj */
+ if (killcnt_free_idx < MAX_DISTINCT_OOM_ADJ) {
+ killcnt_idx[slot] = killcnt_free_idx;
+ killcnt[killcnt_free_idx] = 1;
+ killcnt_free_idx++;
+ } else {
+ ALOGW("Number of distinct oomadj levels exceeds %d",
+ MAX_DISTINCT_OOM_ADJ);
+ }
+ } else {
+ /*
+ * wraparound is highly unlikely and is detectable using total
+ * counter because it has to be equal to the sum of all counters
+ */
+ killcnt[idx]++;
+ }
+ /* increment total kill counter */
+ killcnt_total++;
+}
+
+static int get_killcnt(int min_oomadj, int max_oomadj) {
+ int slot;
+ int count = 0;
+
+ if (min_oomadj > max_oomadj)
+ return 0;
+
+ /* special case to get total kill count */
+ if (min_oomadj > OOM_SCORE_ADJ_MAX)
+ return killcnt_total;
+
+ while (min_oomadj <= max_oomadj &&
+ (slot = ADJTOSLOT(min_oomadj)) < ADJTOSLOT_COUNT) {
+ uint8_t idx = killcnt_idx[slot];
+ if (idx != KILLCNT_INVALID_IDX) {
+ count += killcnt[idx];
+ }
+ min_oomadj++;
+ }
+
+ return count;
+}
+
+static int cmd_getkillcnt(LMKD_CTRL_PACKET packet) {
+ struct lmk_getkillcnt params;
+
+ if (use_inkernel_interface) {
+ /* kernel driver does not expose this information */
+ return 0;
+ }
+
+ lmkd_pack_get_getkillcnt(packet, ¶ms);
+
+ return get_killcnt(params.min_oomadj, params.max_oomadj);
+}
+
static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
int i;
struct lmk_target target;
@@ -748,12 +822,28 @@
return ret;
}
+static int ctrl_data_write(int dsock_idx, char *buf, size_t bufsz) {
+ int ret = 0;
+
+ ret = TEMP_FAILURE_RETRY(write(data_sock[dsock_idx].sock, buf, bufsz));
+
+ if (ret == -1) {
+ ALOGE("control data socket write failed; errno=%d", errno);
+ } else if (ret == 0) {
+ ALOGE("Got EOF on control data socket");
+ ret = -1;
+ }
+
+ return ret;
+}
+
static void ctrl_command_handler(int dsock_idx) {
LMKD_CTRL_PACKET packet;
int len;
enum lmk_cmd cmd;
int nargs;
int targets;
+ int kill_cnt;
len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE);
if (len <= 0)
@@ -791,6 +881,14 @@
goto wronglen;
cmd_procpurge();
break;
+ case LMK_GETKILLCNT:
+ if (nargs != 2)
+ goto wronglen;
+ kill_cnt = cmd_getkillcnt(packet);
+ len = lmkd_pack_set_getkillcnt_repl(packet, kill_cnt);
+ if (ctrl_data_write(dsock_idx, (char *)packet, len) != len)
+ return;
+ break;
default:
ALOGE("Received unknown command code %d", cmd);
return;
@@ -1200,6 +1298,7 @@
/* CAP_KILL required */
r = kill(pid, SIGKILL);
+ inc_killcnt(procp->oomadj);
ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
taskname, pid, uid, procp->oomadj, tasksize * page_k);
@@ -1700,6 +1799,8 @@
procadjslot_list[i].prev = &procadjslot_list[i];
}
+ memset(killcnt_idx, KILLCNT_INVALID_IDX, sizeof(killcnt_idx));
+
return 0;
}