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 | |
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>
-rw-r--r-- | fs/coda/psdev.c | 61 | ||||
-rw-r--r-- | fs/coda/upcall.c | 9 |
2 files changed, 32 insertions, 38 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 | } |
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 1651b918219a..a44ca4155fd5 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
@@ -641,8 +641,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs) | |||
641 | * | 641 | * |
642 | */ | 642 | */ |
643 | 643 | ||
644 | static inline void coda_waitfor_upcall(struct upc_req *vmp, | 644 | static inline void coda_waitfor_upcall(struct upc_req *vmp) |
645 | struct venus_comm *vcommp) | ||
646 | { | 645 | { |
647 | DECLARE_WAITQUEUE(wait, current); | 646 | DECLARE_WAITQUEUE(wait, current); |
648 | 647 | ||
@@ -655,10 +654,6 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp, | |||
655 | else | 654 | else |
656 | set_current_state(TASK_UNINTERRUPTIBLE); | 655 | set_current_state(TASK_UNINTERRUPTIBLE); |
657 | 656 | ||
658 | /* venus died */ | ||
659 | if ( !vcommp->vc_inuse ) | ||
660 | break; | ||
661 | |||
662 | /* got a reply */ | 657 | /* got a reply */ |
663 | if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) | 658 | if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) |
664 | break; | 659 | break; |
@@ -738,7 +733,7 @@ static int coda_upcall(struct coda_sb_info *sbi, | |||
738 | * ENODEV. */ | 733 | * ENODEV. */ |
739 | 734 | ||
740 | /* Go to sleep. Wake up on signals only after the timeout. */ | 735 | /* Go to sleep. Wake up on signals only after the timeout. */ |
741 | coda_waitfor_upcall(req, vcommp); | 736 | coda_waitfor_upcall(req); |
742 | 737 | ||
743 | if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ | 738 | if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ |
744 | /* Op went through, interrupt or not... */ | 739 | /* Op went through, interrupt or not... */ |