Updated from Linux LTS 3.10.24 to 3.10.25
This commit is contained in:
@@ -1660,6 +1660,11 @@ static int __init dm_bufio_init(void)
|
||||
{
|
||||
__u64 mem;
|
||||
|
||||
dm_bufio_allocated_kmem_cache = 0;
|
||||
dm_bufio_allocated_get_free_pages = 0;
|
||||
dm_bufio_allocated_vmalloc = 0;
|
||||
dm_bufio_current_allocated = 0;
|
||||
|
||||
memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
|
||||
memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
struct delay_c {
|
||||
struct timer_list delay_timer;
|
||||
struct mutex timer_lock;
|
||||
struct workqueue_struct *kdelayd_wq;
|
||||
struct work_struct flush_expired_bios;
|
||||
struct list_head delayed_bios;
|
||||
atomic_t may_delay;
|
||||
@@ -45,14 +46,13 @@ struct dm_delay_info {
|
||||
|
||||
static DEFINE_MUTEX(delayed_bios_lock);
|
||||
|
||||
static struct workqueue_struct *kdelayd_wq;
|
||||
static struct kmem_cache *delayed_cache;
|
||||
|
||||
static void handle_delayed_timer(unsigned long data)
|
||||
{
|
||||
struct delay_c *dc = (struct delay_c *)data;
|
||||
|
||||
queue_work(kdelayd_wq, &dc->flush_expired_bios);
|
||||
queue_work(dc->kdelayd_wq, &dc->flush_expired_bios);
|
||||
}
|
||||
|
||||
static void queue_timeout(struct delay_c *dc, unsigned long expires)
|
||||
@@ -191,6 +191,12 @@ out:
|
||||
goto bad_dev_write;
|
||||
}
|
||||
|
||||
dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
|
||||
if (!dc->kdelayd_wq) {
|
||||
DMERR("Couldn't start kdelayd");
|
||||
goto bad_queue;
|
||||
}
|
||||
|
||||
setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
|
||||
|
||||
INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
|
||||
@@ -203,6 +209,8 @@ out:
|
||||
ti->private = dc;
|
||||
return 0;
|
||||
|
||||
bad_queue:
|
||||
mempool_destroy(dc->delayed_pool);
|
||||
bad_dev_write:
|
||||
if (dc->dev_write)
|
||||
dm_put_device(ti, dc->dev_write);
|
||||
@@ -217,7 +225,7 @@ static void delay_dtr(struct dm_target *ti)
|
||||
{
|
||||
struct delay_c *dc = ti->private;
|
||||
|
||||
flush_workqueue(kdelayd_wq);
|
||||
destroy_workqueue(dc->kdelayd_wq);
|
||||
|
||||
dm_put_device(ti, dc->dev_read);
|
||||
|
||||
@@ -350,12 +358,6 @@ static int __init dm_delay_init(void)
|
||||
{
|
||||
int r = -ENOMEM;
|
||||
|
||||
kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
|
||||
if (!kdelayd_wq) {
|
||||
DMERR("Couldn't start kdelayd");
|
||||
goto bad_queue;
|
||||
}
|
||||
|
||||
delayed_cache = KMEM_CACHE(dm_delay_info, 0);
|
||||
if (!delayed_cache) {
|
||||
DMERR("Couldn't create delayed bio cache.");
|
||||
@@ -373,8 +375,6 @@ static int __init dm_delay_init(void)
|
||||
bad_register:
|
||||
kmem_cache_destroy(delayed_cache);
|
||||
bad_memcache:
|
||||
destroy_workqueue(kdelayd_wq);
|
||||
bad_queue:
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -382,7 +382,6 @@ static void __exit dm_delay_exit(void)
|
||||
{
|
||||
dm_unregister_target(&delay_target);
|
||||
kmem_cache_destroy(delayed_cache);
|
||||
destroy_workqueue(kdelayd_wq);
|
||||
}
|
||||
|
||||
/* Module hooks */
|
||||
|
||||
@@ -66,6 +66,18 @@ struct dm_snapshot {
|
||||
|
||||
atomic_t pending_exceptions_count;
|
||||
|
||||
/* Protected by "lock" */
|
||||
sector_t exception_start_sequence;
|
||||
|
||||
/* Protected by kcopyd single-threaded callback */
|
||||
sector_t exception_complete_sequence;
|
||||
|
||||
/*
|
||||
* A list of pending exceptions that completed out of order.
|
||||
* Protected by kcopyd single-threaded callback.
|
||||
*/
|
||||
struct list_head out_of_order_list;
|
||||
|
||||
mempool_t *pending_pool;
|
||||
|
||||
struct dm_exception_table pending;
|
||||
@@ -173,6 +185,14 @@ struct dm_snap_pending_exception {
|
||||
*/
|
||||
int started;
|
||||
|
||||
/* There was copying error. */
|
||||
int copy_error;
|
||||
|
||||
/* A sequence number, it is used for in-order completion. */
|
||||
sector_t exception_sequence;
|
||||
|
||||
struct list_head out_of_order_entry;
|
||||
|
||||
/*
|
||||
* For writing a complete chunk, bypassing the copy.
|
||||
*/
|
||||
@@ -1094,6 +1114,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||||
s->valid = 1;
|
||||
s->active = 0;
|
||||
atomic_set(&s->pending_exceptions_count, 0);
|
||||
s->exception_start_sequence = 0;
|
||||
s->exception_complete_sequence = 0;
|
||||
INIT_LIST_HEAD(&s->out_of_order_list);
|
||||
init_rwsem(&s->lock);
|
||||
INIT_LIST_HEAD(&s->list);
|
||||
spin_lock_init(&s->pe_lock);
|
||||
@@ -1443,6 +1466,19 @@ static void commit_callback(void *context, int success)
|
||||
pending_complete(pe, success);
|
||||
}
|
||||
|
||||
static void complete_exception(struct dm_snap_pending_exception *pe)
|
||||
{
|
||||
struct dm_snapshot *s = pe->snap;
|
||||
|
||||
if (unlikely(pe->copy_error))
|
||||
pending_complete(pe, 0);
|
||||
|
||||
else
|
||||
/* Update the metadata if we are persistent */
|
||||
s->store->type->commit_exception(s->store, &pe->e,
|
||||
commit_callback, pe);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the copy I/O has finished. kcopyd actually runs
|
||||
* this code so don't block.
|
||||
@@ -1452,13 +1488,32 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
|
||||
struct dm_snap_pending_exception *pe = context;
|
||||
struct dm_snapshot *s = pe->snap;
|
||||
|
||||
if (read_err || write_err)
|
||||
pending_complete(pe, 0);
|
||||
pe->copy_error = read_err || write_err;
|
||||
|
||||
else
|
||||
/* Update the metadata if we are persistent */
|
||||
s->store->type->commit_exception(s->store, &pe->e,
|
||||
commit_callback, pe);
|
||||
if (pe->exception_sequence == s->exception_complete_sequence) {
|
||||
s->exception_complete_sequence++;
|
||||
complete_exception(pe);
|
||||
|
||||
while (!list_empty(&s->out_of_order_list)) {
|
||||
pe = list_entry(s->out_of_order_list.next,
|
||||
struct dm_snap_pending_exception, out_of_order_entry);
|
||||
if (pe->exception_sequence != s->exception_complete_sequence)
|
||||
break;
|
||||
s->exception_complete_sequence++;
|
||||
list_del(&pe->out_of_order_entry);
|
||||
complete_exception(pe);
|
||||
}
|
||||
} else {
|
||||
struct list_head *lh;
|
||||
struct dm_snap_pending_exception *pe2;
|
||||
|
||||
list_for_each_prev(lh, &s->out_of_order_list) {
|
||||
pe2 = list_entry(lh, struct dm_snap_pending_exception, out_of_order_entry);
|
||||
if (pe2->exception_sequence < pe->exception_sequence)
|
||||
break;
|
||||
}
|
||||
list_add(&pe->out_of_order_entry, lh);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1553,6 +1608,8 @@ __find_pending_exception(struct dm_snapshot *s,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pe->exception_sequence = s->exception_start_sequence++;
|
||||
|
||||
dm_insert_exception(&s->pending, &pe->e);
|
||||
|
||||
return pe;
|
||||
@@ -2192,7 +2249,7 @@ static struct target_type origin_target = {
|
||||
|
||||
static struct target_type snapshot_target = {
|
||||
.name = "snapshot",
|
||||
.version = {1, 11, 1},
|
||||
.version = {1, 12, 0},
|
||||
.module = THIS_MODULE,
|
||||
.ctr = snapshot_ctr,
|
||||
.dtr = snapshot_dtr,
|
||||
|
||||
@@ -216,6 +216,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
|
||||
|
||||
num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
|
||||
|
||||
if (!num_targets) {
|
||||
kfree(t);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (alloc_targets(t, num_targets)) {
|
||||
kfree(t);
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -640,7 +640,9 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
|
||||
*/
|
||||
r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
|
||||
if (r) {
|
||||
DMERR_LIMIT("dm_thin_insert_block() failed");
|
||||
DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d",
|
||||
dm_device_name(pool->pool_md), r);
|
||||
set_pool_mode(pool, PM_READ_ONLY);
|
||||
cell_error(pool, m->cell);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -317,8 +317,16 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
|
||||
* The shadow op will often be a noop. Only insert if it really
|
||||
* copied data.
|
||||
*/
|
||||
if (dm_block_location(*block) != b)
|
||||
if (dm_block_location(*block) != b) {
|
||||
/*
|
||||
* dm_tm_shadow_block will have already decremented the old
|
||||
* block, but it is still referenced by the btree. We
|
||||
* increment to stop the insert decrementing it below zero
|
||||
* when overwriting the old value.
|
||||
*/
|
||||
dm_tm_inc(info->btree_info.tm, b);
|
||||
r = insert_ablock(info, index, *block, root);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -384,12 +384,16 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
|
||||
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
|
||||
|
||||
int r = sm_metadata_new_block_(sm, b);
|
||||
if (r)
|
||||
if (r) {
|
||||
DMERR("unable to allocate new metadata block");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sm_metadata_get_nr_free(sm, &count);
|
||||
if (r)
|
||||
if (r) {
|
||||
DMERR("couldn't get free block count");
|
||||
return r;
|
||||
}
|
||||
|
||||
check_threshold(&smm->threshold, count);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user