]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS: set w_task only when needed 42/942/2
authorThomas Veerman <thomas@minix3.org>
Sat, 24 Aug 2013 10:23:41 +0000 (12:23 +0200)
committerLionel Sambuc <lionel@minix3.org>
Tue, 18 Feb 2014 10:25:02 +0000 (11:25 +0100)
It was always set, but not always cleared, when talking to asynchronous
drivers. This could cause erratic behavior upon a driver crash.

Normally, a worker thread's w_task field is set when it's about to
communicate with a driver or FS. Then upon receiving a reply we can
do sanity checks (that the thread we want to wake up was actually
waiting for a reply). Also, when a driver/FS crashes, we can identify
which worker threads were talking to the crashed endpoint and handle
the error gracefully.

Asynchronous drivers are a bit special, though. In most cases, the
sender of the request is not interested in the reply (the sender was
suspended and only wants to know whether the request was successfully
caried out or not). However, the open request is special, as the reply
carries information needed by the sender. This is the only request
where a worker thread actually yields and waits for the result. This is
also the only case where we're interested in setting w_task for
asynchronous drivers.

Change-Id: Ia1ce2747937df376122b5e13b6a069de27fcc379

servers/vfs/device.c

index f0647bad382b333b33e4d3c60bd38f8d15ca54a0..2e285a6f93df6bd2d704eef0eeb4fea4d54ec3f7 100644 (file)
@@ -558,7 +558,9 @@ int gen_opcl(
 
   if (op == DEV_OPEN && dp->dmap_style == STYLE_DEVA) {
        fp->fp_task = dp->dmap_driver;
+       self->w_task = dp->dmap_driver;
        worker_wait();
+       self->w_task = NONE;
   }
 
   if (is_bdev)
@@ -769,7 +771,6 @@ int asyn_io(endpoint_t drv_e, message *mess_ptr)
 
   assert(!IS_BDEV_RQ(mess_ptr->m_type));
   self->w_drv_sendrec = mess_ptr; /* Remember where result should be stored */
-  self->w_task = drv_e;
 
   r = asynsend3(drv_e, mess_ptr, AMF_NOREPLY);
 
@@ -892,7 +893,9 @@ int clone_opcl(
   if (op == DEV_OPEN && dev_style_asyn(dp->dmap_style)) {
        /* Wait for reply when driver is asynchronous */
        fp->fp_task = dp->dmap_driver;
+       self->w_task = dp->dmap_driver;
        worker_wait();
+       self->w_task = NONE;
   }
 
   if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
@@ -1069,7 +1072,6 @@ void open_reply(void)
   }
   *wp->w_drv_sendrec = job_m_in;
   wp->w_drv_sendrec = NULL;
-  wp->w_task = NONE;
   worker_signal(wp);   /* Continue open */
 }