^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * fs/sysfs/file.c - sysfs regular (text) file implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2001-3 Patrick Mochel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2007 SUSE Linux Products GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Please see Documentation/filesystems/sysfs.rst for more information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "sysfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Determine ktype->sysfs_ops for the given kernfs_node. This function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * must be called while holding an active reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct kobject *kobj = kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (kn->flags & KERNFS_LOCKDEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) lockdep_assert_held(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Reads on sysfs are handled through seq_file, which takes care of hairy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * details like buffering and seeking. The following function pipes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * sysfs_ops->show() result through seq_file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct kernfs_open_file *of = sf->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct kobject *kobj = of->kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ssize_t count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) count = seq_get_buf(sf, &buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (count < PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) seq_commit(sf, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) memset(buf, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Invoke show(). Control may reach here via seq file lseek even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * if @ops->show() isn't implemented.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (ops->show) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) count = ops->show(kobj, of->kn->priv, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (count < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * The code works fine with PAGE_SIZE return but it's likely to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * indicate truncated result or overflow in normal use cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (count >= (ssize_t)PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) printk("fill_read_buffer: %pS returned bad count\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ops->show);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Try to struggle along */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) count = PAGE_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) seq_commit(sf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct bin_attribute *battr = of->kn->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct kobject *kobj = of->kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) loff_t size = file_inode(of->file)->i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (pos >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (pos + count > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) count = size - pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!battr->read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return battr->read(of->file, kobj, battr, buf, pos, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* kernfs read callback for regular sysfs files with pre-alloc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct kobject *kobj = of->kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * If buf != of->prealloc_buf, we don't know how
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * large it is, so cannot safely pass it to ->show
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (WARN_ON_ONCE(buf != of->prealloc_buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) len = ops->show(kobj, of->kn->priv, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (len <= pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) len -= pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) memmove(buf, buf + pos, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return min_t(ssize_t, count, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* kernfs write callback for regular sysfs files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct kobject *kobj = of->kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return ops->store(kobj, of->kn->priv, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* kernfs write callback for bin sysfs files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct bin_attribute *battr = of->kn->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct kobject *kobj = of->kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) loff_t size = file_inode(of->file)->i_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (size <= pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) count = min_t(ssize_t, count, size - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!battr->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return battr->write(of->file, kobj, battr, buf, pos, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct bin_attribute *battr = of->kn->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct kobject *kobj = of->kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return battr->mmap(of->file, kobj, battr, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct kernfs_node *kn = kobj->sd, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (kn && dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) kn = kernfs_find_and_get(kn, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) kernfs_get(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (kn && attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) tmp = kernfs_find_and_get(kn, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kn = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (kn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) kernfs_notify(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) EXPORT_SYMBOL_GPL(sysfs_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static const struct kernfs_ops sysfs_file_kfops_empty = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static const struct kernfs_ops sysfs_file_kfops_ro = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .seq_show = sysfs_kf_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static const struct kernfs_ops sysfs_file_kfops_wo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .write = sysfs_kf_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static const struct kernfs_ops sysfs_file_kfops_rw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .seq_show = sysfs_kf_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .write = sysfs_kf_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static const struct kernfs_ops sysfs_prealloc_kfops_ro = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .read = sysfs_kf_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .prealloc = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static const struct kernfs_ops sysfs_prealloc_kfops_wo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .write = sysfs_kf_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .prealloc = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static const struct kernfs_ops sysfs_prealloc_kfops_rw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .read = sysfs_kf_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .write = sysfs_kf_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .prealloc = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static const struct kernfs_ops sysfs_bin_kfops_ro = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .read = sysfs_kf_bin_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static const struct kernfs_ops sysfs_bin_kfops_wo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .write = sysfs_kf_bin_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct kernfs_ops sysfs_bin_kfops_rw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .read = sysfs_kf_bin_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .write = sysfs_kf_bin_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct kernfs_ops sysfs_bin_kfops_mmap = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .read = sysfs_kf_bin_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .write = sysfs_kf_bin_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .mmap = sysfs_kf_bin_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int sysfs_add_file_mode_ns(struct kernfs_node *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) const struct attribute *attr, bool is_bin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) umode_t mode, kuid_t uid, kgid_t gid, const void *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct lock_class_key *key = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) const struct kernfs_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) loff_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!is_bin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct kobject *kobj = parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* every kobject with an attribute needs a ktype assigned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (WARN(!sysfs_ops, KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) "missing sysfs attribute operations for kobject: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) kobject_name(kobj)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (sysfs_ops->show && sysfs_ops->store) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (mode & SYSFS_PREALLOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ops = &sysfs_prealloc_kfops_rw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ops = &sysfs_file_kfops_rw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) } else if (sysfs_ops->show) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (mode & SYSFS_PREALLOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ops = &sysfs_prealloc_kfops_ro;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ops = &sysfs_file_kfops_ro;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) } else if (sysfs_ops->store) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (mode & SYSFS_PREALLOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ops = &sysfs_prealloc_kfops_wo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ops = &sysfs_file_kfops_wo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ops = &sysfs_file_kfops_empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) size = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct bin_attribute *battr = (void *)attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (battr->mmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ops = &sysfs_bin_kfops_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) else if (battr->read && battr->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ops = &sysfs_bin_kfops_rw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) else if (battr->read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ops = &sysfs_bin_kfops_ro;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) else if (battr->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ops = &sysfs_bin_kfops_wo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ops = &sysfs_file_kfops_empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) size = battr->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #ifdef CONFIG_DEBUG_LOCK_ALLOC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!attr->ignore_lockdep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) key = attr->key ?: (struct lock_class_key *)&attr->skey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) size, ops, (void *)attr, ns, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (IS_ERR(kn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (PTR_ERR(kn) == -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) sysfs_warn_dup(parent, attr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return PTR_ERR(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * sysfs_create_file_ns - create an attribute file for an object with custom ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * @kobj: object we're creating for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * @attr: attribute descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * @ns: namespace the new file should belong to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) const void *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) kgid_t gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (WARN_ON(!kobj || !kobj->sd || !attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) kobject_get_ownership(kobj, &uid, &gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) uid, gid, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int sysfs_create_files(struct kobject *kobj, const struct attribute * const *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) for (i = 0; ptr[i] && !err; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) err = sysfs_create_file(kobj, ptr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) while (--i >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) sysfs_remove_file(kobj, ptr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) EXPORT_SYMBOL_GPL(sysfs_create_files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * @kobj: object we're acting for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * @attr: attribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @group: group name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int sysfs_add_file_to_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) const struct attribute *attr, const char *group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct kernfs_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) kgid_t gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) parent = kernfs_find_and_get(kobj->sd, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) parent = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) kernfs_get(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) kobject_get_ownership(kobj, &uid, &gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) error = sysfs_add_file_mode_ns(parent, attr, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) attr->mode, uid, gid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) kernfs_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * sysfs_chmod_file - update the modified mode value on an object attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * @kobj: object we're acting for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * @attr: attribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * @mode: file permissions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct iattr newattrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) kn = kernfs_find_and_get(kobj->sd, attr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) newattrs.ia_mode = (mode & S_IALLUGO) | (kn->mode & ~S_IALLUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) newattrs.ia_valid = ATTR_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) rc = kernfs_setattr(kn, &newattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) EXPORT_SYMBOL_GPL(sysfs_chmod_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * sysfs_break_active_protection - break "active" protection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @kobj: The kernel object @attr is associated with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * @attr: The attribute to break the "active" protection for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * With sysfs, just like kernfs, deletion of an attribute is postponed until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * all active .show() and .store() callbacks have finished unless this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * is called. Hence this function is useful in methods that implement self
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * deletion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) const struct attribute *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) kobject_get(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) kn = kernfs_find_and_get(kobj->sd, attr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) kernfs_break_active_protection(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * sysfs_unbreak_active_protection - restore "active" protection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * @kn: Pointer returned by sysfs_break_active_protection().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * Undo the effects of sysfs_break_active_protection(). Since this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * calls kernfs_put() on the kernfs node that corresponds to the 'attr'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * argument passed to sysfs_break_active_protection() that attribute may have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * been removed between the sysfs_break_active_protection() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * this function has returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) void sysfs_unbreak_active_protection(struct kernfs_node *kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct kobject *kobj = kn->parent->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) kernfs_unbreak_active_protection(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) kobject_put(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * @kobj: object we're acting for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * @attr: attribute descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * @ns: namespace tag of the file to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * Hash the attribute name and namespace tag and kill the victim.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) const void *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct kernfs_node *parent = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) kernfs_remove_by_name_ns(parent, attr->name, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * sysfs_remove_file_self - remove an object attribute from its own method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * @kobj: object we're acting for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * @attr: attribute descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * See kernfs_remove_self() for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct kernfs_node *parent = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) kn = kernfs_find_and_get(parent, attr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (WARN_ON_ONCE(!kn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ret = kernfs_remove_self(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) EXPORT_SYMBOL_GPL(sysfs_remove_file_self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) for (i = 0; ptr[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) sysfs_remove_file(kobj, ptr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) EXPORT_SYMBOL_GPL(sysfs_remove_files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * sysfs_remove_file_from_group - remove an attribute file from a group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * @kobj: object we're acting for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * @attr: attribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * @group: group name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) void sysfs_remove_file_from_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) const struct attribute *attr, const char *group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct kernfs_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) parent = kernfs_find_and_get(kobj->sd, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) parent = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) kernfs_get(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) kernfs_remove_by_name(parent, attr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) kernfs_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * sysfs_create_bin_file - create binary file for object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * @kobj: object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * @attr: attribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int sysfs_create_bin_file(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) const struct bin_attribute *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) kgid_t gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (WARN_ON(!kobj || !kobj->sd || !attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) kobject_get_ownership(kobj, &uid, &gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) attr->attr.mode, uid, gid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * sysfs_remove_bin_file - remove binary file for object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * @kobj: object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * @attr: attribute descriptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) void sysfs_remove_bin_file(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) const struct bin_attribute *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) kernfs_remove_by_name(kobj->sd, attr->attr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) kgid_t kgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct iattr newattrs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .ia_valid = ATTR_UID | ATTR_GID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .ia_uid = kuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .ia_gid = kgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return kernfs_setattr(kn, &newattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * sysfs_link_change_owner - change owner of a sysfs file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * @kobj: object of the kernfs_node the symlink is located in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * @targ: object of the kernfs_node the symlink points to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * @name: name of the link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * @kuid: new owner's kuid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @kgid: new owner's kgid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * This function looks up the sysfs symlink entry @name under @kobj and changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * the ownership to @kuid/@kgid. The symlink is looked up in the namespace of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * @targ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) const char *name, kuid_t kuid, kgid_t kgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct kernfs_node *kn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!name || !kobj->state_in_sysfs || !targ->state_in_sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) kn = kernfs_find_and_get_ns(kobj->sd, name, targ->sd->ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (kernfs_type(kn) != KERNFS_LINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (kn->symlink.target_kn->priv != targ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) error = internal_change_owner(kn, kuid, kgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * sysfs_file_change_owner - change owner of a sysfs file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * @kobj: object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * @name: name of the file to change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * @kuid: new owner's kuid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * @kgid: new owner's kgid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * This function looks up the sysfs entry @name under @kobj and changes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * ownership to @kuid/@kgid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) kgid_t kgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (!kobj->state_in_sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) kn = kernfs_find_and_get(kobj->sd, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (!kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) error = internal_change_owner(kn, kuid, kgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) EXPORT_SYMBOL_GPL(sysfs_file_change_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * sysfs_change_owner - change owner of the given object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * @kobj: object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * @kuid: new owner's kuid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * @kgid: new owner's kgid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * Change the owner of the default directory, files, groups, and attributes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * @kobj to @kuid/@kgid. Note that sysfs_change_owner mirrors how the sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * entries for a kobject are added by driver core. In summary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * sysfs_change_owner() takes care of the default directory entry for @kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * the default attributes associated with the ktype of @kobj and the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * attributes associated with the ktype of @kobj.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * Additional properties not added by driver core have to be changed by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * driver or subsystem which created them. This is similar to how
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * driver/subsystem specific entries are removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) const struct kobj_type *ktype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!kobj->state_in_sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* Change the owner of the kobject itself. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) error = internal_change_owner(kobj->sd, kuid, kgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ktype = get_ktype(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (ktype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct attribute **kattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * Change owner of the default attributes associated with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * ktype of @kobj.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) for (kattr = ktype->default_attrs; kattr && *kattr; kattr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) error = sysfs_file_change_owner(kobj, (*kattr)->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) kuid, kgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * Change owner of the default groups associated with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * ktype of @kobj.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) error = sysfs_groups_change_owner(kobj, ktype->default_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) kuid, kgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) EXPORT_SYMBOL_GPL(sysfs_change_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * @buf: start of PAGE_SIZE buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * @fmt: format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * @...: optional arguments to @format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * Returns number of characters written to @buf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int sysfs_emit(char *buf, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (WARN(!buf || offset_in_page(buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) "invalid sysfs_emit: buf:%p\n", buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) len = vscnprintf(buf, PAGE_SIZE, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) EXPORT_SYMBOL_GPL(sysfs_emit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * @buf: start of PAGE_SIZE buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * @at: offset in @buf to start write in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * @at must be >= 0 && < PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) * @fmt: format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * @...: optional arguments to @fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * Returns number of characters written starting at &@buf[@at].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int sysfs_emit_at(char *buf, int at, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) EXPORT_SYMBOL_GPL(sysfs_emit_at);