Linux 文件系统 API 概述

本节包含 API 级别的文档,主要来自源代码本身。

Linux VFS

文件系统类型

enum positive_aop_returns

具有特定语义的 aop 返回代码

常量

AOP_WRITEPAGE_ACTIVATE

通知调用者页面写回已完成,该页面仍处于锁定状态,并且应被视为活动状态。 VM 使用此提示将页面返回到活动列表 - 在不久的将来它不会再次成为写回的候选者。 其他调用者必须小心,如果他们获得此返回值,则解锁页面。 由 writepage() 返回;

AOP_TRUNCATED_PAGE

已传递锁定页面的 AOP 方法已将其解锁,并且该页面可能已被截断。 调用者应该备份到获取一个新页面并再次尝试。 aop 将采取合理的预防措施,以防止发生死锁。 如果调用者持有页面引用,则在重试之前应将其删除。 由 read_folio() 返回。

描述

address_space_operation 函数返回这些大的常量,以向调用者指示特殊的语义。 这些常量远大于页面中的字节数,以便允许函数返回给定页面中操作的字节数。

struct address_space

可缓存、可映射对象的内容。

定义:

struct address_space {
    struct inode            *host;
    struct xarray           i_pages;
    struct rw_semaphore     invalidate_lock;
    gfp_t gfp_mask;
    atomic_t i_mmap_writable;
#ifdef CONFIG_READ_ONLY_THP_FOR_FS;
    atomic_t nr_thps;
#endif;
    struct rb_root_cached   i_mmap;
    unsigned long           nrpages;
    pgoff_t writeback_index;
    const struct address_space_operations *a_ops;
    unsigned long           flags;
    errseq_t wb_err;
    spinlock_t i_private_lock;
    struct list_head        i_private_list;
    struct rw_semaphore     i_mmap_rwsem;
    void *                  i_private_data;
};

成员

host

所有者,inode 或 block_device。

i_pages

缓存的页面。

invalidate_lock

在无效期间,保护页面缓存内容和文件偏移量->磁盘块映射之间的连贯性。 它还用于阻止通过内存映射修改页面缓存内容。

gfp_mask

用于分配页面的内存分配标志。

i_mmap_writable

VM_SHARED、VM_MAYWRITE 映射的数量。

nr_thps

页面缓存中 THP 的数量(仅限非 shmem)。

i_mmap

私有和共享映射的树。

nrpages

页面条目的数量,由 i_pages 锁保护。

writeback_index

写回从这里开始。

a_ops

方法。

flags

错误位和标志 (AS_*)。

wb_err

最近发生的错误。

i_private_lock

供 address_space 的所有者使用。

i_private_list

供 address_space 的所有者使用。

i_mmap_rwsem

保护 i_mmapi_mmap_writable

i_private_data

供 address_space 的所有者使用。

struct file_ra_state

跟踪文件的预读状态。

定义:

struct file_ra_state {
    pgoff_t start;
    unsigned int size;
    unsigned int async_size;
    unsigned int ra_pages;
    unsigned int mmap_miss;
    loff_t prev_pos;
};

成员

start

最近一次预读开始的位置。

size

最近一次预读中读取的页数。

async_size

不需要立即使用,因此确实是“超前”的页数。 当访问这些页面的第一页时,启动下一次预读。

ra_pages

预读请求的最大大小,从 bdi 复制。

mmap_miss

页面缓存中有多少 mmap 访问未命中。

prev_pos

最近一次读取请求中的最后一个字节。

描述

当此结构传递给 ->readahead() 时,“最近”的预读意味着当前的预读。

struct file

表示一个文件

定义:

struct file {
    spinlock_t f_lock;
    fmode_t f_mode;
    const struct file_operations    *f_op;
    struct address_space            *f_mapping;
    void *private_data;
    struct inode                    *f_inode;
    unsigned int                    f_flags;
    unsigned int                    f_iocb_flags;
    const struct cred               *f_cred;
    struct fown_struct              *f_owner;
    struct path                     f_path;
    union {
        struct mutex            f_pos_lock;
        u64 f_pipe;
    };
    loff_t f_pos;
#ifdef CONFIG_SECURITY;
    void *f_security;
#endif;
    errseq_t f_wb_err;
    errseq_t f_sb_err;
#ifdef CONFIG_EPOLL;
    struct hlist_head               *f_ep;
#endif;
    union {
        struct callback_head    f_task_work;
        struct llist_node       f_llist;
        struct file_ra_state    f_ra;
        freeptr_t f_freeptr;
    };
    file_ref_t f_ref;
};

成员

f_lock

保护 f_ep、f_flags。 不能从 IRQ 上下文中获取。

f_mode

热路径中常用的 FMODE_* 标志

f_op

文件操作

f_mapping

可缓存、可映射对象的内容。

private_data

文件系统或驱动程序特定的数据

f_inode

缓存的 inode

f_flags

文件标志

f_iocb_flags

iocb 标志

f_cred

创建者/开启者的隐藏凭据

f_owner

文件所有者

f_path

文件的路径

{unnamed_union}

匿名

f_pos_lock

保护文件位置的锁

f_pipe

特定于管道

f_pos

文件位置

f_security

此文件的 LSM 安全上下文

f_wb_err

写回错误

f_sb_err

每个 sb 的写回错误

f_ep

此文件的所有 epoll 钩子的链接

{unnamed_union}

匿名

f_task_work

任务工作入口点

f_llist

工作队列入口点

f_ra

文件的预读状态

f_freeptr

SLAB_TYPESAFE_BY_RCU 文件缓存使用的指针(请勿触摸。)

f_ref

引用计数

vfsuid_t i_uid_into_vfsuid(struct mnt_idmap *idmap, const struct inode *inode)

根据 idmapping 映射 inode 的 i_uid

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct inode *inode

要映射的 inode

返回

根据 idmap 映射的 whe inode 的 i_uid。 如果 inode 的 i_uid 没有映射,则返回 INVALID_VFSUID。

bool i_uid_needs_update(struct mnt_idmap *idmap, const struct iattr *attr, const struct inode *inode)

检查 inode 的 i_uid 是否需要更新

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct iattr *attr

inode 的新属性

const struct inode *inode

要更新的 inode

描述

如果文件系统支持,请检查是否需要更新 $inode 的 i_uid 字段,并考虑 idmapped 挂载点。

返回

如果 inode 的 i_uid 字段需要更新,则为 true;否则为 false。

void i_uid_update(struct mnt_idmap *idmap, const struct iattr *attr, struct inode *inode)

更新 inode 的 i_uid 字段

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct iattr *attr

inode 的新属性

struct inode *inode

要更新的 inode

描述

安全地更新 inode 的 i_uid 字段,将任何 idmapped 挂载点的 vfsuid 转换为文件系统 kuid。

vfsgid_t i_gid_into_vfsgid(struct mnt_idmap *idmap, const struct inode *inode)

根据 idmapping 映射 inode 的 i_gid

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct inode *inode

要映射的 inode

返回

根据 idmap 映射的 inode 的 i_gid。 如果 inode 的 i_gid 没有映射,则返回 INVALID_VFSGID。

bool i_gid_needs_update(struct mnt_idmap *idmap, const struct iattr *attr, const struct inode *inode)

检查 inode 的 i_gid 是否需要更新

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct iattr *attr

inode 的新属性

const struct inode *inode

要更新的 inode

描述

如果文件系统支持,请检查是否需要更新 $inode 的 i_gid 字段,并考虑 idmapped 挂载点。

返回

如果 inode 的 i_gid 字段需要更新,则为 true;否则为 false。

void i_gid_update(struct mnt_idmap *idmap, const struct iattr *attr, struct inode *inode)

更新 inode 的 i_gid 字段

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct iattr *attr

inode 的新属性

struct inode *inode

要更新的 inode

描述

安全地更新 inode 的 i_gid 字段,将任何 idmapped 挂载点的 vfsgid 转换为文件系统 kgid。

void inode_fsuid_set(struct inode *inode, struct mnt_idmap *idmap)

使用调用者的 fsuid 初始化 inode 的 i_uid 字段

参数

struct inode *inode

要初始化的 inode

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

描述

初始化 inode 的 i_uid 字段。 如果通过 idmapped 挂载点找到/创建了 inode,则根据 idmap 映射调用者的 fsuid。

void inode_fsgid_set(struct inode *inode, struct mnt_idmap *idmap)

使用调用者的 fsgid 初始化 inode 的 i_gid 字段

参数

struct inode *inode

要初始化的 inode

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

描述

初始化 inode 的 i_gid 字段。 如果通过 idmapped 挂载点找到/创建了 inode,则根据 idmap 映射调用者的 fsgid。

bool fsuidgid_has_mapping(struct super_block *sb, struct mnt_idmap *idmap)

检查是否映射了调用者的 fsuid/fsgid

参数

struct super_block *sb

我们想要在其中进行映射的超级块

struct mnt_idmap *idmap

相关挂载点的 idmap

描述

检查调用者的 fsuid 和 fsgid 在超级块 sb 的 s_user_ns 中是否具有有效的映射。 如果调用者位于 idmapped 挂载点,则首先根据 idmap 映射调用者的 fsuid 和 fsgid。

返回

如果映射了 fsuid 和 fsgid,则为 true;否则为 false。

struct timespec64 inode_set_ctime(struct inode *inode, time64_t sec, long nsec)

在 inode 中设置 ctime

参数

struct inode *inode

要在其中设置 ctime 的 inode

time64_t sec

要设置的 tv_sec 值

long nsec

要设置的 tv_nsec 值

描述

inode 中的 ctime 设置为 { sec, nsec }

int __sb_write_started(const struct super_block *sb, int level)

检查是否持有 sb 冻结级别

参数

const struct super_block *sb

我们要写入的 super

int level

冻结级别

描述

  • > 0 - 持有 sb 冻结级别

  • 0 - 未持有 sb 冻结级别

  • < 0 - !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN

bool sb_write_started(const struct super_block *sb)

检查是否持有 SB_FREEZE_WRITE

参数

const struct super_block *sb

我们要写入的 super

描述

在 !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN 的情况下可能是误报。

bool sb_write_not_started(const struct super_block *sb)

检查是否未持有 SB_FREEZE_WRITE

参数

const struct super_block *sb

我们要写入的 super

描述

在 !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN 的情况下可能是误报。

bool file_write_started(const struct file *file)

检查是否持有 SB_FREEZE_WRITE

参数

const struct file *file

我们要写入的文件

描述

在 !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN 的情况下可能是误报。在 !S_ISREG 的情况下可能是误报,因为 file_start_write() 对 !S_ISREG 没有影响。

bool file_write_not_started(const struct file *file)

检查是否未持有 SB_FREEZE_WRITE

参数

const struct file *file

我们要写入的文件

描述

在 !CONFIG_LOCKDEP/LOCK_STATE_UNKNOWN 的情况下可能是误报。在 !S_ISREG 的情况下可能是误报,因为 file_start_write() 对 !S_ISREG 没有影响。

void sb_end_write(struct super_block *sb)

释放对超级块的写访问权

参数

struct super_block *sb

我们写入的超级块

描述

减少文件系统的写入者数量。唤醒可能想要冻结文件系统的等待者。

void sb_end_pagefault(struct super_block *sb)

从页面错误中释放对超级块的写访问权

参数

struct super_block *sb

我们写入的超级块

描述

减少处理文件系统写入页面错误的进程数量。唤醒可能想要冻结文件系统的等待者。

void sb_end_intwrite(struct super_block *sb)

为了文件系统内部目的,释放对超级块的写访问权

参数

struct super_block *sb

我们写入的超级块

描述

减少文件系统内部写入者数量。唤醒可能想要冻结文件系统的等待者。

void sb_start_write(struct super_block *sb)

获取对超级块的写访问权

参数

struct super_block *sb

我们要写入的 super

描述

当进程想要向文件系统写入数据或元数据(即,弄脏页面或 inode)时,它应该将操作嵌入到 sb_start_write() - sb_end_write() 对中,以获得针对文件系统冻结的互斥。此函数增加写入者数量,防止冻结。如果文件系统已经冻结,该函数将等待直到文件系统解冻。

由于冻结保护行为类似于锁,因此用户必须保持冻结保护和其他文件系统锁的顺序。通常,冻结保护应该是最外层的锁。特别是,我们有

sb_start_write

-> i_mutex(写入路径、截断、目录操作...) -> s_umount(freeze_super、thaw_super)

void sb_start_pagefault(struct super_block *sb)

从页面错误中获取对超级块的写访问权

参数

struct super_block *sb

我们要写入的 super

描述

当进程开始处理写入页面错误时,它应该将操作嵌入到 sb_start_pagefault() - sb_end_pagefault() 对中,以获得针对文件系统冻结的互斥。这是必需的,因为页面错误将会弄脏页面。此函数增加正在运行的页面错误数量,防止冻结。如果文件系统已经冻结,该函数将等待直到文件系统解冻。

由于页面错误冻结保护行为类似于锁,因此用户必须保持冻结保护和其他文件系统锁的顺序。建议将 sb_start_pagefault() 放置在锁定顺序中靠近 mmap_lock 的位置。页面错误处理代码暗示锁定依赖关系

mmap_lock

-> sb_start_pagefault

void sb_start_intwrite(struct super_block *sb)

为了文件系统内部目的,获取对超级块的写访问权

参数

struct super_block *sb

我们要写入的 super

描述

这是防止文件系统冻结的第三级保护。文件系统可以自由使用它。唯一的要求是它必须低于 sb_start_pagefault。

例如,文件系统可以在启动事务时调用 sb_start_intwrite(),这在一定程度上简化了文件系统更改的内部源(内部文件系统线程、在文件关闭时丢弃预分配等)的冻结处理。

struct renamedata

包含重命名所需的所有信息

定义:

struct renamedata {
    struct mnt_idmap *old_mnt_idmap;
    struct inode *old_dir;
    struct dentry *old_dentry;
    struct mnt_idmap *new_mnt_idmap;
    struct inode *new_dir;
    struct dentry *new_dentry;
    struct inode **delegated_inode;
    unsigned int flags;
};

成员

old_mnt_idmap

找到 inode 的旧挂载的 idmap

old_dir

源的父目录

old_dentry

new_mnt_idmap

找到 inode 的新挂载的 idmap

new_dir

目标的父目录

new_dentry

目标

delegated_inode

返回需要中断委托的 inode

flags

重命名标志

enum freeze_holder

冻结的持有者

常量

FREEZE_HOLDER_KERNEL

内核想要冻结或解冻文件系统

FREEZE_HOLDER_USERSPACE

用户空间想要冻结或解冻文件系统

FREEZE_MAY_NEST

是否允许嵌套冻结和解冻请求

FREEZE_EXCL

只能由所有者撤消的冻结

描述

指示冻结或解冻请求的所有者是谁,以及冻结是否需要是独占的或可以嵌套。如果没有 FREEZE_MAY_NEST,则不允许来自同一持有者的多个冻结和解冻请求。但是,允许同时持有单个 FREEZE_HOLDER_USERSPACE 和单个 FREEZE_HOLDER_KERNEL 冻结。某些文件系统在在线修复或类似过程中依赖于此。

bool is_mgtime(const struct inode *inode)

此 inode 是否使用多粒度时间戳

参数

const struct inode *inode

要测试多粒度时间戳的 inode

描述

如果 inode 使用多粒度时间戳,则返回 true,否则返回 false。

bool is_idmapped_mnt(const struct vfsmount *mnt)

检查挂载是否已映射

参数

const struct vfsmount *mnt

要检查的挂载

描述

如果 mnt 附加了非 nop_mnt_idmap,则 mnt 已映射。

返回

如果挂载已映射,则为 true,否则为 false。

void file_start_write(struct file *file)

获取对常规文件 IO 的超级块的写访问权

参数

struct file *file

我们要写入的文件

描述

这是 sb_start_write() 的变体,它在非常规文件上是空操作。应与对 file_end_write() 的调用相匹配。

void file_end_write(struct file *file)

释放对常规文件的超级块的写访问权

参数

struct file *file

我们写入的文件

描述

应与对 file_start_write() 的调用相匹配。

void kiocb_start_write(struct kiocb *iocb)

获取对异步文件 IO 的超级块的写访问权

参数

struct kiocb *iocb

我们想要提交写入的 IO 上下文

描述

这是 sb_start_write() 的变体,用于异步 IO 提交。应与对 kiocb_end_write() 的调用相匹配。

void kiocb_end_write(struct kiocb *iocb)

在异步文件 IO 之后释放对超级块的写访问权

参数

struct kiocb *iocb

我们提交写入的 IO 上下文

描述

应与对 kiocb_start_write() 的调用相匹配。

bool is_dot_dotdot(const char *name, size_t len)

仅当 name 是“.”或“..”时才返回 true

参数

const char *name

要检查的文件名

size_t len

文件名的长度,以字节为单位

void inode_dio_begin(struct inode *inode)

发出直接 I/O 请求开始的信号

参数

struct inode *inode

直接 I/O 发生的 inode

描述

一旦我们完成了直接 I/O 请求的处理,就会调用此函数,并用于唤醒等待直接 I/O 静止的调用者。

void inode_dio_end(struct inode *inode)

发出直接 I/O 请求完成的信号

参数

struct inode *inode

直接 I/O 发生的 inode

描述

一旦我们完成了直接 I/O 请求的处理,就会调用此函数,并用于唤醒等待直接 I/O 静止的调用者。

bool generic_ci_validate_strict_name(struct inode *dir, struct qstr *name)

检查给定的名称是否适合目录

参数

struct inode *dir

将在其中创建新文件的目录的 inode

struct qstr *name

新文件的名称

描述

此函数检查建议的文件名对于父目录是否有效。这意味着对于使用严格编码标志创建的文件系统中区分大小写折叠的目录,将仅接受有效的 UTF-8 文件名。这也意味着对于未启用区分大小写折叠或未严格编码的目录,将接受任何名称。

返回

  • True:如果文件名适合此目录。如果给定的名称不适合严格编码目录,但正在使用的目录不严格,则可能为 true

  • False:如果文件名不适合此目录。这仅在目录区分大小写折叠且文件系统对其编码严格时才会发生。

目录缓存

void d_drop(struct dentry *dentry)

丢弃一个 dentry

参数

struct dentry *dentry

要丢弃的 dentry

描述

d_drop() 从父 dentry 哈希中取消哈希条目,以便通过 VFS 查找不再找到它。请注意,这与删除 dentry 不同 - d_delete 将尝试尽可能将 dentry 标记为负数,从而给出成功的 _negative_ 查找,而 d_drop 只会使缓存查找失败。

d_drop() 主要用于想要因某种原因使 dentry 无效的组件(NFS 超时或 autofs 删除)。

__d_drop 需要 dentry->d_lock

___d_drop 不会将 dentry 标记为“未哈希”(dentry->d_hash.pprev 将是 LIST_POISON2,而不是 NULL)。

struct dentry *d_find_any_alias(struct inode *inode)

查找给定 inode 的任何别名

参数

struct inode *inode

要查找别名的 inode

描述

如果给定inode存在任何别名,则获取并返回其中一个别名的引用。如果不存在别名,则返回 NULL

struct dentry *d_find_alias(struct inode *inode)

获取inode的哈希别名

参数

struct inode *inode

有问题的inode

描述

如果inode有一个哈希别名,或者是一个目录并且有任何别名,则获取对别名的引用并返回它。否则返回NULL。请注意,如果inode是一个目录,则只能有一个别名,并且只有在它没有子目录、或者它是文件系统的根目录、或者目录被重命名且d_revalidate是第一个注意到此点的VFS操作时,它才可能是不哈希的。

如果inode有一个IS_ROOT、DCACHE_DISCONNECTED别名,那么优先选择任何其他的哈希别名而不是该别名。

void shrink_dcache_sb(struct super_block *sb)

收缩超级块的dcache

参数

struct super_block *sb

超级块

描述

收缩指定超级块的dcache。这用于在卸载文件系统之前释放dcache。

int path_has_submounts(const struct path *parent)

检查当前命名空间中的dentry上是否存在挂载点。

参数

const struct path *parent

要检查的路径。

描述

如果父路径或其子目录包含当前命名空间中的挂载点,则返回true。

void shrink_dcache_parent(struct dentry *parent)

修剪dcache

参数

struct dentry *parent

要修剪的条目的父dentry

描述

修剪dcache以删除父dentry未使用的子条目。

void d_invalidate(struct dentry *dentry)

分离子挂载点、修剪dcache并删除

参数

struct dentry *dentry

要失效的dentry(也就是分离、修剪和删除)

struct dentry *d_alloc(struct dentry *parent, const struct qstr *name)

分配一个dcache条目

参数

struct dentry * parent

要分配的条目的父条目

const struct qstr *name

名称的qstr

描述

分配一个dentry。如果可用内存不足,则返回NULL。成功后,将返回dentry。传入的名称将被复制,并且在此调用后可以重复使用传入的副本。

void d_instantiate(struct dentry *entry, struct inode *inode)

填写dentry的inode信息

参数

struct dentry *entry

要完成的dentry

struct inode * inode

要附加到此dentry的inode

描述

填写条目中的inode信息。

这将使负dentry变成社会中有用的完全成员。

注意!这假定inode计数已由调用者递增(或以其他方式设置),以指示它现在正被dcache使用。

struct dentry *d_obtain_alias(struct inode *inode)

查找或分配给定inode的DISCONNECTED dentry

参数

struct inode *inode

要为其分配dentry的inode

描述

获取用于NFS文件句柄转换或类似通过句柄操作打开的inode的dentry。返回的dentry可能是匿名的,或者可能具有完整的名称(如果inode已在缓存中)。

