Commit 7cc88fdcff3cc7f0d5d2384ffd7f6d4ce9a745f1

Authored by Jeremy Fitzhardinge

Merge branch 'xen/xenbus' into upstream/xen

* xen/xenbus:
  implement O_NONBLOCK for /proc/xen/xenbus
  xenbus: do not hold transaction_mutex when returning to userspace

Showing 2 changed files Side-by-side Diff

drivers/xen/xenbus/xenbus_xs.c
... ... @@ -76,6 +76,14 @@
76 76 /*
77 77 * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex.
78 78 * response_mutex is never taken simultaneously with the other three.
  79 + *
  80 + * transaction_mutex must be held before incrementing
  81 + * transaction_count. The mutex is held when a suspend is in
  82 + * progress to prevent new transactions starting.
  83 + *
  84 + * When decrementing transaction_count to zero the wait queue
  85 + * should be woken up, the suspend code waits for count to
  86 + * reach zero.
79 87 */
80 88  
81 89 /* One request at a time. */
... ... @@ -85,7 +93,9 @@
85 93 struct mutex response_mutex;
86 94  
87 95 /* Protect transactions against save/restore. */
88   - struct rw_semaphore transaction_mutex;
  96 + struct mutex transaction_mutex;
  97 + atomic_t transaction_count;
  98 + wait_queue_head_t transaction_wq;
89 99  
90 100 /* Protect watch (de)register against save/restore. */
91 101 struct rw_semaphore watch_mutex;
... ... @@ -157,6 +167,31 @@
157 167 return body;
158 168 }
159 169  
  170 +static void transaction_start(void)
  171 +{
  172 + mutex_lock(&xs_state.transaction_mutex);
  173 + atomic_inc(&xs_state.transaction_count);
  174 + mutex_unlock(&xs_state.transaction_mutex);
  175 +}
  176 +
  177 +static void transaction_end(void)
  178 +{
  179 + if (atomic_dec_and_test(&xs_state.transaction_count))
  180 + wake_up(&xs_state.transaction_wq);
  181 +}
  182 +
  183 +static void transaction_suspend(void)
  184 +{
  185 + mutex_lock(&xs_state.transaction_mutex);
  186 + wait_event(xs_state.transaction_wq,
  187 + atomic_read(&xs_state.transaction_count) == 0);
  188 +}
  189 +
  190 +static void transaction_resume(void)
  191 +{
  192 + mutex_unlock(&xs_state.transaction_mutex);
  193 +}
  194 +
160 195 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
161 196 {
162 197 void *ret;
... ... @@ -164,7 +199,7 @@
164 199 int err;
165 200  
166 201 if (req_msg.type == XS_TRANSACTION_START)
167   - down_read(&xs_state.transaction_mutex);
  202 + transaction_start();
168 203  
169 204 mutex_lock(&xs_state.request_mutex);
170 205  
... ... @@ -180,7 +215,7 @@
180 215 if ((msg->type == XS_TRANSACTION_END) ||
181 216 ((req_msg.type == XS_TRANSACTION_START) &&
182 217 (msg->type == XS_ERROR)))
183   - up_read(&xs_state.transaction_mutex);
  218 + transaction_end();
184 219  
185 220 return ret;
186 221 }
187 222  
... ... @@ -432,11 +467,11 @@
432 467 {
433 468 char *id_str;
434 469  
435   - down_read(&xs_state.transaction_mutex);
  470 + transaction_start();
436 471  
437 472 id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL);
438 473 if (IS_ERR(id_str)) {
439   - up_read(&xs_state.transaction_mutex);
  474 + transaction_end();
440 475 return PTR_ERR(id_str);
441 476 }
442 477  
... ... @@ -461,7 +496,7 @@
461 496  
462 497 err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
463 498  
464   - up_read(&xs_state.transaction_mutex);
  499 + transaction_end();
465 500  
466 501 return err;
467 502 }
... ... @@ -662,7 +697,7 @@
662 697  
663 698 void xs_suspend(void)
664 699 {
665   - down_write(&xs_state.transaction_mutex);
  700 + transaction_suspend();
666 701 down_write(&xs_state.watch_mutex);
667 702 mutex_lock(&xs_state.request_mutex);
668 703 mutex_lock(&xs_state.response_mutex);
... ... @@ -677,7 +712,7 @@
677 712  
678 713 mutex_unlock(&xs_state.response_mutex);
679 714 mutex_unlock(&xs_state.request_mutex);
680   - up_write(&xs_state.transaction_mutex);
  715 + transaction_resume();
681 716  
682 717 /* No need for watches_lock: the watch_mutex is sufficient. */
683 718 list_for_each_entry(watch, &watches, list) {
... ... @@ -693,7 +728,7 @@
693 728 mutex_unlock(&xs_state.response_mutex);
694 729 mutex_unlock(&xs_state.request_mutex);
695 730 up_write(&xs_state.watch_mutex);
696   - up_write(&xs_state.transaction_mutex);
  731 + mutex_unlock(&xs_state.transaction_mutex);
697 732 }
698 733  
699 734 static int xenwatch_thread(void *unused)
700 735  
... ... @@ -843,8 +878,10 @@
843 878  
844 879 mutex_init(&xs_state.request_mutex);
845 880 mutex_init(&xs_state.response_mutex);
846   - init_rwsem(&xs_state.transaction_mutex);
  881 + mutex_init(&xs_state.transaction_mutex);
847 882 init_rwsem(&xs_state.watch_mutex);
  883 + atomic_set(&xs_state.transaction_count, 0);
  884 + init_waitqueue_head(&xs_state.transaction_wq);
848 885  
849 886 /* Initialize the shared memory rings to talk to xenstored */
850 887 err = xb_init_comms();
drivers/xen/xenfs/xenbus.c
... ... @@ -124,6 +124,9 @@
124 124 mutex_lock(&u->reply_mutex);
125 125 while (list_empty(&u->read_buffers)) {
126 126 mutex_unlock(&u->reply_mutex);
  127 + if (filp->f_flags & O_NONBLOCK)
  128 + return -EAGAIN;
  129 +
127 130 ret = wait_event_interruptible(u->read_waitq,
128 131 !list_empty(&u->read_buffers));
129 132 if (ret)