Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 140166
b: refs/heads/master
c: 493df71
h: refs/heads/master
v: v3
  • Loading branch information
Jonathan Brassow authored and Alasdair G Kergon committed Apr 2, 2009
1 parent 4dadc0d commit 3d254d9
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 50 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7513c2a761d69d2a93f17146b3563527d3618ba0
refs/heads/master: 493df71c6420b211a68ae82b889c1e8a5fe701be
162 changes: 162 additions & 0 deletions trunk/drivers/md/dm-exception-store.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,168 @@

#define DM_MSG_PREFIX "snapshot exception stores"

static LIST_HEAD(_exception_store_types);
static DEFINE_SPINLOCK(_lock);

static struct dm_exception_store_type *__find_exception_store_type(const char *name)
{
struct dm_exception_store_type *type;

list_for_each_entry(type, &_exception_store_types, list)
if (!strcmp(name, type->name))
return type;

return NULL;
}

static struct dm_exception_store_type *_get_exception_store_type(const char *name)
{
struct dm_exception_store_type *type;

spin_lock(&_lock);

type = __find_exception_store_type(name);

if (type && !try_module_get(type->module))
type = NULL;

spin_unlock(&_lock);

return type;
}

/*
* get_type
* @type_name
*
* Attempt to retrieve the dm_exception_store_type by name. If not already
* available, attempt to load the appropriate module.
*
* Exstore modules are named "dm-exstore-" followed by the 'type_name'.
* Modules may contain multiple types.
* This function will first try the module "dm-exstore-<type_name>",
* then truncate 'type_name' on the last '-' and try again.
*
* For example, if type_name was "clustered-shared", it would search
* 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
*
* 'dm-exception-store-<type_name>' is too long of a name in my
* opinion, which is why I've chosen to have the files
* containing exception store implementations be 'dm-exstore-<type_name>'.
* If you want your module to be autoloaded, you will follow this
* naming convention.
*
* Returns: dm_exception_store_type* on success, NULL on failure
*/
static struct dm_exception_store_type *get_type(const char *type_name)
{
char *p, *type_name_dup;
struct dm_exception_store_type *type;

type = _get_exception_store_type(type_name);
if (type)
return type;

type_name_dup = kstrdup(type_name, GFP_KERNEL);
if (!type_name_dup) {
DMERR("No memory left to attempt load for \"%s\"", type_name);
return NULL;
}

while (request_module("dm-exstore-%s", type_name_dup) ||
!(type = _get_exception_store_type(type_name))) {
p = strrchr(type_name_dup, '-');
if (!p)
break;
p[0] = '\0';
}

if (!type)
DMWARN("Module for exstore type \"%s\" not found.", type_name);

kfree(type_name_dup);

return type;
}

static void put_type(struct dm_exception_store_type *type)
{
spin_lock(&_lock);
module_put(type->module);
spin_unlock(&_lock);
}

int dm_exception_store_type_register(struct dm_exception_store_type *type)
{
int r = 0;

spin_lock(&_lock);
if (!__find_exception_store_type(type->name))
list_add(&type->list, &_exception_store_types);
else
r = -EEXIST;
spin_unlock(&_lock);

return r;
}
EXPORT_SYMBOL(dm_exception_store_type_register);

int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
{
spin_lock(&_lock);

if (!__find_exception_store_type(type->name)) {
spin_unlock(&_lock);
return -EINVAL;
}

list_del(&type->list);

spin_unlock(&_lock);

return 0;
}
EXPORT_SYMBOL(dm_exception_store_type_unregister);

int dm_exception_store_create(const char *type_name,
struct dm_exception_store **store)
{
int r = 0;
struct dm_exception_store_type *type;
struct dm_exception_store *tmp_store;

tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
if (!tmp_store)
return -ENOMEM;

type = get_type(type_name);
if (!type) {
kfree(tmp_store);
return -EINVAL;
}

tmp_store->type = type;

r = type->ctr(tmp_store, 0, NULL);
if (r) {
put_type(type);
kfree(tmp_store);
return r;
}

*store = tmp_store;
return 0;
}
EXPORT_SYMBOL(dm_exception_store_create);

void dm_exception_store_destroy(struct dm_exception_store *store)
{
store->type->dtr(store);
put_type(store->type);
kfree(store);
}
EXPORT_SYMBOL(dm_exception_store_destroy);

