projects
/
platform
/
adaptation
/
renesas_rcar
/
renesas_kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
dm snapshot: split out exception store implementations
[platform/adaptation/renesas_rcar/renesas_kernel.git]
/
drivers
/
md
/
dm-snap.c
diff --git
a/drivers/md/dm-snap.c
b/drivers/md/dm-snap.c
index
b2d9d1a
..
018b567
100644
(file)
--- a/
drivers/md/dm-snap.c
+++ b/
drivers/md/dm-snap.c
@@
-9,6
+9,7
@@
#include <linux/blkdev.h>
#include <linux/ctype.h>
#include <linux/device-mapper.h>
#include <linux/blkdev.h>
#include <linux/ctype.h>
#include <linux/device-mapper.h>
+#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
@@
-20,6
+21,7
@@
#include <linux/log2.h>
#include <linux/dm-kcopyd.h>
#include <linux/log2.h>
#include <linux/dm-kcopyd.h>
+#include "dm-exception-store.h"
#include "dm-snap.h"
#include "dm-bio-list.h"
#include "dm-snap.h"
#include "dm-bio-list.h"
@@
-229,19
+231,21
@@
static void __insert_origin(struct origin *o)
*/
static int register_snapshot(struct dm_snapshot *snap)
{
*/
static int register_snapshot(struct dm_snapshot *snap)
{
- struct origin *o;
+ struct origin *o
, *new_o
;
struct block_device *bdev = snap->origin->bdev;
struct block_device *bdev = snap->origin->bdev;
+ new_o = kmalloc(sizeof(*new_o), GFP_KERNEL);
+ if (!new_o)
+ return -ENOMEM;
+
down_write(&_origins_lock);
o = __lookup_origin(bdev);
down_write(&_origins_lock);
o = __lookup_origin(bdev);
- if (!o) {
+ if (o)
+ kfree(new_o);
+ else {
/* New origin */
/* New origin */
- o = kmalloc(sizeof(*o), GFP_KERNEL);
- if (!o) {
- up_write(&_origins_lock);
- return -ENOMEM;
- }
+ o = new_o;
/* Initialise the struct */
INIT_LIST_HEAD(&o->snapshots);
/* Initialise the struct */
INIT_LIST_HEAD(&o->snapshots);
@@
-368,6
+372,7
@@
static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps
struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
GFP_NOIO);
struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
GFP_NOIO);
+ atomic_inc(&s->pending_exceptions_count);
pe->snap = s;
return pe;
pe->snap = s;
return pe;
@@
-375,7
+380,11
@@
static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps
static void free_pending_exception(struct dm_snap_pending_exception *pe)
{
static void free_pending_exception(struct dm_snap_pending_exception *pe)
{
- mempool_free(pe, pe->snap->pending_pool);
+ struct dm_snapshot *s = pe->snap;
+
+ mempool_free(pe, s->pending_pool);
+ smp_mb__before_atomic_dec();
+ atomic_dec(&s->pending_exceptions_count);
}
static void insert_completed_exception(struct dm_snapshot *s,
}
static void insert_completed_exception(struct dm_snapshot *s,
@@
-600,6
+609,7
@@
static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
s->valid = 1;
s->active = 0;
s->valid = 1;
s->active = 0;
+ atomic_set(&s->pending_exceptions_count, 0);
init_rwsem(&s->lock);
spin_lock_init(&s->pe_lock);
s->ti = ti;
init_rwsem(&s->lock);
spin_lock_init(&s->pe_lock);
s->ti = ti;
@@
-726,6
+736,14
@@
static void snapshot_dtr(struct dm_target *ti)
/* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s);
/* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s);
+ while (atomic_read(&s->pending_exceptions_count))
+ msleep(1);
+ /*
+ * Ensure instructions in mempool_destroy aren't reordered
+ * before atomic_read.
+ */
+ smp_mb();
+
#ifdef CONFIG_DM_DEBUG
for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
#ifdef CONFIG_DM_DEBUG
for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
@@
-872,10
+890,10
@@
static void pending_complete(struct dm_snap_pending_exception *pe, int success)
/*
* Check for conflicting reads. This is extremely improbable,
/*
* Check for conflicting reads. This is extremely improbable,
- * so
yield(
) is sufficient and there is no need for a wait queue.
+ * so
msleep(1
) is sufficient and there is no need for a wait queue.
*/
while (__chunk_is_tracked(s, pe->e.old_chunk))
*/
while (__chunk_is_tracked(s, pe->e.old_chunk))
-
yield(
);
+
msleep(1
);
/*
* Add a proper exception, and remove the
/*
* Add a proper exception, and remove the
@@
-1388,6
+1406,12
@@
static int __init dm_snapshot_init(void)
{
int r;
{
int r;
+ r = dm_exception_store_init();
+ if (r) {
+ DMERR("Failed to initialize exception stores");
+ return r;
+ }
+
r = dm_register_target(&snapshot_target);
if (r) {
DMERR("snapshot target register failed %d", r);
r = dm_register_target(&snapshot_target);
if (r) {
DMERR("snapshot target register failed %d", r);
@@
-1436,39
+1460,34
@@
static int __init dm_snapshot_init(void)
return 0;
return 0;
-
bad_pending_pool:
+bad_pending_pool:
kmem_cache_destroy(tracked_chunk_cache);
kmem_cache_destroy(tracked_chunk_cache);
-
bad5:
+bad5:
kmem_cache_destroy(pending_cache);
kmem_cache_destroy(pending_cache);
-
bad4:
+bad4:
kmem_cache_destroy(exception_cache);
kmem_cache_destroy(exception_cache);
-
bad3:
+bad3:
exit_origin_hash();
exit_origin_hash();
-
bad2:
+bad2:
dm_unregister_target(&origin_target);
dm_unregister_target(&origin_target);
-
bad1:
+bad1:
dm_unregister_target(&snapshot_target);
return r;
}
static void __exit dm_snapshot_exit(void)
{
dm_unregister_target(&snapshot_target);
return r;
}
static void __exit dm_snapshot_exit(void)
{
- int r;
-
destroy_workqueue(ksnapd);
destroy_workqueue(ksnapd);
- r = dm_unregister_target(&snapshot_target);
- if (r)
- DMERR("snapshot unregister failed %d", r);
-
- r = dm_unregister_target(&origin_target);
- if (r)
- DMERR("origin unregister failed %d", r);
+ dm_unregister_target(&snapshot_target);
+ dm_unregister_target(&origin_target);
exit_origin_hash();
kmem_cache_destroy(pending_cache);
kmem_cache_destroy(exception_cache);
kmem_cache_destroy(tracked_chunk_cache);
exit_origin_hash();
kmem_cache_destroy(pending_cache);
kmem_cache_destroy(exception_cache);
kmem_cache_destroy(tracked_chunk_cache);
+
+ dm_exception_store_exit();
}
/* Module hooks */
}
/* Module hooks */