diff options
author | Neil Brown <neilb@suse.de> | 2008-07-15 18:58:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-16 12:24:47 -0400 |
commit | f1282c844e86db5a041afa41335b5f9eea6cec0c (patch) | |
tree | 3736285f2f7ce145fb06538d616a9c1165ffc125 /include | |
parent | ec748fa9ed3fec44aeebbf86ae050b0cc7a978d9 (diff) |
sysfs: Support sysfs_notify from atomic context with new sysfs_notify_dirent
Support sysfs_notify from atomic context with new sysfs_notify_dirent
sysfs_notify currently takes sysfs_mutex.
This means that it cannot be called in atomic context.
sysfs_mutex is sometimes held over a malloc (sysfs_rename_dir)
so it can block on low memory.
In md I want to be able to notify on a sysfs attribute from
atomic context, and I don't want to block on low memory because I
could be in the writeout path for freeing memory.
So:
- export the "sysfs_dirent" structure along with sysfs_get, sysfs_put
and sysfs_get_dirent so I can get the sysfs_dirent that I want to
notify on and hold it in an md structure.
- split sysfs_notify_dirent out of sysfs_notify so the sysfs_dirent
can be notified on with no blocking (just a spinlock).
Signed-off-by: Neil Brown <neilb@suse.de>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/sysfs.h | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 8ec406afb3eb..d8e0230f1e68 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -78,6 +78,8 @@ struct sysfs_ops { | |||
78 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); | 78 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct sysfs_dirent; | ||
82 | |||
81 | #ifdef CONFIG_SYSFS | 83 | #ifdef CONFIG_SYSFS |
82 | 84 | ||
83 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), | 85 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), |
@@ -118,10 +120,13 @@ void sysfs_remove_file_from_group(struct kobject *kobj, | |||
118 | const struct attribute *attr, const char *group); | 120 | const struct attribute *attr, const char *group); |
119 | 121 | ||
120 | void sysfs_notify(struct kobject *kobj, char *dir, char *attr); | 122 | void sysfs_notify(struct kobject *kobj, char *dir, char *attr); |
121 | 123 | void sysfs_notify_dirent(struct sysfs_dirent *sd); | |
124 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | ||
125 | const unsigned char *name); | ||
126 | struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); | ||
127 | void sysfs_put(struct sysfs_dirent *sd); | ||
122 | void sysfs_printk_last_file(void); | 128 | void sysfs_printk_last_file(void); |
123 | 129 | int __must_check sysfs_init(void); | |
124 | extern int __must_check sysfs_init(void); | ||
125 | 130 | ||
126 | #else /* CONFIG_SYSFS */ | 131 | #else /* CONFIG_SYSFS */ |
127 | 132 | ||
@@ -227,6 +232,22 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj, | |||
227 | static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr) | 232 | static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr) |
228 | { | 233 | { |
229 | } | 234 | } |
235 | static inline void sysfs_notify_dirent(struct sysfs_dirent *sd) | ||
236 | { | ||
237 | } | ||
238 | static inline | ||
239 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | ||
240 | const unsigned char *name) | ||
241 | { | ||
242 | return NULL; | ||
243 | } | ||
244 | static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd) | ||
245 | { | ||
246 | return NULL; | ||
247 | } | ||
248 | static inline void sysfs_put(struct sysfs_dirent *sd) | ||
249 | { | ||
250 | } | ||
230 | 251 | ||
231 | static inline int __must_check sysfs_init(void) | 252 | static inline int __must_check sysfs_init(void) |
232 | { | 253 | { |