aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coda
diff options
context:
space:
mode:
authorJan Harkes <jaharkes@cs.cmu.edu>2007-07-19 04:48:45 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:48 -0400
commit87065519633af79e0577e32a58dcd9cf3c45a8a0 (patch)
tree5c53c073d91523081271b1a83a741e32edf28cf7 /fs/coda
parented31a7dd636b296746c131b7386023aa1ef84309 (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')
-rw-r--r--fs/coda/psdev.c61
-rw-r--r--fs/coda/upcall.c9
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
273static int coda_psdev_open(struct inode * inode, struct file * file) 273static 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
306static int coda_psdev_release(struct inode * inode, struct file * file) 304static 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
644static inline void coda_waitfor_upcall(struct upc_req *vmp, 644static 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... */