Commit 87065519 authored by Jan Harkes's avatar Jan Harkes Committed by Linus Torvalds

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: default avatarJan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ed31a7dd
...@@ -272,56 +272,51 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf, ...@@ -272,56 +272,51 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
static int coda_psdev_open(struct inode * inode, struct file * file) static int coda_psdev_open(struct inode * inode, struct file * file)
{ {
struct venus_comm *vcp; struct venus_comm *vcp;
int idx; int idx, err;
lock_kernel();
idx = iminor(inode); idx = iminor(inode);
if(idx >= MAX_CODADEVS) { if (idx < 0 || idx >= MAX_CODADEVS)
unlock_kernel();
return -ENODEV; return -ENODEV;
}
lock_kernel();
err = -EBUSY;
vcp = &coda_comms[idx]; vcp = &coda_comms[idx];
if(vcp->vc_inuse) { if (!vcp->vc_inuse) {
unlock_kernel(); vcp->vc_inuse++;
return -EBUSY;
}
if (!vcp->vc_inuse++) {
INIT_LIST_HEAD(&vcp->vc_pending); INIT_LIST_HEAD(&vcp->vc_pending);
INIT_LIST_HEAD(&vcp->vc_processing); INIT_LIST_HEAD(&vcp->vc_processing);
init_waitqueue_head(&vcp->vc_waitq); init_waitqueue_head(&vcp->vc_waitq);
vcp->vc_sb = NULL; vcp->vc_sb = NULL;
vcp->vc_seq = 0; vcp->vc_seq = 0;
file->private_data = vcp;
err = 0;
} }
file->private_data = vcp;
unlock_kernel(); unlock_kernel();
return 0; return err;
} }
static int coda_psdev_release(struct inode * inode, struct file * file) static int coda_psdev_release(struct inode * inode, struct file * file)
{ {
struct venus_comm *vcp = (struct venus_comm *) file->private_data; struct venus_comm *vcp = (struct venus_comm *) file->private_data;
struct upc_req *req, *tmp; struct upc_req *req, *tmp;
lock_kernel(); if (!vcp || !vcp->vc_inuse ) {
if ( !vcp->vc_inuse ) {
unlock_kernel();
printk("psdev_release: Not open.\n"); printk("psdev_release: Not open.\n");
return -1; return -1;
} }
if (--vcp->vc_inuse) { lock_kernel();
unlock_kernel();
return 0; /* Wakeup clients so they can return. */
}
/* Wakeup clients so they can return. */
list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) { list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
list_del(&req->uc_chain);
/* Async requests need to be freed here */ /* Async requests need to be freed here */
if (req->uc_flags & REQ_ASYNC) { if (req->uc_flags & REQ_ASYNC) {
CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr)); 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,13 +325,17 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
} }
req->uc_flags |= REQ_ABORT; req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep); 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; req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep); wake_up(&req->uc_sleep);
} }
file->private_data = NULL;
vcp->vc_inuse--;
unlock_kernel(); unlock_kernel();
return 0; return 0;
} }
......
...@@ -641,8 +641,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs) ...@@ -641,8 +641,7 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
* *
*/ */
static inline void coda_waitfor_upcall(struct upc_req *vmp, static inline void coda_waitfor_upcall(struct upc_req *vmp)
struct venus_comm *vcommp)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
...@@ -655,10 +654,6 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp, ...@@ -655,10 +654,6 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp,
else else
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
/* venus died */
if ( !vcommp->vc_inuse )
break;
/* got a reply */ /* got a reply */
if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
break; break;
...@@ -738,7 +733,7 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -738,7 +733,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
* ENODEV. */ * ENODEV. */
/* Go to sleep. Wake up on signals only after the timeout. */ /* 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 */ if (vcommp->vc_inuse) { /* i.e. Venus is still alive */
/* Op went through, interrupt or not... */ /* Op went through, interrupt or not... */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment