*/
#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <getopt.h>
#include <pagemap/pagemap.h>
};
struct ksm_page {
+ uint64_t count;
uint32_t hash;
struct vaddr *vaddr;
size_t vaddr_len, vaddr_size;
static int read_pages(struct ksm_pages *kp, pm_map_t **maps, size_t num_maps, uint8_t pr_flags) {
size_t i, j, k;
- size_t len;
uint64_t *pagemap;
size_t map_len;
uint64_t flags;
continue;
}
for (j = 0; j < map_len; j++) {
- error = pm_kernel_flags(ker, pagemap[j], &flags);
+ error = pm_kernel_flags(ker, PM_PAGEMAP_PFN(pagemap[j]), &flags);
if (error) {
- fprintf(stderr, "warning: could not read flags for pfn at address 0x%016llx\n",
+ fprintf(stderr, "warning: could not read flags for pfn at address 0x%016" PRIx64 "\n",
pagemap[i]);
continue;
}
- if (!(flags & PM_PAGE_KSM)) {
+ if (!(flags & KPF_KSM)) {
continue;
}
vaddr = pm_map_start(maps[i]) + j * pm_kernel_pagesize(ker);
fprintf(stderr, "warning: could not lseek to 0x%08lx\n", vaddr);
continue;
}
- len = read(fd, data, pm_kernel_pagesize(ker));
+ ssize_t len = read(fd, data, pm_kernel_pagesize(ker));
if (len != pm_kernel_pagesize(ker)) {
fprintf(stderr, "warning: could not read page at 0x%08lx\n", vaddr);
continue;
kp->pages = tmp;
kp->size += GROWTH_FACTOR;
}
+ rc = pm_kernel_count(ker, PM_PAGEMAP_PFN(pagemap[j]), &kp->pages[kp->len].count);
+ if (rc) {
+ fprintf(stderr, "error reading page count\n");
+ free(pagemap);
+ goto err_count;
+ }
kp->pages[kp->len].hash = hash;
kp->pages[kp->len].pattern =
is_pattern((uint8_t *)data, pm_kernel_pagesize(ker)) ?
goto no_err;
err_realloc:
+err_count:
if (pr_flags & PR_VERBOSE) {
for (i = 0; i < kp->len; i++) {
free(kp->pages[i].vaddr);
} else {
printf("KSM CRC 0x%08x:", kp->pages[i].hash);
}
- printf(" %4d page", kp->pages[i].vaddr_count);
+ printf(" %4zu page", kp->pages[i].vaddr_count);
if (kp->pages[i].vaddr_count > 1) {
printf("s");
}
+ if (!(pr_flags & PR_ALL)) {
+ printf(" (%" PRIu64 " reference", kp->pages[i].count);
+ if (kp->pages[i].count > 1) {
+ printf("s");
+ }
+ printf(")");
+ }
printf("\n");
if (pr_flags & PR_VERBOSE) {
for (k = 0; k < 8 && j < kp->pages[i].vaddr_len; k++, j++) {
printf(" 0x%08lx", kp->pages[i].vaddr[j].addr);
- index = snprintf(suffix, sizeof(suffix), ":%d",
+ index = snprintf(suffix, sizeof(suffix), ":%zu",
kp->pages[i].vaddr[j].num_pages);
if (pr_flags & PR_ALL) {
index += snprintf(suffix + index, sizeof(suffix) - index, "[%d]",
static int cmp_pages(const void *a, const void *b) {
const struct ksm_page *pg_a = a;
const struct ksm_page *pg_b = b;
+ int cmp = pg_b->vaddr_count - pg_a->vaddr_count;
- return pg_b->vaddr_count - pg_a->vaddr_count;
+ return cmp ? cmp : pg_b->count - pg_a->count;
}
static bool is_pattern(uint8_t *data, size_t len) {
return -1;
}
- if (asprintf(&filename, "/proc/%zd/cmdline", pid) < 0) {
+ if (asprintf(&filename, "/proc/%d/cmdline", (int)pid) < 0) {
rc = 1;
goto exit;
}
return rc;
}
-