diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:13:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:13:47 -0400 |
commit | 53baaaa9682c230410a057263d1ce2922f43ddc4 (patch) | |
tree | f5cced5622130f780d76953b284a631c3d226488 /fs | |
parent | f10140fbe5f97ecfeda986a12d0f1bad75642779 (diff) | |
parent | 3f9787046ea37a26170dc4439efa21f8d23a9978 (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: (79 commits)
arm: bus_id -> dev_name() and dev_set_name() conversions
sparc64: fix up bus_id changes in sparc core code
3c59x: handle pci_name() being const
MTD: handle pci_name() being const
HP iLO driver
sysdev: Convert the x86 mce tolerant sysdev attribute to generic attribute
sysdev: Add utility functions for simple int/ulong variable sysdev attributes
sysdev: Pass the attribute to the low level sysdev show/store function
driver core: Suppress sysfs warnings for device_rename().
kobject: Transmit return value of call_usermodehelper() to caller
sysfs-rules.txt: reword API stability statement
debugfs: Implement debugfs_remove_recursive()
HOWTO: change email addresses of James in HOWTO
always enable FW_LOADER unless EMBEDDED=y
uio-howto.tmpl: use unique output names
uio-howto.tmpl: use standard copyright/legal markings
sysfs: don't call notify_change
sysdev: fix debugging statements in registration code.
kobject: should use kobject_put() in kset-example
kobject: reorder kobject to save space on 64 bit builds
...
Diffstat (limited to 'fs')
-rw-r--r-- | fs/coda/psdev.c | 5 | ||||
-rw-r--r-- | fs/debugfs/inode.c | 114 | ||||
-rw-r--r-- | fs/partitions/check.c | 2 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 37 | ||||
-rw-r--r-- | fs/sysfs/file.c | 5 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 41 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 1 |
7 files changed, 173 insertions, 32 deletions
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index e3eb3556622b..40c36f7352a6 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
@@ -362,8 +362,9 @@ static int init_coda_psdev(void) | |||
362 | goto out_chrdev; | 362 | goto out_chrdev; |
363 | } | 363 | } |
364 | for (i = 0; i < MAX_CODADEVS; i++) | 364 | for (i = 0; i < MAX_CODADEVS; i++) |
365 | device_create(coda_psdev_class, NULL, | 365 | device_create_drvdata(coda_psdev_class, NULL, |
366 | MKDEV(CODA_PSDEV_MAJOR,i), "cfs%d", i); | 366 | MKDEV(CODA_PSDEV_MAJOR, i), |
367 | NULL, "cfs%d", i); | ||
367 | coda_sysctl_init(); | 368 | coda_sysctl_init(); |
368 | goto out; | 369 | goto out; |
369 | 370 | ||
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e9602d85c11d..08e28c9bb416 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -309,6 +309,31 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | |||
309 | } | 309 | } |
310 | EXPORT_SYMBOL_GPL(debugfs_create_symlink); | 310 | EXPORT_SYMBOL_GPL(debugfs_create_symlink); |
311 | 311 | ||
312 | static void __debugfs_remove(struct dentry *dentry, struct dentry *parent) | ||
313 | { | ||
314 | int ret = 0; | ||
315 | |||
316 | if (debugfs_positive(dentry)) { | ||
317 | if (dentry->d_inode) { | ||
318 | dget(dentry); | ||
319 | switch (dentry->d_inode->i_mode & S_IFMT) { | ||
320 | case S_IFDIR: | ||
321 | ret = simple_rmdir(parent->d_inode, dentry); | ||
322 | break; | ||
323 | case S_IFLNK: | ||
324 | kfree(dentry->d_inode->i_private); | ||
325 | /* fall through */ | ||
326 | default: | ||
327 | simple_unlink(parent->d_inode, dentry); | ||
328 | break; | ||
329 | } | ||
330 | if (!ret) | ||
331 | d_delete(dentry); | ||
332 | dput(dentry); | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | |||
312 | /** | 337 | /** |
313 | * debugfs_remove - removes a file or directory from the debugfs filesystem | 338 | * debugfs_remove - removes a file or directory from the debugfs filesystem |
314 | * @dentry: a pointer to a the dentry of the file or directory to be | 339 | * @dentry: a pointer to a the dentry of the file or directory to be |
@@ -325,7 +350,6 @@ EXPORT_SYMBOL_GPL(debugfs_create_symlink); | |||
325 | void debugfs_remove(struct dentry *dentry) | 350 | void debugfs_remove(struct dentry *dentry) |
326 | { | 351 | { |
327 | struct dentry *parent; | 352 | struct dentry *parent; |
328 | int ret = 0; | ||
329 | 353 | ||
330 | if (!dentry) | 354 | if (!dentry) |
331 | return; | 355 | return; |
@@ -335,29 +359,83 @@ void debugfs_remove(struct dentry *dentry) | |||
335 | return; | 359 | return; |
336 | 360 | ||
337 | mutex_lock(&parent->d_inode->i_mutex); | 361 | mutex_lock(&parent->d_inode->i_mutex); |
338 | if (debugfs_positive(dentry)) { | 362 | __debugfs_remove(dentry, parent); |
339 | if (dentry->d_inode) { | 363 | mutex_unlock(&parent->d_inode->i_mutex); |
340 | dget(dentry); | 364 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
341 | switch (dentry->d_inode->i_mode & S_IFMT) { | 365 | } |
342 | case S_IFDIR: | 366 | EXPORT_SYMBOL_GPL(debugfs_remove); |
343 | ret = simple_rmdir(parent->d_inode, dentry); | 367 | |
344 | break; | 368 | /** |
345 | case S_IFLNK: | 369 | * debugfs_remove_recursive - recursively removes a directory |
346 | kfree(dentry->d_inode->i_private); | 370 | * @dentry: a pointer to a the dentry of the directory to be removed. |
347 | /* fall through */ | 371 | * |
348 | default: | 372 | * This function recursively removes a directory tree in debugfs that |
349 | simple_unlink(parent->d_inode, dentry); | 373 | * was previously created with a call to another debugfs function |
374 | * (like debugfs_create_file() or variants thereof.) | ||
375 | * | ||
376 | * This function is required to be called in order for the file to be | ||
377 | * removed, no automatic cleanup of files will happen when a module is | ||
378 | * removed, you are responsible here. | ||
379 | */ | ||
380 | void debugfs_remove_recursive(struct dentry *dentry) | ||
381 | { | ||
382 | struct dentry *child; | ||
383 | struct dentry *parent; | ||
384 | |||
385 | if (!dentry) | ||
386 | return; | ||
387 | |||
388 | parent = dentry->d_parent; | ||
389 | if (!parent || !parent->d_inode) | ||
390 | return; | ||
391 | |||
392 | parent = dentry; | ||
393 | mutex_lock(&parent->d_inode->i_mutex); | ||
394 | |||
395 | while (1) { | ||
396 | /* | ||
397 | * When all dentries under "parent" has been removed, | ||
398 | * walk up the tree until we reach our starting point. | ||
399 | */ | ||
400 | if (list_empty(&parent->d_subdirs)) { | ||
401 | mutex_unlock(&parent->d_inode->i_mutex); | ||
402 | if (parent == dentry) | ||
350 | break; | 403 | break; |
351 | } | 404 | parent = parent->d_parent; |
352 | if (!ret) | 405 | mutex_lock(&parent->d_inode->i_mutex); |
353 | d_delete(dentry); | 406 | } |
354 | dput(dentry); | 407 | child = list_entry(parent->d_subdirs.next, struct dentry, |
408 | d_u.d_child); | ||
409 | |||
410 | /* | ||
411 | * If "child" isn't empty, walk down the tree and | ||
412 | * remove all its descendants first. | ||
413 | */ | ||
414 | if (!list_empty(&child->d_subdirs)) { | ||
415 | mutex_unlock(&parent->d_inode->i_mutex); | ||
416 | parent = child; | ||
417 | mutex_lock(&parent->d_inode->i_mutex); | ||
418 | continue; | ||
355 | } | 419 | } |
420 | __debugfs_remove(child, parent); | ||
421 | if (parent->d_subdirs.next == &child->d_u.d_child) { | ||
422 | /* | ||
423 | * Avoid infinite loop if we fail to remove | ||
424 | * one dentry. | ||
425 | */ | ||
426 | mutex_unlock(&parent->d_inode->i_mutex); | ||
427 | break; | ||
428 | } | ||
429 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
356 | } | 430 | } |
431 | |||
432 | parent = dentry->d_parent; | ||
433 | mutex_lock(&parent->d_inode->i_mutex); | ||
434 | __debugfs_remove(dentry, parent); | ||
357 | mutex_unlock(&parent->d_inode->i_mutex); | 435 | mutex_unlock(&parent->d_inode->i_mutex); |
358 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | 436 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
359 | } | 437 | } |
360 | EXPORT_SYMBOL_GPL(debugfs_remove); | 438 | EXPORT_SYMBOL_GPL(debugfs_remove_recursive); |
361 | 439 | ||
362 | /** | 440 | /** |
363 | * debugfs_rename - rename a file/directory in the debugfs filesystem | 441 | * debugfs_rename - rename a file/directory in the debugfs filesystem |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 6149e4b58c88..efef715135d3 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -401,7 +401,7 @@ void register_disk(struct gendisk *disk) | |||
401 | disk->dev.parent = disk->driverfs_dev; | 401 | disk->dev.parent = disk->driverfs_dev; |
402 | disk->dev.devt = MKDEV(disk->major, disk->first_minor); | 402 | disk->dev.devt = MKDEV(disk->major, disk->first_minor); |
403 | 403 | ||
404 | strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN); | 404 | strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE); |
405 | /* ewww... some of these buggers have / in the name... */ | 405 | /* ewww... some of these buggers have / in the name... */ |
406 | s = strchr(disk->dev.bus_id, '/'); | 406 | s = strchr(disk->dev.bus_id, '/'); |
407 | if (s) | 407 | if (s) |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 8c0e4b92574f..c1a7efb310bf 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -398,7 +398,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
398 | } | 398 | } |
399 | 399 | ||
400 | /** | 400 | /** |
401 | * sysfs_add_one - add sysfs_dirent to parent | 401 | * __sysfs_add_one - add sysfs_dirent to parent without warning |
402 | * @acxt: addrm context to use | 402 | * @acxt: addrm context to use |
403 | * @sd: sysfs_dirent to be added | 403 | * @sd: sysfs_dirent to be added |
404 | * | 404 | * |
@@ -417,7 +417,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
417 | * 0 on success, -EEXIST if entry with the given name already | 417 | * 0 on success, -EEXIST if entry with the given name already |
418 | * exists. | 418 | * exists. |
419 | */ | 419 | */ |
420 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | 420 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) |
421 | { | 421 | { |
422 | if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) | 422 | if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) |
423 | return -EEXIST; | 423 | return -EEXIST; |
@@ -435,6 +435,39 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
435 | } | 435 | } |
436 | 436 | ||
437 | /** | 437 | /** |
438 | * sysfs_add_one - add sysfs_dirent to parent | ||
439 | * @acxt: addrm context to use | ||
440 | * @sd: sysfs_dirent to be added | ||
441 | * | ||
442 | * Get @acxt->parent_sd and set sd->s_parent to it and increment | ||
443 | * nlink of parent inode if @sd is a directory and link into the | ||
444 | * children list of the parent. | ||
445 | * | ||
446 | * This function should be called between calls to | ||
447 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | ||
448 | * passed the same @acxt as passed to sysfs_addrm_start(). | ||
449 | * | ||
450 | * LOCKING: | ||
451 | * Determined by sysfs_addrm_start(). | ||
452 | * | ||
453 | * RETURNS: | ||
454 | * 0 on success, -EEXIST if entry with the given name already | ||
455 | * exists. | ||
456 | */ | ||
457 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | ||
458 | { | ||
459 | int ret; | ||
460 | |||
461 | ret = __sysfs_add_one(acxt, sd); | ||
462 | if (ret == -EEXIST) { | ||
463 | printk(KERN_WARNING "sysfs: duplicate filename '%s' " | ||
464 | "can not be created\n", sd->s_name); | ||
465 | WARN_ON(1); | ||
466 | } | ||
467 | return ret; | ||
468 | } | ||
469 | |||
470 | /** | ||
438 | * sysfs_remove_one - remove sysfs_dirent from parent | 471 | * sysfs_remove_one - remove sysfs_dirent from parent |
439 | * @acxt: addrm context to use | 472 | * @acxt: addrm context to use |
440 | * @sd: sysfs_dirent to be removed | 473 | * @sd: sysfs_dirent to be removed |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e7735f643cd1..3f07893ff896 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kobject.h> | 14 | #include <linux/kobject.h> |
15 | #include <linux/kallsyms.h> | 15 | #include <linux/kallsyms.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/fsnotify.h> | ||
17 | #include <linux/namei.h> | 18 | #include <linux/namei.h> |
18 | #include <linux/poll.h> | 19 | #include <linux/poll.h> |
19 | #include <linux/list.h> | 20 | #include <linux/list.h> |
@@ -585,9 +586,11 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | |||
585 | 586 | ||
586 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 587 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
587 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 588 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
588 | rc = notify_change(victim, &newattrs); | 589 | newattrs.ia_ctime = current_fs_time(inode->i_sb); |
590 | rc = sysfs_setattr(victim, &newattrs); | ||
589 | 591 | ||
590 | if (rc == 0) { | 592 | if (rc == 0) { |
593 | fsnotify_change(victim, newattrs.ia_valid); | ||
591 | mutex_lock(&sysfs_mutex); | 594 | mutex_lock(&sysfs_mutex); |
592 | victim_sd->s_mode = newattrs.ia_mode; | 595 | victim_sd->s_mode = newattrs.ia_mode; |
593 | mutex_unlock(&sysfs_mutex); | 596 | mutex_unlock(&sysfs_mutex); |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 817f5966edca..a3ba217fbe74 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -19,13 +19,8 @@ | |||
19 | 19 | ||
20 | #include "sysfs.h" | 20 | #include "sysfs.h" |
21 | 21 | ||
22 | /** | 22 | static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, |
23 | * sysfs_create_link - create symlink between two objects. | 23 | const char *name, int warn) |
24 | * @kobj: object whose directory we're creating the link in. | ||
25 | * @target: object we're pointing to. | ||
26 | * @name: name of the symlink. | ||
27 | */ | ||
28 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) | ||
29 | { | 24 | { |
30 | struct sysfs_dirent *parent_sd = NULL; | 25 | struct sysfs_dirent *parent_sd = NULL; |
31 | struct sysfs_dirent *target_sd = NULL; | 26 | struct sysfs_dirent *target_sd = NULL; |
@@ -65,7 +60,10 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char | |||
65 | target_sd = NULL; /* reference is now owned by the symlink */ | 60 | target_sd = NULL; /* reference is now owned by the symlink */ |
66 | 61 | ||
67 | sysfs_addrm_start(&acxt, parent_sd); | 62 | sysfs_addrm_start(&acxt, parent_sd); |
68 | error = sysfs_add_one(&acxt, sd); | 63 | if (warn) |
64 | error = sysfs_add_one(&acxt, sd); | ||
65 | else | ||
66 | error = __sysfs_add_one(&acxt, sd); | ||
69 | sysfs_addrm_finish(&acxt); | 67 | sysfs_addrm_finish(&acxt); |
70 | 68 | ||
71 | if (error) | 69 | if (error) |
@@ -80,6 +78,33 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char | |||
80 | } | 78 | } |
81 | 79 | ||
82 | /** | 80 | /** |
81 | * sysfs_create_link - create symlink between two objects. | ||
82 | * @kobj: object whose directory we're creating the link in. | ||
83 | * @target: object we're pointing to. | ||
84 | * @name: name of the symlink. | ||
85 | */ | ||
86 | int sysfs_create_link(struct kobject *kobj, struct kobject *target, | ||
87 | const char *name) | ||
88 | { | ||
89 | return sysfs_do_create_link(kobj, target, name, 1); | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * sysfs_create_link_nowarn - create symlink between two objects. | ||
94 | * @kobj: object whose directory we're creating the link in. | ||
95 | * @target: object we're pointing to. | ||
96 | * @name: name of the symlink. | ||
97 | * | ||
98 | * This function does the same as sysf_create_link(), but it | ||
99 | * doesn't warn if the link already exists. | ||
100 | */ | ||
101 | int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, | ||
102 | const char *name) | ||
103 | { | ||
104 | return sysfs_do_create_link(kobj, target, name, 0); | ||
105 | } | ||
106 | |||
107 | /** | ||
83 | * sysfs_remove_link - remove symlink in object's directory. | 108 | * sysfs_remove_link - remove symlink in object's directory. |
84 | * @kobj: object we're acting for. | 109 | * @kobj: object we're acting for. |
85 | * @name: name of the symlink to remove. | 110 | * @name: name of the symlink to remove. |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index ce4e15f8aaeb..a5db496f71c7 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -107,6 +107,7 @@ struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | |||
107 | void sysfs_put_active_two(struct sysfs_dirent *sd); | 107 | void sysfs_put_active_two(struct sysfs_dirent *sd); |
108 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 108 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
109 | struct sysfs_dirent *parent_sd); | 109 | struct sysfs_dirent *parent_sd); |
110 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | ||
110 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 111 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |
111 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 112 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |
112 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | 113 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); |