Skip to content

Commit

Permalink
dm ioctl: retrieve status from inactive table
Browse files Browse the repository at this point in the history
Add the flag DM_QUERY_INACTIVE_TABLE_FLAG to the ioctls to return
infomation about the loaded-but-not-yet-active table instead of the live
table.  Prior to this patch it was impossible to obtain this information
until the device had been 'resumed'.

Userspace dmsetup and libdevmapper support the flag as of version 1.02.40.
e.g. dmsetup info --inactive vg1-lv1

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
  • Loading branch information
Mike Snitzer authored and Alasdair G Kergon committed Dec 10, 2009
1 parent 12fc0f4 commit 1d0f3ce
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 16 deletions.
70 changes: 57 additions & 13 deletions drivers/md/dm-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,6 @@ static int list_versions(struct dm_ioctl *param, size_t param_size)
return 0;
}



static int check_name(const char *name)
{
if (strchr(name, '/')) {
Expand All @@ -535,6 +533,40 @@ static int check_name(const char *name)
return 0;
}

/*
* On successful return, the caller must not attempt to acquire
* _hash_lock without first calling dm_table_put, because dm_table_destroy
* waits for this dm_table_put and could be called under this lock.
*/
static struct dm_table *dm_get_inactive_table(struct mapped_device *md)
{
struct hash_cell *hc;
struct dm_table *table = NULL;

down_read(&_hash_lock);
hc = dm_get_mdptr(md);
if (!hc || hc->md != md) {
DMWARN("device has been removed from the dev hash table.");
goto out;
}

table = hc->new_map;
if (table)
dm_table_get(table);

out:
up_read(&_hash_lock);

return table;
}

static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md,
struct dm_ioctl *param)
{
return (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) ?
dm_get_inactive_table(md) : dm_get_live_table(md);
}

/*
* Fills in a dm_ioctl structure, ready for sending back to
* userland.
Expand All @@ -559,18 +591,30 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
*/
param->open_count = dm_open_count(md);

if (get_disk_ro(disk))
param->flags |= DM_READONLY_FLAG;

param->event_nr = dm_get_event_nr(md);
param->target_count = 0;

table = dm_get_live_table(md);
if (table) {
param->flags |= DM_ACTIVE_PRESENT_FLAG;
param->target_count = dm_table_get_num_targets(table);
if (!(param->flags & DM_QUERY_INACTIVE_TABLE_FLAG)) {
if (get_disk_ro(disk))
param->flags |= DM_READONLY_FLAG;
param->target_count = dm_table_get_num_targets(table);
}
dm_table_put(table);
} else
param->target_count = 0;

param->flags |= DM_ACTIVE_PRESENT_FLAG;
}

if (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) {
table = dm_get_inactive_table(md);
if (table) {
if (!(dm_table_get_mode(table) & FMODE_WRITE))
param->flags |= DM_READONLY_FLAG;
param->target_count = dm_table_get_num_targets(table);
dm_table_put(table);
}
}

return 0;
}
Expand Down Expand Up @@ -993,7 +1037,7 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size)
if (r)
goto out;

table = dm_get_live_table(md);
table = dm_get_live_or_inactive_table(md, param);
if (table) {
retrieve_status(table, param, param_size);
dm_table_put(table);
Expand Down Expand Up @@ -1226,7 +1270,7 @@ static int table_deps(struct dm_ioctl *param, size_t param_size)
if (r)
goto out;

table = dm_get_live_table(md);
table = dm_get_live_or_inactive_table(md, param);
if (table) {
retrieve_deps(table, param, param_size);
dm_table_put(table);
Expand Down Expand Up @@ -1255,13 +1299,13 @@ static int table_status(struct dm_ioctl *param, size_t param_size)
if (r)
goto out;

table = dm_get_live_table(md);
table = dm_get_live_or_inactive_table(md, param);
if (table) {
retrieve_status(table, param, param_size);
dm_table_put(table);
}

out:
out:
dm_put(md);
return r;
}
Expand Down
13 changes: 10 additions & 3 deletions include/linux/dm-ioctl.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
* Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved.
*
* This file is released under the LGPL.
*/
Expand Down Expand Up @@ -266,9 +266,9 @@ enum {
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)

#define DM_VERSION_MAJOR 4
#define DM_VERSION_MINOR 15
#define DM_VERSION_MINOR 16
#define DM_VERSION_PATCHLEVEL 0
#define DM_VERSION_EXTRA "-ioctl (2009-04-01)"
#define DM_VERSION_EXTRA "-ioctl (2009-11-05)"

/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
Expand Down Expand Up @@ -309,4 +309,11 @@ enum {
*/
#define DM_NOFLUSH_FLAG (1 << 11) /* In */

/*
* If set, any table information returned will relate to the inactive
* table instead of the live one. Always check DM_INACTIVE_PRESENT_FLAG
* is set before using the data returned.
*/
#define DM_QUERY_INACTIVE_TABLE_FLAG (1 << 12) /* In */

#endif /* _LINUX_DM_IOCTL_H */

0 comments on commit 1d0f3ce

Please sign in to comment.