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>
This commit is contained in:
parent
ed31a7dd63
commit
8706551963
2 changed files with 34 additions and 40 deletions
|
@ -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)
|
||||
{
|
||||
struct venus_comm *vcp;
|
||||
int idx;
|
||||
struct venus_comm *vcp;
|
||||
int idx, err;
|
||||
|
||||
idx = iminor(inode);
|
||||
if (idx < 0 || idx >= MAX_CODADEVS)
|
||||
return -ENODEV;
|
||||
|
||||
lock_kernel();
|
||||
idx = iminor(inode);
|
||||
if(idx >= MAX_CODADEVS) {
|
||||
unlock_kernel();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
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) {
|
||||
req->uc_flags |= REQ_ABORT;
|
||||
wake_up(&req->uc_sleep);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
file->private_data = NULL;
|
||||
vcp->vc_inuse--;
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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... */
|
||||
|
|
Loading…
Reference in a new issue