Blame view

fs/sysfs/file.c 13.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
6d66f5cd2   Tejun Heo   sysfs: add copyri...
2
3
4
5
6
7
8
9
10
   * fs/sysfs/file.c - sysfs regular (text) file implementation
   *
   * Copyright (c) 2001-3 Patrick Mochel
   * Copyright (c) 2007 SUSE Linux Products GmbH
   * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
   *
   * This file is released under the GPLv2.
   *
   * Please see Documentation/filesystems/sysfs.txt for more information.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
   */
  
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/kobject.h>
815d2d50d   Andrew Morton   driver core: debu...
15
  #include <linux/kallsyms.h>
c6f877338   Robert P. J. Day   SYSFS: Explicitly...
16
  #include <linux/slab.h>
94bebf4d1   Oliver Neukum   Driver core: fix ...
17
  #include <linux/list.h>
52e8c209d   Dave Young   sysfs/file.c - us...
18
  #include <linux/mutex.h>
13c589d5b   Tejun Heo   sysfs: use seq_fi...
19
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  
  #include "sysfs.h"
414985ae2   Tejun Heo   sysfs, kernfs: mo...
22
  #include "../kernfs/kernfs-internal.h"
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
23
24
  
  /*
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
25
   * Determine ktype->sysfs_ops for the given kernfs_node.  This function
375b611e6   Tejun Heo   sysfs: remove sys...
26
27
   * must be called while holding an active reference.
   */
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
28
  static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
375b611e6   Tejun Heo   sysfs: remove sys...
29
  {
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
30
  	struct kobject *kobj = kn->parent->priv;
375b611e6   Tejun Heo   sysfs: remove sys...
31

df23fc39b   Tejun Heo   kernfs: s/sysfs/k...
32
  	if (kn->flags & KERNFS_LOCKDEP)
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
33
  		lockdep_assert_held(kn);
375b611e6   Tejun Heo   sysfs: remove sys...
34
35
  	return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
  }
13c589d5b   Tejun Heo   sysfs: use seq_fi...
36
37
38
39
  /*
   * Reads on sysfs are handled through seq_file, which takes care of hairy
   * details like buffering and seeking.  The following function pipes
   * sysfs_ops->show() result through seq_file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
   */
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
41
  static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  {
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
43
  	struct kernfs_open_file *of = sf->private;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
44
  	struct kobject *kobj = of->kn->parent->priv;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
45
  	const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  	ssize_t count;
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
47
  	char *buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

f5c16f29b   Tejun Heo   sysfs: make sure ...
49
  	/* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
13c589d5b   Tejun Heo   sysfs: use seq_fi...
50
51
52
53
54
  	count = seq_get_buf(sf, &buf);
  	if (count < PAGE_SIZE) {
  		seq_commit(sf, -1);
  		return 0;
  	}
f5c16f29b   Tejun Heo   sysfs: make sure ...
55
  	memset(buf, 0, PAGE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56

13c589d5b   Tejun Heo   sysfs: use seq_fi...
57
  	/*
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
58
59
  	 * Invoke show().  Control may reach here via seq file lseek even
  	 * if @ops->show() isn't implemented.
13c589d5b   Tejun Heo   sysfs: use seq_fi...
60
  	 */
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
61
  	if (ops->show) {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
62
  		count = ops->show(kobj, of->kn->priv, buf);
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
63
64
65
  		if (count < 0)
  			return count;
  	}
0ab66088c   Tejun Heo   sysfs: implement ...
66

8118a859d   Miao Xie   sysfs: fix off-by...
67
68
69
70
  	/*
  	 * The code works fine with PAGE_SIZE return but it's likely to
  	 * indicate truncated result or overflow in normal use cases.
  	 */
815d2d50d   Andrew Morton   driver core: debu...
71
72
73
74
75
76
77
  	if (count >= (ssize_t)PAGE_SIZE) {
  		print_symbol("fill_read_buffer: %s returned bad count
  ",
  			(unsigned long)ops->show);
  		/* Try to struggle along */
  		count = PAGE_SIZE - 1;
  	}
13c589d5b   Tejun Heo   sysfs: use seq_fi...
78
79
  	seq_commit(sf, count);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  }
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
81
  static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
