[PATCH] String conversions for memory policy

From: Christoph Lameter
Date: Fri Jul 29 2005 - 13:41:36 EST


This patch adds two new functions to mm/mempolicy.c that allow the conversion
of a memorypolicy to a textual representation and vice versa.

The patch provides necessary functions for the merging of numa_maps into
smap.

Signed-off-by: Christoph Lameter <christoph@xxxxxxxxxxx>

Index: linux-2.6.13-rc3-mm3/mm/mempolicy.c
===================================================================
--- linux-2.6.13-rc3-mm3.orig/mm/mempolicy.c 2005-07-29 10:37:26.000000000 -0700
+++ linux-2.6.13-rc3-mm3/mm/mempolicy.c 2005-07-29 11:08:13.000000000 -0700
@@ -1170,3 +1170,214 @@
{
sys_set_mempolicy(MPOL_DEFAULT, NULL, 0);
}
+
+/*
+ * Convert a mempolicy into a string.
+ * Returns the number of characters in buffer (if positive)
+ * or an error (negative)
+ */
+int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
+{
+ char *p = buffer;
+ char *e = buffer + maxlen;
+ int first = 1;
+ int node;
+ struct zone **z;
+
+ if (!pol || pol->policy == MPOL_DEFAULT) {
+ strcpy(buffer,"default");
+ return 7;
+ }
+
+ if (pol->policy == MPOL_PREFERRED) {
+ if (e < p + 8 /* fixed string size */ + 4 /* max len of node number */)
+ return -ENOSPC;
+
+ sprintf(p, "prefer=%d", pol->v.preferred_node);
+ return strlen(buffer);
+
+ } else if (pol->policy == MPOL_BIND) {
+
+ if (e < p + 9 + 4)
+ return -ENOSPC;
+
+ p+= sprintf(p, "bind={");
+
+ for (z = pol->v.zonelist->zones; *z ; *z++) {
+ if (!first)
+ *p++ = ',';
+ else
+ first = 0;
+ if (e < p + 2 + 4 + strlen((*z)->name))
+ return -ENOSPC;
+ p += sprintf(p, "%d/%s", (*z)->zone_pgdat->node_id, (*z)->name);
+ }
+
+ *p++ = '}';
+ *p++ = 0;
+ return p-buffer;
+
+ } else if (pol->policy == MPOL_INTERLEAVE) {
+
+ if (e < p + 14 + 4)
+ return -ENOSPC;
+
+ p += sprintf(p, "interleave={");
+
+ for_each_node(node)
+ if (test_bit(node, pol->v.nodes)) {
+ if (!first)
+ *p++ = ',';
+ else
+ first = 0;
+ if (e < p + 2 /* min bytes that follow */ + 4 /* node number */)
+ return -ENOSPC;
+ p += sprintf(p, "%d", node);
+ }
+
+ *p++ = '}';
+ *p++ = 0;
+ return p-buffer;
+ }
+ BUG();
+ return -EFAULT;
+}
+
+/*
+ * Convert a representation of a memory policy from text
+ * form to binary.
+ *
+ * Returns either a memory policy or NULL for error.
+ */
+struct mempolicy *str_to_mpol(char *buffer, char **end)
+{
+ char *p;
+ struct mempolicy *pol;
+ int node;
+ size_t size;
+
+ if (strnicmp(buffer, "default", 7) == 0) {
+
+ *end = buffer + 7;
+ return &default_policy;
+
+ }
+
+ pol = __mpol_copy(&default_policy);
+ if (IS_ERR(pol))
+ return NULL;
+
+ if (strnicmp(buffer, "prefer=", 7) == 0) {
+
+ node = simple_strtoul(buffer + 7, &p, 10);
+ if (node >= MAX_NUMNODES || !node_online(node))
+ goto out;
+
+ pol->policy = MPOL_PREFERRED;
+ pol->v.preferred_node = node;
+
+ } else if (strnicmp(buffer, "interleave={", 12) == 0) {
+
+ pol->policy = MPOL_INTERLEAVE;
+ p = buffer + 12;
+ bitmap_zero(pol->v.nodes, MAX_NUMNODES);
+
+ do {
+ node = simple_strtoul(p, &p, 10);
+
+ /* Check here for cpuset restrictions on nodes */
+ if (node >= MAX_NUMNODES || !node_online(node))
+ goto out;
+ set_bit(node, pol->v.nodes);
+
+ } while (*p++ == ',');
+
+ if (p[-1] != '}' || bitmap_empty(pol->v.nodes, MAX_NUMNODES))
+ goto out;
+
+ } else if (strnicmp(buffer, "bind={", 6) == 0) {
+
+ struct zonelist *zonelist = kmalloc(sizeof(struct zonelist), GFP_KERNEL);
+ struct zone **z = zonelist->zones;
+ struct zonelist *new;
+
+ pol->policy = MPOL_BIND;
+ p = buffer + 6;
+
+ do {
+ pg_data_t *pgdat;
+ struct zone *zone = NULL;
+
+ node = simple_strtoul(p, &p, 10);
+
+ /* Try to find the pgdat for the specified node */
+ for_each_pgdat(pgdat) {
+ if (pgdat->node_id == node) {
+ zone = pgdat->node_zones;
+ break;
+ }
+ }
+ if (!zone || node >= MAX_NUMNODES || !node_online(node))
+ goto bind_out;
+
+ /*
+ * If there is no zone specified then take the first
+ * zone. Otherwise we need to look for a matching name
+ */
+ if (*p == '/') {
+ char *start = ++p;
+ struct zone *q;
+ struct zone *found = NULL;
+
+ /* Find end of the zone name */
+ while (*p && *p != ',' && *p != '}')
+ p++;
+
+ if (start == p)
+ goto bind_out;
+ /*
+ * Go through the zones in this node and check
+ * if any have the name we are looking for
+ */
+ for(q = zone; q < zone + MAX_NR_ZONES; q++) {
+ if (strnicmp(q->name, start, p-start) == 0) {
+ found = q;
+ break;
+ }
+ }
+ zone = found;
+ }
+
+ if (!zone || z > zonelist->zones + MAX_NUMNODES * MAX_NR_ZONES)
+ goto bind_out;
+ *z++ = zone;
+
+ } while (*p++ == ',');
+
+ if (p[-1] != '}') {
+bind_out:
+ kfree(zonelist);
+ goto out;
+ }
+
+ /* Allocate only the necessary elements */
+ *z++ = NULL;
+ size = (z - zonelist->zones) * sizeof(struct zonelist *);
+ new = kmalloc(size, GFP_KERNEL);
+ if (!new)
+ goto out;
+ memcpy(new, zonelist, size);
+ kfree(zonelist);
+
+ pol->v.zonelist = new;
+
+ } else {
+out:
+ __mpol_free(pol);
+ return NULL;
+ }
+
+ *end = p;
+ return pol;
+}
+
Index: linux-2.6.13-rc3-mm3/include/linux/mempolicy.h
===================================================================
--- linux-2.6.13-rc3-mm3.orig/include/linux/mempolicy.h 2005-07-29 10:37:26.000000000 -0700
+++ linux-2.6.13-rc3-mm3/include/linux/mempolicy.h 2005-07-29 11:08:13.000000000 -0700
@@ -157,6 +157,10 @@
extern void numa_policy_init(void);
extern struct mempolicy default_policy;

+/* Conversion functions */
+int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol);
+struct mempolicy *str_to_mpol(char *buffer, char **end);
+
#else

struct mempolicy {};
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/