Lines Matching +full:serial +full:- +full:dir
1 // SPDX-License-Identifier: GPL-2.0-only
3 * proc/fs/generic.c --- generic routines for the proc-fs
5 * This file contains generic proc-fs routines for handling
39 if (S_ISLNK(pde->mode)) in pde_free()
40 kfree(pde->data); in pde_free()
41 if (pde->name != pde->inline_name) in pde_free()
42 kfree(pde->name); in pde_free()
48 if (len < de->namelen) in proc_match()
49 return -1; in proc_match()
50 if (len > de->namelen) in proc_match()
53 return memcmp(name, de->name, len); in proc_match()
56 static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir) in pde_subdir_first() argument
58 return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry, in pde_subdir_first()
62 static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir) in pde_subdir_next() argument
64 return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry, in pde_subdir_next()
68 static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir, in pde_subdir_find() argument
72 struct rb_node *node = dir->subdir.rb_node; in pde_subdir_find()
81 node = node->rb_left; in pde_subdir_find()
83 node = node->rb_right; in pde_subdir_find()
90 static bool pde_subdir_insert(struct proc_dir_entry *dir, in pde_subdir_insert() argument
93 struct rb_root *root = &dir->subdir; in pde_subdir_insert()
94 struct rb_node **new = &root->rb_node, *parent = NULL; in pde_subdir_insert()
101 int result = proc_match(de->name, this, de->namelen); in pde_subdir_insert()
105 new = &(*new)->rb_left; in pde_subdir_insert()
107 new = &(*new)->rb_right; in pde_subdir_insert()
113 rb_link_node(&de->subdir_node, parent, new); in pde_subdir_insert()
114 rb_insert_color(&de->subdir_node, root); in pde_subdir_insert()
131 proc_set_user(de, inode->i_uid, inode->i_gid); in proc_notify_change()
132 de->mode = inode->i_mode; in proc_notify_change()
140 struct inode *inode = d_inode(path->dentry); in proc_getattr()
143 nlink_t nlink = READ_ONCE(de->nlink); in proc_getattr()
158 * This function parses a name such as "tty/driver/serial", and
160 * returns "serial" in residual.
170 de = pde_subdir_find(de, cp, next - cp); in __xlate_proc_name()
173 return -ENOENT; in __xlate_proc_name()
205 i = ida_alloc_max(&proc_inum_ida, UINT_MAX - PROC_DYNAMIC_FIRST, in proc_alloc_inum()
216 ida_free(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST); in proc_free_inum()
219 static int proc_misc_d_revalidate(struct inode *dir, const struct qstr *name, in proc_misc_d_revalidate() argument
223 return -ECHILD; in proc_misc_d_revalidate()
225 if (atomic_read(&PDE(d_inode(dentry))->in_use) < 0) in proc_misc_d_revalidate()
232 return atomic_read(&PDE(d_inode(dentry))->in_use) < 0; in proc_misc_d_delete()
241 * Don't create negative dentries here, return -ENOENT by hand
244 struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry, in proc_lookup_de() argument
250 de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len); in proc_lookup_de()
254 inode = proc_get_inode(dir->i_sb, de); in proc_lookup_de()
256 return ERR_PTR(-ENOMEM); in proc_lookup_de()
257 if (de->flags & PROC_ENTRY_FORCE_LOOKUP) in proc_lookup_de()
264 return ERR_PTR(-ENOENT); in proc_lookup_de()
267 struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, in proc_lookup() argument
270 struct proc_fs_info *fs_info = proc_sb_info(dir->i_sb); in proc_lookup()
272 if (fs_info->pidonly == PROC_PIDONLY_ON) in proc_lookup()
273 return ERR_PTR(-ENOENT); in proc_lookup()
275 return proc_lookup_de(dir, dentry, PDE(dir)); in proc_lookup()
279 * This returns non-zero if at EOF, so that the /proc
283 * Note that the VFS-layer doesn't care about the return
284 * value of the readdir() call, as long as it's non-negative
295 i = ctx->pos - 2; in proc_readdir_de()
306 i--; in proc_readdir_de()
313 if (!dir_emit(ctx, de->name, de->namelen, in proc_readdir_de()
314 de->low_ino, de->mode >> 12)) { in proc_readdir_de()
318 ctx->pos++; in proc_readdir_de()
331 struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb); in proc_readdir()
333 if (fs_info->pidonly == PROC_PIDONLY_ON) in proc_readdir()
341 * use the in-memory "struct proc_dir_entry" tree to parse
350 static int proc_net_d_revalidate(struct inode *dir, const struct qstr *name, in proc_net_d_revalidate() argument
372 const struct proc_ops *proc_ops = pde->proc_ops; in pde_set_flags()
377 if (proc_ops->proc_flags & PROC_ENTRY_PERMANENT) in pde_set_flags()
378 pde->flags |= PROC_ENTRY_PERMANENT; in pde_set_flags()
379 if (proc_ops->proc_read_iter) in pde_set_flags()
380 pde->flags |= PROC_ENTRY_proc_read_iter; in pde_set_flags()
382 if (proc_ops->proc_compat_ioctl) in pde_set_flags()
383 pde->flags |= PROC_ENTRY_proc_compat_ioctl; in pde_set_flags()
385 if (proc_ops->proc_lseek) in pde_set_flags()
386 pde->flags |= PROC_ENTRY_proc_lseek; in pde_set_flags()
390 struct proc_dir_entry *proc_register(struct proc_dir_entry *dir, in proc_register() argument
393 if (proc_alloc_inum(&dp->low_ino)) in proc_register()
396 if (!S_ISDIR(dp->mode)) in proc_register()
400 dp->parent = dir; in proc_register()
401 if (pde_subdir_insert(dir, dp) == false) { in proc_register()
403 dir->name, dp->name); in proc_register()
407 dir->nlink++; in proc_register()
412 proc_free_inum(dp->low_ino); in proc_register()
457 ent->name = ent->inline_name; in __proc_create()
459 ent->name = kmalloc(qstr.len + 1, GFP_KERNEL); in __proc_create()
460 if (!ent->name) { in __proc_create()
466 memcpy(ent->name, fn, qstr.len + 1); in __proc_create()
467 ent->namelen = qstr.len; in __proc_create()
468 ent->mode = mode; in __proc_create()
469 ent->nlink = nlink; in __proc_create()
470 ent->subdir = RB_ROOT; in __proc_create()
471 refcount_set(&ent->refcnt, 1); in __proc_create()
472 spin_lock_init(&ent->pde_unload_lock); in __proc_create()
473 INIT_LIST_HEAD(&ent->pde_openers); in __proc_create()
474 proc_set_user(ent, (*parent)->uid, (*parent)->gid); in __proc_create()
477 if ((*parent)->flags & PROC_ENTRY_FORCE_LOOKUP) in __proc_create()
493 ent->size = strlen(dest); in proc_symlink()
494 ent->data = kmemdup(dest, ent->size + 1, GFP_KERNEL); in proc_symlink()
495 if (ent->data) { in proc_symlink()
496 ent->proc_iops = &proc_link_inode_operations; in proc_symlink()
517 ent->data = data; in _proc_mkdir()
518 ent->proc_dir_ops = &proc_dir_operations; in _proc_mkdir()
519 ent->proc_iops = &proc_dir_inode_operations; in _proc_mkdir()
557 ent->data = NULL; in proc_create_mount_point()
558 ent->proc_dir_ops = NULL; in proc_create_mount_point()
559 ent->proc_iops = NULL; in proc_create_mount_point()
580 p->proc_iops = &proc_file_inode_operations; in proc_create_reg()
581 p->data = data; in proc_create_reg()
595 p->proc_ops = proc_ops; in proc_create_data()
612 if (de->state_size) in proc_seq_open()
613 return seq_open_private(file, de->seq_ops, de->state_size); in proc_seq_open()
614 return seq_open(file, de->seq_ops); in proc_seq_open()
621 if (de->state_size) in proc_seq_release()
627 /* not permanent -- can call into arbitrary seq_operations */
643 p->proc_ops = &proc_seq_ops; in proc_create_seq_private()
644 p->seq_ops = ops; in proc_create_seq_private()
645 p->state_size = state_size; in proc_create_seq_private()
654 return single_open(file, de->single_show, de->data); in proc_single_open()
658 /* not permanent -- can call into arbitrary ->single_show */
674 p->proc_ops = &proc_single_ops; in proc_create_single_data()
675 p->single_show = show; in proc_create_single_data()
682 de->size = size; in proc_set_size()
688 de->uid = uid; in proc_set_user()
689 de->gid = gid; in proc_set_user()
695 if (refcount_dec_and_test(&pde->refcnt)) { in pde_put()
696 proc_free_inum(pde->low_ino); in pde_put()
720 WARN(1, "removing permanent /proc entry '%s'", de->name); in remove_proc_entry()
723 rb_erase(&de->subdir_node, &parent->subdir); in remove_proc_entry()
724 if (S_ISDIR(de->mode)) in remove_proc_entry()
725 parent->nlink--; in remove_proc_entry()
737 "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n", in remove_proc_entry()
738 __func__, de->parent->name, de->name, pde_subdir_first(de)->name); in remove_proc_entry()
752 return -ENOENT; in remove_proc_subtree()
759 return -ENOENT; in remove_proc_subtree()
764 root->parent->name, root->name); in remove_proc_subtree()
765 return -EINVAL; in remove_proc_subtree()
767 rb_erase(&root->subdir_node, &parent->subdir); in remove_proc_subtree()
776 next->parent->name, next->name); in remove_proc_subtree()
777 return -EINVAL; in remove_proc_subtree()
779 rb_erase(&next->subdir_node, &de->subdir); in remove_proc_subtree()
783 next = de->parent; in remove_proc_subtree()
784 if (S_ISDIR(de->mode)) in remove_proc_subtree()
785 next->nlink--; in remove_proc_subtree()
804 return de->parent->data; in proc_get_parent_data()
811 remove_proc_subtree(de->name, de->parent); in proc_remove()
817 * one is supplied. The ->write() method is permitted to modify the
818 * kernel-side buffer.
827 if (!pde->write) in proc_simple_write()
828 return -EACCES; in proc_simple_write()
829 if (size == 0 || size > PAGE_SIZE - 1) in proc_simple_write()
830 return -EINVAL; in proc_simple_write()
834 ret = pde->write(f, buf, size); in proc_simple_write()