当在目录inode上调用时,我们必须确保inode只有一个dentry。如果找到dentry,则返回该dentry而不是分配新的dentry。

在成功返回时,inode的引用已转移到dentry。如果发生错误,则释放inode上的引用。为了更容易在导出操作中使用,可以传入NULL或IS_ERR的inode,并且错误将传播到返回值,NULL inode替换为ERR_PTR(-ESTALE)。

struct dentry *d_obtain_root(struct inode *inode)

查找或分配给定inode的dentry

参数

struct inode *inode

要为其分配dentry的inode

描述

获取文件系统根的IS_ROOT dentry。

我们必须确保目录inode只有一个dentry。如果找到dentry,则返回该dentry而不是分配新的dentry。

在成功返回时,inode的引用已转移到dentry。如果发生错误,则释放inode上的引用。可以传入NULL或IS_ERR的inode,并且错误将传播到返回值,NULL inode替换为ERR_PTR(-ESTALE)。

struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, struct qstr *name)

查找或分配具有区分大小写名称的新dentry

参数

struct dentry *dentry

传递给父条目的lookup函数的负dentry

struct inode *inode

不区分大小写查找发现的inode

struct qstr *name

要与返回的dentry关联的区分大小写的名称

描述

这是为了避免用不区分大小写的名称填充dcache到同一个inode,只有实际正确的区分大小写的名称存储在不区分大小写的文件系统的dcache中。

对于不区分大小写的查找匹配,并且如果区分大小写的dentry已存在于dcache中,则使用它并返回它。

如果不存在具有区分大小写的名称的条目,则分配具有区分大小写的名称的新dentry,并返回拼接的条目。

bool d_same_name(const struct dentry *dentry, const struct dentry *parent, const struct qstr *name)

将dentry名称与区分大小写的名称进行比较

参数

const struct dentry *dentry

传递给父条目的lookup函数的负dentry

const struct dentry *parent

父dentry

const struct qstr *name

要与返回的dentry关联的区分大小写的名称

返回

如果名称相同,则为true,否则为false

struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)

搜索dentry

参数

const struct dentry *parent

父dentry

const struct qstr *name

我们希望找到的名称的qstr

返回

dentry或NULL

描述

d_lookup搜索父dentry的子条目以查找有问题的名称。如果找到dentry,则其引用计数将递增并返回dentry。调用者必须使用dput在完成使用后释放该条目。如果dentry不存在,则返回NULL

void d_delete(struct dentry *dentry)

删除dentry

参数

struct dentry * dentry

要删除的dentry

描述

如果可能,将dentry转换为负dentry,否则将其从哈希队列中删除,以便以后可以删除它

void d_rehash(struct dentry *entry)

将条目添加回哈希

参数

struct dentry * entry

要添加到哈希的dentry

描述

根据dentry的名称将其添加到哈希。

void d_add(struct dentry *entry, struct inode *inode)

将dentry添加到哈希队列

参数

struct dentry *entry

要添加的dentry

struct inode *inode

要附加到此dentry的inode

描述

这会将条目添加到哈希队列并初始化 inode。该条目实际上是在之前的d_alloc()期间填充的。

struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)

如果存在断开连接的dentry,则将其拼接到树中

参数

struct inode *inode

可能具有断开连接的dentry的inode

struct dentry *dentry

我们希望指向inode的负dentry。

描述

如果inode是一个目录并且具有IS_ROOT别名,则d_move它以代替给定的dentry并返回它,否则只需将inode d_add到dentry并返回NULL。

如果找到非IS_ROOT目录,则文件系统已损坏,我们应该报错:目录不能有多个别名。

任何可导出的文件系统(通过knfsd)的查找例程中都需要此功能,以便我们可以有效地构建到目录的dcache路径。

如果找到并移动了dentry,则返回它。否则返回NULL。这与->lookup的预期返回值匹配。

集群文件系统可以使用已哈希的负dentry调用此函数。在这种情况下,我们知道inode将是一个常规文件,并且这只会发生在atomic_open期间。因此,我们只需要在最后一种情况下检查dentry是否已经哈希。

bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)

new_dentry是否是old_dentry的子目录

参数

struct dentry *new_dentry

新的dentry

struct dentry *old_dentry

旧的dentry

描述

如果new_dentry是父条目的子目录(在任何深度),则返回true。否则返回false。调用者必须确保在调用is_subdir()之前固定“new_dentry”

struct dentry *dget_dlock(struct dentry *dentry)

获取dentry的引用

参数

struct dentry *dentry

要获取引用的dentry

描述

给定一个活动的dentry,递增引用计数并返回dentry。调用者必须持有 dentry->d_lock。确保dentry处于活动状态是调用者的责任。有很多条件足以保证这一点;例如,任何具有非负引用计数的条目都是活动的,任何哈希的条目、任何正条目、任何条目的父条目等等。

struct dentry *dget(struct dentry *dentry)

获取dentry的引用

参数

struct dentry *dentry

要获取引用的dentry

描述

给定一个dentry或NULL指针,如果合适,则递增引用计数并返回dentry。当dentry具有引用时,不会销毁dentry。相反,没有引用的dentry可能会因多种原因而消失,从内存压力开始。换句话说,该原语用于克隆现有引用;在引用计数为零的对象上使用它是bug。

注意

如果持有 dentry->d_lock,它将旋转。从避免死锁的角度来看,它等同于spin_lock()/递增引用计数/spin_unlock(),因此在 dentry->d_lock下调用它始终是bug;在它的任何子条目上在->d_lock下调用它也是如此。

int d_unhashed(const struct dentry *dentry)

dentry 是否已哈希

参数

const struct dentry *dentry

要检查的条目

描述

如果传递的 dentry 当前未哈希,则返回 true。

bool d_really_is_negative(const struct dentry *dentry)

确定 dentry 是否真的为负(忽略 fallthrough)

参数

const struct dentry *dentry

有问题的 dentry

描述

如果 dentry 表示一个不存在的名称或一个不映射到 inode 的名称(即 ->d_inode 为 NULL),则返回 true。dentry 可以表示一个真正的未命中,一个不由 0,0 chardev 表示的 whiteout,或者一个不透明目录中的 fallthrough 标记。

注意!(1)这应该由文件系统使用来检查它自己的 dentry。不应该用于查看其他文件系统的 dentry。(2)它也应该与 d_inode() 结合使用来获取 inode。(3)dentry 可能有一些东西附加到 ->d_lower,并且标志的类型字段可能被设置为除 miss 或 whiteout 之外的其他东西。

bool d_really_is_positive(const struct dentry *dentry)

确定 dentry 是否真的为正(忽略 fallthrough)

参数

const struct dentry *dentry

有问题的 dentry

描述

如果 dentry 表示一个映射到 inode 的名称(即 ->d_inode 不为 NULL),则返回 true。如果 whiteout 在介质上表示为 0,0 chardev,则 dentry 仍然可能表示一个 whiteout。

注意!(1)这应该由文件系统使用来检查它自己的 dentry。不应该用于查看其他文件系统的 dentry。(2)它也应该与 d_inode() 结合使用来获取 inode。

struct inode *d_inode(const struct dentry *dentry)

获取此 dentry 的实际 inode

参数

const struct dentry *dentry

要查询的 dentry

描述

这是普通文件系统应该用来获取它们自己的 inode 在它们自己的 dentry 中的助手函数,并忽略叠加在它们之上的分层。

struct inode *d_inode_rcu(const struct dentry *dentry)

使用 READ_ONCE() 获取此 dentry 的实际 inode

参数

const struct dentry *dentry

要查询的 dentry

描述

这是普通文件系统应该用来获取它们自己的 inode 在它们自己的 dentry 中的助手函数,并忽略叠加在它们之上的分层。

struct inode *d_backing_inode(const struct dentry *upper)

获取我们应该使用的上层或下层 inode

参数

const struct dentry *upper

上层

描述

这是应该用来获取 inode 的助手函数,如果这个 dentry 要作为文件打开,将会使用该 inode。inode 可能在上层 dentry 上,也可能在由上层固定的下层 dentry 上。

普通文件系统不应该使用它来访问它们自己的 inode。

struct dentry *d_real(struct dentry *dentry, enum d_real_type type)

返回真实的 dentry

参数

struct dentry *dentry

要查询的 dentry

enum d_real_type type

真实 dentry 的类型(数据或元数据)

描述

如果 dentry 在 union/overlay 上,则返回底层的真实 dentry。否则返回 dentry 本身。

另请参阅:Linux 虚拟文件系统概述

struct inode *d_real_inode(const struct dentry *dentry)

返回托管数据的真实 inode

参数

const struct dentry *dentry

要查询的 dentry

描述

如果 dentry 在 union/overlay 上,则返回底层的真实 inode。否则返回 d_inode()

Inode 处理

int inode_init_always_gfp(struct super_block *sb, struct inode *inode, gfp_t gfp)

执行 inode 结构初始化

参数

struct super_block *sb

inode 所属的超级块

struct inode *inode

要初始化的 inode

gfp_t gfp

分配标志

描述

这些是在每次 inode 分配时都需要完成的初始化,因为这些字段没有被 slab 分配初始化。如果需要额外的分配,则使用 gfp

直接减少 inode 的链接计数

参数

struct inode *inode

inode

描述

这是一个低级文件系统助手,用于替换任何对 i_nlink 的直接文件系统操作。在我们尝试跟踪对文件系统的写入的情况下,减为零意味着当文件被截断并在文件系统上实际取消链接时,即将进行写入。

直接将 inode 的链接计数清零

参数

struct inode *inode

inode

描述

这是一个低级文件系统助手,用于替换任何对 i_nlink 的直接文件系统操作。有关我们为什么关心 i_nlink 达到零的信息,请参阅 drop_nlink()

直接设置 inode 的链接计数

参数

struct inode *inode

inode

unsigned int nlink

新的 nlink(应为非零)

描述

这是一个低级文件系统助手,用于替换任何对 i_nlink 的直接文件系统操作。

直接递增 inode 的链接计数

参数

struct inode *inode

inode

描述

这是一个低级文件系统助手,用于替换任何对 i_nlink 的直接文件系统操作。目前,它只是为了与 dec_nlink() 保持一致。

void inode_sb_list_add(struct inode *inode)

将 inode 添加到 inode 的超级块列表

参数

struct inode *inode

要添加的 inode

void __insert_inode_hash(struct inode *inode, unsigned long hashval)

哈希一个 inode

参数

struct inode *inode

未哈希的 inode

unsigned long hashval

用于在 inode_hashtable 中定位此对象的 unsigned long 值。

将 inode 添加到此超级块的 inode 哈希中。

void __remove_inode_hash(struct inode *inode)

从哈希中删除一个 inode

参数

struct inode *inode

要取消哈希的 inode

从超级块中删除一个 inode。

void evict_inodes(struct super_block *sb)

逐出超级块的所有可逐出的 inode

参数

struct super_block *sb

要操作的超级块

描述

确保不保留任何具有零引用计数的 inode。这在移除 SB_ACTIVE 标志后由超级块关闭调用,因此在此调用期间或之后达到零引用计数的任何 inode 将立即被逐出。

struct inode *new_inode(struct super_block *sb)

获取一个 inode

参数

struct super_block *sb

超级块

为给定的超级块分配一个新的 inode。与 inode->i_mapping 相关的分配的默认 gfp_mask 是 GFP_HIGHUSER_MOVABLE。如果 HIGHMEM 页面不合适,或者已知为页面缓存分配的页面不可回收或不可迁移,则必须使用新创建的 inode 映射上的适当标志调用 mapping_set_gfp_mask()

void unlock_new_inode(struct inode *inode)

清除 I_NEW 状态并唤醒任何等待者

参数

struct inode *inode

要解锁的新 inode

描述

当 inode 完全初始化时调用,以清除 inode 的新状态并唤醒任何等待 inode 完成初始化的人。

void lock_two_nondirectories(struct inode *inode1, struct inode *inode2)

在非目录对象上获取两个 i_mutex

参数

struct inode *inode1

要锁定的第一个 inode

struct inode *inode2

要锁定的第二个 inode

描述

锁定任何非 NULL 参数。传递的对象不能是目录。此函数可以锁定零个、一个或两个对象。

void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2)

lock_two_nondirectories() 释放锁

参数

struct inode *inode1

要解锁的第一个 inode

struct inode *inode2

要解锁的第二个 inode

struct inode *inode_insert5(struct inode *inode, unsigned long hashval, int (*test)(struct inode*, void*), int (*set)(struct inode*, void*), void *data)

从已挂载的文件系统获取一个 inode

参数

struct inode *inode

用于插入到缓存的预分配 inode

unsigned long hashval

要获取的哈希值(通常是 inode 编号)

int (*test)(struct inode *, void *)

用于比较 inode 之间的回调

int (*set)(struct inode *, void *)

用于初始化新 struct inode 的回调函数

void *data

传递给 testset 的不透明数据指针

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode,如果存在,则返回它并增加引用计数。 这是 iget5_locked() 的一个变体,它不分配 inode。

如果 inode 不在缓存中,则插入预先分配的 inode 并返回它,此时它是被锁定的、已哈希的,并且设置了 I_NEW 标志。文件系统可以在通过 unlock_new_inode() 解锁它之前填充它。

请注意,testset 都是在持有 inode_hash_lock 的情况下调用的,因此它们无法睡眠。

struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, int (*test)(struct inode*, void*), int (*set)(struct inode*, void*), void *data)

从已挂载的文件系统获取一个 inode

参数

struct super_block *sb

文件系统的超级块

unsigned long hashval

要获取的哈希值(通常是 inode 编号)

int (*test)(struct inode *, void *)

用于比较 inode 之间的回调

int (*set)(struct inode *, void *)

用于初始化新 struct inode 的回调函数

void *data

传递给 testset 的不透明数据指针

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode,如果存在,则返回它并增加引用计数。 这是 iget_locked() 的一个通用版本,用于 inode 编号不足以唯一标识 inode 的文件系统。

如果 inode 不在缓存中,则分配并插入一个新的 inode 并返回它,此时它是被锁定的、已哈希的,并且设置了 I_NEW 标志。文件系统可以在通过 unlock_new_inode() 解锁它之前填充它。

请注意,testset 都是在持有 inode_hash_lock 的情况下调用的,因此它们无法睡眠。

struct inode *iget5_locked_rcu(struct super_block *sb, unsigned long hashval, int (*test)(struct inode*, void*), int (*set)(struct inode*, void*), void *data)

从已挂载的文件系统获取一个 inode

参数

struct super_block *sb

文件系统的超级块

unsigned long hashval

要获取的哈希值(通常是 inode 编号)

int (*test)(struct inode *, void *)

用于比较 inode 之间的回调

int (*set)(struct inode *, void *)

用于初始化新 struct inode 的回调函数

void *data

传递给 testset 的不透明数据指针

描述

这等效于 iget5_locked,但 test 回调必须容忍 inode 不稳定,包括正在拆卸过程中。

struct inode *iget_locked(struct super_block *sb, unsigned long ino)

从已挂载的文件系统获取一个 inode

参数

struct super_block *sb

文件系统的超级块

unsigned long ino

要获取的 inode 编号

描述

在 inode 缓存中搜索由 ino 指定的 inode,如果存在,则返回它并增加引用计数。 这适用于 inode 编号足以唯一标识 inode 的文件系统。

如果 inode 不在缓存中,则分配一个新的 inode 并返回它,此时它是被锁定的、已哈希的,并且设置了 I_NEW 标志。文件系统可以在通过 unlock_new_inode() 解锁它之前填充它。

ino_t iunique(struct super_block *sb, ino_t max_reserved)

获取唯一的 inode 编号

参数

struct super_block *sb

超级块

ino_t max_reserved

最高保留的 inode 编号

获取对于给定的超级块在系统上唯一的 inode 编号。 这适用于没有自然永久 inode 编号系统的文件系统。 返回的 inode 编号高于保留限制但唯一。

错误:如果文件系统上有大量 inode,则此函数目前会变得非常慢。

struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, int (*test)(struct inode*, void*), void *data)

在 inode 缓存中搜索 inode

参数

struct super_block *sb

要搜索的文件系统的超级块

unsigned long hashval

要搜索的哈希值(通常是 inode 编号)

int (*test)(struct inode *, void *)

用于比较 inode 之间的回调

void *data

传递给 test 的不透明数据指针

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode。 如果 inode 在缓存中,则返回该 inode 并增加引用计数。

注意2:test 是在持有 inode_hash_lock 的情况下调用的,因此无法睡眠。

注意

I_NEW 不会被等待,因此您必须非常小心如何处理返回的 inode。 您可能应该使用 ilookup5() 来代替。

struct inode *ilookup5(struct super_block *sb, unsigned long hashval, int (*test)(struct inode*, void*), void *data)

在 inode 缓存中搜索 inode

参数

struct super_block *sb

要搜索的文件系统的超级块

unsigned long hashval

要搜索的哈希值(通常是 inode 编号)

int (*test)(struct inode *, void *)

用于比较 inode 之间的回调

void *data

传递给 test 的不透明数据指针

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode,如果 inode 在缓存中,则返回该 inode 并增加引用计数。 在返回 inode 之前等待 I_NEW。 返回的 inode 增加引用计数。

这是 ilookup() 的一个通用版本,用于 inode 编号不足以唯一标识 inode 的文件系统。

注意

test 是在持有 inode_hash_lock 的情况下调用的,因此无法睡眠。

struct inode *ilookup(struct super_block *sb, unsigned long ino)

在 inode 缓存中搜索 inode

参数

struct super_block *sb

要搜索的文件系统的超级块

unsigned long ino

要搜索的 inode 编号

描述

在 inode 缓存中搜索 inode ino,如果 inode 在缓存中,则返回该 inode 并增加引用计数。

struct inode *find_inode_nowait(struct super_block *sb, unsigned long hashval, int (*match)(struct inode*, unsigned long, void*), void *data)

在 inode 缓存中查找 inode

参数

struct super_block *sb

要搜索的文件系统的超级块

unsigned long hashval

要搜索的哈希值(通常是 inode 编号)

int (*match)(struct inode *, unsigned long, void *)

用于比较 inode 之间的回调

void *data

传递给 match 的不透明数据指针

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode,其中辅助函数 match 将在 inode 不匹配时返回 0,在 inode 匹配时返回 1,在应停止搜索时返回 -1。 match 函数必须负责获取 i_lock 自旋锁并检查 i_state 以查找正在释放或正在初始化的 inode,并在返回 1 之前增加引用计数。 它也不能睡眠,因为它是在持有 inode_hash_lock 自旋锁的情况下调用的。

这是 ilookup5() 的更通用版本,当该函数绝不能阻塞时 --- find_inode() 可以在 __wait_on_freeing_inode() 中阻塞 --- 或者当调用者无法增加引用计数时,因为生成的 iput() 可能会导致 inode 逐出。 权衡之处在于,match 函数必须非常小心地实现。

struct inode *find_inode_rcu(struct super_block *sb, unsigned long hashval, int (*test)(struct inode*, void*), void *data)

在 inode 缓存中查找 inode

参数

struct super_block *sb

要搜索的文件系统的超级块

unsigned long hashval

要哈希的键

int (*test)(struct inode *, void *)

用于测试 inode 上的匹配项的函数

void *data

测试函数的数据

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode,其中辅助函数 test 将在 inode 不匹配时返回 0,匹配时返回 1。 test 函数必须负责获取 i_lock 自旋锁并检查 i_state 以查找正在释放或正在初始化的 inode。

如果成功,这将返回 test 函数返回 1 的 inode,否则返回 NULL。

不允许 test 函数获取呈现的任何 inode 的引用。 也不允许睡眠。

调用者必须持有 RCU 读锁。

struct inode *find_inode_by_ino_rcu(struct super_block *sb, unsigned long ino)

在 inode 缓存中查找 inode

参数

struct super_block *sb

要搜索的文件系统的超级块

unsigned long ino

要匹配的 inode 编号

描述

在 inode 缓存中搜索由 hashvaldata 指定的 inode,其中辅助函数 test 将在 inode 不匹配时返回 0,匹配时返回 1。 test 函数必须负责获取 i_lock 自旋锁并检查 i_state 以查找正在释放或正在初始化的 inode。

如果成功,这将返回 test 函数返回 1 的 inode,否则返回 NULL。

不允许 test 函数获取呈现的任何 inode 的引用。 也不允许睡眠。

调用者必须持有 RCU 读锁。

void iput(struct inode *inode)

释放 inode

参数

struct inode *inode

要释放的 inode

释放一个 inode,删除其使用计数。 如果 inode 使用计数达到零,则释放该 inode,也可能被销毁。

因此,iput() 可以睡眠。

int bmap(struct inode *inode, sector_t *block)

在文件中查找块编号

参数

struct inode *inode

拥有所请求的块编号的 inode

sector_t *block

包含要查找的块的指针

*block 中的值替换为设备上保存与文件中所请求的块编号相对应的块的块编号。 也就是说,要求 inode 1 的块 4,该函数将 *block 中的 4 替换为相对于磁盘开始处,保存该文件的块的磁盘块。

如果发生错误,则返回 -EINVAL,否则返回 0。 如果映射落入一个空洞,则返回 0,并且 *block 也设置为 0。

int inode_update_timestamps(struct inode *inode, int flags)

更新 inode 上的时间戳

参数

struct inode *inode

要更新的 inode

int flags

需要更新的 S_* 标志

描述

当需要为读取或写入操作更新 inode 的时间戳时,调用 update_time 函数。 此函数处理更新实际时间戳。 由调用者负责确保 inode 已被适当标记为脏。

