{"id":20730,"url":"https://patchwork.libcamera.org/api/patches/20730/?format=json","web_url":"https://patchwork.libcamera.org/patch/20730/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20240731135936.2105-2-laurent.pinchart@ideasonboard.com>","date":"2024-07-31T13:59:33","name":"[v2,1/4] libcamera: base: Add MemFd helper class","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"a3c770fe5090bfd17287973367edd01d2503d3c1","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/20730/mbox/","series":[{"id":4470,"url":"https://patchwork.libcamera.org/api/series/4470/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=4470","date":"2024-07-31T13:59:32","name":"libcamera: Address soft ISP file seal TODO item","version":2,"mbox":"https://patchwork.libcamera.org/series/4470/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/20730/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/20730/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A9FF0C32BB\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 31 Jul 2024 14:00:02 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3658E63379;\n\tWed, 31 Jul 2024 16:00:02 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 713BB6198E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 31 Jul 2024 15:59:59 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5B86DF85\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 31 Jul 2024 15:59:11 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"iZH+jKzO\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1722434351;\n\tbh=eqHwR1evMb7EhKijHWNnlouTO3Bknq5MaVJwRTQNs04=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=iZH+jKzOlUjZNNH3APtdV9DHUI8Z9ZLpC6odr430uih4Z1zXpgc5wjT/daujBJ8E8\n\temv+TQcYaaWe1X0ow1RxcwUh9j1xV+G+4C5ebOweqSFOXddEp0GxxbyVGuU8otlCEZ\n\ttbG49HJVm6ovGSwhurg/9d/3Mk7xMr48/z7LkUto=","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Subject":"[PATCH v2 1/4] libcamera: base: Add MemFd helper class","Date":"Wed, 31 Jul 2024 16:59:33 +0300","Message-ID":"<20240731135936.2105-2-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.44.2","In-Reply-To":"<20240731135936.2105-1-laurent.pinchart@ideasonboard.com>","References":"<20240731135936.2105-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"libcamera creates memfds in two locations already, duplicating some\ncode. Move the code to a new MemFd helper class.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nReviewed-by: Milan Zamazal <mzamazal@redhat.com>\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n---\n include/libcamera/base/memfd.h      |  34 ++++++++\n include/libcamera/base/meson.build  |   1 +\n src/libcamera/base/memfd.cpp        | 116 ++++++++++++++++++++++++++++\n src/libcamera/base/meson.build      |   1 +\n src/libcamera/dma_buf_allocator.cpp |  46 +----------\n src/libcamera/shared_mem_object.cpp |  21 ++---\n 6 files changed, 161 insertions(+), 58 deletions(-)\n create mode 100644 include/libcamera/base/memfd.h\n create mode 100644 src/libcamera/base/memfd.cpp","diff":"diff --git a/include/libcamera/base/memfd.h b/include/libcamera/base/memfd.h\nnew file mode 100644\nindex 000000000000..b0edd2de5d83\n--- /dev/null\n+++ b/include/libcamera/base/memfd.h\n@@ -0,0 +1,34 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Ideas on Board Oy\n+ *\n+ * Anonymous file creation\n+ */\n+\n+#pragma once\n+\n+#include <stddef.h>\n+\n+#include <libcamera/base/flags.h>\n+#include <libcamera/base/unique_fd.h>\n+\n+namespace libcamera {\n+\n+class MemFd\n+{\n+public:\n+\tenum class Seal {\n+\t\tNone = 0,\n+\t\tShrink = (1 << 0),\n+\t\tGrow = (1 << 1),\n+\t};\n+\n+\tusing Seals = Flags<Seal>;\n+\n+\tstatic UniqueFD create(const char *name, std::size_t size,\n+\t\t\t       Seals seals = Seal::None);\n+};\n+\n+LIBCAMERA_FLAGS_ENABLE_OPERATORS(MemFd::Seal)\n+\n+} /* namespace libcamera */\ndiff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build\nindex bace25d56b13..2a0cee317204 100644\n--- a/include/libcamera/base/meson.build\n+++ b/include/libcamera/base/meson.build\n@@ -21,6 +21,7 @@ libcamera_base_private_headers = files([\n     'event_notifier.h',\n     'file.h',\n     'log.h',\n+    'memfd.h',\n     'message.h',\n     'mutex.h',\n     'private.h',\ndiff --git a/src/libcamera/base/memfd.cpp b/src/libcamera/base/memfd.cpp\nnew file mode 100644\nindex 000000000000..72474307af09\n--- /dev/null\n+++ b/src/libcamera/base/memfd.cpp\n@@ -0,0 +1,116 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Ideas on Board Oy\n+ *\n+ * Anonymous file creation\n+ */\n+\n+#include <libcamera/base/memfd.h>\n+\n+#include <fcntl.h>\n+#include <string.h>\n+#include <sys/mman.h>\n+#include <sys/syscall.h>\n+#include <unistd.h>\n+\n+#include <libcamera/base/log.h>\n+\n+/**\n+ * \\file base/memfd.h\n+ * \\brief Anonymous file creation\n+ */\n+\n+/* uClibc doesn't provide the file sealing API. */\n+#ifndef __DOXYGEN__\n+#if not HAVE_FILE_SEALS\n+#define F_ADD_SEALS\t\t1033\n+#define F_SEAL_SHRINK\t\t0x0002\n+#define F_SEAL_GROW\t\t0x0004\n+#endif\n+#endif\n+\n+namespace libcamera {\n+\n+LOG_DECLARE_CATEGORY(File)\n+\n+/**\n+ * \\class MemFd\n+ * \\brief Helper class to create anonymous files\n+ *\n+ * Anonymous files behave like regular files, and can be modified, truncated,\n+ * memory-mapped and so on. Unlike regular files, they however live in RAM and\n+ * don't have permanent backing storage.\n+ */\n+\n+/**\n+ * \\enum MemFd::Seal\n+ * \\brief Seals for the MemFd::create() function\n+ * \\var MemFd::Seal::None\n+ * \\brief No seals (used as default value)\n+ * \\var MemFd::Seal::Shrink\n+ * \\brief Prevent the memfd from shrinking\n+ * \\var MemFd::Seal::Grow\n+ * \\brief Prevent the memfd from growing\n+ */\n+\n+/**\n+ * \\typedef MemFd::Seals\n+ * \\brief A bitwise combination of MemFd::Seal values\n+ */\n+\n+/**\n+ * \\brief Create an anonymous file\n+ * \\param[in] name The file name (displayed in symbolic links in /proc/self/fd/)\n+ * \\param[in] size The file size\n+ * \\param[in] seals The file seals\n+ *\n+ * This function is a helper that wraps anonymous file (memfd) creation and\n+ * sets the file size and optional seals.\n+ *\n+ * \\return The descriptor of the anonymous file if creation succeeded, or an\n+ * invalid UniqueFD otherwise\n+ */\n+UniqueFD MemFd::create(const char *name, std::size_t size, Seals seals)\n+{\n+#if HAVE_MEMFD_CREATE\n+\tint ret = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);\n+#else\n+\tint ret = syscall(SYS_memfd_create, name, MFD_ALLOW_SEALING | MFD_CLOEXEC);\n+#endif\n+\tif (ret < 0) {\n+\t\tret = errno;\n+\t\tLOG(File, Error)\n+\t\t\t<< \"Failed to allocate memfd storage for \" << name\n+\t\t\t<< \": \" << strerror(ret);\n+\t\treturn {};\n+\t}\n+\n+\tUniqueFD memfd(ret);\n+\n+\tret = ftruncate(memfd.get(), size);\n+\tif (ret < 0) {\n+\t\tret = errno;\n+\t\tLOG(File, Error)\n+\t\t\t<< \"Failed to set memfd size for \" << name\n+\t\t\t<< \": \" << strerror(ret);\n+\t\treturn {};\n+\t}\n+\n+\tif (seals) {\n+\t\tint fileSeals = (seals & Seal::Shrink ? F_SEAL_SHRINK : 0)\n+\t\t\t      | (seals & Seal::Grow ? F_SEAL_GROW : 0);\n+\n+\t\tret = fcntl(memfd.get(), F_ADD_SEALS, fileSeals);\n+\t\tif (ret < 0) {\n+\t\t\tret = errno;\n+\t\t\tLOG(File, Error)\n+\t\t\t\t<< \"Failed to seal the memfd for \" << name\n+\t\t\t\t<< \": \" << strerror(ret);\n+\t\t\treturn {};\n+\t\t}\n+\t}\n+\n+\treturn memfd;\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build\nindex 7a7fd7e4ca87..4a228d335ba4 100644\n--- a/src/libcamera/base/meson.build\n+++ b/src/libcamera/base/meson.build\n@@ -10,6 +10,7 @@ libcamera_base_sources = files([\n     'file.cpp',\n     'flags.cpp',\n     'log.cpp',\n+    'memfd.cpp',\n     'message.cpp',\n     'mutex.cpp',\n     'object.cpp',\ndiff --git a/src/libcamera/dma_buf_allocator.cpp b/src/libcamera/dma_buf_allocator.cpp\nindex c06eca7d04ec..be6efb89fbb7 100644\n--- a/src/libcamera/dma_buf_allocator.cpp\n+++ b/src/libcamera/dma_buf_allocator.cpp\n@@ -13,7 +13,6 @@\n #include <sys/ioctl.h>\n #include <sys/mman.h>\n #include <sys/stat.h>\n-#include <sys/syscall.h>\n #include <sys/types.h>\n #include <unistd.h>\n \n@@ -22,6 +21,7 @@\n #include <linux/udmabuf.h>\n \n #include <libcamera/base/log.h>\n+#include <libcamera/base/memfd.h>\n \n /**\n  * \\file dma_buf_allocator.cpp\n@@ -126,54 +126,16 @@ DmaBufAllocator::~DmaBufAllocator() = default;\n  * \\brief Check if the DmaBufAllocator instance is valid\n  * \\return True if the DmaBufAllocator is valid, false otherwise\n  */\n-\n-/* uClibc doesn't provide the file sealing API. */\n-#ifndef __DOXYGEN__\n-#if not HAVE_FILE_SEALS\n-#define F_ADD_SEALS\t\t1033\n-#define F_SEAL_SHRINK\t\t0x0002\n-#endif\n-#endif\n-\n UniqueFD DmaBufAllocator::allocFromUDmaBuf(const char *name, std::size_t size)\n {\n \t/* Size must be a multiple of the page size. Round it up. */\n \tstd::size_t pageMask = sysconf(_SC_PAGESIZE) - 1;\n \tsize = (size + pageMask) & ~pageMask;\n \n-#if HAVE_MEMFD_CREATE\n-\tint ret = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);\n-#else\n-\tint ret = syscall(SYS_memfd_create, name, MFD_ALLOW_SEALING | MFD_CLOEXEC);\n-#endif\n-\tif (ret < 0) {\n-\t\tret = errno;\n-\t\tLOG(DmaBufAllocator, Error)\n-\t\t\t<< \"Failed to allocate memfd storage for \" << name\n-\t\t\t<< \": \" << strerror(ret);\n-\t\treturn {};\n-\t}\n-\n-\tUniqueFD memfd(ret);\n-\n-\tret = ftruncate(memfd.get(), size);\n-\tif (ret < 0) {\n-\t\tret = errno;\n-\t\tLOG(DmaBufAllocator, Error)\n-\t\t\t<< \"Failed to set memfd size for \" << name\n-\t\t\t<< \": \" << strerror(ret);\n-\t\treturn {};\n-\t}\n-\n \t/* udmabuf dma-buffers *must* have the F_SEAL_SHRINK seal. */\n-\tret = fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_SHRINK);\n-\tif (ret < 0) {\n-\t\tret = errno;\n-\t\tLOG(DmaBufAllocator, Error)\n-\t\t\t<< \"Failed to seal the memfd for \" << name\n-\t\t\t<< \": \" << strerror(ret);\n+\tUniqueFD memfd = MemFd::create(name, size, MemFd::Seal::Shrink);\n+\tif (!memfd.isValid())\n \t\treturn {};\n-\t}\n \n \tstruct udmabuf_create create;\n \n@@ -182,7 +144,7 @@ UniqueFD DmaBufAllocator::allocFromUDmaBuf(const char *name, std::size_t size)\n \tcreate.offset = 0;\n \tcreate.size = size;\n \n-\tret = ::ioctl(providerHandle_.get(), UDMABUF_CREATE, &create);\n+\tint ret = ::ioctl(providerHandle_.get(), UDMABUF_CREATE, &create);\n \tif (ret < 0) {\n \t\tret = errno;\n \t\tLOG(DmaBufAllocator, Error)\ndiff --git a/src/libcamera/shared_mem_object.cpp b/src/libcamera/shared_mem_object.cpp\nindex 809fbdaf95de..022645e71a35 100644\n--- a/src/libcamera/shared_mem_object.cpp\n+++ b/src/libcamera/shared_mem_object.cpp\n@@ -13,9 +13,9 @@\n #include <stddef.h>\n #include <stdint.h>\n #include <sys/mman.h>\n-#include <sys/syscall.h>\n #include <sys/types.h>\n-#include <unistd.h>\n+\n+#include <libcamera/base/memfd.h>\n \n /**\n  * \\file shared_mem_object.cpp\n@@ -58,22 +58,11 @@ SharedMem::SharedMem() = default;\n  */\n SharedMem::SharedMem(const std::string &name, std::size_t size)\n {\n-#if HAVE_MEMFD_CREATE\n-\tint fd = memfd_create(name.c_str(), MFD_CLOEXEC);\n-#else\n-\tint fd = syscall(SYS_memfd_create, name.c_str(), MFD_CLOEXEC);\n-#endif\n-\tif (fd < 0)\n+\tUniqueFD memfd = MemFd::create(name.c_str(), size);\n+\tif (!memfd.isValid())\n \t\treturn;\n \n-\tfd_ = SharedFD(std::move(fd));\n-\tif (!fd_.isValid())\n-\t\treturn;\n-\n-\tif (ftruncate(fd_.get(), size) < 0) {\n-\t\tfd_ = SharedFD();\n-\t\treturn;\n-\t}\n+\tfd_ = SharedFD(std::move(memfd));\n \n \tvoid *mem = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED,\n \t\t\t fd_.get(), 0);\n","prefixes":["v2","1/4"]}