82
  				 size_t count, loff_t pos)
2f0c6b759   Tejun Heo   sysfs: add sysfs_...
83
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
84
  	struct bin_attribute *battr = of->kn->priv;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
85
  	struct kobject *kobj = of->kn->parent->priv;
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
86
  	loff_t size = file_inode(of->file)->i_size;
2f0c6b759   Tejun Heo   sysfs: add sysfs_...
87

c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
88
  	if (!count)
2f0c6b759   Tejun Heo   sysfs: add sysfs_...
89
90
91
  		return 0;
  
  	if (size) {
eaa5cd926   Vladimir Zapolskiy   fs: sysfs: don't ...
92
  		if (pos >= size)
2f0c6b759   Tejun Heo   sysfs: add sysfs_...
93
  			return 0;
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
94
95
  		if (pos + count > size)
  			count = size - pos;
2f0c6b759   Tejun Heo   sysfs: add sysfs_...
96
  	}
c2b19daf6   Tejun Heo   sysfs, kernfs: pr...
97
98
99
100
101
  	if (!battr->read)
  		return -EIO;
  
  	return battr->read(of->file, kobj, battr, buf, pos, count);
  }
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
102
103
104
105
106
107
  /* kernfs read callback for regular sysfs files with pre-alloc */
  static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
  			     size_t count, loff_t pos)
  {
  	const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
  	struct kobject *kobj = of->kn->parent->priv;
c8a139d00   NeilBrown   sysfs: be careful...
108
  	ssize_t len;
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
109
110
111
112
113
  
  	/*
  	 * If buf != of->prealloc_buf, we don't know how
  	 * large it is, so cannot safely pass it to ->show
  	 */
17d0774f8   Konstantin Khlebnikov   sysfs: correctly ...
114
  	if (WARN_ON_ONCE(buf != of->prealloc_buf))
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
115
  		return 0;
65da3484d   NeilBrown   sysfs: correctly ...
116
  	len = ops->show(kobj, of->kn->priv, buf);
c8a139d00   NeilBrown   sysfs: be careful...
117
118
  	if (len < 0)
  		return len;
17d0774f8   Konstantin Khlebnikov   sysfs: correctly ...
119
120
121
122
123
124
  	if (pos) {
  		if (len <= pos)
  			return 0;
  		len -= pos;
  		memmove(buf, buf + pos, len);
  	}
c8a139d00   NeilBrown   sysfs: be careful...
125
  	return min_t(ssize_t, count, len);
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
126
  }
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
127
  /* kernfs write callback for regular sysfs files */
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
128
  static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
129
  			      size_t count, loff_t pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
131
  	const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
132
  	struct kobject *kobj = of->kn->parent->priv;
0ab66088c   Tejun Heo   sysfs: implement ...
133

50b38ca08   Tejun Heo   sysfs, kernfs: pr...
134
135
  	if (!count)
  		return 0;
0ab66088c   Tejun Heo   sysfs: implement ...
136

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
137
  	return ops->store(kobj, of->kn->priv, buf, count);
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
138
  }
f9b9a6217   Tejun Heo   sysfs: prepare pa...
139

50b38ca08   Tejun Heo   sysfs, kernfs: pr...
140
  /* kernfs write callback for bin sysfs files */
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
141
  static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
142
143
  				  size_t count, loff_t pos)
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
144
  	struct bin_attribute *battr = of->kn->priv;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
145
  	struct kobject *kobj = of->kn->parent->priv;
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
146
  	loff_t size = file_inode(of->file)->i_size;
f9b9a6217   Tejun Heo   sysfs: prepare pa...
147