在任何 S_MTIME、S_CTIME 或 S_VERSION 需要更新的情况下,尝试更新所有三个时间戳。 S_ATIME 更新可以独立于其余更新处理。

返回一组指示哪些值已更改的 S_* 标志。

int generic_update_time(struct inode *inode, int flags)

更新 inode 上的时间戳

参数

struct inode *inode

要更新的 inode

int flags

需要更新的 S_* 标志

描述

当需要为读取或写入操作更新 inode 的时间戳时,将调用 update_time 函数。 如果需要更新 S_MTIME、S_CTIME 或 S_VERSION 中的任何一个,我们将尝试更新所有这三个。 S_ATIME 的更新可以独立于其余部分进行处理。

返回一个 S_* 掩码,指示哪些字段已更新。

int file_remove_privs(struct file *file)

移除特殊文件权限 (suid, capabilities)

参数

struct file *file

要移除权限的文件

描述

当文件被写入或截断修改时,确保移除特殊文件权限。

返回

成功时返回 0,失败时返回负的 errno。

struct timespec64 current_time(struct inode *inode)

返回 FS 时间(可能为细粒度)

参数

struct inode *inode

inode。

描述

返回截断到文件系统支持的时间粒度的当前时间,适用于 ctime/mtime 更改。 如果 ctime 被标记为已 QUERIED,则获取细粒度的时间戳,但不要更新 floor。

对于 multigrain inode,这实际上是文件将收到的时间戳的估计值。 实际的更新必须通过 inode_set_ctime_current()

int file_update_time(struct file *file)

更新 mtime 和 ctime 时间

参数

struct file *file

访问的文件

描述

更新 inode 的 mtime 和 ctime 成员,并将 inode 标记为写回。 请注意,此函数专门用于文件系统的文件写入路径,并且文件系统可以选择使用 _NOCMTIME inode 标志显式忽略通过此函数进行的更新,例如,对于网络文件系统,这些时间戳由服务器处理。 对于需要分配空间才能更新 inode 的文件系统,这可能会返回错误。

返回

成功时返回 0,失败时返回负的 errno。

int file_modified(struct file *file)

处理修改文件时强制执行的 vfs 更改

参数

struct file *file

已修改的文件

描述

当文件被修改时,确保移除特殊文件权限并更新时间设置。

上下文

调用者必须持有文件的 inode 锁。

返回

成功时返回 0,失败时返回负的 errno。

int kiocb_modified(struct kiocb *iocb)

处理修改文件时强制执行的 vfs 更改

参数

struct kiocb *iocb

已修改的 iocb

描述

当文件被修改时,确保移除特殊文件权限并更新时间设置。

上下文

调用者必须持有文件的 inode 锁。

返回

成功时返回 0,失败时返回负的 errno。

void inode_init_owner(struct mnt_idmap *idmap, struct inode *inode, const struct inode *dir, umode_t mode)

根据 posix 标准初始化新 inode 的 uid、gid、mode

参数

struct mnt_idmap *idmap

创建 inode 的挂载的 idmap

struct inode *inode

新的 inode

const struct inode *dir

目录 inode

umode_t mode

新 inode 的模式

描述

如果 inode 是通过 idmapped 挂载创建的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限并初始化 i_uid 和 i_gid。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

bool inode_owner_or_capable(struct mnt_idmap *idmap, const struct inode *inode)

检查当前任务对 inode 的权限

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct inode *inode

正在检查的 inode

描述

如果当前用户在具有映射的 inode 所有者 uid 的命名空间中具有 CAP_FOWNER,或者拥有该文件,则返回 true。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

void inode_dio_wait(struct inode *inode)

等待未完成的 DIO 请求完成

参数

struct inode *inode

要等待的 inode

描述

等待所有挂起的直接 I/O 请求完成,以便我们可以继续进行截断或等效操作。

必须在序列化获取对 i_dio_count 的新引用的锁下调用,通常通过 inode->i_mutex。

struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode)

将 timespec 截断为粒度

参数

struct timespec64 t

Timespec

struct inode *inode

正在更新的 inode

描述

将 timespec 截断为包含 inode 的文件系统支持的粒度。 始终向下舍入。 gran 不得为 0,也不得大于 1 秒(NSEC_PER_SEC 或 10^9 纳秒)。

struct timespec64 inode_set_ctime_current(struct inode *inode)

将 ctime 设置为 current_time

参数

struct inode *inode

inode

描述

将 inode 的 ctime 设置为 inode 的当前值。 返回已分配的当前值。 如果这不是 multigrain inode,则我们将其设置为粗略时间和 floor 值的较晚者。

如果是 multigrain,则我们首先查看粗粒度时间戳是否与已有的时间戳不同。 如果是,则使用它。 否则,获取细粒度时间戳。

之后,尝试将新值交换到 i_ctime_nsec 中。 接受结果 ctime,无论交换结果如何。 如果它已经被替换,则该时间戳晚于早期不可接受的时间戳,因此是可以接受的。

struct timespec64 inode_set_ctime_deleg(struct inode *inode, struct timespec64 update)

尝试更新委托 inode 上的 ctime

参数

struct inode *inode

要更新的 inode

struct timespec64 update

用于设置 ctime 的 timespec64

描述

尝试代表委托持有者原子地更新 ctime。

nfs 服务器可以回调委托的持有者以获取更新的 inode 属性,包括 mtime。 更新 mtime 时,将 ctime 更新为至少等于该值的值。

这可能会与对 inode 的并发更新竞争,在这种情况下,更新将被跳过。

请注意,即使未启用 multigrain 时间戳,这也可以工作,因此在任何一种情况下都会使用它。

bool in_group_or_capable(struct mnt_idmap *idmap, const struct inode *inode, vfsgid_t vfsgid)

检查调用方是否具有 CAP_FSETID 权限

参数

struct mnt_idmap *idmap

inode 中找到的挂载的 idmap

const struct inode *inode

要检查的 inode

vfsgid_t vfsgid

inode 的新/当前 vfsgid

描述

检查 vfsgid 是否在调用方的组列表中,或者调用方是否对 inode 具有 CAP_FSETID 权限。 这可以用于确定是否可以保留 setgid 位或必须删除它。

返回

如果调用方具有足够的权限,则为 true,否则为 false。

umode_t mode_strip_sgid(struct mnt_idmap *idmap, const struct inode *dir, umode_t mode)

处理非目录的 sgid 位

参数

struct mnt_idmap *idmap

创建 inode 的挂载的 idmap

const struct inode *dir

父目录 inode

umode_t mode

要在 dir 中创建的文件的模式

描述

如果新文件的 mode 同时提高了 S_ISGID 和 S_IXGRP 位,并且 dir 提高了 S_ISGID 位,则确保调用方要么在父目录的组中,要么在其用户命名空间中具有 CAP_FSETID 权限,并且对父目录具有权限。 在所有其他情况下,从 mode 中删除 S_ISGID 位。

返回

用于文件的新模式

void make_bad_inode(struct inode *inode)

由于 I/O 错误,将 inode 标记为坏

参数

struct inode *inode

要标记为坏的 Inode

当由于介质或远程网络故障而无法读取 inode 时,此函数会使 inode “损坏”,并导致从此开始对其进行的 I/O 操作失败。

bool is_bad_inode(struct inode *inode)

inode 是否出错

参数

struct inode *inode

要测试的 inode

如果问题中的 inode 已被标记为坏,则返回 true。

void iget_failed(struct inode *inode)

将正在构建的 inode 标记为死并释放它

参数

struct inode *inode

要丢弃的 inode

描述

将正在构建的 inode 标记为死并释放它。

注册和超级块

void deactivate_locked_super(struct super_block *s)

删除对超级块的活动引用

参数

struct super_block *s

要停用的超级块

删除对超级块的活动引用,如果没有其他活动引用,则将其转换为临时引用。 在这种情况下,我们告诉 fs 驱动程序将其关闭并删除我们刚刚获得的临时引用。

调用方持有对超级块的独占锁; 该锁将被释放。

void deactivate_super(struct super_block *s)

删除对超级块的活动引用

参数

struct super_block *s

要停用的超级块

deactivate_locked_super() 的变体,不同之处在于超级块被调用方锁定。 如果我们要删除最终的活动引用,则会在删除之前获取锁。

void retire_super(struct super_block *sb)

防止超级块被重用

参数

struct super_block *sb

要停用的超级块

该函数将超级块标记为在超级块测试中被忽略,这可以防止它被重用于任何新的挂载。 如果超级块具有私有 bdi,它也会注销它,但不会减少超级块的引用计数以防止潜在的竞争。 引用计数由 generic_shutdown_super() 减少。 该函数不能与 generic_shutdown_super() 并发调用。 多次调用该函数是安全的,后续调用无效。

该标记只会影响基于块设备的超级块的重用。 如果使用此函数,其他超级块仍将被标记,但这不会影响它们的可重用性。

void generic_shutdown_super(struct super_block *sb)

用于 ->kill_sb() 的常见助手

参数

struct super_block *sb

要终止的超级块

generic_shutdown_super() 在超级块关闭时执行所有 fs 独立的工作。 典型的 ->kill_sb() 应该从超级块中挑选出所有需要销毁的 fs 特定对象,调用 generic_shutdown_super() 并释放上述对象。 注意:dentry 和 inode _已_得到处理,不需要特定的处理。

调用此函数后,文件系统可能不再更改或重新排列属于此 super_block 的 dentry 集合,也不得更改 dentry 到 inode 的连接。

struct super_block *sget_fc(struct fs_context *fc, int (*test)(struct super_block*, struct fs_context*), int (*set)(struct super_block*, struct fs_context*))

查找或创建超级块

参数

struct fs_context *fc

文件系统上下文。

int (*test)(struct super_block *, struct fs_context *)

比较回调函数

int (*set)(struct super_block *, struct fs_context *)

设置回调函数

描述

创建一个新的超级块或查找一个已存在的超级块。

test 回调函数用于查找匹配的现有超级块。fc 中请求的参数是否被考虑取决于所使用的 test 回调函数。它们甚至可能被完全忽略。

如果匹配到一个现有的超级块,它将被返回,除非

  1. 文件系统上下文 fc 和现有超级块的命名空间不同

  2. 文件系统上下文 fc 已经请求不允许重用现有的超级块

在这两种情况下,都会返回 EBUSY。

如果没有找到匹配项,将分配一个新的超级块并执行基本的初始化(s_type、s_fs_info 和 s_id 将被设置,并且 set 回调函数将被调用),超级块将被发布,并且它将在部分构建的状态下返回,SB_BORN 和 SB_ACTIVE 尚未设置。

返回

成功时,返回一个已存在的或新创建的超级块。

失败时,返回一个错误指针。

struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block*, void*), int (*set)(struct super_block*, void*), int flags, void *data)

查找或创建一个超级块

参数

struct file_system_type *type

超级块所属的文件系统类型

int (*test)(struct super_block *,void *)

比较回调函数

int (*set)(struct super_block *,void *)

设置回调函数

int flags

挂载标志

void *data

传递给每个回调函数的参数

void iterate_supers_type(struct file_system_type *type, void (*f)(struct super_block*, void*), void *arg)

为给定类型的所有超级块调用函数

参数

struct file_system_type *type

文件系统类型

void (*f)(struct super_block *, void *)

要调用的函数

void *arg

传递给函数的参数

扫描超级块列表并调用给定函数,传递锁定的超级块和给定参数。

int get_anon_bdev(dev_t *p)

为没有块设备的文件系统分配一个块设备。

参数

dev_t *p

指向 dev_t 的指针。

描述

不使用真实块设备的文件系统可以调用此函数来分配一个虚拟块设备。

上下文

任何上下文。经常在持有 sb_lock 时调用。

返回

成功时返回 0,如果没有剩余的匿名 bdevs,则返回 -EMFILE,如果内存分配失败,则返回 -ENOMEM。

struct super_block *sget_dev(struct fs_context *fc, dev_t dev)

通过设备号查找或创建超级块

参数

struct fs_context *fc

文件系统上下文。

dev_t dev

设备号

描述

使用提供的设备号查找或创建超级块,该设备号将存储在 fc->sget_key 中。

如果匹配到一个现有的超级块,则将返回该超级块,并增加其引用计数,调用者必须传输或丢弃该引用计数。

如果没有找到匹配项,将分配一个新的超级块并执行基本的初始化(s_type、s_fs_info、s_id、s_dev 将被设置)。超级块将被发布,并且它将在部分构建的状态下返回,SB_BORN 和 SB_ACTIVE 尚未设置。

返回

成功时,返回一个已存在的或新创建的超级块,失败时返回一个错误指针。

失败时返回指针。

int get_tree_bdev_flags(struct fs_context *fc, int (*fill_super)(struct super_block *sb, struct fs_context *fc), unsigned int flags)

基于单个块设备获取超级块

参数

struct fs_context *fc

包含参数的文件系统上下文

int (*fill_super)(struct super_block *sb, struct fs_context *fc)

用于初始化新超级块的辅助函数

unsigned int flags

GET_TREE_BDEV_* 标志

int get_tree_bdev(struct fs_context *fc, int (*fill_super)(struct super_block*, struct fs_context*))

基于单个块设备获取超级块

参数

struct fs_context *fc

包含参数的文件系统上下文

int (*fill_super)(struct super_block *, struct fs_context *)

用于初始化新超级块的辅助函数

int vfs_get_tree(struct fs_context *fc)

获取可挂载的根

参数

struct fs_context *fc

超级块配置上下文。

描述

调用文件系统以获取或创建超级块,然后可以将其用于挂载。文件系统将指向要用于挂载的根的指针放置在 fc->root 中。

int freeze_super(struct super_block *sb, enum freeze_holder who, const void *freeze_owner)

锁定文件系统并强制其进入一致状态

参数

struct super_block *sb

要锁定的超级块

enum freeze_holder who

想要冻结的上下文

const void *freeze_owner

冻结的所有者

描述

同步超级块以确保文件系统一致,并调用文件系统的 freeze_fs。在没有首先解冻文件系统的情况下,后续的调用可能会返回 -EBUSY。

who 应该是:* 如果用户空间想要冻结文件系统,则为 FREEZE_HOLDER_USERSPACE;* 如果内核想要冻结文件系统,则为 FREEZE_HOLDER_KERNEL。* FREEZE_MAY_NEST 是否允许嵌套冻结和解冻请求。

who 参数区分了内核和用户空间尝试冻结文件系统。虽然在任何给定时间都不能有多个内核冻结或多个用户空间冻结生效,但内核和用户空间都可以保持文件系统冻结。文件系统保持冻结状态,直到没有内核或用户空间冻结生效。

一个文件系统可能持有多个设备,因此可以通过块层通过多个块设备冻结文件系统。在这种情况下,通过传递 FREEZE_MAY_NEST 将该请求标记为允许嵌套。文件系统保持冻结状态,直到所有块设备都被解冻。如果在没有 FREEZE_MAY_NEST 的情况下尝试多个冻结,则会返回 -EBUSY。

在此函数期间,sb->s_writers.frozen 经历以下值

SB_UNFROZEN:文件系统正常,所有写入照常进行。

SB_FREEZE_WRITE:文件系统正在被冻结的过程中。应该阻止新的写入,但仍然允许页面错误。我们等待所有写入完成,然后进行到下一个阶段。

SB_FREEZE_PAGEFAULT:冻结继续。现在页面错误也被阻止了,但是内部 fs 线程仍然可以修改文件系统(尽管它们不应该修改新的脏页面或 inode),回写可以运行等等。在等待所有正在运行的页面错误后,我们同步文件系统,这将清理所有脏页面和 inode(当同步运行时,无法创建新的脏页面或 inode)。

SB_FREEZE_FS:文件系统已冻结。现在,所有文件系统修改的内部来源都被阻止(例如,XFS 预分配在 inode 回收时截断)。这通常是通过阻止具有它们并需要此额外保护的文件系统的新事务来实现的。在所有内部写入器完成后,我们调用 ->freeze_fs() 以完成文件系统的冻结。然后我们转换到 SB_FREEZE_COMPLETE 状态。此状态主要用于文件系统验证它们是否不修改冻结的 fs。

sb->s_writers.frozen 受 sb->s_umount 保护。

返回

如果冻结成功,则返回零。如果冻结失败,则返回负错误代码。

如果失败,则返回一个负的错误代码。

int thaw_super(struct super_block *sb, enum freeze_holder who, const void *freeze_owner)
  • 解锁文件系统

参数

struct super_block *sb

要解冻的超级块

enum freeze_holder who

想要冻结的上下文

const void *freeze_owner

冻结的所有者

描述

freeze_super() 之后,如果文件系统上没有剩余的冻结,则解锁文件系统并将其标记为可再次写入。

who 应该是:* 如果用户空间想要解冻文件系统,则为 FREEZE_HOLDER_USERSPACE;* 如果内核想要解冻文件系统,则为 FREEZE_HOLDER_KERNEL。* FREEZE_MAY_NEST 是否允许嵌套冻结和解冻请求。

一个文件系统可能持有多个设备,因此可以通过块层通过多个块设备冻结文件系统。文件系统保持冻结状态,直到所有块设备都被解冻。

文件锁

bool locks_owner_has_blockers(struct file_lock_context *flctx, fl_owner_t owner)

检查是否存在阻塞锁请求

参数

struct file_lock_context *flctx

文件锁上下文

fl_owner_t owner

锁所有者

描述

返回值

trueowner 至少有一个阻塞者 falseowner 没有阻塞者

int locks_delete_block(struct file_lock *waiter)

停止等待文件锁

参数

struct file_lock *waiter

正在等待的锁

lockd/nfsd 需要在处理锁时断开连接。

int posix_lock_file(struct file *filp, struct file_lock *fl, struct file_lock *conflock)

将 POSIX 风格的锁应用于文件

参数

struct file *filp

要应用锁的文件

struct file_lock *fl

要应用的锁

struct file_lock *conflock

如果找到冲突锁,则返回冲突锁的副本的位置。

描述

将 POSIX 风格的锁添加到文件。我们尽可能地合并相邻和重叠的锁。POSIX 锁按所有者任务排序,然后按起始地址排序

请注意,如果使用 FL_EXISTS 参数调用,则调用者可以通过测试返回值是否为 -ENOENT 来确定是否成功释放了锁。

int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)

撤销文件上的所有未完成的租约

参数

struct inode *inode

要返回的文件的 inode

unsigned int mode

O_RDONLY: 仅中断写租约;O_WRONLY 或 O_RDWR: 中断所有租约

unsigned int type

FL_LEASE: 中断租约和委托;FL_DELEG: 仅中断委托

break_lease(为了速度内联)已经检查过此文件上至少存在某种类型的锁(可能是租约)。租约在调用 open() 或 truncate() 时中断。除非您在 open() 中指定了 O_NONBLOCK,否则此函数可以休眠。

void lease_get_mtime(struct inode *inode, struct timespec64 *time)

使用独占租约更新 inode 的修改时间

参数

struct inode *inode

inode

struct timespec64 *time

指向包含上次修改时间的 timespec 的指针

描述

这是为了强制 NFS 客户端刷新具有独占租约的文件的缓存。理由是如果有人拥有独占租约,那么他们可能会修改它。

int generic_setlease(struct file *filp, int arg, struct file_lease **flp, void **priv)

在打开的文件上设置租约

参数

struct file *filp

文件指针

int arg

要获得的租约的类型

struct file_lease **flp

输入 - 要使用的 file_lock,输出 - 插入的 file_lock

void **priv

lm_setup 的私有数据(如果 lm_setup 不需要,则可以为 NULL)

(输入) flp->fl_lmops->lm_break 函数是 break_lease() 所必需的。

int vfs_setlease(struct file *filp, int arg, struct file_lease **lease, void **priv)

在打开的文件上设置租约

参数

struct file *filp

文件指针

int arg

要获得的租约的类型

struct file_lease **lease

添加租约时要使用的 file_lock

void **priv

添加租约时 lm_setup 的私有信息(如果 lm_setup 不需要,则可以为 NULL)

描述

调用此函数以在文件上建立租约。 “lease”参数不用于 F_UNLCK 请求,可以为 NULL。 对于设置或更改现有租约的命令,必须设置 (*lease)->fl_lmops->lm_break 操作; 如果没有,此函数将返回 -ENOLCK(并生成一个看起来很可怕的堆栈跟踪)。

“priv”指针直接传递给 lm_setup 函数,并且按原样传递。 如果 lm_setup 操作不需要,则可以为 NULL。

int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)

将锁应用于 inode

参数

struct inode *inode

要应用到的文件的 inode

struct file_lock *fl

要应用的锁

描述

将 POSIX 或 FLOCK 样式的锁请求应用于 inode。

int vfs_test_lock(struct file *filp, struct file_lock *fl)

测试文件字节范围锁

参数

struct file *filp

要测试锁定的文件

struct file_lock *fl

要测试的锁; 也用于保存结果

描述

失败时返回 -ERRNO。 通过将 conf->fl_type 设置为 F_UNLCK 以外的值来指示是否存在冲突锁。

int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)

文件字节范围锁

参数

struct file *filp

要应用锁的文件

unsigned int cmd

锁定操作的类型 (F_SETLK、F_GETLK 等)

struct file_lock *fl

要应用的锁

struct file_lock *conf

如果找到冲突锁,则返回冲突锁的副本的位置。

描述

不关心冲突锁的调用者可以将 NULL 作为最后一个参数传递。

如果文件系统定义了一个私有的 ->lock() 方法,那么 conf 将保持不变;因此,关心的调用者应将其初始化为一些可接受的默认值。

