struct file *do_last(struct nameidata *nd, struct path *path,
int open_flag, int acc_mode,
int mode, const char *pathname)
{
struct dentry *dir = nd->path.dentry;
/* just plain open? */
if (!(open_flag & O_CREAT)){
error = do_lookup(nd, &nd->last, path);
if (error)
goto exit;
/*#define ENOENT 2 /* No such file or directory */*/
error = -ENOENT; //非创建模式如果找不到就上报错误
if (!path->dentry->d_inode)
goto exit_dput;
if (path->dentry->d_inode->i_op->follow_link)
return NULL;
/*#define ENOTDIR 20 /* Not a directory */*/
error = -ENOTDIR;
}
/* OK, it's O_CREAT */
path->dentry = lookup_hash(nd);
=>struct dentry *lookup_hash(struct nameidata *nd)
{
return __lookup_hash(&nd->last, nd->path.dentry, nd);
=>struct dentry *__lookup_hash(struct qstr *name,
struct dentry *base, struct nameidata *nd)
{
inode = base->d_inode;
dentry = __d_lookup(base, name);
if (!dentry)
dentry = d_lookup(base, name);
if (!dentry) {
struct dentry *new;
new = d_alloc(base, name);//申请dentry空间
dentry = inode->i_op->lookup(inode, new, nd);
=>struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
/*根据文件名找节点号,找不到则返回空*/
ino = ext2_inode_by_name(dir, &dentry->d_name);
if (ino) {
inode = ext2_iget(dir->i_sb, ino);
}
return d_splice_alias(inode, dentry);
}
/*不存在则创建新dentry*/
if (!dentry)
dentry = new;
else
dput(new);
}
return dentry;
}
}
path->mnt = nd->path.mnt;
/* Negative dentry, just create the file */
if (!path->dentry->d_inode) {
error = __open_namei_create(nd, path, open_flag, mode);
=>int __open_namei_create(struct nameidata *nd, struct path *path,
int open_flag, int mode)
{
struct dentry *dir = nd->path.dentry;
error = vfs_create(dir->d_inode, path->dentry, mode, nd);
/*创建dentry对应的inode节点*/
=>int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
error = dir->i_op->create(dir, dentry, mode, nd);
=>int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
{
inode = ext2_new_inode(dir, mode);
inode->i_op = &ext2_file_inode_operations;
if (ext2_use_xip(inode->i_sb)) {
inode->i_mapping->a_ops = &ext2_aops_xip;
inode->i_fop = &ext2_xip_file_operations;
} else if (test_opt(inode->i_sb, NOBH)) {
inode->i_mapping->a_ops = &ext2_nobh_aops;
inode->i_fop = &ext2_file_operations;
} else {
inode->i_mapping->a_ops = &ext2_aops;
inode->i_fop = &ext2_file_operations;
}
mark_inode_dirty(inode);
return ext2_add_nondir(dentry, inode);
}
return error;
}
dput(nd->path.dentry);
nd->path.dentry = path->dentry;
return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
}
}
}