[RFC PATCH 4/6] mm: mempolicy: Add and expose mpol_create

From: Ackerley Tng
Date: Thu Apr 13 2023 - 20:12:17 EST


mpol_create builds a mempolicy based on mode, nmask and maxnode.

mpol_create is exposed for use in memfd_restricted_bind() in a later
patch.

Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
---
include/linux/mempolicy.h | 2 ++
mm/mempolicy.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)

diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 9a2a2dd95432..15facd9de087 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -125,6 +125,8 @@ struct shared_policy {
};

int vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst);
+struct mempolicy *mpol_create(
+ unsigned long mode, const unsigned long __user *nmask, unsigned long maxnode)
void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
int __mpol_set_shared_policy(struct shared_policy *info, struct mempolicy *mpol,
unsigned long pgoff_start, unsigned long npages);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index f3fa5494e4a8..f4fe241c17ff 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -3181,3 +3181,42 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
p += scnprintf(p, buffer + maxlen - p, ":%*pbl",
nodemask_pr_args(&nodes));
}
+
+/**
+ * mpol_create - build mempolicy based on mode, nmask and maxnode
+ * @mode: policy mode, as in MPOL_MODE_FLAGS
+ * @nmask: node mask from userspace
+ * @maxnode: number of valid bits in nmask
+ *
+ * Will allocate a new struct mempolicy that has to be released with
+ * mpol_put. Will also take and release the write lock mmap_lock in current->mm.
+ */
+struct mempolicy *mpol_create(
+ unsigned long mode, const unsigned long __user *nmask, unsigned long maxnode)
+{
+ int err;
+ unsigned short mode_flags;
+ nodemask_t nodes;
+ int lmode = mode;
+ struct mempolicy *mpol;
+
+ err = sanitize_mpol_flags(&lmode, &mode_flags);
+ if (err)
+ return ERR_PTR(err);
+
+ err = get_nodes(&nodes, nmask, maxnode);
+ if (err)
+ return ERR_PTR(err);
+
+ mpol = mpol_new(mode, mode_flags, &nodes);
+ if (IS_ERR(mpol))
+ return mpol;
+
+ err = mpol_init_from_nodemask(mpol, &nodes, true);
+ if (err) {
+ mpol_put(mpol);
+ return ERR_PTR(err);
+ }
+
+ return mpol;
+}
--
2.40.0.634.g4ca3ef3211-goog