为了避免阻塞需要获取 POSIX 锁的内核守护进程(例如 lockd),如果设置了 lm_grant,则 ->lock() 接口可能会异步返回,在底层文件系统授予或拒绝锁之前。(并且只有在这种情况下) 此外,需要设置 export_operations 标志中的 EXPORT_OP_ASYNC_LOCK。

期望 ->lock() 异步返回的调用者将只使用 F_SETLK,而不是 F_SETLKW; 如果(并且只有在这种情况下)该请求用于阻塞锁,它们将设置 FL_SLEEP。 当 ->lock() 异步返回时,它必须返回 FILE_LOCK_DEFERRED,并在锁请求完成时调用 ->lm_grant()。 如果请求用于非阻塞锁,则文件系统应返回 FILE_LOCK_DEFERRED,然后尝试获取锁并使用结果调用回调例程。 如果请求超时,则回调例程将返回一个非零的返回码,并且文件系统应释放该锁。 文件系统还有责任在授予锁时保持相应的 posix 锁,以便 VFS 可以找出哪些锁在本地持有,并在需要时进行正确的锁清理。 在以 FILE_LOCK_DEFERRED 返回码返回到调用者之前,底层文件系统不得删除内核锁或调用 ->lm_grant()。

int vfs_cancel_lock(struct file *filp, struct file_lock *fl)

文件字节范围取消阻塞锁定

参数

struct file *filp

要应用取消阻塞的文件

struct file_lock *fl

要取消阻塞的锁

描述

锁管理器使用此功能来取消阻塞的请求

bool vfs_inode_has_locks(struct inode *inode)

是否在 inode 上持有任何文件锁?

参数

struct inode *inode

要检查锁的 inode

描述

如果当前在 inode 上设置了任何 FL_POSIX 或 FL_FLOCK 锁,则返回 true。

int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)

将 POSIX 风格的锁应用于文件

参数

struct inode *inode

应向其应用锁请求的文件的 inode

struct file_lock *fl

要应用的锁

描述

将 POSIX 样式的锁请求应用于 inode。

int fcntl_getlease(struct file *filp)

查询当前活动的租约是什么

参数

struct file *filp

文件

此函数返回的值将是以下之一(如果未挂起任何租约中断)

F_RDLCK 指示持有共享租约。

F_WRLCK 指示持有独占租约。

F_UNLCK 指示未持有任何租约。

(如果挂起租约中断)

F_RDLCK 指示独占租约需要

更改为共享租约(或删除)。

F_UNLCK 指示需要删除租约。

XXX:sfr & willy 对是否应将 F_INPROGRESS 返回给用户空间存在分歧。

int check_conflicting_open(struct file *filp, const int arg, int flags)

查看给定文件是否指向一个现有的打开的 inode,该 inode 会与所需的租约冲突。

参数

struct file *filp

要检查的文件

const int arg

我们正在尝试获得的租约的类型

int flags

当前锁定标志

描述

检查此文件上是否存在现有的打开的 fd,该 fd 会与我们尝试设置的租约冲突。

int fcntl_setlease(unsigned int fd, struct file *filp, int arg)

在打开的文件上设置租约

参数

unsigned int fd

打开的文件描述符

struct file *filp

文件指针

int arg

要获得的租约的类型

调用此 fcntl 以在文件上建立租约。 请注意,您还需要调用 F_SETSIG 以在租约中断时收到信号。

int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl)

将 FLOCK 样式的锁应用于文件

参数

struct inode *inode

要应用到的文件的 inode

struct file_lock *fl

要应用的锁

描述

将 FLOCK 样式的锁请求应用于 inode。

long sys_flock(unsigned int fd, unsigned int cmd)
  • flock() 系统调用。

参数

unsigned int fd

要锁定的文件描述符。

unsigned int cmd

要应用的锁的类型。

FL_FLOCK 样式的锁应用于打开的文件描述符。 cmd 可以是以下之一

  • LOCK_SH -- 共享锁。

  • LOCK_EX -- 独占锁。

  • LOCK_UN -- 删除现有锁。

  • LOCK_MAND -- “强制” flock。(已弃用)

LOCK_MAND 支持已从内核中删除。

pid_t locks_translate_pid(struct file_lock_core *fl, struct pid_namespace *ns)

将 file_lock 的 fl_pid 编号转换为命名空间

参数

struct file_lock_core *fl

应该转换其 fl_pid 的 file_lock

struct pid_namespace *ns

应该将 pid 转换成的命名空间

描述

用于将 fl_pid 转换为命名空间虚拟 pid 编号

其他函数

void mpage_readahead(struct readahead_control *rac, get_block_t get_block)

针对页面启动读取

参数

struct readahead_control *rac

描述要读取的页面。

get_block_t get_block

文件系统的块映射器函数。

描述

此函数遍历页面和每个页面中的块,构建和发出大型 BIO。

如果发生任何不寻常的事情,例如

  • 遇到一个带有缓冲区的页面

  • 在孔之后遇到一个没有孔的页面

  • 遇到一个带有非连续块的页面

然后,此代码只是放弃并调用基于 buffer_head 的读取函数。 它可以处理在末尾有孔的页面 - 这是一种常见情况:blocksize < PAGE_SIZE 设置上的文件结尾。

BH_Boundary 解释

存在一个问题。 mpage 读取代码组装多个页面,获取它们的所有磁盘映射,然后提交它们。 这很好,但是获取磁盘映射可能需要 I/O。 例如,读取间接块。

因此,读取 ext2 文件的前 16 个块的 mpage 将导致按以下顺序提交 I/O

12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16

因为必须读取间接块才能获取块 13、14、15、16 的映射。 显然,这会影响性能。

因此,我们所做的是允许文件系统的 get_block() 函数在映射块 11 时设置 BH_Boundary。 BH_Boundary 说:此块之后的块的映射将需要针对可能与此块接近的块进行 I/O。 因此,您应该推送当前已累积的 I/O。

所有这些都会导致按正确的顺序发出磁盘请求。

int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block)

遍历给定地址空间的脏页列表并对所有页执行 writepage()

参数

struct address_space *mapping

要写入的地址空间结构

struct writeback_control *wbc

*wbc->nr_to_write 中减去已写入页面的数量

get_block_t get_block

文件系统的块映射函数。

描述

这是一个库函数,实现了 writepages() address_space_operation。

int generic_permission(struct mnt_idmap *idmap, struct inode *inode, int mask)

检查类 Posix 文件系统上的访问权限

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *inode

要检查访问权限的 inode

int mask

要检查的权限(MAY_READMAY_WRITEMAY_EXECMAY_NOT_BLOCK ...)

描述

用于检查文件上的读/写/执行权限。我们使用 "fsuid" 来实现这一点,允许我们在不更改用于其他事物的 "normal" uid 的情况下,为文件系统访问设置任意权限。

generic_permission 知道 rcu-walk。 如果无法满足 rcu-walk 请求(例如,需要阻塞或过于复杂),则返回 -ECHILD。 然后将在 ref-walk 模式下再次调用它。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

int inode_permission(struct mnt_idmap *idmap, struct inode *inode, int mask)

检查对给定 inode 的访问权限

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *inode

要检查权限的 Inode

int mask

要检查的权限(MAY_READMAY_WRITEMAY_EXEC

描述

检查 inode 上的读/写/执行权限。我们使用 fs[ug]id 来实现这一点,允许我们在不更改用于其他事物的“normal”UID 的情况下,为文件系统访问设置任意权限。

在检查 MAY_APPEND 时,mask 中也必须设置 MAY_WRITE。

void path_get(const struct path *path)

获取对路径的引用

参数

const struct path *path

要获取引用的路径

描述

给定一个路径,递增对 dentry 和 vfsmount 的引用计数。

void path_put(const struct path *path)

释放对路径的引用

参数

const struct path *path

要释放引用的路径

描述

给定一个路径,递减对 dentry 和 vfsmount 的引用计数。

int vfs_path_parent_lookup(struct filename *filename, unsigned int flags, struct path *parent, struct qstr *last, int *type, const struct path *root)

查找相对于 dentry-vfsmount 对的父路径

参数

struct filename *filename

文件名结构

unsigned int flags

查找标志

struct path *parent

指向要填充的 struct path 的指针

struct qstr *last

最后一个组件

int *type

最后一个组件的类型

const struct path *root

指向基本目录的 struct path 的指针

int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, const char *name, unsigned int flags, struct path *path)

查找相对于 dentry-vfsmount 对的文件路径

参数

struct dentry *dentry

指向基本目录的 dentry 的指针

struct vfsmount *mnt

指向基本目录的 vfs mount 的指针

const char *name

指向文件名的指针

unsigned int flags

查找标志

struct path *path

指向要填充的 struct path 的指针

struct dentry *try_lookup_noperm(struct qstr *name, struct dentry *base)

文件系统帮助程序,用于查找单个路径名组件

参数

struct qstr *name

qstr 存储要查找的路径名组件

struct dentry *base

要从中查找的基本目录

描述

按名称在 dcache 中查找 dentry,如果当前不存在,则返回 NULL。 该函数不尝试创建 dentry,如果找到 dentry,也不会尝试重新验证它。

请注意,此例程纯粹是文件系统使用的帮助程序,不应由通用代码调用。 它不进行任何权限检查。

不需要持有锁 - 只需要对 base 的计数引用。

struct dentry *lookup_noperm(struct qstr *name, struct dentry *base)

文件系统帮助程序,用于查找单个路径名组件

参数

struct qstr *name

qstr 存储要查找的路径名组件

struct dentry *base

要从中查找的基本目录

描述

请注意,此例程纯粹是文件系统使用的帮助程序,不应由通用代码调用。 它不进行任何权限检查。

调用者必须持有 base->i_mutex。

struct dentry *lookup_one(struct mnt_idmap *idmap, struct qstr *name, struct dentry *base)

查找单个路径名组件

参数

struct mnt_idmap *idmap

执行查找的挂载的 idmap

struct qstr *name

qstr 存储要查找的路径名组件

struct dentry *base

要从中查找的基本目录

描述

这可以用于内核文件系统客户端,例如文件服务器。

调用者必须持有 base->i_mutex。

struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap, struct qstr *name, struct dentry *base)

查找单个路径名组件

参数

struct mnt_idmap *idmap

执行查找的挂载的 idmap

struct qstr *name

qstr olding 要查找的路径名组件

struct dentry *base

要从中查找的基本目录

描述

这可以用于内核文件系统客户端,例如文件服务器。

与 lookup_one 不同,它应该在没有持有父 i_rwsem 的情况下调用,并且如果需要,它将获取 i_rwsem 本身。

struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap, struct qstr *name, struct dentry *base)

查找单个路径名组件

参数

struct mnt_idmap *idmap

执行查找的挂载的 idmap

struct qstr *name

qstr 存储要查找的路径名组件

struct dentry *base

要从中查找的基本目录

描述

如果为负数,此帮助程序将产生 ERR_PTR(-ENOENT)。 帮助程序返回已知的正数或 ERR_PTR()。 这是大多数用户想要的。

请注意,带有未锁定父级的已固定的负数_可以_随时变为正数,因此 lookup_one_unlocked() 的调用者需要非常小心; 已固定的正数具有 >d_inode 稳定,因此这一个避免了此类问题。

这可以用于内核文件系统客户端,例如文件服务器。

该帮助程序应在未持有 i_rwsem 的情况下调用。

struct dentry *lookup_noperm_unlocked(struct qstr *name, struct dentry *base)

文件系统帮助程序,用于查找单个路径名组件

参数

struct qstr *name

要查找的路径名组件

struct dentry *base

要从中查找的基本目录

描述

请注意,此例程纯粹是文件系统使用的帮助程序,不应由通用代码调用。 它不进行任何权限检查。

lookup_noperm() 不同,它应该在没有持有父 i_rwsem 的情况下调用,并且如果需要,它将获取 i_rwsem 本身。

try_lookup_noperm() 不同,如果 dentry 已经存在,它重新验证 dentry。

int vfs_create(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, bool want_excl)

创建新文件

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *dir

父目录的 inode

struct dentry *dentry

子文件的 dentry

umode_t mode

子文件的模式

bool want_excl

该文件是否必须尚不存在

描述

创建一个新文件。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

struct file *kernel_tmpfile_open(struct mnt_idmap *idmap, const struct path *parentpath, umode_t mode, int open_flag, const struct cred *cred)

为内核内部使用打开一个 tmpfile

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

const struct path *parentpath

基本目录的路径

umode_t mode

新 tmpfile 的模式

int open_flag

flags

const struct cred *cred

用于打开的凭据

描述

创建并打开一个临时文件。该文件未在 nr_files 中进行核算,因此这仅用于内核内部使用,并且不得安装到文件表等中。

int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)

创建设备节点或文件

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *dir

父目录的 inode

struct dentry *dentry

子设备节点的 dentry

umode_t mode

子设备节点的模式

dev_t dev

要创建的设备的设备编号

描述

创建一个设备节点或文件。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode)

创建目录,如果可能,返回正确的dentry

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *dir

父目录的 inode

struct dentry *dentry

子目录的dentry

umode_t mode

子目录的模式

描述

创建一个目录。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

如果文件系统不使用**dentry**,而是将其保留为负值或取消散列,并可能拼接一个不同的dentry并返回,则原始dentry将被dput(),并返回备用dentry。

如果发生错误,则dentry将被dput(),并返回一个ERR_PTR()

int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry)

删除目录

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *dir

父目录的 inode

struct dentry *dentry

子目录的dentry

描述

删除一个目录。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

取消链接一个文件系统对象

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *dir

父目录

struct dentry *dentry

受害者

struct inode **delegated_inode

如果 inode 被委托,则返回受害者的 inode。

描述

调用者必须持有 dir->i_mutex。

如果 vfs_unlink 发现一个委托,它将返回 -EWOULDBLOCK 并在 delegated_inode 中返回一个指向 inode 的引用。然后,调用者应该在该 inode 上打破委托并重试。由于打破委托可能需要很长时间,因此调用者应该在这样做之前释放 dir->i_mutex。

或者,调用者可以为 delegated_inode 传递 NULL。这可能适用于期望底层文件系统不被 NFS 导出的调用者。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

创建符号链接

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *dir

父目录的 inode

struct dentry *dentry

子符号链接文件的dentry

const char *oldname

要链接到的文件的名称

描述

创建一个符号链接。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

创建一个新链接

参数

struct dentry *old_dentry

要链接的对象

struct mnt_idmap *idmap

挂载的 idmap

struct inode *dir

新的父目录

struct dentry *new_dentry

在哪里创建新的链接

struct inode **delegated_inode

返回需要委托中断的 inode

描述

调用者必须持有 dir->i_mutex

如果 vfs_link 在需要中断的待链接文件上发现委托,它将返回 -EWOULDBLOCK 并在 delegated_inode 中返回一个指向 inode 的引用。然后,调用者应该中断委托并重试。由于打破委托可能需要很长时间,因此调用者应该在这样做之前释放 i_mutex。

或者,调用者可以为 delegated_inode 传递 NULL。这可能适用于期望底层文件系统不被 NFS 导出的调用者。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

int vfs_rename(struct renamedata *rd)

重命名一个文件系统对象

参数

struct renamedata *rd

指向struct renamedata信息的指针

描述

调用者必须持有多个互斥锁--请参见 lock_rename()。

如果 vfs_rename 在源或目标上发现需要中断的委托,它将返回 -EWOULDBLOCK 并在 delegated_inode 中返回一个指向 inode 的引用。然后,调用者应该中断委托并重试。由于打破委托可能需要很长时间,因此调用者应该在这样做之前释放所有锁。

或者,调用者可以为 delegated_inode 传递 NULL。这可能适用于期望底层文件系统不被 NFS 导出的调用者。

所有命名空间操作中最糟糕的 - 重命名目录。“变态”甚至不足以形容它。UCB 中的某个人度过了一段糟糕的旅程... 问题

  1. 我们可以进入循环创建。

  2. 竞争潜力 - 两个无辜的重命名可以一起创建一个循环。这就是 4.4BSD 搞砸的地方。目前的修复:sb->s_vfs_rename_mutex 上的序列化。我们可能会更准确,但那是另一个故事。

  3. 我们可能必须锁定多达 _四个_ 对象 - 父目录和受害者(如果存在),以及源(如果它是一个非目录或移动到不同父目录的子目录)。而且是在我们获取父母的 ->i_mutex 之后(在此之前我们不知道目标是否存在)。解决方案:尝试在 inode 的锁定顺序方面变得聪明。我们依赖于树拓扑只能在 ->s_vfs_rename_mutex _和_ 我们移动的对象的父目录将被锁定的事实。因此,我们可以按树对目录进行排序(祖先优先),并将所有非目录排在它们之后。这之所以有效,是因为除了重命名之外的每个人都执行“锁定父目录,查找,锁定子目录”,并且重命名在 ->s_vfs_rename_mutex 下。但是,它依赖于这样一个假设:任何具有 ->lookup() 的对象都只有一个 dentry。如果“混合”对象将来出现,我们最好确保它们没有 link(2)。

  4. 从 fhandle 到 dentry 的转换可能会在错误的时刻发生 - 当我们删除目标时。解决方案:我们必须在 fhandle_to_dentry 代码中获取 ->i_mutex。[FIXME - 当前的 nfsfh.c 依赖于父母的 ->i_mutex,这虽然有效,但会导致一些真正过度的锁定]。

将符号链接主体复制到用户空间缓冲区

参数

struct dentry *dentry

要在其上获取符号链接的 dentry

char __user *buffer

用户内存指针

int buflen

缓冲区大小

描述

不接触 atime。如有必要,这取决于调用者

不调用安全钩子。

获取符号链接主体

参数

struct dentry *dentry

要在其上获取符号链接的 dentry

struct delayed_call *done

调用者需要使用它来释放返回的数据

描述

在提供的 inode 上调用安全钩子和 i_op->get_link()。

它不接触 atime。如有必要,这取决于调用者。

不适用于“特殊”符号链接,如 /proc/$$/fd/N

get_link inode_operation 的一个实现。

参数

struct dentry *dentry

作为符号链接的目录条目。

struct inode *inode

符号链接的 inode。

struct delayed_call *callback

用于删除对符号链接的引用。

描述

将其符号链接存储在页面缓存中的文件系统应使用此方法来实现其 inode_operations 的 get_link() 成员。

返回

指向以 NUL 结尾的符号链接的指针。

删除对符号链接的引用。

参数

void *arg

包含符号链接的区域。

描述

这是 page_get_link() 内部使用的。导出它是为了供需要实现 page_get_link() 变体本身的文件系统使用。尽管表面上对称,但使用 page_get_link() 的文件系统不需要调用 page_put_link()

参数虽然具有 void 指针类型,但必须是指向从页面缓存中检索的区域的指针。delayed_call 基础设施用于在调用者完成符号链接后删除引用计数。

void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf)

重新初始化一个 bio

参数

struct bio *bio

要重置的 bio

struct block_device *bdev

要使用 bio 的块设备

blk_opf_t opf

bio 的操作和标志

描述

在调用 bio_reset() 之后,**bio** 将处于与 bio bio_alloc_bioset() 返回的全新分配的 bio 相同的状态 - 唯一保留的字段是由 bio_alloc_bioset() 初始化的字段。请参阅 struct bio 中的注释。

void bio_chain(struct bio *bio, struct bio *parent)

链式 bio 完成

参数

struct bio *bio

目标 bio

struct bio *parent

**bio** 的父 bio

描述

当 **bio** 完成时,不会调用调用者的 bi_end_io - 相反,在 **parent** 和 **bio** 都完成之前,不会调用 **parent** 的 bi_end_io;链接的 bio 也将在完成时被释放。

调用者不得在 **bio** 中设置 bi_private 或 bi_end_io。

struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, blk_opf_t opf, gfp_t gfp_mask, struct bio_set *bs)

为 I/O 分配一个 bio

参数

struct block_device *bdev

为其分配 bio 的块设备(可以为 NULL

unsigned short nr_vecs

要预分配的 bvecs 的数量

blk_opf_t opf

bio 的操作和标志

gfp_t gfp_mask

提供给 slab 分配器的 GFP_* 掩码

struct bio_set *bs

要从中分配的 bio_set。

描述

从 **bs** 中的内存池分配一个 bio。

如果设置了 __GFP_DIRECT_RECLAIM,则 bio_alloc 将始终能够分配一个 bio。这是由于内存池保证。为了使这项工作能够正常进行,调用者绝不能一次从通用池中分配超过 1 个 bio。需要分配超过 1 个 bio 的调用者必须始终在尝试分配新 bio 之前提交先前分配的 bio 以进行 IO。否则可能会导致内存压力下的死锁。

请注意,在 submit_bio_noacct() 下运行时(即任何块驱动程序),bio 不会被提交,直到您返回之后 - 请参见 submit_bio_noacct() 中的代码,该代码将递归转换为迭代,以防止堆栈溢出。

这通常意味着在 submit_bio_noacct() 下分配多个 bio 容易发生死锁,但我们有死锁避免代码,该代码从救援线程重新提交任何被阻止的 bio。

但是,我们不保证从其他内存池进行分配能够取得进展。应避免在 submit_bio_noacct() 下从同一内存池进行多次分配 - 而应使用 bio_set 的 front_pad 进行每个 bio 的分配。

返回

成功时指向新 bio 的指针,失败时为 NULL。

struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)

kmalloc 一个 bio

参数

unsigned short nr_vecs

要分配的 bio_vecs 的数量

gfp_t gfp_mask

提供给 slab 分配器的 GFP_* 掩码

描述

