mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
tools/lib/mm: add shared file helpers
Move read_file(), write_file(), read_num(), write_num() and write_num_ignore_einval() out of tools/testing/selftests/mm/vm_util.c into a new shared helper under tools/lib/mm/. These helpers are used by mm selftests today and will also be needed by shared hugepage helpers in subsequent patches. Move them to a generic location so they can be reused outside selftests as well. Keep the helpers exposed to mm selftests through vm_util.h by including the new shared header there, and link the new helper into the selftests/mm build. Update the explicit x86 protection_keys 32-bit and 64-bit build rules to preserve prerequisite paths, now that file_utils.c is built from tools/lib/mm. Add tools/lib/mm/ to the MEMORY MANAGEMENT - MISC entry in MAINTAINERS. Link: https://lore.kernel.org/20260918112234.195857-3-sarthak.sharma@arm.com Signed-off-by: Sarthak Sharma <sarthak.sharma@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Tested-by: Muhammad Usama Anjum <usama.anjum@arm.com> Cc: Anshuman Khandual <anshuman.khandual@arm.com> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Barry Song <baohua@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: John Hubbard <jhubbard@nvidia.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Lance Yang <lance.yang@linux.dev> Cc: Leon Romanovsky <leon@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Mark Brown <broonie@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Nico Pache <npache@redhat.com> Cc: Peter Xu <peterx@redhat.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Zi Yan <ziy@nvidia.com>
This commit is contained in:
parent
23d0a7444f
commit
1d59dd1383
|
|
@ -17290,6 +17290,7 @@ F: mm/mapping_dirty_helpers.c
|
|||
F: mm/page_idle.c
|
||||
F: mm/pgalloc-track.h
|
||||
F: mm/process_vm_access.c
|
||||
F: tools/lib/mm/
|
||||
F: tools/testing/selftests/mm/
|
||||
|
||||
MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION
|
||||
|
|
|
|||
106
tools/lib/mm/file_utils.c
Normal file
106
tools/lib/mm/file_utils.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "file_utils.h"
|
||||
|
||||
int read_file(const char *path, char *buf, size_t buflen)
|
||||
{
|
||||
int fd, err;
|
||||
ssize_t numread;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return -errno;
|
||||
|
||||
numread = read(fd, buf, buflen - 1);
|
||||
if (numread < 1) {
|
||||
err = numread ? errno : ENODATA;
|
||||
close(fd);
|
||||
return -err;
|
||||
}
|
||||
|
||||
buf[numread] = '\0';
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_file(const char *path, const char *buf, size_t buflen)
|
||||
{
|
||||
int fd, saved_errno;
|
||||
ssize_t numwritten;
|
||||
|
||||
if (buflen < 2)
|
||||
return -EINVAL;
|
||||
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd == -1)
|
||||
return -errno;
|
||||
|
||||
numwritten = write(fd, buf, buflen - 1);
|
||||
saved_errno = errno;
|
||||
close(fd);
|
||||
|
||||
if (numwritten < 0)
|
||||
return -saved_errno;
|
||||
|
||||
if (numwritten != (ssize_t)(buflen - 1))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_num(const char *path, unsigned long *num)
|
||||
{
|
||||
unsigned long val;
|
||||
int ret;
|
||||
char buf[21];
|
||||
char *end;
|
||||
|
||||
if (!num)
|
||||
return -EINVAL;
|
||||
|
||||
ret = read_file(path, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reject signs and leading whitespace that are accepted by strtoul() */
|
||||
if (buf[0] < '0' || buf[0] > '9')
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
val = strtoul(buf, &end, 10);
|
||||
if (errno)
|
||||
return -errno;
|
||||
|
||||
/* Only allow a newline after the number */
|
||||
if (*end == '\n')
|
||||
end++;
|
||||
|
||||
if (*end != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
*num = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_num(const char *path, unsigned long num)
|
||||
{
|
||||
char buf[21];
|
||||
|
||||
sprintf(buf, "%lu", num);
|
||||
return write_file(path, buf, strlen(buf) + 1);
|
||||
}
|
||||
|
||||
int write_num_ignore_einval(const char *path, unsigned long num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = write_num(path, num);
|
||||
return ret == -EINVAL ? 0 : ret;
|
||||
}
|
||||
13
tools/lib/mm/file_utils.h
Normal file
13
tools/lib/mm/file_utils.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __MM_FILE_UTILS_H__
|
||||
#define __MM_FILE_UTILS_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
int read_file(const char *path, char *buf, size_t buflen);
|
||||
int write_file(const char *path, const char *buf, size_t buflen);
|
||||
int read_num(const char *path, unsigned long *num);
|
||||
int write_num(const char *path, unsigned long num);
|
||||
int write_num_ignore_einval(const char *path, unsigned long num);
|
||||
|
||||
#endif
|
||||
|
|
@ -37,7 +37,8 @@ endif
|
|||
# LDLIBS.
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
CFLAGS = -Wall -O2 -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES)
|
||||
CFLAGS = -Wall -O2 -I $(top_srcdir) -I $(top_srcdir)/tools/lib
|
||||
CFLAGS += $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES)
|
||||
CFLAGS += -Wunreachable-code
|
||||
LDLIBS = -lrt -lpthread -lm
|
||||
|
||||
|
|
@ -184,8 +185,8 @@ TEST_FILES += write_hugetlb_memory.sh
|
|||
|
||||
include ../lib.mk
|
||||
|
||||
$(TEST_GEN_PROGS): vm_util.c hugepage_settings.c
|
||||
$(TEST_GEN_FILES): vm_util.c hugepage_settings.c
|
||||
$(TEST_GEN_PROGS): vm_util.c hugepage_settings.c $(top_srcdir)/tools/lib/mm/file_utils.c
|
||||
$(TEST_GEN_FILES): vm_util.c hugepage_settings.c $(top_srcdir)/tools/lib/mm/file_utils.c
|
||||
|
||||
$(OUTPUT)/uffd-stress: uffd-common.c
|
||||
$(OUTPUT)/uffd-unit-tests: uffd-common.c
|
||||
|
|
@ -214,7 +215,7 @@ $(BINARIES_32): CFLAGS += -m32 -mxsave
|
|||
$(BINARIES_32): LDLIBS += -lrt -ldl -lm
|
||||
$(BINARIES_32): $(OUTPUT)/%_32: %.c
|
||||
$(call msg,CC,,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
|
||||
$(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $^ $(LDLIBS) -o $@
|
||||
$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-32,$(t))))
|
||||
endif
|
||||
|
||||
|
|
@ -223,7 +224,7 @@ $(BINARIES_64): CFLAGS += -m64 -mxsave
|
|||
$(BINARIES_64): LDLIBS += -lrt -ldl
|
||||
$(BINARIES_64): $(OUTPUT)/%_64: %.c
|
||||
$(call msg,CC,,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
|
||||
$(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $^ $(LDLIBS) -o $@
|
||||
$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-64,$(t))))
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -885,103 +885,6 @@ int unpoison_memory(unsigned long pfn)
|
|||
return ret > 0 ? 0 : -errno;
|
||||
}
|
||||
|
||||
int read_file(const char *path, char *buf, size_t buflen)
|
||||
{
|
||||
int fd, err;
|
||||
ssize_t numread;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return -errno;
|
||||
|
||||
numread = read(fd, buf, buflen - 1);
|
||||
if (numread < 1) {
|
||||
err = numread ? errno : ENODATA;
|
||||
close(fd);
|
||||
return -err;
|
||||
}
|
||||
|
||||
buf[numread] = '\0';
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_file(const char *path, const char *buf, size_t buflen)
|
||||
{
|
||||
int fd, saved_errno;
|
||||
ssize_t numwritten;
|
||||
|
||||
if (buflen < 2)
|
||||
return -EINVAL;
|
||||
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd == -1)
|
||||
return -errno;
|
||||
|
||||
numwritten = write(fd, buf, buflen - 1);
|
||||
saved_errno = errno;
|
||||
close(fd);
|
||||
|
||||
if (numwritten < 0)
|
||||
return -saved_errno;
|
||||
|
||||
if (numwritten != (ssize_t)(buflen - 1))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_num(const char *path, unsigned long *num)
|
||||
{
|
||||
unsigned long val;
|
||||
int ret;
|
||||
char buf[21];
|
||||
char *end;
|
||||
|
||||
if (!num)
|
||||
return -EINVAL;
|
||||
|
||||
ret = read_file(path, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reject signs and leading whitespace that are accepted by strtoul() */
|
||||
if (buf[0] < '0' || buf[0] > '9')
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
val = strtoul(buf, &end, 10);
|
||||
if (errno)
|
||||
return -errno;
|
||||
|
||||
/* Only allow a newline after the number */
|
||||
if (*end == '\n')
|
||||
end++;
|
||||
|
||||
if (*end != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
*num = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_num(const char *path, unsigned long num)
|
||||
{
|
||||
char buf[21];
|
||||
|
||||
sprintf(buf, "%lu", num);
|
||||
return write_file(path, buf, strlen(buf) + 1);
|
||||
}
|
||||
|
||||
int write_num_ignore_einval(const char *path, unsigned long num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = write_num(path, num);
|
||||
return ret == -EINVAL ? 0 : ret;
|
||||
}
|
||||
|
||||
static unsigned long shmall, shmmax;
|
||||
|
||||
void __shm_limits_restore(void)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <unistd.h> /* _SC_PAGESIZE */
|
||||
#include "kselftest.h"
|
||||
#include <linux/fs.h>
|
||||
#include <mm/file_utils.h>
|
||||
|
||||
#define BIT_ULL(nr) (1ULL << (nr))
|
||||
#define PM_SOFT_DIRTY BIT_ULL(55)
|
||||
|
|
@ -166,12 +167,6 @@ int unpoison_memory(unsigned long pfn);
|
|||
#define PAGEMAP_PRESENT(ent) (((ent) & (1ull << 63)) != 0)
|
||||
#define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1))
|
||||
|
||||
int write_file(const char *path, const char *buf, size_t buflen);
|
||||
int read_file(const char *path, char *buf, size_t buflen);
|
||||
int read_num(const char *path, unsigned long *num);
|
||||
int write_num(const char *path, unsigned long num);
|
||||
int write_num_ignore_einval(const char *path, unsigned long num);
|
||||
|
||||
void shm_limits_prepare(unsigned long length);
|
||||
void __shm_limits_restore(void);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user