50b38ca08   Tejun Heo   sysfs, kernfs: pr...
148
149
  	if (size) {
  		if (size <= pos)
093689605   Vladimir Zapolskiy   fs: sysfs: return...
150
  			return -EFBIG;
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
151
  		count = min_t(ssize_t, count, size - pos);
f9b9a6217   Tejun Heo   sysfs: prepare pa...
152
  	}
50b38ca08   Tejun Heo   sysfs, kernfs: pr...
153
154
  	if (!count)
  		return 0;
0ab66088c   Tejun Heo   sysfs: implement ...
155

50b38ca08   Tejun Heo   sysfs, kernfs: pr...
156
157
  	if (!battr->write)
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158

50b38ca08   Tejun Heo   sysfs, kernfs: pr...
159
  	return battr->write(of->file, kobj, battr, buf, pos, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  }
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
161
  static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
fdbffaa47   Tejun Heo   sysfs, kernfs: pr...
162
163
  			     struct vm_area_struct *vma)
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
164
  	struct bin_attribute *battr = of->kn->priv;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
165
  	struct kobject *kobj = of->kn->parent->priv;
fdbffaa47   Tejun Heo   sysfs, kernfs: pr...
166

fdbffaa47   Tejun Heo   sysfs, kernfs: pr...
167
168
  	return battr->mmap(of->file, kobj, battr, vma);
  }
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
169
  void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
4508a7a73   NeilBrown   [PATCH] sysfs: Al...
170
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
171
  	struct kernfs_node *kn = kobj->sd, *tmp;
51225039f   Tejun Heo   sysfs: make direc...
172

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
173
174
  	if (kn && dir)
  		kn = kernfs_find_and_get(kn, dir);
024f64711   Tejun Heo   sysfs, kernfs: in...
175
  	else
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
176
  		kernfs_get(kn);
024f64711   Tejun Heo   sysfs, kernfs: in...
177

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
178
179
180
181
  	if (kn && attr) {
  		tmp = kernfs_find_and_get(kn, attr);
  		kernfs_put(kn);
  		kn = tmp;
024f64711   Tejun Heo   sysfs, kernfs: in...
182
  	}
51225039f   Tejun Heo   sysfs: make direc...
183

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
184
185
186
  	if (kn) {
  		kernfs_notify(kn);
  		kernfs_put(kn);
024f64711   Tejun Heo   sysfs, kernfs: in...
187
  	}
4508a7a73   NeilBrown   [PATCH] sysfs: Al...
188
189
  }
  EXPORT_SYMBOL_GPL(sysfs_notify);
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  static const struct kernfs_ops sysfs_file_kfops_empty = {
  };
  
  static const struct kernfs_ops sysfs_file_kfops_ro = {
  	.seq_show	= sysfs_kf_seq_show,
  };
  
  static const struct kernfs_ops sysfs_file_kfops_wo = {
  	.write		= sysfs_kf_write,
  };
  
  static const struct kernfs_ops sysfs_file_kfops_rw = {
  	.seq_show	= sysfs_kf_seq_show,
  	.write		= sysfs_kf_write,
  };
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
205
206
207
208
  static const struct kernfs_ops sysfs_prealloc_kfops_ro = {
  	.read		= sysfs_kf_read,
  	.prealloc	= true,
  };