使用 kmalloc 分配一个 bio(包括 bvecs)。在使用前,必须使用 bio_init() 初始化 bio。要释放从此函数返回的 bio,在使用 bio_uninit() 之后使用 kfree()。可以通过在再次调用 bio_init() 之前调用 bio_uninit() 来重用从此函数返回的 bio。

请注意,与 bio_alloc() 或 bio_alloc_bioset() 不同,从此函数分配的内存没有 mempool 支持,可能会失败。不要在文件系统 I/O 路径中使用此函数进行分配。

返回

成功时指向新 bio 的指针,失败时为 NULL。

void bio_put(struct bio *bio)

释放对 bio 的引用

参数

struct bio *bio

要释放引用的 bio

描述

释放对 struct bio 的引用,这个 bio 可以是你通过 bio_alloc、bio_get 或 bio_clone_* 获取的。对 bio 的最后一次 put 操作将会释放它。

struct bio *bio_alloc_clone(struct block_device *bdev, struct bio *bio_src, gfp_t gfp, struct bio_set *bs)

克隆一个 bio,该 bio 共享原始 bio 的 biovec

参数

struct block_device *bdev

要克隆到的 block_device

struct bio *bio_src

要克隆的 bio

gfp_t gfp

分配优先级

struct bio_set *bs

要从中分配的 bio_set

描述

分配一个新的 bio,它是 bio_src 的克隆。调用者拥有返回的 bio,但不拥有它指向的实际数据。

调用者必须确保在 bio_src 之前不要释放返回的 bio。

int bio_init_clone(struct block_device *bdev, struct bio *bio, struct bio *bio_src, gfp_t gfp)

克隆一个 bio,该 bio 共享原始 bio 的 biovec

参数

struct block_device *bdev

要克隆到的 block_device

struct bio *bio

要克隆到的 bio

struct bio *bio_src

要克隆的 bio

gfp_t gfp

分配优先级

描述

在调用者提供的内存中初始化一个新的 bio,它是 bio_src 的克隆。调用者拥有返回的 bio,但不拥有它指向的实际数据。

调用者必须确保在 bio 之前不要释放 bio_src

void __bio_add_page(struct bio *bio, struct page *page, unsigned int len, unsigned int off)

将页面添加到新段中的 bio

参数

struct bio *bio

目标 bio

struct page *page

要添加的起始页

unsigned int len

要添加的数据的长度,可能跨越多个页面

unsigned int off

数据相对于 page 的偏移量,可能跨越多个页面

描述

page + off 处的数据作为新的 bvec 添加到 bio。调用者必须确保 bio 有足够的空间容纳另一个 bvec。

void bio_add_virt_nofail(struct bio *bio, void *vaddr, unsigned len)

将直接内核映射中的数据添加到 bio

参数

struct bio *bio

目标 bio

void *vaddr

要添加的数据

unsigned len

要添加的数据的长度,可能跨越多个页面

描述

vaddr 处的数据添加到 bio。调用者必须确保有一个段可用于添加的数据。不会执行与现有段的合并。

int bio_add_page(struct bio *bio, struct page *page, unsigned int len, unsigned int offset)

尝试将页面添加到 bio

参数

struct bio *bio

目标 bio

struct page *page

要添加的起始页

unsigned int len

vec 条目长度,可能跨越多个页面

unsigned int offset

vec 条目相对于 page 的偏移量,可能跨越多个页面

尝试将页面添加到 bio_vec maplist。只有当 bio->bi_vcnt == bio->bi_max_vecs 或它是克隆的 bio 时,此操作才会失败。

bool bio_add_folio(struct bio *bio, struct folio *folio, size_t len, size_t off)

尝试将 folio 的一部分添加到 bio。

参数

struct bio *bio

要添加到的 BIO。

struct folio *folio

要添加的 Folio。

size_t len

要从 folio 添加多少字节。

size_t off

要添加的此 folio 中的第一个字节。

描述

使用 folio 的文件系统可以调用此函数,而不是为 folio 中的每个页面调用 bio_add_page()。如果 off 大于 PAGE_SIZE,则此函数可以创建一个 bio_vec,它从 bv_page 之后的页面开始。BIO 不支持 4GiB 或更大的 folio。

返回

添加是否成功。

unsigned int bio_add_vmalloc_chunk(struct bio *bio, void *vaddr, unsigned len)

将 vmalloc 块添加到 bio

参数

struct bio *bio

目标 bio

void *vaddr

要添加的 vmalloc 地址

unsigned len

要添加的数据的总长度(以字节为单位)

描述

将从 vaddr 开始的数据添加到 bio 并返回已添加的字节数。这可能小于最初要求的数量。如果无法将数据添加到 bio,则返回 0。

此 helper 函数为添加的范围调用 flush_kernel_vmap_range()。对于读取,调用者仍然需要在完成处理程序中手动调用 invalidate_kernel_vmap_range()。

bool bio_add_vmalloc(struct bio *bio, void *vaddr, unsigned int len)

将 vmalloc 区域添加到 bio

参数

struct bio *bio

目标 bio

void *vaddr

要添加的 vmalloc 地址

unsigned int len

要添加的数据的总长度(以字节为单位)

描述

将从 vaddr 开始的数据添加到 bio。如果成功,则返回 true,如果 bio 没有足够的空间容纳有效负载,则返回 false

此 helper 函数为添加的范围调用 flush_kernel_vmap_range()。对于读取,调用者仍然需要在完成处理程序中手动调用 invalidate_kernel_vmap_range()。

int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)

将用户或内核页面添加到 bio

参数

struct bio *bio

要添加页面的 bio

struct iov_iter *iter

描述要添加区域的 iov 迭代器

描述

这需要一个指向用户内存的迭代器,或者一个指向内核页面(BVEC 迭代器)的迭代器。 如果我们正在添加用户页面,我们会固定它们并将它们映射到内核中。 在 IO 完成时,调用者应该 put 那些页面。 对于基于 bvec 的迭代器,bio_iov_iter_get_pages() 使用提供的 bvecs 而不是复制它们。 因此,任何发出基于 kiocb 的 IO 的人都需要确保 bvecs 和页面保持引用状态,直到提交的 I/O 通过调用 ->ki_complete() 完成,或者返回一个错误(除了 -EIOCBQUEUED)。 调用者需要在 IO 完成时检查 bio 是否标记了 BIO_NO_PAGE_REF。 如果没有,则应该释放页面。

该函数尝试但不能保证固定尽可能多的页面,这些页面可以放入 bio 中,或者在 iter 中请求,无论哪个更小。 如果 MM 在固定请求的页面时遇到错误,它会停止。 仅当无法固定 0 个页面时,才会返回错误。

int submit_bio_wait(struct bio *bio)

提交一个 bio,并等待它完成

参数

struct bio *bio

描述 I/O 的 struct bio

描述

围绕 submit_bio() 的简单包装器。 成功时返回 0,失败时返回来自 bio_endio() 的错误。

警告:与通常使用 submit_bio() 的方式不同,此函数不会导致 bio 引用被消耗。 调用者必须自行释放引用。

int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, size_t len, enum req_op op)

同步读取到/写入到内核映射

参数

struct block_device *bdev

要访问的块设备

sector_t sector

要访问的扇区

void *data

要读取/写入的数据

size_t len

要读取/写入的长度(以字节为单位)

enum req_op op

操作(例如,REQ_OP_READ/REQ_OP_WRITE)

描述

bdev 执行同步 I/O 以处理 data/lendata 必须位于内核直接映射中,而不是 vmalloc 地址。

void bio_copy_data(struct bio *dst, struct bio *src)

将数据缓冲区的内容从一个 bio 复制到另一个 bio

参数

struct bio *dst

目标 bio

struct bio *src

源 bio

描述

当到达 srcdst 的末尾时停止 - 即,复制 min(src->bi_size, dst->bi_size) 字节(或 bio 列表的等效字节数)。

void bio_endio(struct bio *bio)

结束 bio 上的 I/O

参数

struct bio *bio

bio

描述

bio_endio() 将结束整个 bio 上的 I/O。 bio_endio() 是结束 bio 上的 I/O 的首选方式。 除非他们拥有 bio 并因此知道它具有 end_io 函数,否则任何人都不能直接在 bio 上调用 bi_end_io()。

可以在使用 bio_chain() 链接的 bio 上多次调用 bio_endio()。 ->bi_end_io() 函数只会在最后一次调用。

struct bio *bio_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs)

拆分一个 bio

参数

struct bio *bio

bio 分割

int sectors

bio 前面分割的扇区数

gfp_t gfp

gfp 掩码

struct bio_set *bs

用于分配的 bio 集

描述

分配并返回一个新的 bio,它表示从 bio 开始的 sectors 扇区,并更新 bio 以表示剩余的扇区。

除非这是一个丢弃请求,否则新分配的 bio 将指向 bio 的 bi_io_vec。调用者有责任确保在拆分 bio 之前,biobs 都不会被释放。

void bio_trim(struct bio *bio, sector_t offset, sector_t size)

修剪 bio

参数

struct bio *bio

要修剪的 bio

sector_t offset

要从 bio 前面修剪的扇区数

sector_t size

我们希望将 bio 修剪到的尺寸,以扇区为单位

描述

此函数通常用于克隆并以部分形式提交给底层设备的 bio。

int bioset_init(struct bio_set *bs, unsigned int pool_size, unsigned int front_pad, int flags)

初始化 bio_set

参数

struct bio_set *bs

要初始化的池

unsigned int pool_size

要在内存池中缓存的 bio 和 bio_vecs 的数量

unsigned int front_pad

要在返回的 bio 前面分配的字节数

int flags

修改行为的标志,当前为 BIOSET_NEED_BVECSBIOSET_NEED_RESCUER

描述

设置一个 bio_set 以与 bio_alloc_bioset 一起使用。允许调用者请求在 bio 前面分配一定数量的字节。 前端填充分配对于将 bio 嵌入到另一个结构中非常有用,以避免分配额外的与 bio 一起使用的数据。 请注意,bio 必须始终嵌入到该结构的末尾,否则会严重损坏。 如果在 flags 中设置了 BIOSET_NEED_BVECS,则将分配一个单独的池来分配 iovec。 例如,对于 bio_init_clone(),不需要此池。 如果设置了 BIOSET_NEED_RESCUER,则会创建一个工作队列,该队列可用于在内存池空间不足时调度排队的请求。

int seq_open(struct file *file, const struct seq_operations *op)

初始化顺序文件

参数

struct file *file

我们初始化的文件

const struct seq_operations *op

描述序列的方法表

seq_open() 设置 file,将其与由 op 描述的序列相关联。 op->start() 设置迭代器并返回序列的第一个元素。 op->stop() 关闭它。 op->next() 返回序列的下一个元素。 op->show() 将元素打印到缓冲区中。 如果出现错误,->start() 和 ->next() 返回 ERR_PTR(错误)。 在序列的末尾,它们返回 NULL。 ->show() 在成功时返回 0,在出错时返回负数。 返回 SEQ_SKIP 表示“放弃此元素并继续”。

注意

seq_open() 将分配一个 struct seq_file 并将其存储在

file->private_data 中。 不应修改此指针。

ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)

顺序文件的 ->read() 方法。

参数

struct file *file

要从中读取的文件

char __user *buf

要读取到的缓冲区

size_t size

要读取的最大字节数

loff_t *ppos

文件中的当前位置

现成的 ->f_op->read()

loff_t seq_lseek(struct file *file, loff_t offset, int whence)

顺序文件的 ->llseek() 方法。

参数

struct file *file

有问题的文件

loff_t offset

新位置

int whence

0 表示绝对位置,1 表示相对位置

现成的 ->f_op->llseek()

int seq_release(struct inode *inode, struct file *file)

释放与顺序文件关联的结构。

参数

struct inode *inode

它的 inode

struct file *file

有问题的文件

释放与顺序文件关联的结构; 如果您没有要销毁的私有数据,则可以用作 ->f_op->release()。

void seq_escape_mem(struct seq_file *m, const char *src, size_t len, unsigned int flags, const char *esc)

将数据打印到缓冲区中,转义某些字符

参数

struct seq_file *m

目标缓冲区

const char *src

源缓冲区

size_t len

源缓冲区的大小

unsigned int flags

要传递给 string_escape_mem() 的标志

const char *esc

需要转义的字符集

描述

将数据放入缓冲区,将给定类(由 flagsesc 定义)中每个字符的出现替换为可打印的转义序列。

使用 seq_has_overflowed() 检查错误。

char *mangle_path(char *s, const char *p, const char *esc)

处理并将路径复制到缓冲区开头

参数

char *s

缓冲区开始

const char *p

上述缓冲区中路径的开头

const char *esc

需要转义的字符集

将路径从 p 复制到 s,将 esc 中每个字符的出现替换为常用的八进制转义。 返回指向 s 中最后一个写入字符之后的指针,如果失败则返回 NULL。

int seq_path(struct seq_file *m, const struct path *path, const char *esc)

seq_file 接口,用于打印路径名

参数

struct seq_file *m

seq_file 句柄

const struct path *path

要打印的结构路径

const char *esc

要在输出中转义的字符集

描述

返回 'path' 的绝对路径,由路径参数中的 dentry / mnt 对表示。

int seq_file_path(struct seq_file *m, struct file *file, const char *esc)

seq_file 接口,用于打印文件的路径名

参数

struct seq_file *m

seq_file 句柄

struct file *file

要打印的 struct file

const char *esc

要在输出中转义的字符集

描述

返回文件的绝对路径。

int seq_write(struct seq_file *seq, const void *data, size_t len)

将任意数据写入缓冲区

参数

struct seq_file *seq

标识应在其中写入数据的缓冲区的 seq_file

const void *data

数据地址

size_t len

字节数

描述

成功时返回 0,否则返回非零值。

void seq_pad(struct seq_file *m, char c)

将填充空格写入缓冲区

参数

struct seq_file *m

标识应在其中写入数据的缓冲区的 seq_file

char c

如果非零,则在填充后追加的字节

struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)

开始 hlist 的迭代

参数

struct hlist_head *head

hlist 的头

loff_t pos

序列的起始位置

描述

在 seq_file->op->start() 处调用。

struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)

开始 hlist 的迭代

参数

struct hlist_head *head

hlist 的头

loff_t pos

序列的起始位置

描述

在 seq_file->op->start() 处调用。 如果您想在输出顶部打印标题,请调用此函数。

struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, loff_t *ppos)

移动到 hlist 的下一个位置

参数

void *v

当前迭代器

struct hlist_head *head

hlist 的头

loff_t *ppos

当前位置

描述

在 seq_file->op->next() 处调用。

struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, loff_t pos)

开始由 RCU 保护的 hlist 的迭代

参数

struct hlist_head *head

hlist 的头

loff_t pos

序列的起始位置

描述

在 seq_file->op->start() 处调用。

只要遍历受 rcu_read_lock() 的保护,此列表遍历原语就可以与 _rcu 列表修改原语(例如 hlist_add_head_rcu())安全地并发运行。

struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, loff_t pos)

开始由 RCU 保护的 hlist 的迭代

参数

struct hlist_head *head

hlist 的头

loff_t pos

序列的起始位置

描述

在 seq_file->op->start() 处调用。 如果您想在输出顶部打印标题,请调用此函数。

只要遍历受 rcu_read_lock() 的保护,此列表遍历原语就可以与 _rcu 列表修改原语(例如 hlist_add_head_rcu())安全地并发运行。

struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head, loff_t *ppos)

移动到受 RCU 保护的 hlist 的下一个位置

参数

void *v

当前迭代器

struct hlist_head *head

hlist 的头

loff_t *ppos

当前位置

描述

在 seq_file->op->next() 处调用。

只要遍历受 rcu_read_lock() 的保护,此列表遍历原语就可以与 _rcu 列表修改原语(例如 hlist_add_head_rcu())安全地并发运行。

struct hlist_node *seq_hlist_start_percpu(struct hlist_head __percpu *head, int *cpu, loff_t pos)

启动一个 percpu hlist 数组的迭代

参数

struct hlist_head __percpu *head

指向 struct hlist_heads 的 percpu 数组的指针

int *cpu

指向 cpu “光标” 的指针

loff_t pos

序列的起始位置

描述

在 seq_file->op->start() 处调用。

struct hlist_node *seq_hlist_next_percpu(void *v, struct hlist_head __percpu *head, int *cpu, loff_t *pos)

移动到 percpu hlist 数组的下一个位置

参数

void *v

指向当前 hlist_node 的指针

struct hlist_head __percpu *head

指向 struct hlist_heads 的 percpu 数组的指针

int *cpu

指向 cpu “光标” 的指针

loff_t *pos

序列的起始位置

描述

在 seq_file->op->next() 处调用。

int register_filesystem(struct file_system_type *fs)

注册一个新的文件系统

参数

struct file_system_type * fs

文件系统结构

将传递的文件系统添加到内核知道的用于挂载和其他系统调用的文件系统列表中。成功时返回 0,错误时返回负 errno 代码。

传递的 struct file_system_type 链接到内核结构中,并且在文件系统注销之前不得释放。

int unregister_filesystem(struct file_system_type *fs)

注销一个文件系统

参数

struct file_system_type * fs

要注销的文件系统

删除先前已成功向内核注册的文件系统。如果未找到文件系统,则返回错误。成功时返回零。

一旦此函数返回,struct file_system_type 结构就可以释放或重用。

void wbc_attach_fdatawrite_inode(struct writeback_control *wbc, struct inode *inode)

关联 wbc 和 inode 以进行 fdatawrite

参数

struct writeback_control *wbc

感兴趣的 writeback_control

struct inode *inode

目标 inode

描述

此函数由 __filemap_fdatawrite_range() 使用,它是写入代码的备用入口点,并且首先确保 inode 与 bdi_writeback 关联并将其附加到 wbc

void wbc_detach_inode(struct writeback_control *wbc)

将 wbc 与 inode 分离并执行外部检测

参数

struct writeback_control *wbc

刚刚完成的回写的 writeback_control

描述

在 inode 的回写尝试完成后调用,并撤消 wbc_attach_and_unlock_inode()。可以在任何上下文中调用。

由于 inode 的并发写入共享预计非常罕见,并且 memcg 仅根据首次使用情况跟踪页面所有权,严重限制了此类共享的有用性,因此 cgroup 回写跟踪每个 inode 的所有权。虽然对 inode 的并发写入共享的支持被认为是不必要的,但在不同时间点由不同 cgroup 写入 inode 更为常见,而且更重要的是,仅根据首次使用情况收费很容易导致严重不正确的行为(单个外部页面可能导致千兆字节的回写被错误地归因)。

为了解决这个问题,cgroup 回写检测 inode 的主要脏页者,并将所有权转移给它。为了避免不必要的振荡,检测机制会跟踪历史记录,并且仅当外部使用模式在一定时间内和/或回写尝试中保持稳定时才给出切换判断。

在每次回写尝试时,wbc 尝试使用 Boyer-Moore 多数投票算法检测主要写入者。除了来自多数投票的字节数之外,它还计算当前 wb 和上一轮获胜者 wb 的写入字节数(上一轮当前 wb 的最大值、两个轮次之前的获胜者以及上一轮的多数候选者)。跟踪历史获胜者有助于该算法半可靠地检测最活跃的写入者,即使它不是绝对多数。

一旦确定了该轮的获胜者,无论获胜者是外部的还是否,以及该轮消耗了多少 IO 时间,都会记录在 inode->i_wb_frn_history 中。如果记录的外部 IO 时间量超过某个阈值,则给出切换判断。

void wbc_account_cgroup_owner(struct writeback_control *wbc, struct folio *folio, size_t bytes)

记账回写以更新 inode cgroup 所有权

参数

struct writeback_control *wbc

正在进行的回写的 writeback_control

struct folio *folio

正在写出的 folio

size_t bytes

正在写出的字节数

描述

来自 foliobytes 将要在由 wbc 控制的回写期间写出。保留外部 inode 检测的账本。请参阅 wbc_detach_inode()

void __mark_inode_dirty(struct inode *inode, int flags)

用于将 inode 标记为脏的内部函数

参数

struct inode *inode

要标记的 inode

int flags

什么样的脏,例如 I_DIRTY_SYNC。这可以是多个 I_DIRTY_* 标志的组合,但 I_DIRTY_TIME 不能与 I_DIRTY_PAGES 组合。

描述

将 inode 标记为脏。我们通知文件系统,然后更新 inode 的脏标志。然后,如果需要,我们将 inode 添加到相应的脏列表中。

大多数调用者应使用 mark_inode_dirty() 或 mark_inode_dirty_sync() 而不是直接调用此函数。

小心!我们仅在 inode 被散列或引用 blockdev 时才将其添加到脏列表中。未散列的 inode 永远不会被添加到脏列表中,即使它们稍后被散列,因为它们已经被标记为脏。

简而言之,请确保在开始将任何 inode 标记为脏_之前_对其进行散列。

请注意,对于 blockdev,inode->dirtied_when 表示块特殊 inode (/dev/hda1) 本身的脏时间。内核内部 blockdev inode 的 ->dirtied_when 字段表示 blockdev 页面的脏时间。这就是为什么对于 I_DIRTY_PAGES,我们总是使用 page->mapping->host,因此页面脏时间记录在内部 blockdev inode 中。

void writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr, enum wb_reason reason)

从给定的超级块回写脏 inode

参数

struct super_block *sb

超级块

unsigned long nr

要写入的页面数

enum wb_reason reason

启动某些回写工作的原因

描述

在此超级块上启动某些 inode 的回写。不保证将写入多少(如果有的话),并且此函数不会等待提交 IO 的 IO 完成。

