diff options
author | Jan Harkes <jaharkes@cs.cmu.edu> | 2007-07-19 04:48:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:48 -0400 |
commit | 87065519633af79e0577e32a58dcd9cf3c45a8a0 (patch) | |
tree | 5c53c073d91523081271b1a83a741e32edf28cf7 /fs/coda/psdev.c | |
parent | ed31a7dd636b296746c131b7386023aa1ef84309 (diff) |
coda: cleanup /dev/cfs open and close handling
- Make sure device index is not a negative number.
- Unlink queued requests when the device is closed to avoid passing them
to the next opener.
Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/coda/psdev.c')
-rw-r--r-- | fs/coda/psdev.c | 61 |
1 files changed, 30 insertions, 31 deletions
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 09382d47a4e1..6818c20372ca 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
@@ -272,56 +272,51 @@ out: | |||
272 | 272 | ||
273 | static int coda_psdev_open(struct inode * inode, struct file * file) | 273 | static int coda_psdev_open(struct inode * inode, struct file * file) |
274 | { | 274 | { |
275 | struct venus_comm *vcp; | 275 | struct venus_comm *vcp; |
276 | int idx; | 276 | int idx, err; |
277 | 277 | ||
278 | lock_kernel(); | ||
279 | idx = iminor(inode); | 278 | idx = iminor(inode); |
280 | if(idx >= MAX_CODADEVS) { | 279 | if (idx < 0 || idx >= MAX_CODADEVS) |
281 | unlock_kernel(); | ||
282 | return -ENODEV; | 280 | return -ENODEV; |
283 | } | ||
284 | 281 | ||
282 | lock_kernel(); | ||
283 | |||
284 | err = -EBUSY; | ||
285 | vcp = &coda_comms[idx]; | 285 | vcp = &coda_comms[idx]; |
286 | if(vcp->vc_inuse) { | 286 | if (!vcp->vc_inuse) { |
287 | unlock_kernel(); | 287 | vcp->vc_inuse++; |
288 | return -EBUSY; | 288 | |
289 | } | ||
290 | |||
291 | if (!vcp->vc_inuse++) { | ||
292 | INIT_LIST_HEAD(&vcp->vc_pending); | 289 | INIT_LIST_HEAD(&vcp->vc_pending); |
293 | INIT_LIST_HEAD(&vcp->vc_processing); | 290 | INIT_LIST_HEAD(&vcp->vc_processing); |
294 | init_waitqueue_head(&vcp->vc_waitq); | 291 | init_waitqueue_head(&vcp->vc_waitq); |
295 | vcp->vc_sb = NULL; | 292 | vcp->vc_sb = NULL; |
296 | vcp->vc_seq = 0; | 293 | vcp->vc_seq = 0; |
294 | |||
295 | file->private_data = vcp; | ||
296 | err = 0; | ||
297 | } | 297 | } |
298 | |||
299 | file->private_data = vcp; | ||
300 | 298 | ||
301 | unlock_kernel(); | 299 | unlock_kernel(); |
302 | return 0; | 300 | return err; |
303 | } | 301 | } |
304 | 302 | ||
305 | 303 | ||
306 | static int coda_psdev_release(struct inode * inode, struct file * file) | 304 | static int coda_psdev_release(struct inode * inode, struct file * file) |
307 | { | 305 | { |
308 | struct venus_comm *vcp = (struct venus_comm *) file->private_data; | 306 | struct venus_comm *vcp = (struct venus_comm *) file->private_data; |
309 | struct upc_req *req, *tmp; | 307 | struct upc_req *req, *tmp; |
310 | 308 | ||
311 | lock_kernel(); | 309 | if (!vcp || !vcp->vc_inuse ) { |
312 | if ( !vcp->vc_inuse ) { | ||
313 | unlock_kernel(); | ||
314 | printk("psdev_release: Not open.\n"); | 310 | printk("psdev_release: Not open.\n"); |
315 | return -1; | 311 | return -1; |
316 | } | 312 | } |
317 | 313 | ||
318 | if (--vcp->vc_inuse) { | 314 | lock_kernel(); |
319 | unlock_kernel(); | 315 | |
320 | return 0; | 316 | /* Wakeup clients so they can return. */ |
321 | } | ||
322 | |||
323 | /* Wakeup clients so they can return. */ | ||
324 | list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) { | 317 | list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) { |
318 | list_del(&req->uc_chain); | ||
319 | |||
325 | /* Async requests need to be freed here */ | 320 | /* Async requests need to be freed here */ |
326 | if (req->uc_flags & REQ_ASYNC) { | 321 | if (req->uc_flags & REQ_ASYNC) { |
327 | CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr)); | 322 | CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr)); |
@@ -330,13 +325,17 @@ static int coda_psdev_release(struct inode * inode, struct file * file) | |||
330 | } | 325 | } |
331 | req->uc_flags |= REQ_ABORT; | 326 | req->uc_flags |= REQ_ABORT; |
332 | wake_up(&req->uc_sleep); | 327 | wake_up(&req->uc_sleep); |
333 | } | 328 | } |
334 | 329 | ||
335 | list_for_each_entry(req, &vcp->vc_processing, uc_chain) { | 330 | list_for_each_entry_safe(req, tmp, &vcp->vc_processing, uc_chain) { |
331 | list_del(&req->uc_chain); | ||
332 | |||
336 | req->uc_flags |= REQ_ABORT; | 333 | req->uc_flags |= REQ_ABORT; |
337 | wake_up(&req->uc_sleep); | 334 | wake_up(&req->uc_sleep); |
338 | } | 335 | } |
339 | 336 | ||
337 | file->private_data = NULL; | ||
338 | vcp->vc_inuse--; | ||
340 | unlock_kernel(); | 339 | unlock_kernel(); |
341 | return 0; | 340 | return 0; |
342 | } | 341 | } |