You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
5.7 KiB
234 lines
5.7 KiB
7 months ago
|
/*
|
||
|
* zram: generic RAM based compressed R/W block devices
|
||
|
* http://lkml.org/lkml/2010/8/9/227
|
||
|
*
|
||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of version 2 of the GNU General Public
|
||
|
* License as published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it would be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
*
|
||
|
* Further, this software is distributed without any warranty that it
|
||
|
* is free of the rightful claim of any third person regarding
|
||
|
* infringement or the like. Any license provided herein, whether
|
||
|
* implied or otherwise, applies only to this software file. Patent
|
||
|
* licenses, if any, provided herein do not apply to combinations of
|
||
|
* this program with other software, or any other product whatsoever.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||
|
* 02110-1301, USA.
|
||
|
*/
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/mman.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "test.h"
|
||
|
#include "safe_macros.h"
|
||
|
|
||
|
char *TCID = "zram03";
|
||
|
int TST_TOTAL = 1;
|
||
|
|
||
|
#define PATH_ZRAM "/sys/block/zram0"
|
||
|
#define OBSOLETE_ZRAM_FILE "/sys/block/zram0/num_reads"
|
||
|
#define PATH_ZRAM_STAT "/sys/block/zram0/stat"
|
||
|
#define PATH_ZRAM_MM_STAT "/sys/block/zram0/mm_stat"
|
||
|
#define SIZE (512 * 1024 * 1024L)
|
||
|
#define DEVICE "/dev/zram0"
|
||
|
|
||
|
static int modprobe;
|
||
|
|
||
|
static void set_disksize(void);
|
||
|
static void write_device(void);
|
||
|
static void verify_device(void);
|
||
|
static void reset(void);
|
||
|
static void setup(void);
|
||
|
static void cleanup(void);
|
||
|
static void print(char *string);
|
||
|
static void dump_info(void);
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
int lc;
|
||
|
|
||
|
tst_parse_opts(argc, argv, NULL, NULL);
|
||
|
|
||
|
setup();
|
||
|
|
||
|
for (lc = 0; TEST_LOOPING(lc); lc++) {
|
||
|
tst_count = 0;
|
||
|
|
||
|
set_disksize();
|
||
|
|
||
|
write_device();
|
||
|
dump_info();
|
||
|
verify_device();
|
||
|
|
||
|
reset();
|
||
|
dump_info();
|
||
|
}
|
||
|
cleanup();
|
||
|
tst_exit();
|
||
|
}
|
||
|
|
||
|
static void set_disksize(void)
|
||
|
{
|
||
|
tst_resm(TINFO, "create a zram device with %ld bytes in size.", SIZE);
|
||
|
SAFE_FILE_PRINTF(cleanup, PATH_ZRAM "/disksize", "%ld", SIZE);
|
||
|
}
|
||
|
|
||
|
static void write_device(void)
|
||
|
{
|
||
|
int fd;
|
||
|
char *s;
|
||
|
|
||
|
tst_resm(TINFO, "map this zram device into memory.");
|
||
|
fd = SAFE_OPEN(cleanup, DEVICE, O_RDWR);
|
||
|
s = SAFE_MMAP(cleanup, NULL, SIZE, PROT_READ | PROT_WRITE,
|
||
|
MAP_SHARED, fd, 0);
|
||
|
|
||
|
tst_resm(TINFO, "write all the memory.");
|
||
|
memset(s, 'a', SIZE - 1);
|
||
|
s[SIZE - 1] = '\0';
|
||
|
|
||
|
SAFE_MUNMAP(cleanup, s, SIZE);
|
||
|
SAFE_CLOSE(cleanup, fd);
|
||
|
}
|
||
|
|
||
|
static void verify_device(void)
|
||
|
{
|
||
|
int fd;
|
||
|
long i = 0, fail = 0;
|
||
|
char *s;
|
||
|
|
||
|
tst_resm(TINFO, "verify contents from device.");
|
||
|
fd = SAFE_OPEN(cleanup, DEVICE, O_RDONLY);
|
||
|
s = SAFE_MMAP(cleanup, NULL, SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
|
||
|
|
||
|
while (s[i] && i < SIZE - 1) {
|
||
|
if (s[i] != 'a')
|
||
|
fail++;
|
||
|
i++;
|
||
|
}
|
||
|
if (i != SIZE - 1) {
|
||
|
tst_resm(TFAIL, "expect size: %ld, actual size: %ld.",
|
||
|
SIZE - 1, i);
|
||
|
} else if (s[i] != '\0') {
|
||
|
tst_resm(TFAIL, "zram device seems not null terminated");
|
||
|
} else if (fail) {
|
||
|
tst_resm(TFAIL, "%ld failed bytes found.", fail);
|
||
|
} else {
|
||
|
tst_resm(TPASS, "data read from zram device is consistent "
|
||
|
"with those are written");
|
||
|
}
|
||
|
|
||
|
SAFE_MUNMAP(cleanup, s, SIZE);
|
||
|
SAFE_CLOSE(cleanup, fd);
|
||
|
}
|
||
|
|
||
|
static void reset(void)
|
||
|
{
|
||
|
tst_resm(TINFO, "reset it.");
|
||
|
SAFE_FILE_PRINTF(cleanup, PATH_ZRAM "/reset", "1");
|
||
|
}
|
||
|
|
||
|
static void setup(void)
|
||
|
{
|
||
|
int retried = 0;
|
||
|
|
||
|
tst_require_root();
|
||
|
|
||
|
retry:
|
||
|
if (access(PATH_ZRAM, F_OK) == -1) {
|
||
|
if (errno == ENOENT) {
|
||
|
if (retried) {
|
||
|
tst_brkm(TCONF, NULL,
|
||
|
"system has no zram device.");
|
||
|
}
|
||
|
if (system("modprobe zram") == -1) {
|
||
|
tst_brkm(TBROK | TERRNO, cleanup,
|
||
|
"system(modprobe zram) failed");
|
||
|
}
|
||
|
modprobe = 1;
|
||
|
retried = 1;
|
||
|
goto retry;
|
||
|
} else
|
||
|
tst_brkm(TBROK | TERRNO, NULL, "access");
|
||
|
}
|
||
|
|
||
|
tst_sig(FORK, DEF_HANDLER, cleanup);
|
||
|
TEST_PAUSE;
|
||
|
}
|
||
|
|
||
|
static void cleanup(void)
|
||
|
{
|
||
|
if (modprobe == 1 && system("rmmod zram") == -1)
|
||
|
tst_resm(TWARN | TERRNO, "system(rmmod zram) failed");
|
||
|
}
|
||
|
|
||
|
static void print(char *string)
|
||
|
{
|
||
|
char filename[BUFSIZ], value[BUFSIZ];
|
||
|
|
||
|
sprintf(filename, "%s/%s", PATH_ZRAM, string);
|
||
|
SAFE_FILE_SCANF(cleanup, filename, "%s", value);
|
||
|
tst_resm(TINFO, "%s is %s", filename, value);
|
||
|
}
|
||
|
|
||
|
static void print_stat(char *nread, char *nwrite)
|
||
|
{
|
||
|
char nread_val[BUFSIZ], nwrite_val[BUFSIZ];
|
||
|
|
||
|
SAFE_FILE_SCANF(cleanup, PATH_ZRAM_STAT, "%s %*s %*s %*s %s",
|
||
|
nread_val, nwrite_val);
|
||
|
tst_resm(TINFO, "%s from %s is %s", nread, PATH_ZRAM_STAT,
|
||
|
nread_val);
|
||
|
tst_resm(TINFO, "%s from %s is %s", nwrite, PATH_ZRAM_STAT,
|
||
|
nwrite_val);
|
||
|
}
|
||
|
|
||
|
static void print_mm_stat(char *orig, char *compr, char *mem, char *zero)
|
||
|
{
|
||
|
char orig_val[BUFSIZ], compr_val[BUFSIZ];
|
||
|
char mem_val[BUFSIZ], zero_val[BUFSIZ];
|
||
|
|
||
|
SAFE_FILE_SCANF(cleanup, PATH_ZRAM_MM_STAT, "%s %s %s %*s %*s %s",
|
||
|
orig_val, compr_val, mem_val, zero_val);
|
||
|
tst_resm(TINFO, "%s from %s is %s", orig, PATH_ZRAM_MM_STAT,
|
||
|
orig_val);
|
||
|
tst_resm(TINFO, "%s from %s is %s", compr, PATH_ZRAM_MM_STAT,
|
||
|
compr_val);
|
||
|
tst_resm(TINFO, "%s from %s is %s", mem, PATH_ZRAM_MM_STAT,
|
||
|
mem_val);
|
||
|
tst_resm(TINFO, "%s from %s is %s", zero, PATH_ZRAM_MM_STAT,
|
||
|
zero_val);
|
||
|
}
|
||
|
|
||
|
static void dump_info(void)
|
||
|
{
|
||
|
print("initstate");
|
||
|
print("disksize");
|
||
|
if (!access(OBSOLETE_ZRAM_FILE, F_OK)) {
|
||
|
print("orig_data_size");
|
||
|
print("compr_data_size");
|
||
|
print("mem_used_total");
|
||
|
print("zero_pages");
|
||
|
print("num_reads");
|
||
|
print("num_writes");
|
||
|
} else {
|
||
|
print_mm_stat("orig_data_size", "compr_data_size",
|
||
|
"mem_used_total", "zero/same_pages");
|
||
|
print_stat("num_reads", "num_writes");
|
||
|
}
|
||
|
}
|