ia64/linux-2.6.18-xen.hg

view drivers/md/dm-snap.h @ 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 * dm-snapshot.c
3 *
4 * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
5 *
6 * This file is released under the GPL.
7 */
9 #ifndef DM_SNAPSHOT_H
10 #define DM_SNAPSHOT_H
12 #include "dm.h"
13 #include <linux/blkdev.h>
15 struct exception_table {
16 uint32_t hash_mask;
17 struct list_head *table;
18 };
20 /*
21 * The snapshot code deals with largish chunks of the disk at a
22 * time. Typically 64k - 256k.
23 */
24 /* FIXME: can we get away with limiting these to a uint32_t ? */
25 typedef sector_t chunk_t;
27 /*
28 * An exception is used where an old chunk of data has been
29 * replaced by a new one.
30 */
31 struct exception {
32 struct list_head hash_list;
34 chunk_t old_chunk;
35 chunk_t new_chunk;
36 };
38 /*
39 * Abstraction to handle the meta/layout of exception stores (the
40 * COW device).
41 */
42 struct exception_store {
44 /*
45 * Destroys this object when you've finished with it.
46 */
47 void (*destroy) (struct exception_store *store);
49 /*
50 * The target shouldn't read the COW device until this is
51 * called.
52 */
53 int (*read_metadata) (struct exception_store *store);
55 /*
56 * Find somewhere to store the next exception.
57 */
58 int (*prepare_exception) (struct exception_store *store,
59 struct exception *e);
61 /*
62 * Update the metadata with this exception.
63 */
64 void (*commit_exception) (struct exception_store *store,
65 struct exception *e,
66 void (*callback) (void *, int success),
67 void *callback_context);
69 /*
70 * The snapshot is invalid, note this in the metadata.
71 */
72 void (*drop_snapshot) (struct exception_store *store);
74 /*
75 * Return how full the snapshot is.
76 */
77 void (*fraction_full) (struct exception_store *store,
78 sector_t *numerator,
79 sector_t *denominator);
81 struct dm_snapshot *snap;
82 void *context;
83 };
85 struct dm_snapshot {
86 struct rw_semaphore lock;
87 struct dm_table *table;
89 struct dm_dev *origin;
90 struct dm_dev *cow;
92 /* List of snapshots per Origin */
93 struct list_head list;
95 /* Size of data blocks saved - must be a power of 2 */
96 chunk_t chunk_size;
97 chunk_t chunk_mask;
98 chunk_t chunk_shift;
100 /* You can't use a snapshot if this is 0 (e.g. if full) */
101 int valid;
103 /* Origin writes don't trigger exceptions until this is set */
104 int active;
106 /* Used for display of table */
107 char type;
109 /* The last percentage we notified */
110 int last_percent;
112 struct exception_table pending;
113 struct exception_table complete;
115 /* The on disk metadata handler */
116 struct exception_store store;
118 struct kcopyd_client *kcopyd_client;
119 };
121 /*
122 * Used by the exception stores to load exceptions hen
123 * initialising.
124 */
125 int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new);
127 /*
128 * Constructor and destructor for the default persistent
129 * store.
130 */
131 int dm_create_persistent(struct exception_store *store, uint32_t chunk_size);
133 int dm_create_transient(struct exception_store *store,
134 struct dm_snapshot *s, int blocksize);
136 /*
137 * Return the number of sectors in the device.
138 */
139 static inline sector_t get_dev_size(struct block_device *bdev)
140 {
141 return bdev->bd_inode->i_size >> SECTOR_SHIFT;
142 }
144 static inline chunk_t sector_to_chunk(struct dm_snapshot *s, sector_t sector)
145 {
146 return (sector & ~s->chunk_mask) >> s->chunk_shift;
147 }
149 static inline sector_t chunk_to_sector(struct dm_snapshot *s, chunk_t chunk)
150 {
151 return chunk << s->chunk_shift;
152 }
154 static inline int bdev_equal(struct block_device *lhs, struct block_device *rhs)
155 {
156 /*
157 * There is only ever one instance of a particular block
158 * device so we can compare pointers safely.
159 */
160 return lhs == rhs;
161 }
163 #endif