diff options
-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 09382d4..6818c20 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -272,56 +272,51 @@ out: static int coda_psdev_open(struct inode * inode, struct file * file) { - struct venus_comm *vcp; - int idx; + struct venus_comm *vcp; + int idx, err; - lock_kernel(); idx = iminor(inode); - if(idx >= MAX_CODADEVS) { - unlock_kernel(); + if (idx < 0 || idx >= MAX_CODADEVS) return -ENODEV; - } + lock_kernel(); + + err = -EBUSY; vcp = &coda_comms[idx]; - if(vcp->vc_inuse) { - unlock_kernel(); - return -EBUSY; - } - - if (!vcp->vc_inuse++) { + if (!vcp->vc_inuse) { + vcp->vc_inuse++; + INIT_LIST_HEAD(&vcp->vc_pending); INIT_LIST_HEAD(&vcp->vc_processing); init_waitqueue_head(&vcp->vc_waitq); vcp->vc_sb = NULL; vcp->vc_seq = 0; + + file->private_data = vcp; + err = 0; } - - file->private_data = vcp; unlock_kernel(); - return 0; + return err; } static int coda_psdev_release(struct inode * inode, struct file * file) { - struct venus_comm *vcp = (struct venus_comm *) file->private_data; - struct upc_req *req, *tmp; + struct venus_comm *vcp = (struct venus_comm *) file->private_data; + struct upc_req *req, *tmp; - lock_kernel(); - if ( !vcp->vc_inuse ) { - unlock_kernel(); + if (!vcp || !vcp->vc_inuse ) { printk("psdev_release: Not open.\n"); return -1; } - if (--vcp->vc_inuse) { - unlock_kernel(); - return 0; - } - - /* Wakeup clients so they can return. */ + lock_kernel(); + + /* Wakeup clients so they can return. */ list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) { + list_del(&req->uc_chain); + /* Async requests need to be freed here */ if (req->uc_flags & REQ_ASYNC) { 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) } req->uc_flags |= REQ_ABORT; wake_up(&req->uc_sleep); - } - - list_for_each_entry(req, &vcp->vc_processing, uc_chain) { + } + + list_for_each_entry_safe(req, tmp, &vcp->vc_processing, uc_chain) { + list_del(&req->uc_chain); + req->uc_flags |= REQ_ABORT; - wake_up(&req->uc_sleep); - } + wake_up(&req->uc_sleep); + } + file->private_data = NULL; + vcp->vc_inuse--; unlock_kernel(); return 0; } diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 1651b91..a44ca41 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -641,8 +641,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs) * */ -static inline void coda_waitfor_upcall(struct upc_req *vmp, - struct venus_comm *vcommp) +static inline void coda_waitfor_upcall(struct upc_req *vmp) { DECLARE_WAITQUEUE(wait, current); @@ -655,10 +654,6 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp, else set_current_state(TASK_UNINTERRUPTIBLE); - /* venus died */ - if ( !vcommp->vc_inuse ) - break; - /* got a reply */ if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) break; @@ -738,7 +733,7 @@ static int coda_upcall(struct coda_sb_info *sbi, * ENODEV. */ /* Go to sleep. Wake up on signals only after the timeout. */ - coda_waitfor_upcall(req, vcommp); + coda_waitfor_upcall(req); if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ /* Op went through, interrupt or not... */ |