blob: 130fc6fbcc038b8e429cffd6f34859dac4d99ea4 [file] [log] [blame]
Greg Kroah-Hartman619daee2018-01-22 16:18:13 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
Tejun Heo6d66f5c2007-09-20 17:31:38 +09003 * fs/sysfs/file.c - sysfs regular (text) file implementation
4 *
5 * Copyright (c) 2001-3 Patrick Mochel
6 * Copyright (c) 2007 SUSE Linux Products GmbH
7 * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
8 *
Tejun Heo6d66f5c2007-09-20 17:31:38 +09009 * Please see Documentation/filesystems/sysfs.txt for more information.
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 */
11
12#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/kobject.h>
Robert P. J. Dayc6f87732008-03-13 22:41:52 -040014#include <linux/slab.h>
Oliver Neukum94bebf42006-12-20 10:52:44 +010015#include <linux/list.h>
Dave Young52e8c202007-07-26 11:03:54 +000016#include <linux/mutex.h>
Tejun Heo13c589d2013-10-01 17:42:02 -040017#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
19#include "sysfs.h"
Tejun Heof6acf8b2013-11-28 14:54:21 -050020
21/*
Tejun Heo324a56e2013-12-11 14:11:53 -050022 * Determine ktype->sysfs_ops for the given kernfs_node. This function
Tejun Heo375b6112013-10-01 17:41:57 -040023 * must be called while holding an active reference.
24 */
Tejun Heo324a56e2013-12-11 14:11:53 -050025static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
Tejun Heo375b6112013-10-01 17:41:57 -040026{
Tejun Heoadc5e8b2013-12-11 14:11:54 -050027 struct kobject *kobj = kn->parent->priv;
Tejun Heo375b6112013-10-01 17:41:57 -040028
Tejun Heodf23fc32013-12-11 14:11:56 -050029 if (kn->flags & KERNFS_LOCKDEP)
Tejun Heo324a56e2013-12-11 14:11:53 -050030 lockdep_assert_held(kn);
Tejun Heo375b6112013-10-01 17:41:57 -040031 return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
32}
33
Tejun Heo13c589d2013-10-01 17:42:02 -040034/*
35 * Reads on sysfs are handled through seq_file, which takes care of hairy
36 * details like buffering and seeking. The following function pipes
37 * sysfs_ops->show() result through seq_file.
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 */
Tejun Heoc2b19da2013-11-28 14:54:16 -050039static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040{
Tejun Heoc525aad2013-12-11 14:11:55 -050041 struct kernfs_open_file *of = sf->private;
Tejun Heoadc5e8b2013-12-11 14:11:54 -050042 struct kobject *kobj = of->kn->parent->priv;
Tejun Heo324a56e2013-12-11 14:11:53 -050043 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 ssize_t count;
Tejun Heoc2b19da2013-11-28 14:54:16 -050045 char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Tejun Heof5c16f22014-05-19 15:52:10 -040047 /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
Tejun Heo13c589d2013-10-01 17:42:02 -040048 count = seq_get_buf(sf, &buf);
49 if (count < PAGE_SIZE) {
50 seq_commit(sf, -1);
51 return 0;
52 }
Tejun Heof5c16f22014-05-19 15:52:10 -040053 memset(buf, 0, PAGE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Tejun Heo13c589d2013-10-01 17:42:02 -040055 /*
Tejun Heoc2b19da2013-11-28 14:54:16 -050056 * Invoke show(). Control may reach here via seq file lseek even
57 * if @ops->show() isn't implemented.
Tejun Heo13c589d2013-10-01 17:42:02 -040058 */
Tejun Heoc2b19da2013-11-28 14:54:16 -050059 if (ops->show) {
Tejun Heo324a56e2013-12-11 14:11:53 -050060 count = ops->show(kobj, of->kn->priv, buf);
Tejun Heoc2b19da2013-11-28 14:54:16 -050061 if (count < 0)
62 return count;
63 }
Tejun Heo0ab66082007-06-14 03:45:16 +090064
Miao Xie8118a852007-11-21 14:55:19 -080065 /*
66 * The code works fine with PAGE_SIZE return but it's likely to
67 * indicate truncated result or overflow in normal use cases.
68 */
Andrew Morton815d2d52008-03-04 15:09:07 -080069 if (count >= (ssize_t)PAGE_SIZE) {
Sergey Senozhatsky9e6d35f2017-12-11 21:50:22 +090070 printk("fill_read_buffer: %pS returned bad count\n",
71 ops->show);
Andrew Morton815d2d52008-03-04 15:09:07 -080072 /* Try to struggle along */
73 count = PAGE_SIZE - 1;
74 }
Tejun Heo13c589d2013-10-01 17:42:02 -040075 seq_commit(sf, count);
76 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077}
78
Tejun Heoc525aad2013-12-11 14:11:55 -050079static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
Tejun Heoc2b19da2013-11-28 14:54:16 -050080 size_t count, loff_t pos)
Tejun Heo2f0c6b72013-10-01 17:42:06 -040081{
Tejun Heo324a56e2013-12-11 14:11:53 -050082 struct bin_attribute *battr = of->kn->priv;
Tejun Heoadc5e8b2013-12-11 14:11:54 -050083 struct kobject *kobj = of->kn->parent->priv;
Tejun Heoc2b19da2013-11-28 14:54:16 -050084 loff_t size = file_inode(of->file)->i_size;
Tejun Heo2f0c6b72013-10-01 17:42:06 -040085
Tejun Heoc2b19da2013-11-28 14:54:16 -050086 if (!count)
Tejun Heo2f0c6b72013-10-01 17:42:06 -040087 return 0;
88
89 if (size) {
Vladimir Zapolskiyeaa5cd92015-05-22 00:21:16 +030090 if (pos >= size)
Tejun Heo2f0c6b72013-10-01 17:42:06 -040091 return 0;
Tejun Heoc2b19da2013-11-28 14:54:16 -050092 if (pos + count > size)
93 count = size - pos;
Tejun Heo2f0c6b72013-10-01 17:42:06 -040094 }
95
Tejun Heoc2b19da2013-11-28 14:54:16 -050096 if (!battr->read)
97 return -EIO;
98
99 return battr->read(of->file, kobj, battr, buf, pos, count);
100}
101
NeilBrown4ef67a82014-10-14 16:57:26 +1100102/* kernfs read callback for regular sysfs files with pre-alloc */
103static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
104 size_t count, loff_t pos)
105{
106 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
107 struct kobject *kobj = of->kn->parent->priv;
NeilBrownc8a139d2017-04-03 11:30:34 +1000108 ssize_t len;
NeilBrown4ef67a82014-10-14 16:57:26 +1100109
110 /*
111 * If buf != of->prealloc_buf, we don't know how
112 * large it is, so cannot safely pass it to ->show
113 */
Konstantin Khlebnikov17d07742016-06-22 21:42:16 +0300114 if (WARN_ON_ONCE(buf != of->prealloc_buf))
NeilBrown4ef67a82014-10-14 16:57:26 +1100115 return 0;
NeilBrown65da3482015-08-06 08:27:55 +1000116 len = ops->show(kobj, of->kn->priv, buf);
NeilBrownc8a139d2017-04-03 11:30:34 +1000117 if (len < 0)
118 return len;
Konstantin Khlebnikov17d07742016-06-22 21:42:16 +0300119 if (pos) {
120 if (len <= pos)
121 return 0;
122 len -= pos;
123 memmove(buf, buf + pos, len);
124 }
NeilBrownc8a139d2017-04-03 11:30:34 +1000125 return min_t(ssize_t, count, len);
NeilBrown4ef67a82014-10-14 16:57:26 +1100126}
127
Tejun Heo50b38ca2013-11-28 14:54:17 -0500128/* kernfs write callback for regular sysfs files */
Tejun Heoc525aad2013-12-11 14:11:55 -0500129static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
Tejun Heo50b38ca2013-11-28 14:54:17 -0500130 size_t count, loff_t pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131{
Tejun Heo324a56e2013-12-11 14:11:53 -0500132 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
Tejun Heoadc5e8b2013-12-11 14:11:54 -0500133 struct kobject *kobj = of->kn->parent->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Tejun Heo50b38ca2013-11-28 14:54:17 -0500135 if (!count)
136 return 0;
137
Tejun Heo324a56e2013-12-11 14:11:53 -0500138 return ops->store(kobj, of->kn->priv, buf, count);
Tejun Heo50b38ca2013-11-28 14:54:17 -0500139}
140
141/* kernfs write callback for bin sysfs files */
Tejun Heoc525aad2013-12-11 14:11:55 -0500142static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
Tejun Heo50b38ca2013-11-28 14:54:17 -0500143 size_t count, loff_t pos)
144{
Tejun Heo324a56e2013-12-11 14:11:53 -0500145 struct bin_attribute *battr = of->kn->priv;
Tejun Heoadc5e8b2013-12-11 14:11:54 -0500146 struct kobject *kobj = of->kn->parent->priv;
Tejun Heo50b38ca2013-11-28 14:54:17 -0500147 loff_t size = file_inode(of->file)->i_size;
148
149 if (size) {
150 if (size <= pos)
Vladimir Zapolskiy09368962014-09-24 18:21:04 +0300151 return -EFBIG;
Tejun Heo50b38ca2013-11-28 14:54:17 -0500152 count = min_t(ssize_t, count, size - pos);
Tejun Heo8ef445f2013-10-01 17:42:01 -0400153 }
Tejun Heo50b38ca2013-11-28 14:54:17 -0500154 if (!count)
155 return 0;
Tejun Heo0ab66082007-06-14 03:45:16 +0900156
Tejun Heo50b38ca2013-11-28 14:54:17 -0500157 if (!battr->write)
158 return -EIO;
Tejun Heof9b9a622013-10-01 17:42:05 -0400159
Tejun Heo50b38ca2013-11-28 14:54:17 -0500160 return battr->write(of->file, kobj, battr, buf, pos, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161}
162
Tejun Heoc525aad2013-12-11 14:11:55 -0500163static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
Tejun Heofdbffaa2013-11-28 14:54:18 -0500164 struct vm_area_struct *vma)
165{
Tejun Heo324a56e2013-12-11 14:11:53 -0500166 struct bin_attribute *battr = of->kn->priv;
Tejun Heoadc5e8b2013-12-11 14:11:54 -0500167 struct kobject *kobj = of->kn->parent->priv;
Tejun Heofdbffaa2013-11-28 14:54:18 -0500168
Tejun Heofdbffaa2013-11-28 14:54:18 -0500169 return battr->mmap(of->file, kobj, battr, vma);
170}
171
Tejun Heo324a56e2013-12-11 14:11:53 -0500172void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
NeilBrown4508a7a2006-03-20 17:53:53 +1100173{
Tejun Heo324a56e2013-12-11 14:11:53 -0500174 struct kernfs_node *kn = kobj->sd, *tmp;
NeilBrown4508a7a2006-03-20 17:53:53 +1100175
Tejun Heo324a56e2013-12-11 14:11:53 -0500176 if (kn && dir)
177 kn = kernfs_find_and_get(kn, dir);
Tejun Heo024f6472013-11-28 14:54:27 -0500178 else
Tejun Heo324a56e2013-12-11 14:11:53 -0500179 kernfs_get(kn);
Tejun Heo51225032007-06-14 04:27:25 +0900180
Tejun Heo324a56e2013-12-11 14:11:53 -0500181 if (kn && attr) {
182 tmp = kernfs_find_and_get(kn, attr);
183 kernfs_put(kn);
184 kn = tmp;
Tejun Heo024f6472013-11-28 14:54:27 -0500185 }
186
Tejun Heo324a56e2013-12-11 14:11:53 -0500187 if (kn) {
188 kernfs_notify(kn);
189 kernfs_put(kn);
Tejun Heo024f6472013-11-28 14:54:27 -0500190 }
NeilBrown4508a7a2006-03-20 17:53:53 +1100191}
192EXPORT_SYMBOL_GPL(sysfs_notify);
193
Tejun Heof6acf8b2013-11-28 14:54:21 -0500194static const struct kernfs_ops sysfs_file_kfops_empty = {
195};
196
197static const struct kernfs_ops sysfs_file_kfops_ro = {
198 .seq_show = sysfs_kf_seq_show,
199};
200
201static const struct kernfs_ops sysfs_file_kfops_wo = {
202 .write = sysfs_kf_write,
203};
204
205static const struct kernfs_ops sysfs_file_kfops_rw = {
206 .seq_show = sysfs_kf_seq_show,
207 .write = sysfs_kf_write,
208};
209
NeilBrown4ef67a82014-10-14 16:57:26 +1100210static const struct kernfs_ops sysfs_prealloc_kfops_ro = {
211 .read = sysfs_kf_read,
212 .prealloc = true,
213};
214
NeilBrown2b758692014-10-13 16:41:28 +1100215static const struct kernfs_ops sysfs_prealloc_kfops_wo = {
216 .write = sysfs_kf_write,
217 .prealloc = true,
218};
219
220static const struct kernfs_ops sysfs_prealloc_kfops_rw = {
NeilBrown4ef67a82014-10-14 16:57:26 +1100221 .read = sysfs_kf_read,
NeilBrown2b758692014-10-13 16:41:28 +1100222 .write = sysfs_kf_write,
223 .prealloc = true,
224};
225
Tejun Heof6acf8b2013-11-28 14:54:21 -0500226static const struct kernfs_ops sysfs_bin_kfops_ro = {
227 .read = sysfs_kf_bin_read,
228};
229
230static const struct kernfs_ops sysfs_bin_kfops_wo = {
231 .write = sysfs_kf_bin_write,
232};
233
234static const struct kernfs_ops sysfs_bin_kfops_rw = {
235 .read = sysfs_kf_bin_read,
236 .write = sysfs_kf_bin_write,
Tejun Heo9b2db6e2013-12-10 09:29:17 -0500237};
238
239static const struct kernfs_ops sysfs_bin_kfops_mmap = {
240 .read = sysfs_kf_bin_read,
241 .write = sysfs_kf_bin_write,
Tejun Heof6acf8b2013-11-28 14:54:21 -0500242 .mmap = sysfs_kf_bin_mmap,
243};
244
Tejun Heo324a56e2013-12-11 14:11:53 -0500245int sysfs_add_file_mode_ns(struct kernfs_node *parent,
Tejun Heoa7dc66d2013-11-28 14:54:23 -0500246 const struct attribute *attr, bool is_bin,
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000247 umode_t mode, kuid_t uid, kgid_t gid, const void *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
Tejun Heo517e64f2013-11-28 14:54:29 -0500249 struct lock_class_key *key = NULL;
Tejun Heof6acf8b2013-11-28 14:54:21 -0500250 const struct kernfs_ops *ops;
Tejun Heo324a56e2013-12-11 14:11:53 -0500251 struct kernfs_node *kn;
Tejun Heo471bd7b2013-11-28 14:54:22 -0500252 loff_t size;
Tejun Heoa26cd722007-06-14 03:45:14 +0900253
Tejun Heoa7dc66d2013-11-28 14:54:23 -0500254 if (!is_bin) {
Tejun Heo324a56e2013-12-11 14:11:53 -0500255 struct kobject *kobj = parent->priv;
Tejun Heof6acf8b2013-11-28 14:54:21 -0500256 const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
257
258 /* every kobject with an attribute needs a ktype assigned */
259 if (WARN(!sysfs_ops, KERN_ERR
260 "missing sysfs attribute operations for kobject: %s\n",
261 kobject_name(kobj)))
262 return -EINVAL;
263
NeilBrown2b758692014-10-13 16:41:28 +1100264 if (sysfs_ops->show && sysfs_ops->store) {
265 if (mode & SYSFS_PREALLOC)
266 ops = &sysfs_prealloc_kfops_rw;
267 else
268 ops = &sysfs_file_kfops_rw;
NeilBrown4ef67a82014-10-14 16:57:26 +1100269 } else if (sysfs_ops->show) {
270 if (mode & SYSFS_PREALLOC)
271 ops = &sysfs_prealloc_kfops_ro;
272 else
273 ops = &sysfs_file_kfops_ro;
274 } else if (sysfs_ops->store) {
NeilBrown2b758692014-10-13 16:41:28 +1100275 if (mode & SYSFS_PREALLOC)
276 ops = &sysfs_prealloc_kfops_wo;
277 else
278 ops = &sysfs_file_kfops_wo;
279 } else
Tejun Heof6acf8b2013-11-28 14:54:21 -0500280 ops = &sysfs_file_kfops_empty;
Tejun Heo471bd7b2013-11-28 14:54:22 -0500281
282 size = PAGE_SIZE;
Tejun Heof6acf8b2013-11-28 14:54:21 -0500283 } else {
284 struct bin_attribute *battr = (void *)attr;
285
Tejun Heo9b2db6e2013-12-10 09:29:17 -0500286 if (battr->mmap)
287 ops = &sysfs_bin_kfops_mmap;
288 else if (battr->read && battr->write)
Tejun Heof6acf8b2013-11-28 14:54:21 -0500289 ops = &sysfs_bin_kfops_rw;
290 else if (battr->read)
291 ops = &sysfs_bin_kfops_ro;
292 else if (battr->write)
293 ops = &sysfs_bin_kfops_wo;
294 else
295 ops = &sysfs_file_kfops_empty;
Tejun Heo471bd7b2013-11-28 14:54:22 -0500296
297 size = battr->size;
Tejun Heof6acf8b2013-11-28 14:54:21 -0500298 }
299
Tejun Heo517e64f2013-11-28 14:54:29 -0500300#ifdef CONFIG_DEBUG_LOCK_ALLOC
301 if (!attr->ignore_lockdep)
302 key = attr->key ?: (struct lock_class_key *)&attr->skey;
303#endif
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000304
305 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
Dmitry Torokhov488dee92018-07-20 21:56:47 +0000306 size, ops, (void *)attr, ns, key);
Tejun Heo324a56e2013-12-11 14:11:53 -0500307 if (IS_ERR(kn)) {
308 if (PTR_ERR(kn) == -EEXIST)
309 sysfs_warn_dup(parent, attr->name);
310 return PTR_ERR(kn);
Tejun Heo496f7392013-11-28 14:54:24 -0500311 }
312 return 0;
313}
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315/**
Tejun Heo58292cbe2013-09-11 22:29:04 -0400316 * sysfs_create_file_ns - create an attribute file for an object with custom ns
317 * @kobj: object we're creating for
318 * @attr: attribute descriptor
319 * @ns: namespace the new file should belong to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 */
Tejun Heo58292cbe2013-09-11 22:29:04 -0400321int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
322 const void *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000324 kuid_t uid;
325 kgid_t gid;
326
Greg Kroah-Hartmande96e9f2019-01-03 10:23:47 +0100327 if (WARN_ON(!kobj || !kobj->sd || !attr))
328 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000330 kobject_get_ownership(kobj, &uid, &gid);
331 return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode,
332 uid, gid, ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334}
Tejun Heo58292cbe2013-09-11 22:29:04 -0400335EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Jani Nikula9ee46852018-10-04 17:37:49 +0300337int sysfs_create_files(struct kobject *kobj, const struct attribute * const *ptr)
Andi Kleen1c205ae2010-01-05 12:48:01 +0100338{
339 int err = 0;
340 int i;
341
342 for (i = 0; ptr[i] && !err; i++)
343 err = sysfs_create_file(kobj, ptr[i]);
344 if (err)
345 while (--i >= 0)
346 sysfs_remove_file(kobj, ptr[i]);
347 return err;
348}
Greg Kroah-Hartman1b866752013-08-21 16:17:47 -0700349EXPORT_SYMBOL_GPL(sysfs_create_files);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351/**
Alan Sterndfa87c82007-02-20 15:02:44 -0500352 * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
353 * @kobj: object we're acting for.
354 * @attr: attribute descriptor.
355 * @group: group name.
356 */
357int sysfs_add_file_to_group(struct kobject *kobj,
358 const struct attribute *attr, const char *group)
359{
Tejun Heo324a56e2013-12-11 14:11:53 -0500360 struct kernfs_node *parent;
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000361 kuid_t uid;
362 kgid_t gid;
Alan Sterndfa87c82007-02-20 15:02:44 -0500363 int error;
364
Tejun Heoccf73cf2013-11-28 14:54:30 -0500365 if (group) {
Tejun Heo324a56e2013-12-11 14:11:53 -0500366 parent = kernfs_find_and_get(kobj->sd, group);
Tejun Heoccf73cf2013-11-28 14:54:30 -0500367 } else {
Tejun Heo324a56e2013-12-11 14:11:53 -0500368 parent = kobj->sd;
369 kernfs_get(parent);
Tejun Heoccf73cf2013-11-28 14:54:30 -0500370 }
James Bottomley11f24fb2008-01-02 18:44:05 -0600371
Tejun Heo324a56e2013-12-11 14:11:53 -0500372 if (!parent)
Tejun Heo608e2662007-06-14 04:27:22 +0900373 return -ENOENT;
374
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000375 kobject_get_ownership(kobj, &uid, &gid);
Tyler Hicksd1753392018-07-27 21:33:27 +0000376 error = sysfs_add_file_mode_ns(parent, attr, false,
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000377 attr->mode, uid, gid, NULL);
Tejun Heo324a56e2013-12-11 14:11:53 -0500378 kernfs_put(parent);
Tejun Heo608e2662007-06-14 04:27:22 +0900379
Alan Sterndfa87c82007-02-20 15:02:44 -0500380 return error;
381}
382EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
383
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384/**
Kay Sievers31e5abe2005-04-18 21:57:32 -0700385 * sysfs_chmod_file - update the modified mode value on an object attribute.
386 * @kobj: object we're acting for.
387 * @attr: attribute descriptor.
388 * @mode: file permissions.
389 *
390 */
Jean Delvare49c19402010-07-02 16:54:05 +0200391int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
Al Viro48176a92011-07-24 03:40:40 -0400392 umode_t mode)
Kay Sievers31e5abe2005-04-18 21:57:32 -0700393{
Tejun Heo324a56e2013-12-11 14:11:53 -0500394 struct kernfs_node *kn;
Maneesh Sonibc062b12005-07-29 12:13:35 -0700395 struct iattr newattrs;
Tejun Heo51225032007-06-14 04:27:25 +0900396 int rc;
Kay Sievers31e5abe2005-04-18 21:57:32 -0700397
Tejun Heo324a56e2013-12-11 14:11:53 -0500398 kn = kernfs_find_and_get(kobj->sd, attr->name);
399 if (!kn)
Tejun Heo5d604182013-11-23 17:21:52 -0500400 return -ENOENT;
Tejun Heo51225032007-06-14 04:27:25 +0900401
Tejun Heoadc5e8b2013-12-11 14:11:54 -0500402 newattrs.ia_mode = (mode & S_IALLUGO) | (kn->mode & ~S_IALLUGO);
Eric W. Biederman4c6974f2009-11-07 23:27:02 -0800403 newattrs.ia_valid = ATTR_MODE;
Tejun Heof88123e2007-09-20 16:05:10 +0900404
Tejun Heo324a56e2013-12-11 14:11:53 -0500405 rc = kernfs_setattr(kn, &newattrs);
Tejun Heo5d604182013-11-23 17:21:52 -0500406
Tejun Heo324a56e2013-12-11 14:11:53 -0500407 kernfs_put(kn);
Tejun Heo51225032007-06-14 04:27:25 +0900408 return rc;
Kay Sievers31e5abe2005-04-18 21:57:32 -0700409}
410EXPORT_SYMBOL_GPL(sysfs_chmod_file);
411
Kay Sievers31e5abe2005-04-18 21:57:32 -0700412/**
Bart Van Assche2afc9162018-08-02 10:51:40 -0700413 * sysfs_break_active_protection - break "active" protection
414 * @kobj: The kernel object @attr is associated with.
415 * @attr: The attribute to break the "active" protection for.
416 *
417 * With sysfs, just like kernfs, deletion of an attribute is postponed until
418 * all active .show() and .store() callbacks have finished unless this function
419 * is called. Hence this function is useful in methods that implement self
420 * deletion.
421 */
422struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
423 const struct attribute *attr)
424{
425 struct kernfs_node *kn;
426
427 kobject_get(kobj);
428 kn = kernfs_find_and_get(kobj->sd, attr->name);
429 if (kn)
430 kernfs_break_active_protection(kn);
431 return kn;
432}
433EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
434
435/**
436 * sysfs_unbreak_active_protection - restore "active" protection
437 * @kn: Pointer returned by sysfs_break_active_protection().
438 *
439 * Undo the effects of sysfs_break_active_protection(). Since this function
440 * calls kernfs_put() on the kernfs node that corresponds to the 'attr'
441 * argument passed to sysfs_break_active_protection() that attribute may have
442 * been removed between the sysfs_break_active_protection() and
443 * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after
444 * this function has returned.
445 */
446void sysfs_unbreak_active_protection(struct kernfs_node *kn)
447{
448 struct kobject *kobj = kn->parent->priv;
449
450 kernfs_unbreak_active_protection(kn);
451 kernfs_put(kn);
452 kobject_put(kobj);
453}
454EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
455
456/**
Tejun Heo58292cbe2013-09-11 22:29:04 -0400457 * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
458 * @kobj: object we're acting for
459 * @attr: attribute descriptor
460 * @ns: namespace tag of the file to remove
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 *
Tejun Heo58292cbe2013-09-11 22:29:04 -0400462 * Hash the attribute name and namespace tag and kill the victim.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 */
Tejun Heo58292cbe2013-09-11 22:29:04 -0400464void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
465 const void *ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
Tejun Heo324a56e2013-12-11 14:11:53 -0500467 struct kernfs_node *parent = kobj->sd;
Eric W. Biederman487505c2011-10-12 21:53:38 +0000468
Tejun Heo324a56e2013-12-11 14:11:53 -0500469 kernfs_remove_by_name_ns(parent, attr->name, ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470}
Tejun Heo58292cbe2013-09-11 22:29:04 -0400471EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
Tejun Heo6b0afc22014-02-03 14:03:01 -0500473/**
474 * sysfs_remove_file_self - remove an object attribute from its own method
475 * @kobj: object we're acting for
476 * @attr: attribute descriptor
477 *
478 * See kernfs_remove_self() for details.
479 */
480bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
481{
482 struct kernfs_node *parent = kobj->sd;
483 struct kernfs_node *kn;
484 bool ret;
485
486 kn = kernfs_find_and_get(parent, attr->name);
487 if (WARN_ON_ONCE(!kn))
488 return false;
489
490 ret = kernfs_remove_self(kn);
491
492 kernfs_put(kn);
493 return ret;
494}
495
Jani Nikula9ee46852018-10-04 17:37:49 +0300496void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *ptr)
Andi Kleen1c205ae2010-01-05 12:48:01 +0100497{
498 int i;
Stephen Martin4bd4e922018-12-20 13:50:28 -0800499
Andi Kleen1c205ae2010-01-05 12:48:01 +0100500 for (i = 0; ptr[i]; i++)
501 sysfs_remove_file(kobj, ptr[i]);
502}
Greg Kroah-Hartman1b866752013-08-21 16:17:47 -0700503EXPORT_SYMBOL_GPL(sysfs_remove_files);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
Alan Sterndfa87c82007-02-20 15:02:44 -0500505/**
506 * sysfs_remove_file_from_group - remove an attribute file from a group.
507 * @kobj: object we're acting for.
508 * @attr: attribute descriptor.
509 * @group: group name.
510 */
511void sysfs_remove_file_from_group(struct kobject *kobj,
512 const struct attribute *attr, const char *group)
513{
Tejun Heo324a56e2013-12-11 14:11:53 -0500514 struct kernfs_node *parent;
Alan Sterndfa87c82007-02-20 15:02:44 -0500515
Tejun Heoccf73cf2013-11-28 14:54:30 -0500516 if (group) {
Tejun Heo324a56e2013-12-11 14:11:53 -0500517 parent = kernfs_find_and_get(kobj->sd, group);
Tejun Heoccf73cf2013-11-28 14:54:30 -0500518 } else {
Tejun Heo324a56e2013-12-11 14:11:53 -0500519 parent = kobj->sd;
520 kernfs_get(parent);
Tejun Heoccf73cf2013-11-28 14:54:30 -0500521 }
522
Tejun Heo324a56e2013-12-11 14:11:53 -0500523 if (parent) {
524 kernfs_remove_by_name(parent, attr->name);
525 kernfs_put(parent);
Alan Sterndfa87c82007-02-20 15:02:44 -0500526 }
527}
528EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
529
Tejun Heo3124eb12013-10-01 17:42:09 -0400530/**
531 * sysfs_create_bin_file - create binary file for object.
532 * @kobj: object.
533 * @attr: attribute descriptor.
534 */
535int sysfs_create_bin_file(struct kobject *kobj,
536 const struct bin_attribute *attr)
537{
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000538 kuid_t uid;
539 kgid_t gid;
540
Greg Kroah-Hartmande96e9f2019-01-03 10:23:47 +0100541 if (WARN_ON(!kobj || !kobj->sd || !attr))
542 return -EINVAL;
Tejun Heo3124eb12013-10-01 17:42:09 -0400543
Dmitry Torokhov5f818802018-07-20 21:56:48 +0000544 kobject_get_ownership(kobj, &uid, &gid);
545 return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true,
546 attr->attr.mode, uid, gid, NULL);
Tejun Heo3124eb12013-10-01 17:42:09 -0400547}
548EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
549
550/**
551 * sysfs_remove_bin_file - remove binary file for object.
552 * @kobj: object.
553 * @attr: attribute descriptor.
554 */
555void sysfs_remove_bin_file(struct kobject *kobj,
556 const struct bin_attribute *attr)
557{
Tejun Heo879f40d2013-11-23 17:21:49 -0500558 kernfs_remove_by_name(kobj->sd, attr->attr.name);
Tejun Heo3124eb12013-10-01 17:42:09 -0400559}
560EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);