Content #
如果创建一个新文件,会调用 open 函数,并且参数会有 O_CREAT。这表示当文件找不到的时候,就需要创建一个。open 是一个系统调用,在内核里面会调用 sys_open,定义如下:
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, filename, flags, mode);
}
调用链:
do_sys_open-> do_filp_open->path_openat->do_last->lookup_open
这个调用链的逻辑是,要打开一个文件,先要根据路径找到文件夹。如果发现文件夹下面没有这个文件,同时又设置了 O_CREAT,就说明要在这个文件夹下面创建一个文件,那就需要一个新的 inode。
static int lookup_open(struct nameidata *nd, struct path *path,
struct file *file,
const struct open_flags *op,
bool got_write, int *opened)
{
......
if (!dentry->d_inode && (open_flag & O_CREAT)) {
......
error = dir_inode->i_op->create(dir_inode, dentry, mode,
open_flag & O_EXCL);
......
}
......
}
想要创建新的 inode,就要调用 dir_inode,也就是文件夹的 inode 的 create 函数。它的具体定义是这样的:
const struct inode_operations ext4_dir_inode_operations = {
.create = ext4_create,
.lookup = ext4_lookup,
.link = ext4_link,
.unlink = ext4_unlink,
.symlink = ext4_symlink,
.mkdir = ext4_mkdir,
.rmdir = ext4_rmdir,
.mknod = ext4_mknod,
.tmpfile = ext4_tmpfile,
.rename = ext4_rename2,
.setattr = ext4_setattr,
.getattr = ext4_getattr,
.listxattr = ext4_listxattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
};
create 操作调用的是 ext4_create。
接下来的调用链是这样的:
ext4_create->ext4_new_inode_start_handle->__ext4_new_inode
在 __ext4_new_inode 函数中,会创建新的 inode。
struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
umode_t mode, const struct qstr *qstr,
__u32 goal, uid_t *owner, __u32 i_flags,
int handle_type, unsigned int line_no,
int nblocks)
{
......
inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
......
ino = ext4_find_next_zero_bit((unsigned long *)
inode_bitmap_bh->b_data,
EXT4_INODES_PER_GROUP(sb), ino);
......
}
从文件系统里面读取 inode 位图,然后找到下一个为 0 的 inode,就是空闲的 inode。