From 7265abe77a76f848a316640b5da106e882bdbc8a Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Fri, 21 Nov 2014 13:54:45 -0800 Subject: Be increasingly aggressive about fstrim if it isn't being run The current heuristics depend on devices being alive at midnight+ in order to run periodic background fstrim operations. This unfortunately means that people who routinely turn their devices off overnight wind up with their devices *never* running fstrim, and this causes major performance and disk-life problems. We now backstop this very-friendly schedule with an increasingly aggressive one. If the device goes a defined time without a background fstrim, we then force the fstrim at the next reboot. Once the device hits the midnight+ idle fstrim request time, then we already aggressively attempt to fstrim at the first available moment thereafter, even if it's days/weeks later without a reboot. 'Available' here means charging + device idle. If the device never becomes idle then we can't do much without rendering an in-use device inoperable for some number of minutes -- but we have no evidence of devices ever failing to run fstrim due to this usage pattern. A new Settings.Global element (type 'long', called "fstrim_mandatory_interval") is the source of the backstop time. If this element is zero or negative, no mandatory boot-time fstrim will ever be performed. If the element is not supplied on a given device, the default backstop is 3 days. Adds a new string to display in the upgrading dialog when doing the fstrim. Note it is too late for this to be localized, but since this operation can take a long time it is probably better to have it show *something* even if not localized, rather than just sit there. Bug 18486922 Change-Id: I5b265ca0a65570fb8931251aa1ac37b530635a2c --- core/java/android/os/storage/IMountService.java | 63 +++++++++++++++++++++++++ core/java/android/provider/Settings.java | 7 +++ 2 files changed, 70 insertions(+) (limited to 'core/java/android') diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index cf407f401844..116110eba74d 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -856,6 +856,38 @@ public interface IMountService extends IInterface { } return _result; } + + @Override + public long lastMaintenance() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + long _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_lastMaintenance, _data, _reply, 0); + _reply.readException(); + _result = _reply.readLong(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + @Override + public void runMaintenance() throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + mRemote.transact(Stub.TRANSACTION_runMaintenance, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return; + } } private static final String DESCRIPTOR = "IMountService"; @@ -942,6 +974,10 @@ public interface IMountService extends IInterface { static final int TRANSACTION_resizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 40; + static final int TRANSACTION_lastMaintenance = IBinder.FIRST_CALL_TRANSACTION + 41; + + static final int TRANSACTION_runMaintenance = IBinder.FIRST_CALL_TRANSACTION + 42; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1347,6 +1383,19 @@ public interface IMountService extends IInterface { reply.writeInt(resultCode); return true; } + case TRANSACTION_lastMaintenance: { + data.enforceInterface(DESCRIPTOR); + long lastMaintenance = lastMaintenance(); + reply.writeNoException(); + reply.writeLong(lastMaintenance); + return true; + } + case TRANSACTION_runMaintenance: { + data.enforceInterface(DESCRIPTOR); + runMaintenance(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1617,4 +1666,18 @@ public interface IMountService extends IInterface { public String getField(String field) throws RemoteException; public int resizeSecureContainer(String id, int sizeMb, String key) throws RemoteException; + + /** + * Report the time of the last maintenance operation such as fstrim. + * @return Timestamp of the last maintenance operation, in the + * System.currentTimeMillis() time base + * @throws RemoteException + */ + public long lastMaintenance() throws RemoteException; + + /** + * Kick off an immediate maintenance operation + * @throws RemoteException + */ + public void runMaintenance() throws RemoteException; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 79e84d959109..73c7cc38af49 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5543,6 +5543,13 @@ public final class Settings { */ public static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs"; + /** + * Time since last fstrim (milliseconds) after which we force one to happen + * during device startup. If unset, the default is 3 days. + * @hide + */ + public static final String FSTRIM_MANDATORY_INTERVAL = "fstrim_mandatory_interval"; + /** * The interval in milliseconds at which to check packet counts on the * mobile data interface when screen is on, to detect possible data -- cgit v1.2.3