/* * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * This test is manually run because it requires an NVRAM device to be * mapped as DAX file system or, at least, to be simulated by a * volatile RAM mapped file system. Also, on AArch64 it requires an * ARMV8.2 CPU which implements the dc CVAP instruction (CPU feature * dcpop) and an OS that makes it available from user space. * * If the test runs on such a host without throwing an exception then * that confirms that NVRAM-backed byte buffers can be allocated, * updated and forced via cache line writeback. */ /* * How to run this test: * * Ideally this test should be run on a x86_64/amd64 or aarch64 host * fitted with an NVRAM memory device. The NVRAM should appear as * /dev/pmem0 or some equivalent DAX file device. The file device * should be mounted at /mnt/pmem with a directory tmp created * directly under that mount point with a+rwx access. * * It is possible to run the test on x86_64 using a volatile RAM * backed device to simulate NVRAM, even though this does not provide * any guarantee of persistence of data across program runs. For the * latter case the following instructions explain how to set up the * simulated NVRAM device. * * https://developers.redhat.com/blog/2016/12/05/configuring-and-using-persistent-memory-rhel-7-3/ * https://nvdimm.wiki.kernel.org/ * TL;DR: add "memmap=1G!4G" to /etc/default/grub, eg. GRUB_CMDLINE_LINUX="memmap=1G!4G" * then ("sudo" may required) * for RHEL(BIOS-based): grub2-mkconfig -o /boot/grub2/grub.cfg * for RHEL(UEFI-based): grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg * for Ubuntu: update-grub2 * finally reboot * after the host been rebooted, a new /dev/pmem{N} device should exist, * naming conversion starts at /dev/pmem0 * * Prepare test directory follow below commands, "sudo" may required * (if ndctl or mkfs.xfs not exist, install ndctl or xfsprogs package first) * (for RHEL8, when call mkfs.xfs, specify the -m reflink=0 option to disable reflink feature) * * ndctl create-namespace -f -e namespace0.0 -m memory -M mem * mkdir /mnt/pmem * mkfs.xfs -f /dev/pmem0; mount -o dax /dev/pmem0 /mnt/pmem/ * mkdir /mnt/pmem/test; chmod a+rwx /mnt/pmem/test * * Now run the test program * * java PmemTest * * or * * make test TEST=jdk/java/nio/MappedByteBuffer/PmemTest.java */ /* @test * @summary Testing NVRAM mapped byte buffer support * @run main/manual PmemTest * @requires (os.family == "linux") * @requires (os.arch == "x86_64") */ /* @test * @summary Testing NVRAM mapped byte buffer support * @run main/manual PmemTest * @requires (os.family == "linux") * @requires ((os.arch == "amd64")|(os.arch == "aarch64")|(os.arch == "ppc64le")) * @ignore The test described here is currently disabled on systems that are not * x64-based and lack an external NVRAM memory device. In order to re-enable the * test, you will need to mount the NVRAM device, which will typically appear as * /dev/pmem0, to the directory /mnt/pmem. Once that is done, you can follow the * instructions above to create a test directory and remove the ignore tag. */ import java.io.File; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.EnumSet; import java.util.List; import jdk.nio.mapmode.ExtendedMapMode; import java.lang.management.ManagementFactory; import java.lang.management.BufferPoolMXBean; public class PmemTest { public static final int K = 1024; public static final int NUM_KBS = 16; public static void main(String[] args) throws Exception { System.out.println("test"); String dir = "/tmp"; // mapSync should fail dir = "/mnt/pmem/test"; // mapSync should work, since fs mount is -o dax Path path = new File(dir, "pmemtest").toPath(); FileChannel fileChannel = (FileChannel) Files .newByteChannel(path, EnumSet.of( StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)); MappedByteBuffer mappedByteBuffer = fileChannel.map(ExtendedMapMode.READ_WRITE_SYNC, 0, NUM_KBS * K); dumpBufferPoolBeans(); // for (int loops = 0; loops < 1000; loops++) { for (int loops = 0; loops < 100; loops++) { int base = K * (loops % NUM_KBS); for (int i = 0; i < K ; i++) { for (int j = 0; j < K ;j++) { testBuffer(mappedByteBuffer, base, (i << 3) + j); commitBuffer(mappedByteBuffer, base); } } } dumpBufferPoolBeans(); } public static void testBuffer(MappedByteBuffer mappedByteBuffer, int base, int start) { for (int k = 0; k < 8; k++) { int idx = (start + k) % K; byte z = mappedByteBuffer.get(base + idx); z++; mappedByteBuffer.put(base + idx, z); } } public static void commitBuffer(MappedByteBuffer mappedByteBuffer, int base) { mappedByteBuffer.force(base, K); } public static void dumpBufferPoolBeans() { List beansList = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); for (BufferPoolMXBean bean : beansList) { System.out.println("BufferPoolMXBean {" + "\n\tname: " + bean.getName() + "\n\tcount: " + bean.getCount() + "\n\ttotalCapacity: " + bean.getTotalCapacity() + "\n\tmemoryUsed: " + bean.getMemoryUsed() + "\n}"); } } }