@ -22,6 +22,7 @@
# include <list>
# include <list>
# include <memory>
# include <memory>
# include <string>
# include <string>
# include <thread>
# include <vector>
# include <vector>
# include <android-base/file.h>
# include <android-base/file.h>
@ -37,7 +38,11 @@
# include <mntent.h>
# include <mntent.h>
# include <sys/mount.h>
# include <sys/mount.h>
# include <sys/stat.h>
# include <sys/stat.h>
# include <sys/statvfs.h>
# include <unistd.h>
using android : : base : : GetBoolProperty ;
using android : : base : : GetUintProperty ;
using android : : base : : SetProperty ;
using android : : base : : SetProperty ;
using android : : binder : : Status ;
using android : : binder : : Status ;
using android : : fs_mgr : : Fstab ;
using android : : fs_mgr : : Fstab ;
@ -126,7 +131,7 @@ Status cp_startCheckpoint(int retry) {
namespace {
namespace {
bool isCheckpointing = false ;
volatile bool isCheckpointing = false ;
}
}
Status cp_commitChanges ( ) {
Status cp_commitChanges ( ) {
@ -255,6 +260,53 @@ bool cp_needsCheckpoint() {
return false ;
return false ;
}
}
namespace {
const std : : string kSleepTimeProp = " ro.sys.cp_usleeptime " ;
const uint32_t usleeptime_default = 1000 ; // 1 s
const std : : string kMinFreeBytesProp = " ro.sys.cp_min_free_bytes " ;
const uint64_t min_free_bytes_default = 100 * ( 1 < < 20 ) ; // 100 MiB
const std : : string kCommitOnFullProp = " ro.sys.cp_commit_on_full " ;
const bool commit_on_full_default = true ;
static void cp_healthDaemon ( std : : string mnt_pnt , std : : string blk_device , bool is_fs_cp ) {
struct statvfs data ;
uint64_t free_bytes = 0 ;
uint32_t usleeptime = GetUintProperty ( kSleepTimeProp , usleeptime_default , ( uint32_t ) - 1 ) ;
uint64_t min_free_bytes = GetUintProperty ( kSleepTimeProp , min_free_bytes_default , ( uint64_t ) - 1 ) ;
bool commit_on_full = GetBoolProperty ( kCommitOnFullProp , commit_on_full_default ) ;
while ( isCheckpointing ) {
if ( is_fs_cp ) {
statvfs ( mnt_pnt . c_str ( ) , & data ) ;
free_bytes = data . f_bavail * data . f_frsize ;
} else {
int ret ;
std : : string size_filename = std : : string ( " /sys/ " ) + blk_device . substr ( 5 ) + " /bow/free " ;
std : : string content ;
ret = android : : base : : ReadFileToString ( kMetadataCPFile , & content ) ;
if ( ret ) {
free_bytes = std : : strtoul ( content . c_str ( ) , NULL , 10 ) ;
}
}
if ( free_bytes < min_free_bytes ) {
if ( commit_on_full ) {
LOG ( INFO ) < < " Low space for checkpointing. Commiting changes " ;
cp_commitChanges ( ) ;
break ;
} else {
LOG ( INFO ) < < " Low space for checkpointing. Rebooting " ;
cp_abortChanges ( " checkpoint,low_space " , false ) ;
break ;
}
}
usleep ( usleeptime ) ;
}
}
} // namespace
Status cp_prepareCheckpoint ( ) {
Status cp_prepareCheckpoint ( ) {
if ( ! isCheckpointing ) {
if ( ! isCheckpointing ) {
return Status : : ok ( ) ;
return Status : : ok ( ) ;
@ -286,6 +338,12 @@ Status cp_prepareCheckpoint() {
setBowState ( mount_rec . blk_device , " 1 " ) ;
setBowState ( mount_rec . blk_device , " 1 " ) ;
}
}
if ( fstab_rec - > fs_mgr_flags . checkpoint_blk | | fstab_rec - > fs_mgr_flags . checkpoint_fs ) {
std : : thread ( cp_healthDaemon , std : : string ( mount_rec . mount_point ) ,
std : : string ( mount_rec . mount_point ) ,
fstab_rec - > fs_mgr_flags . checkpoint_fs = = 1 )
. detach ( ) ;
}
}
}
return Status : : ok ( ) ;
return Status : : ok ( ) ;
}
}