void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)

从给定的超级块回写脏 inode

参数

struct super_block *sb

超级块

enum wb_reason reason

启动某些回写工作的原因

描述

在此超级块上启动某些 inode 的回写。不保证将写入多少(如果有的话),并且此函数不会等待提交 IO 的 IO 完成。

void try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)

如果没有正在进行的回写,则尝试启动回写

参数

struct super_block *sb

超级块

enum wb_reason reason

启动某些回写工作的原因

描述

如果没有正在进行的回写,则调用 __writeback_inodes_sb_nr。

void sync_inodes_sb(struct super_block *sb)

同步 sb inode 页面

参数

struct super_block *sb

超级块

描述

此函数写入并等待属于此超级块的任何脏 inode。

int write_inode_now(struct inode *inode, int sync)

将 inode 写入磁盘

参数

struct inode *inode

要写入磁盘的 inode

int sync

写入是否应该是同步的

描述

如果 inode 是脏的,此函数会立即将其提交到磁盘。这主要是 knfsd 所需的。

调用者必须对 inode 具有引用,或者必须已设置 I_WILL_FREE。

int sync_inode_metadata(struct inode *inode, int wait)

将 inode 写入磁盘

参数

struct inode *inode

要同步的 inode

int wait

等待 I/O 完成。

描述

将 inode 写入磁盘并在完成后调整其脏状态。

注意

仅写入实际的 inode,不写入任何关联的数据或其他元数据。

struct file *anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags)

通过将其连接到匿名 inode 和描述文件“类”的 dentry 来创建一个新的文件实例

参数

const char *name

[in] 新文件“类”的名称

const struct file_operations *fops

[in] 新文件的文件操作

void *priv

[in] 新文件的私有数据(将是文件的 private_data)

int flags

[in] 标志

描述

通过将其连接到单个 inode 来创建一个新文件。这对于不需要具有完整的 inode 才能正确操作的文件非常有用。所有使用 anon_inode_getfile() 创建的文件将共享单个 inode,从而节省内存并避免文件/inode/dentry 设置的代码重复。返回新创建的 file* 或错误指针。

struct file *anon_inode_getfile_fmode(const char *name, const struct file_operations *fops, void *priv, int flags, fmode_t f_mode)

通过将其连接到匿名 inode 和描述文件“类”的 dentry 来创建一个新的文件实例

参数

const char *name

[in] 新文件“类”的名称

const struct file_operations *fops

[in] 新文件的文件操作

void *priv

[in] 新文件的私有数据(将是文件的 private_data)

int flags

[in] 标志

fmode_t f_mode

[in] fmode

描述

通过将其连接到单个 inode 来创建一个新文件。这对于不需要具有完整的 inode 才能正确操作的文件非常有用。所有使用 anon_inode_getfile() 创建的文件将共享单个 inode,从而节省内存并避免文件/inode/dentry 设置的代码重复。允许设置 fmode。返回新创建的 file* 或错误指针。

struct file *anon_inode_create_getfile(const char *name, const struct file_operations *fops, void *priv, int flags, const struct inode *context_inode)

类似于 anon_inode_getfile(),但会创建一个新的 !S_PRIVATE 匿名 inode,而不是重用单例匿名 inode,并调用 inode_init_security_anon() LSM 钩子。

参数

const char *name

[in] 新文件“类”的名称

const struct file_operations *fops

[in] 新文件的文件操作

void *priv

[in] 新文件的私有数据(将是文件的 private_data)

int flags

[in] 标志

const struct inode *context_inode

[in] 与新 inode 的逻辑关系(可选)

描述

创建新的匿名 inode 和文件对。这可以出于两个原因完成

  • 为了使 inode 具有自己的安全上下文,以便 LSM 可以强制执行对 inode 创建的策略;

  • 如果调用者需要唯一的 inode,例如为了自定义 fstat() 返回的大小

LSM 可能会在 inode_init_security_anon() 中使用 context_inode,但不会持有对它的引用。

返回新创建的 file* 或错误指针。

int anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv, int flags)

通过将其连接到匿名 inode 和描述文件“类”的 dentry 来创建新的文件实例

参数

const char *name

[in] 新文件“类”的名称

const struct file_operations *fops

[in] 新文件的文件操作

void *priv

[in] 新文件的私有数据(将是文件的 private_data)

int flags

[in] 标志

描述

通过将其连接到单个 inode 来创建新文件。这对于不需要具有完整 inode 才能正确操作的文件很有用。使用 anon_inode_getfd() 创建的所有文件将使用相同的单例 inode,从而减少内存使用并避免文件/inode/dentry 设置的代码重复。返回新创建的文件描述符或错误代码。

int setattr_should_drop_sgid(struct mnt_idmap *idmap, const struct inode *inode)

确定是否需要删除 setgid 位

参数

struct mnt_idmap *idmap

inode 中找到的挂载的 idmap

const struct inode *inode

要检查的 inode

描述

此函数确定是否需要删除 setgid 位。我们保留向后兼容性,并且如果设置了 S_IXGRP,则需要无条件删除 setgid 位。否则,我们具有与 setattr_prepare()setattr_copy() 完全相同的要求。

返回

如果需要删除 setgid 位,则为 ATTR_KILL_SGID,否则为 0。

int setattr_should_drop_suidgid(struct mnt_idmap *idmap, struct inode *inode)

确定是否需要删除 set{g,u}id 位

参数

struct mnt_idmap *idmap

inode 中找到的挂载的 idmap

struct inode *inode

要检查的 inode

描述

此函数确定是否需要删除 set{g,u}id 位。如果需要删除 setuid 位,则返回 ATTR_KILL_SUID。如果需要删除 setgid 位,则返回 ATTR_KILL_SGID。如果需要删除 set{g,u}id 位,则返回两个标志的相应掩码。

返回

指示要删除哪些 setid 位(如果有)的 ATTR_KILL_S{G,U}ID 的掩码,否则为 0。

int setattr_prepare(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr)

检查是否允许更改 dentry 的属性

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct dentry *dentry

要检查的 dentry

struct iattr *attr

要更改的属性

描述

检查是否允许更改给定 dentry 中包含在 attr 中的属性。这包括正常的 unix 访问权限检查,以及对 rlimit 和其他内容的检查。如果用户无权设置 SGID 位,该函数还会从模式中清除该位。如果设置了 ATTR_KILL_PRIV,还会清除文件功能和 IMA 扩展属性。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

应在 ->setattr 实现中作为第一件事调用,可能在获取其他锁之后。

int inode_newsize_ok(const struct inode *inode, loff_t offset)

是否可以将此 inode 截断为给定大小

参数

const struct inode *inode

要截断的 inode

loff_t offset

要分配给 inode 的新大小

描述

必须在持有 i_mutex 的情况下调用 inode_newsize_ok。

inode_newsize_ok 将检查文件系统限制和 ulimit,以检查新的 inode 大小是否在限制范围内。inode_newsize_ok 还将在必要时发送 SIGXFSZ。如果返回失败,调用者不得继续进行 inode 大小更改。inode 必须是文件(而不是目录),并且具有允许截断的适当权限(inode_newsize_ok 不检查这些条件)。

返回

成功时为 0,失败时为 -ve errno

void setattr_copy(struct mnt_idmap *idmap, struct inode *inode, const struct iattr *attr)

将简单的元数据更新复制到通用 inode 中

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct inode *inode

要更新的 inode

const struct iattr *attr

新属性

描述

必须在持有 i_mutex 的情况下调用 setattr_copy。

setattr_copy 使用 attr 中指定的元数据更新 idmapped 挂载上的 inode 元数据。使用正确的 idmapped 挂载权限助手执行必要的权限检查,以确定是否需要删除 S_ISGID 属性。明显缺少的是 inode 大小更新,因为它需要更复杂的 pagecache 更新。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

此操作后,inode 不会标记为脏。理由是对于“简单”文件系统,struct inode 是 inode 存储。如果需要,调用者可以随意在之后将 inode 标记为脏。

int notify_change(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr, struct inode **delegated_inode)

修改文件系统对象的属性

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

struct dentry *dentry

受影响的对象

struct iattr *attr

新属性

struct inode **delegated_inode

如果 inode 已委托,则返回 inode

描述

调用者必须持有受影响对象上的 i_mutex。

如果 notify_change 发现需要中断的委托,它将返回 -EWOULDBLOCK 并在 delegated_inode 中返回对 inode 的引用。然后,调用者应中断委托并重试。由于中断委托可能需要很长时间,因此调用者应在执行此操作之前释放 i_mutex。

或者,调用者可以为 delegated_inode 传递 NULL。这可能适用于期望底层文件系统未导出 NFS 的调用者。此外,对于为写入打开文件的调用者来说,传递 NULL 是可以的,因为在这种情况下不可能存在冲突的委托。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

char *d_path(const struct path *path, char *buf, int buflen)

返回 dentry 的路径

参数

const struct path *path

要报告的路径

char *buf

用于在其中返回值的缓冲区

int buflen

缓冲区长度

描述

将 dentry 转换为 ASCII 路径名。如果条目已被删除,则会附加字符串“ (已删除)”。请注意,这不明确。

如果路径太长,则返回指向缓冲区中的指针或错误代码。注意:调用者应使用返回的指针,而不是传入的缓冲区,来使用名称!该实现通常从缓冲区中的偏移量开始,并且可能会在开头留下 0 个字节。

“buflen”应为正数。

struct page *dax_layout_busy_page_range(struct address_space *mapping, loff_t start, loff_t end)

mapping 中查找第一个固定的页面

参数

struct address_space *mapping

要扫描引用计数 > 1 的页面的地址空间

loff_t start

起始偏移量。包含“start”的页面包含在内。

loff_t end

结束偏移量。包含“end”的页面包含在内。如果“end”为 LLONG_MAX,则包含从“start”到文件结尾的页面。

描述

DAX 需要 ZONE_DEVICE 映射的页面。这些页面从未“联机”到页面分配器,因此当 page->count == 1 时,它们被认为是空闲的。文件系统使用此接口来确定映射中的任何页面是否繁忙,即用于 DMA 或其他 get_user_pages() 用法。

预期文件系统持有锁以阻止在此 address_space 中建立新映射。即,它期望能够运行 unmap_mapping_range(),随后不会竞争 mapping_mapped() 变为 true。

ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops)

对 DAX 文件执行 I/O

参数

struct kiocb *iocb

此 I/O 的控制块

struct iov_iter *iter

从或向其执行 I/O 的地址

const struct iomap_ops *ops

从文件系统传递的 iomap ops

描述

此函数对直接映射的持久内存执行读取和写入操作。调用者需要注意读取/写入排除以及驱逐 I/O 下区域中的任何页面缓存页面。

vm_fault_t dax_iomap_fault(struct vm_fault *vmf, unsigned int order, pfn_t *pfnp, int *iomap_errp, const struct iomap_ops *ops)

处理 DAX 文件上的页面错误

参数

struct vm_fault *vmf

错误的描述

unsigned int order

要错误获取的页面的顺序

pfn_t *pfnp

如果需要 fsync,则为同步错误的要插入的 PFN

int *iomap_errp

用于在发生错误时存储详细错误代码的存储

const struct iomap_ops *ops

从文件系统传递的 Iomap ops

描述

发生页面错误时,文件系统可能会在其 DAX 文件的错误处理程序中调用此帮助程序。dax_iomap_fault() 假定调用者已完成所有必要的锁定,以便页面错误成功进行。

vm_fault_t dax_finish_sync_fault(struct vm_fault *vmf, unsigned int order, pfn_t pfn)

完成同步页面错误

参数

struct vm_fault *vmf

错误的描述

unsigned int order

要插入的条目的顺序

pfn_t pfn

要插入的 PFN

描述

此函数确保页面错误触及的文件范围持久存储在介质上,并处理插入适当的页表条目。

void simple_rename_timestamp(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)

更新重命名的各种 inode 时间戳

参数

struct inode *old_dir

旧的父目录

struct dentry *old_dentry

正在重命名的 dentry

struct inode *new_dir

新的父目录

struct dentry *new_dentry

重命名的目标

描述

POSIX 规定旧的和新的父目录都需要更新其 ctime 和 mtime,并且 old_dentrynew_dentry 的 inode(如果有)需要更新其 ctime。

int simple_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *iattr)

为简单文件系统设置属性

参数

struct mnt_idmap *idmap

目标挂载的idmap

struct dentry *dentry

目录项(dentry)

struct iattr *iattr

iattr 结构体

描述

成功时返回 0,失败时返回 -error。

simple_setattr 是一个简单的 ->setattr 实现,没有正确实现大小更改。

它既可以用于内存文件系统,也可以用于简单常规文件系统上的特殊文件。任何需要在大小更改时更改磁盘上或网络状态的内容都需要自己的 setattr 方法。

ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos, const void *from, size_t available)

将数据从缓冲区复制到用户空间

参数

void __user *to

要读取到的用户空间缓冲区

size_t count

要读取的最大字节数

loff_t *ppos

缓冲区中的当前位置

const void *from

要从中读取的缓冲区

size_t available

缓冲区的大小

描述

simple_read_from_buffer() 函数从 from 缓冲区的 ppos 偏移量处读取最多 count 个字节到从 to 开始的用户空间地址。

成功时,返回读取的字节数,并且偏移量 ppos 会增加此数字;出错时,返回负值。

ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos, const void __user *from, size_t count)

将数据从用户空间复制到缓冲区

参数

void *to

要写入的缓冲区

size_t available

缓冲区的大小

loff_t *ppos

缓冲区中的当前位置

const void __user *from

要从中读取的用户空间缓冲区

size_t count

要读取的最大字节数

描述

simple_write_to_buffer() 函数从 from 开始的用户空间地址读取最多 count 个字节到 to 缓冲区中的 ppos 偏移量处。

成功时,返回写入的字节数,并且偏移量 ppos 会增加此数字;出错时,返回负值。

ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, const void *from, size_t available)

从缓冲区复制数据

参数

void *to

要读取到的内核空间缓冲区

size_t count

要读取的最大字节数

loff_t *ppos

缓冲区中的当前位置

const void *from

要从中读取的缓冲区

size_t available

缓冲区的大小

描述

memory_read_from_buffer() 函数从 from 缓冲区的 ppos 偏移量处读取最多 count 个字节到从 to 开始的内核空间地址。

成功时,返回读取的字节数,并且偏移量 ppos 会增加此数字;出错时,返回负值。

int generic_encode_ino32_fh(struct inode *inode, __u32 *fh, int *max_len, struct inode *parent)

通用的 export_operations->encode_fh 函数

参数

struct inode *inode

要编码的对象

__u32 *fh

文件句柄片段的存储位置

int *max_len

存储的最大长度(以 4 字节为单位)

struct inode *parent

父目录 inode(如果需要)

描述

此通用 encode_fh 函数假定 32 位 inode 编号适合用于定位 inode,并且可以使用生成号来检查它是否仍然有效。它将它们放置在 export_decode_fh 期望找到它们的 filehandle 片段中。

struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type, struct inode *(*get_inode)(struct super_block *sb, u64 ino, u32 gen))

fh_to_dentry 导出操作的通用助手函数

参数

struct super_block *sb

要在其上执行文件句柄转换的文件系统

struct fid *fid

要转换的文件句柄

int fh_len

文件句柄的长度(以字节为单位)

int fh_type

文件句柄的类型

struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen)

文件系统回调,用于检索 inode

描述

只要 fid 具有已知的 Linux 文件句柄类型之一,此函数就会解码 fid,并在其上调用 get_inode 以检索文件句柄中指定的对象的 inode。

struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type, struct inode *(*get_inode)(struct super_block *sb, u64 ino, u32 gen))

fh_to_parent 导出操作的通用助手函数

参数

struct super_block *sb

要在其上执行文件句柄转换的文件系统

struct fid *fid

要转换的文件句柄

int fh_len

文件句柄的长度(以字节为单位)

int fh_type

文件句柄的类型

struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen)

文件系统回调,用于检索 inode

描述

只要 fid 具有已知的 Linux 文件句柄类型之一,此函数就会解码 fid,并在其上调用 get_inode 以检索文件句柄中指定的 _parent_ 对象的 inode(如果在文件句柄中指定),否则返回 NULL。

int __generic_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)

简单文件系统的通用 fsync 实现

参数

struct file *file

要同步的文件

loff_t start

起始偏移量(以字节为单位)

loff_t end

结束偏移量(包含)

int datasync

如果为 true,则仅同步基本元数据

描述

这是简单文件系统的 fsync 方法的通用实现,它在 address_space 结构挂起的缓冲区列表中跟踪所有非 inode 元数据。

int generic_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)

带有 flush 的简单文件系统的通用 fsync 实现

参数

struct file *file

要同步的文件

loff_t start

起始偏移量(以字节为单位)

loff_t end

结束偏移量(包含)

int datasync

如果为 true,则仅同步基本元数据

int generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)

检查文件系统的可寻址性

参数

unsigned blocksize_bits

文件系统块大小的对数

u64 num_blocks

文件系统中的块数

描述

确定具有 num_blocks 个块(以及 2****blocksize_bits** 的块大小)的文件系统是否可由系统的 sector_t 和页面缓存寻址。如果是,则返回 0;否则返回 -EFBIG。

int simple_nosetlease(struct file *filp, int arg, struct file_lease **flp, void **priv)

禁止租约的通用助手函数

参数

struct file *filp

文件指针

int arg

要获得的租约的类型

struct file_lease **flp

提供插入的新租约

void **priv

lm_setup 操作的私有数据

描述

用于不希望允许设置租约的文件系统的通用助手函数。所有参数都将被忽略,它只返回 -EINVAL。

用于获取“快速”符号链接目标的通用助手函数

参数

struct dentry *dentry

此处未使用

struct inode *inode

符号链接 inode

struct delayed_call *done

此处未使用

描述

用于文件系统的通用助手函数,用于符号链接 inode,其中指向符号链接目标的指针存储在 ->i_link 中。注意:这通常不会被调用,因为作为一种优化,路径查找代码直接使用任何非 NULL ->i_link,而不调用 ->get_link()。但是 ->get_link() 仍然必须设置,以将 inode_operations 标记为用于符号链接。

返回

符号链接目标

int generic_ci_d_compare(const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name)

区分大小写的文件系统的通用 d_compare 实现

参数

const struct dentry *dentry

要检查其名称的目录项

unsigned int len

目录项名称的长度

const char *str

指向目录项名称的 str 指针

const struct qstr *name

要比较的名称

返回

如果名称匹配,则为 0;如果名称不匹配,则为 1;或者为 -ERRNO

int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str)

区分大小写的文件系统的通用 d_hash 实现

参数

const struct dentry *dentry

父目录的目录项

struct qstr *str

需要填充哈希值的名称的 qstr

返回

如果哈希成功或未更改,则为 0;如果发生错误,则为 -EINVAL

int generic_ci_match(const struct inode *parent, const struct qstr *name, const struct qstr *folded_name, const u8 *de_name, u32 de_name_len)

将名称(不区分大小写)与目录项进行匹配。这是用于与目录条目进行比较的文件系统辅助函数。在 VFS 的 ->d_compare 中应使用 generic_ci_d_compare。

参数

const struct inode *parent

正在比较的目录项的父 inode

const struct qstr *name

查找下的名称。

const struct qstr *folded_name

查找下可选的预折叠名称

const u8 *de_name

目录项名称。

u32 de_name_len

目录项名称长度。

描述

测试不区分大小写的目录项是否与正在搜索的文件名匹配。如果提供了 folded_name,则使用它而不是重新计算 name 的 casefold。

返回

> 如果目录项匹配,则为 0;如果不匹配,则为 0;如果出错,则 < 0。

void generic_set_sb_d_ops(struct super_block *sb)

用于为已启用的特性选择文件系统范围的目录项操作集的辅助函数

参数

struct super_block *sb

要配置的超级块

描述

支持 casefolding 和/或 fscrypt 的文件系统可以在挂载时调用此辅助函数,以配置 sb->s_d_op 为已启用特性所需的最佳目录项操作集。必须在配置这些特性之后,但在创建根目录项之前调用此辅助函数。

bool inode_maybe_inc_iversion(struct inode *inode, bool force)

递增 i_version

参数

struct inode *inode

带有应更新的 i_version 的 inode

bool force

即使没有必要,也要递增计数器?

描述

每次修改 inode 时,任何观察者都必须看到 i_version 字段已更改。

如果设置了“force”或设置了 QUERIED 标志,则确保我们递增该值并清除 queried 标志。

在未设置两者的一般情况下,我们可以返回“false”而不更新 i_version。

如果此函数返回 false 并且没有其他元数据已更改,则我们可以避免记录元数据。

u64 inode_query_iversion(struct inode *inode)

读取 i_version 以供以后使用

参数

struct inode *inode

从中读取 i_version 的 inode

描述

读取 inode i_version 计数器。希望存储返回的 i_version 以供以后比较的调用方应使用此计数器。这将保证如果任何内容发生更改,则以后对 i_version 的查询将产生不同的值。

在此实现中,我们获取当前值,设置 QUERIED 标志,然后尝试使用 cmpxchg 将其交换到位,如果尚未设置。如果失败,我们将使用来自 cmpxchg 的新获取的值重试。

struct timespec64 simple_inode_init_ts(struct inode *inode)

初始化新 inode 的时间戳

参数

struct inode *inode

要初始化的 inode

描述

创建新 inode 时,大多数文件系统会将时间戳设置为当前时间。添加一个辅助函数来执行此操作。

int posix_acl_chmod(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode)

chmod 一个 posix acl

参数

struct mnt_idmap *idmap

