vfs-7.0-rc1.misc.2

Please consider pulling these changes from the signed vfs-7.0-rc1.misc.2 tag.
 
 Thanks!
 Christian
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCaZMOCwAKCRCRxhvAZXjc
 oswrAP9r1zjzMimjX2J0hBoMnYjNzQfLLew8+IRygImQ+yaqWgD9Fiw/cQ9eE1Hm
 TMLqck/ky588ywSDaBzfztrXAY3ISgg=
 =4yr2
 -----END PGP SIGNATURE-----

Merge tag 'vfs-7.0-rc1.misc.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull more misc vfs updates from Christian Brauner:
 "Features:

   - Optimize close_range() from O(range size) to O(active FDs) by using
     find_next_bit() on the open_fds bitmap instead of linearly scanning
     the entire requested range. This is a significant improvement for
     large-range close operations on sparse file descriptor tables.

   - Add FS_XFLAG_VERITY file attribute for fs-verity files, retrievable
     via FS_IOC_FSGETXATTR and file_getattr(). The flag is read-only.
     Add tracepoints for fs-verity enable and verify operations,
     replacing the previously removed debug printk's.

   - Prevent nfsd from exporting special kernel filesystems like pidfs
     and nsfs. These filesystems have custom ->open() and ->permission()
     export methods that are designed for open_by_handle_at(2) only and
     are incompatible with nfsd. Update the exportfs documentation
     accordingly.

  Fixes:

   - Fix KMSAN uninit-value in ovl_fill_real() where strcmp() was used
     on a non-null-terminated decrypted directory entry name from
     fscrypt. This triggered on encrypted lower layers when the
     decrypted name buffer contained uninitialized tail data.

     The fix also adds VFS-level name_is_dot(), name_is_dotdot(), and
     name_is_dot_dotdot() helpers, replacing various open-coded "." and
     ".." checks across the tree.

   - Fix read-only fsflags not being reset together with xflags in
     vfs_fileattr_set(). Currently harmless since no read-only xflags
     overlap with flags, but this would cause inconsistencies for any
     future shared read-only flag

   - Return -EREMOTE instead of -ESRCH from PIDFD_GET_INFO when the
     target process is in a different pid namespace. This lets userspace
     distinguish "process exited" from "process in another namespace",
     matching glibc's pidfd_getpid() behavior

  Cleanups:

   - Use C-string literals in the Rust seq_file bindings, replacing the
     kernel::c_str!() macro (available since Rust 1.77)

   - Fix typo in d_walk_ret enum comment, add porting notes for the
     readlink_copy() calling convention change"

* tag 'vfs-7.0-rc1.misc.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fs: add porting notes about readlink_copy()
  pidfs: return -EREMOTE when PIDFD_GET_INFO is called on another ns
  nfsd: do not allow exporting of special kernel filesystems
  exportfs: clarify the documentation of open()/permission() expotrfs ops
  fsverity: add tracepoints
  fs: add FS_XFLAG_VERITY for fs-verity files
  rust: seq_file: replace `kernel::c_str!` with C-Strings
  fs: dcache: fix typo in enum d_walk_ret comment
  ovl: use name_is_dot* helpers in readdir code
  fs: add helpers name_is_dot{,dot,_dotdot}
  ovl: Fix uninit-value in ovl_fill_real
  fs: reset read-only fsflags together with xflags
  fs/file: optimize close_range() complexity from O(N) to O(Sparse)
This commit is contained in:
Linus Torvalds 2026-02-16 13:00:36 -08:00
commit 45a43ac5ac
26 changed files with 274 additions and 57 deletions

View file

@ -341,6 +341,22 @@ the file has fs-verity enabled. This can perform better than
FS_IOC_GETFLAGS and FS_IOC_MEASURE_VERITY because it doesn't require
opening the file, and opening verity files can be expensive.
FS_IOC_FSGETXATTR
-----------------
Since Linux v7.0, the FS_IOC_FSGETXATTR ioctl sets FS_XFLAG_VERITY (0x00020000)
in the returned flags when the file has verity enabled. Note that this attribute
cannot be set with FS_IOC_FSSETXATTR as enabling verity requires input
parameters. See FS_IOC_ENABLE_VERITY.
file_getattr
------------
Since Linux v7.0, the file_getattr() syscall sets FS_XFLAG_VERITY (0x00020000)
in the returned flags when the file has verity enabled. Note that this attribute
cannot be set with file_setattr() as enabling verity requires input parameters.
See FS_IOC_ENABLE_VERITY.
.. _accessing_verity_files:
Accessing verity files