2b75869bb   NeilBrown   sysfs/kernfs: all...
209
210
211
212
213
214
  static const struct kernfs_ops sysfs_prealloc_kfops_wo = {
  	.write		= sysfs_kf_write,
  	.prealloc	= true,
  };
  
  static const struct kernfs_ops sysfs_prealloc_kfops_rw = {
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
215
  	.read		= sysfs_kf_read,
2b75869bb   NeilBrown   sysfs/kernfs: all...
216
217
218
  	.write		= sysfs_kf_write,
  	.prealloc	= true,
  };
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
219
220
221
222
223
224
225
226
227
228
229
  static const struct kernfs_ops sysfs_bin_kfops_ro = {
  	.read		= sysfs_kf_bin_read,
  };
  
  static const struct kernfs_ops sysfs_bin_kfops_wo = {
  	.write		= sysfs_kf_bin_write,
  };
  
  static const struct kernfs_ops sysfs_bin_kfops_rw = {
  	.read		= sysfs_kf_bin_read,
  	.write		= sysfs_kf_bin_write,
9b2db6e18   Tejun Heo   sysfs: bail early...
230
231
232
233
234
  };
  
  static const struct kernfs_ops sysfs_bin_kfops_mmap = {
  	.read		= sysfs_kf_bin_read,
  	.write		= sysfs_kf_bin_write,
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
235
236
  	.mmap		= sysfs_kf_bin_mmap,
  };
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
237
  int sysfs_add_file_mode_ns(struct kernfs_node *parent,
a7dc66dfb   Tejun Heo   sysfs, kernfs: re...
238
  			   const struct attribute *attr, bool is_bin,
496f73944   Tejun Heo   sysfs, kernfs: in...
239
  			   umode_t mode, const void *ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  {
517e64f57   Tejun Heo   sysfs, kernfs: re...
241
  	struct lock_class_key *key = NULL;
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
242
  	const struct kernfs_ops *ops;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
243
  	struct kernfs_node *kn;
471bd7b78   Tejun Heo   sysfs, kernfs: ad...
244
  	loff_t size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245

a7dc66dfb   Tejun Heo   sysfs, kernfs: re...
246
  	if (!is_bin) {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
247
  		struct kobject *kobj = parent->priv;
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
248
249
250
251
252
253
254
255
  		const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
  
  		/* every kobject with an attribute needs a ktype assigned */
  		if (WARN(!sysfs_ops, KERN_ERR
  			 "missing sysfs attribute operations for kobject: %s
  ",
  			 kobject_name(kobj)))
  			return -EINVAL;
2b75869bb   NeilBrown   sysfs/kernfs: all...
256
257
258
259
260
  		if (sysfs_ops->show && sysfs_ops->store) {
  			if (mode & SYSFS_PREALLOC)
  				ops = &sysfs_prealloc_kfops_rw;
  			else
  				ops = &sysfs_file_kfops_rw;
4ef67a8c9   NeilBrown   sysfs/kernfs: mak...
261
262
263
264
265
266
  		} else if (sysfs_ops->show) {
  			if (mode & SYSFS_PREALLOC)
  				ops = &sysfs_prealloc_kfops_ro;
  			else
  				ops = &sysfs_file_kfops_ro;
  		} else if (sysfs_ops->store) {
2b75869bb   NeilBrown   sysfs/kernfs: all...
267
268
269
270
271
  			if (mode & SYSFS_PREALLOC)
  				ops = &sysfs_prealloc_kfops_wo;
  			else
  				ops = &sysfs_file_kfops_wo;
  		} else
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
272
  			ops = &sysfs_file_kfops_empty;
471bd7b78   Tejun Heo   sysfs, kernfs: ad...
273
274
  
  		size = PAGE_SIZE;
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
275
276
  	} else {
  		struct bin_attribute *battr = (void *)attr;
9b2db6e18   Tejun Heo   sysfs: bail early...
277
278
279
  		if (battr->mmap)
  			ops = &sysfs_bin_kfops_mmap;
  		else if (battr->read && battr->write)
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
280
281
282
283
284
285
286
  			ops = &sysfs_bin_kfops_rw;
  		else if (battr->read)
  			ops = &sysfs_bin_kfops_ro;
  		else if (battr->write)
  			ops = &sysfs_bin_kfops_wo;
  		else
  			ops = &sysfs_file_kfops_empty;
471bd7b78   Tejun Heo   sysfs, kernfs: ad...
287
288
  
  		size = battr->size;
f6acf8bb6   Tejun Heo   sysfs, kernfs: in...
289
  	}
517e64f57   Tejun Heo   sysfs, kernfs: re...
290
291
292
293
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  	if (!attr->ignore_lockdep)
  		key = attr->key ?: (struct lock_class_key *)&attr->skey;
  #endif
2b75869bb   NeilBrown   sysfs/kernfs: all...
294
  	kn = __kernfs_create_file(parent, attr->name, mode & 0777, size, ops,
dfeb0750b   Tejun Heo   kernfs: remove KE...
295
  				  (void *)attr, ns, key);
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
296
297
298
299
  	if (IS_ERR(kn)) {
  		if (PTR_ERR(kn) == -EEXIST)
  			sysfs_warn_dup(parent, attr->name);
  		return PTR_ERR(kn);
496f73944   Tejun Heo   sysfs, kernfs: in...
300
301
302
  	}
  	return 0;
  }
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
303
  int sysfs_add_file(struct kernfs_node *parent, const struct attribute *attr,
a7dc66dfb   Tejun Heo   sysfs, kernfs: re...
304
  		   bool is_bin)
0f4238958   James Bottomley   [SCSI] sysfs: mak...
305
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
306
  	return sysfs_add_file_mode_ns(parent, attr, is_bin, attr->mode, NULL);
0f4238958   James Bottomley   [SCSI] sysfs: mak...
307
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  /**
58292cbe6   Tejun Heo   sysfs: make attr ...
309
310
311
312
   * sysfs_create_file_ns - create an attribute file for an object with custom ns
   * @kobj: object we're creating for
   * @attr: attribute descriptor
   * @ns: namespace the new file should belong to
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
   */
58292cbe6   Tejun Heo   sysfs: make attr ...
314
315
  int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
  			 const void *ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  {
608e266a2   Tejun Heo   sysfs: make kobj ...
317
  	BUG_ON(!kobj || !kobj->sd || !attr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

a7dc66dfb   Tejun Heo   sysfs, kernfs: re...
319
  	return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode, ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
  
  }
58292cbe6   Tejun Heo   sysfs: make attr ...
322
  EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323

1c205ae18   Andi Kleen   sysfs: Add sysfs_...
324
325
326
327
328
329
330
331
332
333
334
335
  int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
  {
  	int err = 0;
  	int i;
  
  	for (i = 0; ptr[i] && !err; i++)
  		err = sysfs_create_file(kobj, ptr[i]);
  	if (err)
  		while (--i >= 0)
  			sysfs_remove_file(kobj, ptr[i]);
  	return err;
  }
1b866757f   Greg Kroah-Hartman   sysfs: fix placem...
336
  EXPORT_SYMBOL_GPL(sysfs_create_files);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
  
  /**
dfa87c824   Alan Stern   sysfs: allow attr...
339
340
341
342
343
344
345
346
   * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
   * @kobj: object we're acting for.
   * @attr: attribute descriptor.
   * @group: group name.
   */
  int sysfs_add_file_to_group(struct kobject *kobj,
  		const struct attribute *attr, const char *group)
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
347
  	struct kernfs_node *parent;
dfa87c824   Alan Stern   sysfs: allow attr...
348
  	int error;
ccf73cf33   Tejun Heo   sysfs, kernfs: in...
349
  	if (group) {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
350
  		parent = kernfs_find_and_get(kobj->sd, group);
ccf73cf33   Tejun Heo   sysfs, kernfs: in...
351
  	} else {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
352
353
  		parent = kobj->sd;
  		kernfs_get(parent);
ccf73cf33   Tejun Heo   sysfs, kernfs: in...
354
  	}
11f24fbdf   James Bottomley   [SCSI] sysfs: fix...
355

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
356
  	if (!parent)
608e266a2   Tejun Heo   sysfs: make kobj ...
357
  		return -ENOENT;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
358
359
  	error = sysfs_add_file(parent, attr, false);
  	kernfs_put(parent);
608e266a2   Tejun Heo   sysfs: make kobj ...
360

dfa87c824   Alan Stern   sysfs: allow attr...
361
362
363
  	return error;
  }
  EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  /**
31e5abe9a   Kay Sievers   [PATCH] sysfs: ad...
365
366
367
368
369
370
   * sysfs_chmod_file - update the modified mode value on an object attribute.
   * @kobj: object we're acting for.
   * @attr: attribute descriptor.
   * @mode: file permissions.
   *
   */
49c19400f   Jean Delvare   sysfs: sysfs_chmo...
371
  int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
48176a973   Al Viro   switch sysfs_chmo...
372
  		     umode_t mode)
