libpagemap: add pm_map_usage_flags

Add pm_map_usage_flags, which is the same as pm_map_usage but only
counts pages with the specified flags set.  This can be used to
only count "swapbacked" pages, which are pages that cannot be
flushed back to disk without using swap.

Change-Id: I6367555d9385502c797935849bb4221a8354e251
diff --git a/libpagemap/pm_map.c b/libpagemap/pm_map.c
index ef9e2ce..6e3fe7d 100644
--- a/libpagemap/pm_map.c
+++ b/libpagemap/pm_map.c
@@ -27,7 +27,8 @@
                                     pagemap_out, len);
 }
 
-int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out) {
+int pm_map_usage_flags(pm_map_t *map, pm_memusage_t *usage_out,
+                        uint64_t flags_mask, uint64_t required_flags) {
     uint64_t *pagemap;
     size_t len, i;
     uint64_t count;
@@ -49,6 +50,16 @@
             PM_PAGEMAP_SWAPPED(pagemap[i]))
             continue;
 
+        if (flags_mask) {
+            uint64_t flags;
+            error = pm_kernel_flags(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
+                                    &flags);
+            if (error) goto out;
+
+            if ((flags & flags_mask) != required_flags)
+                continue;
+        }
+
         error = pm_kernel_count(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
                                 &count);
         if (error) goto out;
@@ -68,6 +79,10 @@
     return error;
 }
 
+int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out) {
+    return pm_map_usage_flags(map, usage_out, 0, 0);
+}
+
 int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out) {
     uint64_t *pagemap;
     size_t len, i;