Merge "zram: support zram_writeback"
This commit is contained in:
commit
2fdbdfddac
5 changed files with 157 additions and 0 deletions
|
@ -79,6 +79,7 @@
|
|||
|
||||
#define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
|
||||
#define ZRAM_CONF_MCS "/sys/block/zram0/max_comp_streams"
|
||||
#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
|
||||
|
||||
|
@ -1373,6 +1374,70 @@ int fs_mgr_do_tmpfs_mount(const char *n_name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool InstallZramDevice(const std::string& device) {
|
||||
if (!android::base::WriteStringToFile(device, ZRAM_BACK_DEV)) {
|
||||
PERROR << "Cannot write " << device << " in: " << ZRAM_BACK_DEV;
|
||||
return false;
|
||||
}
|
||||
LINFO << "Success to set " << device << " to " << ZRAM_BACK_DEV;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool PrepareZramDevice(const std::string& loop, off64_t size, const std::string& bdev) {
|
||||
if (loop.empty() && bdev.empty()) return true;
|
||||
|
||||
if (bdev.length()) {
|
||||
return InstallZramDevice(bdev);
|
||||
}
|
||||
|
||||
// Get free loopback
|
||||
unique_fd loop_fd(TEMP_FAILURE_RETRY(open("/dev/loop-control", O_RDWR | O_CLOEXEC)));
|
||||
if (loop_fd.get() == -1) {
|
||||
PERROR << "Cannot open loop-control";
|
||||
return false;
|
||||
}
|
||||
|
||||
int num = ioctl(loop_fd.get(), LOOP_CTL_GET_FREE);
|
||||
if (num == -1) {
|
||||
PERROR << "Cannot get free loop slot";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepare target path
|
||||
unique_fd target_fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0664)));
|
||||
if (target_fd.get() == -1) {
|
||||
PERROR << "Cannot open target path: " << loop;
|
||||
return false;
|
||||
}
|
||||
if (fallocate(target_fd.get(), 0, 0, size) < 0) {
|
||||
PERROR << "Cannot truncate target path: " << loop;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect loopback (device_fd) to target path (target_fd)
|
||||
std::string device = android::base::StringPrintf("/dev/block/loop%d", num);
|
||||
unique_fd device_fd(TEMP_FAILURE_RETRY(open(device.c_str(), O_RDWR | O_CLOEXEC)));
|
||||
if (device_fd.get() == -1) {
|
||||
PERROR << "Cannot open /dev/block/loop" << num;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get())) {
|
||||
PERROR << "Cannot set loopback to target path";
|
||||
return false;
|
||||
}
|
||||
|
||||
// set block size & direct IO
|
||||
if (ioctl(device_fd.get(), LOOP_SET_BLOCK_SIZE, 4096)) {
|
||||
PWARNING << "Cannot set 4KB blocksize to /dev/block/loop" << num;
|
||||
}
|
||||
if (ioctl(device_fd.get(), LOOP_SET_DIRECT_IO, 1)) {
|
||||
PWARNING << "Cannot set direct_io to /dev/block/loop" << num;
|
||||
}
|
||||
|
||||
return InstallZramDevice(device);
|
||||
}
|
||||
|
||||
bool fs_mgr_swapon_all(const Fstab& fstab) {
|
||||
bool ret = true;
|
||||
for (const auto& entry : fstab) {
|
||||
|
@ -1381,6 +1446,10 @@ bool fs_mgr_swapon_all(const Fstab& fstab) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!PrepareZramDevice(entry.zram_loopback_path, entry.zram_loopback_size, entry.zram_backing_dev_path)) {
|
||||
LERROR << "Skipping losetup for '" << entry.blk_device << "'";
|
||||
}
|
||||
|
||||
if (entry.zram_size > 0) {
|
||||
// A zram_size was specified, so we need to configure the
|
||||
// device. There is no point in having multiple zram devices
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/parseint.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <libgsi/libgsi.h>
|
||||
|
@ -44,6 +45,9 @@ struct fs_mgr_flag_values {
|
|||
std::string key_dir;
|
||||
std::string verity_loc;
|
||||
std::string sysfs_path;
|
||||
std::string zram_loopback_path;
|
||||
uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default
|
||||
std::string zram_backing_dev_path;
|
||||
off64_t part_length = 0;
|
||||
std::string label;
|
||||
int partnum = -1;
|
||||
|
@ -118,6 +122,9 @@ static struct flag_list fs_mgr_flags[] = {
|
|||
{"checkpoint=block", MF_CHECKPOINT_BLK},
|
||||
{"checkpoint=fs", MF_CHECKPOINT_FS},
|
||||
{"slotselect_other", MF_SLOTSELECT_OTHER},
|
||||
{"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH},
|
||||
{"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE},
|
||||
{"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
|
@ -345,6 +352,16 @@ static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_fla
|
|||
} else if (flag == MF_SYSFS) {
|
||||
/* The path to trigger device gc by idle-maint of vold. */
|
||||
flag_vals->sysfs_path = arg;
|
||||
} else if (flag == MF_ZRAM_LOOPBACK_PATH) {
|
||||
/* The path to use loopback for zram. */
|
||||
flag_vals->zram_loopback_path = arg;
|
||||
} else if (flag == MF_ZRAM_LOOPBACK_SIZE) {
|
||||
if (!android::base::ParseByteCount(arg, &flag_vals->zram_loopback_size)) {
|
||||
LERROR << "Warning: zram_loopback_size = flag malformed";
|
||||
}
|
||||
} else if (flag == MF_ZRAM_BACKING_DEV_PATH) {
|
||||
/* The path to use loopback for zram. */
|
||||
flag_vals->zram_backing_dev_path = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -570,6 +587,9 @@ static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fs
|
|||
entry.logical_blk_size = flag_vals.logical_blk_size;
|
||||
entry.sysfs_path = std::move(flag_vals.sysfs_path);
|
||||
entry.vbmeta_partition = std::move(flag_vals.vbmeta_partition);
|
||||
entry.zram_loopback_path = std::move(flag_vals.zram_loopback_path);
|
||||
entry.zram_loopback_size = std::move(flag_vals.zram_loopback_size);
|
||||
entry.zram_backing_dev_path = std::move(flag_vals.zram_backing_dev_path);
|
||||
if (entry.fs_mgr_flags.logical) {
|
||||
entry.logical_partition_name = entry.blk_device;
|
||||
}
|
||||
|
@ -811,6 +831,8 @@ void fs_mgr_free_fstab(struct fstab *fstab)
|
|||
free(fstab->recs[i].key_dir);
|
||||
free(fstab->recs[i].label);
|
||||
free(fstab->recs[i].sysfs_path);
|
||||
free(fstab->recs[i].zram_loopback_path);
|
||||
free(fstab->recs[i].zram_backing_dev_path);
|
||||
}
|
||||
|
||||
/* Free the fstab_recs array created by calloc(3) */
|
||||
|
@ -908,6 +930,9 @@ FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec) {
|
|||
entry.erase_blk_size = fstab_rec->erase_blk_size;
|
||||
entry.logical_blk_size = fstab_rec->logical_blk_size;
|
||||
entry.sysfs_path = fstab_rec->sysfs_path;
|
||||
entry.zram_loopback_path = fstab_rec->zram_loopback_path;
|
||||
entry.zram_loopback_size = fstab_rec->zram_loopback_size;
|
||||
entry.zram_backing_dev_path = fstab_rec->zram_backing_dev_path;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -951,6 +976,9 @@ fstab* FstabToLegacyFstab(const Fstab& fstab) {
|
|||
legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
|
||||
legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
|
||||
legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
|
||||
legacy_fstab->recs[i].zram_loopback_path = strdup(fstab[i].zram_loopback_path.c_str());
|
||||
legacy_fstab->recs[i].zram_loopback_size = fstab[i].zram_loopback_size;
|
||||
legacy_fstab->recs[i].zram_backing_dev_path = strdup(fstab[i].zram_backing_dev_path.c_str());
|
||||
}
|
||||
return legacy_fstab;
|
||||
}
|
||||
|
|
|
@ -122,6 +122,12 @@
|
|||
0x80000000
|
||||
#define MF_SLOTSELECT_OTHER \
|
||||
0x100000000
|
||||
#define MF_ZRAM_LOOPBACK_PATH \
|
||||
0x200000000
|
||||
#define MF_ZRAM_LOOPBACK_SIZE \
|
||||
0x400000000
|
||||
#define MF_ZRAM_BACKING_DEV_PATH \
|
||||
0x800000000
|
||||
// clang-format on
|
||||
|
||||
#define DM_BUF_SIZE 4096
|
||||
|
|
|
@ -59,6 +59,9 @@ struct fstab_rec {
|
|||
off64_t erase_blk_size;
|
||||
off64_t logical_blk_size;
|
||||
char* sysfs_path;
|
||||
char* zram_loopback_path;
|
||||
uint64_t zram_loopback_size;
|
||||
char* zram_backing_dev_path;
|
||||
};
|
||||
|
||||
struct fstab* fs_mgr_read_fstab_default();
|
||||
|
@ -119,6 +122,9 @@ struct FstabEntry {
|
|||
off64_t logical_blk_size = 0;
|
||||
std::string sysfs_path;
|
||||
std::string vbmeta_partition;
|
||||
std::string zram_loopback_path;
|
||||
uint64_t zram_loopback_size;
|
||||
std::string zram_backing_dev_path;
|
||||
|
||||
// TODO: Remove this union once fstab_rec is deprecated. It only serves as a
|
||||
// convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
#include <fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <mntent.h>
|
||||
#include <linux/loop.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/swap.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -58,6 +60,7 @@
|
|||
using android::base::Split;
|
||||
using android::base::StringPrintf;
|
||||
using android::base::Timer;
|
||||
using android::base::unique_fd;
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
@ -285,6 +288,48 @@ static UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeo
|
|||
return stat;
|
||||
}
|
||||
|
||||
// zram is able to use backing device on top of a loopback device.
|
||||
// In order to unmount /data successfully, we have to kill the loopback device first
|
||||
#define ZRAM_DEVICE "/dev/block/zram0"
|
||||
#define ZRAM_RESET "/sys/block/zram0/reset"
|
||||
#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
|
||||
static void KillZramBackingDevice() {
|
||||
std::string backing_dev;
|
||||
if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return;
|
||||
|
||||
if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return;
|
||||
|
||||
// cut the last "\n"
|
||||
backing_dev.erase(backing_dev.length() - 1);
|
||||
|
||||
// shutdown zram handle
|
||||
Timer swap_timer;
|
||||
LOG(INFO) << "swapoff() start...";
|
||||
if (swapoff(ZRAM_DEVICE) == -1) {
|
||||
LOG(ERROR) << "zram_backing_dev: swapoff (" << backing_dev << ")" << " failed";
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "swapoff() took " << swap_timer;;
|
||||
|
||||
if (!android::base::WriteStringToFile("1", ZRAM_RESET)) {
|
||||
LOG(ERROR) << "zram_backing_dev: reset (" << backing_dev << ")" << " failed";
|
||||
return;
|
||||
}
|
||||
|
||||
// clear loopback device
|
||||
unique_fd loop(TEMP_FAILURE_RETRY(open(backing_dev.c_str(), O_RDWR | O_CLOEXEC)));
|
||||
if (loop.get() < 0) {
|
||||
LOG(ERROR) << "zram_backing_dev: open(" << backing_dev << ")" << " failed";
|
||||
return;
|
||||
}
|
||||
|
||||
if (ioctl(loop.get(), LOOP_CLR_FD, 0) < 0) {
|
||||
LOG(ERROR) << "zram_backing_dev: loop_clear (" << backing_dev << ")" << " failed";
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "zram_backing_dev: `" << backing_dev << "` is cleared successfully.";
|
||||
}
|
||||
|
||||
//* Reboot / shutdown the system.
|
||||
// cmd ANDROID_RB_* as defined in android_reboot.h
|
||||
// reason Reason string like "reboot", "shutdown,userrequested"
|
||||
|
@ -427,6 +472,9 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
|
|||
sync();
|
||||
LOG(INFO) << "sync() before umount took" << sync_timer;
|
||||
}
|
||||
// 5. drop caches and disable zram backing device, if exist
|
||||
KillZramBackingDevice();
|
||||
|
||||
UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
|
||||
// Follow what linux shutdown is doing: one more sync with little bit delay
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue