From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B767E41DEE5; Thu, 16 Jul 2026 12:33:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784205192; cv=none; b=kBUYa/6igxtSdVjx5ShZzEJ+hIWyFvN88leSnOq3p/ec2odi7S3ji5CG9xyysUfXscEbMsR8qxPjHV5aFJg9rf/fDdtxMYCqw2U/D7ln4k50UtENJQzvpLWfKYuqYdsRFKRmn7IqaF92gd6NlbHLNW5alJ5z2Emp8XNDqVQMlQc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784205192; c=relaxed/simple; bh=DBJv/0ksG+vCGfmd3BGRAFUPsj0u9YdtLegB9ZTgoP8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FYNFr0+JaJdWjoJEg/NFqFzbf/ULSE+cYf3IrPUS5kEqHfHLvndbklMkBwwPxc+WOWm4651qBqg+vksHs+hruNpUw7AmcqNvfe96eU6nTOChTNlSw86qqSyvw/J65z2A7g+6O6ICTTashrhNmBpSR5JYOL5SBrEikrbMyH2v+BU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=NnjrMzY6; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="NnjrMzY6" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B98CA1691; Thu, 16 Jul 2026 05:33:05 -0700 (PDT) Received: from a081061.blr.arm.com (a081061.arm.com [10.164.19.84]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8FC6B3F7B4; Thu, 16 Jul 2026 05:33:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1784205189; bh=DBJv/0ksG+vCGfmd3BGRAFUPsj0u9YdtLegB9ZTgoP8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NnjrMzY6XcFv8CCluji1WTRp19GQ1fDhykXaujz++4nzPjc1kjBX18NxaFWP720a5 6918geC/hVmFMUouXfzZ/E4iqIBkCSyv1TRATPoImry7k7iqbDqfiALubj6mSIj7T8 /RMthXI2OqZo0YnW1AvZLUEpqVXtVkk/yZRnHqrU= From: Sarthak Sharma To: Andrew Morton , David Hildenbrand Cc: Lorenzo Stoakes , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Shuah Khan , Shuah Khan , Jason Gunthorpe , John Hubbard , Peter Xu , Leon Romanovsky , Zi Yan , Baolin Wang , Nico Pache , Ryan Roberts , Dev Jain , Barry Song , Lance Yang , Jonathan Corbet , Mark Brown , Anshuman Khandual , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Sarthak Sharma Subject: [PATCH v5 2/5] tools/lib/mm: add shared file helpers Date: Thu, 16 Jul 2026 18:02:23 +0530 Message-ID: <20260716123226.197736-3-sarthak.sharma@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260716123226.197736-1-sarthak.sharma@arm.com> References: <20260716123226.197736-1-sarthak.sharma@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Move read_file(), write_file(), read_num(), and write_num() 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. Signed-off-by: Sarthak Sharma --- MAINTAINERS | 1 + tools/lib/mm/file_utils.c | 119 +++++++++++++++++++++++++++ tools/lib/mm/file_utils.h | 12 +++ tools/testing/selftests/mm/Makefile | 11 +-- tools/testing/selftests/mm/vm_util.c | 109 ------------------------ tools/testing/selftests/mm/vm_util.h | 6 +- 6 files changed, 139 insertions(+), 119 deletions(-) create mode 100644 tools/lib/mm/file_utils.c create mode 100644 tools/lib/mm/file_utils.h diff --git a/MAINTAINERS b/MAINTAINERS index 806bd2d80d15..26b06d80ab45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17128,6 +17128,7 @@ F: mm/memory-tiers.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 diff --git a/tools/lib/mm/file_utils.c b/tools/lib/mm/file_utils.c new file mode 100644 index 000000000000..792f4b4db625 --- /dev/null +++ b/tools/lib/mm/file_utils.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +#include "file_utils.h" + +int read_file(const char *path, char *buf, size_t buflen) +{ + int fd; + ssize_t numread; + + fd = open(path, O_RDONLY); + if (fd == -1) { + int err = errno; + + printf("# %s: %s (%d)\n", path, strerror(err), err); + return -err; + } + + numread = read(fd, buf, buflen - 1); + if (numread < 1) { + int err = numread ? errno : ENODATA; + + close(fd); + printf("# %s: %s (%d)\n", path, strerror(err), err); + return -err; + } + + buf[numread] = '\0'; + close(fd); + + return (int)numread; +} + +int write_file(const char *path, const char *buf, size_t buflen) +{ + int fd, saved_errno; + ssize_t numwritten; + + if (buflen < 2) { + printf("# %s: %s (%d)\n", path, strerror(EINVAL), EINVAL); + return -EINVAL; + } + + fd = open(path, O_WRONLY); + if (fd == -1) { + int err = errno; + + printf("# %s: %s (%d)\n", path, strerror(err), err); + return -err; + } + + numwritten = write(fd, buf, buflen - 1); + saved_errno = errno; + close(fd); + if (numwritten < 0) { + printf("# %s: %s (%d)\n", path, strerror(saved_errno), + saved_errno); + return -saved_errno; + } + if (numwritten != (ssize_t)(buflen - 1)) { + printf("# %s write(%.*s) is truncated, expected %zu bytes, got %zd bytes\n", + path, (int)(buflen - 1), buf, buflen - 1, numwritten); + return -EIO; + } + + return 0; +} + +int read_num(const char *path, unsigned long *num) +{ + unsigned long val; + int err, ret; + char buf[21]; + char *end; + + if (!num) + return -EINVAL; + + ret = read_file(path, buf, sizeof(buf)); + if (ret < 0) + return ret; + + errno = 0; + val = strtoul(buf, &end, 10); + if (errno) { + err = errno; + printf("# %s: %s (%d)\n", path, strerror(err), err); + return -err; + } + + if (end == buf || buf[0] == '-') { + printf("# %s: invalid numeric value\n", path); + return -EINVAL; + } + + if (*end == '\n') + end++; + + if (*end != '\0') { + printf("# %s: invalid numeric value\n", path); + return -EINVAL; + } + + *num = val; + return 0; +} + +int write_num(const char *path, unsigned long num) +{ + char buf[21]; + + snprintf(buf, sizeof(buf), "%lu", num); + return write_file(path, buf, strlen(buf) + 1); +} diff --git a/tools/lib/mm/file_utils.h b/tools/lib/mm/file_utils.h new file mode 100644 index 000000000000..38576790a342 --- /dev/null +++ b/tools/lib/mm/file_utils.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __MM_FILE_UTILS_H__ +#define __MM_FILE_UTILS_H__ + +#include + +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); + +#endif diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index e6df968f0971..70d6a9ccf9c9 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -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 @@ -187,8 +188,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 @@ -217,7 +218,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 @@ -226,7 +227,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 diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c index bfe0efbe517e..f276eee57680 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -698,115 +698,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; - ssize_t numread; - - fd = open(path, O_RDONLY); - if (fd == -1) { - int err = errno; - - printf("# %s: %s (%d)\n", path, strerror(err), err); - return -err; - } - - numread = read(fd, buf, buflen - 1); - if (numread < 1) { - int err = numread ? errno : ENODATA; - close(fd); - printf("# %s: %s (%d)\n", path, strerror(err), err); - return -err; - } - - buf[numread] = '\0'; - close(fd); - - return (int)numread; -} - -int write_file(const char *path, const char *buf, size_t buflen) -{ - int fd, saved_errno; - ssize_t numwritten; - - if (buflen < 2) { - printf("# %s: %s (%d)\n", path, strerror(EINVAL), EINVAL); - return -EINVAL; - } - - fd = open(path, O_WRONLY); - if (fd == -1) { - int err = errno; - - printf("# %s: %s (%d)\n", path, strerror(err), err); - return -err; - } - - numwritten = write(fd, buf, buflen - 1); - saved_errno = errno; - close(fd); - if (numwritten < 0) { - printf("# %s: %s (%d)\n", path, strerror(saved_errno), saved_errno); - return -saved_errno; - } - - if (numwritten != (ssize_t)(buflen - 1)) { - printf("# %s write(%.*s) is truncated, expected %zu bytes, got %zd bytes\n", - path, (int)(buflen - 1), buf, buflen - 1, numwritten); - return -EIO; - } - - return 0; -} - -int read_num(const char *path, unsigned long *num) -{ - unsigned long val; - int err, ret; - char buf[21]; - char *end; - - if (!num) - return -EINVAL; - - ret = read_file(path, buf, sizeof(buf)); - if (ret < 0) - return ret; - - errno = 0; - val = strtoul(buf, &end, 10); - if (errno) { - err = errno; - printf("# %s: %s (%d)\n", path, strerror(err), err); - return -err; - } - - if (end == buf || buf[0] == '-') { - printf("# %s: invalid numeric value\n", path); - return -EINVAL; - } - - if (*end == '\n') - end++; - - if (*end != '\0') { - printf("# %s: invalid numeric value\n", path); - 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); -} - static unsigned long shmall, shmmax; void __shm_limits_restore(void) diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h index 28c3d7c1faed..d45135283732 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -8,6 +8,7 @@ #include /* _SC_PAGESIZE */ #include "kselftest.h" #include +#include #define BIT_ULL(nr) (1ULL << (nr)) #define PM_SOFT_DIRTY BIT_ULL(55) @@ -164,11 +165,6 @@ int unpoison_memory(unsigned long pfn); #define PAGEMAP_PRESENT(ent) (((ent) & (1ull << 63)) != 0) #define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1)) -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); - void shm_limits_prepare(unsigned long length); void __shm_limits_restore(void); -- 2.39.5