Commit 87065519633af79e0577e32a58dcd9cf3c45a8a0
Committed by
Linus Torvalds
1 parent
ed31a7dd63
Exists in
master
and in
7 other branches
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>
Showing 2 changed files with 32 additions and 38 deletions Side-by-side Diff
fs/coda/psdev.c
... | ... | @@ -272,56 +272,51 @@ |
272 | 272 | |
273 | 273 | static int coda_psdev_open(struct inode * inode, struct file * file) |
274 | 274 | { |
275 | - struct venus_comm *vcp; | |
276 | - int idx; | |
275 | + struct venus_comm *vcp; | |
276 | + int idx, err; | |
277 | 277 | |
278 | - lock_kernel(); | |
279 | 278 | idx = iminor(inode); |
280 | - if(idx >= MAX_CODADEVS) { | |
281 | - unlock_kernel(); | |
279 | + if (idx < 0 || idx >= MAX_CODADEVS) | |
282 | 280 | return -ENODEV; |
283 | - } | |
284 | 281 | |
282 | + lock_kernel(); | |
283 | + | |
284 | + err = -EBUSY; | |
285 | 285 | vcp = &coda_comms[idx]; |
286 | - if(vcp->vc_inuse) { | |
287 | - unlock_kernel(); | |
288 | - return -EBUSY; | |
289 | - } | |
290 | - | |
291 | - if (!vcp->vc_inuse++) { | |
286 | + if (!vcp->vc_inuse) { | |
287 | + vcp->vc_inuse++; | |
288 | + | |
292 | 289 | INIT_LIST_HEAD(&vcp->vc_pending); |
293 | 290 | INIT_LIST_HEAD(&vcp->vc_processing); |
294 | 291 | init_waitqueue_head(&vcp->vc_waitq); |
295 | 292 | vcp->vc_sb = NULL; |
296 | 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 | 299 | unlock_kernel(); |
302 | - return 0; | |
300 | + return err; | |
303 | 301 | } |
304 | 302 | |
305 | 303 | |
306 | 304 | static int coda_psdev_release(struct inode * inode, struct file * file) |
307 | 305 | { |
308 | - struct venus_comm *vcp = (struct venus_comm *) file->private_data; | |
309 | - struct upc_req *req, *tmp; | |
306 | + struct venus_comm *vcp = (struct venus_comm *) file->private_data; | |
307 | + struct upc_req *req, *tmp; | |
310 | 308 | |
311 | - lock_kernel(); | |
312 | - if ( !vcp->vc_inuse ) { | |
313 | - unlock_kernel(); | |
309 | + if (!vcp || !vcp->vc_inuse ) { | |
314 | 310 | printk("psdev_release: Not open.\n"); |
315 | 311 | return -1; |
316 | 312 | } |
317 | 313 | |
318 | - if (--vcp->vc_inuse) { | |
319 | - unlock_kernel(); | |
320 | - return 0; | |
321 | - } | |
322 | - | |
323 | - /* Wakeup clients so they can return. */ | |
314 | + lock_kernel(); | |
315 | + | |
316 | + /* Wakeup clients so they can return. */ | |
324 | 317 | list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) { |
318 | + list_del(&req->uc_chain); | |
319 | + | |
325 | 320 | /* Async requests need to be freed here */ |
326 | 321 | if (req->uc_flags & REQ_ASYNC) { |
327 | 322 | CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr)); |
328 | 323 | |
329 | 324 | |
... | ... | @@ -330,13 +325,17 @@ |
330 | 325 | } |
331 | 326 | req->uc_flags |= REQ_ABORT; |
332 | 327 | wake_up(&req->uc_sleep); |
333 | - } | |
334 | - | |
335 | - list_for_each_entry(req, &vcp->vc_processing, uc_chain) { | |
328 | + } | |
329 | + | |
330 | + list_for_each_entry_safe(req, tmp, &vcp->vc_processing, uc_chain) { | |
331 | + list_del(&req->uc_chain); | |
332 | + | |
336 | 333 | req->uc_flags |= REQ_ABORT; |
337 | - wake_up(&req->uc_sleep); | |
338 | - } | |
334 | + wake_up(&req->uc_sleep); | |
335 | + } | |
339 | 336 | |
337 | + file->private_data = NULL; | |
338 | + vcp->vc_inuse--; | |
340 | 339 | unlock_kernel(); |
341 | 340 | return 0; |
342 | 341 | } |
fs/coda/upcall.c
... | ... | @@ -641,8 +641,7 @@ |
641 | 641 | * |
642 | 642 | */ |
643 | 643 | |
644 | -static inline void coda_waitfor_upcall(struct upc_req *vmp, | |
645 | - struct venus_comm *vcommp) | |
644 | +static inline void coda_waitfor_upcall(struct upc_req *vmp) | |
646 | 645 | { |
647 | 646 | DECLARE_WAITQUEUE(wait, current); |
648 | 647 | |
... | ... | @@ -655,10 +654,6 @@ |
655 | 654 | else |
656 | 655 | set_current_state(TASK_UNINTERRUPTIBLE); |
657 | 656 | |
658 | - /* venus died */ | |
659 | - if ( !vcommp->vc_inuse ) | |
660 | - break; | |
661 | - | |
662 | 657 | /* got a reply */ |
663 | 658 | if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) |
664 | 659 | break; |
... | ... | @@ -738,7 +733,7 @@ |
738 | 733 | * ENODEV. */ |
739 | 734 | |
740 | 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 | 738 | if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ |
744 | 739 | /* Op went through, interrupt or not... */ |