aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 18:24:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 18:24:56 -0500
commitf58df54a54451c5feb2fdc4bc2f4fb12cf79be01 (patch)
tree930b5892717ce84de93508407ebc35757bbc5ea0 /fs
parent748e566b7e24541e05e3e70be311887a1262f2a1 (diff)
parent3589972e51fac1e02d0aaa576fa47f568cb94d40 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (27 commits) Driver core: fix race in dev_driver_string Driver Core: Early platform driver buffer sysfs: sysfs_setattr remove unnecessary permission check. sysfs: Factor out sysfs_rename from sysfs_rename_dir and sysfs_move_dir sysfs: Propagate renames to the vfs on demand sysfs: Gut sysfs_addrm_start and sysfs_addrm_finish sysfs: In sysfs_chmod_file lazily propagate the mode change. sysfs: Implement sysfs_getattr & sysfs_permission sysfs: Nicely indent sysfs_symlink_inode_operations sysfs: Update s_iattr on link and unlink. sysfs: Fix locking and factor out sysfs_sd_setattr sysfs: Simplify iattr time assignments sysfs: Simplify sysfs_chmod_file semantics sysfs: Use dentry_ops instead of directly playing with the dcache sysfs: Rename sysfs_d_iput to sysfs_dentry_iput sysfs: Update sysfs_setxattr so it updates secdata under the sysfs_mutex debugfs: fix create mutex racy fops and private data Driver core: Don't remove kobjects in device_shutdown. firmware_class: make request_firmware_nowait more useful Driver-Core: devtmpfs - set root directory mode to 0755 ...
Diffstat (limited to 'fs')
-rw-r--r--fs/debugfs/inode.c55
-rw-r--r--fs/namei.c22
-rw-r--r--fs/sysfs/dir.c388
-rw-r--r--fs/sysfs/file.c41
-rw-r--r--fs/sysfs/inode.c176
-rw-r--r--fs/sysfs/symlink.c11
-rw-r--r--fs/sysfs/sysfs.h9
7 files changed, 285 insertions, 417 deletions
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 0d23b52dd22c..b486169f42bf 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -32,7 +32,9 @@ static struct vfsmount *debugfs_mount;
32static int debugfs_mount_count; 32static int debugfs_mount_count;
33static bool debugfs_registered; 33static bool debugfs_registered;
34 34
35static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev) 35static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev,
36 void *data, const struct file_operations *fops)
37
36{ 38{
37 struct inode *inode = new_inode(sb); 39 struct inode *inode = new_inode(sb);
38 40
@@ -44,14 +46,18 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
44 init_special_inode(inode, mode, dev); 46 init_special_inode(inode, mode, dev);
45 break; 47 break;
46 case S_IFREG: 48 case S_IFREG:
47 inode->i_fop = &debugfs_file_operations; 49 inode->i_fop = fops ? fops : &debugfs_file_operations;
50 inode->i_private = data;
48 break; 51 break;
49 case S_IFLNK: 52 case S_IFLNK:
50 inode->i_op = &debugfs_link_operations; 53 inode->i_op = &debugfs_link_operations;
54 inode->i_fop = fops;
55 inode->i_private = data;
51 break; 56 break;
52 case S_IFDIR: 57 case S_IFDIR:
53 inode->i_op = &simple_dir_inode_operations; 58 inode->i_op = &simple_dir_inode_operations;
54 inode->i_fop = &simple_dir_operations; 59 inode->i_fop = fops ? fops : &simple_dir_operations;
60 inode->i_private = data;
55 61
56 /* directory inodes start off with i_nlink == 2 62 /* directory inodes start off with i_nlink == 2
57 * (for "." entry) */ 63 * (for "." entry) */
@@ -64,7 +70,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
64 70
65/* SMP-safe */ 71/* SMP-safe */
66static int debugfs_mknod(struct inode *dir, struct dentry *dentry, 72static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
67 int mode, dev_t dev) 73 int mode, dev_t dev, void *data,
74 const struct file_operations *fops)
68{ 75{
69 struct inode *inode; 76 struct inode *inode;
70 int error = -EPERM; 77 int error = -EPERM;
@@ -72,7 +79,7 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
72 if (dentry->d_inode) 79 if (dentry->d_inode)
73 return -EEXIST; 80 return -EEXIST;
74 81
75 inode = debugfs_get_inode(dir->i_sb, mode, dev); 82 inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops);
76 if (inode) { 83 if (inode) {
77 d_instantiate(dentry, inode); 84 d_instantiate(dentry, inode);
78 dget(dentry); 85 dget(dentry);
@@ -81,12 +88,13 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
81 return error; 88 return error;
82} 89}
83 90
84static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 91static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
92 void *data, const struct file_operations *fops)
85{ 93{
86 int res; 94 int res;
87 95
88 mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; 96 mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
89 res = debugfs_mknod(dir, dentry, mode, 0); 97 res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
90 if (!res) { 98 if (!res) {
91 inc_nlink(dir); 99 inc_nlink(dir);
92 fsnotify_mkdir(dir, dentry); 100 fsnotify_mkdir(dir, dentry);
@@ -94,18 +102,20 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
94 return res; 102 return res;
95} 103}
96 104
97static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode) 105static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode,
106 void *data, const struct file_operations *fops)
98{ 107{
99 mode = (mode & S_IALLUGO) | S_IFLNK; 108 mode = (mode & S_IALLUGO) | S_IFLNK;
100 return debugfs_mknod(dir, dentry, mode, 0); 109 return debugfs_mknod(dir, dentry, mode, 0, data, fops);
101} 110}
102 111
103static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) 112static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode,
113 void *data, const struct file_operations *fops)
104{ 114{
105 int res; 115 int res;
106 116
107 mode = (mode & S_IALLUGO) | S_IFREG; 117 mode = (mode & S_IALLUGO) | S_IFREG;
108 res = debugfs_mknod(dir, dentry, mode, 0); 118 res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
109 if (!res) 119 if (!res)
110 fsnotify_create(dir, dentry); 120 fsnotify_create(dir, dentry);
111 return res; 121 return res;
@@ -139,7 +149,9 @@ static struct file_system_type debug_fs_type = {
139 149
140static int debugfs_create_by_name(const char *name, mode_t mode, 150static int debugfs_create_by_name(const char *name, mode_t mode,
141 struct dentry *parent, 151 struct dentry *parent,
142 struct dentry **dentry) 152 struct dentry **dentry,
153 void *data,
154 const struct file_operations *fops)
143{ 155{
144 int error = 0; 156 int error = 0;
145 157
@@ -164,13 +176,16 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
164 if (!IS_ERR(*dentry)) { 176 if (!IS_ERR(*dentry)) {
165 switch (mode & S_IFMT) { 177 switch (mode & S_IFMT) {
166 case S_IFDIR: 178 case S_IFDIR:
167 error = debugfs_mkdir(parent->d_inode, *dentry, mode); 179 error = debugfs_mkdir(parent->d_inode, *dentry, mode,
180 data, fops);
168 break; 181 break;
169 case S_IFLNK: 182 case S_IFLNK:
170 error = debugfs_link(parent->d_inode, *dentry, mode); 183 error = debugfs_link(parent->d_inode, *dentry, mode,
184 data, fops);
171 break; 185 break;
172 default: 186 default:
173 error = debugfs_create(parent->d_inode, *dentry, mode); 187 error = debugfs_create(parent->d_inode, *dentry, mode,
188 data, fops);
174 break; 189 break;
175 } 190 }
176 dput(*dentry); 191 dput(*dentry);
@@ -221,19 +236,13 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
221 if (error) 236 if (error)
222 goto exit; 237 goto exit;
223 238
224 error = debugfs_create_by_name(name, mode, parent, &dentry); 239 error = debugfs_create_by_name(name, mode, parent, &dentry,
240 data, fops);
225 if (error) { 241 if (error) {
226 dentry = NULL; 242 dentry = NULL;
227 simple_release_fs(&debugfs_mount, &debugfs_mount_count); 243 simple_release_fs(&debugfs_mount, &debugfs_mount_count);
228 goto exit; 244 goto exit;
229 } 245 }
230
231 if (dentry->d_inode) {
232 if (data)
233 dentry->d_inode->i_private = data;
234 if (fops)
235 dentry->d_inode->i_fop = fops;
236 }
237exit: 246exit:
238 return dentry; 247 return dentry;
239} 248}
diff --git a/fs/namei.c b/fs/namei.c
index d11f404667e9..d3c190c35fcc 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1279,28 +1279,6 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
1279 return __lookup_hash(&this, base, NULL); 1279 return __lookup_hash(&this, base, NULL);
1280} 1280}
1281 1281
1282/**
1283 * lookup_one_noperm - bad hack for sysfs
1284 * @name: pathname component to lookup
1285 * @base: base directory to lookup from
1286 *
1287 * This is a variant of lookup_one_len that doesn't perform any permission
1288 * checks. It's a horrible hack to work around the braindead sysfs
1289 * architecture and should not be used anywhere else.
1290 *
1291 * DON'T USE THIS FUNCTION EVER, thanks.
1292 */
1293struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
1294{
1295 int err;
1296 struct qstr this;
1297
1298 err = __lookup_one_len(name, &this, base, strlen(name));
1299 if (err)
1300 return ERR_PTR(err);
1301 return __lookup_hash(&this, base, NULL);
1302}
1303
1304int user_path_at(int dfd, const char __user *name, unsigned flags, 1282int user_path_at(int dfd, const char __user *name, unsigned flags,
1305 struct path *path) 1283 struct path *path)
1306{ 1284{
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index e0201837d244..f05f2303a8b8 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 *
@@ -298,7 +257,61 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
298 goto repeat; 257 goto repeat;
299} 258}
300 259
301static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) 260static int sysfs_dentry_delete(struct dentry *dentry)
261{
262 struct sysfs_dirent *sd = dentry->d_fsdata;
263 return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
264}
265
266static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
267{
268 struct sysfs_dirent *sd = dentry->d_fsdata;
269 int is_dir;
270
271 mutex_lock(&sysfs_mutex);
272
273 /* The sysfs dirent has been deleted */
274 if (sd->s_flags & SYSFS_FLAG_REMOVED)
275 goto out_bad;
276
277 /* The sysfs dirent has been moved? */
278 if (dentry->d_parent->d_fsdata != sd->s_parent)
279 goto out_bad;
280
281 /* The sysfs dirent has been renamed */
282 if (strcmp(dentry->d_name.name, sd->s_name) != 0)
283 goto out_bad;
284
285 mutex_unlock(&sysfs_mutex);
286out_valid:
287 return 1;
288out_bad:
289 /* Remove the dentry from the dcache hashes.
290 * If this is a deleted dentry we use d_drop instead of d_delete
291 * so sysfs doesn't need to cope with negative dentries.
292 *
293 * If this is a dentry that has simply been renamed we
294 * use d_drop to remove it from the dcache lookup on its
295 * old parent. If this dentry persists later when a lookup
296 * is performed at its new name the dentry will be readded
297 * to the dcache hashes.
298 */
299 is_dir = (sysfs_type(sd) == SYSFS_DIR);
300 mutex_unlock(&sysfs_mutex);
301 if (is_dir) {
302 /* If we have submounts we must allow the vfs caches
303 * to lie about the state of the filesystem to prevent
304 * leaks and other nasty things.
305 */
306 if (have_submounts(dentry))
307 goto out_valid;
308 shrink_dcache_parent(dentry);
309 }
310 d_drop(dentry);
311 return 0;
312}
313
314static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode)
302{ 315{
303 struct sysfs_dirent * sd = dentry->d_fsdata; 316 struct sysfs_dirent * sd = dentry->d_fsdata;
304 317
@@ -307,7 +320,9 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
307} 320}
308 321
309static const struct dentry_operations sysfs_dentry_ops = { 322static const struct dentry_operations sysfs_dentry_ops = {
310 .d_iput = sysfs_d_iput, 323 .d_revalidate = sysfs_dentry_revalidate,
324 .d_delete = sysfs_dentry_delete,
325 .d_iput = sysfs_dentry_iput,
311}; 326};
312 327
313struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) 328struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
@@ -344,12 +359,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
344 return NULL; 359 return NULL;
345} 360}
346 361
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/** 362/**
354 * sysfs_addrm_start - prepare for sysfs_dirent add/remove 363 * sysfs_addrm_start - prepare for sysfs_dirent add/remove
355 * @acxt: pointer to sysfs_addrm_cxt to be used 364 * @acxt: pointer to sysfs_addrm_cxt to be used
@@ -357,47 +366,20 @@ static int sysfs_ilookup_test(struct inode *inode, void *arg)
357 * 366 *
358 * This function is called when the caller is about to add or 367 * This function is called when the caller is about to add or
359 * remove sysfs_dirent under @parent_sd. This function acquires 368 * remove sysfs_dirent under @parent_sd. This function acquires
360 * sysfs_mutex, grabs inode for @parent_sd if available and lock 369 * 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. 370 * other addrm functions.
363 * 371 *
364 * LOCKING: 372 * LOCKING:
365 * Kernel thread context (may sleep). sysfs_mutex is locked on 373 * Kernel thread context (may sleep). sysfs_mutex is locked on
366 * return. i_mutex of parent inode is locked on return if 374 * return.
367 * available.
368 */ 375 */
369void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, 376void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
370 struct sysfs_dirent *parent_sd) 377 struct sysfs_dirent *parent_sd)
371{ 378{
372 struct inode *inode;
373
374 memset(acxt, 0, sizeof(*acxt)); 379 memset(acxt, 0, sizeof(*acxt));
375 acxt->parent_sd = parent_sd; 380 acxt->parent_sd = parent_sd;
376 381
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); 382 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} 383}
402 384
403/** 385/**
@@ -422,18 +404,22 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
422 */ 404 */
423int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 405int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
424{ 406{
407 struct sysfs_inode_attrs *ps_iattr;
408
425 if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) 409 if (sysfs_find_dirent(acxt->parent_sd, sd->s_name))
426 return -EEXIST; 410 return -EEXIST;
427 411
428 sd->s_parent = sysfs_get(acxt->parent_sd); 412 sd->s_parent = sysfs_get(acxt->parent_sd);
429 413
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); 414 sysfs_link_sibling(sd);
436 415
416 /* Update timestamps on the parent */
417 ps_iattr = acxt->parent_sd->s_iattr;
418 if (ps_iattr) {
419 struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
420 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
421 }
422
437 return 0; 423 return 0;
438} 424}
439 425
@@ -512,70 +498,22 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
512 */ 498 */
513void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 499void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
514{ 500{
501 struct sysfs_inode_attrs *ps_iattr;
502
515 BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED); 503 BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED);
516 504
517 sysfs_unlink_sibling(sd); 505 sysfs_unlink_sibling(sd);
518 506
507 /* Update timestamps on the parent */
508 ps_iattr = acxt->parent_sd->s_iattr;
509 if (ps_iattr) {
510 struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
511 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
512 }
513
519 sd->s_flags |= SYSFS_FLAG_REMOVED; 514 sd->s_flags |= SYSFS_FLAG_REMOVED;
520 sd->s_sibling = acxt->removed; 515 sd->s_sibling = acxt->removed;
521 acxt->removed = sd; 516 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} 517}
580 518
581/** 519/**
@@ -584,25 +522,15 @@ repeat:
584 * 522 *
585 * Finish up sysfs_dirent add/remove. Resources acquired by 523 * Finish up sysfs_dirent add/remove. Resources acquired by
586 * sysfs_addrm_start() are released and removed sysfs_dirents are 524 * sysfs_addrm_start() are released and removed sysfs_dirents are
587 * cleaned up. Timestamps on the parent inode are updated. 525 * cleaned up.
588 * 526 *
589 * LOCKING: 527 * LOCKING:
590 * All mutexes acquired by sysfs_addrm_start() are released. 528 * sysfs_mutex is released.
591 */ 529 */
592void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) 530void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
593{ 531{
594 /* release resources acquired by sysfs_addrm_start() */ 532 /* release resources acquired by sysfs_addrm_start() */
595 mutex_unlock(&sysfs_mutex); 533 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 534
607 /* kill removed sysfs_dirents */ 535 /* kill removed sysfs_dirents */
608 while (acxt->removed) { 536 while (acxt->removed) {
@@ -611,7 +539,6 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
611 acxt->removed = sd->s_sibling; 539 acxt->removed = sd->s_sibling;
612 sd->s_sibling = NULL; 540 sd->s_sibling = NULL;
613 541
614 sysfs_drop_dentry(sd);
615 sysfs_deactivate(sd); 542 sysfs_deactivate(sd);
616 unmap_bin_file(sd); 543 unmap_bin_file(sd);
617 sysfs_put(sd); 544 sysfs_put(sd);
@@ -751,10 +678,15 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
751 } 678 }
752 679
753 /* instantiate and hash dentry */ 680 /* instantiate and hash dentry */
754 dentry->d_op = &sysfs_dentry_ops; 681 ret = d_find_alias(inode);
755 dentry->d_fsdata = sysfs_get(sd); 682 if (!ret) {
756 d_instantiate(dentry, inode); 683 dentry->d_op = &sysfs_dentry_ops;
757 d_rehash(dentry); 684 dentry->d_fsdata = sysfs_get(sd);
685 d_add(dentry, inode);
686 } else {
687 d_move(ret, dentry);
688 iput(inode);
689 }
758 690
759 out_unlock: 691 out_unlock:
760 mutex_unlock(&sysfs_mutex); 692 mutex_unlock(&sysfs_mutex);
@@ -763,7 +695,9 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
763 695
764const struct inode_operations sysfs_dir_inode_operations = { 696const struct inode_operations sysfs_dir_inode_operations = {
765 .lookup = sysfs_lookup, 697 .lookup = sysfs_lookup,
698 .permission = sysfs_permission,
766 .setattr = sysfs_setattr, 699 .setattr = sysfs_setattr,
700 .getattr = sysfs_getattr,
767 .setxattr = sysfs_setxattr, 701 .setxattr = sysfs_setxattr,
768}; 702};
769 703
@@ -826,141 +760,65 @@ void sysfs_remove_dir(struct kobject * kobj)
826 __sysfs_remove_dir(sd); 760 __sysfs_remove_dir(sd);
827} 761}
828 762
829int sysfs_rename_dir(struct kobject * kobj, const char *new_name) 763int sysfs_rename(struct sysfs_dirent *sd,
764 struct sysfs_dirent *new_parent_sd, const char *new_name)
830{ 765{
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; 766 const char *dup_name = NULL;
835 int error; 767 int error;
836 768
837 mutex_lock(&sysfs_rename_mutex); 769 mutex_lock(&sysfs_mutex);
838 770
839 error = 0; 771 error = 0;
840 if (strcmp(sd->s_name, new_name) == 0) 772 if ((sd->s_parent == new_parent_sd) &&
773 (strcmp(sd->s_name, new_name) == 0))
841 goto out; /* nothing to rename */ 774 goto out; /* nothing to rename */
842 775
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; 776 error = -EEXIST;
858 if (sysfs_find_dirent(sd->s_parent, new_name)) 777 if (sysfs_find_dirent(new_parent_sd, new_name))
859 goto out_unlock; 778 goto out;
860
861 error = -ENOMEM;
862 new_dentry = d_alloc_name(parent, new_name);
863 if (!new_dentry)
864 goto out_unlock;
865 779
866 /* rename sysfs_dirent */ 780 /* rename sysfs_dirent */
867 error = -ENOMEM; 781 if (strcmp(sd->s_name, new_name) != 0) {
868 new_name = dup_name = kstrdup(new_name, GFP_KERNEL); 782 error = -ENOMEM;
869 if (!new_name) 783 new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
870 goto out_unlock; 784 if (!new_name)
871 785 goto out;
872 dup_name = sd->s_name; 786
873 sd->s_name = new_name; 787 dup_name = sd->s_name;
788 sd->s_name = new_name;
789 }
874 790
875 /* rename */ 791 /* Remove from old parent's list and insert into new parent's list. */
876 d_add(new_dentry, NULL); 792 if (sd->s_parent != new_parent_sd) {
877 d_move(old_dentry, new_dentry); 793 sysfs_unlink_sibling(sd);
794 sysfs_get(new_parent_sd);
795 sysfs_put(sd->s_parent);
796 sd->s_parent = new_parent_sd;
797 sysfs_link_sibling(sd);
798 }
878 799
879 error = 0; 800 error = 0;
880 out_unlock: 801 out:
881 mutex_unlock(&sysfs_mutex); 802 mutex_unlock(&sysfs_mutex);
882 mutex_unlock(&parent->d_inode->i_mutex);
883 kfree(dup_name); 803 kfree(dup_name);
884 dput(old_dentry);
885 dput(new_dentry);
886 out:
887 mutex_unlock(&sysfs_rename_mutex);
888 return error; 804 return error;
889} 805}
890 806
807int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
808{
809 return sysfs_rename(kobj->sd, kobj->sd->s_parent, new_name);
810}
811
891int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) 812int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
892{ 813{
893 struct sysfs_dirent *sd = kobj->sd; 814 struct sysfs_dirent *sd = kobj->sd;
894 struct sysfs_dirent *new_parent_sd; 815 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 816
899 mutex_lock(&sysfs_rename_mutex);
900 BUG_ON(!sd->s_parent); 817 BUG_ON(!sd->s_parent);
901 new_parent_sd = (new_parent_kobj && new_parent_kobj->sd) ? 818 new_parent_sd = new_parent_kobj && new_parent_kobj->sd ?
902 new_parent_kobj->sd : &sysfs_root; 819 new_parent_kobj->sd : &sysfs_root;
903 820
904 error = 0; 821 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} 822}
965 823
966/* Relationship between s_mode and the DT_xxx types */ 824/* Relationship between s_mode and the DT_xxx types */
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index f5ea4680f15f..dc30d9e31683 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -579,46 +579,23 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
579 */ 579 */
580int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) 580int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
581{ 581{
582 struct sysfs_dirent *victim_sd = NULL; 582 struct sysfs_dirent *sd;
583 struct dentry *victim = NULL;
584 struct inode * inode;
585 struct iattr newattrs; 583 struct iattr newattrs;
586 int rc; 584 int rc;
587 585
588 rc = -ENOENT; 586 mutex_lock(&sysfs_mutex);
589 victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
590 if (!victim_sd)
591 goto out;
592 587
593 mutex_lock(&sysfs_rename_mutex); 588 rc = -ENOENT;
594 victim = sysfs_get_dentry(victim_sd); 589 sd = sysfs_find_dirent(kobj->sd, attr->name);
595 mutex_unlock(&sysfs_rename_mutex); 590 if (!sd)
596 if (IS_ERR(victim)) {
597 rc = PTR_ERR(victim);
598 victim = NULL;
599 goto out; 591 goto out;
600 }
601
602 inode = victim->d_inode;
603
604 mutex_lock(&inode->i_mutex);
605 592
606 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 593 newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO);
607 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 594 newattrs.ia_valid = ATTR_MODE;
608 newattrs.ia_ctime = current_fs_time(inode->i_sb); 595 rc = sysfs_sd_setattr(sd, &newattrs);
609 rc = sysfs_setattr(victim, &newattrs);
610 596
611 if (rc == 0) {
612 fsnotify_change(victim, newattrs.ia_valid);
613 mutex_lock(&sysfs_mutex);
614 victim_sd->s_mode = newattrs.ia_mode;
615 mutex_unlock(&sysfs_mutex);
616 }
617
618 mutex_unlock(&inode->i_mutex);
619 out: 597 out:
620 dput(victim); 598 mutex_unlock(&sysfs_mutex);
621 sysfs_put(victim_sd);
622 return rc; 599 return rc;
623} 600}
624EXPORT_SYMBOL_GPL(sysfs_chmod_file); 601EXPORT_SYMBOL_GPL(sysfs_chmod_file);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index e28cecf179f5..220b758523ae 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -37,7 +37,9 @@ static struct backing_dev_info sysfs_backing_dev_info = {
37}; 37};
38 38
39static const struct inode_operations sysfs_inode_operations ={ 39static const struct inode_operations sysfs_inode_operations ={
40 .permission = sysfs_permission,
40 .setattr = sysfs_setattr, 41 .setattr = sysfs_setattr,
42 .getattr = sysfs_getattr,
41 .setxattr = sysfs_setxattr, 43 .setxattr = sysfs_setxattr,
42}; 44};
43 45
@@ -46,7 +48,7 @@ int __init sysfs_inode_init(void)
46 return bdi_init(&sysfs_backing_dev_info); 48 return bdi_init(&sysfs_backing_dev_info);
47} 49}
48 50
49struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd) 51static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
50{ 52{
51 struct sysfs_inode_attrs *attrs; 53 struct sysfs_inode_attrs *attrs;
52 struct iattr *iattrs; 54 struct iattr *iattrs;
@@ -64,30 +66,15 @@ struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
64 66
65 return attrs; 67 return attrs;
66} 68}
67int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) 69
70int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr)
68{ 71{
69 struct inode * inode = dentry->d_inode;
70 struct sysfs_dirent * sd = dentry->d_fsdata;
71 struct sysfs_inode_attrs *sd_attrs; 72 struct sysfs_inode_attrs *sd_attrs;
72 struct iattr *iattrs; 73 struct iattr *iattrs;
73 unsigned int ia_valid = iattr->ia_valid; 74 unsigned int ia_valid = iattr->ia_valid;
74 int error;
75
76 if (!sd)
77 return -EINVAL;
78 75
79 sd_attrs = sd->s_iattr; 76 sd_attrs = sd->s_iattr;
80 77
81 error = inode_change_ok(inode, iattr);
82 if (error)
83 return error;
84
85 iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
86
87 error = inode_setattr(inode, iattr);
88 if (error)
89 return error;
90
91 if (!sd_attrs) { 78 if (!sd_attrs) {
92 /* setting attributes for the first time, allocate now */ 79 /* setting attributes for the first time, allocate now */
93 sd_attrs = sysfs_init_inode_attrs(sd); 80 sd_attrs = sysfs_init_inode_attrs(sd);
@@ -103,42 +90,78 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
103 if (ia_valid & ATTR_GID) 90 if (ia_valid & ATTR_GID)
104 iattrs->ia_gid = iattr->ia_gid; 91 iattrs->ia_gid = iattr->ia_gid;
105 if (ia_valid & ATTR_ATIME) 92 if (ia_valid & ATTR_ATIME)
106 iattrs->ia_atime = timespec_trunc(iattr->ia_atime, 93 iattrs->ia_atime = iattr->ia_atime;
107 inode->i_sb->s_time_gran);
108 if (ia_valid & ATTR_MTIME) 94 if (ia_valid & ATTR_MTIME)
109 iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime, 95 iattrs->ia_mtime = iattr->ia_mtime;
110 inode->i_sb->s_time_gran);
111 if (ia_valid & ATTR_CTIME) 96 if (ia_valid & ATTR_CTIME)
112 iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime, 97 iattrs->ia_ctime = iattr->ia_ctime;
113 inode->i_sb->s_time_gran);
114 if (ia_valid & ATTR_MODE) { 98 if (ia_valid & ATTR_MODE) {
115 umode_t mode = iattr->ia_mode; 99 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; 100 iattrs->ia_mode = sd->s_mode = mode;
120 } 101 }
121 } 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;
110 int error;
111
112 if (!sd)
113 return -EINVAL;
114
115 error = inode_change_ok(inode, iattr);
116 if (error)
117 return error;
118
119 iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
120
121 error = inode_setattr(inode, iattr);
122 if (error)
123 return error;
124
125 mutex_lock(&sysfs_mutex);
126 error = sysfs_sd_setattr(sd, iattr);
127 mutex_unlock(&sysfs_mutex);
128
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;
@@ -315,3 +344,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
315 else 344 else
316 return -ENOENT; 345 return -ENOENT;
317} 346}
347
348int sysfs_permission(struct inode *inode, int mask)
349{
350 struct sysfs_dirent *sd = inode->i_private;
351
352 mutex_lock(&sysfs_mutex);
353 sysfs_refresh_inode(sd, inode);
354 mutex_unlock(&sysfs_mutex);
355
356 return generic_permission(inode, mask, NULL);
357}
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index c5081ad77026..c5eff49fa41b 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -210,10 +210,13 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
210} 210}
211 211
212const struct inode_operations sysfs_symlink_inode_operations = { 212const struct inode_operations sysfs_symlink_inode_operations = {
213 .setxattr = sysfs_setxattr, 213 .setxattr = sysfs_setxattr,
214 .readlink = generic_readlink, 214 .readlink = generic_readlink,
215 .follow_link = sysfs_follow_link, 215 .follow_link = sysfs_follow_link,
216 .put_link = sysfs_put_link, 216 .put_link = sysfs_put_link,
217 .setattr = sysfs_setattr,
218 .getattr = sysfs_getattr,
219 .permission = sysfs_permission,
217}; 220};
218 221
219 222
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index af4c4e7482ac..ca52e7b9d8f8 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -89,9 +89,7 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
89 */ 89 */
90struct sysfs_addrm_cxt { 90struct sysfs_addrm_cxt {
91 struct sysfs_dirent *parent_sd; 91 struct sysfs_dirent *parent_sd;
92 struct inode *parent_inode;
93 struct sysfs_dirent *removed; 92 struct sysfs_dirent *removed;
94 int cnt;
95}; 93};
96 94
97/* 95/*
@@ -105,7 +103,6 @@ extern struct kmem_cache *sysfs_dir_cachep;
105 * dir.c 103 * dir.c
106 */ 104 */
107extern struct mutex sysfs_mutex; 105extern struct mutex sysfs_mutex;
108extern struct mutex sysfs_rename_mutex;
109extern spinlock_t sysfs_assoc_lock; 106extern spinlock_t sysfs_assoc_lock;
110 107
111extern const struct file_operations sysfs_dir_operations; 108extern const struct file_operations sysfs_dir_operations;
@@ -133,6 +130,9 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
133 struct sysfs_dirent **p_sd); 130 struct sysfs_dirent **p_sd);
134void sysfs_remove_subdir(struct sysfs_dirent *sd); 131void sysfs_remove_subdir(struct sysfs_dirent *sd);
135 132
133int sysfs_rename(struct sysfs_dirent *sd,
134 struct sysfs_dirent *new_parent_sd, const char *new_name);
135
136static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) 136static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
137{ 137{
138 if (sd) { 138 if (sd) {
@@ -155,7 +155,10 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
155 */ 155 */
156struct inode *sysfs_get_inode(struct sysfs_dirent *sd); 156struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
157void sysfs_delete_inode(struct inode *inode); 157void sysfs_delete_inode(struct inode *inode);
158int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
159int sysfs_permission(struct inode *inode, int mask);
158int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); 160int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
161int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
159int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, 162int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
160 size_t size, int flags); 163 size_t size, int flags);
161int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); 164int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);