inode 中找到的挂载的 idmap

struct dentry *dentry

在其上检查权限的 dentry

umode_t mode

inode 的新模式

描述

如果通过 idmapped 挂载找到了该目录项,则必须通过 idmap 传递 vfsmount 的 idmap。然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

int posix_acl_update_mode(struct mnt_idmap *idmap, struct inode *inode, umode_t *mode_p, struct posix_acl **acl)

更新 set_acl 中的模式

参数

struct mnt_idmap *idmap

inode 中找到的挂载的 idmap

struct inode *inode

目标 inode

umode_t *mode_p

用于更新的模式(指针)

struct posix_acl **acl

acl 指针

描述

设置 ACL 时更新文件模式:基于 ACL 计算新的文件权限位。此外,如果 ACL 等效于新的文件模式,则将 *acl 设置为 NULL,以指示不应设置任何 ACL。

与 chmod 一样,如果调用方不在拥有的组中,或者没有 CAP_FSETID 的功能,则清除 setgid 位(请参阅 inode_change_ok)。

如果 inode 是通过 idmapped 挂载找到的,则必须通过 idmap 传递 vfsmount 的 idmap。 然后,此函数将负责根据 idmap 映射 inode,然后再检查权限。 在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

从 set_acl inode 操作调用。

struct posix_acl *posix_acl_from_xattr(struct user_namespace *userns, const void *value, size_t size)

将 POSIX ACL 从后备存储转换为 VFS 格式

参数

struct user_namespace *userns

文件系统的 idmapping

const void *value

POSIX ACL 的 uapi 表示形式

size_t size

void 的大小

描述

以未更改的 uapi 格式存储 POSIX ACL 的文件系统应在从后备存储读取 POSIX ACL 并将其转换为 struct posix_acl VFS 格式时使用 posix_acl_from_xattr()。该辅助函数专门用于从 acl inode 操作中调用。

posix_acl_from_xattr() 函数会将存储在 ACL_{GROUP,USER} 条目中的原始 {g,u}id 值映射到 userns 中的 idmapping。

请注意,posix_acl_from_xattr() 不考虑 idmapped 挂载。如果考虑了,则从 get acl inode 操作调用它将返回根据 idmapped 挂载映射的 POSIX ACL,这意味着该值无法为文件系统缓存。Idmapped 挂载在权限检查期间或在将它们报告给用户之前就在 VFS - 用户空间边界上动态考虑。

返回

成功时分配的 struct posix_acl,对于有效的标头为 NULL,但

没有实际的 POSIX ACL 条目,或 ERR_PTR() 编码的错误代码。

int vfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)

设置 posix acls

参数

struct mnt_idmap *idmap

挂载的 idmap

struct dentry *dentry

在其上设置 posix acls 的 dentry

const char *acl_name

posix acl 的名称

struct posix_acl *kacl

采用适当 VFS 格式的 posix acls

描述

此函数设置 kacl。调用方必须在此后对 kacl 调用 posix_acl_release()。

返回

成功时为 0,出错时为负 errno。

struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name)

获取 posix acls

参数

struct mnt_idmap *idmap

挂载的 idmap

struct dentry *dentry

在其上检索 posix acls 的 dentry

const char *acl_name

posix acl 的名称

描述

此函数从文件系统检索 kacl。调用方必须对 kacl 调用 posix_acl_release()。

返回

成功时为 VFS 格式的 POSIX ACL,出错时为负 errno。

int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name)

删除 posix acls

参数

struct mnt_idmap *idmap

挂载的 idmap

struct dentry *dentry

在其上检索 posix acls 的 dentry

const char *acl_name

posix acl 的名称

描述

此函数删除 posix acls。

返回

成功时为 0,出错时为负 errno。

void fill_mg_cmtime(struct kstat *stat, u32 request_mask, struct inode *inode)

填充 mtime 和 ctime 并将 ctime 标记为 QUERIED

参数

struct kstat *stat

在何处存储结果值

u32 request_mask

请求的 STATX_* 值

struct inode *inode

从中抓取 c/mtime 的 inode

描述

给定 inode,如果存在,则从中抓取 ctime 和 mtime,并将结果存储在 stat 中。在获取该值时,将其标记为 QUERIED(如果尚未标记),以便下次写入将记录不同的时间戳。

注意:QUERIED 标志在 ctime 中进行跟踪,但即使仅请求了 mtime,我们也会在此处设置它,因为这可以确保下次 mtime 更改将是不同的。

void generic_fillattr(struct mnt_idmap *idmap, u32 request_mask, struct inode *inode, struct kstat *stat)

从 inode 结构填充基本属性

参数

struct mnt_idmap *idmap

找到 inode 的挂载点的 idmap

u32 request_mask

statx request_mask

struct inode *inode

用作源的 Inode

struct kstat *stat

在何处填充属性

描述

从 VFS inode 结构上可以找到的数据填充 kstat 结构中的基本属性。如果没有提供 getattr inode 操作,则这是默认值。

如果通过 idmapped 挂载找到了该 inode,则必须通过 idmap 传递 vfsmount 的 idmap。然后,此函数将负责根据 idmap 映射 inode,然后再填充 uid 和 gid filds。在非 idmapped 挂载上,或者如果要在原始 inode 上执行权限检查,只需传递 nop_mnt_idmap

void generic_fill_statx_attr(struct inode *inode, struct kstat *stat)

从 inode 标志填充 statx 属性

参数

struct inode *inode

用作源的 Inode

struct kstat *stat

在何处填充属性标志

描述

填充 kstat 结构中的 STATX_ATTR_* 标志,以表示在 i_flags 上发布并由 VFS 强制执行的 inode 的属性。

void generic_fill_statx_atomic_writes(struct kstat *stat, unsigned int unit_min, unsigned int unit_max, unsigned int unit_max_opt)

填充原子写入 statx 属性

参数

struct kstat *stat

在何处填充属性标志

unsigned int unit_min

支持的最小原子写入长度(以字节为单位)

unsigned int unit_max

支持的最大原子写入长度(以字节为单位)

unsigned int unit_max_opt

优化的最大支持原子写入长度(以字节为单位)

描述

从原子写入 unit_min 和 unit_max 值填充 kstat 结构中的 STATX{_ATTR}_WRITE_ATOMIC 标志。

int vfs_getattr_nosec(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags)

获取属性但不进行安全检查

参数

const struct path *path

从中获取属性的文件

struct kstat *stat

用于返回属性的结构

u32 request_mask

指示调用者需要什么的STATX_xxx 标志

unsigned int query_flags

查询模式 (AT_STATX_SYNC_TYPE)

描述

获取属性而不调用 security_inode_getattr。

目前,除了 vfs_getattr 之外,唯一的调用者是文件句柄查找代码内部,它仅使用 inode 编号,不向任何用户返回任何属性。任何其他代码可能需要 vfs_getattr。

int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)

用于将一定范围的数据和元数据同步到磁盘的辅助函数

参数

struct file *file

要同步的文件

loff_t start

要同步的数据范围起点的字节偏移量

loff_t end

数据范围终点的字节偏移量(包含)

int datasync

仅执行 datasync

描述

将范围 **start**..**end** 中的数据和 **file** 的元数据写回磁盘。如果设置了 **datasync**,则仅写入访问修改的文件数据所需的元数据。

int vfs_fsync(struct file *file, int datasync)

对文件执行 fsync 或 fdatasync

参数

struct file *file

要同步的文件

int datasync

仅执行 fdatasync 操作

描述

将 **file** 的数据和元数据写回磁盘。如果设置了 **datasync**,则仅写入访问修改的文件数据所需的元数据。

int __vfs_setxattr_locked(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags, struct inode **delegated_inode)

在持有 inode 锁时设置扩展属性

参数

struct mnt_idmap *idmap

目标 inode 的挂载的 idmap

struct dentry *dentry

要在其上执行 setxattr 的对象

const char *name

要设置的 xattr 名称

const void *value

要将 **name** 设置为的值

size_t size

**value** 的大小

int flags

要传递到文件系统操作的标志

struct inode **delegated_inode

返回时,将包含一个委派被破坏的 inode 指针,如果没有,则为 NULL。

ssize_t vfs_listxattr(struct dentry *dentry, char *list, size_t size)

检索 0 分隔的 xattr 名称列表

参数

struct dentry *dentry

从中检索 xattr 名称的 inode 的 dentry

char *list

用于存储 xattr 名称的缓冲区

size_t size

缓冲区的大小

描述

此函数返回与 **dentry** 的 inode 关联的所有 xattr 的名称。

请注意,由于历史原因,vfs_listxattr() 函数也列出了 POSIX ACL。由于 POSIX ACL 与 IOP_XATTR 解耦,因此 vfs_listxattr() 函数不检查此标志,因为文件系统可以在不实现任何其他 xattr 的情况下实现 POSIX ACL。

但是,由于所有删除 IOP_XATTR 的代码路径也分配了不实现或实现存根 ->listxattr() 操作的 inode 操作。

返回

成功时,使用缓冲区的字节大小。出错时,返回一个

负错误代码。

int __vfs_removexattr_locked(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, struct inode **delegated_inode)

在持有 inode 锁时设置扩展属性

参数

struct mnt_idmap *idmap

目标 inode 的挂载的 idmap

struct dentry *dentry

要在其上执行 setxattr 的对象

const char *name

要删除的 xattr 的名称

struct inode **delegated_inode

返回时,将包含一个委派被破坏的 inode 指针,如果没有,则为 NULL。

ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)

运行通过 dentry 的 xattr list() 操作

参数

struct dentry *dentry

要列出 xattr 的 dentry

char *buffer

结果缓冲区

size_t buffer_size

**buffer** 的大小

描述

合并来自 xattr_handler 堆栈中每个 xattr_handler 的 list() 操作的结果。

请注意,这不包括 POSIX ACL 的条目。

const char *xattr_full_name(const struct xattr_handler *handler, const char *name)

从后缀计算完整属性名称

参数

const struct xattr_handler *handler

xattr_handler 操作的处理程序

const char *name

传递给 xattr_handler 操作的名称

描述

get 和 set xattr 处理程序操作在跳过处理程序的前缀后,使用属性名称的其余部分调用:例如,“foo”传递给具有前缀“user.”的处理程序的 get 操作,以获取属性“user.foo”。完整名称仍然在名称中“存在”。

注意

当从 vfs 调用时,list xattr 处理程序操作会传递一个 NULL 名称;一些文件系统在内部使用此操作,语义各不相同。

int mnt_get_write_access(struct vfsmount *m)

获取对挂载的写入权限,没有冻结保护

参数

struct vfsmount *m

要在其上进行写入的挂载

描述

这告诉底层文件系统即将对其执行写入操作,并确保允许写入(mnt 是读写),然后才返回成功。此操作不防止文件系统被冻结。写入操作完成后,必须调用 mnt_put_write_access()。这实际上是一个引用计数。

int mnt_want_write(struct vfsmount *m)

获取对挂载的写入权限

参数

struct vfsmount *m

要在其上进行写入的挂载

描述

这告诉底层文件系统即将对其执行写入操作,并确保允许写入(挂载是读写,文件系统未冻结),然后才返回成功。写入操作完成后,必须调用 mnt_drop_write()。这实际上是一个引用计数。

int mnt_want_write_file(struct file *file)

获取对文件挂载的写入权限

参数

struct file *file

要在其上进行写入的文件的挂载

描述

这类似于 mnt_want_write,但如果该文件已经打开以进行写入,它将跳过递增 mnt_writers(因为打开的文件已经具有引用),而是仅执行冻结保护和紧急 r/o 重新挂载检查。这必须与 mnt_drop_write_file 配对。

void mnt_put_write_access(struct vfsmount *mnt)

放弃对挂载的写入权限

参数

struct vfsmount *mnt

要放弃写入权限的挂载

描述

告诉底层文件系统,我们已完成对其执行写入操作。必须与上面的 mnt_get_write_access() 调用匹配。

void mnt_drop_write(struct vfsmount *mnt)

放弃对挂载的写入权限

参数

struct vfsmount *mnt

要放弃写入权限的挂载

描述

告诉底层文件系统,我们已完成对其执行写入操作,并且还允许再次冻结文件系统。必须与上面的 mnt_want_write() 调用匹配。

struct vfsmount *vfs_create_mount(struct fs_context *fc)

为已配置的超级块创建挂载

参数

struct fs_context *fc

带有附加的超级块的配置上下文

描述

创建到已配置的超级块的挂载。如有必要,调用者应在调用此函数之前调用 vfs_get_tree()

请注意,这不会将挂载附加到任何内容。

bool path_is_mountpoint(const struct path *path)

检查路径是否为当前命名空间中的挂载点。

参数

const struct path *path

要检查的路径

d_mountpoint() 只能可靠地用于确定 dentry 是否未挂载在任何命名空间中,并且内联处理了常见的这种情况。d_mountpoint() 不知道可能存在多个在不同命名空间中使用给定 dentry 的挂载。此函数检查传入的路径是否为挂载点,而不是仅检查 dentry。

int may_umount_tree(struct vfsmount *m)

检查挂载树是否繁忙

参数

struct vfsmount *m

挂载树的根

描述

调用此函数是为了检查挂载树是否具有任何打开的文件、pwds、chroot 或繁忙的子挂载。

int may_umount(struct vfsmount *mnt)

检查挂载点是否繁忙

参数

struct vfsmount *mnt

挂载的根

描述

调用此函数是为了检查挂载点是否具有任何打开的文件、pwds、chroot 或子挂载。如果挂载具有子挂载,则无论子挂载是否繁忙,此函数都将返回繁忙。

不考虑配额和其他内容。换句话说,在某些情况下,它会给出错误的否定结果。它存在的主要原因是我们需要一种非破坏性的方式来查找易于卸载的文件系统。

struct vfsmount *clone_private_mount(const struct path *path)

创建路径的私有克隆

参数

const struct path *path

要克隆的路径

描述

这将创建一个新的 vfsmount,它将是 **path** 的克隆。新的挂载将不会附加到命名空间中的任何位置,并且将是私有的(即,对原始挂载的更改将不会传播到此挂载中)。

这假定调用者已调用或执行了与 may_mount() 等效的操作。

使用 mntput() 释放。

void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)

将挂载放在到期列表中

参数

struct vfsmount *mnt

要列出的挂载。

struct list_head *expiry_list

要将挂载添加到的列表。

proc 文件系统

sysctl 接口

int proc_dostring(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取一个字符串 sysctl

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从用户缓冲区读取/写入字符串。如果内核缓冲区不够大,无法容纳字符串,则字符串将被截断。复制的字符串以 NULL 结尾。如果字符串正在被用户进程读取,则会被复制并添加换行符“n”。如果缓冲区不够大,则会被截断。

成功时返回 0。

int proc_dobool(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取/写入一个布尔值

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入一个整数值,将其视为 ASCII 字符串。

table->data 必须指向一个 bool 变量,并且 table->maxlen 必须为 sizeof(bool)。

成功时返回 0。

int proc_dointvec(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取一个整数向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个整数值,将其视为 ASCII 字符串。

成功时返回 0。

int proc_douintvec(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取一个无符号整数向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个无符号整数值,将其视为 ASCII 字符串。

成功时返回 0。

int proc_dointvec_minmax(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取具有最小值/最大值的整数向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个整数值,将其视为 ASCII 字符串。

此例程将确保这些值在 table->extra1(最小值)和 table->extra2(最大值)指定的范围内。

成功时返回 0,如果写入时范围检查失败,则返回 -EINVAL。

int proc_douintvec_minmax(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取具有最小值/最大值的无符号整数向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个无符号整数值,将其视为 ASCII 字符串。不允许使用负字符串。

此例程将确保这些值在 table->extra1(最小值)和 table->extra2(最大值)指定的范围内。最终会对 UINT_MAX 进行健全性检查,以避免不得不支持来自用户空间的环绕使用。

成功时返回 0,如果写入时范围检查失败,则返回 -ERANGE。

int proc_dou8vec_minmax(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取具有最小值/最大值的无符号字符向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(u8) 个无符号字符值,将其视为 ASCII 字符串。不允许使用负字符串。

此例程将确保这些值在 table->extra1(最小值)和 table->extra2(最大值)指定的范围内。

成功时返回 0,如果写入时范围检查失败,则返回错误。

int proc_doulongvec_minmax(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取具有最小值/最大值的长整数向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned long) 个无符号长整数值,将其视为 ASCII 字符串。

此例程将确保这些值在 table->extra1(最小值)和 table->extra2(最大值)指定的范围内。

成功时返回 0。

int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

读取具有最小值/最大值的毫秒值向量

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned long) 个无符号长整数值,将其视为 ASCII 字符串。这些值被视为毫秒,并在存储时转换为节拍数。

此例程将确保这些值在 table->extra1(最小值)和 table->extra2(最大值)指定的范围内。

成功时返回 0。

int proc_dointvec_jiffies(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

将整数向量读取为秒

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个整数值,将其视为 ASCII 字符串。假定读取的值以秒为单位,并转换为节拍数。

成功时返回 0。

int proc_dointvec_userhz_jiffies(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

将整数向量读取为 1/USER_HZ 秒

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

指向文件位置的指针

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个整数值,将其视为 ASCII 字符串。假定读取的值以 1/USER_HZ 秒为单位,并转换为节拍数。

成功时返回 0。

int proc_dointvec_ms_jiffies(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

将整数向量读取为 1 毫秒

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件中的当前位置

描述

从/向用户缓冲区读取/写入最多 table->maxlen/sizeof(unsigned int) 个整数值,将其视为 ASCII 字符串。假定读取的值以 1/1000 秒为单位,并转换为节拍数。

成功时返回 0。

int proc_do_large_bitmap(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos)

从/向大型位图读取/写入

参数

const struct ctl_table *table

sysctl 表

int write

如果这是对 sysctl 文件的写入,则为 TRUE

void *buffer

用户缓冲区

size_t *lenp

用户缓冲区的大小

loff_t *ppos

文件位置

描述

位图存储在 table->data 中,位图长度(以位为单位)存储在 table->maxlen 中。

我们使用范围逗号分隔格式(例如 1,3-4,10-10),以便大型位图可以以紧凑的方式表示。写入文件将清除位图,然后使用给定的输入更新它。

成功时返回 0。

proc 文件系统接口

void proc_flush_pid(struct pid *pid)

从 /proc dcache 中删除 pid 的 dcache 条目。

参数

struct pid *pid

应该刷新的 pid。

描述

此函数遍历附加到 pid 的 inode 列表(属于任何 proc 文件系统),并将它们从目录项缓存中刷新。

在任务退出之前缓存该任务的 /proc 条目是安全合理的。在此之后,它们只会用无用的条目阻塞目录项缓存,可能会导致有用的目录项缓存条目被刷新。提供此例程是为了在重新获得进程时刷新这些无用的目录项缓存条目。

注意

此例程只是一种优化,因此不保证

在重新获得进程后不存在任何目录项缓存条目,它只是使任何条目持续存在的可能性很小。

基于文件描述符的事件

void eventfd_signal_mask(struct eventfd_ctx *ctx, __poll_t mask)

递增事件计数器

参数

struct eventfd_ctx *ctx

[in] 指向 eventfd 上下文的指针。

__poll_t mask

[in] 轮询掩码

描述

此函数应该由内核在不允许睡眠的路径中调用。在此函数中,我们允许计数器达到 ULLONG_MAX 值,并通过向 poll(2) 返回 EPOLLERR 来指示此溢出情况。

void eventfd_ctx_put(struct eventfd_ctx *ctx)

释放对内部 eventfd 上下文的引用。

参数

struct eventfd_ctx *ctx

[in] 指向 eventfd 上下文的指针。

描述

eventfd 上下文引用必须先前已通过 eventfd_ctx_fdget()eventfd_ctx_fileget() 获取。

int eventfd_ctx_remove_wait_queue(struct eventfd_ctx *ctx, wait_queue_entry_t *wait, __u64 *cnt)

读取当前计数器并删除等待队列。

参数

struct eventfd_ctx *ctx

[in] 指向 eventfd 上下文的指针。

wait_queue_entry_t *wait

[输入] 要移除的等待队列。

__u64 *cnt

[输出] 指向 64 位计数器值的指针。

描述

如果成功,返回 0,否则返回以下错误代码

-EAGAIN

: 操作将会阻塞。

此函数用于从 eventfd 等待队列头原子性地移除一个等待队列条目,并读取/重置计数器值。

struct file *eventfd_fget(int fd)

获取 eventfd 文件描述符的引用。

参数

int fd

[输入] Eventfd 文件描述符。

描述

如果成功,返回指向 eventfd 文件结构的指针,否则返回以下错误指针

-EBADF

: 无效的 fd 文件描述符。

-EINVAL

: fd 文件描述符不是 eventfd 文件。

struct eventfd_ctx *eventfd_ctx_fdget(int fd)

获取对内部 eventfd 上下文的引用。

参数

int fd

[输入] Eventfd 文件描述符。

描述

返回指向内部 eventfd 上下文的指针,否则返回以下函数返回的错误指针

eventfd_fget

struct eventfd_ctx *eventfd_ctx_fileget(struct file *file)

获取对内部 eventfd 上下文的引用。

参数

struct file *file

[输入] Eventfd 文件指针。

描述

返回指向内部 eventfd 上下文的指针,否则返回错误指针

-EINVAL

: fd 文件描述符不是 eventfd 文件。

eventpoll (epoll) 接口

int ep_events_available(struct eventpoll *ep)

检查是否有准备好的事件可用。

参数

struct eventpoll *ep

指向 eventpoll 上下文的指针。

返回

如果准备好的事件可用,则返回一个不同于 zero 的值,

否则返回 zero

bool busy_loop_ep_timeout(unsigned long start_time, struct eventpoll *ep)

检查忙轮询是否超时。优先使用 epoll 实例 ep 中的超时值,但如果未设置,则回退到通过 busy_loop_timeout 设置的全系统全局超时值。

参数

unsigned long start_time

用于计算到超时剩余时间的开始时间。

struct eventpoll *ep

指向 eventpoll 上下文的指针。

返回

如果超时已过期,则为 true,否则为 false。

int reverse_path_check(void)

tfile_check_list 是 epitem_head 的列表,其中包含提议新添加的链接。我们需要确保这些添加的链接不会添加过多的路径,以免我们花费所有时间唤醒 eventpoll 对象。

参数

void

无参数

返回

如果提议的链接没有创建过多的路径,则返回 zero

否则返回 -1

int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, struct timespec64 *timeout)

检索就绪事件,并将它们传递给调用者提供的事件缓冲区。

参数

struct eventpoll *ep

指向 eventpoll 上下文的指针。

struct epoll_event __user *events

指向用户空间缓冲区的指针,就绪事件应存储在该缓冲区中。

int maxevents

调用者事件缓冲区的大小(以事件数为单位)。

struct timespec64 *timeout

用于获取就绪事件的最大超时时间(以 timespec 为单位)。如果超时时间为零,则该函数不会阻塞;如果 timeout 指针为 NULL,则该函数将阻塞,直到至少检索到一个事件(或发生错误)。

返回

已获取的就绪事件数,或一个

错误代码(如果发生错误)。

int ep_loop_check_proc(struct eventpoll *ep, int depth)

验证将一个 epoll 文件添加到另一个 epoll 结构中是否违反了约束,包括闭环或过深的链(可能导致过多的堆栈使用)。

参数

struct eventpoll *ep

要当前检查的 struct eventpoll

int depth

正在检查的路径的当前深度。

返回

如果将 epoll file 添加到当前 epoll

结构 ep 中没有违反约束,则返回 zero,否则返回 -1

int ep_loop_check(struct eventpoll *ep, struct eventpoll *to)

执行检查以验证将一个 epoll 文件 (to) 添加到另一个 epoll 文件(由 ep 表示)中是否会创建闭环或过深的链。

参数

struct eventpoll *ep

指向要插入到的 epoll。

struct eventpoll *to

指向要插入的 epoll。

返回

如果将 epoll to 添加到 epoll from 中没有违反约束,则返回 zero,否则返回 -1

用于导出内核对象的文件系统

int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr, const void *ns)

为具有自定义 ns 的对象创建属性文件

参数

struct kobject *kobj

我们正在为其创建的对象

const struct attribute *attr

属性描述符

const void *ns

新文件应属于的命名空间

int sysfs_add_file_to_group(struct kobject *kobj, const struct attribute *attr, const char *group)

将属性文件添加到预先存在的组。

参数

struct kobject *kobj

我们正在操作的对象。

const struct attribute *attr

属性描述符。

const char *group

组名。

int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, umode_t mode)

更新对象属性上的修改后的模式值。

参数

struct kobject *kobj

我们正在操作的对象。

const struct attribute *attr

属性描述符。

umode_t mode

文件权限。

struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj, const struct attribute *attr)

打破“活动”保护

参数

struct kobject *kobj

与内核对象 attr 关联。

const struct attribute *attr

要打破“活动”保护的属性。

描述

与 kernfs 一样,使用 sysfs 时,属性的删除将推迟到所有活动的 .show() 和 .store() 回调完成之后,除非调用此函数。因此,此函数在实现自删除的方法中很有用。

void sysfs_unbreak_active_protection(struct kernfs_node *kn)

恢复“活动”保护

参数

struct kernfs_node *kn

sysfs_break_active_protection() 返回的指针。

描述

撤消 sysfs_break_active_protection() 的效果。由于此函数在与传递给 sysfs_break_active_protection() 的 'attr' 参数对应的 kernfs 节点上调用 kernfs_put(),因此在该属性已被删除,所以在 sysfs_break_active_protection()sysfs_unbreak_active_protection() 调用之间访问 kn 是不安全的。

void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, const void *ns)

删除具有自定义 ns 标签的对象属性

参数

struct kobject *kobj

我们正在操作的对象

const struct attribute *attr

属性描述符

const void *ns

要删除的文件的命名空间标签

描述

哈希属性名称和命名空间标签,然后杀死目标。

bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)

从其自身的方法中删除对象属性

参数

struct kobject *kobj

我们正在操作的对象

const struct attribute *attr

属性描述符

描述

有关详细信息,请参阅 kernfs_remove_self()。

void sysfs_remove_file_from_group(struct kobject *kobj, const struct attribute *attr, const char *group)

从组中删除属性文件。

参数

struct kobject *kobj

我们正在操作的对象。

const struct attribute *attr

属性描述符。

const char *group

组名。

int sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr)

为对象创建二进制文件。

参数

struct kobject *kobj

对象。

const struct bin_attribute *attr

属性描述符。

void sysfs_remove_bin_file(struct kobject *kobj, const struct bin_attribute *attr)

删除对象的二进制文件。

参数

struct kobject *kobj

对象。

const struct bin_attribute *attr

属性描述符。

int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid, kgid_t kgid)

更改 sysfs 文件的所有者。

参数

struct kobject *kobj

对象。

const char *name

要更改的文件的名称。

kuid_t kuid

新所有者的 kuid

kgid_t kgid

新所有者的 kgid

描述

此函数查找 kobj 下的 sysfs 条目 name,并将所有权更改为 kuid/kgid

成功时返回 0,失败时返回错误代码。

int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid)

