summaryrefslogtreecommitdiffstats
path: root/fs/coda/psdev.c
diff options
context:
space:
mode:
authorJan Harkes <jaharkes@cs.cmu.edu>2007-07-19 01:48:45 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 10:04:48 -0700
commit87065519633af79e0577e32a58dcd9cf3c45a8a0 (patch)
tree5c53c073d91523081271b1a83a741e32edf28cf7 /fs/coda/psdev.c
parented31a7dd636b296746c131b7386023aa1ef84309 (diff)
downloadlinux-87065519633af79e0577e32a58dcd9cf3c45a8a0.tar.bz2
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/psdev.c')
-rw-r--r--fs/coda/psdev.c61
1 files changed, 30 insertions, 31 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:
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;
}