aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/bin.c56
-rw-r--r--fs/sysfs/dir.c532
-rw-r--r--fs/sysfs/file.c88
-rw-r--r--fs/sysfs/inode.c205
-rw-r--r--fs/sysfs/mount.c5
-rw-r--r--fs/sysfs/symlink.c50
-rw-r--r--fs/sysfs/sysfs.h37
7 files changed, 473 insertions, 500 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 60c702bc10ae..e9d293593e52 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -54,14 +54,14 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
54 int rc; 54 int rc;
55 55
56 /* need attr_sd for attr, its parent for kobj */ 56 /* need attr_sd for attr, its parent for kobj */
57 if (!sysfs_get_active_two(attr_sd)) 57 if (!sysfs_get_active(attr_sd))
58 return -ENODEV; 58 return -ENODEV;
59 59
60 rc = -EIO; 60 rc = -EIO;
61 if (attr->read) 61 if (attr->read)
62 rc = attr->read(kobj, attr, buffer, off, count); 62 rc = attr->read(kobj, attr, buffer, off, count);
63 63
64 sysfs_put_active_two(attr_sd); 64 sysfs_put_active(attr_sd);
65 65
66 return rc; 66 return rc;
67} 67}
@@ -125,14 +125,14 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
125 int rc; 125 int rc;
126 126
127 /* need attr_sd for attr, its parent for kobj */ 127 /* need attr_sd for attr, its parent for kobj */
128 if (!sysfs_get_active_two(attr_sd)) 128 if (!sysfs_get_active(attr_sd))
129 return -ENODEV; 129 return -ENODEV;
130 130
131 rc = -EIO; 131 rc = -EIO;
132 if (attr->write) 132 if (attr->write)
133 rc = attr->write(kobj, attr, buffer, offset, count); 133 rc = attr->write(kobj, attr, buffer, offset, count);
134 134
135 sysfs_put_active_two(attr_sd); 135 sysfs_put_active(attr_sd);
136 136
137 return rc; 137 return rc;
138} 138}
@@ -184,12 +184,12 @@ static void bin_vma_open(struct vm_area_struct *vma)
184 if (!bb->vm_ops || !bb->vm_ops->open) 184 if (!bb->vm_ops || !bb->vm_ops->open)
185 return; 185 return;
186 186
187 if (!sysfs_get_active_two(attr_sd)) 187 if (!sysfs_get_active(attr_sd))
188 return; 188 return;
189 189
190 bb->vm_ops->open(vma); 190 bb->vm_ops->open(vma);
191 191
192 sysfs_put_active_two(attr_sd); 192 sysfs_put_active(attr_sd);
193} 193}
194 194
195static void bin_vma_close(struct vm_area_struct *vma) 195static void bin_vma_close(struct vm_area_struct *vma)
@@ -201,12 +201,12 @@ static void bin_vma_close(struct vm_area_struct *vma)
201 if (!bb->vm_ops || !bb->vm_ops->close) 201 if (!bb->vm_ops || !bb->vm_ops->close)
202 return; 202 return;
203 203
204 if (!sysfs_get_active_two(attr_sd)) 204 if (!sysfs_get_active(attr_sd))
205 return; 205 return;
206 206
207 bb->vm_ops->close(vma); 207 bb->vm_ops->close(vma);
208 208
209 sysfs_put_active_two(attr_sd); 209 sysfs_put_active(attr_sd);
210} 210}
211 211
212static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 212static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -219,12 +219,12 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
219 if (!bb->vm_ops || !bb->vm_ops->fault) 219 if (!bb->vm_ops || !bb->vm_ops->fault)
220 return VM_FAULT_SIGBUS; 220 return VM_FAULT_SIGBUS;
221 221
222 if (!sysfs_get_active_two(attr_sd)) 222 if (!sysfs_get_active(attr_sd))
223 return VM_FAULT_SIGBUS; 223 return VM_FAULT_SIGBUS;
224 224
225 ret = bb->vm_ops->fault(vma, vmf); 225 ret = bb->vm_ops->fault(vma, vmf);
226 226
227 sysfs_put_active_two(attr_sd); 227 sysfs_put_active(attr_sd);
228 return ret; 228 return ret;
229} 229}
230 230
@@ -241,12 +241,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
241 if (!bb->vm_ops->page_mkwrite) 241 if (!bb->vm_ops->page_mkwrite)
242 return 0; 242 return 0;
243 243
244 if (!sysfs_get_active_two(attr_sd)) 244 if (!sysfs_get_active(attr_sd))
245 return VM_FAULT_SIGBUS; 245 return VM_FAULT_SIGBUS;
246 246
247 ret = bb->vm_ops->page_mkwrite(vma, vmf); 247 ret = bb->vm_ops->page_mkwrite(vma, vmf);
248 248
249 sysfs_put_active_two(attr_sd); 249 sysfs_put_active(attr_sd);
250 return ret; 250 return ret;
251} 251}
252 252
@@ -261,12 +261,12 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr,
261 if (!bb->vm_ops || !bb->vm_ops->access) 261 if (!bb->vm_ops || !bb->vm_ops->access)
262 return -EINVAL; 262 return -EINVAL;
263 263
264 if (!sysfs_get_active_two(attr_sd)) 264 if (!sysfs_get_active(attr_sd))
265 return -EINVAL; 265 return -EINVAL;
266 266
267 ret = bb->vm_ops->access(vma, addr, buf, len, write); 267 ret = bb->vm_ops->access(vma, addr, buf, len, write);
268 268
269 sysfs_put_active_two(attr_sd); 269 sysfs_put_active(attr_sd);
270 return ret; 270 return ret;
271} 271}
272 272
@@ -281,12 +281,12 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
281 if (!bb->vm_ops || !bb->vm_ops->set_policy) 281 if (!bb->vm_ops || !bb->vm_ops->set_policy)
282 return 0; 282 return 0;
283 283
284 if (!sysfs_get_active_two(attr_sd)) 284 if (!sysfs_get_active(attr_sd))
285 return -EINVAL; 285 return -EINVAL;
286 286
287 ret = bb->vm_ops->set_policy(vma, new); 287 ret = bb->vm_ops->set_policy(vma, new);
288 288
289 sysfs_put_active_two(attr_sd); 289 sysfs_put_active(attr_sd);
290 return ret; 290 return ret;
291} 291}
292 292
@@ -301,12 +301,12 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
301 if (!bb->vm_ops || !bb->vm_ops->get_policy) 301 if (!bb->vm_ops || !bb->vm_ops->get_policy)
302 return vma->vm_policy; 302 return vma->vm_policy;
303 303
304 if (!sysfs_get_active_two(attr_sd)) 304 if (!sysfs_get_active(attr_sd))
305 return vma->vm_policy; 305 return vma->vm_policy;
306 306
307 pol = bb->vm_ops->get_policy(vma, addr); 307 pol = bb->vm_ops->get_policy(vma, addr);
308 308
309 sysfs_put_active_two(attr_sd); 309 sysfs_put_active(attr_sd);
310 return pol; 310 return pol;
311} 311}
312 312
@@ -321,12 +321,12 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
321 if (!bb->vm_ops || !bb->vm_ops->migrate) 321 if (!bb->vm_ops || !bb->vm_ops->migrate)
322 return 0; 322 return 0;
323 323
324 if (!sysfs_get_active_two(attr_sd)) 324 if (!sysfs_get_active(attr_sd))
325 return 0; 325 return 0;
326 326
327 ret = bb->vm_ops->migrate(vma, from, to, flags); 327 ret = bb->vm_ops->migrate(vma, from, to, flags);
328 328
329 sysfs_put_active_two(attr_sd); 329 sysfs_put_active(attr_sd);
330 return ret; 330 return ret;
331} 331}
332#endif 332#endif
@@ -356,7 +356,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
356 356
357 /* need attr_sd for attr, its parent for kobj */ 357 /* need attr_sd for attr, its parent for kobj */
358 rc = -ENODEV; 358 rc = -ENODEV;
359 if (!sysfs_get_active_two(attr_sd)) 359 if (!sysfs_get_active(attr_sd))
360 goto out_unlock; 360 goto out_unlock;
361 361
362 rc = -EINVAL; 362 rc = -EINVAL;
@@ -384,7 +384,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
384 bb->vm_ops = vma->vm_ops; 384 bb->vm_ops = vma->vm_ops;
385 vma->vm_ops = &bin_vm_ops; 385 vma->vm_ops = &bin_vm_ops;
386out_put: 386out_put:
387 sysfs_put_active_two(attr_sd); 387 sysfs_put_active(attr_sd);
388out_unlock: 388out_unlock:
389 mutex_unlock(&bb->mutex); 389 mutex_unlock(&bb->mutex);
390 390
@@ -399,7 +399,7 @@ static int open(struct inode * inode, struct file * file)
399 int error; 399 int error;
400 400
401 /* binary file operations requires both @sd and its parent */ 401 /* binary file operations requires both @sd and its parent */
402 if (!sysfs_get_active_two(attr_sd)) 402 if (!sysfs_get_active(attr_sd))
403 return -ENODEV; 403 return -ENODEV;
404 404
405 error = -EACCES; 405 error = -EACCES;
@@ -426,11 +426,11 @@ static int open(struct inode * inode, struct file * file)
426 mutex_unlock(&sysfs_bin_lock); 426 mutex_unlock(&sysfs_bin_lock);
427 427
428 /* open succeeded, put active references */ 428 /* open succeeded, put active references */
429 sysfs_put_active_two(attr_sd); 429 sysfs_put_active(attr_sd);
430 return 0; 430 return 0;
431 431
432 err_out: 432 err_out:
433 sysfs_put_active_two(attr_sd); 433 sysfs_put_active(attr_sd);
434 kfree(bb); 434 kfree(bb);
435 return error; 435 return error;
436} 436}
@@ -483,7 +483,8 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd)
483 * @attr: attribute descriptor. 483 * @attr: attribute descriptor.
484 */ 484 */
485 485
486int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) 486int sysfs_create_bin_file(struct kobject *kobj,
487 const struct bin_attribute *attr)
487{ 488{
488 BUG_ON(!kobj || !kobj->sd || !attr); 489 BUG_ON(!kobj || !kobj->sd || !attr);
489 490
@@ -497,7 +498,8 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
497 * @attr: attribute descriptor. 498 * @attr: attribute descriptor.
498 */ 499 */
499 500
500void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) 501void sysfs_remove_bin_file(struct kobject *kobj,
502 const struct bin_attribute *attr)
501{ 503{
502 sysfs_hash_and_remove(kobj->sd, attr->attr.name); 504 sysfs_hash_and_remove(kobj->sd, attr->attr.name);
503} 505}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index e0201837d244..590717861c7a 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -25,7 +25,6 @@
25#include "sysfs.h" 25#include "sysfs.h"
26 26
27DEFINE_MUTEX(sysfs_mutex); 27DEFINE_MUTEX(sysfs_mutex);
28DEFINE_MUTEX(sysfs_rename_mutex);
29DEFINE_SPINLOCK(sysfs_assoc_lock); 28DEFINE_SPINLOCK(sysfs_assoc_lock);
30 29
31static DEFINE_SPINLOCK(sysfs_ino_lock); 30static DEFINE_SPINLOCK(sysfs_ino_lock);
@@ -85,46 +84,6 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
85} 84}
86 85
87/** 86/**
88 * sysfs_get_dentry - get dentry for the given sysfs_dirent
89 * @sd: sysfs_dirent of interest
90 *
91 * Get dentry for @sd. Dentry is looked up if currently not
92 * present. This function descends from the root looking up
93 * dentry for each step.
94 *
95 * LOCKING:
96 * mutex_lock(sysfs_rename_mutex)
97 *
98 * RETURNS:
99 * Pointer to found dentry on success, ERR_PTR() value on error.
100 */
101struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
102{
103 struct dentry *dentry = dget(sysfs_sb->s_root);
104
105 while (dentry->d_fsdata != sd) {
106 struct sysfs_dirent *cur;
107 struct dentry *parent;
108
109 /* find the first ancestor which hasn't been looked up */
110 cur = sd;
111 while (cur->s_parent != dentry->d_fsdata)
112 cur = cur->s_parent;
113
114 /* look it up */
115 parent = dentry;
116 mutex_lock(&parent->d_inode->i_mutex);
117 dentry = lookup_one_noperm(cur->s_name, parent);
118 mutex_unlock(&parent->d_inode->i_mutex);
119 dput(parent);
120
121 if (IS_ERR(dentry))
122 break;
123 }
124 return dentry;
125}
126
127/**
128 * sysfs_get_active - get an active reference to sysfs_dirent 87 * sysfs_get_active - get an active reference to sysfs_dirent
129 * @sd: sysfs_dirent to get an active reference to 88 * @sd: sysfs_dirent to get an active reference to
130 * 89 *
@@ -134,7 +93,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
134 * RETURNS: 93 * RETURNS:
135 * Pointer to @sd on success, NULL on failure. 94 * Pointer to @sd on success, NULL on failure.
136 */ 95 */
137static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) 96struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
138{ 97{
139 if (unlikely(!sd)) 98 if (unlikely(!sd))
140 return NULL; 99 return NULL;
@@ -147,8 +106,10 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
147 return NULL; 106 return NULL;
148 107
149 t = atomic_cmpxchg(&sd->s_active, v, v + 1); 108 t = atomic_cmpxchg(&sd->s_active, v, v + 1);
150 if (likely(t == v)) 109 if (likely(t == v)) {
110 rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
151 return sd; 111 return sd;
112 }
152 if (t < 0) 113 if (t < 0)
153 return NULL; 114 return NULL;
154 115
@@ -163,7 +124,7 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
163 * Put an active reference to @sd. This function is noop if @sd 124 * Put an active reference to @sd. This function is noop if @sd
164 * is NULL. 125 * is NULL.
165 */ 126 */
166static void sysfs_put_active(struct sysfs_dirent *sd) 127void sysfs_put_active(struct sysfs_dirent *sd)
167{ 128{
168 struct completion *cmpl; 129 struct completion *cmpl;
169 int v; 130 int v;
@@ -171,6 +132,7 @@ static void sysfs_put_active(struct sysfs_dirent *sd)
171 if (unlikely(!sd)) 132 if (unlikely(!sd))
172 return; 133 return;
173 134
135 rwsem_release(&sd->dep_map, 1, _RET_IP_);
174 v = atomic_dec_return(&sd->s_active); 136 v = atomic_dec_return(&sd->s_active);
175 if (likely(v != SD_DEACTIVATED_BIAS)) 137 if (likely(v != SD_DEACTIVATED_BIAS))
176 return; 138 return;
@@ -183,45 +145,6 @@ static void sysfs_put_active(struct sysfs_dirent *sd)
183} 145}
184 146
185/** 147/**
186 * sysfs_get_active_two - get active references to sysfs_dirent and parent
187 * @sd: sysfs_dirent of interest
188 *
189 * Get active reference to @sd and its parent. Parent's active
190 * reference is grabbed first. This function is noop if @sd is
191 * NULL.
192 *
193 * RETURNS:
194 * Pointer to @sd on success, NULL on failure.
195 */
196struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
197{
198 if (sd) {
199 if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
200 return NULL;
201 if (unlikely(!sysfs_get_active(sd))) {
202 sysfs_put_active(sd->s_parent);
203 return NULL;
204 }
205 }
206 return sd;
207}
208
209/**
210 * sysfs_put_active_two - put active references to sysfs_dirent and parent
211 * @sd: sysfs_dirent of interest
212 *
213 * Put active references to @sd and its parent. This function is
214 * noop if @sd is NULL.
215 */
216void sysfs_put_active_two(struct sysfs_dirent *sd)
217{
218 if (sd) {
219 sysfs_put_active(sd);
220 sysfs_put_active(sd->s_parent);
221 }
222}
223
224/**
225 * sysfs_deactivate - deactivate sysfs_dirent 148 * sysfs_deactivate - deactivate sysfs_dirent
226 * @sd: sysfs_dirent to deactivate 149 * @sd: sysfs_dirent to deactivate
227 * 150 *
@@ -233,17 +156,27 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
233 int v; 156 int v;
234 157
235 BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); 158 BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
159
160 if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF))
161 return;
162
236 sd->s_sibling = (void *)&wait; 163 sd->s_sibling = (void *)&wait;
237 164
165 rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
238 /* atomic_add_return() is a mb(), put_active() will always see 166 /* atomic_add_return() is a mb(), put_active() will always see
239 * the updated sd->s_sibling. 167 * the updated sd->s_sibling.
240 */ 168 */
241 v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active); 169 v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
242 170
243 if (v != SD_DEACTIVATED_BIAS) 171 if (v != SD_DEACTIVATED_BIAS) {
172 lock_contended(&sd->dep_map, _RET_IP_);
244 wait_for_completion(&wait); 173 wait_for_completion(&wait);
174 }
245 175
246 sd->s_sibling = NULL; 176 sd->s_sibling = NULL;
177
178 lock_acquired(&sd->dep_map, _RET_IP_);
179 rwsem_release(&sd->dep_map, 1, _RET_IP_);
247} 180}
248 181
249static int sysfs_alloc_ino(ino_t *pino) 182static int sysfs_alloc_ino(ino_t *pino)
@@ -298,7 +231,61 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
298 goto repeat; 231 goto repeat;
299} 232}
300 233
301static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) 234static int sysfs_dentry_delete(struct dentry *dentry)
235{
236 struct sysfs_dirent *sd = dentry->d_fsdata;
237 return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
238}
239
240static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
241{
242 struct sysfs_dirent *sd = dentry->d_fsdata;
243 int is_dir;
244
245 mutex_lock(&sysfs_mutex);
246
247 /* The sysfs dirent has been deleted */
248 if (sd->s_flags & SYSFS_FLAG_REMOVED)
249 goto out_bad;
250
251 /* The sysfs dirent has been moved? */
252 if (dentry->d_parent->d_fsdata != sd->s_parent)
253 goto out_bad;
254
255 /* The sysfs dirent has been renamed */
256 if (strcmp(dentry->d_name.name, sd->s_name) != 0)
257 goto out_bad;
258
259 mutex_unlock(&sysfs_mutex);
260out_valid:
261 return 1;
262out_bad:
263 /* Remove the dentry from the dcache hashes.
264 * If this is a deleted dentry we use d_drop instead of d_delete
265 * so sysfs doesn't need to cope with negative dentries.
266 *
267 * If this is a dentry that has simply been renamed we
268 * use d_drop to remove it from the dcache lookup on its
269 * old parent. If this dentry persists later when a lookup
270 * is performed at its new name the dentry will be readded
271 * to the dcache hashes.
272 */
273 is_dir = (sysfs_type(sd) == SYSFS_DIR);
274 mutex_unlock(&sysfs_mutex);
275 if (is_dir) {
276 /* If we have submounts we must allow the vfs caches
277 * to lie about the state of the filesystem to prevent
278 * leaks and other nasty things.
279 */
280 if (have_submounts(dentry))
281 goto out_valid;
282 shrink_dcache_parent(dentry);
283 }
284 d_drop(dentry);
285 return 0;
286}
287
288static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode)
302{ 289{
303 struct sysfs_dirent * sd = dentry->d_fsdata; 290 struct sysfs_dirent * sd = dentry->d_fsdata;
304 291
@@ -307,7 +294,9 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
307} 294}
308 295
309static const struct dentry_operations sysfs_dentry_ops = { 296static const struct dentry_operations sysfs_dentry_ops = {
310 .d_iput = sysfs_d_iput, 297 .d_revalidate = sysfs_dentry_revalidate,
298 .d_delete = sysfs_dentry_delete,
299 .d_iput = sysfs_dentry_iput,
311}; 300};
312 301
313struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) 302struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
@@ -344,12 +333,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
344 return NULL; 333 return NULL;
345} 334}
346 335
347static int sysfs_ilookup_test(struct inode *inode, void *arg)
348{
349 struct sysfs_dirent *sd = arg;
350 return inode->i_ino == sd->s_ino;
351}
352
353/** 336/**
354 * sysfs_addrm_start - prepare for sysfs_dirent add/remove 337 * sysfs_addrm_start - prepare for sysfs_dirent add/remove
355 * @acxt: pointer to sysfs_addrm_cxt to be used 338 * @acxt: pointer to sysfs_addrm_cxt to be used
@@ -357,47 +340,20 @@ static int sysfs_ilookup_test(struct inode *inode, void *arg)
357 * 340 *
358 * This function is called when the caller is about to add or 341 * This function is called when the caller is about to add or
359 * remove sysfs_dirent under @parent_sd. This function acquires 342 * remove sysfs_dirent under @parent_sd. This function acquires
360 * sysfs_mutex, grabs inode for @parent_sd if available and lock 343 * sysfs_mutex. @acxt is used to keep and pass context to
361 * i_mutex of it. @acxt is used to keep and pass context to
362 * other addrm functions. 344 * other addrm functions.
363 * 345 *
364 * LOCKING: 346 * LOCKING:
365 * Kernel thread context (may sleep). sysfs_mutex is locked on 347 * Kernel thread context (may sleep). sysfs_mutex is locked on
366 * return. i_mutex of parent inode is locked on return if 348 * return.
367 * available.
368 */ 349 */
369void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, 350void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
370 struct sysfs_dirent *parent_sd) 351 struct sysfs_dirent *parent_sd)
371{ 352{
372 struct inode *inode;
373
374 memset(acxt, 0, sizeof(*acxt)); 353 memset(acxt, 0, sizeof(*acxt));
375 acxt->parent_sd = parent_sd; 354 acxt->parent_sd = parent_sd;
376 355
377 /* Lookup parent inode. inode initialization is protected by
378 * sysfs_mutex, so inode existence can be determined by
379 * looking up inode while holding sysfs_mutex.
380 */
381 mutex_lock(&sysfs_mutex); 356 mutex_lock(&sysfs_mutex);
382
383 inode = ilookup5(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
384 parent_sd);
385 if (inode) {
386 WARN_ON(inode->i_state & I_NEW);
387
388 /* parent inode available */
389 acxt->parent_inode = inode;
390
391 /* sysfs_mutex is below i_mutex in lock hierarchy.
392 * First, trylock i_mutex. If fails, unlock
393 * sysfs_mutex and lock them in order.
394 */
395 if (!mutex_trylock(&inode->i_mutex)) {
396 mutex_unlock(&sysfs_mutex);
397 mutex_lock(&inode->i_mutex);
398 mutex_lock(&sysfs_mutex);
399 }
400 }
401} 357}
402 358
403/** 359/**
@@ -422,18 +378,22 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
422 */ 378 */
423int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 379int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
424{ 380{
381 struct sysfs_inode_attrs *ps_iattr;
382
425 if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) 383 if (sysfs_find_dirent(acxt->parent_sd, sd->s_name))
426 return -EEXIST; 384 return -EEXIST;
427 385
428 sd->s_parent = sysfs_get(acxt->parent_sd); 386 sd->s_parent = sysfs_get(acxt->parent_sd);
429 387
430 if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
431 inc_nlink(acxt->parent_inode);
432
433 acxt->cnt++;
434
435 sysfs_link_sibling(sd); 388 sysfs_link_sibling(sd);
436 389
390 /* Update timestamps on the parent */
391 ps_iattr = acxt->parent_sd->s_iattr;
392 if (ps_iattr) {
393 struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
394 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
395 }
396
437 return 0; 397 return 0;
438} 398}
439 399
@@ -512,70 +472,22 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
512 */ 472 */
513void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 473void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
514{ 474{
475 struct sysfs_inode_attrs *ps_iattr;
476
515 BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED); 477 BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED);
516 478
517 sysfs_unlink_sibling(sd); 479 sysfs_unlink_sibling(sd);
518 480
481 /* Update timestamps on the parent */
482 ps_iattr = acxt->parent_sd->s_iattr;
483 if (ps_iattr) {
484 struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
485 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
486 }
487
519 sd->s_flags |= SYSFS_FLAG_REMOVED; 488 sd->s_flags |= SYSFS_FLAG_REMOVED;
520 sd->s_sibling = acxt->removed; 489 sd->s_sibling = acxt->removed;
521 acxt->removed = sd; 490 acxt->removed = sd;
522
523 if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
524 drop_nlink(acxt->parent_inode);
525
526 acxt->cnt++;
527}
528
529/**
530 * sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
531 * @sd: target sysfs_dirent
532 *
533 * Drop dentry for @sd. @sd must have been unlinked from its
534 * parent on entry to this function such that it can't be looked
535 * up anymore.
536 */
537static void sysfs_drop_dentry(struct sysfs_dirent *sd)
538{
539 struct inode *inode;
540 struct dentry *dentry;
541
542 inode = ilookup(sysfs_sb, sd->s_ino);
543 if (!inode)
544 return;
545
546 /* Drop any existing dentries associated with sd.
547 *
548 * For the dentry to be properly freed we need to grab a
549 * reference to the dentry under the dcache lock, unhash it,
550 * and then put it. The playing with the dentry count allows
551 * dput to immediately free the dentry if it is not in use.
552 */
553repeat:
554 spin_lock(&dcache_lock);
555 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
556 if (d_unhashed(dentry))
557 continue;
558 dget_locked(dentry);
559 spin_lock(&dentry->d_lock);
560 __d_drop(dentry);
561 spin_unlock(&dentry->d_lock);
562 spin_unlock(&dcache_lock);
563 dput(dentry);
564 goto repeat;
565 }
566 spin_unlock(&dcache_lock);
567
568 /* adjust nlink and update timestamp */
569 mutex_lock(&inode->i_mutex);
570
571 inode->i_ctime = CURRENT_TIME;
572 drop_nlink(inode);
573 if (sysfs_type(sd) == SYSFS_DIR)
574 drop_nlink(inode);
575
576 mutex_unlock(&inode->i_mutex);
577
578 iput(inode);
579} 491}
580 492
581/** 493/**
@@ -584,25 +496,15 @@ repeat:
584 * 496 *
585 * Finish up sysfs_dirent add/remove. Resources acquired by 497 * Finish up sysfs_dirent add/remove. Resources acquired by
586 * sysfs_addrm_start() are released and removed sysfs_dirents are 498 * sysfs_addrm_start() are released and removed sysfs_dirents are
587 * cleaned up. Timestamps on the parent inode are updated. 499 * cleaned up.
588 * 500 *
589 * LOCKING: 501 * LOCKING:
590 * All mutexes acquired by sysfs_addrm_start() are released. 502 * sysfs_mutex is released.
591 */ 503 */
592void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) 504void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
593{ 505{
594 /* release resources acquired by sysfs_addrm_start() */ 506 /* release resources acquired by sysfs_addrm_start() */
595 mutex_unlock(&sysfs_mutex); 507 mutex_unlock(&sysfs_mutex);
596 if (acxt->parent_inode) {
597 struct inode *inode = acxt->parent_inode;
598
599 /* if added/removed, update timestamps on the parent */
600 if (acxt->cnt)
601 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
602
603 mutex_unlock(&inode->i_mutex);
604 iput(inode);
605 }
606 508
607 /* kill removed sysfs_dirents */ 509 /* kill removed sysfs_dirents */
608 while (acxt->removed) { 510 while (acxt->removed) {
@@ -611,7 +513,6 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
611 acxt->removed = sd->s_sibling; 513 acxt->removed = sd->s_sibling;
612 sd->s_sibling = NULL; 514 sd->s_sibling = NULL;
613 515
614 sysfs_drop_dentry(sd);
615 sysfs_deactivate(sd); 516 sysfs_deactivate(sd);
616 unmap_bin_file(sd); 517 unmap_bin_file(sd);
617 sysfs_put(sd); 518 sysfs_put(sd);
@@ -744,17 +645,22 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
744 } 645 }
745 646
746 /* attach dentry and inode */ 647 /* attach dentry and inode */
747 inode = sysfs_get_inode(sd); 648 inode = sysfs_get_inode(dir->i_sb, sd);
748 if (!inode) { 649 if (!inode) {
749 ret = ERR_PTR(-ENOMEM); 650 ret = ERR_PTR(-ENOMEM);
750 goto out_unlock; 651 goto out_unlock;
751 } 652 }
752 653
753 /* instantiate and hash dentry */ 654 /* instantiate and hash dentry */
754 dentry->d_op = &sysfs_dentry_ops; 655 ret = d_find_alias(inode);
755 dentry->d_fsdata = sysfs_get(sd); 656 if (!ret) {
756 d_instantiate(dentry, inode); 657 dentry->d_op = &sysfs_dentry_ops;
757 d_rehash(dentry); 658 dentry->d_fsdata = sysfs_get(sd);
659 d_add(dentry, inode);
660 } else {
661 d_move(ret, dentry);
662 iput(inode);
663 }
758 664
759 out_unlock: 665 out_unlock:
760 mutex_unlock(&sysfs_mutex); 666 mutex_unlock(&sysfs_mutex);
@@ -763,7 +669,9 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
763 669
764const struct inode_operations sysfs_dir_inode_operations = { 670const struct inode_operations sysfs_dir_inode_operations = {
765 .lookup = sysfs_lookup, 671 .lookup = sysfs_lookup,
672 .permission = sysfs_permission,
766 .setattr = sysfs_setattr, 673 .setattr = sysfs_setattr,
674 .getattr = sysfs_getattr,
767 .setxattr = sysfs_setxattr, 675 .setxattr = sysfs_setxattr,
768}; 676};
769 677
@@ -826,141 +734,65 @@ void sysfs_remove_dir(struct kobject * kobj)
826 __sysfs_remove_dir(sd); 734 __sysfs_remove_dir(sd);
827} 735}
828 736
829int sysfs_rename_dir(struct kobject * kobj, const char *new_name) 737int sysfs_rename(struct sysfs_dirent *sd,
738 struct sysfs_dirent *new_parent_sd, const char *new_name)
830{ 739{
831 struct sysfs_dirent *sd = kobj->sd;
832 struct dentry *parent = NULL;
833 struct dentry *old_dentry = NULL, *new_dentry = NULL;
834 const char *dup_name = NULL; 740 const char *dup_name = NULL;
835 int error; 741 int error;
836 742
837 mutex_lock(&sysfs_rename_mutex); 743 mutex_lock(&sysfs_mutex);
838 744
839 error = 0; 745 error = 0;
840 if (strcmp(sd->s_name, new_name) == 0) 746 if ((sd->s_parent == new_parent_sd) &&
747 (strcmp(sd->s_name, new_name) == 0))
841 goto out; /* nothing to rename */ 748 goto out; /* nothing to rename */
842 749
843 /* get the original dentry */
844 old_dentry = sysfs_get_dentry(sd);
845 if (IS_ERR(old_dentry)) {
846 error = PTR_ERR(old_dentry);
847 old_dentry = NULL;
848 goto out;
849 }
850
851 parent = old_dentry->d_parent;
852
853 /* lock parent and get dentry for new name */
854 mutex_lock(&parent->d_inode->i_mutex);
855 mutex_lock(&sysfs_mutex);
856
857 error = -EEXIST; 750 error = -EEXIST;
858 if (sysfs_find_dirent(sd->s_parent, new_name)) 751 if (sysfs_find_dirent(new_parent_sd, new_name))
859 goto out_unlock; 752 goto out;
860
861 error = -ENOMEM;
862 new_dentry = d_alloc_name(parent, new_name);
863 if (!new_dentry)
864 goto out_unlock;
865 753
866 /* rename sysfs_dirent */ 754 /* rename sysfs_dirent */
867 error = -ENOMEM; 755 if (strcmp(sd->s_name, new_name) != 0) {
868 new_name = dup_name = kstrdup(new_name, GFP_KERNEL); 756 error = -ENOMEM;
869 if (!new_name) 757 new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
870 goto out_unlock; 758 if (!new_name)
871 759 goto out;
872 dup_name = sd->s_name; 760
873 sd->s_name = new_name; 761 dup_name = sd->s_name;
762 sd->s_name = new_name;
763 }
874 764
875 /* rename */ 765 /* Remove from old parent's list and insert into new parent's list. */
876 d_add(new_dentry, NULL); 766 if (sd->s_parent != new_parent_sd) {
877 d_move(old_dentry, new_dentry); 767 sysfs_unlink_sibling(sd);
768 sysfs_get(new_parent_sd);
769 sysfs_put(sd->s_parent);
770 sd->s_parent = new_parent_sd;
771 sysfs_link_sibling(sd);
772 }
878 773
879 error = 0; 774 error = 0;
880 out_unlock: 775 out:
881 mutex_unlock(&sysfs_mutex); 776 mutex_unlock(&sysfs_mutex);
882 mutex_unlock(&parent->d_inode->i_mutex);
883 kfree(dup_name); 777 kfree(dup_name);
884 dput(old_dentry);
885 dput(new_dentry);
886 out:
887 mutex_unlock(&sysfs_rename_mutex);
888 return error; 778 return error;
889} 779}
890 780
781int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
782{
783 return sysfs_rename(kobj->sd, kobj->sd->s_parent, new_name);
784}
785
891int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) 786int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
892{ 787{
893 struct sysfs_dirent *sd = kobj->sd; 788 struct sysfs_dirent *sd = kobj->sd;
894 struct sysfs_dirent *new_parent_sd; 789 struct sysfs_dirent *new_parent_sd;
895 struct dentry *old_parent, *new_parent = NULL;
896 struct dentry *old_dentry = NULL, *new_dentry = NULL;
897 int error;
898 790
899 mutex_lock(&sysfs_rename_mutex);
900 BUG_ON(!sd->s_parent); 791 BUG_ON(!sd->s_parent);
901 new_parent_sd = (new_parent_kobj && new_parent_kobj->sd) ? 792 new_parent_sd = new_parent_kobj && new_parent_kobj->sd ?
902 new_parent_kobj->sd : &sysfs_root; 793 new_parent_kobj->sd : &sysfs_root;
903 794
904 error = 0; 795 return sysfs_rename(sd, new_parent_sd, sd->s_name);
905 if (sd->s_parent == new_parent_sd)
906 goto out; /* nothing to move */
907
908 /* get dentries */
909 old_dentry = sysfs_get_dentry(sd);
910 if (IS_ERR(old_dentry)) {
911 error = PTR_ERR(old_dentry);
912 old_dentry = NULL;
913 goto out;
914 }
915 old_parent = old_dentry->d_parent;
916
917 new_parent = sysfs_get_dentry(new_parent_sd);
918 if (IS_ERR(new_parent)) {
919 error = PTR_ERR(new_parent);
920 new_parent = NULL;
921 goto out;
922 }
923
924again:
925 mutex_lock(&old_parent->d_inode->i_mutex);
926 if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
927 mutex_unlock(&old_parent->d_inode->i_mutex);
928 goto again;
929 }
930 mutex_lock(&sysfs_mutex);
931
932 error = -EEXIST;
933 if (sysfs_find_dirent(new_parent_sd, sd->s_name))
934 goto out_unlock;
935
936 error = -ENOMEM;
937 new_dentry = d_alloc_name(new_parent, sd->s_name);
938 if (!new_dentry)
939 goto out_unlock;
940
941 error = 0;
942 d_add(new_dentry, NULL);
943 d_move(old_dentry, new_dentry);
944
945 /* Remove from old parent's list and insert into new parent's list. */
946 sysfs_unlink_sibling(sd);
947 sysfs_get(new_parent_sd);
948 drop_nlink(old_parent->d_inode);
949 sysfs_put(sd->s_parent);
950 sd->s_parent = new_parent_sd;
951 inc_nlink(new_parent->d_inode);
952 sysfs_link_sibling(sd);
953
954 out_unlock:
955 mutex_unlock(&sysfs_mutex);
956 mutex_unlock(&new_parent->d_inode->i_mutex);
957 mutex_unlock(&old_parent->d_inode->i_mutex);
958 out:
959 dput(new_parent);
960 dput(old_dentry);
961 dput(new_dentry);
962 mutex_unlock(&sysfs_rename_mutex);
963 return error;
964} 796}
965 797
966/* Relationship between s_mode and the DT_xxx types */ 798/* Relationship between s_mode and the DT_xxx types */
@@ -969,11 +801,46 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
969 return (sd->s_mode >> 12) & 15; 801 return (sd->s_mode >> 12) & 15;
970} 802}
971 803
804static int sysfs_dir_release(struct inode *inode, struct file *filp)
805{
806 sysfs_put(filp->private_data);
807 return 0;
808}
809
810static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd,
811 ino_t ino, struct sysfs_dirent *pos)
812{
813 if (pos) {
814 int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
815 pos->s_parent == parent_sd &&
816 ino == pos->s_ino;
817 sysfs_put(pos);
818 if (valid)
819 return pos;
820 }
821 pos = NULL;
822 if ((ino > 1) && (ino < INT_MAX)) {
823 pos = parent_sd->s_dir.children;
824 while (pos && (ino > pos->s_ino))
825 pos = pos->s_sibling;
826 }
827 return pos;
828}
829
830static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd,
831 ino_t ino, struct sysfs_dirent *pos)
832{
833 pos = sysfs_dir_pos(parent_sd, ino, pos);
834 if (pos)
835 pos = pos->s_sibling;
836 return pos;
837}
838
972static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 839static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
973{ 840{
974 struct dentry *dentry = filp->f_path.dentry; 841 struct dentry *dentry = filp->f_path.dentry;
975 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 842 struct sysfs_dirent * parent_sd = dentry->d_fsdata;
976 struct sysfs_dirent *pos; 843 struct sysfs_dirent *pos = filp->private_data;
977 ino_t ino; 844 ino_t ino;
978 845
979 if (filp->f_pos == 0) { 846 if (filp->f_pos == 0) {
@@ -989,29 +856,31 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
989 if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) 856 if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
990 filp->f_pos++; 857 filp->f_pos++;
991 } 858 }
992 if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { 859 mutex_lock(&sysfs_mutex);
993 mutex_lock(&sysfs_mutex); 860 for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos);
994 861 pos;
995 /* Skip the dentries we have already reported */ 862 pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) {
996 pos = parent_sd->s_dir.children; 863 const char * name;
997 while (pos && (filp->f_pos > pos->s_ino)) 864 unsigned int type;
998 pos = pos->s_sibling; 865 int len, ret;
999 866
1000 for ( ; pos; pos = pos->s_sibling) { 867 name = pos->s_name;
1001 const char * name; 868 len = strlen(name);
1002 int len; 869 ino = pos->s_ino;
1003 870 type = dt_type(pos);
1004 name = pos->s_name; 871 filp->f_pos = ino;
1005 len = strlen(name); 872 filp->private_data = sysfs_get(pos);
1006 filp->f_pos = ino = pos->s_ino;
1007 873
1008 if (filldir(dirent, name, len, filp->f_pos, ino,
1009 dt_type(pos)) < 0)
1010 break;
1011 }
1012 if (!pos)
1013 filp->f_pos = INT_MAX;
1014 mutex_unlock(&sysfs_mutex); 874 mutex_unlock(&sysfs_mutex);
875 ret = filldir(dirent, name, len, filp->f_pos, ino, type);
876 mutex_lock(&sysfs_mutex);
877 if (ret < 0)
878 break;
879 }
880 mutex_unlock(&sysfs_mutex);
881 if ((filp->f_pos > 1) && !pos) { /* EOF */
882 filp->f_pos = INT_MAX;
883 filp->private_data = NULL;
1015 } 884 }
1016 return 0; 885 return 0;
1017} 886}
@@ -1020,5 +889,6 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
1020const struct file_operations sysfs_dir_operations = { 889const struct file_operations sysfs_dir_operations = {
1021 .read = generic_read_dir, 890 .read = generic_read_dir,
1022 .readdir = sysfs_readdir, 891 .readdir = sysfs_readdir,
892 .release = sysfs_dir_release,
1023 .llseek = generic_file_llseek, 893 .llseek = generic_file_llseek,
1024}; 894};
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index f5ea4680f15f..e222b2582746 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -53,7 +53,7 @@ struct sysfs_buffer {
53 size_t count; 53 size_t count;
54 loff_t pos; 54 loff_t pos;
55 char * page; 55 char * page;
56 struct sysfs_ops * ops; 56 const struct sysfs_ops * ops;
57 struct mutex mutex; 57 struct mutex mutex;
58 int needs_read_fill; 58 int needs_read_fill;
59 int event; 59 int event;
@@ -75,7 +75,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
75{ 75{
76 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 76 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
77 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 77 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
78 struct sysfs_ops * ops = buffer->ops; 78 const struct sysfs_ops * ops = buffer->ops;
79 int ret = 0; 79 int ret = 0;
80 ssize_t count; 80 ssize_t count;
81 81
@@ -85,13 +85,13 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
85 return -ENOMEM; 85 return -ENOMEM;
86 86
87 /* need attr_sd for attr and ops, its parent for kobj */ 87 /* need attr_sd for attr and ops, its parent for kobj */
88 if (!sysfs_get_active_two(attr_sd)) 88 if (!sysfs_get_active(attr_sd))
89 return -ENODEV; 89 return -ENODEV;
90 90
91 buffer->event = atomic_read(&attr_sd->s_attr.open->event); 91 buffer->event = atomic_read(&attr_sd->s_attr.open->event);
92 count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); 92 count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
93 93
94 sysfs_put_active_two(attr_sd); 94 sysfs_put_active(attr_sd);
95 95
96 /* 96 /*
97 * The code works fine with PAGE_SIZE return but it's likely to 97 * The code works fine with PAGE_SIZE return but it's likely to
@@ -199,16 +199,16 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
199{ 199{
200 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 200 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
201 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 201 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
202 struct sysfs_ops * ops = buffer->ops; 202 const struct sysfs_ops * ops = buffer->ops;
203 int rc; 203 int rc;
204 204
205 /* need attr_sd for attr and ops, its parent for kobj */ 205 /* need attr_sd for attr and ops, its parent for kobj */
206 if (!sysfs_get_active_two(attr_sd)) 206 if (!sysfs_get_active(attr_sd))
207 return -ENODEV; 207 return -ENODEV;
208 208
209 rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); 209 rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
210 210
211 sysfs_put_active_two(attr_sd); 211 sysfs_put_active(attr_sd);
212 212
213 return rc; 213 return rc;
214} 214}
@@ -335,7 +335,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
335 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 335 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
336 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 336 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
337 struct sysfs_buffer *buffer; 337 struct sysfs_buffer *buffer;
338 struct sysfs_ops *ops; 338 const struct sysfs_ops *ops;
339 int error = -EACCES; 339 int error = -EACCES;
340 char *p; 340 char *p;
341 341
@@ -344,7 +344,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
344 memmove(last_sysfs_file, p, strlen(p) + 1); 344 memmove(last_sysfs_file, p, strlen(p) + 1);
345 345
346 /* need attr_sd for attr and ops, its parent for kobj */ 346 /* need attr_sd for attr and ops, its parent for kobj */
347 if (!sysfs_get_active_two(attr_sd)) 347 if (!sysfs_get_active(attr_sd))
348 return -ENODEV; 348 return -ENODEV;
349 349
350 /* every kobject with an attribute needs a ktype assigned */ 350 /* every kobject with an attribute needs a ktype assigned */
@@ -393,13 +393,13 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
393 goto err_free; 393 goto err_free;
394 394
395 /* open succeeded, put active references */ 395 /* open succeeded, put active references */
396 sysfs_put_active_two(attr_sd); 396 sysfs_put_active(attr_sd);
397 return 0; 397 return 0;
398 398
399 err_free: 399 err_free:
400 kfree(buffer); 400 kfree(buffer);
401 err_out: 401 err_out:
402 sysfs_put_active_two(attr_sd); 402 sysfs_put_active(attr_sd);
403 return error; 403 return error;
404} 404}
405 405
@@ -437,12 +437,12 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
437 struct sysfs_open_dirent *od = attr_sd->s_attr.open; 437 struct sysfs_open_dirent *od = attr_sd->s_attr.open;
438 438
439 /* need parent for the kobj, grab both */ 439 /* need parent for the kobj, grab both */
440 if (!sysfs_get_active_two(attr_sd)) 440 if (!sysfs_get_active(attr_sd))
441 goto trigger; 441 goto trigger;
442 442
443 poll_wait(filp, &od->poll, wait); 443 poll_wait(filp, &od->poll, wait);
444 444
445 sysfs_put_active_two(attr_sd); 445 sysfs_put_active(attr_sd);
446 446
447 if (buffer->event != atomic_read(&od->event)) 447 if (buffer->event != atomic_read(&od->event))
448 goto trigger; 448 goto trigger;
@@ -509,6 +509,7 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
509 if (!sd) 509 if (!sd)
510 return -ENOMEM; 510 return -ENOMEM;
511 sd->s_attr.attr = (void *)attr; 511 sd->s_attr.attr = (void *)attr;
512 sysfs_dirent_init_lockdep(sd);
512 513
513 sysfs_addrm_start(&acxt, dir_sd); 514 sysfs_addrm_start(&acxt, dir_sd);
514 rc = sysfs_add_one(&acxt, sd); 515 rc = sysfs_add_one(&acxt, sd);
@@ -542,6 +543,18 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
542 543
543} 544}
544 545
546int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
547{
548 int err = 0;
549 int i;
550
551 for (i = 0; ptr[i] && !err; i++)
552 err = sysfs_create_file(kobj, ptr[i]);
553 if (err)
554 while (--i >= 0)
555 sysfs_remove_file(kobj, ptr[i]);
556 return err;
557}
545 558
546/** 559/**
547 * sysfs_add_file_to_group - add an attribute file to a pre-existing group. 560 * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
@@ -579,46 +592,23 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
579 */ 592 */
580int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) 593int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
581{ 594{
582 struct sysfs_dirent *victim_sd = NULL; 595 struct sysfs_dirent *sd;
583 struct dentry *victim = NULL;
584 struct inode * inode;
585 struct iattr newattrs; 596 struct iattr newattrs;
586 int rc; 597 int rc;
587 598
588 rc = -ENOENT; 599 mutex_lock(&sysfs_mutex);
589 victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
590 if (!victim_sd)
591 goto out;
592 600
593 mutex_lock(&sysfs_rename_mutex); 601 rc = -ENOENT;
594 victim = sysfs_get_dentry(victim_sd); 602 sd = sysfs_find_dirent(kobj->sd, attr->name);
595 mutex_unlock(&sysfs_rename_mutex); 603 if (!sd)
596 if (IS_ERR(victim)) {
597 rc = PTR_ERR(victim);
598 victim = NULL;
599 goto out; 604 goto out;
600 }
601
602 inode = victim->d_inode;
603
604 mutex_lock(&inode->i_mutex);
605
606 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
607 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
608 newattrs.ia_ctime = current_fs_time(inode->i_sb);
609 rc = sysfs_setattr(victim, &newattrs);
610 605
611 if (rc == 0) { 606 newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO);
612 fsnotify_change(victim, newattrs.ia_valid); 607 newattrs.ia_valid = ATTR_MODE;
613 mutex_lock(&sysfs_mutex); 608 rc = sysfs_sd_setattr(sd, &newattrs);
614 victim_sd->s_mode = newattrs.ia_mode;
615 mutex_unlock(&sysfs_mutex);
616 }
617 609
618 mutex_unlock(&inode->i_mutex);
619 out: 610 out:
620 dput(victim); 611 mutex_unlock(&sysfs_mutex);
621 sysfs_put(victim_sd);
622 return rc; 612 return rc;
623} 613}
624EXPORT_SYMBOL_GPL(sysfs_chmod_file); 614EXPORT_SYMBOL_GPL(sysfs_chmod_file);
@@ -637,6 +627,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
637 sysfs_hash_and_remove(kobj->sd, attr->name); 627 sysfs_hash_and_remove(kobj->sd, attr->name);
638} 628}
639 629
630void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
631{
632 int i;
633 for (i = 0; ptr[i]; i++)
634 sysfs_remove_file(kobj, ptr[i]);
635}
640 636
641/** 637/**
642 * sysfs_remove_file_from_group - remove an attribute file from a group. 638 * sysfs_remove_file_from_group - remove an attribute file from a group.
@@ -755,3 +751,5 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
755 751
756EXPORT_SYMBOL_GPL(sysfs_create_file); 752EXPORT_SYMBOL_GPL(sysfs_create_file);
757EXPORT_SYMBOL_GPL(sysfs_remove_file); 753EXPORT_SYMBOL_GPL(sysfs_remove_file);
754EXPORT_SYMBOL_GPL(sysfs_remove_files);
755EXPORT_SYMBOL_GPL(sysfs_create_files);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index e28cecf179f5..a4a0a9419711 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -18,6 +18,7 @@
18#include <linux/capability.h> 18#include <linux/capability.h>
19#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/slab.h>
21#include <linux/xattr.h> 22#include <linux/xattr.h>
22#include <linux/security.h> 23#include <linux/security.h>
23#include "sysfs.h" 24#include "sysfs.h"
@@ -37,7 +38,9 @@ static struct backing_dev_info sysfs_backing_dev_info = {
37}; 38};
38 39
39static const struct inode_operations sysfs_inode_operations ={ 40static const struct inode_operations sysfs_inode_operations ={
41 .permission = sysfs_permission,
40 .setattr = sysfs_setattr, 42 .setattr = sysfs_setattr,
43 .getattr = sysfs_getattr,
41 .setxattr = sysfs_setxattr, 44 .setxattr = sysfs_setxattr,
42}; 45};
43 46
@@ -46,7 +49,7 @@ int __init sysfs_inode_init(void)
46 return bdi_init(&sysfs_backing_dev_info); 49 return bdi_init(&sysfs_backing_dev_info);
47} 50}
48 51
49struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) 52static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
50{ 53{
51 struct sysfs_inode_attrs *attrs; 54 struct sysfs_inode_attrs *attrs;
52 struct iattr *iattrs; 55 struct iattr *iattrs;
@@ -64,81 +67,101 @@ struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
64 67
65 return attrs; 68 return attrs;
66} 69}
67int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) 70
71int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr)
68{ 72{
69 struct inode * inode = dentry->d_inode;
70 struct sysfs_dirent * sd = dentry->d_fsdata;
71 struct sysfs_inode_attrs *sd_attrs; 73 struct sysfs_inode_attrs *sd_attrs;
72 struct iattr *iattrs; 74 struct iattr *iattrs;
73 unsigned int ia_valid = iattr->ia_valid; 75 unsigned int ia_valid = iattr->ia_valid;
76
77 sd_attrs = sd->s_iattr;
78
79 if (!sd_attrs) {
80 /* setting attributes for the first time, allocate now */
81 sd_attrs = sysfs_init_inode_attrs(sd);
82 if (!sd_attrs)
83 return -ENOMEM;
84 sd->s_iattr = sd_attrs;
85 }
86 /* attributes were changed at least once in past */
87 iattrs = &sd_attrs->ia_iattr;
88
89 if (ia_valid & ATTR_UID)
90 iattrs->ia_uid = iattr->ia_uid;
91 if (ia_valid & ATTR_GID)
92 iattrs->ia_gid = iattr->ia_gid;
93 if (ia_valid & ATTR_ATIME)
94 iattrs->ia_atime = iattr->ia_atime;
95 if (ia_valid & ATTR_MTIME)
96 iattrs->ia_mtime = iattr->ia_mtime;
97 if (ia_valid & ATTR_CTIME)
98 iattrs->ia_ctime = iattr->ia_ctime;
99 if (ia_valid & ATTR_MODE) {
100 umode_t mode = iattr->ia_mode;
101 iattrs->ia_mode = sd->s_mode = mode;
102 }
103 return 0;
104}
105
106int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
107{
108 struct inode *inode = dentry->d_inode;
109 struct sysfs_dirent *sd = dentry->d_fsdata;
74 int error; 110 int error;
75 111
76 if (!sd) 112 if (!sd)
77 return -EINVAL; 113 return -EINVAL;
78 114
79 sd_attrs = sd->s_iattr; 115 mutex_lock(&sysfs_mutex);
80
81 error = inode_change_ok(inode, iattr); 116 error = inode_change_ok(inode, iattr);
82 if (error) 117 if (error)
83 return error; 118 goto out;
84 119
85 iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */ 120 iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
86 121
87 error = inode_setattr(inode, iattr); 122 error = inode_setattr(inode, iattr);
88 if (error) 123 if (error)
89 return error; 124 goto out;
90 125
91 if (!sd_attrs) { 126 error = sysfs_sd_setattr(sd, iattr);
92 /* setting attributes for the first time, allocate now */ 127out:
93 sd_attrs = sysfs_init_inode_attrs(sd); 128 mutex_unlock(&sysfs_mutex);
94 if (!sd_attrs)
95 return -ENOMEM;
96 sd->s_iattr = sd_attrs;
97 } else {
98 /* attributes were changed at least once in past */
99 iattrs = &sd_attrs->ia_iattr;
100
101 if (ia_valid & ATTR_UID)
102 iattrs->ia_uid = iattr->ia_uid;
103 if (ia_valid & ATTR_GID)
104 iattrs->ia_gid = iattr->ia_gid;
105 if (ia_valid & ATTR_ATIME)
106 iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
107 inode->i_sb->s_time_gran);
108 if (ia_valid & ATTR_MTIME)
109 iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
110 inode->i_sb->s_time_gran);
111 if (ia_valid & ATTR_CTIME)
112 iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
113 inode->i_sb->s_time_gran);
114 if (ia_valid & ATTR_MODE) {
115 umode_t mode = iattr->ia_mode;
116
117 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
118 mode &= ~S_ISGID;
119 iattrs->ia_mode = sd->s_mode = mode;
120 }
121 }
122 return error; 129 return error;
123} 130}
124 131
132static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *secdata_len)
133{
134 struct sysfs_inode_attrs *iattrs;
135 void *old_secdata;
136 size_t old_secdata_len;
137
138 iattrs = sd->s_iattr;
139 if (!iattrs)
140 iattrs = sysfs_init_inode_attrs(sd);
141 if (!iattrs)
142 return -ENOMEM;
143
144 old_secdata = iattrs->ia_secdata;
145 old_secdata_len = iattrs->ia_secdata_len;
146
147 iattrs->ia_secdata = *secdata;
148 iattrs->ia_secdata_len = *secdata_len;
149
150 *secdata = old_secdata;
151 *secdata_len = old_secdata_len;
152 return 0;
153}
154
125int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, 155int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
126 size_t size, int flags) 156 size_t size, int flags)
127{ 157{
128 struct sysfs_dirent *sd = dentry->d_fsdata; 158 struct sysfs_dirent *sd = dentry->d_fsdata;
129 struct sysfs_inode_attrs *iattrs;
130 void *secdata; 159 void *secdata;
131 int error; 160 int error;
132 u32 secdata_len = 0; 161 u32 secdata_len = 0;
133 162
134 if (!sd) 163 if (!sd)
135 return -EINVAL; 164 return -EINVAL;
136 if (!sd->s_iattr)
137 sd->s_iattr = sysfs_init_inode_attrs(sd);
138 if (!sd->s_iattr)
139 return -ENOMEM;
140
141 iattrs = sd->s_iattr;
142 165
143 if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { 166 if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
144 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; 167 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
@@ -150,12 +173,13 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
150 &secdata, &secdata_len); 173 &secdata, &secdata_len);
151 if (error) 174 if (error)
152 goto out; 175 goto out;
153 if (iattrs->ia_secdata)
154 security_release_secctx(iattrs->ia_secdata,
155 iattrs->ia_secdata_len);
156 iattrs->ia_secdata = secdata;
157 iattrs->ia_secdata_len = secdata_len;
158 176
177 mutex_lock(&sysfs_mutex);
178 error = sysfs_sd_setsecdata(sd, &secdata, &secdata_len);
179 mutex_unlock(&sysfs_mutex);
180
181 if (secdata)
182 security_release_secctx(secdata, secdata_len);
159 } else 183 } else
160 return -EINVAL; 184 return -EINVAL;
161out: 185out:
@@ -170,7 +194,6 @@ static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
170 194
171static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) 195static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
172{ 196{
173 inode->i_mode = iattr->ia_mode;
174 inode->i_uid = iattr->ia_uid; 197 inode->i_uid = iattr->ia_uid;
175 inode->i_gid = iattr->ia_gid; 198 inode->i_gid = iattr->ia_gid;
176 inode->i_atime = iattr->ia_atime; 199 inode->i_atime = iattr->ia_atime;
@@ -178,17 +201,6 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
178 inode->i_ctime = iattr->ia_ctime; 201 inode->i_ctime = iattr->ia_ctime;
179} 202}
180 203
181
182/*
183 * sysfs has a different i_mutex lock order behavior for i_mutex than other
184 * filesystems; sysfs i_mutex is called in many places with subsystem locks
185 * held. At the same time, many of the VFS locking rules do not apply to
186 * sysfs at all (cross directory rename for example). To untangle this mess
187 * (which gives false positives in lockdep), we're giving sysfs inodes their
188 * own class for i_mutex.
189 */
190static struct lock_class_key sysfs_inode_imutex_key;
191
192static int sysfs_count_nlink(struct sysfs_dirent *sd) 204static int sysfs_count_nlink(struct sysfs_dirent *sd)
193{ 205{
194 struct sysfs_dirent *child; 206 struct sysfs_dirent *child;
@@ -201,38 +213,55 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
201 return nr + 2; 213 return nr + 2;
202} 214}
203 215
216static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
217{
218 struct sysfs_inode_attrs *iattrs = sd->s_iattr;
219
220 inode->i_mode = sd->s_mode;
221 if (iattrs) {
222 /* sysfs_dirent has non-default attributes
223 * get them from persistent copy in sysfs_dirent
224 */
225 set_inode_attr(inode, &iattrs->ia_iattr);
226 security_inode_notifysecctx(inode,
227 iattrs->ia_secdata,
228 iattrs->ia_secdata_len);
229 }
230
231 if (sysfs_type(sd) == SYSFS_DIR)
232 inode->i_nlink = sysfs_count_nlink(sd);
233}
234
235int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
236{
237 struct sysfs_dirent *sd = dentry->d_fsdata;
238 struct inode *inode = dentry->d_inode;
239
240 mutex_lock(&sysfs_mutex);
241 sysfs_refresh_inode(sd, inode);
242 mutex_unlock(&sysfs_mutex);
243
244 generic_fillattr(inode, stat);
245 return 0;
246}
247
204static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) 248static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
205{ 249{
206 struct bin_attribute *bin_attr; 250 struct bin_attribute *bin_attr;
207 struct sysfs_inode_attrs *iattrs;
208 251
209 inode->i_private = sysfs_get(sd); 252 inode->i_private = sysfs_get(sd);
210 inode->i_mapping->a_ops = &sysfs_aops; 253 inode->i_mapping->a_ops = &sysfs_aops;
211 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; 254 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
212 inode->i_op = &sysfs_inode_operations; 255 inode->i_op = &sysfs_inode_operations;
213 inode->i_ino = sd->s_ino;
214 lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
215 256
216 iattrs = sd->s_iattr; 257 set_default_inode_attr(inode, sd->s_mode);
217 if (iattrs) { 258 sysfs_refresh_inode(sd, inode);
218 /* sysfs_dirent has non-default attributes
219 * get them for the new inode from persistent copy
220 * in sysfs_dirent
221 */
222 set_inode_attr(inode, &iattrs->ia_iattr);
223 if (iattrs->ia_secdata)
224 security_inode_notifysecctx(inode,
225 iattrs->ia_secdata,
226 iattrs->ia_secdata_len);
227 } else
228 set_default_inode_attr(inode, sd->s_mode);
229 259
230 /* initialize inode according to type */ 260 /* initialize inode according to type */
231 switch (sysfs_type(sd)) { 261 switch (sysfs_type(sd)) {
232 case SYSFS_DIR: 262 case SYSFS_DIR:
233 inode->i_op = &sysfs_dir_inode_operations; 263 inode->i_op = &sysfs_dir_inode_operations;
234 inode->i_fop = &sysfs_dir_operations; 264 inode->i_fop = &sysfs_dir_operations;
235 inode->i_nlink = sysfs_count_nlink(sd);
236 break; 265 break;
237 case SYSFS_KOBJ_ATTR: 266 case SYSFS_KOBJ_ATTR:
238 inode->i_size = PAGE_SIZE; 267 inode->i_size = PAGE_SIZE;
@@ -255,6 +284,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
255 284
256/** 285/**
257 * sysfs_get_inode - get inode for sysfs_dirent 286 * sysfs_get_inode - get inode for sysfs_dirent
287 * @sb: super block
258 * @sd: sysfs_dirent to allocate inode for 288 * @sd: sysfs_dirent to allocate inode for
259 * 289 *
260 * Get inode for @sd. If such inode doesn't exist, a new inode 290 * Get inode for @sd. If such inode doesn't exist, a new inode
@@ -267,11 +297,11 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
267 * RETURNS: 297 * RETURNS:
268 * Pointer to allocated inode on success, NULL on failure. 298 * Pointer to allocated inode on success, NULL on failure.
269 */ 299 */
270struct inode * sysfs_get_inode(struct sysfs_dirent *sd) 300struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
271{ 301{
272 struct inode *inode; 302 struct inode *inode;
273 303
274 inode = iget_locked(sysfs_sb, sd->s_ino); 304 inode = iget_locked(sb, sd->s_ino);
275 if (inode && (inode->i_state & I_NEW)) 305 if (inode && (inode->i_state & I_NEW))
276 sysfs_init_inode(sd, inode); 306 sysfs_init_inode(sd, inode);
277 307
@@ -315,3 +345,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
315 else 345 else
316 return -ENOENT; 346 return -ENOENT;
317} 347}
348
349int sysfs_permission(struct inode *inode, int mask)
350{
351 struct sysfs_dirent *sd = inode->i_private;
352
353 mutex_lock(&sysfs_mutex);
354 sysfs_refresh_inode(sd, inode);
355 mutex_unlock(&sysfs_mutex);
356
357 return generic_permission(inode, mask, NULL);
358}
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 49749955ccaf..776137828dca 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -18,12 +18,12 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/magic.h> 20#include <linux/magic.h>
21#include <linux/slab.h>
21 22
22#include "sysfs.h" 23#include "sysfs.h"
23 24
24 25
25static struct vfsmount *sysfs_mount; 26static struct vfsmount *sysfs_mount;
26struct super_block * sysfs_sb = NULL;
27struct kmem_cache *sysfs_dir_cachep; 27struct kmem_cache *sysfs_dir_cachep;
28 28
29static const struct super_operations sysfs_ops = { 29static const struct super_operations sysfs_ops = {
@@ -50,11 +50,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
50 sb->s_magic = SYSFS_MAGIC; 50 sb->s_magic = SYSFS_MAGIC;
51 sb->s_op = &sysfs_ops; 51 sb->s_op = &sysfs_ops;
52 sb->s_time_gran = 1; 52 sb->s_time_gran = 1;
53 sysfs_sb = sb;
54 53
55 /* get root inode, initialize and unlock it */ 54 /* get root inode, initialize and unlock it */
56 mutex_lock(&sysfs_mutex); 55 mutex_lock(&sysfs_mutex);
57 inode = sysfs_get_inode(&sysfs_root); 56 inode = sysfs_get_inode(sb, &sysfs_root);
58 mutex_unlock(&sysfs_mutex); 57 mutex_unlock(&sysfs_mutex);
59 if (!inode) { 58 if (!inode) {
60 pr_debug("sysfs: could not get root inode\n"); 59 pr_debug("sysfs: could not get root inode\n");
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index c5081ad77026..b93ec51fa7ac 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/gfp.h>
14#include <linux/mount.h> 15#include <linux/mount.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/kobject.h> 17#include <linux/kobject.h>
@@ -123,6 +124,44 @@ void sysfs_remove_link(struct kobject * kobj, const char * name)
123 sysfs_hash_and_remove(parent_sd, name); 124 sysfs_hash_and_remove(parent_sd, name);
124} 125}
125 126
127/**
128 * sysfs_rename_link - rename symlink in object's directory.
129 * @kobj: object we're acting for.
130 * @targ: object we're pointing to.
131 * @old: previous name of the symlink.
132 * @new: new name of the symlink.
133 *
134 * A helper function for the common rename symlink idiom.
135 */
136int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
137 const char *old, const char *new)
138{
139 struct sysfs_dirent *parent_sd, *sd = NULL;
140 int result;
141
142 if (!kobj)
143 parent_sd = &sysfs_root;
144 else
145 parent_sd = kobj->sd;
146
147 result = -ENOENT;
148 sd = sysfs_get_dirent(parent_sd, old);
149 if (!sd)
150 goto out;
151
152 result = -EINVAL;
153 if (sysfs_type(sd) != SYSFS_KOBJ_LINK)
154 goto out;
155 if (sd->s_symlink.target_sd->s_dir.kobj != targ)
156 goto out;
157
158 result = sysfs_rename(sd, parent_sd, new);
159
160out:
161 sysfs_put(sd);
162 return result;
163}
164
126static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, 165static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
127 struct sysfs_dirent *target_sd, char *path) 166 struct sysfs_dirent *target_sd, char *path)
128{ 167{
@@ -210,10 +249,13 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
210} 249}
211 250
212const struct inode_operations sysfs_symlink_inode_operations = { 251const struct inode_operations sysfs_symlink_inode_operations = {
213 .setxattr = sysfs_setxattr, 252 .setxattr = sysfs_setxattr,
214 .readlink = generic_readlink, 253 .readlink = generic_readlink,
215 .follow_link = sysfs_follow_link, 254 .follow_link = sysfs_follow_link,
216 .put_link = sysfs_put_link, 255 .put_link = sysfs_put_link,
256 .setattr = sysfs_setattr,
257 .getattr = sysfs_getattr,
258 .permission = sysfs_permission,
217}; 259};
218 260
219 261
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index af4c4e7482ac..30f5a44fb5d3 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -8,6 +8,7 @@
8 * This file is released under the GPLv2. 8 * This file is released under the GPLv2.
9 */ 9 */
10 10
11#include <linux/lockdep.h>
11#include <linux/fs.h> 12#include <linux/fs.h>
12 13
13struct sysfs_open_dirent; 14struct sysfs_open_dirent;
@@ -50,6 +51,9 @@ struct sysfs_inode_attrs {
50struct sysfs_dirent { 51struct sysfs_dirent {
51 atomic_t s_count; 52 atomic_t s_count;
52 atomic_t s_active; 53 atomic_t s_active;
54#ifdef CONFIG_DEBUG_LOCK_ALLOC
55 struct lockdep_map dep_map;
56#endif
53 struct sysfs_dirent *s_parent; 57 struct sysfs_dirent *s_parent;
54 struct sysfs_dirent *s_sibling; 58 struct sysfs_dirent *s_sibling;
55 const char *s_name; 59 const char *s_name;
@@ -62,8 +66,8 @@ struct sysfs_dirent {
62 }; 66 };
63 67
64 unsigned int s_flags; 68 unsigned int s_flags;
69 unsigned short s_mode;
65 ino_t s_ino; 70 ino_t s_ino;
66 umode_t s_mode;
67 struct sysfs_inode_attrs *s_iattr; 71 struct sysfs_inode_attrs *s_iattr;
68}; 72};
69 73
@@ -75,6 +79,7 @@ struct sysfs_dirent {
75#define SYSFS_KOBJ_BIN_ATTR 0x0004 79#define SYSFS_KOBJ_BIN_ATTR 0x0004
76#define SYSFS_KOBJ_LINK 0x0008 80#define SYSFS_KOBJ_LINK 0x0008
77#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) 81#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
82#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
78 83
79#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK 84#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
80#define SYSFS_FLAG_REMOVED 0x0200 85#define SYSFS_FLAG_REMOVED 0x0200
@@ -84,36 +89,46 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
84 return sd->s_flags & SYSFS_TYPE_MASK; 89 return sd->s_flags & SYSFS_TYPE_MASK;
85} 90}
86 91
92#ifdef CONFIG_DEBUG_LOCK_ALLOC
93#define sysfs_dirent_init_lockdep(sd) \
94do { \
95 struct attribute *attr = sd->s_attr.attr; \
96 struct lock_class_key *key = attr->key; \
97 if (!key) \
98 key = &attr->skey; \
99 \
100 lockdep_init_map(&sd->dep_map, "s_active", key, 0); \
101} while(0)
102#else
103#define sysfs_dirent_init_lockdep(sd) do {} while(0)
104#endif
105
87/* 106/*
88 * Context structure to be used while adding/removing nodes. 107 * Context structure to be used while adding/removing nodes.
89 */ 108 */
90struct sysfs_addrm_cxt { 109struct sysfs_addrm_cxt {
91 struct sysfs_dirent *parent_sd; 110 struct sysfs_dirent *parent_sd;
92 struct inode *parent_inode;
93 struct sysfs_dirent *removed; 111 struct sysfs_dirent *removed;
94 int cnt;
95}; 112};
96 113
97/* 114/*
98 * mount.c 115 * mount.c
99 */ 116 */
100extern struct sysfs_dirent sysfs_root; 117extern struct sysfs_dirent sysfs_root;
101extern struct super_block *sysfs_sb;
102extern struct kmem_cache *sysfs_dir_cachep; 118extern struct kmem_cache *sysfs_dir_cachep;
103 119
104/* 120/*
105 * dir.c 121 * dir.c
106 */ 122 */
107extern struct mutex sysfs_mutex; 123extern struct mutex sysfs_mutex;
108extern struct mutex sysfs_rename_mutex;
109extern spinlock_t sysfs_assoc_lock; 124extern spinlock_t sysfs_assoc_lock;
110 125
111extern const struct file_operations sysfs_dir_operations; 126extern const struct file_operations sysfs_dir_operations;
112extern const struct inode_operations sysfs_dir_inode_operations; 127extern const struct inode_operations sysfs_dir_inode_operations;
113 128
114struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); 129struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
115struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); 130struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
116void sysfs_put_active_two(struct sysfs_dirent *sd); 131void sysfs_put_active(struct sysfs_dirent *sd);
117void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, 132void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
118 struct sysfs_dirent *parent_sd); 133 struct sysfs_dirent *parent_sd);
119int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); 134int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
@@ -133,6 +148,9 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
133 struct sysfs_dirent **p_sd); 148 struct sysfs_dirent **p_sd);
134void sysfs_remove_subdir(struct sysfs_dirent *sd); 149void sysfs_remove_subdir(struct sysfs_dirent *sd);
135 150
151int sysfs_rename(struct sysfs_dirent *sd,
152 struct sysfs_dirent *new_parent_sd, const char *new_name);
153
136static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) 154static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
137{ 155{
138 if (sd) { 156 if (sd) {
@@ -153,9 +171,12 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
153/* 171/*
154 * inode.c 172 * inode.c
155 */ 173 */
156struct inode *sysfs_get_inode(struct sysfs_dirent *sd); 174struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
157void sysfs_delete_inode(struct inode *inode); 175void sysfs_delete_inode(struct inode *inode);
176int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
177int sysfs_permission(struct inode *inode, int mask);
158int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); 178int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
179int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
159int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, 180int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
160 size_t size, int flags); 181 size_t size, int flags);
161int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); 182int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);