Bump Linux kernel to 5.10
This bumps our Linux kernel to 5.10. There's one minor fix in fsinfo accounting for the fact that strings are
now null-terminated. While debugging this I also drive-by fixed a minor typing issue in quotactl.go.
This drops support for the old initramfs loading method (which was the driving force for the EROFS changes)
as refactors in the kernel made the patch we carried until now non-viable. Nothing uses it anymore, everything is
either a microvm-style machine which doesn't use EFI and thus doesn't suffer from the issue or uses EROFS.
Test Plan: No new functionality, should be covered by E2E tests.
X-Origin-Diff: phab/D697
GitOrigin-RevId: d8e40954abb66cb082eecbca372b94a7e40b84a8
diff --git a/third_party/linux/external/0001-fsinfo-Introduce-a-non-repeating-system-unique-super.patch b/third_party/linux/external/0001-fsinfo-Introduce-a-non-repeating-system-unique-super.patch
new file mode 100644
index 0000000..831114e
--- /dev/null
+++ b/third_party/linux/external/0001-fsinfo-Introduce-a-non-repeating-system-unique-super.patch
@@ -0,0 +1,70 @@
+From 2ed1d2a0a5bf09ab741f5c3d6d10021c0702be08 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 5 Jul 2019 11:10:10 +0100
+Subject: [PATCH 1/3] fsinfo: Introduce a non-repeating system-unique
+ superblock ID
+
+Introduce an (effectively) non-repeating system-unique superblock ID that
+can be used to determine that two objects are in the same superblock
+without needing to worry about the ID changing in the meantime (as is
+possible with device IDs).
+
+The counter could also be used to tag other features, such as mount
+objects.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ fs/internal.h | 1 +
+ fs/super.c | 2 ++
+ include/linux/fs.h | 3 +++
+ 3 files changed, 6 insertions(+)
+
+diff --git a/fs/internal.h b/fs/internal.h
+index a7cd0f64faa4a..1b7460f055a3b 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -112,6 +112,7 @@ extern struct file *alloc_empty_file_noaccount(int, const struct cred *);
+ /*
+ * super.c
+ */
++extern atomic64_t vfs_unique_counter;
+ extern int reconfigure_super(struct fs_context *);
+ extern bool trylock_super(struct super_block *sb);
+ extern struct super_block *user_get_super(dev_t);
+diff --git a/fs/super.c b/fs/super.c
+index 98bb0629ee108..31fadb7189d27 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -44,6 +44,7 @@ static int thaw_super_locked(struct super_block *sb);
+
+ static LIST_HEAD(super_blocks);
+ static DEFINE_SPINLOCK(sb_lock);
++atomic64_t vfs_unique_counter; /* Unique identifier counter */
+
+ static char *sb_writers_name[SB_FREEZE_LEVELS] = {
+ "sb_writers",
+@@ -273,6 +274,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
+ goto fail;
+ if (list_lru_init_memcg(&s->s_inode_lru, &s->s_shrink))
+ goto fail;
++ s->s_unique_id = atomic64_inc_return(&vfs_unique_counter);
+ return s;
+
+ fail:
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 8bde32cf97115..e1325dec4fa86 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1547,6 +1547,9 @@ struct super_block {
+
+ spinlock_t s_inode_wblist_lock;
+ struct list_head s_inodes_wb; /* writeback inodes */
++
++ /* Superblock information */
++ u64 s_unique_id;
+ } __randomize_layout;
+
+ /* Helper functions so that in most cases filesystems will
+--
+2.25.1
+
diff --git a/third_party/linux/external/0001-x86-Allow-built-in-command-line-to-work-in-early-ker.patch b/third_party/linux/external/0001-x86-Allow-built-in-command-line-to-work-in-early-ker.patch
deleted file mode 100644
index 6578571..0000000
--- a/third_party/linux/external/0001-x86-Allow-built-in-command-line-to-work-in-early-ker.patch
+++ /dev/null
@@ -1,368 +0,0 @@
-From 12a40099310177c4a494654b592e7f76ec4045f4 Mon Sep 17 00:00:00 2001
-From: Matthew Garrett <mjg59@coreos.com>
-Date: Thu, 9 Apr 2015 13:25:00 -0700
-Subject: [PATCH 1/4] x86: Allow built-in command line to work in early kernel
- init
-
-The kernel supports having a command line built into it. Unfortunately this
-doesn't work in all cases - the built-in command line is only appended
-after we've jumped to the kernel proper, but various parts of the early
-boot process also pay attention to the command line.
-
-This patch moves the command line override code from the kernel itself to
-the early init code. Unfortunately the kernel can be executed by jumping
-to the 16-bit entry point, the UEFI entry point, directly to the 32-bit
-entry point or even to the entry point of the uncompressed image, and
-there is no guarantee that any of these will have access to data held in
-the others. As a result, four copies of the command line will be embedded
-in the kernel.
-
-This patch also defines a new field in boot_params in order to allow the
-earlier entry points to inform the generic setup code that the command line
-has already been appended and so shouldn't be added once more.
-
-Updated for Linux 4.19 by Lorenz Brun <lorenz@nexantic.com>
-Updated for Linux 5.4 by Leopold Schabel <leo@nexantic.com>
-Updated for Linux 5.6 by Lorenz Brun <lorenz@nexantic.com>
-
-Signed-off-by: Matthew Garrett <mjg59@coreos.com>
----
- Documentation/x86/zero-page.rst | 1 +
- arch/x86/boot/boot.h | 10 ++++
- arch/x86/boot/cmdline.c | 37 ++++++++++++++
- arch/x86/boot/compressed/cmdline.c | 10 ++++
- arch/x86/boot/compressed/eboot.c | 3 ++
- arch/x86/boot/compressed/misc.c | 2 +
- arch/x86/boot/compressed/misc.h | 1 +
- arch/x86/boot/main.c | 3 ++
- arch/x86/include/uapi/asm/bootparam.h | 5 +-
- arch/x86/kernel/setup.c | 16 +++---
- .../firmware/efi/libstub/efi-stub-helper.c | 51 +++++++++++++++++--
- 11 files changed, 127 insertions(+), 12 deletions(-)
-
-diff --git a/Documentation/x86/zero-page.rst b/Documentation/x86/zero-page.rst
-index f088f5881666..5339329af8d2 100644
---- a/Documentation/x86/zero-page.rst
-+++ b/Documentation/x86/zero-page.rst
-@@ -16,6 +16,7 @@ Offset/Size Proto Name Meaning
- 000/040 ALL screen_info Text mode or frame buffer information
- (struct screen_info)
- 040/014 ALL apm_bios_info APM BIOS information (struct apm_bios_info)
-+054/004 ALL setup_flags Flags passed from early kernel setup
- 058/008 ALL tboot_addr Physical address of tboot shared page
- 060/010 ALL ist_info Intel SpeedStep (IST) BIOS support information
- (struct ist_info)
-diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
-index ca866f1cca2e..a97502baba73 100644
---- a/arch/x86/boot/boot.h
-+++ b/arch/x86/boot/boot.h
-@@ -269,6 +269,7 @@ void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
- /* cmdline.c */
- int __cmdline_find_option(unsigned long cmdline_ptr, const char *option, char *buffer, int bufsize);
- int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option);
-+int __cmdline_init(unsigned long cmdline_ptr, struct boot_params *params);
- static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
- {
- unsigned long cmd_line_ptr = boot_params.hdr.cmd_line_ptr;
-@@ -289,6 +290,15 @@ static inline int cmdline_find_option_bool(const char *option)
- return __cmdline_find_option_bool(cmd_line_ptr, option);
- }
-
-+static inline int cmdline_init(void)
-+{
-+ unsigned long cmd_line_ptr = boot_params.hdr.cmd_line_ptr;
-+
-+ if (cmd_line_ptr >= 0x100000)
-+ return -1; /* inaccessible */
-+
-+ return __cmdline_init(cmd_line_ptr, &boot_params);
-+}
- /* cpu.c, cpucheck.c */
- int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
- int check_knl_erratum(void);
-diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
-index 4ff01176c1cc..b5dfbe0b3209 100644
---- a/arch/x86/boot/cmdline.c
-+++ b/arch/x86/boot/cmdline.c
-@@ -12,6 +12,10 @@
-
- #include "boot.h"
-
-+#ifdef CONFIG_CMDLINE_BOOL
-+static char builtin_cmdline[] = CONFIG_CMDLINE;
-+#endif
-+
- static inline int myisspace(u8 c)
- {
- return c <= ' '; /* Close enough approximation */
-@@ -154,3 +158,36 @@ int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option)
-
- return 0; /* Buffer overrun */
- }
-+
-+int __cmdline_init(unsigned long cmdline_ptr, struct boot_params *params)
-+{
-+#ifdef CONFIG_CMDLINE_BOOL
-+ addr_t cptr;
-+ int i = 0;
-+
-+ if (!cmdline_ptr)
-+ return -1; /* No command line */
-+
-+ set_fs(cmdline_ptr >> 4);
-+ cptr = cmdline_ptr & 0xf;
-+
-+#ifndef CONFIG_CMDLINE_OVERRIDE
-+ while (cptr < 0x10000) {
-+ char c = rdfs8(cptr);
-+ if (!c) {
-+ wrfs8(' ', cptr++);
-+ break;
-+ }
-+ cptr++;
-+ }
-+#endif /* !CONFIG_CMDLINE_OVERRIDE */
-+ while (builtin_cmdline[i] && cptr < 0xffff)
-+ wrfs8(builtin_cmdline[i++], cptr++);
-+
-+ wrfs8('\0', cptr);
-+
-+ params->setup_flags |= SETUP_CMDLINE_APPENDED;
-+#endif /* CONFIG_CMDLINE_BOOL */
-+
-+ return 0;
-+}
-diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c
-index f1add5d85da9..c69b27a5e76d 100644
---- a/arch/x86/boot/compressed/cmdline.c
-+++ b/arch/x86/boot/compressed/cmdline.c
-@@ -11,6 +11,10 @@ static inline char rdfs8(addr_t addr)
- {
- return *((char *)(fs + addr));
- }
-+static inline void wrfs8(u8 v, addr_t addr)
-+{
-+ *((char *)(fs + addr)) = v;
-+}
- #include "../cmdline.c"
- unsigned long get_cmd_line_ptr(void)
- {
-@@ -28,3 +32,9 @@ int cmdline_find_option_bool(const char *option)
- {
- return __cmdline_find_option_bool(get_cmd_line_ptr(), option);
- }
-+int cmdline_init(void)
-+{
-+ if (!(boot_params->setup_flags & SETUP_CMDLINE_APPENDED))
-+ return __cmdline_init(get_cmd_line_ptr(), boot_params);
-+ return 0;
-+}
-diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
-index 287393d725f0..6854fe44ac2c 100644
---- a/arch/x86/boot/compressed/eboot.c
-+++ b/arch/x86/boot/compressed/eboot.c
-@@ -413,6 +413,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
- /* Fill in upper bits of command line address, NOP on 32 bit */
- boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
-
-+#ifdef CONFIG_CMDLINE_BOOL
-+ boot_params->setup_flags |= SETUP_CMDLINE_APPENDED;
-+#endif
- hdr->ramdisk_image = 0;
- hdr->ramdisk_size = 0;
-
-diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
-index 9652d5c2afda..05fd4372b630 100644
---- a/arch/x86/boot/compressed/misc.c
-+++ b/arch/x86/boot/compressed/misc.c
-@@ -366,6 +366,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
- lines = boot_params->screen_info.orig_video_lines;
- cols = boot_params->screen_info.orig_video_cols;
-
-+ cmdline_init();
-+
- console_init();
-
- /*
-diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
-index c8181392f70d..e2f962e7c0d4 100644
---- a/arch/x86/boot/compressed/misc.h
-+++ b/arch/x86/boot/compressed/misc.h
-@@ -68,6 +68,7 @@ static inline void debug_puthex(const char *s)
- /* cmdline.c */
- int cmdline_find_option(const char *option, char *buffer, int bufsize);
- int cmdline_find_option_bool(const char *option);
-+int cmdline_init(void);
-
- struct mem_vector {
- unsigned long long start;
-diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
-index e3add857c2c9..e20e81253a7d 100644
---- a/arch/x86/boot/main.c
-+++ b/arch/x86/boot/main.c
-@@ -136,6 +136,9 @@ void main(void)
- /* First, copy the boot header into the "zeropage" */
- copy_boot_params();
-
-+ /* Handle built-in command line */
-+ cmdline_init();
-+
- /* Initialize the early-boot console */
- console_init();
- if (cmdline_find_option_bool("debug"))
-diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
-index 8669c6bdbb84..e11a678d4afa 100644
---- a/arch/x86/include/uapi/asm/bootparam.h
-+++ b/arch/x86/include/uapi/asm/bootparam.h
-@@ -37,6 +37,9 @@
- #define XLF_5LEVEL (1<<5)
- #define XLF_5LEVEL_ENABLED (1<<6)
-
-+/* setup_flags */
-+#define SETUP_CMDLINE_APPENDED (1<<0)
-+
- #ifndef __ASSEMBLY__
-
- #include <linux/types.h>
-@@ -175,7 +178,7 @@ struct jailhouse_setup_data {
- struct boot_params {
- struct screen_info screen_info; /* 0x000 */
- struct apm_bios_info apm_bios_info; /* 0x040 */
-- __u8 _pad2[4]; /* 0x054 */
-+ __u32 setup_flags; /* 0x054 */
- __u64 tboot_addr; /* 0x058 */
- struct ist_info ist_info; /* 0x060 */
- __u64 acpi_rsdp_addr; /* 0x070 */
-diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
-index a74262c71484..6dcc6722ca73 100644
---- a/arch/x86/kernel/setup.c
-+++ b/arch/x86/kernel/setup.c
-@@ -903,16 +903,18 @@ void __init setup_arch(char **cmdline_p)
- bss_resource.end = __pa_symbol(__bss_stop)-1;
-
- #ifdef CONFIG_CMDLINE_BOOL
-+ if (!(boot_params.setup_flags & SETUP_CMDLINE_APPENDED)) {
- #ifdef CONFIG_CMDLINE_OVERRIDE
-- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
--#else
-- if (builtin_cmdline[0]) {
-- /* append boot loader cmdline to builtin */
-- strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
-- strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
-- }
-+#else
-+ if (builtin_cmdline[0]) {
-+ /* append boot loader cmdline to builtin */
-+ strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
-+ strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
-+ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
-+ }
- #endif
-+ }
- #endif
-
- strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
-diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
-index 74ddfb496140..5b066819befb 100644
---- a/drivers/firmware/efi/libstub/efi-stub-helper.c
-+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
-@@ -9,9 +9,14 @@
-
- #include <linux/efi.h>
- #include <asm/efi.h>
-+#include <asm/setup.h>
-
- #include "efistub.h"
-
-+#ifdef CONFIG_CMDLINE_BOOL
-+static char builtin_cmdline[] = CONFIG_CMDLINE;
-+#endif
-+
- /*
- * Some firmware implementations have problems reading files in one go.
- * A read chunk size of 1MB seems to work for most platforms.
-@@ -814,6 +819,20 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
- #ifndef MAX_CMDLINE_ADDRESS
- #define MAX_CMDLINE_ADDRESS ULONG_MAX
- #endif
-+static size_t efi_strlcat(char *dest, const char *src, size_t count)
-+{
-+ size_t dsize = strlen(dest);
-+ size_t len = strlen(src);
-+ size_t res = dsize + len;
-+
-+ dest += dsize;
-+ count -= dsize;
-+ if (len >= count)
-+ len = count-1;
-+ memcpy(dest, src, len);
-+ dest[len] = 0;
-+ return res;
-+}
-
- /*
- * Convert the unicode UEFI command line to ASCII to pass to kernel.
-@@ -823,14 +842,16 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
- char *efi_convert_cmdline(efi_loaded_image_t *image,
- int *cmd_line_len)
- {
-+ unsigned long cmdline_addr = 0;
-+ int i;
-+ efi_status_t status;
-+#ifndef CONFIG_CMDLINE_OVERRIDE
- const u16 *s2;
- u8 *s1 = NULL;
-- unsigned long cmdline_addr = 0;
- int load_options_chars = image->load_options_size / 2; /* UTF-16 */
- const u16 *options = image->load_options;
- int options_bytes = 0; /* UTF-8 bytes */
- int options_chars = 0; /* UTF-16 chars */
-- efi_status_t status;
- u16 zero = 0;
-
- if (options) {
-@@ -849,8 +870,13 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
-
- options_bytes++; /* NUL termination */
-
-- status = efi_high_alloc(options_bytes, 0, &cmdline_addr,
-- MAX_CMDLINE_ADDRESS);
-+#ifdef CONFIG_CMDLINE_BOOL
-+ /* Add length of the built-in command line, plus a space */
-+ options_bytes += strlen(builtin_cmdline);
-+ options_bytes++;
-+#endif
-+ status = efi_high_alloc(options_bytes, 0,
-+ &cmdline_addr, MAX_CMDLINE_ADDRESS);
- if (status != EFI_SUCCESS)
- return NULL;
-
-@@ -860,7 +886,24 @@ char *efi_convert_cmdline(efi_loaded_image_t *image,
- s1 = efi_utf16_to_utf8(s1, s2, options_chars);
- *s1 = '\0';
-
-+#ifdef CONFIG_CMDLINE_BOOL
-+ efi_strlcat((char *)cmdline_addr, " ", COMMAND_LINE_SIZE);
-+ efi_strlcat((char *)cmdline_addr, builtin_cmdline, COMMAND_LINE_SIZE);
-+#endif
- *cmd_line_len = options_bytes;
-+#else /* CONFIG_CMDLINE_OVERRIDE */
-+ status = efi_high_alloc(strlen(builtin_cmdline), 0,
-+ &cmdline_addr, MAX_CMDLINE_ADDRESS);
-+ if (status != EFI_SUCCESS)
-+ return NULL;
-+ while (builtin_cmdline[i] && i < COMMAND_LINE_SIZE) {
-+ ((char *)cmdline_addr)[i] = builtin_cmdline[i];
-+ i++;
-+ }
-+ ((char *)cmdline_addr)[i] = '\0';
-+ *cmd_line_len = strlen(builtin_cmdline);
-+#endif /* CONFIG_CMDLINE_OVERRIDE */
-+
- return (char *)cmdline_addr;
- }
-
---
-2.20.1
-
diff --git a/third_party/linux/external/0003-fsinfo-Add-fsinfo-syscall-to-query-filesystem-inform.patch b/third_party/linux/external/0002-fsinfo-Add-fsinfo-syscall-to-query-filesystem-inform.patch
similarity index 88%
rename from third_party/linux/external/0003-fsinfo-Add-fsinfo-syscall-to-query-filesystem-inform.patch
rename to third_party/linux/external/0002-fsinfo-Add-fsinfo-syscall-to-query-filesystem-inform.patch
index 91ae975..7b5147f 100644
--- a/third_party/linux/external/0003-fsinfo-Add-fsinfo-syscall-to-query-filesystem-inform.patch
+++ b/third_party/linux/external/0002-fsinfo-Add-fsinfo-syscall-to-query-filesystem-inform.patch
@@ -1,7 +1,7 @@
-From c91b96ad3f53de22e11d6692d2d8a80ed611a5a5 Mon Sep 17 00:00:00 2001
+From 5837a1c690d51c270c8f04029530f2ce6856739a Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
Date: Fri, 6 Mar 2020 14:59:51 +0000
-Subject: [PATCH 3/4] fsinfo: Add fsinfo() syscall to query filesystem
+Subject: [PATCH 2/3] fsinfo: Add fsinfo() syscall to query filesystem
information
Add a system call to allow filesystem information to be queried. A request
@@ -93,7 +93,7 @@
get the subset they're expecting. If either buffer of result_buf_size are
0, no copy will take place and the data size will be returned.
-Backported for Linux 5.6 by Lorenz Brun <lorenz@nexantic.com>
+Ported to 5.10 by Lorenz Brun <lorenz@nexantic.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-api@vger.kernel.org
@@ -118,196 +118,196 @@
arch/xtensa/kernel/syscalls/syscall.tbl | 1 +
fs/Kconfig | 7 +
fs/Makefile | 1 +
- fs/fsinfo.c | 586 ++++++++++++++++++
+ fs/fsinfo.c | 596 ++++++++++++++++++
include/linux/fs.h | 4 +
- include/linux/fsinfo.h | 73 +++
+ include/linux/fsinfo.h | 74 +++
include/linux/syscalls.h | 4 +
include/uapi/asm-generic/unistd.h | 4 +-
- include/uapi/linux/fsinfo.h | 187 ++++++
+ include/uapi/linux/fsinfo.h | 189 ++++++
kernel/sys_ni.c | 1 +
- samples/vfs/Makefile | 5 +
- samples/vfs/test-fsinfo.c | 633 ++++++++++++++++++++
- 29 files changed, 1523 insertions(+), 2 deletions(-)
+ samples/vfs/Makefile | 2 +-
+ samples/vfs/test-fsinfo.c | 646 ++++++++++++++++++++
+ 29 files changed, 1545 insertions(+), 3 deletions(-)
create mode 100644 fs/fsinfo.c
create mode 100644 include/linux/fsinfo.h
create mode 100644 include/uapi/linux/fsinfo.h
create mode 100644 samples/vfs/test-fsinfo.c
diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
-index 36d42da7466a..59388edc444a 100644
+index ee7b01bb7346c..c955e31d57289 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
-@@ -477,3 +477,4 @@
- # 545 reserved for clone3
- 547 common openat2 sys_openat2
+@@ -480,3 +480,4 @@
548 common pidfd_getfd sys_pidfd_getfd
+ 549 common faccessat2 sys_faccessat2
+ 550 common process_madvise sys_process_madvise
+551 common fsinfo sys_fsinfo
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
-index 4d1cf74a2caa..a670f6add5ab 100644
+index d056a548358ea..308dfe68d892c 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
-@@ -451,3 +451,4 @@
- 435 common clone3 sys_clone3
- 437 common openat2 sys_openat2
+@@ -454,3 +454,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
-index 803039d504de..86a9d7b3eabe 100644
+index b3b2019f8d16b..86a9d7b3eabe9 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -38,7 +38,7 @@
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
#define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
--#define __NR_compat_syscalls 439
+-#define __NR_compat_syscalls 441
+#define __NR_compat_syscalls 442
#endif
#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
-index c1c61635f89c..1f7d2c8d481a 100644
+index 107f08e03b9fd..20650e0edacb2 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
-@@ -883,6 +883,8 @@ __SYSCALL(__NR_clone3, sys_clone3)
- __SYSCALL(__NR_openat2, sys_openat2)
- #define __NR_pidfd_getfd 438
- __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+@@ -889,6 +889,8 @@ __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+ __SYSCALL(__NR_faccessat2, sys_faccessat2)
+ #define __NR_process_madvise 440
+ __SYSCALL(__NR_process_madvise, sys_process_madvise)
+#define __NR_fsinfo 441
+__SYSCALL(__NR_fsinfo, sys_fsinfo)
/*
* Please add new compat syscalls above this comment and update
diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl
-index 042911e670b8..2a4aea2f1050 100644
+index b96ed8b8a5089..548428f7b76c7 100644
--- a/arch/ia64/kernel/syscalls/syscall.tbl
+++ b/arch/ia64/kernel/syscalls/syscall.tbl
-@@ -358,3 +358,4 @@
- # 435 reserved for clone3
- 437 common openat2 sys_openat2
+@@ -361,3 +361,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
-index f4f49fcb76d0..9e254f0ef8ea 100644
+index 625fb6d328424..3dd9c1f0815ce 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
-@@ -437,3 +437,4 @@
- 435 common clone3 __sys_clone3
- 437 common openat2 sys_openat2
+@@ -440,3 +440,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
-index 4c67b11f9c9e..75924284ee3b 100644
+index aae729c95cf99..420a6d0b01004 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
-@@ -443,3 +443,4 @@
- 435 common clone3 sys_clone3
- 437 common openat2 sys_openat2
+@@ -446,3 +446,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
-index 1f9e8ad636cc..4e03df1d67d0 100644
+index 32817c954435d..01420fe120bab 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
-@@ -376,3 +376,4 @@
- 435 n32 clone3 __sys_clone3
- 437 n32 openat2 sys_openat2
+@@ -379,3 +379,4 @@
438 n32 pidfd_getfd sys_pidfd_getfd
+ 439 n32 faccessat2 sys_faccessat2
+ 440 n32 process_madvise sys_process_madvise
+441 n32 fsinfo sys_fsinfo
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
-index c0b9d802dbf6..fdcc5ca0a776 100644
+index 9e4ea3c31b1ce..6c319c38779e9 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
-@@ -352,3 +352,4 @@
- 435 n64 clone3 __sys_clone3
- 437 n64 openat2 sys_openat2
+@@ -355,3 +355,4 @@
438 n64 pidfd_getfd sys_pidfd_getfd
+ 439 n64 faccessat2 sys_faccessat2
+ 440 n64 process_madvise sys_process_madvise
+441 n64 fsinfo sys_fsinfo
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
-index ac586774c980..17fb101db45c 100644
+index 29f5f28cf5cea..46d4aa7ecb306 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
-@@ -425,3 +425,4 @@
- 435 o32 clone3 __sys_clone3
- 437 o32 openat2 sys_openat2
+@@ -428,3 +428,4 @@
438 o32 pidfd_getfd sys_pidfd_getfd
+ 439 o32 faccessat2 sys_faccessat2
+ 440 o32 process_madvise sys_process_madvise
+441 o32 fsinfo sys_fsinfo
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
-index 52a15f5cd130..daa7f0c22da0 100644
+index f375ea528e59c..008282637f6af 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
-@@ -435,3 +435,4 @@
- 435 common clone3 sys_clone3_wrapper
- 437 common openat2 sys_openat2
+@@ -438,3 +438,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
-index 35b61bfc1b1a..ad1de6e3e866 100644
+index 1275daec7fec3..85da23afb3535 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
-@@ -519,3 +519,4 @@
- 435 nospu clone3 ppc_clone3
- 437 common openat2 sys_openat2
+@@ -530,3 +530,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
-index bd7bd3581a0f..915ee9824956 100644
+index 28c1680004834..83fdaebbf0b08 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
-@@ -440,3 +440,4 @@
- 435 common clone3 sys_clone3 sys_clone3
- 437 common openat2 sys_openat2 sys_openat2
+@@ -443,3 +443,4 @@
438 common pidfd_getfd sys_pidfd_getfd sys_pidfd_getfd
-+441 common fsinfo sys_fsinfo sys_fsinfo
+ 439 common faccessat2 sys_faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise sys_process_madvise
++441 common fsinfo sys_fsinfo sys_fsinfo
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
-index c7a30fcd135f..35facfae37c9 100644
+index 783738448ff55..e1f52ffa86bb8 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
-@@ -440,3 +440,4 @@
- # 435 reserved for clone3
- 437 common openat2 sys_openat2
+@@ -443,3 +443,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
-index f13615ecdecc..45adfd34b654 100644
+index 78160260991be..1f42dc9965c23 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
-@@ -483,3 +483,4 @@
- # 435 reserved for clone3
- 437 common openat2 sys_openat2
+@@ -486,3 +486,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
-index c17cb77eb150..37aa4ed3dbef 100644
+index 0d0667a9fbd70..70da9bad3f79d 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
-@@ -442,3 +442,4 @@
- 435 i386 clone3 sys_clone3 __ia32_sys_clone3
- 437 i386 openat2 sys_openat2 __ia32_sys_openat2
- 438 i386 pidfd_getfd sys_pidfd_getfd __ia32_sys_pidfd_getfd
-+441 i386 fsinfo sys_fsinfo __ia32_sys_fsinfo
+@@ -445,3 +445,4 @@
+ 438 i386 pidfd_getfd sys_pidfd_getfd
+ 439 i386 faccessat2 sys_faccessat2
+ 440 i386 process_madvise sys_process_madvise
++441 i386 fsinfo sys_fsinfo
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
-index 44d510bc9b78..eacf0b7c5c3d 100644
+index 379819244b91d..94a51b78e85ed 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
-@@ -359,6 +359,7 @@
- 435 common clone3 __x64_sys_clone3/ptregs
- 437 common openat2 __x64_sys_openat2
- 438 common pidfd_getfd __x64_sys_pidfd_getfd
-+441 common fsinfo __x64_sys_fsinfo
+@@ -362,6 +362,7 @@
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
++441 common fsinfo sys_fsinfo
#
- # x32-specific system call numbers start at 512 to avoid cache impact
+ # Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
-index 85a9ab1bc04d..4d7803550754 100644
+index b070f272995d6..2723c2f43c59a 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
-@@ -408,3 +408,4 @@
- 435 common clone3 sys_clone3
- 437 common openat2 sys_openat2
+@@ -411,3 +411,4 @@
438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
+ 440 common process_madvise sys_process_madvise
+441 common fsinfo sys_fsinfo
diff --git a/fs/Kconfig b/fs/Kconfig
-index 708ba336e689..1d1b48059ec9 100644
+index aa4c122823018..b84156272983b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -15,6 +15,13 @@ config VALIDATE_FS_PARSER
@@ -325,7 +325,7 @@
config FS_IOMAP
diff --git a/fs/Makefile b/fs/Makefile
-index 505e51166973..b5cc9bcd17a4 100644
+index 999d1a23f036c..02da949de3b42 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_COREDUMP) += coredump.o
@@ -338,10 +338,10 @@
obj-y += quota/
diff --git a/fs/fsinfo.c b/fs/fsinfo.c
new file mode 100644
-index 000000000000..1830c73f37a7
+index 0000000000000..7d9c73e9cbdef
--- /dev/null
+++ b/fs/fsinfo.c
-@@ -0,0 +1,586 @@
+@@ -0,0 +1,596 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Filesystem information query.
+ *
@@ -361,26 +361,36 @@
+#include "internal.h"
+
+/**
++ * fsinfo_opaque - Store opaque blob as an fsinfo attribute value.
++ * @s: The blob to store (may be NULL)
++ * @ctx: The parameter context
++ * @len: The length of the blob
++ */
++int fsinfo_opaque(const void *s, struct fsinfo_context *ctx, unsigned int len)
++{
++ void *p = ctx->buffer;
++ int ret = 0;
++
++ if (s) {
++ if (!ctx->want_size_only)
++ memcpy(p, s, len);
++ ret = len;
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL(fsinfo_opaque);
++
++/**
+ * fsinfo_string - Store a NUL-terminated string as an fsinfo attribute value.
+ * @s: The string to store (may be NULL)
+ * @ctx: The parameter context
+ */
+int fsinfo_string(const char *s, struct fsinfo_context *ctx)
+{
-+ unsigned int len;
-+ char *p = ctx->buffer;
-+ int ret = 0;
-+
-+ if (s) {
-+ len = min_t(size_t, strlen(s), ctx->buf_size - 1);
-+ if (!ctx->want_size_only) {
-+ memcpy(p, s, len);
-+ p[len] = 0;
-+ }
-+ ret = len;
-+ }
-+
-+ return ret;
++ if (!s)
++ return 1;
++ return fsinfo_opaque(s, ctx, min_t(size_t, strlen(s) + 1, ctx->buf_size));
+}
+EXPORT_SYMBOL(fsinfo_string);
+
@@ -929,7 +939,7 @@
+ return ret;
+}
diff --git a/include/linux/fs.h b/include/linux/fs.h
-index fb0db8474141..13270f1a8663 100644
+index e1325dec4fa86..2d5a2f709f322 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -68,6 +68,7 @@ struct fsverity_info;
@@ -940,7 +950,7 @@
extern void __init inode_init(void);
extern void __init inode_init_early(void);
-@@ -1958,6 +1959,9 @@ struct super_operations {
+@@ -1951,6 +1952,9 @@ struct super_operations {
int (*thaw_super) (struct super_block *);
int (*unfreeze_fs) (struct super_block *);
int (*statfs) (struct dentry *, struct kstatfs *);
@@ -952,10 +962,10 @@
diff --git a/include/linux/fsinfo.h b/include/linux/fsinfo.h
new file mode 100644
-index 000000000000..bf806669b4fb
+index 0000000000000..a811d69b02ff0
--- /dev/null
+++ b/include/linux/fsinfo.h
-@@ -0,0 +1,73 @@
+@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Filesystem information query
+ *
@@ -1019,6 +1029,7 @@
+#define FSINFO_LIST(A,G) _FSINFO (A, FSINFO_TYPE_LIST, sizeof(A##__STRUCT), G)
+#define FSINFO_LIST_N(A,G) _FSINFO_N (A, FSINFO_TYPE_LIST, sizeof(A##__STRUCT), G)
+
++extern int fsinfo_opaque(const void *, struct fsinfo_context *, unsigned int);
+extern int fsinfo_string(const char *, struct fsinfo_context *);
+extern int fsinfo_generic_timestamp_info(struct path *, struct fsinfo_context *);
+extern int fsinfo_generic_supports(struct path *, struct fsinfo_context *);
@@ -1030,7 +1041,7 @@
+
+#endif /* _LINUX_FSINFO_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
-index 1815065d52f3..623f61dcdb9b 100644
+index 37bea07c12f21..e315f719899a1 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -47,6 +47,7 @@ struct stat64;
@@ -1038,42 +1049,42 @@
struct statfs64;
struct statx;
+struct fsinfo_params;
- struct __sysctl_args;
struct sysinfo;
struct timespec;
-@@ -1003,6 +1004,9 @@ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
+ struct __kernel_old_timeval;
+@@ -1008,6 +1009,9 @@ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
siginfo_t __user *info,
unsigned int flags);
asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags);
+asmlinkage long sys_fsinfo(int dfd, const char __user *pathname,
-+ struct fsinfo_params __user *params, size_t params_size,
++ const struct fsinfo_params __user *params, size_t params_size,
+ void __user *result_buffer, size_t result_buf_size);
/*
* Architecture-specific system calls
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
-index 3a3201e4618e..1708d24cf98d 100644
+index 2056318988f77..3a2e44f770f8e 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
-@@ -855,9 +855,11 @@ __SYSCALL(__NR_clone3, sys_clone3)
- __SYSCALL(__NR_openat2, sys_openat2)
- #define __NR_pidfd_getfd 438
- __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+@@ -859,9 +859,11 @@ __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+ __SYSCALL(__NR_faccessat2, sys_faccessat2)
+ #define __NR_process_madvise 440
+ __SYSCALL(__NR_process_madvise, sys_process_madvise)
+#define __NR_fsinfo 441
+__SYSCALL(__NR_fsinfo, sys_fsinfo)
#undef __NR_syscalls
--#define __NR_syscalls 439
-+#define __NR_syscalls 442
+-#define __NR_syscalls 441
++#define __NR_syscalls 443
/*
* 32 bit systems traditionally used different
diff --git a/include/uapi/linux/fsinfo.h b/include/uapi/linux/fsinfo.h
new file mode 100644
-index 000000000000..e9b35b9b7629
+index 0000000000000..65892239ba86c
--- /dev/null
+++ b/include/uapi/linux/fsinfo.h
-@@ -0,0 +1,187 @@
+@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* fsinfo() definitions.
+ *
@@ -1225,8 +1236,10 @@
+ __u32 fs_ioc_getflags; /* What FS_IOC_GETFLAGS may return */
+ __u32 fs_ioc_setflags_set; /* What FS_IOC_SETFLAGS may set */
+ __u32 fs_ioc_setflags_clear; /* What FS_IOC_SETFLAGS may clear */
++ __u32 fs_ioc_fsgetxattr_xflags; /* What FS_IOC_FSGETXATTR[A] may return in fsx_xflags */
++ __u32 fs_ioc_fssetxattr_xflags_set; /* What FS_IOC_FSSETXATTR may set in fsx_xflags */
++ __u32 fs_ioc_fssetxattr_xflags_clear; /* What FS_IOC_FSSETXATTR may set in fsx_xflags */
+ __u32 win_file_attrs; /* What DOS/Windows FILE_* attributes are supported */
-+ __u32 __padding[1];
+};
+
+#define FSINFO_ATTR_SUPPORTS__STRUCT struct fsinfo_supports
@@ -1262,7 +1275,7 @@
+
+#endif /* _UAPI_LINUX_FSINFO_H */
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
-index 3b69a560a7ac..58246e6b5603 100644
+index f27ac94d5fa72..3cf167e82606f 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -51,6 +51,7 @@ COND_SYSCALL_COMPAT(io_pgetevents);
@@ -1274,31 +1287,21 @@
/* fs/xattr.c */
diff --git a/samples/vfs/Makefile b/samples/vfs/Makefile
-index 65acdde5c117..9159ad1d7fc5 100644
+index 6377a678134ac..8efb67c45ceaa 100644
--- a/samples/vfs/Makefile
+++ b/samples/vfs/Makefile
-@@ -1,10 +1,15 @@
+@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
- # List of programs to build
-+
- hostprogs := \
-+ test-fsinfo \
- test-fsmount \
- test-statx
+-userprogs-always-y += test-fsmount test-statx
++userprogs-always-y += test-fsinfo test-fsmount test-statx
- always-y := $(hostprogs)
-
-+HOSTCFLAGS_test-fsinfo.o += -I$(objtree)/usr/include
-+HOSTLDLIBS_test-fsinfo += -static -lm
-+
- HOSTCFLAGS_test-fsmount.o += -I$(objtree)/usr/include
- HOSTCFLAGS_test-statx.o += -I$(objtree)/usr/include
+ userccflags += -I usr/include
diff --git a/samples/vfs/test-fsinfo.c b/samples/vfs/test-fsinfo.c
new file mode 100644
-index 000000000000..2b53c735d330
+index 0000000000000..934b25399ffed
--- /dev/null
+++ b/samples/vfs/test-fsinfo.c
-@@ -0,0 +1,633 @@
+@@ -0,0 +1,646 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Test the fsinfo() system call
+ *
@@ -1354,30 +1357,30 @@
+
+static ssize_t get_fsinfo(const char *, const char *, struct fsinfo_params *, void **);
+
-+static void dump_hex(unsigned int *data, int from, int to)
++static void dump_hex(FILE *f, unsigned char *data, int from, int to)
+{
-+ unsigned offset, print_offset = 1, col = 0;
-+
-+ from /= 4;
-+ to = (to + 3) / 4;
++ unsigned offset, col = 0;
++ bool print_offset = true;
+
+ for (offset = from; offset < to; offset++) {
+ if (print_offset) {
-+ printf("%04x: ", offset * 8);
++ fprintf(f, "%04x: ", offset);
+ print_offset = 0;
+ }
-+ printf("%08x", data[offset]);
++ fprintf(f, "%02x", data[offset]);
+ col++;
+ if ((col & 3) == 0) {
-+ printf("\n");
-+ print_offset = 1;
-+ } else {
-+ printf(" ");
++ if ((col & 15) == 0) {
++ fprintf(f, "\n");
++ print_offset = 1;
++ } else {
++ fprintf(f, " ");
++ }
+ }
+ }
+
+ if (!print_offset)
-+ printf("\n");
++ fprintf(f, "\n");
+}
+
+static void dump_attribute_info(void *reply, unsigned int size)
@@ -1432,8 +1435,10 @@
+ (unsigned long long)f->f_files.lo,
+ (unsigned long long)f->f_ffree.lo,
+ (unsigned long long)f->f_favail.lo);
-+ printf("\tbsize : %llu\n", f->f_bsize);
-+ printf("\tfrsize : %llu\n", f->f_frsize);
++ printf("\tbsize : %llu\n",
++ (unsigned long long)f->f_bsize);
++ printf("\tfrsize : %llu\n",
++ (unsigned long long)f->f_frsize);
+}
+
+static void dump_fsinfo_generic_ids(void *reply, unsigned int size)
@@ -1482,16 +1487,19 @@
+ printf("\tstx_mask : %x\n", f->stx_mask);
+ printf("\tfs_ioc_*flags: get=%x set=%x clr=%x\n",
+ f->fs_ioc_getflags, f->fs_ioc_setflags_set, f->fs_ioc_setflags_clear);
++ printf("\tfs_ioc_*xattr: fsx_xflags: get=%x set=%x clr=%x\n",
++ f->fs_ioc_fsgetxattr_xflags,
++ f->fs_ioc_fssetxattr_xflags_set,
++ f->fs_ioc_fssetxattr_xflags_clear);
+ printf("\twin_fattrs : %x\n", f->win_file_attrs);
+}
+
+static void print_time(struct fsinfo_timestamp_one *t, char stamp)
+{
-+ printf("\t%ctime : gran=%gs range=%llx-%llx\n",
++ printf("\t%ctime : gran=%uE%d range=%llx-%llx\n",
+ stamp,
-+ t->gran_mantissa * pow(10., t->gran_exponent),
-+ (long long)t->minimum,
-+ (long long)t->maximum);
++ t->gran_mantissa, t->gran_exponent,
++ (long long)t->minimum, (long long)t->maximum);
+}
+
+static void dump_fsinfo_generic_timestamp_info(void *reply, unsigned int size)
@@ -1595,6 +1603,22 @@
+ {}
+};
+
++static __attribute__((noreturn))
++void bad_value(const char *what,
++ struct fsinfo_params *params,
++ const struct fsinfo_attribute *attr,
++ const struct fsinfo_attribute_info *attr_info,
++ void *reply, unsigned int size)
++{
++ printf("\n");
++ fprintf(stderr, "%s %s{%u}{%u} t=%x f=%x s=%x\n",
++ what, attr->name, params->Nth, params->Mth,
++ attr_info->type, attr_info->flags, attr_info->size);
++ fprintf(stderr, "size=%u\n", size);
++ dump_hex(stderr, reply, 0, size);
++ exit(1);
++}
++
+static void dump_value(unsigned int attr_id,
+ const struct fsinfo_attribute *attr,
+ const struct fsinfo_attribute_info *attr_info,
@@ -1720,22 +1744,16 @@
+ if (size == -1) {
+ if (errno == ENODATA) {
+ if (!(attr_info->flags & (FSINFO_FLAGS_N | FSINFO_FLAGS_NM)) &&
-+ params->Nth == 0 && params->Mth == 0) {
-+ fprintf(stderr,
-+ "Unexpected ENODATA (0x%x{%u}{%u})\n",
-+ params->request, params->Nth, params->Mth);
-+ exit(1);
-+ }
++ params->Nth == 0 && params->Mth == 0)
++ bad_value("Unexpected ENODATA",
++ params, attr, attr_info, r, size);
+ free(r);
+ return (params->Mth == 0) ? 2 : 1;
+ }
+ if (errno == EOPNOTSUPP) {
-+ if (params->Nth > 0 || params->Mth > 0) {
-+ fprintf(stderr,
-+ "Should return -ENODATA (0x%x{%u}{%u})\n",
-+ params->request, params->Nth, params->Mth);
-+ exit(1);
-+ }
++ if (params->Nth > 0 || params->Mth > 0)
++ bad_value("Should return ENODATA",
++ params, attr, attr_info, r, size);
+ //printf("\e[33m%s\e[m: <not supported>\n",
+ // fsinfo_attr_names[attr]);
+ free(r);
@@ -1748,7 +1766,7 @@
+ if (raw) {
+ if (size > 4096)
+ size = 4096;
-+ dump_hex(r, 0, size);
++ dump_hex(stdout, r, 0, size);
+ free(r);
+ return 0;
+ }
@@ -1766,8 +1784,12 @@
+ }
+
+ switch (attr_info->type) {
-+ case FSINFO_TYPE_VSTRUCT:
+ case FSINFO_TYPE_STRING:
++ if (size == 0 || ((char *)r)[size - 1] != 0)
++ bad_value("Unterminated string",
++ params, attr, attr_info, r, size);
++ case FSINFO_TYPE_VSTRUCT:
++ case FSINFO_TYPE_OPAQUE:
+ dump_value(params->request, attr, attr_info, r, size);
+ free(r);
+ return 0;
@@ -1777,14 +1799,8 @@
+ free(r);
+ return 0;
+
-+ case FSINFO_TYPE_OPAQUE:
-+ free(r);
-+ return 0;
-+
+ default:
-+ fprintf(stderr, "Fishy about %u 0x%x,%x,%x\n",
-+ params->request, attr_info->type, attr_info->flags, attr_info->size);
-+ exit(1);
++ bad_value("Fishy type", params, attr, attr_info, r, size);
+ }
+}
+
@@ -1933,5 +1949,5 @@
+ return 0;
+}
--
-2.20.1
+2.25.1
diff --git a/third_party/linux/external/0002-watch_queue-Introduce-a-non-repeating-system-unique-.patch b/third_party/linux/external/0002-watch_queue-Introduce-a-non-repeating-system-unique-.patch
deleted file mode 100644
index c3d4367..0000000
--- a/third_party/linux/external/0002-watch_queue-Introduce-a-non-repeating-system-unique-.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From 695a880f7d1bf86090dae3c32e3dc67c30917267 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 5 Jul 2019 11:10:10 +0100
-Subject: [PATCH 2/4] watch_queue: Introduce a non-repeating system-unique
- superblock ID
-
-Introduce an (effectively) non-repeating system-unique superblock ID that
-can be used to determine that two object are in the same superblock without
-risking reuse of the ID in the meantime (as is possible with device IDs).
-
-The ID is time-based to make it harder to use it as a covert communications
-channel.
-
-In future patches, this ID will be used to tag superblock notification
-messages. It will also be made queryable.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- fs/internal.h | 1 +
- fs/super.c | 24 ++++++++++++++++++++++++
- include/linux/fs.h | 3 +++
- 3 files changed, 28 insertions(+)
-
-diff --git a/fs/internal.h b/fs/internal.h
-index f3f280b952a3..a0d90f23593c 100644
---- a/fs/internal.h
-+++ b/fs/internal.h
-@@ -109,6 +109,7 @@ extern int reconfigure_super(struct fs_context *);
- extern bool trylock_super(struct super_block *sb);
- extern struct super_block *user_get_super(dev_t);
- extern bool mount_capable(struct fs_context *);
-+extern void vfs_generate_unique_id(u64 *);
-
- /*
- * open.c
-diff --git a/fs/super.c b/fs/super.c
-index cd352530eca9..ececa5695fd1 100644
---- a/fs/super.c
-+++ b/fs/super.c
-@@ -44,6 +44,8 @@ static int thaw_super_locked(struct super_block *sb);
-
- static LIST_HEAD(super_blocks);
- static DEFINE_SPINLOCK(sb_lock);
-+static u64 vfs_last_identifier;
-+static u64 vfs_identifier_offset;
-
- static char *sb_writers_name[SB_FREEZE_LEVELS] = {
- "sb_writers",
-@@ -273,6 +275,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
- goto fail;
- if (list_lru_init_memcg(&s->s_inode_lru, &s->s_shrink))
- goto fail;
-+ vfs_generate_unique_id(&s->s_unique_id);
- return s;
-
- fail:
-@@ -1867,3 +1870,24 @@ int thaw_super(struct super_block *sb)
- return thaw_super_locked(sb);
- }
- EXPORT_SYMBOL(thaw_super);
-+
-+/*
-+ * Generate a unique identifier for a superblock or mount object.
-+ */
-+void vfs_generate_unique_id(u64 *_id)
-+{
-+ u64 id = ktime_to_ns(ktime_get());
-+
-+ spin_lock(&sb_lock);
-+
-+ id += vfs_identifier_offset;
-+ if (id <= vfs_last_identifier) {
-+ id = vfs_last_identifier + 1;
-+ vfs_identifier_offset = vfs_last_identifier - id;
-+ }
-+
-+ vfs_last_identifier = id;
-+ spin_unlock(&sb_lock);
-+
-+ *_id = id;
-+}
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index abedbffe2c9e..fb0db8474141 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1549,6 +1549,9 @@ struct super_block {
-
- spinlock_t s_inode_wblist_lock;
- struct list_head s_inodes_wb; /* writeback inodes */
-+
-+ /* Superblock event notifications */
-+ u64 s_unique_id;
- } __randomize_layout;
-
- /* Helper functions so that in most cases filesystems will
---
-2.20.1
-
diff --git a/third_party/linux/external/0004-fsinfo-Allow-retrieval-of-superblock-devname-options.patch b/third_party/linux/external/0003-fsinfo-Allow-retrieval-of-superblock-devname-options.patch
similarity index 79%
rename from third_party/linux/external/0004-fsinfo-Allow-retrieval-of-superblock-devname-options.patch
rename to third_party/linux/external/0003-fsinfo-Allow-retrieval-of-superblock-devname-options.patch
index 86ba2cc..d05bff4 100644
--- a/third_party/linux/external/0004-fsinfo-Allow-retrieval-of-superblock-devname-options.patch
+++ b/third_party/linux/external/0003-fsinfo-Allow-retrieval-of-superblock-devname-options.patch
@@ -1,7 +1,7 @@
-From fa2ff1a0da263362a2c98c8cfe68bcac3a323ac4 Mon Sep 17 00:00:00 2001
+From 69b33d464bcadd6c60018f5d0bde8ad3e7530dc7 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
Date: Tue, 3 Mar 2020 14:29:27 +0000
-Subject: [PATCH 4/4] fsinfo: Allow retrieval of superblock devname, options
+Subject: [PATCH 3/3] fsinfo: Allow retrieval of superblock devname, options
and stats
Provide fsinfo() attributes to retrieve superblock device name, options,
@@ -16,37 +16,39 @@
Signed-off-by: David Howells <dhowells@redhat.com>
---
- fs/fsinfo.c | 41 +++++++++++++++++++++++++++++++++++++
+ fs/fsinfo.c | 39 +++++++++++++++++++++++++++++++++++
fs/internal.h | 2 ++
- fs/namespace.c | 39 +++++++++++++++++++++++++++++++++++
+ fs/namespace.c | 41 +++++++++++++++++++++++++++++++++++++
include/uapi/linux/fsinfo.h | 3 +++
samples/vfs/test-fsinfo.c | 4 ++++
5 files changed, 89 insertions(+)
diff --git a/fs/fsinfo.c b/fs/fsinfo.c
-index 1830c73f37a7..3ed43c5a10e8 100644
+index 7d9c73e9cbdef..7e2d871eb5dfe 100644
--- a/fs/fsinfo.c
+++ b/fs/fsinfo.c
-@@ -188,6 +188,44 @@ static int fsinfo_generic_volume_id(struct path *path, struct fsinfo_context *ct
+@@ -198,6 +198,42 @@ static int fsinfo_generic_volume_id(struct path *path, struct fsinfo_context *ct
return fsinfo_string(path->dentry->d_sb->s_id, ctx);
}
+/*
+ * Retrieve the superblock configuration (mount options) as a comma-separated
-+ * string. The initial comma is stripped off.
++ * string. The initial comma is stripped off and NUL termination is added.
+ */
+static int fsinfo_generic_seq_read(struct path *path, struct fsinfo_context *ctx)
+{
+ struct super_block *sb = path->dentry->d_sb;
+ struct seq_file m = {
+ .buf = ctx->buffer,
-+ .size = ctx->buf_size,
++ .size = ctx->buf_size - 1,
+ };
+ int ret = 0;
+
+ switch (ctx->requested_attr) {
+ case FSINFO_ATTR_CONFIGURATION:
-+ if (sb->s_op->show_options)
++ seq_puts(&m, sb_rdonly(sb) ? "ro" : "rw");
++ ret = security_sb_show_options(&m, sb);
++ if (!ret && sb->s_op->show_options)
+ ret = sb->s_op->show_options(&m, path->mnt->mnt_root);
+ break;
+
@@ -60,19 +62,15 @@
+ return ret;
+ if (seq_has_overflowed(&m))
+ return ctx->buf_size + PAGE_SIZE;
-+ if (ctx->requested_attr == FSINFO_ATTR_CONFIGURATION) {
-+ if (m.count > 0 && ((char *)ctx->buffer)[0] == ',') {
-+ m.count--;
-+ ctx->skip = 1;
-+ }
-+ }
-+ return m.count;
++
++ ((char *)ctx->buffer)[ctx->skip + m.count] = 0;
++ return m.count + 1;
+}
+
static const struct fsinfo_attribute fsinfo_common_attributes[] = {
FSINFO_VSTRUCT (FSINFO_ATTR_STATFS, fsinfo_generic_statfs),
FSINFO_VSTRUCT (FSINFO_ATTR_IDS, fsinfo_generic_ids),
-@@ -196,6 +234,9 @@ static const struct fsinfo_attribute fsinfo_common_attributes[] = {
+@@ -206,6 +242,9 @@ static const struct fsinfo_attribute fsinfo_common_attributes[] = {
FSINFO_VSTRUCT (FSINFO_ATTR_TIMESTAMP_INFO, fsinfo_generic_timestamp_info),
FSINFO_STRING (FSINFO_ATTR_VOLUME_ID, fsinfo_generic_volume_id),
FSINFO_VSTRUCT (FSINFO_ATTR_VOLUME_UUID, fsinfo_generic_volume_uuid),
@@ -83,20 +81,20 @@
FSINFO_LIST (FSINFO_ATTR_FSINFO_ATTRIBUTES, (void *)123UL),
FSINFO_VSTRUCT_N(FSINFO_ATTR_FSINFO_ATTRIBUTE_INFO, (void *)123UL),
diff --git a/fs/internal.h b/fs/internal.h
-index a0d90f23593c..6f2cc77bf38d 100644
+index 1b7460f055a3b..a2a529da7e673 100644
--- a/fs/internal.h
+++ b/fs/internal.h
-@@ -91,6 +91,8 @@ extern int __mnt_want_write_file(struct file *);
- extern void __mnt_drop_write_file(struct file *);
+@@ -98,6 +98,8 @@ int path_mount(const char *dev_name, struct path *path,
+ const char *type_page, unsigned long flags, void *data_page);
+ int path_umount(struct path *path, int flags);
- extern void dissolve_on_fput(struct vfsmount *);
+extern int fsinfo_generic_mount_source(struct path *, struct fsinfo_context *);
+
/*
* fs_struct.c
*/
diff --git a/fs/namespace.c b/fs/namespace.c
-index 85b5f7bea82e..b4951e2afae1 100644
+index cebaa3e817940..33218f67ad5b1 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -30,6 +30,7 @@
@@ -107,7 +105,7 @@
#include "pnode.h"
#include "internal.h"
-@@ -3975,3 +3976,41 @@ const struct proc_ns_operations mntns_operations = {
+@@ -4105,3 +4106,43 @@ const struct proc_ns_operations mntns_operations = {
.install = mntns_install,
.owner = mntns_owner,
};
@@ -129,7 +127,7 @@
+ struct mount *mnt = real_mount(path->mnt);
+ struct seq_file m = {
+ .buf = ctx->buffer,
-+ .size = ctx->buf_size,
++ .size = ctx->buf_size - 1,
+ };
+ int ret;
+
@@ -145,12 +143,14 @@
+
+ if (seq_has_overflowed(&m))
+ return ctx->buf_size + PAGE_SIZE;
-+ return m.count;
++
++ ((char *)ctx->buffer)[m.count] = 0;
++ return m.count + 1;
+}
+
+#endif /* CONFIG_FSINFO */
diff --git a/include/uapi/linux/fsinfo.h b/include/uapi/linux/fsinfo.h
-index e9b35b9b7629..d3722c7142a6 100644
+index 65892239ba86c..45d9f4b758787 100644
--- a/include/uapi/linux/fsinfo.h
+++ b/include/uapi/linux/fsinfo.h
@@ -23,6 +23,9 @@
@@ -164,10 +164,10 @@
#define FSINFO_ATTR_FSINFO_ATTRIBUTE_INFO 0x100 /* Information about attr N (for path) */
#define FSINFO_ATTR_FSINFO_ATTRIBUTES 0x101 /* List of supported attrs (for path) */
diff --git a/samples/vfs/test-fsinfo.c b/samples/vfs/test-fsinfo.c
-index 2b53c735d330..1797f7b8d08a 100644
+index 934b25399ffed..cf849c9778f71 100644
--- a/samples/vfs/test-fsinfo.c
+++ b/samples/vfs/test-fsinfo.c
-@@ -289,6 +289,10 @@ static const struct fsinfo_attribute fsinfo_attributes[] = {
+@@ -294,6 +294,10 @@ static const struct fsinfo_attribute fsinfo_attributes[] = {
FSINFO_STRING (FSINFO_ATTR_VOLUME_ID, string),
FSINFO_VSTRUCT (FSINFO_ATTR_VOLUME_UUID, fsinfo_generic_volume_uuid),
FSINFO_STRING (FSINFO_ATTR_VOLUME_NAME, string),
@@ -179,5 +179,5 @@
FSINFO_LIST (FSINFO_ATTR_FSINFO_ATTRIBUTES, fsinfo_meta_attributes),
{}
--
-2.20.1
+2.25.1