31e5abe9a   Kay Sievers   [PATCH] sysfs: ad...
373
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
374
  	struct kernfs_node *kn;
bc062b1b5   Maneesh Soni   [PATCH] sysfs: fi...
375
  	struct iattr newattrs;
51225039f   Tejun Heo   sysfs: make direc...
376
  	int rc;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
377
378
  	kn = kernfs_find_and_get(kobj->sd, attr->name);
  	if (!kn)
5d60418e5   Tejun Heo   sysfs, kernfs: in...
379
  		return -ENOENT;
f88123eaf   Tejun Heo   sysfs: fix sysfs_...
380

adc5e8b58   Tejun Heo   kernfs: drop s_ p...
381
  	newattrs.ia_mode = (mode & S_IALLUGO) | (kn->mode & ~S_IALLUGO);
4c6974f51   Eric W. Biederman   sysfs: Simplify s...
382
  	newattrs.ia_valid = ATTR_MODE;
f88123eaf   Tejun Heo   sysfs: fix sysfs_...
383

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
384
  	rc = kernfs_setattr(kn, &newattrs);
5d60418e5   Tejun Heo   sysfs, kernfs: in...
385

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
386
  	kernfs_put(kn);
51225039f   Tejun Heo   sysfs: make direc...
387
  	return rc;
