12fb3683eSBastian Blank /* 22fb3683eSBastian Blank * Driver giving user-space access to the kernel's xenbus connection 32fb3683eSBastian Blank * to xenstore. 42fb3683eSBastian Blank * 52fb3683eSBastian Blank * Copyright (c) 2005, Christian Limpach 62fb3683eSBastian Blank * Copyright (c) 2005, Rusty Russell, IBM Corporation 72fb3683eSBastian Blank * 82fb3683eSBastian Blank * This program is free software; you can redistribute it and/or 92fb3683eSBastian Blank * modify it under the terms of the GNU General Public License version 2 102fb3683eSBastian Blank * as published by the Free Software Foundation; or, when distributed 112fb3683eSBastian Blank * separately from the Linux kernel or incorporated into other 122fb3683eSBastian Blank * software packages, subject to the following license: 132fb3683eSBastian Blank * 142fb3683eSBastian Blank * Permission is hereby granted, free of charge, to any person obtaining a copy 152fb3683eSBastian Blank * of this source file (the "Software"), to deal in the Software without 162fb3683eSBastian Blank * restriction, including without limitation the rights to use, copy, modify, 172fb3683eSBastian Blank * merge, publish, distribute, sublicense, and/or sell copies of the Software, 182fb3683eSBastian Blank * and to permit persons to whom the Software is furnished to do so, subject to 192fb3683eSBastian Blank * the following conditions: 202fb3683eSBastian Blank * 212fb3683eSBastian Blank * The above copyright notice and this permission notice shall be included in 222fb3683eSBastian Blank * all copies or substantial portions of the Software. 232fb3683eSBastian Blank * 242fb3683eSBastian Blank * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 252fb3683eSBastian Blank * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 262fb3683eSBastian Blank * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 272fb3683eSBastian Blank * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 282fb3683eSBastian Blank * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 292fb3683eSBastian Blank * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 302fb3683eSBastian Blank * IN THE SOFTWARE. 312fb3683eSBastian Blank * 322fb3683eSBastian Blank * Changes: 332fb3683eSBastian Blank * 2008-10-07 Alex Zeffertt Replaced /proc/xen/xenbus with xenfs filesystem 342fb3683eSBastian Blank * and /proc/xen compatibility mount point. 352fb3683eSBastian Blank * Turned xenfs into a loadable module. 362fb3683eSBastian Blank */ 372fb3683eSBastian Blank 38283c0972SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 39283c0972SJoe Perches 402fb3683eSBastian Blank #include <linux/kernel.h> 412fb3683eSBastian Blank #include <linux/errno.h> 422fb3683eSBastian Blank #include <linux/uio.h> 432fb3683eSBastian Blank #include <linux/notifier.h> 442fb3683eSBastian Blank #include <linux/wait.h> 452fb3683eSBastian Blank #include <linux/fs.h> 462fb3683eSBastian Blank #include <linux/poll.h> 472fb3683eSBastian Blank #include <linux/mutex.h> 482fb3683eSBastian Blank #include <linux/sched.h> 492fb3683eSBastian Blank #include <linux/spinlock.h> 502fb3683eSBastian Blank #include <linux/mount.h> 512fb3683eSBastian Blank #include <linux/pagemap.h> 522fb3683eSBastian Blank #include <linux/uaccess.h> 532fb3683eSBastian Blank #include <linux/init.h> 542fb3683eSBastian Blank #include <linux/namei.h> 552fb3683eSBastian Blank #include <linux/string.h> 562fb3683eSBastian Blank #include <linux/slab.h> 572fb3683eSBastian Blank #include <linux/miscdevice.h> 58a8fabb38SJuergen Gross #include <linux/workqueue.h> 592fb3683eSBastian Blank 602fb3683eSBastian Blank #include <xen/xenbus.h> 61b79d2ff9SKonrad Rzeszutek Wilk #include <xen/xen.h> 622fb3683eSBastian Blank #include <asm/xen/hypervisor.h> 632fb3683eSBastian Blank 64332f791dSJuergen Gross #include "xenbus.h" 65332f791dSJuergen Gross 66d10e0cc1SRoss Lagerwall unsigned int xb_dev_generation_id; 67d10e0cc1SRoss Lagerwall 682fb3683eSBastian Blank /* 692fb3683eSBastian Blank * An element of a list of outstanding transactions, for which we're 702fb3683eSBastian Blank * still waiting a reply. 712fb3683eSBastian Blank */ 722fb3683eSBastian Blank struct xenbus_transaction_holder { 732fb3683eSBastian Blank struct list_head list; 742fb3683eSBastian Blank struct xenbus_transaction handle; 75d10e0cc1SRoss Lagerwall unsigned int generation_id; 762fb3683eSBastian Blank }; 772fb3683eSBastian Blank 782fb3683eSBastian Blank /* 792fb3683eSBastian Blank * A buffer of data on the queue. 802fb3683eSBastian Blank */ 812fb3683eSBastian Blank struct read_buffer { 822fb3683eSBastian Blank struct list_head list; 832fb3683eSBastian Blank unsigned int cons; 842fb3683eSBastian Blank unsigned int len; 852fb3683eSBastian Blank char msg[]; 862fb3683eSBastian Blank }; 872fb3683eSBastian Blank 882fb3683eSBastian Blank struct xenbus_file_priv { 892fb3683eSBastian Blank /* 902fb3683eSBastian Blank * msgbuffer_mutex is held while partial requests are built up 912fb3683eSBastian Blank * and complete requests are acted on. It therefore protects 922fb3683eSBastian Blank * the "transactions" and "watches" lists, and the partial 932fb3683eSBastian Blank * request length and buffer. 942fb3683eSBastian Blank * 952fb3683eSBastian Blank * reply_mutex protects the reply being built up to return to 962fb3683eSBastian Blank * usermode. It nests inside msgbuffer_mutex but may be held 972fb3683eSBastian Blank * alone during a watch callback. 982fb3683eSBastian Blank */ 992fb3683eSBastian Blank struct mutex msgbuffer_mutex; 1002fb3683eSBastian Blank 1012fb3683eSBastian Blank /* In-progress transactions */ 1022fb3683eSBastian Blank struct list_head transactions; 1032fb3683eSBastian Blank 1042fb3683eSBastian Blank /* Active watches. */ 1052fb3683eSBastian Blank struct list_head watches; 1062fb3683eSBastian Blank 1072fb3683eSBastian Blank /* Partial request. */ 1082fb3683eSBastian Blank unsigned int len; 1092fb3683eSBastian Blank union { 1102fb3683eSBastian Blank struct xsd_sockmsg msg; 11150bf7379SIan Campbell char buffer[XENSTORE_PAYLOAD_MAX]; 1122fb3683eSBastian Blank } u; 1132fb3683eSBastian Blank 1142fb3683eSBastian Blank /* Response queue. */ 1152fb3683eSBastian Blank struct mutex reply_mutex; 1162fb3683eSBastian Blank struct list_head read_buffers; 1172fb3683eSBastian Blank wait_queue_head_t read_waitq; 1182fb3683eSBastian Blank 119fd8aa909SJuergen Gross struct kref kref; 120a8fabb38SJuergen Gross 121a8fabb38SJuergen Gross struct work_struct wq; 1222fb3683eSBastian Blank }; 1232fb3683eSBastian Blank 1242fb3683eSBastian Blank /* Read out any raw xenbus messages queued up. */ 1252fb3683eSBastian Blank static ssize_t xenbus_file_read(struct file *filp, 1262fb3683eSBastian Blank char __user *ubuf, 1272fb3683eSBastian Blank size_t len, loff_t *ppos) 1282fb3683eSBastian Blank { 1292fb3683eSBastian Blank struct xenbus_file_priv *u = filp->private_data; 1302fb3683eSBastian Blank struct read_buffer *rb; 131*32ad1112SDan Carpenter ssize_t i; 1322fb3683eSBastian Blank int ret; 1332fb3683eSBastian Blank 1342fb3683eSBastian Blank mutex_lock(&u->reply_mutex); 1352fb3683eSBastian Blank again: 1362fb3683eSBastian Blank while (list_empty(&u->read_buffers)) { 1372fb3683eSBastian Blank mutex_unlock(&u->reply_mutex); 1382fb3683eSBastian Blank if (filp->f_flags & O_NONBLOCK) 1392fb3683eSBastian Blank return -EAGAIN; 1402fb3683eSBastian Blank 1412fb3683eSBastian Blank ret = wait_event_interruptible(u->read_waitq, 1422fb3683eSBastian Blank !list_empty(&u->read_buffers)); 1432fb3683eSBastian Blank if (ret) 1442fb3683eSBastian Blank return ret; 1452fb3683eSBastian Blank mutex_lock(&u->reply_mutex); 1462fb3683eSBastian Blank } 1472fb3683eSBastian Blank 1482fb3683eSBastian Blank rb = list_entry(u->read_buffers.next, struct read_buffer, list); 1492fb3683eSBastian Blank i = 0; 1502fb3683eSBastian Blank while (i < len) { 151*32ad1112SDan Carpenter size_t sz = min_t(size_t, len - i, rb->len - rb->cons); 1522fb3683eSBastian Blank 1532fb3683eSBastian Blank ret = copy_to_user(ubuf + i, &rb->msg[rb->cons], sz); 1542fb3683eSBastian Blank 1552fb3683eSBastian Blank i += sz - ret; 1562fb3683eSBastian Blank rb->cons += sz - ret; 1572fb3683eSBastian Blank 1582fb3683eSBastian Blank if (ret != 0) { 1592fb3683eSBastian Blank if (i == 0) 1602fb3683eSBastian Blank i = -EFAULT; 1612fb3683eSBastian Blank goto out; 1622fb3683eSBastian Blank } 1632fb3683eSBastian Blank 1642fb3683eSBastian Blank /* Clear out buffer if it has been consumed */ 1652fb3683eSBastian Blank if (rb->cons == rb->len) { 1662fb3683eSBastian Blank list_del(&rb->list); 1672fb3683eSBastian Blank kfree(rb); 1682fb3683eSBastian Blank if (list_empty(&u->read_buffers)) 1692fb3683eSBastian Blank break; 1702fb3683eSBastian Blank rb = list_entry(u->read_buffers.next, 1712fb3683eSBastian Blank struct read_buffer, list); 1722fb3683eSBastian Blank } 1732fb3683eSBastian Blank } 1742fb3683eSBastian Blank if (i == 0) 1752fb3683eSBastian Blank goto again; 1762fb3683eSBastian Blank 1772fb3683eSBastian Blank out: 1782fb3683eSBastian Blank mutex_unlock(&u->reply_mutex); 1792fb3683eSBastian Blank return i; 1802fb3683eSBastian Blank } 1812fb3683eSBastian Blank 1822fb3683eSBastian Blank /* 1832fb3683eSBastian Blank * Add a buffer to the queue. Caller must hold the appropriate lock 1842fb3683eSBastian Blank * if the queue is not local. (Commonly the caller will build up 1852fb3683eSBastian Blank * multiple queued buffers on a temporary local list, and then add it 1862fb3683eSBastian Blank * to the appropriate list under lock once all the buffers have een 1872fb3683eSBastian Blank * successfully allocated.) 1882fb3683eSBastian Blank */ 1892fb3683eSBastian Blank static int queue_reply(struct list_head *queue, const void *data, size_t len) 1902fb3683eSBastian Blank { 1912fb3683eSBastian Blank struct read_buffer *rb; 1922fb3683eSBastian Blank 1932fb3683eSBastian Blank if (len == 0) 1942fb3683eSBastian Blank return 0; 19585c0a87cSInsu Yun if (len > XENSTORE_PAYLOAD_MAX) 19685c0a87cSInsu Yun return -EINVAL; 1972fb3683eSBastian Blank 1982fb3683eSBastian Blank rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL); 1992fb3683eSBastian Blank if (rb == NULL) 2002fb3683eSBastian Blank return -ENOMEM; 2012fb3683eSBastian Blank 2022fb3683eSBastian Blank rb->cons = 0; 2032fb3683eSBastian Blank rb->len = len; 2042fb3683eSBastian Blank 2052fb3683eSBastian Blank memcpy(rb->msg, data, len); 2062fb3683eSBastian Blank 2072fb3683eSBastian Blank list_add_tail(&rb->list, queue); 2082fb3683eSBastian Blank return 0; 2092fb3683eSBastian Blank } 2102fb3683eSBastian Blank 2112fb3683eSBastian Blank /* 2122fb3683eSBastian Blank * Free all the read_buffer s on a list. 2132fb3683eSBastian Blank * Caller must have sole reference to list. 2142fb3683eSBastian Blank */ 2152fb3683eSBastian Blank static void queue_cleanup(struct list_head *list) 2162fb3683eSBastian Blank { 2172fb3683eSBastian Blank struct read_buffer *rb; 2182fb3683eSBastian Blank 2192fb3683eSBastian Blank while (!list_empty(list)) { 2202fb3683eSBastian Blank rb = list_entry(list->next, struct read_buffer, list); 2212fb3683eSBastian Blank list_del(list->next); 2222fb3683eSBastian Blank kfree(rb); 2232fb3683eSBastian Blank } 2242fb3683eSBastian Blank } 2252fb3683eSBastian Blank 2262fb3683eSBastian Blank struct watch_adapter { 2272fb3683eSBastian Blank struct list_head list; 2282fb3683eSBastian Blank struct xenbus_watch watch; 2292fb3683eSBastian Blank struct xenbus_file_priv *dev_data; 2302fb3683eSBastian Blank char *token; 2312fb3683eSBastian Blank }; 2322fb3683eSBastian Blank 2332fb3683eSBastian Blank static void free_watch_adapter(struct watch_adapter *watch) 2342fb3683eSBastian Blank { 2352fb3683eSBastian Blank kfree(watch->watch.node); 2362fb3683eSBastian Blank kfree(watch->token); 2372fb3683eSBastian Blank kfree(watch); 2382fb3683eSBastian Blank } 2392fb3683eSBastian Blank 2402fb3683eSBastian Blank static struct watch_adapter *alloc_watch_adapter(const char *path, 2412fb3683eSBastian Blank const char *token) 2422fb3683eSBastian Blank { 2432fb3683eSBastian Blank struct watch_adapter *watch; 2442fb3683eSBastian Blank 2452fb3683eSBastian Blank watch = kzalloc(sizeof(*watch), GFP_KERNEL); 2462fb3683eSBastian Blank if (watch == NULL) 2472fb3683eSBastian Blank goto out_fail; 2482fb3683eSBastian Blank 2492fb3683eSBastian Blank watch->watch.node = kstrdup(path, GFP_KERNEL); 2502fb3683eSBastian Blank if (watch->watch.node == NULL) 2512fb3683eSBastian Blank goto out_free; 2522fb3683eSBastian Blank 2532fb3683eSBastian Blank watch->token = kstrdup(token, GFP_KERNEL); 2542fb3683eSBastian Blank if (watch->token == NULL) 2552fb3683eSBastian Blank goto out_free; 2562fb3683eSBastian Blank 2572fb3683eSBastian Blank return watch; 2582fb3683eSBastian Blank 2592fb3683eSBastian Blank out_free: 2602fb3683eSBastian Blank free_watch_adapter(watch); 2612fb3683eSBastian Blank 2622fb3683eSBastian Blank out_fail: 2632fb3683eSBastian Blank return NULL; 2642fb3683eSBastian Blank } 2652fb3683eSBastian Blank 2662fb3683eSBastian Blank static void watch_fired(struct xenbus_watch *watch, 2675584ea25SJuergen Gross const char *path, 2685584ea25SJuergen Gross const char *token) 2692fb3683eSBastian Blank { 2702fb3683eSBastian Blank struct watch_adapter *adap; 2712fb3683eSBastian Blank struct xsd_sockmsg hdr; 2725584ea25SJuergen Gross const char *token_caller; 2735584ea25SJuergen Gross int path_len, tok_len, body_len; 2742fb3683eSBastian Blank int ret; 2752fb3683eSBastian Blank LIST_HEAD(staging_q); 2762fb3683eSBastian Blank 2772fb3683eSBastian Blank adap = container_of(watch, struct watch_adapter, watch); 2782fb3683eSBastian Blank 2795584ea25SJuergen Gross token_caller = adap->token; 2802fb3683eSBastian Blank 2812fb3683eSBastian Blank path_len = strlen(path) + 1; 2825584ea25SJuergen Gross tok_len = strlen(token_caller) + 1; 2835584ea25SJuergen Gross body_len = path_len + tok_len; 2842fb3683eSBastian Blank 2852fb3683eSBastian Blank hdr.type = XS_WATCH_EVENT; 2862fb3683eSBastian Blank hdr.len = body_len; 2872fb3683eSBastian Blank 2882fb3683eSBastian Blank mutex_lock(&adap->dev_data->reply_mutex); 2892fb3683eSBastian Blank 2902fb3683eSBastian Blank ret = queue_reply(&staging_q, &hdr, sizeof(hdr)); 2912fb3683eSBastian Blank if (!ret) 2922fb3683eSBastian Blank ret = queue_reply(&staging_q, path, path_len); 2932fb3683eSBastian Blank if (!ret) 2945584ea25SJuergen Gross ret = queue_reply(&staging_q, token_caller, tok_len); 2952fb3683eSBastian Blank 2962fb3683eSBastian Blank if (!ret) { 2972fb3683eSBastian Blank /* success: pass reply list onto watcher */ 2982fb3683eSBastian Blank list_splice_tail(&staging_q, &adap->dev_data->read_buffers); 2992fb3683eSBastian Blank wake_up(&adap->dev_data->read_waitq); 3002fb3683eSBastian Blank } else 3012fb3683eSBastian Blank queue_cleanup(&staging_q); 3022fb3683eSBastian Blank 3032fb3683eSBastian Blank mutex_unlock(&adap->dev_data->reply_mutex); 3042fb3683eSBastian Blank } 3052fb3683eSBastian Blank 306a8fabb38SJuergen Gross static void xenbus_worker(struct work_struct *wq) 307fd8aa909SJuergen Gross { 308fd8aa909SJuergen Gross struct xenbus_file_priv *u; 309fd8aa909SJuergen Gross struct xenbus_transaction_holder *trans, *tmp; 310fd8aa909SJuergen Gross struct watch_adapter *watch, *tmp_watch; 311fd8aa909SJuergen Gross struct read_buffer *rb, *tmp_rb; 312fd8aa909SJuergen Gross 313a8fabb38SJuergen Gross u = container_of(wq, struct xenbus_file_priv, wq); 314fd8aa909SJuergen Gross 315fd8aa909SJuergen Gross /* 316fd8aa909SJuergen Gross * No need for locking here because there are no other users, 317fd8aa909SJuergen Gross * by definition. 318fd8aa909SJuergen Gross */ 319fd8aa909SJuergen Gross 320fd8aa909SJuergen Gross list_for_each_entry_safe(trans, tmp, &u->transactions, list) { 321fd8aa909SJuergen Gross xenbus_transaction_end(trans->handle, 1); 322fd8aa909SJuergen Gross list_del(&trans->list); 323fd8aa909SJuergen Gross kfree(trans); 324fd8aa909SJuergen Gross } 325fd8aa909SJuergen Gross 326fd8aa909SJuergen Gross list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) { 327fd8aa909SJuergen Gross unregister_xenbus_watch(&watch->watch); 328fd8aa909SJuergen Gross list_del(&watch->list); 329fd8aa909SJuergen Gross free_watch_adapter(watch); 330fd8aa909SJuergen Gross } 331fd8aa909SJuergen Gross 332fd8aa909SJuergen Gross list_for_each_entry_safe(rb, tmp_rb, &u->read_buffers, list) { 333fd8aa909SJuergen Gross list_del(&rb->list); 334fd8aa909SJuergen Gross kfree(rb); 335fd8aa909SJuergen Gross } 336fd8aa909SJuergen Gross kfree(u); 337fd8aa909SJuergen Gross } 338fd8aa909SJuergen Gross 339a8fabb38SJuergen Gross static void xenbus_file_free(struct kref *kref) 340a8fabb38SJuergen Gross { 341a8fabb38SJuergen Gross struct xenbus_file_priv *u; 342a8fabb38SJuergen Gross 343a8fabb38SJuergen Gross /* 344a8fabb38SJuergen Gross * We might be called in xenbus_thread(). 345a8fabb38SJuergen Gross * Use workqueue to avoid deadlock. 346a8fabb38SJuergen Gross */ 347a8fabb38SJuergen Gross u = container_of(kref, struct xenbus_file_priv, kref); 348a8fabb38SJuergen Gross schedule_work(&u->wq); 349a8fabb38SJuergen Gross } 350a8fabb38SJuergen Gross 351fd8aa909SJuergen Gross static struct xenbus_transaction_holder *xenbus_get_transaction( 352fd8aa909SJuergen Gross struct xenbus_file_priv *u, uint32_t tx_id) 353fd8aa909SJuergen Gross { 354fd8aa909SJuergen Gross struct xenbus_transaction_holder *trans; 355fd8aa909SJuergen Gross 356fd8aa909SJuergen Gross list_for_each_entry(trans, &u->transactions, list) 357fd8aa909SJuergen Gross if (trans->handle.id == tx_id) 358fd8aa909SJuergen Gross return trans; 359fd8aa909SJuergen Gross 360fd8aa909SJuergen Gross return NULL; 361fd8aa909SJuergen Gross } 362fd8aa909SJuergen Gross 363fd8aa909SJuergen Gross void xenbus_dev_queue_reply(struct xb_req_data *req) 364fd8aa909SJuergen Gross { 365fd8aa909SJuergen Gross struct xenbus_file_priv *u = req->par; 366fd8aa909SJuergen Gross struct xenbus_transaction_holder *trans = NULL; 367fd8aa909SJuergen Gross int rc; 368fd8aa909SJuergen Gross LIST_HEAD(staging_q); 369fd8aa909SJuergen Gross 370fd8aa909SJuergen Gross xs_request_exit(req); 371fd8aa909SJuergen Gross 372fd8aa909SJuergen Gross mutex_lock(&u->msgbuffer_mutex); 373fd8aa909SJuergen Gross 374fd8aa909SJuergen Gross if (req->type == XS_TRANSACTION_START) { 375fd8aa909SJuergen Gross trans = xenbus_get_transaction(u, 0); 376fd8aa909SJuergen Gross if (WARN_ON(!trans)) 377fd8aa909SJuergen Gross goto out; 378fd8aa909SJuergen Gross if (req->msg.type == XS_ERROR) { 379fd8aa909SJuergen Gross list_del(&trans->list); 380fd8aa909SJuergen Gross kfree(trans); 381fd8aa909SJuergen Gross } else { 382fd8aa909SJuergen Gross rc = kstrtou32(req->body, 10, &trans->handle.id); 383fd8aa909SJuergen Gross if (WARN_ON(rc)) 384fd8aa909SJuergen Gross goto out; 385fd8aa909SJuergen Gross } 3862a22ee6cSSimon Gaiser } else if (req->type == XS_TRANSACTION_END) { 387fd8aa909SJuergen Gross trans = xenbus_get_transaction(u, req->msg.tx_id); 388fd8aa909SJuergen Gross if (WARN_ON(!trans)) 389fd8aa909SJuergen Gross goto out; 390fd8aa909SJuergen Gross list_del(&trans->list); 391fd8aa909SJuergen Gross kfree(trans); 392fd8aa909SJuergen Gross } 393fd8aa909SJuergen Gross 394fd8aa909SJuergen Gross mutex_unlock(&u->msgbuffer_mutex); 395fd8aa909SJuergen Gross 396fd8aa909SJuergen Gross mutex_lock(&u->reply_mutex); 397fd8aa909SJuergen Gross rc = queue_reply(&staging_q, &req->msg, sizeof(req->msg)); 398fd8aa909SJuergen Gross if (!rc) 399fd8aa909SJuergen Gross rc = queue_reply(&staging_q, req->body, req->msg.len); 400fd8aa909SJuergen Gross if (!rc) { 401fd8aa909SJuergen Gross list_splice_tail(&staging_q, &u->read_buffers); 402fd8aa909SJuergen Gross wake_up(&u->read_waitq); 403fd8aa909SJuergen Gross } else { 404fd8aa909SJuergen Gross queue_cleanup(&staging_q); 405fd8aa909SJuergen Gross } 406fd8aa909SJuergen Gross mutex_unlock(&u->reply_mutex); 407fd8aa909SJuergen Gross 408fd8aa909SJuergen Gross kfree(req->body); 409fd8aa909SJuergen Gross kfree(req); 410fd8aa909SJuergen Gross 411fd8aa909SJuergen Gross kref_put(&u->kref, xenbus_file_free); 412fd8aa909SJuergen Gross 413fd8aa909SJuergen Gross return; 414fd8aa909SJuergen Gross 415fd8aa909SJuergen Gross out: 416fd8aa909SJuergen Gross mutex_unlock(&u->msgbuffer_mutex); 417fd8aa909SJuergen Gross } 418fd8aa909SJuergen Gross 4199a6161feSJuergen Gross static int xenbus_command_reply(struct xenbus_file_priv *u, 4209a6161feSJuergen Gross unsigned int msg_type, const char *reply) 4219a6161feSJuergen Gross { 4229a6161feSJuergen Gross struct { 4239a6161feSJuergen Gross struct xsd_sockmsg hdr; 424ebf04f33SSimon Gaiser char body[16]; 4259a6161feSJuergen Gross } msg; 4269a6161feSJuergen Gross int rc; 4279a6161feSJuergen Gross 4289a6161feSJuergen Gross msg.hdr = u->u.msg; 4299a6161feSJuergen Gross msg.hdr.type = msg_type; 4309a6161feSJuergen Gross msg.hdr.len = strlen(reply) + 1; 4319a6161feSJuergen Gross if (msg.hdr.len > sizeof(msg.body)) 4329a6161feSJuergen Gross return -E2BIG; 433ebf04f33SSimon Gaiser memcpy(&msg.body, reply, msg.hdr.len); 4349a6161feSJuergen Gross 4359a6161feSJuergen Gross mutex_lock(&u->reply_mutex); 4369a6161feSJuergen Gross rc = queue_reply(&u->read_buffers, &msg, sizeof(msg.hdr) + msg.hdr.len); 4379a6161feSJuergen Gross wake_up(&u->read_waitq); 4389a6161feSJuergen Gross mutex_unlock(&u->reply_mutex); 4399a6161feSJuergen Gross 440fd8aa909SJuergen Gross if (!rc) 441fd8aa909SJuergen Gross kref_put(&u->kref, xenbus_file_free); 442fd8aa909SJuergen Gross 4439a6161feSJuergen Gross return rc; 4449a6161feSJuergen Gross } 4459a6161feSJuergen Gross 4462fb3683eSBastian Blank static int xenbus_write_transaction(unsigned msg_type, 4472fb3683eSBastian Blank struct xenbus_file_priv *u) 4482fb3683eSBastian Blank { 4492fb3683eSBastian Blank int rc; 4502fb3683eSBastian Blank struct xenbus_transaction_holder *trans = NULL; 4518fe5ab41SSimon Gaiser struct { 4528fe5ab41SSimon Gaiser struct xsd_sockmsg hdr; 4538fe5ab41SSimon Gaiser char body[]; 4548fe5ab41SSimon Gaiser } *msg = (void *)u->u.buffer; 4552fb3683eSBastian Blank 4562fb3683eSBastian Blank if (msg_type == XS_TRANSACTION_START) { 457fd8aa909SJuergen Gross trans = kzalloc(sizeof(*trans), GFP_KERNEL); 4582fb3683eSBastian Blank if (!trans) { 4592fb3683eSBastian Blank rc = -ENOMEM; 4602fb3683eSBastian Blank goto out; 4612fb3683eSBastian Blank } 462d10e0cc1SRoss Lagerwall trans->generation_id = xb_dev_generation_id; 4632fb3683eSBastian Blank list_add(&trans->list, &u->transactions); 4648fe5ab41SSimon Gaiser } else if (msg->hdr.tx_id != 0 && 4658fe5ab41SSimon Gaiser !xenbus_get_transaction(u, msg->hdr.tx_id)) 466fd8aa909SJuergen Gross return xenbus_command_reply(u, XS_ERROR, "ENOENT"); 4678fe5ab41SSimon Gaiser else if (msg_type == XS_TRANSACTION_END && 4688fe5ab41SSimon Gaiser !(msg->hdr.len == 2 && 4698fe5ab41SSimon Gaiser (!strcmp(msg->body, "T") || !strcmp(msg->body, "F")))) 4708fe5ab41SSimon Gaiser return xenbus_command_reply(u, XS_ERROR, "EINVAL"); 471d10e0cc1SRoss Lagerwall else if (msg_type == XS_TRANSACTION_END) { 472d10e0cc1SRoss Lagerwall trans = xenbus_get_transaction(u, msg->hdr.tx_id); 473d10e0cc1SRoss Lagerwall if (trans && trans->generation_id != xb_dev_generation_id) { 474d10e0cc1SRoss Lagerwall list_del(&trans->list); 475d10e0cc1SRoss Lagerwall kfree(trans); 476d10e0cc1SRoss Lagerwall if (!strcmp(msg->body, "T")) 477d10e0cc1SRoss Lagerwall return xenbus_command_reply(u, XS_ERROR, 478d10e0cc1SRoss Lagerwall "EAGAIN"); 479d10e0cc1SRoss Lagerwall else 480d10e0cc1SRoss Lagerwall return xenbus_command_reply(u, 481d10e0cc1SRoss Lagerwall XS_TRANSACTION_END, 482d10e0cc1SRoss Lagerwall "OK"); 483d10e0cc1SRoss Lagerwall } 484d10e0cc1SRoss Lagerwall } 485fd8aa909SJuergen Gross 4868fe5ab41SSimon Gaiser rc = xenbus_dev_request_and_reply(&msg->hdr, u); 487ac4cde39SJan Beulich if (rc && trans) { 488ac4cde39SJan Beulich list_del(&trans->list); 4892fb3683eSBastian Blank kfree(trans); 490ac4cde39SJan Beulich } 4912fb3683eSBastian Blank 4922fb3683eSBastian Blank out: 4932fb3683eSBastian Blank return rc; 4942fb3683eSBastian Blank } 4952fb3683eSBastian Blank 4962fb3683eSBastian Blank static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u) 4972fb3683eSBastian Blank { 498e1e5b3ffSJan Beulich struct watch_adapter *watch; 4992fb3683eSBastian Blank char *path, *token; 5002fb3683eSBastian Blank int err, rc; 5012fb3683eSBastian Blank 5022fb3683eSBastian Blank path = u->u.buffer + sizeof(u->u.msg); 5032fb3683eSBastian Blank token = memchr(path, 0, u->u.msg.len); 5042fb3683eSBastian Blank if (token == NULL) { 5059a6161feSJuergen Gross rc = xenbus_command_reply(u, XS_ERROR, "EINVAL"); 5062fb3683eSBastian Blank goto out; 5072fb3683eSBastian Blank } 5082fb3683eSBastian Blank token++; 509a43a5ccdSJan Beulich if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) { 5109a6161feSJuergen Gross rc = xenbus_command_reply(u, XS_ERROR, "EINVAL"); 511a43a5ccdSJan Beulich goto out; 512a43a5ccdSJan Beulich } 5132fb3683eSBastian Blank 5142fb3683eSBastian Blank if (msg_type == XS_WATCH) { 5152fb3683eSBastian Blank watch = alloc_watch_adapter(path, token); 5162fb3683eSBastian Blank if (watch == NULL) { 5172fb3683eSBastian Blank rc = -ENOMEM; 5182fb3683eSBastian Blank goto out; 5192fb3683eSBastian Blank } 5202fb3683eSBastian Blank 5212fb3683eSBastian Blank watch->watch.callback = watch_fired; 5222fb3683eSBastian Blank watch->dev_data = u; 5232fb3683eSBastian Blank 5242fb3683eSBastian Blank err = register_xenbus_watch(&watch->watch); 5252fb3683eSBastian Blank if (err) { 5262fb3683eSBastian Blank free_watch_adapter(watch); 5272fb3683eSBastian Blank rc = err; 5282fb3683eSBastian Blank goto out; 5292fb3683eSBastian Blank } 5302fb3683eSBastian Blank list_add(&watch->list, &u->watches); 5312fb3683eSBastian Blank } else { 532e1e5b3ffSJan Beulich list_for_each_entry(watch, &u->watches, list) { 5332fb3683eSBastian Blank if (!strcmp(watch->token, token) && 5342fb3683eSBastian Blank !strcmp(watch->watch.node, path)) { 5352fb3683eSBastian Blank unregister_xenbus_watch(&watch->watch); 5362fb3683eSBastian Blank list_del(&watch->list); 5372fb3683eSBastian Blank free_watch_adapter(watch); 5382fb3683eSBastian Blank break; 5392fb3683eSBastian Blank } 5402fb3683eSBastian Blank } 5412fb3683eSBastian Blank } 5422fb3683eSBastian Blank 5432fb3683eSBastian Blank /* Success. Synthesize a reply to say all is OK. */ 5449a6161feSJuergen Gross rc = xenbus_command_reply(u, msg_type, "OK"); 5452fb3683eSBastian Blank 5462fb3683eSBastian Blank out: 5472fb3683eSBastian Blank return rc; 5482fb3683eSBastian Blank } 5492fb3683eSBastian Blank 5502fb3683eSBastian Blank static ssize_t xenbus_file_write(struct file *filp, 5512fb3683eSBastian Blank const char __user *ubuf, 5522fb3683eSBastian Blank size_t len, loff_t *ppos) 5532fb3683eSBastian Blank { 5542fb3683eSBastian Blank struct xenbus_file_priv *u = filp->private_data; 5552fb3683eSBastian Blank uint32_t msg_type; 5562fb3683eSBastian Blank int rc = len; 5572fb3683eSBastian Blank int ret; 5582fb3683eSBastian Blank 5592fb3683eSBastian Blank /* 5602fb3683eSBastian Blank * We're expecting usermode to be writing properly formed 5612fb3683eSBastian Blank * xenbus messages. If they write an incomplete message we 5622fb3683eSBastian Blank * buffer it up. Once it is complete, we act on it. 5632fb3683eSBastian Blank */ 5642fb3683eSBastian Blank 5652fb3683eSBastian Blank /* 5662fb3683eSBastian Blank * Make sure concurrent writers can't stomp all over each 5672fb3683eSBastian Blank * other's messages and make a mess of our partial message 5682fb3683eSBastian Blank * buffer. We don't make any attemppt to stop multiple 5692fb3683eSBastian Blank * writers from making a mess of each other's incomplete 5702fb3683eSBastian Blank * messages; we're just trying to guarantee our own internal 5712fb3683eSBastian Blank * consistency and make sure that single writes are handled 5722fb3683eSBastian Blank * atomically. 5732fb3683eSBastian Blank */ 5742fb3683eSBastian Blank mutex_lock(&u->msgbuffer_mutex); 5752fb3683eSBastian Blank 5762fb3683eSBastian Blank /* Get this out of the way early to avoid confusion */ 5772fb3683eSBastian Blank if (len == 0) 5782fb3683eSBastian Blank goto out; 5792fb3683eSBastian Blank 5802fb3683eSBastian Blank /* Can't write a xenbus message larger we can buffer */ 5811bcaba51SJan Beulich if (len > sizeof(u->u.buffer) - u->len) { 5822fb3683eSBastian Blank /* On error, dump existing buffer */ 5832fb3683eSBastian Blank u->len = 0; 5842fb3683eSBastian Blank rc = -EINVAL; 5852fb3683eSBastian Blank goto out; 5862fb3683eSBastian Blank } 5872fb3683eSBastian Blank 5882fb3683eSBastian Blank ret = copy_from_user(u->u.buffer + u->len, ubuf, len); 5892fb3683eSBastian Blank 5902fb3683eSBastian Blank if (ret != 0) { 5912fb3683eSBastian Blank rc = -EFAULT; 5922fb3683eSBastian Blank goto out; 5932fb3683eSBastian Blank } 5942fb3683eSBastian Blank 5952fb3683eSBastian Blank /* Deal with a partial copy. */ 5962fb3683eSBastian Blank len -= ret; 5972fb3683eSBastian Blank rc = len; 5982fb3683eSBastian Blank 5992fb3683eSBastian Blank u->len += len; 6002fb3683eSBastian Blank 6012fb3683eSBastian Blank /* Return if we haven't got a full message yet */ 6022fb3683eSBastian Blank if (u->len < sizeof(u->u.msg)) 6032fb3683eSBastian Blank goto out; /* not even the header yet */ 6042fb3683eSBastian Blank 6052fb3683eSBastian Blank /* If we're expecting a message that's larger than we can 6062fb3683eSBastian Blank possibly send, dump what we have and return an error. */ 6072fb3683eSBastian Blank if ((sizeof(u->u.msg) + u->u.msg.len) > sizeof(u->u.buffer)) { 6082fb3683eSBastian Blank rc = -E2BIG; 6092fb3683eSBastian Blank u->len = 0; 6102fb3683eSBastian Blank goto out; 6112fb3683eSBastian Blank } 6122fb3683eSBastian Blank 6132fb3683eSBastian Blank if (u->len < (sizeof(u->u.msg) + u->u.msg.len)) 6142fb3683eSBastian Blank goto out; /* incomplete data portion */ 6152fb3683eSBastian Blank 6162fb3683eSBastian Blank /* 6172fb3683eSBastian Blank * OK, now we have a complete message. Do something with it. 6182fb3683eSBastian Blank */ 6192fb3683eSBastian Blank 620fd8aa909SJuergen Gross kref_get(&u->kref); 621fd8aa909SJuergen Gross 6222fb3683eSBastian Blank msg_type = u->u.msg.type; 6232fb3683eSBastian Blank 6242fb3683eSBastian Blank switch (msg_type) { 6252fb3683eSBastian Blank case XS_WATCH: 6262fb3683eSBastian Blank case XS_UNWATCH: 6272fb3683eSBastian Blank /* (Un)Ask for some path to be watched for changes */ 6282fb3683eSBastian Blank ret = xenbus_write_watch(msg_type, u); 6292fb3683eSBastian Blank break; 6302fb3683eSBastian Blank 6312fb3683eSBastian Blank default: 6322fb3683eSBastian Blank /* Send out a transaction */ 6332fb3683eSBastian Blank ret = xenbus_write_transaction(msg_type, u); 6342fb3683eSBastian Blank break; 6352fb3683eSBastian Blank } 636fd8aa909SJuergen Gross if (ret != 0) { 6372fb3683eSBastian Blank rc = ret; 638fd8aa909SJuergen Gross kref_put(&u->kref, xenbus_file_free); 639fd8aa909SJuergen Gross } 6402fb3683eSBastian Blank 6412fb3683eSBastian Blank /* Buffered message consumed */ 6422fb3683eSBastian Blank u->len = 0; 6432fb3683eSBastian Blank 6442fb3683eSBastian Blank out: 6452fb3683eSBastian Blank mutex_unlock(&u->msgbuffer_mutex); 6462fb3683eSBastian Blank return rc; 6472fb3683eSBastian Blank } 6482fb3683eSBastian Blank 6492fb3683eSBastian Blank static int xenbus_file_open(struct inode *inode, struct file *filp) 6502fb3683eSBastian Blank { 6512fb3683eSBastian Blank struct xenbus_file_priv *u; 6522fb3683eSBastian Blank 6532fb3683eSBastian Blank if (xen_store_evtchn == 0) 6542fb3683eSBastian Blank return -ENOENT; 6552fb3683eSBastian Blank 65610dce8afSKirill Smelkov stream_open(inode, filp); 657581d21a2SDavid Vrabel 6582fb3683eSBastian Blank u = kzalloc(sizeof(*u), GFP_KERNEL); 6592fb3683eSBastian Blank if (u == NULL) 6602fb3683eSBastian Blank return -ENOMEM; 6612fb3683eSBastian Blank 662fd8aa909SJuergen Gross kref_init(&u->kref); 663fd8aa909SJuergen Gross 6642fb3683eSBastian Blank INIT_LIST_HEAD(&u->transactions); 6652fb3683eSBastian Blank INIT_LIST_HEAD(&u->watches); 6662fb3683eSBastian Blank INIT_LIST_HEAD(&u->read_buffers); 6672fb3683eSBastian Blank init_waitqueue_head(&u->read_waitq); 668a8fabb38SJuergen Gross INIT_WORK(&u->wq, xenbus_worker); 6692fb3683eSBastian Blank 6702fb3683eSBastian Blank mutex_init(&u->reply_mutex); 6712fb3683eSBastian Blank mutex_init(&u->msgbuffer_mutex); 6722fb3683eSBastian Blank 6732fb3683eSBastian Blank filp->private_data = u; 6742fb3683eSBastian Blank 6752fb3683eSBastian Blank return 0; 6762fb3683eSBastian Blank } 6772fb3683eSBastian Blank 6782fb3683eSBastian Blank static int xenbus_file_release(struct inode *inode, struct file *filp) 6792fb3683eSBastian Blank { 6802fb3683eSBastian Blank struct xenbus_file_priv *u = filp->private_data; 6812fb3683eSBastian Blank 682fd8aa909SJuergen Gross kref_put(&u->kref, xenbus_file_free); 6832fb3683eSBastian Blank 6842fb3683eSBastian Blank return 0; 6852fb3683eSBastian Blank } 6862fb3683eSBastian Blank 687afc9a42bSAl Viro static __poll_t xenbus_file_poll(struct file *file, poll_table *wait) 6882fb3683eSBastian Blank { 6892fb3683eSBastian Blank struct xenbus_file_priv *u = file->private_data; 6902fb3683eSBastian Blank 6912fb3683eSBastian Blank poll_wait(file, &u->read_waitq, wait); 6922fb3683eSBastian Blank if (!list_empty(&u->read_buffers)) 693a9a08845SLinus Torvalds return EPOLLIN | EPOLLRDNORM; 6942fb3683eSBastian Blank return 0; 6952fb3683eSBastian Blank } 6962fb3683eSBastian Blank 6972fb3683eSBastian Blank const struct file_operations xen_xenbus_fops = { 6982fb3683eSBastian Blank .read = xenbus_file_read, 6992fb3683eSBastian Blank .write = xenbus_file_write, 7002fb3683eSBastian Blank .open = xenbus_file_open, 7012fb3683eSBastian Blank .release = xenbus_file_release, 7022fb3683eSBastian Blank .poll = xenbus_file_poll, 7032fb3683eSBastian Blank .llseek = no_llseek, 7042fb3683eSBastian Blank }; 7052fb3683eSBastian Blank EXPORT_SYMBOL_GPL(xen_xenbus_fops); 7062fb3683eSBastian Blank 7072fb3683eSBastian Blank static struct miscdevice xenbus_dev = { 7082fb3683eSBastian Blank .minor = MISC_DYNAMIC_MINOR, 7092fb3683eSBastian Blank .name = "xen/xenbus", 7102fb3683eSBastian Blank .fops = &xen_xenbus_fops, 7112fb3683eSBastian Blank }; 7122fb3683eSBastian Blank 7132fb3683eSBastian Blank static int __init xenbus_init(void) 7142fb3683eSBastian Blank { 7152fb3683eSBastian Blank int err; 7162fb3683eSBastian Blank 7172fb3683eSBastian Blank if (!xen_domain()) 7182fb3683eSBastian Blank return -ENODEV; 7192fb3683eSBastian Blank 7202fb3683eSBastian Blank err = misc_register(&xenbus_dev); 7212fb3683eSBastian Blank if (err) 722283c0972SJoe Perches pr_err("Could not register xenbus frontend device\n"); 7232fb3683eSBastian Blank return err; 7242fb3683eSBastian Blank } 725ab1241a1SPaul Gortmaker device_initcall(xenbus_init); 726