xenstore.c (41716b8d5151d2bec72b6796ed58b6206cdb4779) xenstore.c (5f8f664619ecc3afcbc3573a64a814646b3584ba)
1/******************************************************************************
2 * xenstore.c
3 *
4 * Low-level kernel interface to the XenStore.
5 *
6 * Copyright (C) 2005 Rusty Russell, IBM Corporation
7 * Copyright (C) 2009,2010 Spectra Logic Corporation
8 *

--- 188 unchanged lines hidden (view full) ---

197 * List of pending watch callback events.
198 */
199 struct xs_stored_msg_list watch_events;
200
201 /** Lock protecting the watch calback list. */
202 struct mtx watch_events_lock;
203
204 /**
1/******************************************************************************
2 * xenstore.c
3 *
4 * Low-level kernel interface to the XenStore.
5 *
6 * Copyright (C) 2005 Rusty Russell, IBM Corporation
7 * Copyright (C) 2009,2010 Spectra Logic Corporation
8 *

--- 188 unchanged lines hidden (view full) ---

197 * List of pending watch callback events.
198 */
199 struct xs_stored_msg_list watch_events;
200
201 /** Lock protecting the watch calback list. */
202 struct mtx watch_events_lock;
203
204 /**
205 * Sleepable lock used to prevent VM suspension while a
206 * xenstore transaction is outstanding.
207 *
208 * Each active transaction holds a shared lock on the
209 * suspend mutex. Our suspend method blocks waiting
210 * to acquire an exclusive lock. This guarantees that
211 * suspend processing will only proceed once all active
212 * transactions have been retired.
213 */
214 struct sx suspend_mutex;
215
216 /**
217 * The processid of the xenwatch thread.
218 */
219 pid_t xenwatch_pid;
220
221 /**
222 * Sleepable mutex used to gate the execution of XenStore
223 * watch event callbacks.
224 *

--- 480 unchanged lines hidden (view full) ---

705 error = xs_process_msg(&type);
706 if (error)
707 printf("XENSTORE error %d while reading message\n",
708 error);
709 }
710}
711
712/*---------------- XenStore Message Request/Reply Processing -----------------*/
205 * The processid of the xenwatch thread.
206 */
207 pid_t xenwatch_pid;
208
209 /**
210 * Sleepable mutex used to gate the execution of XenStore
211 * watch event callbacks.
212 *

--- 480 unchanged lines hidden (view full) ---

693 error = xs_process_msg(&type);
694 if (error)
695 printf("XENSTORE error %d while reading message\n",
696 error);
697 }
698}
699
700/*---------------- XenStore Message Request/Reply Processing -----------------*/
713/**
714 * Filter invoked before transmitting any message to the XenStore service.
715 *
716 * The role of the filter may expand, but currently serves to manage
717 * the interactions of messages with transaction state.
718 *
719 * \param request_msg_type The message type for the request.
720 */
721static inline void
722xs_request_filter(uint32_t request_msg_type)
723{
724 if (request_msg_type == XS_TRANSACTION_START)
725 sx_slock(&xs.suspend_mutex);
726}
727
728/**
729 * Filter invoked after transmitting any message to the XenStore service.
730 *
731 * The role of the filter may expand, but currently serves to manage
732 * the interactions of messages with transaction state.
733 *
734 * \param request_msg_type The message type for the original request.
735 * \param reply_msg_type The message type for any received reply.
736 * \param request_reply_error The error status from the attempt to send
737 * the request or retrieve the reply.
738 */
739static inline void
740xs_reply_filter(uint32_t request_msg_type,
741 uint32_t reply_msg_type, int request_reply_error)
742{
743 /*
744 * The count of transactions drops if we attempted
745 * to end a transaction (even if that attempt fails
746 * in error), we receive a transaction end acknowledgement,
747 * or if our attempt to begin a transaction fails.
748 */
749 if (request_msg_type == XS_TRANSACTION_END
750 || (request_reply_error == 0 && reply_msg_type == XS_TRANSACTION_END)
751 || (request_msg_type == XS_TRANSACTION_START
752 && (request_reply_error != 0 || reply_msg_type == XS_ERROR)))
753 sx_sunlock(&xs.suspend_mutex);
754
755}
756
757#define xsd_error_count (sizeof(xsd_errors) / sizeof(xsd_errors[0]))
758
759/**
760 * Convert a XenStore error string into an errno number.
761 *
762 * \param errorstring The error string to convert.
763 *
764 * \return The errno best matching the input string.

--- 73 unchanged lines hidden (view full) ---

838 */
839int
840xs_dev_request_and_reply(struct xsd_sockmsg *msg, void **result)
841{
842 uint32_t request_type;
843 int error;
844
845 request_type = msg->type;
701#define xsd_error_count (sizeof(xsd_errors) / sizeof(xsd_errors[0]))
702
703/**
704 * Convert a XenStore error string into an errno number.
705 *
706 * \param errorstring The error string to convert.
707 *
708 * \return The errno best matching the input string.

--- 73 unchanged lines hidden (view full) ---

782 */
783int
784xs_dev_request_and_reply(struct xsd_sockmsg *msg, void **result)
785{
786 uint32_t request_type;
787 int error;
788
789 request_type = msg->type;
846 xs_request_filter(request_type);
847
848 sx_xlock(&xs.request_mutex);
849 if ((error = xs_write_store(msg, sizeof(*msg) + msg->len)) == 0)
850 error = xs_read_reply(&msg->type, &msg->len, result);
851 sx_xunlock(&xs.request_mutex);
852
790
791 sx_xlock(&xs.request_mutex);
792 if ((error = xs_write_store(msg, sizeof(*msg) + msg->len)) == 0)
793 error = xs_read_reply(&msg->type, &msg->len, result);
794 sx_xunlock(&xs.request_mutex);
795
853 xs_reply_filter(request_type, msg->type, error);
854
855 return (error);
856}
857
858/**
859 * Send a message with an optionally muti-part body to the XenStore service.
860 *
861 * \param t The transaction to use for this request.
862 * \param request_type The type of message to send.

--- 19 unchanged lines hidden (view full) ---

882
883 msg.tx_id = t.id;
884 msg.req_id = 0;
885 msg.type = request_type;
886 msg.len = 0;
887 for (i = 0; i < num_vecs; i++)
888 msg.len += iovec[i].iov_len;
889
796 return (error);
797}
798
799/**
800 * Send a message with an optionally muti-part body to the XenStore service.
801 *
802 * \param t The transaction to use for this request.
803 * \param request_type The type of message to send.

--- 19 unchanged lines hidden (view full) ---

823
824 msg.tx_id = t.id;
825 msg.req_id = 0;
826 msg.type = request_type;
827 msg.len = 0;
828 for (i = 0; i < num_vecs; i++)
829 msg.len += iovec[i].iov_len;
830
890 xs_request_filter(request_type);
891
892 sx_xlock(&xs.request_mutex);
893 error = xs_write_store(&msg, sizeof(msg));
894 if (error) {
895 printf("xs_talkv failed %d\n", error);
896 goto error_lock_held;
897 }
898
899 for (i = 0; i < num_vecs; i++) {
900 error = xs_write_store(iovec[i].iov_base, iovec[i].iov_len);
901 if (error) {
902 printf("xs_talkv failed %d\n", error);
903 goto error_lock_held;
904 }
905 }
906
907 error = xs_read_reply(&msg.type, len, &ret);
908
909error_lock_held:
910 sx_xunlock(&xs.request_mutex);
831 sx_xlock(&xs.request_mutex);
832 error = xs_write_store(&msg, sizeof(msg));
833 if (error) {
834 printf("xs_talkv failed %d\n", error);
835 goto error_lock_held;
836 }
837
838 for (i = 0; i < num_vecs; i++) {
839 error = xs_write_store(iovec[i].iov_base, iovec[i].iov_len);
840 if (error) {
841 printf("xs_talkv failed %d\n", error);
842 goto error_lock_held;
843 }
844 }
845
846 error = xs_read_reply(&msg.type, len, &ret);
847
848error_lock_held:
849 sx_xunlock(&xs.request_mutex);
911 xs_reply_filter(request_type, msg.type, error);
912 if (error)
913 return (error);
914
915 if (msg.type == XS_ERROR) {
916 error = xs_get_error(ret);
917 free(ret, M_XENSTORE);
918 return (error);
919 }

--- 281 unchanged lines hidden (view full) ---

1201
1202 TAILQ_INIT(&xs.reply_list);
1203 TAILQ_INIT(&xs.watch_events);
1204
1205 mtx_init(&xs.ring_lock, "ring lock", NULL, MTX_DEF);
1206 mtx_init(&xs.reply_lock, "reply lock", NULL, MTX_DEF);
1207 sx_init(&xs.xenwatch_mutex, "xenwatch");
1208 sx_init(&xs.request_mutex, "xenstore request");
850 if (error)
851 return (error);
852
853 if (msg.type == XS_ERROR) {
854 error = xs_get_error(ret);
855 free(ret, M_XENSTORE);
856 return (error);
857 }

--- 281 unchanged lines hidden (view full) ---

1139
1140 TAILQ_INIT(&xs.reply_list);
1141 TAILQ_INIT(&xs.watch_events);
1142
1143 mtx_init(&xs.ring_lock, "ring lock", NULL, MTX_DEF);
1144 mtx_init(&xs.reply_lock, "reply lock", NULL, MTX_DEF);
1145 sx_init(&xs.xenwatch_mutex, "xenwatch");
1146 sx_init(&xs.request_mutex, "xenstore request");
1209 sx_init(&xs.suspend_mutex, "xenstore suspend");
1210 mtx_init(&xs.registered_watches_lock, "watches", NULL, MTX_DEF);
1211 mtx_init(&xs.watch_events_lock, "watch events", NULL, MTX_DEF);
1212
1213 /* Initialize the shared memory rings to talk to xenstored */
1214 error = xs_init_comms();
1215 if (error)
1216 return (error);
1217

--- 26 unchanged lines hidden (view full) ---

1244{
1245 int error;
1246
1247 /* Suspend child Xen devices. */
1248 error = bus_generic_suspend(dev);
1249 if (error != 0)
1250 return (error);
1251
1147 mtx_init(&xs.registered_watches_lock, "watches", NULL, MTX_DEF);
1148 mtx_init(&xs.watch_events_lock, "watch events", NULL, MTX_DEF);
1149
1150 /* Initialize the shared memory rings to talk to xenstored */
1151 error = xs_init_comms();
1152 if (error)
1153 return (error);
1154

--- 26 unchanged lines hidden (view full) ---

1181{
1182 int error;
1183
1184 /* Suspend child Xen devices. */
1185 error = bus_generic_suspend(dev);
1186 if (error != 0)
1187 return (error);
1188
1252 sx_xlock(&xs.suspend_mutex);
1253 sx_xlock(&xs.request_mutex);
1254
1255 return (0);
1256}
1257
1258/**
1259 * Resume XenStore operations after this VM is resumed.
1260 */
1261static int
1262xs_resume(device_t dev __unused)
1263{
1264 struct xs_watch *watch;
1265 char token[sizeof(watch) * 2 + 1];
1266
1267 xs_init_comms();
1268
1269 sx_xunlock(&xs.request_mutex);
1270
1271 /*
1189 sx_xlock(&xs.request_mutex);
1190
1191 return (0);
1192}
1193
1194/**
1195 * Resume XenStore operations after this VM is resumed.
1196 */
1197static int
1198xs_resume(device_t dev __unused)
1199{
1200 struct xs_watch *watch;
1201 char token[sizeof(watch) * 2 + 1];
1202
1203 xs_init_comms();
1204
1205 sx_xunlock(&xs.request_mutex);
1206
1207 /*
1272 * No need for registered_watches_lock: the suspend_mutex
1273 * is sufficient.
1208 * NB: since xenstore childs have not been resumed yet, there's
1209 * no need to hold any watch mutex. Having clients try to add or
1210 * remove watches at this point (before xenstore is resumed) is
1211 * clearly a violantion of the resume order.
1274 */
1275 LIST_FOREACH(watch, &xs.registered_watches, list) {
1276 sprintf(token, "%lX", (long)watch);
1277 xs_watch(watch->node, token);
1278 }
1279
1212 */
1213 LIST_FOREACH(watch, &xs.registered_watches, list) {
1214 sprintf(token, "%lX", (long)watch);
1215 xs_watch(watch->node, token);
1216 }
1217
1280 sx_xunlock(&xs.suspend_mutex);
1281
1282 /* Resume child Xen devices. */
1283 bus_generic_resume(dev);
1284
1285 return (0);
1286}
1287
1288/*-------------------- Private Device Attachment Data -----------------------*/
1289static device_method_t xenstore_methods[] = {

--- 336 unchanged lines hidden (view full) ---

1626xs_register_watch(struct xs_watch *watch)
1627{
1628 /* Pointer in ascii is the token. */
1629 char token[sizeof(watch) * 2 + 1];
1630 int error;
1631
1632 sprintf(token, "%lX", (long)watch);
1633
1218 /* Resume child Xen devices. */
1219 bus_generic_resume(dev);
1220
1221 return (0);
1222}
1223
1224/*-------------------- Private Device Attachment Data -----------------------*/
1225static device_method_t xenstore_methods[] = {

--- 336 unchanged lines hidden (view full) ---

1562xs_register_watch(struct xs_watch *watch)
1563{
1564 /* Pointer in ascii is the token. */
1565 char token[sizeof(watch) * 2 + 1];
1566 int error;
1567
1568 sprintf(token, "%lX", (long)watch);
1569
1634 sx_slock(&xs.suspend_mutex);
1635
1636 mtx_lock(&xs.registered_watches_lock);
1637 KASSERT(find_watch(token) == NULL, ("watch already registered"));
1638 LIST_INSERT_HEAD(&xs.registered_watches, watch, list);
1639 mtx_unlock(&xs.registered_watches_lock);
1640
1641 error = xs_watch(watch->node, token);
1642
1643 /* Ignore errors due to multiple registration. */
1644 if (error == EEXIST)
1645 error = 0;
1646
1647 if (error != 0) {
1648 mtx_lock(&xs.registered_watches_lock);
1649 LIST_REMOVE(watch, list);
1650 mtx_unlock(&xs.registered_watches_lock);
1651 }
1652
1570 mtx_lock(&xs.registered_watches_lock);
1571 KASSERT(find_watch(token) == NULL, ("watch already registered"));
1572 LIST_INSERT_HEAD(&xs.registered_watches, watch, list);
1573 mtx_unlock(&xs.registered_watches_lock);
1574
1575 error = xs_watch(watch->node, token);
1576
1577 /* Ignore errors due to multiple registration. */
1578 if (error == EEXIST)
1579 error = 0;
1580
1581 if (error != 0) {
1582 mtx_lock(&xs.registered_watches_lock);
1583 LIST_REMOVE(watch, list);
1584 mtx_unlock(&xs.registered_watches_lock);
1585 }
1586
1653 sx_sunlock(&xs.suspend_mutex);
1654
1655 return (error);
1656}
1657
1658void
1659xs_unregister_watch(struct xs_watch *watch)
1660{
1661 struct xs_stored_msg *msg, *tmp;
1662 char token[sizeof(watch) * 2 + 1];
1663 int error;
1664
1665 sprintf(token, "%lX", (long)watch);
1666
1587 return (error);
1588}
1589
1590void
1591xs_unregister_watch(struct xs_watch *watch)
1592{
1593 struct xs_stored_msg *msg, *tmp;
1594 char token[sizeof(watch) * 2 + 1];
1595 int error;
1596
1597 sprintf(token, "%lX", (long)watch);
1598
1667 sx_slock(&xs.suspend_mutex);
1668
1669 mtx_lock(&xs.registered_watches_lock);
1670 if (find_watch(token) == NULL) {
1671 mtx_unlock(&xs.registered_watches_lock);
1599 mtx_lock(&xs.registered_watches_lock);
1600 if (find_watch(token) == NULL) {
1601 mtx_unlock(&xs.registered_watches_lock);
1672 sx_sunlock(&xs.suspend_mutex);
1673 return;
1674 }
1675 LIST_REMOVE(watch, list);
1676 mtx_unlock(&xs.registered_watches_lock);
1677
1678 error = xs_unwatch(watch->node, token);
1679 if (error)
1680 log(LOG_WARNING, "XENSTORE Failed to release watch %s: %i\n",
1681 watch->node, error);
1682
1602 return;
1603 }
1604 LIST_REMOVE(watch, list);
1605 mtx_unlock(&xs.registered_watches_lock);
1606
1607 error = xs_unwatch(watch->node, token);
1608 if (error)
1609 log(LOG_WARNING, "XENSTORE Failed to release watch %s: %i\n",
1610 watch->node, error);
1611
1683 sx_sunlock(&xs.suspend_mutex);
1684
1685 /* Cancel pending watch events. */
1686 mtx_lock(&xs.watch_events_lock);
1687 TAILQ_FOREACH_SAFE(msg, &xs.watch_events, list, tmp) {
1688 if (msg->u.watch.handle != watch)
1689 continue;
1690 TAILQ_REMOVE(&xs.watch_events, msg, list);
1691 free(msg->u.watch.vec, M_XENSTORE);
1692 free(msg, M_XENSTORE);

--- 26 unchanged lines hidden ---
1612 /* Cancel pending watch events. */
1613 mtx_lock(&xs.watch_events_lock);
1614 TAILQ_FOREACH_SAFE(msg, &xs.watch_events, list, tmp) {
1615 if (msg->u.watch.handle != watch)
1616 continue;
1617 TAILQ_REMOVE(&xs.watch_events, msg, list);
1618 free(msg->u.watch.vec, M_XENSTORE);
1619 free(msg, M_XENSTORE);

--- 26 unchanged lines hidden ---