int dm_exception_store_init(void)
{
int r;
Expand Down
19 changes: 14 additions & 5 deletions trunk/drivers/md/dm-exception-store.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ struct dm_snap_exception {
*/
struct dm_exception_store;
struct dm_exception_store_type {
const char *name;
struct module *module;

int (*ctr) (struct dm_exception_store *store,
unsigned argc, char **argv);

Expand Down Expand Up @@ -85,10 +88,13 @@ struct dm_exception_store_type {
void (*fraction_full) (struct dm_exception_store *store,
sector_t *numerator,
sector_t *denominator);

/* For internal device-mapper use only. */
struct list_head list;
};

struct dm_exception_store {
struct dm_exception_store_type type;
struct dm_exception_store_type *type;

struct dm_snapshot *snap;

Expand Down Expand Up @@ -138,6 +144,13 @@ static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)

# endif

int dm_exception_store_type_register(struct dm_exception_store_type *type);
int dm_exception_store_type_unregister(struct dm_exception_store_type *type);

int dm_exception_store_create(const char *type_name,
struct dm_exception_store **store);
void dm_exception_store_destroy(struct dm_exception_store *store);

int dm_exception_store_init(void);
void dm_exception_store_exit(void);

Expand All @@ -150,8 +163,4 @@ void dm_persistent_snapshot_exit(void);
int dm_transient_snapshot_init(void);
void dm_transient_snapshot_exit(void);

int dm_create_persistent(struct dm_exception_store *store);

int dm_create_transient(struct dm_exception_store *store);

#endif /* _LINUX_DM_EXCEPTION_STORE */
67 changes: 57 additions & 10 deletions trunk/drivers/md/dm-snap-persistent.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ static void persistent_fraction_full(struct dm_exception_store *store,
*denominator = get_dev_size(store->snap->cow->bdev);
}

static void persistent_destroy(struct dm_exception_store *store)
static void persistent_dtr(struct dm_exception_store *store)
{
struct pstore *ps = get_info(store);

Expand Down Expand Up @@ -656,7 +656,8 @@ static void persistent_drop_snapshot(struct dm_exception_store *store)
DMWARN("write header failed");
}

int dm_create_persistent(struct dm_exception_store *store)
static int persistent_ctr(struct dm_exception_store *store,
unsigned argc, char **argv)
{
struct pstore *ps;

Expand All @@ -683,23 +684,69 @@ int dm_create_persistent(struct dm_exception_store *store)
return -ENOMEM;
}

store->type.dtr = persistent_destroy;
store->type.read_metadata = persistent_read_metadata;
store->type.prepare_exception = persistent_prepare_exception;
store->type.commit_exception = persistent_commit_exception;
store->type.drop_snapshot = persistent_drop_snapshot;
store->type.fraction_full = persistent_fraction_full;

store->context = ps;

return 0;
}

static int persistent_status(struct dm_exception_store *store,
status_type_t status, char *result,
unsigned int maxlen)
{
int sz = 0;

return sz;
}

static struct dm_exception_store_type _persistent_type = {
.name = "persistent",
.module = THIS_MODULE,
.ctr = persistent_ctr,
.dtr = persistent_dtr,
.read_metadata = persistent_read_metadata,
.prepare_exception = persistent_prepare_exception,
.commit_exception = persistent_commit_exception,
.drop_snapshot = persistent_drop_snapshot,
.fraction_full = persistent_fraction_full,
.status = persistent_status,
};

static struct dm_exception_store_type _persistent_compat_type = {
.name = "P",
.module = THIS_MODULE,
.ctr = persistent_ctr,
.dtr = persistent_dtr,
.read_metadata = persistent_read_metadata,
.prepare_exception = persistent_prepare_exception,
.commit_exception = persistent_commit_exception,
.drop_snapshot = persistent_drop_snapshot,
.fraction_full = persistent_fraction_full,
.status = persistent_status,
};

int dm_persistent_snapshot_init(void)
{
return 0;
int r;

r = dm_exception_store_type_register(&_persistent_type);
if (r) {
DMERR("Unable to register persistent exception store type");
return r;
}

r = dm_exception_store_type_register(&_persistent_compat_type);
if (r) {
DMERR("Unable to register old-style persistent exception "
"store type");
dm_exception_store_type_unregister(&_persistent_type);
return r;
}

return r;
}

void dm_persistent_snapshot_exit(void)
{
dm_exception_store_type_unregister(&_persistent_type);
dm_exception_store_type_unregister(&_persistent_compat_type);
}
Loading

0 comments on commit 3d254d9

Please sign in to comment.