ia64/linux-2.6.18-xen.hg

view drivers/bluetooth/hci_vhci.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 *
3 * Bluetooth virtual HCI driver
4 *
5 * Copyright (C) 2000-2001 Qualcomm Incorporated
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
26 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/init.h>
30 #include <linux/slab.h>
31 #include <linux/types.h>
32 #include <linux/errno.h>
33 #include <linux/sched.h>
34 #include <linux/poll.h>
36 #include <linux/skbuff.h>
37 #include <linux/miscdevice.h>
39 #include <net/bluetooth/bluetooth.h>
40 #include <net/bluetooth/hci_core.h>
42 #ifndef CONFIG_BT_HCIVHCI_DEBUG
43 #undef BT_DBG
44 #define BT_DBG(D...)
45 #endif
47 #define VERSION "1.2"
49 static int minor = MISC_DYNAMIC_MINOR;
51 struct vhci_data {
52 struct hci_dev *hdev;
54 unsigned long flags;
56 wait_queue_head_t read_wait;
57 struct sk_buff_head readq;
59 struct fasync_struct *fasync;
60 };
62 #define VHCI_FASYNC 0x0010
64 static struct miscdevice vhci_miscdev;
66 static int vhci_open_dev(struct hci_dev *hdev)
67 {
68 set_bit(HCI_RUNNING, &hdev->flags);
70 return 0;
71 }
73 static int vhci_close_dev(struct hci_dev *hdev)
74 {
75 struct vhci_data *vhci = hdev->driver_data;
77 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
78 return 0;
80 skb_queue_purge(&vhci->readq);
82 return 0;
83 }
85 static int vhci_flush(struct hci_dev *hdev)
86 {
87 struct vhci_data *vhci = hdev->driver_data;
89 skb_queue_purge(&vhci->readq);
91 return 0;
92 }
94 static int vhci_send_frame(struct sk_buff *skb)
95 {
96 struct hci_dev* hdev = (struct hci_dev *) skb->dev;
97 struct vhci_data *vhci;
99 if (!hdev) {
100 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
101 return -ENODEV;
102 }
104 if (!test_bit(HCI_RUNNING, &hdev->flags))
105 return -EBUSY;
107 vhci = hdev->driver_data;
109 memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
110 skb_queue_tail(&vhci->readq, skb);
112 if (vhci->flags & VHCI_FASYNC)
113 kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
115 wake_up_interruptible(&vhci->read_wait);
117 return 0;
118 }
120 static void vhci_destruct(struct hci_dev *hdev)
121 {
122 kfree(hdev->driver_data);
123 }
125 static inline ssize_t vhci_get_user(struct vhci_data *vhci,
126 const char __user *buf, size_t count)
127 {
128 struct sk_buff *skb;
130 if (count > HCI_MAX_FRAME_SIZE)
131 return -EINVAL;
133 skb = bt_skb_alloc(count, GFP_KERNEL);
134 if (!skb)
135 return -ENOMEM;
137 if (copy_from_user(skb_put(skb, count), buf, count)) {
138 kfree_skb(skb);
139 return -EFAULT;
140 }
142 skb->dev = (void *) vhci->hdev;
143 bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
144 skb_pull(skb, 1);
146 hci_recv_frame(skb);
148 return count;
149 }
151 static inline ssize_t vhci_put_user(struct vhci_data *vhci,
152 struct sk_buff *skb, char __user *buf, int count)
153 {
154 char __user *ptr = buf;
155 int len, total = 0;
157 len = min_t(unsigned int, skb->len, count);
159 if (copy_to_user(ptr, skb->data, len))
160 return -EFAULT;
162 total += len;
164 vhci->hdev->stat.byte_tx += len;
166 switch (bt_cb(skb)->pkt_type) {
167 case HCI_COMMAND_PKT:
168 vhci->hdev->stat.cmd_tx++;
169 break;
171 case HCI_ACLDATA_PKT:
172 vhci->hdev->stat.acl_tx++;
173 break;
175 case HCI_SCODATA_PKT:
176 vhci->hdev->stat.cmd_tx++;
177 break;
178 };
180 return total;
181 }
183 static loff_t vhci_llseek(struct file * file, loff_t offset, int origin)
184 {
185 return -ESPIPE;
186 }
188 static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
189 {
190 DECLARE_WAITQUEUE(wait, current);
191 struct vhci_data *vhci = file->private_data;
192 struct sk_buff *skb;
193 ssize_t ret = 0;
195 add_wait_queue(&vhci->read_wait, &wait);
196 while (count) {
197 set_current_state(TASK_INTERRUPTIBLE);
199 skb = skb_dequeue(&vhci->readq);
200 if (!skb) {
201 if (file->f_flags & O_NONBLOCK) {
202 ret = -EAGAIN;
203 break;
204 }
206 if (signal_pending(current)) {
207 ret = -ERESTARTSYS;
208 break;
209 }
211 schedule();
212 continue;
213 }
215 if (access_ok(VERIFY_WRITE, buf, count))
216 ret = vhci_put_user(vhci, skb, buf, count);
217 else
218 ret = -EFAULT;
220 kfree_skb(skb);
221 break;
222 }
223 set_current_state(TASK_RUNNING);
224 remove_wait_queue(&vhci->read_wait, &wait);
226 return ret;
227 }
229 static ssize_t vhci_write(struct file *file,
230 const char __user *buf, size_t count, loff_t *pos)
231 {
232 struct vhci_data *vhci = file->private_data;
234 if (!access_ok(VERIFY_READ, buf, count))
235 return -EFAULT;
237 return vhci_get_user(vhci, buf, count);
238 }
240 static unsigned int vhci_poll(struct file *file, poll_table *wait)
241 {
242 struct vhci_data *vhci = file->private_data;
244 poll_wait(file, &vhci->read_wait, wait);
246 if (!skb_queue_empty(&vhci->readq))
247 return POLLIN | POLLRDNORM;
249 return POLLOUT | POLLWRNORM;
250 }
252 static int vhci_ioctl(struct inode *inode, struct file *file,
253 unsigned int cmd, unsigned long arg)
254 {
255 return -EINVAL;
256 }
258 static int vhci_open(struct inode *inode, struct file *file)
259 {
260 struct vhci_data *vhci;
261 struct hci_dev *hdev;
263 vhci = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
264 if (!vhci)
265 return -ENOMEM;
267 skb_queue_head_init(&vhci->readq);
268 init_waitqueue_head(&vhci->read_wait);
270 hdev = hci_alloc_dev();
271 if (!hdev) {
272 kfree(vhci);
273 return -ENOMEM;
274 }
276 vhci->hdev = hdev;
278 hdev->type = HCI_VHCI;
279 hdev->driver_data = vhci;
281 hdev->open = vhci_open_dev;
282 hdev->close = vhci_close_dev;
283 hdev->flush = vhci_flush;
284 hdev->send = vhci_send_frame;
285 hdev->destruct = vhci_destruct;
287 hdev->owner = THIS_MODULE;
289 if (hci_register_dev(hdev) < 0) {
290 BT_ERR("Can't register HCI device");
291 kfree(vhci);
292 hci_free_dev(hdev);
293 return -EBUSY;
294 }
296 file->private_data = vhci;
298 return nonseekable_open(inode, file);
299 }
301 static int vhci_release(struct inode *inode, struct file *file)
302 {
303 struct vhci_data *vhci = file->private_data;
304 struct hci_dev *hdev = vhci->hdev;
306 if (hci_unregister_dev(hdev) < 0) {
307 BT_ERR("Can't unregister HCI device %s", hdev->name);
308 }
310 hci_free_dev(hdev);
312 file->private_data = NULL;
314 return 0;
315 }
317 static int vhci_fasync(int fd, struct file *file, int on)
318 {
319 struct vhci_data *vhci = file->private_data;
320 int err;
322 err = fasync_helper(fd, file, on, &vhci->fasync);
323 if (err < 0)
324 return err;
326 if (on)
327 vhci->flags |= VHCI_FASYNC;
328 else
329 vhci->flags &= ~VHCI_FASYNC;
331 return 0;
332 }
334 static struct file_operations vhci_fops = {
335 .owner = THIS_MODULE,
336 .llseek = vhci_llseek,
337 .read = vhci_read,
338 .write = vhci_write,
339 .poll = vhci_poll,
340 .ioctl = vhci_ioctl,
341 .open = vhci_open,
342 .release = vhci_release,
343 .fasync = vhci_fasync,
344 };
346 static struct miscdevice vhci_miscdev= {
347 .name = "vhci",
348 .fops = &vhci_fops,
349 };
351 static int __init vhci_init(void)
352 {
353 BT_INFO("Virtual HCI driver ver %s", VERSION);
355 vhci_miscdev.minor = minor;
357 if (misc_register(&vhci_miscdev) < 0) {
358 BT_ERR("Can't register misc device with minor %d", minor);
359 return -EIO;
360 }
362 return 0;
363 }
365 static void __exit vhci_exit(void)
366 {
367 if (misc_deregister(&vhci_miscdev) < 0)
368 BT_ERR("Can't unregister misc device with minor %d", minor);
369 }
371 module_init(vhci_init);
372 module_exit(vhci_exit);
374 module_param(minor, int, 0444);
375 MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
377 MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
378 MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
379 MODULE_VERSION(VERSION);
380 MODULE_LICENSE("GPL");