更改给定对象的所有者。

参数

struct kobject *kobj

对象。

kuid_t kuid

新所有者的 kuid

kgid_t kgid

新所有者的 kgid

描述

kobj 的默认目录、文件、组和属性的所有者更改为 kuid/kgid。请注意,sysfs_change_owner 反映了驱动程序核心如何添加 kobject 的 sysfs 条目。总之,sysfs_change_owner() 负责 kobj 的默认目录条目、与 kobj 的 ktype 关联的默认属性以及与 kobj 的 ktype 关联的默认属性。驱动程序核心未添加的其他属性必须由创建它们的驱动程序或子系统更改。这类似于删除特定于驱动程序/子系统的条目的方式。

成功时返回 0,失败时返回错误代码。

int sysfs_emit(char *buf, const char *fmt, ...)

scnprintf 等效项,了解 PAGE_SIZE 缓冲区。

参数

char *buf

PAGE_SIZE 缓冲区的开始。

const char *fmt

格式

...

format 的可选参数

描述

返回写入 buf 的字符数。

int sysfs_emit_at(char *buf, int at, const char *fmt, ...)

scnprintf 等效项,了解 PAGE_SIZE 缓冲区。

参数

char *buf

PAGE_SIZE 缓冲区的开始。

int at

buf 中的偏移量,以字节为单位开始写入。at 必须 >= 0 && < PAGE_SIZE

const char *fmt

格式

...

fmt 的可选参数

描述

返回从 &**buf**[at] 开始写入的字符数。

ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj, const struct bin_attribute *attr, char *buf, loff_t off, size_t count)

读取回调以简单地从内存复制。

参数

struct file *file

正在读取的属性文件。

struct kobject *kobj

属性所属的对象。

const struct bin_attribute *attr

属性描述符。

char *buf

目标缓冲区。

loff_t off

要从中读取的字节偏移量。

size_t count

要读取的最大字节数。

描述

由内存中的缓冲区支持的 bin_attributes 的简单 ->read() 回调。在 sysfs 中创建 bin_attribute 之前,必须将 struct bin_attribute 中的 privatesize 成员设置为缓冲区的位置和大小。

offcount 的边界检查在 sysfs_kf_bin_read() 中完成。off 的负值检查在 vfs_setpos() 和 default_llseek() 中完成。

返回写入 buf 的字节数。

在两个对象之间创建符号链接。

参数

struct kobject *kobj

我们要在其中创建链接的目录的对象。

struct kobject *target

我们要指向的对象。

const char *name

符号链接的名称。

在两个对象之间创建符号链接。

参数

struct kobject *kobj

我们要在其中创建链接的目录的对象。

struct kobject *target

我们要指向的对象。

const char *name

符号链接的名称。

此函数与 sysfs_create_link() 的作用相同,但如果链接已存在,则不会发出警告。

删除对象目录中的符号链接。

参数

struct kobject *kobj

我们正在操作的对象。

const char *name

要删除的符号链接的名称。

重命名对象目录中的符号链接。

参数

struct kobject *kobj

我们正在操作的对象。

struct kobject *targ

我们要指向的对象。

const char *old

符号链接的先前名称。

const char *new

符号链接的新名称。

const void *new_ns

符号链接的新命名空间。

用于常见重命名符号链接习惯用法的辅助函数。

debugfs 文件系统

debugfs 接口

struct dentry *debugfs_lookup(const char *name, struct dentry *parent)

查找现有 debugfs 文件

参数

const char *name

指向包含要查找的文件的名称的字符串的指针。

struct dentry *parent

指向文件的父 dentry 的指针。

描述

如果此函数成功,将返回指向 dentry 的指针。如果文件不存在或发生错误,将返回 NULL。不再需要时,必须将返回的 dentry 传递给 dput()。

如果内核中未启用 debugfs,将返回值 -ENODEV

struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops)

在 debugfs 文件系统中创建一个文件

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限。

struct dentry *parent

指向此文件的父 dentry 的指针。如果设置,这应为目录 dentry。如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

void *data

指向调用方稍后想要访问的内容的指针。inode.i_private 指针将在 open() 调用时指向此值。

const struct file_operations *fops

指向应用于此文件的 struct file_operations 的指针。

描述

debugfs_create_file_unsafe() 与 debugfs_create_file() 完全类似,唯一的区别是传递给它的 fops 不会受到 debugfs 核心的文件删除的保护。

您有责任通过 debugfs_file_get()debugfs_file_put() 来保护您的 struct file_operation 方法免受文件删除。但是,->open() 仍然受到 debugfs 的保护。

任何通过 DEFINE_DEBUGFS_ATTRIBUTE() 定义的 struct file_operations 都受到文件删除的保护,因此,可以在此处使用。

void debugfs_create_file_size(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops, loff_t file_size)

在 debugfs 文件系统中创建一个文件

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限。

struct dentry *parent

指向此文件的父 dentry 的指针。如果设置,这应为目录 dentry。如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

void *data

指向调用方稍后想要访问的内容的指针。inode.i_private 指针将在 open() 调用时指向此值。

const struct file_operations *fops

指向应用于此文件的 struct file_operations 的指针。

loff_t file_size

初始文件大小

描述

这是 debugfs 的基本“创建文件”函数。它允许在创建文件或目录时具有广泛的灵活性(如果要创建目录,建议使用 debugfs_create_dir() 函数)。

struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)

在 debugfs 文件系统中创建一个目录

参数

const char *name

指向包含要创建的目录的名称的字符串的指针。

struct dentry *parent

指向此文件的父 dentry 的指针。如果设置,这应为目录 dentry。如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该目录。

描述

此函数使用给定的名称在 debugfs 中创建一个目录。

如果此函数成功,将返回指向 dentry 的指针。删除文件时,必须将此指针传递给 debugfs_remove() 函数(如果您的模块已卸载,则不会自动清理,您在此处负责。)如果发生错误,将返回 ERR_PTR(-ERROR)。

如果内核中未启用 debugfs,将返回值 -ENODEV

注意

期望大多数调用方应 _ignore_ 此函数返回的错误。其他 debugfs 函数会处理传递给它们的“dentry”可能是错误的事实,并且它们在这种情况下不会崩溃。即使 debugfs 无法初始化,驱动程序通常也能正常工作。

struct dentry *debugfs_create_automount(const char *name, struct dentry *parent, debugfs_automount_t f, void *data)

在 debugfs 文件系统中创建自动挂载点

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

struct dentry *parent

指向此文件的父 dentry 的指针。如果设置,这应为目录 dentry。如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

debugfs_automount_t f

当路径名解析步骤执行该步骤时要调用的函数。

void *data

要传递给 f() 的不透明参数。

描述

f 应返回 ->d_automount() 将返回的内容。

在 debugfs 文件系统中创建符号链接

参数

const char *name

指向包含要创建的符号链接的名称的字符串的指针。

struct dentry *parent

指向此符号链接的父 dentry 的指针。如果设置,这应为目录 dentry。如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建符号链接。

const char *target

指向包含符号链接目标的路径的字符串的指针。

描述

此函数使用给定的名称在 debugfs 中创建一个链接到给定目标路径的符号链接。

如果此函数成功,将返回指向 dentry 的指针。删除符号链接时,必须将此指针传递给 debugfs_remove() 函数(如果您的模块已卸载,则不会自动清理,您在此处负责。)如果发生错误,将返回 ERR_PTR(-ERROR)。

如果内核中未启用 debugfs,将返回值 -ENODEV

void debugfs_remove(struct dentry *dentry)

递归删除目录

参数

struct dentry *dentry

指向要删除的目录的 dentry 的指针。如果此参数为 NULL 或错误值,则不执行任何操作。

描述

此函数递归删除 debugfs 中的目录树,该目录树先前通过调用另一个 debugfs 函数(如 debugfs_create_file() 或其变体)创建。

需要调用此函数才能删除文件,当模块被删除时,不会自动清理文件,您在此处负责。

void debugfs_lookup_and_remove(const char *name, struct dentry *parent)

查找目录或文件并递归地删除它

参数

const char *name

指向包含要查找项目名称的字符串的指针。

struct dentry *parent

指向项目的父 dentry 的指针。

描述

这相当于执行类似 debugfs_remove(debugfs_lookup(..)) 的操作,但为正在查找的目录处理了正确的引用计数。

int debugfs_change_name(struct dentry *dentry, const char *fmt, ...)

在 debugfs 文件系统中重命名文件/目录

参数

struct dentry *dentry

要重命名的对象的 dentry。

const char *fmt

新名称的格式

...

可变参数

描述

此函数在 debugfs 中重命名文件/目录。目标必须不存在才能成功重命名。

此函数成功时返回 0,失败时返回 -E...

如果内核中未启用 debugfs,将返回值 -ENODEV

bool debugfs_initialized(void)

告知 debugfs 是否已注册

参数

void

无参数

int debugfs_file_get(struct dentry *dentry)

标记文件数据访问的开始

参数

struct dentry *dentry

正在访问数据的 dentry 对象。

描述

直到匹配的 debugfs_file_put() 调用为止,对文件删除函数 debugfs_remove() 和 debugfs_remove_recursive() 的任何后续调用都将阻塞。 由于关联的私有文件数据可能仅在任何删除函数成功返回后才能释放,因此您可以在成功调用 debugfs_file_get() 后安全地访问它,而不必担心生存期问题。

如果返回 -EIO,则该文件已被删除,因此访问其任何数据都是不安全的。 另一方面,如果允许访问文件数据,则返回零。

void debugfs_file_put(struct dentry *dentry)

标记文件数据访问的结束

参数

struct dentry *dentry

先前传递给 debugfs_file_get() 的 dentry 对象。

描述

允许任何正在进行的并发调用 debugfs_remove() 或 debugfs_remove_recursive() 被先前调用 debugfs_file_get() 阻止,以便继续并返回其调用方。

void debugfs_enter_cancellation(struct file *file, struct debugfs_cancellation *cancellation)

进入 debugfs 取消

参数

struct file *file

正在访问的文件

struct debugfs_cancellation *cancellation

取消对象,其中的取消回调必须已初始化

描述

删除 debugfs 文件时,它需要等待所有活动操作完成。 但是,操作本身可能需要等待硬件或某些异步进程的完成或类似情况。 因此,可能需要取消它以避免长时间的等待甚至死锁。

此函数可以在可能需要取消的 debugfs 处理程序中使用。 一旦调用此函数,就可以调用 cancellation 的“cancel”回调,此时调用者应继续调用 debugfs_leave_cancellation() 并尽快离开 debugfs 处理程序函数。 请注意,“cancel”回调仅在某种 debugfs_remove() 的上下文中调用。

此函数必须与 debugfs_leave_cancellation() 配对使用。

void debugfs_leave_cancellation(struct file *file, struct debugfs_cancellation *cancellation)

离开取消部分

参数

struct file *file

正在访问的文件

struct debugfs_cancellation *cancellation

先前使用 debugfs_enter_cancellation() 注册的取消

描述

请参阅 debugfs_enter_cancellation() 的文档。

void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, u8 *value)

创建一个 debugfs 文件,用于读取和写入无符号 8 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u8 *value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, u16 *value)

创建一个 debugfs 文件,用于读取和写入无符号 16 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u16 *value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, u32 *value)

创建一个 debugfs 文件,用于读取和写入无符号 32 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u32 *value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, u64 *value)

创建一个 debugfs 文件,用于读取和写入无符号 64 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u64 *value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

void debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, unsigned long *value)

创建一个 debugfs 文件,用于读取和写入无符号长整型值。

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

unsigned long *value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value)

创建一个 debugfs 文件,用于读取和写入无符号 8 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u8 *value

指向文件应从中读取和写入的变量的指针。

void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value)

创建一个 debugfs 文件,用于读取和写入无符号 16 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u16 *value

指向文件应从中读取和写入的变量的指针。

void debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, u32 *value)

创建一个 debugfs 文件,用于读取和写入无符号 32 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u32 *value

指向文件应从中读取和写入的变量的指针。

void debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, u64 *value)

创建一个 debugfs 文件,用于读取和写入无符号 64 位值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

u64 *value

指向文件应从中读取和写入的变量的指针。

void debugfs_create_size_t(const char *name, umode_t mode, struct dentry *parent, size_t *value)

创建一个 debugfs 文件,用于读取和写入 size_t 值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

size_t *value

指向文件应从中读取和写入的变量的指针。

void debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, atomic_t *value)

创建一个 debugfs 文件,用于读取和写入 atomic_t 值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

atomic_t *value

指向文件应从中读取和写入的变量的指针。

void debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, bool *value)

创建一个 debugfs 文件,用于读取和写入布尔值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

bool *value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

void debugfs_create_str(const char *name, umode_t mode, struct dentry *parent, char **value)

创建一个 debugfs 文件,用于读取和写入字符串值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

char **value

指向文件应从中读取和写入的变量的指针。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,其中包含变量 **value** 的值。 如果设置了 **mode** 变量,则可以从中读取和写入。

struct dentry *debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob)

创建一个 debugfs 文件,用于读写二进制 blob

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

struct debugfs_blob_wrapper *blob

指向 struct debugfs_blob_wrapper 的指针,该结构包含指向 blob 数据的指针和数据大小。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,该文件将 blob->data 导出为二进制 blob。如果设置了 mode 变量,则可以对其进行读取和写入。

如果此函数成功,将返回指向 dentry 的指针。删除文件时,必须将此指针传递给 debugfs_remove() 函数(如果您的模块已卸载,则不会自动清理,您在此处负责。)如果发生错误,将返回 ERR_PTR(-ERROR)。

如果内核中未启用 debugfs,则将返回 ERR_PTR(-ENODEV) 值。

void debugfs_create_u32_array(const char *name, umode_t mode, struct dentry *parent, struct debugfs_u32_array *array)

创建一个 debugfs 文件,用于读取 u32 数组。

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限。

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

struct debugfs_u32_array *array

包含数据指针和数组大小的包装结构体。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,该文件将 array 导出为数据。如果设置了 mode 变量,则可以读取该数据。不支持写入。也不支持在文件中搜索。一旦创建了数组,就无法更改其大小。

void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs, int nregs, void __iomem *base, char *prefix)

使用 seq_print 来描述一组寄存器

参数

struct seq_file *s

用于生成输出的 seq_file 结构

const struct debugfs_reg32 *regs

struct debugfs_reg32 结构体的数组

int nregs

上述数组的长度

void __iomem *base

用于读取寄存器的基地址

char *prefix

要添加到每个输出行前面的字符串

描述

此函数输出一个文本块,描述一些 32 位硬件寄存器的当前值。 它旨在用于基于 seq_file 的 debugfs 文件中,这些文件需要显示与其他信息混合的寄存器。 prefix 参数可用于指定前导字符串,因为某些外围设备具有多个相同的寄存器块,例如 dma 通道的配置

void debugfs_create_regset32(const char *name, umode_t mode, struct dentry *parent, struct debugfs_regset32 *regset)

创建一个 debugfs 文件,该文件返回寄存器值

参数

const char *name

指向包含要创建的文件的名称的字符串的指针。

umode_t mode

文件应具有的权限

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

struct debugfs_regset32 *regset

指向 struct debugfs_regset32 的指针,该结构包含指向寄存器定义数组的指针、数组大小和要查找寄存器组的基地址。

描述

此函数在 debugfs 中创建一个具有给定名称的文件,该文件报告一组 32 位寄存器的名称和值。如果设置了 mode 变量,则可以从中读取。不支持写入。

void debugfs_create_devm_seqfile(struct device *dev, const char *name, struct dentry *parent, int (*read_fn)(struct seq_file *s, void *data))

创建一个绑定到设备的 debugfs 文件。

参数

struct device *dev

与此 debugfs 文件相关的设备。

const char *name

debugfs 文件的名称。

struct dentry *parent

指向此文件的父 dentry 的指针。 如果设置,这应该是目录 dentry。 如果此参数为 NULL,则将在 debugfs 文件系统的根目录中创建该文件。

int (*read_fn)(struct seq_file *s, void *data)

用于打印 seq_file 内容的函数指针。