static int swap_file_activate(void *data)
{
struct swap_module_ops *swap = (struct swap_module_ops *)data;
- int r;
file_control.swap_reclaim_bytes =
file_control.swap_file_size * FILESWAP_FULLNESS_RATIO;
- r = access(file_control.swapfile, F_OK);
- if (r < 0 && errno == ENOENT) {
- r = do_dd("/dev/zero", file_control.swapfile, PAGE_SIZE,
- KBYTE_TO_BYTE(swap->k_size) >> PAGE_SHIFT);
- if (r > 0) {
- _E("Failed to create swap file(%s), exit code: %d",
- file_control.swapfile, r);
- return -1;
- } else if (r < 0) {
- _E("Failed to create swap file(%s): %s",
- file_control.swapfile, strerror(-r));
- return r;
- }
- _I("SwapFile is created: %s", file_control.swapfile);
- } else if (r != 0) {
- _E("Failed to access swap file(%s): %m",
- file_control.swapfile);
- return -errno;
- }
-
- r = swap_losetup(swap, file_control.crypt_type, file_control.swapfile);
- if (r < 0)
- return r;
-
- if (!swap->path)
- return -ENOENT;
-
- r = do_mkswap(swap->path);
- if (r > 0) {
- _E("Failed to make swap device(%s), exit code: %d", swap->path, r);
- return -EBUSY;
- } else if (r < 0) {
- _E("Failed to make swap device(%s): %s", swap->path, strerror(-r));
- return r;
- }
-
- return 0;
+ return swap_set_file(file_control.swapfile, swap, file_control.crypt_type);
}
static int swap_file_reclaim(void *data)
return 0;
}
-int swap_losetup(struct swap_module_ops *swap,
+static int swap_losetup(struct swap_module_ops *swap,
char *crypt_type,
char *swapfile)
{
return r;
}
+int swap_set_file(char *filename, struct swap_module_ops *swap, char *crypt_type)
+{
+ int r;
+
+ r = access(filename, F_OK);
+ if (r < 0 && errno == ENOENT) {
+ r = do_dd("/dev/zero", filename, PAGE_SIZE,
+ KBYTE_TO_BYTE(swap->k_size) >> PAGE_SHIFT);
+ if (r > 0) {
+ _E("Failed to create swap file(%s), exit code: %d",
+ filename, r);
+ return -1;
+ } else if (r < 0) {
+ _E("Failed to create swap file(%s): %s",
+ filename, strerror(-r));
+ return r;
+ }
+ _I("SwapFile is created: %s", filename);
+ } else if (r != 0) {
+ _E("Failed to access swap file(%s): %m", filename);
+ return -errno;
+ }
+
+ r = swap_losetup(swap, crypt_type, filename);
+ if (r < 0)
+ return r;
+
+ if (!swap->path)
+ return -ENOENT;
+
+ r = do_mkswap(swap->path);
+ if (r > 0) {
+ _E("Failed to make swap device(%s), exit code: %d", swap->path, r);
+ return -EBUSY;
+ } else if (r < 0) {
+ _E("Failed to make swap device(%s): %s", swap->path, strerror(-r));
+ }
+ return r;
+}
+
bool swap_is_on(const char *name)
{
_cleanup_proc_swaps_free_ struct proc_swaps **swaps = NULL;
*type |= SWAP_TYPE_ZRAM;
else if (strneq(word, "file", l))
*type |= SWAP_TYPE_FILE;
+ else if (strneq(word, "zswap", l))
+ *type |= SWAP_TYPE_ZSWAP;
else
return -EINVAL;
}
--- /dev/null
+/*
+ * resourced
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "macro.h"
+#include "module.h"
+#include "module-data.h"
+#include "trace.h"
+#include "util.h"
+#include "file-helper.h"
+#include "procfs.h"
+#include "swap-common.h"
+#include "memory-common.h"
+#include "config-parser.h"
+#include "lowmem-handler.h"
+
+#define DEFAULT_ZSWAP_POOL_RATIO ((double) 0.25)
+#define ZSWAP_FULLNESS_RATIO 0.8
+#define DEFAULT_ZSWAP_FILE_SIZE MBYTE_TO_BYTE(30)
+
+#define ZSWAP_POOL_SIZE "/sys/module/zswap/parameters/max_pool_size"
+#define ZSWAP_WRITTEN_SIZE "/sys/kernel/debug/zswap/written_back_pages"
+
+struct swap_zswap_control {
+ char crypt_type[MAX_TYPE_LENGTH];
+ char swapfile[64];
+ float zpool_ratio;
+ unsigned long zswap_file_size;
+ unsigned long zswap_reclaim_bytes;
+};
+
+static struct swap_zswap_control zswap_control = {
+ .crypt_type = "aes",
+ .swapfile = SWAP_FILE_NAME,
+ .zpool_ratio = DEFAULT_ZSWAP_POOL_RATIO,
+ .zswap_file_size = DEFAULT_ZSWAP_FILE_SIZE,
+ .zswap_reclaim_bytes = 0,
+};
+
+static int swap_zswap_activate(void *data)
+{
+ struct swap_module_ops *swap = (struct swap_module_ops *)data;
+ unsigned int max_pool_size;
+ int r;
+
+ zswap_control.zswap_reclaim_bytes =
+ zswap_control.zswap_file_size * ZSWAP_FULLNESS_RATIO;
+
+ r = swap_set_file(zswap_control.swapfile, swap, zswap_control.crypt_type);
+ if (r < 0)
+ return r;
+
+ max_pool_size = lowmem_get_ktotalram() * zswap_control.zpool_ratio;
+ r = fwrite_int(ZSWAP_POOL_SIZE, max_pool_size);
+ if (r < 0) {
+ _E("fail to write max_pool_size : %d", max_pool_size);
+ return r;
+ }
+
+ return 0;
+}
+
+static int swap_zswap_reclaim(void *data)
+{
+ int r;
+ unsigned int swap_size;
+
+ r = fread_uint(ZSWAP_WRITTEN_SIZE, &swap_size);
+ if (r < 0) {
+ _E("fail to read written swap size");
+ return r;
+ }
+
+ swap_size <<= PAGE_SHIFT;
+ if (swap_size <= zswap_control.zswap_reclaim_bytes)
+ return 0;
+
+ return -ENOSPC;
+}
+
+static int swap_zswap_parse_config_file(void)
+{
+ ConfigTableItem items[] = {
+ { "FILE", "CryptType", config_parse_string, 0, NULL },
+ { "FILE", "FileSize", config_parse_bytes, 0, NULL },
+ { "ZSWAP", "PoolRatio", config_parse_float, 0, NULL },
+ { NULL, NULL, NULL, 0, NULL }
+ };
+
+ int r;
+ _cleanup_free_ char *crypt_type = NULL;
+
+ items[0].data = &crypt_type;
+ items[1].data = &zswap_control.zswap_file_size;
+ items[2].data = &zswap_control.zpool_ratio;
+
+ r = config_parse_new(SWAP_CONF_FILE, (void*) items);
+ if (r < 0) {
+ _E("Failed to parse configuration file: %s", strerror(-r));
+ return r;
+ }
+
+ if (crypt_type)
+ strncpy(zswap_control.crypt_type, crypt_type, MAX_TYPE_LENGTH-1);
+
+ return 0;
+}
+
+static int swap_zswap_init(void *data)
+{
+ struct swap_module_ops *swap = (struct swap_module_ops *)data;
+ int r;
+
+ if (access(ZSWAP_POOL_SIZE, R_OK) != 0)
+ return -ENOENT;
+
+ r = swap_zswap_parse_config_file();
+ if (r < 0) {
+ _E("Failed to parse SwapFile config: %s", strerror(-r));
+ return r;
+ }
+
+ swap->k_size = BYTE_TO_KBYTE(zswap_control.zswap_file_size);
+ return 0;
+}
+
+static const struct swap_module_ops swap_zswap_ops = {
+ .name = "ZSWAP",
+ .type = SWAP_TYPE_ZSWAP,
+ .path = "",
+ .priority = SWAP_PRI_DISABLE,
+ .k_size = 0,
+ .init = swap_zswap_init,
+ .activate = swap_zswap_activate,
+ .reclaim = swap_zswap_reclaim,
+};
+SWAP_MODLE_REGISTER(&swap_zswap_ops)