Lines Matching +full:next +full:- +full:mode

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()
58 return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry, in pde_subdir_first()
64 return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry, in pde_subdir_next()
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()
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()
165 const char *cp = name, *next; in __xlate_proc_name() local
169 while ((next = strchr(cp, '/')) != NULL) { in __xlate_proc_name()
170 de = pde_subdir_find(de, cp, next - cp); in __xlate_proc_name()
173 return -ENOENT; in __xlate_proc_name()
175 cp = next + 1; 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()
222 return -ECHILD; in proc_misc_d_revalidate()
224 if (atomic_read(&PDE(d_inode(dentry))->in_use) < 0) in proc_misc_d_revalidate()
231 return atomic_read(&PDE(d_inode(dentry))->in_use) < 0; in proc_misc_d_delete()
240 * Don't create negative dentries here, return -ENOENT by hand
249 de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len); in proc_lookup_de()
253 inode = proc_get_inode(dir->i_sb, de); in proc_lookup_de()
255 return ERR_PTR(-ENOMEM); in proc_lookup_de()
256 d_set_d_op(dentry, de->proc_dops); in proc_lookup_de()
260 return ERR_PTR(-ENOENT); in proc_lookup_de()
266 struct proc_fs_info *fs_info = proc_sb_info(dir->i_sb); in proc_lookup()
268 if (fs_info->pidonly == PROC_PIDONLY_ON) in proc_lookup()
269 return ERR_PTR(-ENOENT); in proc_lookup()
275 * This returns non-zero if at EOF, so that the /proc
279 * Note that the VFS-layer doesn't care about the return
280 * value of the readdir() call, as long as it's non-negative
291 i = ctx->pos - 2; in proc_readdir_de()
302 i--; in proc_readdir_de()
306 struct proc_dir_entry *next; in proc_readdir_de() local
309 if (!dir_emit(ctx, de->name, de->namelen, in proc_readdir_de()
310 de->low_ino, de->mode >> 12)) { in proc_readdir_de()
314 ctx->pos++; in proc_readdir_de()
316 next = pde_subdir_next(de); in proc_readdir_de()
318 de = next; in proc_readdir_de()
327 struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb); in proc_readdir()
329 if (fs_info->pidonly == PROC_PIDONLY_ON) in proc_readdir()
337 * use the in-memory "struct proc_dir_entry" tree to parse
369 if (proc_alloc_inum(&dp->low_ino)) in proc_register()
373 dp->parent = dir; in proc_register()
376 dir->name, dp->name); in proc_register()
380 dir->nlink++; in proc_register()
385 proc_free_inum(dp->low_ino); in proc_register()
393 umode_t mode, in __proc_create() argument
430 ent->name = ent->inline_name; in __proc_create()
432 ent->name = kmalloc(qstr.len + 1, GFP_KERNEL); in __proc_create()
433 if (!ent->name) { in __proc_create()
439 memcpy(ent->name, fn, qstr.len + 1); in __proc_create()
440 ent->namelen = qstr.len; in __proc_create()
441 ent->mode = mode; in __proc_create()
442 ent->nlink = nlink; in __proc_create()
443 ent->subdir = RB_ROOT; in __proc_create()
444 refcount_set(&ent->refcnt, 1); in __proc_create()
445 spin_lock_init(&ent->pde_unload_lock); in __proc_create()
446 INIT_LIST_HEAD(&ent->pde_openers); in __proc_create()
447 proc_set_user(ent, (*parent)->uid, (*parent)->gid); in __proc_create()
449 ent->proc_dops = &proc_misc_dentry_ops; in __proc_create()
451 if ((*parent)->proc_dops == &proc_net_dentry_ops) in __proc_create()
467 ent->size = strlen(dest); in proc_symlink()
468 ent->data = kmemdup(dest, ent->size + 1, GFP_KERNEL); in proc_symlink()
469 if (ent->data) { in proc_symlink()
470 ent->proc_iops = &proc_link_inode_operations; in proc_symlink()
481 struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode, in _proc_mkdir() argument
486 if (mode == 0) in _proc_mkdir()
487 mode = S_IRUGO | S_IXUGO; in _proc_mkdir()
489 ent = __proc_create(&parent, name, S_IFDIR | mode, 2); in _proc_mkdir()
491 ent->data = data; in _proc_mkdir()
492 ent->proc_dir_ops = &proc_dir_operations; in _proc_mkdir()
493 ent->proc_iops = &proc_dir_inode_operations; in _proc_mkdir()
503 struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, in proc_mkdir_data() argument
506 return _proc_mkdir(name, mode, parent, data, false); in proc_mkdir_data()
510 struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode, in proc_mkdir_mode() argument
513 return proc_mkdir_data(name, mode, parent, NULL); in proc_mkdir_mode()
526 umode_t mode = S_IFDIR | S_IRUGO | S_IXUGO; in proc_create_mount_point() local
529 ent = __proc_create(&parent, name, mode, 2); in proc_create_mount_point()
531 ent->data = NULL; in proc_create_mount_point()
532 ent->proc_dir_ops = NULL; in proc_create_mount_point()
533 ent->proc_iops = NULL; in proc_create_mount_point()
540 struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode, in proc_create_reg() argument
545 if ((mode & S_IFMT) == 0) in proc_create_reg()
546 mode |= S_IFREG; in proc_create_reg()
547 if ((mode & S_IALLUGO) == 0) in proc_create_reg()
548 mode |= S_IRUGO; in proc_create_reg()
549 if (WARN_ON_ONCE(!S_ISREG(mode))) in proc_create_reg()
552 p = __proc_create(parent, name, mode, 1); in proc_create_reg()
554 p->proc_iops = &proc_file_inode_operations; in proc_create_reg()
555 p->data = data; in proc_create_reg()
562 if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT) in pde_set_flags()
563 pde->flags |= PROC_ENTRY_PERMANENT; in pde_set_flags()
566 struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, in proc_create_data() argument
572 p = proc_create_reg(name, mode, &parent, data); in proc_create_data()
575 p->proc_ops = proc_ops; in proc_create_data()
581 struct proc_dir_entry *proc_create(const char *name, umode_t mode, in proc_create() argument
585 return proc_create_data(name, mode, parent, proc_ops, NULL); in proc_create()
593 if (de->state_size) in proc_seq_open()
594 return seq_open_private(file, de->seq_ops, de->state_size); in proc_seq_open()
595 return seq_open(file, de->seq_ops); in proc_seq_open()
602 if (de->state_size) in proc_seq_release()
608 /* not permanent -- can call into arbitrary seq_operations */
615 struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode, in proc_create_seq_private() argument
621 p = proc_create_reg(name, mode, &parent, data); in proc_create_seq_private()
624 p->proc_ops = &proc_seq_ops; in proc_create_seq_private()
625 p->seq_ops = ops; in proc_create_seq_private()
626 p->state_size = state_size; in proc_create_seq_private()
635 return single_open(file, de->single_show, de->data); in proc_single_open()
639 /* not permanent -- can call into arbitrary ->single_show */
646 struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode, in proc_create_single_data() argument
652 p = proc_create_reg(name, mode, &parent, data); in proc_create_single_data()
655 p->proc_ops = &proc_single_ops; in proc_create_single_data()
656 p->single_show = show; in proc_create_single_data()
663 de->size = size; in proc_set_size()
669 de->uid = uid; in proc_set_user()
670 de->gid = gid; in proc_set_user()
676 if (refcount_dec_and_test(&pde->refcnt)) { in pde_put()
677 proc_free_inum(pde->low_ino); in pde_put()
701 WARN(1, "removing permanent /proc entry '%s'", de->name); in remove_proc_entry()
704 rb_erase(&de->subdir_node, &parent->subdir); in remove_proc_entry()
705 if (S_ISDIR(de->mode)) in remove_proc_entry()
706 parent->nlink--; in remove_proc_entry()
718 "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n", in remove_proc_entry()
719 __func__, de->parent->name, de->name, pde_subdir_first(de)->name); in remove_proc_entry()
726 struct proc_dir_entry *root = NULL, *de, *next; in remove_proc_subtree() local
733 return -ENOENT; in remove_proc_subtree()
740 return -ENOENT; in remove_proc_subtree()
745 root->parent->name, root->name); in remove_proc_subtree()
746 return -EINVAL; in remove_proc_subtree()
748 rb_erase(&root->subdir_node, &parent->subdir); in remove_proc_subtree()
752 next = pde_subdir_first(de); in remove_proc_subtree()
753 if (next) { in remove_proc_subtree()
754 if (unlikely(pde_is_permanent(next))) { in remove_proc_subtree()
757 next->parent->name, next->name); in remove_proc_subtree()
758 return -EINVAL; in remove_proc_subtree()
760 rb_erase(&next->subdir_node, &de->subdir); in remove_proc_subtree()
761 de = next; in remove_proc_subtree()
764 next = de->parent; in remove_proc_subtree()
765 if (S_ISDIR(de->mode)) in remove_proc_subtree()
766 next->nlink--; in remove_proc_subtree()
775 de = next; in remove_proc_subtree()
785 return de->parent->data; in proc_get_parent_data()
792 remove_proc_subtree(de->name, de->parent); in proc_remove()
798 * one is supplied. The ->write() method is permitted to modify the
799 * kernel-side buffer.
808 if (!pde->write) in proc_simple_write()
809 return -EACCES; in proc_simple_write()
810 if (size == 0 || size > PAGE_SIZE - 1) in proc_simple_write()
811 return -EINVAL; in proc_simple_write()
815 ret = pde->write(f, buf, size); in proc_simple_write()