open("fileName", O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO) Get file descriptor for named file sys_open(const char __user *filename, int flags, int mode) do_sys_open(int dfd, const char __user *filename, int flags, int mode) getname(filename) Fetch file name string from user space __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL) Allocate a kernel buffer for string do_getname(filename, tmp) strncpy_from_user(page, filename, len) __do_strncpy_from_user(dst, src, count, res) <----return to getname() with kernel_ptr to file name string get_unused_fd() Look for empty slot in current process open file array do_filp_open(dfd, tmp, flags, mode) open_namei(dfd, filename, namei_flags, mode, &nd) path_lookup_open(dfd, pathname, lookup_flags(flag), nd, flag) path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode) __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE, nd, open_flags, create_mode) get_empty_filp() nd->intent.open.file = filp nd->intent.open.flags = open_flags nd->intent.open.create_mode = create_mode do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd) if (*name=='/') read_lock(¤t->fs->lock) nd->mnt = mntget(current->fs->rootmnt) nd->dentry = dget(current->fs->root) read_unlock(¤t->fs->lock) if (currentWorkingDirectory) read_lock(¤t->fs->lock) nd->mnt = mntget(current->fs->pwdmnt) nd->dentry = dget(current->fs->pwd) read_unlock(¤t->fs->lock link_path_walk(name, nd) dget(save.dentry) mntget(save.mnt) __link_path_walk(name, nd) exec_permission_lite(inode, nd) this.name = name c = *(const unsigned char *)name; hash = init_name_hash(); hash = partial_name_hash(c, hash); c = *(const unsigned char *)name; while (c && (c != '/')); this.len = name - (const char *) this.name; this.hash = end_name_hash(hash) do_lookup(nd, &this, &next) __d_lookup(nd->dentry, name) real_lookup(nd->dentry, name, nd) mutex_lock(&dir->i_mutex) d_lookup(parent, name) rcu_read_lock() spin_lock(&dentry->d_lock) memcmp(qstr->name, str, len) int res = 0 for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) if ((res = *su1 - *su2) != 0) break; return res; spin_unlock(&dentry->d_lock) rcu_read_unlock() return found or d_alloc(parent, name) mutex_unlock(&dir->i_mutex) <-return to real_lookup() result __follow_mount(path) <-return to __link_path_walk() dput(save.dentry) mntput(save.mnt) <-------return to path_lookup() dir = nd->dentry nd->flags &= ~LOOKUP_PARENT mutex_lock(&dir->d_inode->i_mutex) path.dentry = lookup_hash(nd) path.mnt = nd->mnt vfs_create(dir->d_inode, path.dentry, mode, nd) mutex_unlock(&dir->d_inode->i_mutex) __follow_mount(&path) path_to_nameidata(&path, nd) may_open(nd, acc_mode, flag) <-return to open_namei() nameidata_to_filp(&nd, flags) __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL) get_write_access(inode) spin_lock(&inode->i_lock) atomic_read(&inode->i_writecount) atomic_inc(&inode->i_writecount) spin_unlock(&inode->i_lock) f->f_mapping = inode->i_mapping; f->f_dentry = dentry; f->f_vfsmnt = mnt; f->f_pos = 0; f->f_op = fops_get(inode->i_fop) local_inc(&module->ref[cpu].count) file_move(f, &inode->i_sb->s_files) file_list_lock() list_move(struct list_head *list, struct list_head *head) __list_del(list->prev, list->next) list_add(list, head) file_list_unlock() f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC) file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping) ra->ra_pages = mapping->backing_dev_info->ra_pages ra->prev_page = -1 fops_put(f->f_op) module_put((fops)->owner) get_cpu() local_dec(&module->ref[cpu].count) if module_is_live(module) wake_up_process(module->waiter) put_cpu() put_write_access(inode) <-return to nameidata_to_filp() with f file_kill(f) file_list_lock() list_del_init(&file->f_u.fu_list); file_list_unlock() f->f_dentry = NULL f->f_vfsmnt = NULL put_filp(f) dput(dentry); mntput(mnt); <-return to nameidata_to_filp() with ERR_PTR(error) <-return to do_filp_open() with pointer to filp record put_unused_fd(fd) fsnotify_open(f->f_dentry) fd_install(fd, f) struct files_struct *files = current->files; struct fdtable *fdt; spin_lock(&files->file_lock); fdt = files_fdtable(files); BUG_ON(fdt->fd[fd] != NULL); rcu_assign_pointer(fdt->fd[fd], file); spin_unlock(&files->file_lock); putname(tmp) Remove kernel buffer for file name string <-return to sys_open() <-return to open() with file descriptor for named file