View file

@ -1351,3 +1351,13 @@ and do_rmdir()) are gone; they are replaced with non-consuming analogues
(filename_renameat2(), etc.)
Callers are adjusted - responsibility for dropping the filenames belongs
to them now.
---
**mandatory**
readlink_copy() now requires link length as the 4th argument. Said length needs
to match what strlen() would return if it was ran on the string.
However, if the string is freely accessible for the duration of inode's
lifetime, consider using inode_set_cached_link() instead.

View file

@ -10415,6 +10415,7 @@ T: git https://git.kernel.org/pub/scm/fs/fsverity/linux.git
F: Documentation/filesystems/fsverity.rst
F: fs/verity/
F: include/linux/fsverity.h
F: include/trace/events/fsverity.h
F: include/uapi/linux/fsverity.h
FT260 FTDI USB-HID TO I2C BRIDGE DRIVER

View file

@ -76,7 +76,7 @@ struct fscrypt_nokey_name {
static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
{
return is_dot_dotdot(str->name, str->len);
return name_is_dot_dotdot(str->name, str->len);
}
/**

View file

@ -1298,8 +1298,8 @@ void shrink_dcache_sb(struct super_block *sb)
EXPORT_SYMBOL(shrink_dcache_sb);
/**
* enum d_walk_ret - action to talke during tree walk
* @D_WALK_CONTINUE: contrinue walk
* enum d_walk_ret - action to take during tree walk
* @D_WALK_CONTINUE: continue walk
* @D_WALK_QUIT: quit walk
* @D_WALK_NORETRY: quit when retry is needed
* @D_WALK_SKIP: skip this dentry and its children

View file

@ -1904,7 +1904,7 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name,
if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) &&
!(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)) {
if (is_dot_dotdot(name, name_size)) {
if (name_is_dot_dotdot(name, name_size)) {
rc = ecryptfs_copy_filename(plaintext_name,
plaintext_name_size,
name, name_size);

View file

@ -253,7 +253,8 @@ static bool filldir_one(struct dir_context *ctx, const char *name, int len,
container_of(ctx, struct getdents_callback, ctx);
buf->sequence++;
if (buf->ino == ino && len <= NAME_MAX && !is_dot_dotdot(name, len)) {
if (buf->ino == ino && len <= NAME_MAX &&
!name_is_dot_dotdot(name, len)) {
memcpy(buf->name, name, len);
buf->name[len] = '\0';
buf->found = 1;

View file

@ -68,7 +68,7 @@ int f2fs_init_casefolded_name(const struct inode *dir,
int len;
if (IS_CASEFOLDED(dir) &&
!is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) {
!name_is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) {
buf = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
GFP_NOFS, false, F2FS_SB(sb));
if (!buf)

View file

@ -100,7 +100,7 @@ void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname)
WARN_ON_ONCE(!name);
if (is_dot_dotdot(name, len)) {
if (name_is_dot_dotdot(name, len)) {
fname->hash = 0;
return;
}

View file

@ -777,23 +777,29 @@ static inline void __range_close(struct files_struct *files, unsigned int fd,
unsigned int max_fd)
{
struct file *file;
struct fdtable *fdt;
unsigned n;
spin_lock(&files->file_lock);
n = last_fd(files_fdtable(files));
fdt = files_fdtable(files);
n = last_fd(fdt);
max_fd = min(max_fd, n);
for (; fd <= max_fd; fd++) {
for (fd = find_next_bit(fdt->open_fds, max_fd + 1, fd);
fd <= max_fd;
fd = find_next_bit(fdt->open_fds, max_fd + 1, fd + 1)) {
file = file_close_fd_locked(files, fd);
if (file) {
spin_unlock(&files->file_lock);
filp_close(file, files);
cond_resched();
spin_lock(&files->file_lock);
fdt = files_fdtable(files);
} else if (need_resched()) {
spin_unlock(&files->file_lock);
cond_resched();
spin_lock(&files->file_lock);
fdt = files_fdtable(files);
}
}
spin_unlock(&files->file_lock);

View file

@ -37,6 +37,8 @@ void fileattr_fill_xflags(struct file_kattr *fa, u32 xflags)
fa->flags |= FS_DAX_FL;
if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
fa->flags |= FS_PROJINHERIT_FL;
if (fa->fsx_xflags & FS_XFLAG_VERITY)
fa->flags |= FS_VERITY_FL;
}
EXPORT_SYMBOL(fileattr_fill_xflags);
@ -67,6 +69,8 @@ void fileattr_fill_flags(struct file_kattr *fa, u32 flags)
fa->fsx_xflags |= FS_XFLAG_DAX;
if (fa->flags & FS_PROJINHERIT_FL)
fa->fsx_xflags |= FS_XFLAG_PROJINHERIT;
if (fa->flags & FS_VERITY_FL)
fa->fsx_xflags |= FS_XFLAG_VERITY;
}
EXPORT_SYMBOL(fileattr_fill_flags);
@ -142,8 +146,7 @@ static int file_attr_to_fileattr(const struct file_attr *fattr,
if (fattr->fa_xflags & ~mask)
return -EINVAL;
fileattr_fill_xflags(fa, fattr->fa_xflags);
fa->fsx_xflags &= ~FS_XFLAG_RDONLY_MASK;
fileattr_fill_xflags(fa, fattr->fa_xflags & ~FS_XFLAG_RDONLY_MASK);
fa->fsx_extsize = fattr->fa_extsize;
fa->fsx_projid = fattr->fa_projid;
fa->fsx_cowextsize = fattr->fa_cowextsize;
@ -163,8 +166,7 @@ static int copy_fsxattr_from_user(struct file_kattr *fa,
if (xfa.fsx_xflags & ~mask)
return -EOPNOTSUPP;
fileattr_fill_xflags(fa, xfa.fsx_xflags);
fa->fsx_xflags &= ~FS_XFLAG_RDONLY_MASK;
fileattr_fill_xflags(fa, xfa.fsx_xflags & ~FS_XFLAG_RDONLY_MASK);
fa->fsx_extsize = xfa.fsx_extsize;
fa->fsx_nextents = xfa.fsx_nextents;
fa->fsx_projid = xfa.fsx_projid;

View file

@ -3088,7 +3088,7 @@ int lookup_noperm_common(struct qstr *qname, struct dentry *base)
if (!len)
return -EACCES;
if (is_dot_dotdot(name, len))
if (name_is_dot_dotdot(name, len))
return -EACCES;
while (len--) {

View file

@ -427,7 +427,8 @@ static int check_export(const struct path *path, int *flags, unsigned char *uuid
* either a device number (so FS_REQUIRES_DEV needed)
* or an FSID number (so NFSEXP_FSID or ->uuid is needed).
* 2: We must be able to find an inode from a filehandle.
* This means that s_export_op must be set.
* This means that s_export_op must be set and comply with
* the requirements for remote filesystem export.
* 3: We must not currently be on an idmapped mount.
*/
if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
@ -437,8 +438,9 @@ static int check_export(const struct path *path, int *flags, unsigned char *uuid
return -EINVAL;
}
if (!exportfs_can_decode_fh(inode->i_sb->s_export_op)) {
dprintk("exp_export: export of invalid fs type.\n");
if (!exportfs_may_export(inode->i_sb->s_export_op)) {
dprintk("exp_export: export of invalid fs type (%s).\n",
inode->i_sb->s_type->name);
return -EINVAL;
}

View file

@ -77,7 +77,8 @@ static int ovl_casefold(struct ovl_readdir_data *rdd, const char *str, int len,
char *cf_name;
int cf_len;
if (!IS_ENABLED(CONFIG_UNICODE) || !rdd->map || is_dot_dotdot(str, len))
if (!IS_ENABLED(CONFIG_UNICODE) || !rdd->map ||
name_is_dot_dotdot(str, len))
return 0;
cf_name = kmalloc(NAME_MAX, GFP_KERNEL);
@ -154,7 +155,7 @@ static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd,
return true;
/* Always recalc d_ino for parent */
if (strcmp(p->name, "..") == 0)
if (name_is_dotdot(p->name, p->len))
return true;
/* If this is lower, then native d_ino will do */
@ -165,7 +166,7 @@ static bool ovl_calc_d_ino(struct ovl_readdir_data *rdd,
* Recalc d_ino for '.' and for all entries if dir is impure (contains
* copied up entries)
*/
if ((p->name[0] == '.' && p->len == 1) ||
if (name_is_dot(p->name, p->len) ||
ovl_test_flag(OVL_IMPURE, d_inode(rdd->dentry)))
return true;
@ -561,12 +562,12 @@ static int ovl_cache_update(const struct path *path, struct ovl_cache_entry *p,
if (!ovl_same_dev(ofs) && !p->check_xwhiteout)
goto out;
if (p->name[0] == '.') {
if (name_is_dot_dotdot(p->name, p->len)) {
if (p->len == 1) {
this = dget(dir);
goto get;
}
if (p->len == 2 && p->name[1] == '.') {
if (p->len == 2) {
/* we shall not be moved */
this = dget(dir->d_parent);
goto get;
@ -666,8 +667,7 @@ static int ovl_dir_read_impure(const struct path *path, struct list_head *list,
return err;
list_for_each_entry_safe(p, n, list, l_node) {
if (strcmp(p->name, ".") != 0 &&
strcmp(p->name, "..") != 0) {
if (!name_is_dot_dotdot(p->name, p->len)) {
err = ovl_cache_update(path, p, true);
if (err)
return err;
@ -756,7 +756,7 @@ static bool ovl_fill_real(struct dir_context *ctx, const char *name,
struct dir_context *orig_ctx = rdt->orig_ctx;
bool res;
if (rdt->parent_ino && strcmp(name, "..") == 0) {
if (rdt->parent_ino && name_is_dotdot(name, namelen)) {
ino = rdt->parent_ino;
} else if (rdt->cache) {
struct ovl_cache_entry *p;
@ -1098,12 +1098,8 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
goto del_entry;
}
if (p->name[0] == '.') {
if (p->len == 1)
if (name_is_dot_dotdot(p->name, p->len))
goto del_entry;
if (p->len == 2 && p->name[1] == '.')
goto del_entry;
}
err = -ENOTEMPTY;
break;
@ -1147,7 +1143,7 @@ static bool ovl_check_d_type(struct dir_context *ctx, const char *name,
container_of(ctx, struct ovl_readdir_data, ctx);
/* Even if d_type is not supported, DT_DIR is returned for . and .. */
if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen))
if (name_is_dot_dotdot(name, namelen))
return true;
if (d_type != DT_UNKNOWN)
@ -1210,10 +1206,7 @@ static int ovl_workdir_cleanup_recurse(struct ovl_fs *ofs, const struct path *pa
list_for_each_entry(p, &list, l_node) {
struct dentry *dentry;
if (p->name[0] == '.') {
if (p->len == 1)
continue;
if (p->len == 2 && p->name[1] == '.')
if (name_is_dot_dotdot(p->name, p->len)) {
continue;
} else if (incompat) {
pr_err("overlay with incompat feature '%s' cannot be mounted\n",
@ -1279,12 +1272,8 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
goto out;
list_for_each_entry(p, &list, l_node) {
if (p->name[0] == '.') {
if (p->len == 1)
if (name_is_dot_dotdot(p->name, p->len))
continue;
if (p->len == 2 && p->name[1] == '.')
continue;
}
index = ovl_lookup_upper_unlocked(ofs, p->name, indexdir, p->len);
if (IS_ERR(index)) {
err = PTR_ERR(index);

View file

@ -360,7 +360,7 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
* namespace hierarchy.
*/
if (!pid_in_current_pidns(pid))
return -ESRCH;
return -EREMOTE;
attr = READ_ONCE(pid->attr);
if (mask & PIDFD_INFO_EXIT) {

View file

@ -1044,7 +1044,7 @@ static bool __dir_empty(struct dir_context *ctx, const char *name, int namlen,
struct ksmbd_readdir_data *buf;
buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
if (!is_dot_dotdot(name, namlen))
if (!name_is_dot_dotdot(name, namlen))
buf->dirent_count++;
return !buf->dirent_count;

View file

@ -223,6 +223,8 @@ static int enable_verity(struct file *filp,
if (err)
goto out;
trace_fsverity_enable(inode, &params);
/*
* Start enabling verity on this file, serialized by the inode lock.
* Fail if verity is already enabled or is already being enabled.
@ -265,6 +267,8 @@ static int enable_verity(struct file *filp,
goto rollback;
}
trace_fsverity_tree_done(inode, vi, &params);
/*
* Add the fsverity_info into the hash table before finishing the
* initialization so that we don't have to undo the enabling when memory

View file

@ -163,4 +163,6 @@ static inline void fsverity_init_signature(void)
void __init fsverity_init_workqueue(void);
#include <trace/events/fsverity.h>
#endif /* _FSVERITY_PRIVATE_H */

View file

@ -5,6 +5,7 @@
* Copyright 2019 Google LLC
*/
#define CREATE_TRACE_POINTS
#include "fsverity_private.h"
#include <linux/ratelimit.h>

View file

@ -177,6 +177,9 @@ static bool verify_data_block(struct fsverity_info *vi,
/* Byte offset of the wanted hash relative to @addr */
unsigned int hoffset;
} hblocks[FS_VERITY_MAX_LEVELS];
trace_fsverity_verify_data_block(inode, params, data_pos);
/*
* The index of the previous level's block within that level; also the
* index of that block's hash within the current level.
@ -255,6 +258,9 @@ static bool verify_data_block(struct fsverity_info *vi,
want_hash = _want_hash;
kunmap_local(haddr);
put_page(hpage);
trace_fsverity_merkle_hit(inode, data_pos, hblock_idx,
level,
hoffset >> params->log_digestsize);
goto descend;
}
hblocks[level].page = hpage;
@ -273,6 +279,9 @@ descend:
unsigned long hblock_idx = hblocks[level - 1].index;
unsigned int hoffset = hblocks[level - 1].hoffset;
trace_fsverity_verify_merkle_block(inode, hblock_idx,
level, hoffset >> params->log_digestsize);
fsverity_hash_block(params, haddr, real_hash);
if (memcmp(want_hash, real_hash, hsize) != 0)
goto corrupted;

View file

@ -200,6 +200,10 @@ struct handle_to_path_ctx {
* @get_parent: find the parent of a given directory
* @commit_metadata: commit metadata changes to stable storage
*
* Methods for open_by_handle(2) syscall with special kernel file systems:
* @permission: custom permission for opening a file by handle
* @open: custom open routine for opening file by handle
*
* See Documentation/filesystems/nfs/exporting.rst for details on how to use
* this interface correctly and the definition of the flags.
*
@ -244,10 +248,14 @@ struct handle_to_path_ctx {
* space cannot be allocated, a %ERR_PTR should be returned.
*
* @permission:
* Allow filesystems to specify a custom permission function.
* Allow filesystems to specify a custom permission function for the
* open_by_handle_at(2) syscall instead of the default permission check.
* This custom permission function is not respected by nfsd.
*
* @open:
* Allow filesystems to specify a custom open function.
* Allow filesystems to specify a custom open function for the
* open_by_handle_at(2) syscall instead of the default file_open_root().
* This custom open function is not respected by nfsd.
*
* @commit_metadata:
* @commit_metadata should commit metadata changes to stable storage.
@ -330,6 +338,15 @@ static inline bool exportfs_can_decode_fh(const struct export_operations *nop)
return nop && nop->fh_to_dentry;
}
static inline bool exportfs_may_export(const struct export_operations *nop)
{
/*
* Do not allow nfs export for filesystems with custom ->open() or
* ->permission() ops, which nfsd does not respect (e.g. pidfs, nsfs).
*/
return exportfs_can_decode_fh(nop) && !nop->open && !nop->permission;
}
static inline bool exportfs_can_encode_fh(const struct export_operations *nop,
int fh_flags)
{

View file

@ -7,16 +7,16 @@
#define FS_COMMON_FL \
(FS_SYNC_FL | FS_IMMUTABLE_FL | FS_APPEND_FL | \
FS_NODUMP_FL | FS_NOATIME_FL | FS_DAX_FL | \
FS_PROJINHERIT_FL)
FS_PROJINHERIT_FL | FS_VERITY_FL)
#define FS_XFLAG_COMMON \
(FS_XFLAG_SYNC | FS_XFLAG_IMMUTABLE | FS_XFLAG_APPEND | \
FS_XFLAG_NODUMP | FS_XFLAG_NOATIME | FS_XFLAG_DAX | \
FS_XFLAG_PROJINHERIT)
FS_XFLAG_PROJINHERIT | FS_XFLAG_VERITY)
/* Read-only inode flags */
#define FS_XFLAG_RDONLY_MASK \
(FS_XFLAG_PREALLOC | FS_XFLAG_HASATTR)
(FS_XFLAG_PREALLOC | FS_XFLAG_HASATTR | FS_XFLAG_VERITY)
/* Flags to indicate valid value of fsx_ fields */
#define FS_XFLAG_VALUES_MASK \

View file

@ -2872,12 +2872,22 @@ u64 vfsmount_to_propagation_flags(struct vfsmount *mnt);
extern char *file_path(struct file *, char *, int);
static inline bool name_is_dot(const char *name, size_t len)
{
return unlikely(len == 1 && name[0] == '.');
}
static inline bool name_is_dotdot(const char *name, size_t len)
{
return unlikely(len == 2 && name[0] == '.' && name[1] == '.');
}
/**
* is_dot_dotdot - returns true only if @name is "." or ".."
* name_is_dot_dotdot - returns true only if @name is "." or ".."
* @name: file name to check
* @len: length of file name, in bytes
*/
static inline bool is_dot_dotdot(const char *name, size_t len)
static inline bool name_is_dot_dotdot(const char *name, size_t len)
{
return len && unlikely(name[0] == '.') &&
(len == 1 || (len == 2 && name[1] == '.'));

View file

@ -0,0 +1,146 @@
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM fsverity
#if !defined(_TRACE_FSVERITY_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_FSVERITY_H
#include <linux/tracepoint.h>
struct fsverity_descriptor;
struct merkle_tree_params;
struct fsverity_info;
TRACE_EVENT(fsverity_enable,
TP_PROTO(const struct inode *inode,
const struct merkle_tree_params *params),
TP_ARGS(inode, params),
TP_STRUCT__entry(
__field(ino_t, ino)
__field(u64, data_size)
__field(u64, tree_size)
__field(unsigned int, merkle_block)
__field(unsigned int, num_levels)
),
TP_fast_assign(
__entry->ino = inode->i_ino;
__entry->data_size = i_size_read(inode);
__entry->tree_size = params->tree_size;
__entry->merkle_block = params->block_size;
__entry->num_levels = params->num_levels;
),
TP_printk("ino %lu data_size %llu tree_size %llu merkle_block %u levels %u",
(unsigned long) __entry->ino,
__entry->data_size,
__entry->tree_size,
__entry->merkle_block,
__entry->num_levels)
);
TRACE_EVENT(fsverity_tree_done,
TP_PROTO(const struct inode *inode, const struct fsverity_info *vi,
const struct merkle_tree_params *params),
TP_ARGS(inode, vi, params),
TP_STRUCT__entry(
__field(ino_t, ino)
__field(u64, data_size)
__field(u64, tree_size)
__field(unsigned int, merkle_block)
__field(unsigned int, levels)
__dynamic_array(u8, root_hash, params->digest_size)
__dynamic_array(u8, file_digest, params->digest_size)
),
TP_fast_assign(
__entry->ino = inode->i_ino;
__entry->data_size = i_size_read(inode);
__entry->tree_size = params->tree_size;
__entry->merkle_block = params->block_size;
__entry->levels = params->num_levels;
memcpy(__get_dynamic_array(root_hash), vi->root_hash, __get_dynamic_array_len(root_hash));
memcpy(__get_dynamic_array(file_digest), vi->file_digest, __get_dynamic_array_len(file_digest));
),
TP_printk("ino %lu data_size %llu tree_size %lld merkle_block %u levels %u root_hash %s digest %s",
(unsigned long) __entry->ino,
__entry->data_size,
__entry->tree_size,
__entry->merkle_block,
__entry->levels,
__print_hex_str(__get_dynamic_array(root_hash), __get_dynamic_array_len(root_hash)),
__print_hex_str(__get_dynamic_array(file_digest), __get_dynamic_array_len(file_digest)))
);
TRACE_EVENT(fsverity_verify_data_block,
TP_PROTO(const struct inode *inode,
const struct merkle_tree_params *params,
u64 data_pos),
TP_ARGS(inode, params, data_pos),
TP_STRUCT__entry(
__field(ino_t, ino)
__field(u64, data_pos)
__field(unsigned int, merkle_block)
),
TP_fast_assign(
__entry->ino = inode->i_ino;
__entry->data_pos = data_pos;
__entry->merkle_block = params->block_size;
),
TP_printk("ino %lu data_pos %llu merkle_block %u",
(unsigned long) __entry->ino,
__entry->data_pos,
__entry->merkle_block)
);
TRACE_EVENT(fsverity_merkle_hit,
TP_PROTO(const struct inode *inode, u64 data_pos,
unsigned long hblock_idx, unsigned int level,
unsigned int hidx),
TP_ARGS(inode, data_pos, hblock_idx, level, hidx),
TP_STRUCT__entry(
__field(ino_t, ino)
__field(u64, data_pos)
__field(unsigned long, hblock_idx)
__field(unsigned int, level)
__field(unsigned int, hidx)
),
TP_fast_assign(
__entry->ino = inode->i_ino;
__entry->data_pos = data_pos;
__entry->hblock_idx = hblock_idx;
__entry->level = level;
__entry->hidx = hidx;
),
TP_printk("ino %lu data_pos %llu hblock_idx %lu level %u hidx %u",
(unsigned long) __entry->ino,
__entry->data_pos,
__entry->hblock_idx,
__entry->level,
__entry->hidx)
);
TRACE_EVENT(fsverity_verify_merkle_block,
TP_PROTO(const struct inode *inode, unsigned long hblock_idx,
unsigned int level, unsigned int hidx),
TP_ARGS(inode, hblock_idx, level, hidx),
TP_STRUCT__entry(
__field(ino_t, ino)
__field(unsigned long, hblock_idx)
__field(unsigned int, level)
__field(unsigned int, hidx)
),
TP_fast_assign(
__entry->ino = inode->i_ino;
__entry->hblock_idx = hblock_idx;
__entry->level = level;
__entry->hidx = hidx;
),
TP_printk("ino %lu hblock_idx %lu level %u hidx %u",
(unsigned long) __entry->ino,
__entry->hblock_idx,
__entry->level,
__entry->hidx)
);
#endif /* _TRACE_FSVERITY_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View file

@ -253,6 +253,7 @@ struct file_attr {
#define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
#define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */
#define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */
#define FS_XFLAG_VERITY 0x00020000 /* fs-verity enabled */
#define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
/* the read-only stuff doesn't really belong here, but any other place is

View file

@ -4,7 +4,7 @@
//!
//! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.h)
use crate::{bindings, c_str, fmt, str::CStrExt as _, types::NotThreadSafe, types::Opaque};
use crate::{bindings, fmt, str::CStrExt as _, types::NotThreadSafe, types::Opaque};
/// A utility for generating the contents of a seq file.
#[repr(transparent)]
@ -36,7 +36,7 @@ impl SeqFile {
unsafe {
bindings::seq_printf(
self.inner.get(),
c_str!("%pA").as_char_ptr(),
c"%pA".as_char_ptr(),
core::ptr::from_ref(&args).cast::<crate::ffi::c_void>(),
);
}