Merge "Freezer: improve file lock exemption"

This commit is contained in:
Li Li
2022-11-16 17:01:23 +00:00
committed by Android (Google) Code Review
3 changed files with 106 additions and 49 deletions

View File

@@ -16,6 +16,8 @@
package com.android.internal.os;
import android.util.IntArray;
import com.android.internal.util.ProcFileReader;
import java.io.FileInputStream;
@@ -35,6 +37,7 @@ import java.io.IOException;
public class ProcLocksReader {
private final String mPath;
private ProcFileReader mReader = null;
private IntArray mPids = new IntArray();
public ProcLocksReader() {
mPath = "/proc/locks";
@@ -51,9 +54,13 @@ public class ProcLocksReader {
public interface ProcLocksReaderCallback {
/**
* Call the callback function of handleBlockingFileLocks().
* @param pid Each process that hold file locks blocking other processes.
* @param pids Each process that hold file locks blocking other processes.
* pids[0] is the process blocking others
* pids[1..n-1] are the processes being blocked
* NOTE: pids are cleared immediately after onBlockingFileLock() returns. If the caller
* needs to cache it, please make a copy, e.g. by calling pids.toArray().
*/
void onBlockingFileLock(int pid);
void onBlockingFileLock(IntArray pids);
}
/**
@@ -64,8 +71,7 @@ public class ProcLocksReader {
public void handleBlockingFileLocks(ProcLocksReaderCallback callback) throws IOException {
long last = -1;
long id; // ordinal position of the lock in the list
int owner = -1; // the PID of the process that owns the lock
int pid = -1; // the PID of the process blocking others
int pid = -1; // the PID of the process being blocked
if (mReader == null) {
mReader = new ProcFileReader(new FileInputStream(mPath));
@@ -73,26 +79,49 @@ public class ProcLocksReader {
mReader.rewind();
}
mPids.clear();
while (mReader.hasMoreData()) {
id = mReader.nextLong(true); // lock id
if (id == last) {
mReader.finishLine(); // blocked lock
if (pid < 0) {
pid = owner; // get pid from the previous line
callback.onBlockingFileLock(pid);
// blocked lock found
mReader.nextIgnored(); // ->
mReader.nextIgnored(); // lock type: POSIX?
mReader.nextIgnored(); // lock type: MANDATORY?
mReader.nextIgnored(); // lock type: RW?
pid = mReader.nextInt(); // pid
if (pid > 0) {
mPids.add(pid);
}
continue;
mReader.finishLine();
} else {
pid = -1; // a new lock
// process blocking lock and move on to a new lock
if (mPids.size() > 1) {
callback.onBlockingFileLock(mPids);
mPids.clear();
}
// new lock found
mReader.nextIgnored(); // lock type: POSIX?
mReader.nextIgnored(); // lock type: MANDATORY?
mReader.nextIgnored(); // lock type: RW?
pid = mReader.nextInt(); // pid
if (pid > 0) {
if (mPids.size() == 0) {
mPids.add(pid);
} else {
mPids.set(0, pid);
}
}
mReader.finishLine();
last = id;
}
mReader.nextIgnored(); // lock type: POSIX?
mReader.nextIgnored(); // lock type: MANDATORY?
mReader.nextIgnored(); // lock type: RW?
owner = mReader.nextInt(); // pid
mReader.finishLine();
last = id;
}
// The last unprocessed blocking lock immediately before EOF
if (mPids.size() > 1) {
callback.onBlockingFileLock(mPids);
}
}
}

View File

@@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.os.FileUtils;
import android.util.IntArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -33,13 +34,15 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ProcLocksReaderTest implements
ProcLocksReader.ProcLocksReaderCallback {
private File mProcDirectory;
private ArrayList<Integer> mPids = new ArrayList<>();
private ArrayList<int[]> mPids = new ArrayList<>();
@Before
public void setUp() {
@@ -54,41 +57,51 @@ public class ProcLocksReaderTest implements
@Test
public void testRunSimpleLocks() throws Exception {
String simpleLocks =
"1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" +
"2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n";
String simpleLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n";
runHandleBlockingFileLocks(simpleLocks);
assertTrue(mPids.isEmpty());
}
@Test
public void testRunBlockingLocks() throws Exception {
String blockedLocks =
"1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" +
"2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n" +
"2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n" +
"2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n" +
"3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n" +
"4: POSIX ADVISORY READ 3888 fd:09:14230 1073741826 1073742335\n";
String blockedLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"
+ "2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n"
+ "2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n"
+ "3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n"
+ "4: POSIX ADVISORY READ 3888 fd:09:14230 1073741826 1073742335\n";
runHandleBlockingFileLocks(blockedLocks);
assertTrue(mPids.remove(0).equals(18292));
assertTrue(Arrays.equals(mPids.remove(0), new int[]{18292, 18291, 18293}));
assertTrue(mPids.isEmpty());
}
@Test
public void testRunLastBlockingLocks() throws Exception {
String blockedLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"
+ "2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n"
+ "2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n";
runHandleBlockingFileLocks(blockedLocks);
assertTrue(Arrays.equals(mPids.remove(0), new int[]{18292, 18291, 18293}));
assertTrue(mPids.isEmpty());
}
@Test
public void testRunMultipleBlockingLocks() throws Exception {
String blockedLocks =
"1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n" +
"2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n" +
"2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n" +
"2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n" +
"3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n" +
"4: FLOCK ADVISORY WRITE 3840 fe:01:5111809 0 EOF\n" +
"4: -> FLOCK ADVISORY WRITE 3841 fe:01:5111809 0 EOF\n" +
"5: POSIX ADVISORY READ 3888 fd:09:14230 1073741826 1073742335\n";
String blockedLocks = "1: POSIX ADVISORY READ 18403 fd:09:9070 1073741826 1073742335\n"
+ "2: POSIX ADVISORY WRITE 18292 fd:09:34062 0 EOF\n"
+ "2: -> POSIX ADVISORY WRITE 18291 fd:09:34062 0 EOF\n"
+ "2: -> POSIX ADVISORY WRITE 18293 fd:09:34062 0 EOF\n"
+ "3: POSIX ADVISORY READ 3888 fd:09:13992 128 128\n"
+ "4: FLOCK ADVISORY WRITE 3840 fe:01:5111809 0 EOF\n"
+ "4: -> FLOCK ADVISORY WRITE 3841 fe:01:5111809 0 EOF\n"
+ "5: FLOCK ADVISORY READ 3888 fd:09:14230 0 EOF\n"
+ "5: -> FLOCK ADVISORY READ 3887 fd:09:14230 0 EOF\n";
runHandleBlockingFileLocks(blockedLocks);
assertTrue(mPids.remove(0).equals(18292));
assertTrue(mPids.remove(0).equals(3840));
assertTrue(Arrays.equals(mPids.remove(0), new int[]{18292, 18291, 18293}));
assertTrue(Arrays.equals(mPids.remove(0), new int[]{3840, 3841}));
assertTrue(Arrays.equals(mPids.remove(0), new int[]{3888, 3887}));
assertTrue(mPids.isEmpty());
}
@@ -102,11 +115,12 @@ public class ProcLocksReaderTest implements
/**
* Call the callback function of handleBlockingFileLocks().
*
* @param pid Each process that hold file locks blocking other processes.
* @param pids Each process that hold file locks blocking other processes.
* pids[0] is the process blocking others
* pids[1..n-1] are the processes being blocked
*/
@Override
public void onBlockingFileLock(int pid) {
mPids.add(pid);
public void onBlockingFileLock(IntArray pids) {
mPids.add(pids.toArray());
}
}

View File

@@ -37,6 +37,7 @@ import android.provider.DeviceConfig.Properties;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -2110,15 +2111,28 @@ public final class CachedAppOptimizer {
@GuardedBy({"mAm"})
@Override
public void onBlockingFileLock(int pid) {
public void onBlockingFileLock(IntArray pids) {
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "Process (pid=" + pid + ") holds blocking file lock");
Slog.d(TAG_AM, "Blocking file lock found: " + pids);
}
synchronized (mProcLock) {
int pid = pids.get(0);
ProcessRecord app = mFrozenProcesses.get(pid);
ProcessRecord pr;
if (app != null) {
Slog.i(TAG_AM, app.processName + " (" + pid + ") holds blocking file lock");
unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
for (int i = 1; i < pids.size(); i++) {
int blocked = pids.get(i);
synchronized (mAm.mPidsSelfLocked) {
pr = mAm.mPidsSelfLocked.get(blocked);
}
if (pr != null && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
+ pr.processName + " (" + blocked + ")");
// Found at least one blocked non-cached process
unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
break;
}
}
}
}
}