diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2010-02-11 18:18:38 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-07 20:04:51 -0500 |
commit | e72ceb8ccac5f770b3e696e09bb673dca7024b20 (patch) | |
tree | 9868803df687838c3c5f6f2265ceb7532b93a5f4 /fs | |
parent | 3c31f07ad0dab02fe17195d32a965d57fd947707 (diff) |
sysfs: Remove sysfs_get/put_active_two
It turns out that holding an active reference on a directory is
pointless. The purpose of the active references are to allows us to
block when removing sysfs entries that have custom methods so we don't
remove modules while running modular code and to keep those custom
methods from accessing data structures after the files have been
removed. Further sysfs_remove_dir remove all elements in the
directory before removing the directory itself, so there is no chance
we will remove a directory with active children.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/sysfs/bin.c | 50 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 43 | ||||
-rw-r--r-- | fs/sysfs/file.c | 18 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 4 |
4 files changed, 38 insertions, 77 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index a0a500af24a1..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 | ||
195 | static void bin_vma_close(struct vm_area_struct *vma) | 195 | static 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 | ||
212 | static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 212 | static 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; |
386 | out_put: | 386 | out_put: |
387 | sysfs_put_active_two(attr_sd); | 387 | sysfs_put_active(attr_sd); |
388 | out_unlock: | 388 | out_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 | } |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5c4703d751b5..1bdc42f4fd93 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -93,7 +93,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) | |||
93 | * RETURNS: | 93 | * RETURNS: |
94 | * Pointer to @sd on success, NULL on failure. | 94 | * Pointer to @sd on success, NULL on failure. |
95 | */ | 95 | */ |
96 | static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | 96 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) |
97 | { | 97 | { |
98 | if (unlikely(!sd)) | 98 | if (unlikely(!sd)) |
99 | return NULL; | 99 | return NULL; |
@@ -124,7 +124,7 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | |||
124 | * 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 |
125 | * is NULL. | 125 | * is NULL. |
126 | */ | 126 | */ |
127 | static void sysfs_put_active(struct sysfs_dirent *sd) | 127 | void sysfs_put_active(struct sysfs_dirent *sd) |
128 | { | 128 | { |
129 | struct completion *cmpl; | 129 | struct completion *cmpl; |
130 | int v; | 130 | int v; |
@@ -145,45 +145,6 @@ static void sysfs_put_active(struct sysfs_dirent *sd) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | /** |
148 | * sysfs_get_active_two - get active references to sysfs_dirent and parent | ||
149 | * @sd: sysfs_dirent of interest | ||
150 | * | ||
151 | * Get active reference to @sd and its parent. Parent's active | ||
152 | * reference is grabbed first. This function is noop if @sd is | ||
153 | * NULL. | ||
154 | * | ||
155 | * RETURNS: | ||
156 | * Pointer to @sd on success, NULL on failure. | ||
157 | */ | ||
158 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd) | ||
159 | { | ||
160 | if (sd) { | ||
161 | if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent))) | ||
162 | return NULL; | ||
163 | if (unlikely(!sysfs_get_active(sd))) { | ||
164 | sysfs_put_active(sd->s_parent); | ||
165 | return NULL; | ||
166 | } | ||
167 | } | ||
168 | return sd; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * sysfs_put_active_two - put active references to sysfs_dirent and parent | ||
173 | * @sd: sysfs_dirent of interest | ||
174 | * | ||
175 | * Put active references to @sd and its parent. This function is | ||
176 | * noop if @sd is NULL. | ||
177 | */ | ||
178 | void sysfs_put_active_two(struct sysfs_dirent *sd) | ||
179 | { | ||
180 | if (sd) { | ||
181 | sysfs_put_active(sd); | ||
182 | sysfs_put_active(sd->s_parent); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * sysfs_deactivate - deactivate sysfs_dirent | 148 | * sysfs_deactivate - deactivate sysfs_dirent |
188 | * @sd: sysfs_dirent to deactivate | 149 | * @sd: sysfs_dirent to deactivate |
189 | * | 150 | * |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index ced2299f1c9a..40961366e929 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -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 |
@@ -203,12 +203,12 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t | |||
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 | } |
@@ -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; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index cdd9377a6e06..bb7723c4f5a5 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -124,8 +124,8 @@ extern const struct file_operations sysfs_dir_operations; | |||
124 | extern const struct inode_operations sysfs_dir_inode_operations; | 124 | extern const struct inode_operations sysfs_dir_inode_operations; |
125 | 125 | ||
126 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); | 126 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); |
127 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | 127 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); |
128 | void sysfs_put_active_two(struct sysfs_dirent *sd); | 128 | void sysfs_put_active(struct sysfs_dirent *sd); |
129 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | 129 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
130 | struct sysfs_dirent *parent_sd); | 130 | struct sysfs_dirent *parent_sd); |
131 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | 131 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); |