31e5abe9a   Kay Sievers   [PATCH] sysfs: ad...
388
389
  }
  EXPORT_SYMBOL_GPL(sysfs_chmod_file);
31e5abe9a   Kay Sievers   [PATCH] sysfs: ad...
390
  /**
c984f4d1d   Bart Van Assche   scsi: sysfs: Intr...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
   * sysfs_break_active_protection - break "active" protection
   * @kobj: The kernel object @attr is associated with.
   * @attr: The attribute to break the "active" protection for.
   *
   * With sysfs, just like kernfs, deletion of an attribute is postponed until
   * all active .show() and .store() callbacks have finished unless this function
   * is called. Hence this function is useful in methods that implement self
   * deletion.
   */
  struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
  						  const struct attribute *attr)
  {
  	struct kernfs_node *kn;
  
  	kobject_get(kobj);
  	kn = kernfs_find_and_get(kobj->sd, attr->name);
  	if (kn)
  		kernfs_break_active_protection(kn);
  	return kn;
  }
  EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
  
  /**
   * sysfs_unbreak_active_protection - restore "active" protection
   * @kn: Pointer returned by sysfs_break_active_protection().
   *
   * Undo the effects of sysfs_break_active_protection(). Since this function
   * calls kernfs_put() on the kernfs node that corresponds to the 'attr'
   * argument passed to sysfs_break_active_protection() that attribute may have
   * been removed between the sysfs_break_active_protection() and
   * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after
   * this function has returned.
   */
  void sysfs_unbreak_active_protection(struct kernfs_node *kn)
  {
  	struct kobject *kobj = kn->parent->priv;
  
  	kernfs_unbreak_active_protection(kn);
  	kernfs_put(kn);
  	kobject_put(kobj);
  }
  EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
  
  /**
58292cbe6   Tejun Heo   sysfs: make attr ...
435
436
437
438
   * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
   * @kobj: object we're acting for
   * @attr: attribute descriptor
   * @ns: namespace tag of the file to remove
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
   *
58292cbe6   Tejun Heo   sysfs: make attr ...
440
   * Hash the attribute name and namespace tag and kill the victim.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
   */
58292cbe6   Tejun Heo   sysfs: make attr ...
442
443
  void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
  			  const void *ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
445
  	struct kernfs_node *parent = kobj->sd;
487505c25   Eric W. Biederman   sysfs: Implement ...
446

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
447
  	kernfs_remove_by_name_ns(parent, attr->name, ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  }
58292cbe6   Tejun Heo   sysfs: make attr ...
449
  EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450

6b0afc2a2   Tejun Heo   kernfs, sysfs, dr...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  /**
   * sysfs_remove_file_self - remove an object attribute from its own method
   * @kobj: object we're acting for
   * @attr: attribute descriptor
   *
   * See kernfs_remove_self() for details.
   */
  bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
  {
  	struct kernfs_node *parent = kobj->sd;
  	struct kernfs_node *kn;
  	bool ret;
  
  	kn = kernfs_find_and_get(parent, attr->name);
  	if (WARN_ON_ONCE(!kn))
  		return false;
  
  	ret = kernfs_remove_self(kn);
  
  	kernfs_put(kn);
  	return ret;
  }
1b18dc2be   Greg Kroah-Hartman   sysfs: fix up spa...
473
  void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
1c205ae18   Andi Kleen   sysfs: Add sysfs_...
474
475
476
477
478
  {
  	int i;
  	for (i = 0; ptr[i]; i++)
  		sysfs_remove_file(kobj, ptr[i]);
  }
1b866757f   Greg Kroah-Hartman   sysfs: fix placem...
479
  EXPORT_SYMBOL_GPL(sysfs_remove_files);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480

dfa87c824   Alan Stern   sysfs: allow attr...
481
482
483
484
485
486
487
488
489
  /**
   * sysfs_remove_file_from_group - remove an attribute file from a group.
   * @kobj: object we're acting for.
   * @attr: attribute descriptor.
   * @group: group name.
   */
  void sysfs_remove_file_from_group(struct kobject *kobj,
  		const struct attribute *attr, const char *group)
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
490
  	struct kernfs_node *parent;
dfa87c824   Alan Stern   sysfs: allow attr...
491

ccf73cf33   Tejun Heo   sysfs, kernfs: in...
492
  	if (group) {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
493
  		parent = kernfs_find_and_get(kobj->sd, group);
ccf73cf33   Tejun Heo   sysfs, kernfs: in...
494
  	} else {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
495
496
  		parent = kobj->sd;
  		kernfs_get(parent);
ccf73cf33   Tejun Heo   sysfs, kernfs: in...
497
  	}
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
498
499
500
  	if (parent) {
  		kernfs_remove_by_name(parent, attr->name);
  		kernfs_put(parent);
dfa87c824   Alan Stern   sysfs: allow attr...
501
502
503
  	}
  }
  EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
3124eb167   Tejun Heo   sysfs: merge regu...
504
505
506
507
508
509
510
511
512
  /**
   *	sysfs_create_bin_file - create binary file for object.
   *	@kobj:	object.
   *	@attr:	attribute descriptor.
   */
  int sysfs_create_bin_file(struct kobject *kobj,
  			  const struct bin_attribute *attr)
  {
  	BUG_ON(!kobj || !kobj->sd || !attr);
a7dc66dfb   Tejun Heo   sysfs, kernfs: re...
513
  	return sysfs_add_file(kobj->sd, &attr->attr, true);
3124eb167   Tejun Heo   sysfs: merge regu...
514
515
516
517
518
519
520
521
522
523
524
  }
  EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
  
  /**
   *	sysfs_remove_bin_file - remove binary file for object.
   *	@kobj:	object.
   *	@attr:	attribute descriptor.
   */
  void sysfs_remove_bin_file(struct kobject *kobj,
  			   const struct bin_attribute *attr)
  {
879f40d19   Tejun Heo   sysfs, kernfs: in...
525
  	kernfs_remove_by_name(kobj->sd, attr->attr.name);
3124eb167   Tejun Heo   sysfs: merge regu...
526
527
  }
  EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);