Commit 77d7ccc8 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] dm: v4 ioctl interface

From: Joe Thornber <thornber@sistina.com>

v4 of the ioctl interface.  Note there never was a v2 or a v3 except in an
unofficial EVMS way.

This works correctly with the 64-bit dev_t patches in -mm kernels.

There is now a config option to allow the user to select v1 or v4, it
defaults to v1.  dm-ioctl.[hc] just #includes dm-ioctl-v[14].[hc] depending
on the config option.

If you want to use v4 you will have to update your tools
(libdevmapper/lvm).  The latest tools at the time of writing are:

dmsetup + libdevmapper + replacement kernel patches for 2.4.20 & 2.4.21:

  ftp://ftp.sistina.com/pub/LVM2/device-mapper/device-mapper-testing-new-version4-interface.tgz

Updated LVM2 tools to work with the above:

  ftp://ftp.sistina.com/pub/LVM2/tools/LVM2.0-testing.tgz
parent aa6d85aa
......@@ -145,5 +145,12 @@ config BLK_DEV_DM
If unsure, say N.
config DM_IOCTL_V4
bool "ioctl interface version 4"
depends on BLK_DEV_DM
---help---
Recent tools use a new version of the ioctl interface, only
select this option if you intend using such tools.
endmenu
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -515,6 +515,11 @@ static int dm_request(request_queue_t *q, struct bio *bio)
down_read(&md->lock);
}
if (!md->map) {
bio_io_error(bio, bio->bi_size);
return 0;
}
__split_bio(md, bio);
up_read(&md->lock);
return 0;
......@@ -671,6 +676,9 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
static void __unbind(struct mapped_device *md)
{
if (!md->map)
return;
dm_table_event_callback(md->map, NULL, NULL);
dm_table_put(md->map);
md->map = NULL;
......@@ -681,35 +689,26 @@ static void __unbind(struct mapped_device *md)
* Constructor for a new device.
*/
static int create_aux(unsigned int minor, int persistent,
struct dm_table *table, struct mapped_device **result)
struct mapped_device **result)
{
int r;
struct mapped_device *md;
md = alloc_dev(minor, persistent);
if (!md)
return -ENXIO;
r = __bind(md, table);
if (r) {
free_dev(md);
return r;
}
dm_table_resume_targets(md->map);
*result = md;
return 0;
}
int dm_create(struct dm_table *table, struct mapped_device **result)
int dm_create(struct mapped_device **result)
{
return create_aux(0, 0, table, result);
return create_aux(0, 0, result);
}
int dm_create_with_minor(unsigned int minor,
struct dm_table *table, struct mapped_device **result)
int dm_create_with_minor(unsigned int minor, struct mapped_device **result)
{
return create_aux(minor, 1, table, result);
return create_aux(minor, 1, result);
}
void dm_get(struct mapped_device *md)
......@@ -720,7 +719,7 @@ void dm_get(struct mapped_device *md)
void dm_put(struct mapped_device *md)
{
if (atomic_dec_and_test(&md->holders)) {
if (!test_bit(DMF_SUSPENDED, &md->flags))
if (!test_bit(DMF_SUSPENDED, &md->flags) && md->map)
dm_table_suspend_targets(md->map);
__unbind(md);
free_dev(md);
......@@ -810,6 +809,7 @@ int dm_suspend(struct mapped_device *md)
down_write(&md->lock);
remove_wait_queue(&md->wait, &wait);
set_bit(DMF_SUSPENDED, &md->flags);
if (md->map)
dm_table_suspend_targets(md->map);
up_write(&md->lock);
......@@ -821,7 +821,8 @@ int dm_resume(struct mapped_device *md)
struct deferred_io *def;
down_write(&md->lock);
if (!test_bit(DMF_SUSPENDED, &md->flags) ||
if (!md->map ||
!test_bit(DMF_SUSPENDED, &md->flags) ||
!dm_table_get_size(md->map)) {
up_write(&md->lock);
return -EINVAL;
......@@ -891,6 +892,7 @@ struct dm_table *dm_get_table(struct mapped_device *md)
down_read(&md->lock);
t = md->map;
if (t)
dm_table_get(t);
up_read(&md->lock);
......
......@@ -51,9 +51,8 @@ struct mapped_device;
* Functions for manipulating a struct mapped_device.
* Drop the reference with dm_put when you finish with the object.
*---------------------------------------------------------------*/
int dm_create(struct dm_table *table, struct mapped_device **md);
int dm_create_with_minor(unsigned int minor, struct dm_table *table,
struct mapped_device **md);
int dm_create(struct mapped_device **md);
int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
/*
* Reference counting for md.
......
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef _LINUX_DM_IOCTL_V1_H
#define _LINUX_DM_IOCTL_V1_H
#include <linux/types.h>
#define DM_DIR "mapper" /* Slashes not supported */
#define DM_MAX_TYPE_NAME 16
#define DM_NAME_LEN 128
#define DM_UUID_LEN 129
/*
* Implements a traditional ioctl interface to the device mapper.
*/
/*
* All ioctl arguments consist of a single chunk of memory, with
* this structure at the start. If a uuid is specified any
* lookup (eg. for a DM_INFO) will be done on that, *not* the
* name.
*/
struct dm_ioctl {
/*
* The version number is made up of three parts:
* major - no backward or forward compatibility,
* minor - only backwards compatible,
* patch - both backwards and forwards compatible.
*
* All clients of the ioctl interface should fill in the
* version number of the interface that they were
* compiled with.
*
* All recognised ioctl commands (ie. those that don't
* return -ENOTTY) fill out this field, even if the
* command failed.
*/
uint32_t version[3]; /* in/out */
uint32_t data_size; /* total size of data passed in
* including this struct */
uint32_t data_start; /* offset to start of data
* relative to start of this struct */
uint32_t target_count; /* in/out */
uint32_t open_count; /* out */
uint32_t flags; /* in/out */
__kernel_dev_t dev; /* in/out */
char name[DM_NAME_LEN]; /* device name */
char uuid[DM_UUID_LEN]; /* unique identifier for
* the block device */
};
/*
* Used to specify tables. These structures appear after the
* dm_ioctl.
*/
struct dm_target_spec {
int32_t status; /* used when reading from kernel only */
uint64_t sector_start;
uint32_t length;
/*
* Offset in bytes (from the start of this struct) to
* next target_spec.
*/
uint32_t next;
char target_type[DM_MAX_TYPE_NAME];
/*
* Parameter string starts immediately after this object.
* Be careful to add padding after string to ensure correct
* alignment of subsequent dm_target_spec.
*/
};
/*
* Used to retrieve the target dependencies.
*/
struct dm_target_deps {
uint32_t count;
__kernel_dev_t dev[0]; /* out */
};
/*
* If you change this make sure you make the corresponding change
* to dm-ioctl.c:lookup_ioctl()
*/
enum {
/* Top level cmds */
DM_VERSION_CMD = 0,
DM_REMOVE_ALL_CMD,
/* device level cmds */
DM_DEV_CREATE_CMD,
DM_DEV_REMOVE_CMD,
DM_DEV_RELOAD_CMD,
DM_DEV_RENAME_CMD,
DM_DEV_SUSPEND_CMD,
DM_DEV_DEPS_CMD,
DM_DEV_STATUS_CMD,
/* target level cmds */
DM_TARGET_STATUS_CMD,
DM_TARGET_WAIT_CMD
};
#define DM_IOCTL 0xfd
#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
#define DM_DEV_RELOAD _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD, struct dm_ioctl)
#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
#define DM_DEV_DEPS _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD, struct dm_ioctl)
#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
#define DM_TARGET_STATUS _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD, struct dm_ioctl)
#define DM_TARGET_WAIT _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 1
#define DM_VERSION_MINOR 0
#define DM_VERSION_PATCHLEVEL 6
#define DM_VERSION_EXTRA "-ioctl (2002-10-15)"
/* Status bits */
#define DM_READONLY_FLAG 0x00000001
#define DM_SUSPEND_FLAG 0x00000002
#define DM_EXISTS_FLAG 0x00000004
#define DM_PERSISTENT_DEV_FLAG 0x00000008
/*
* Flag passed into ioctl STATUS command to get table information
* rather than current status.
*/
#define DM_STATUS_TABLE_FLAG 0x00000010
#endif /* _LINUX_DM_IOCTL_H */
/*
* Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef _LINUX_DM_IOCTL_V4_H
#define _LINUX_DM_IOCTL_V4_H
#include <linux/types.h>
#define DM_DIR "mapper" /* Slashes not supported */
#define DM_MAX_TYPE_NAME 16
#define DM_NAME_LEN 128
#define DM_UUID_LEN 129
/*
* A traditional ioctl interface for the device mapper.
*
* Each device can have two tables associated with it, an
* 'active' table which is the one currently used by io passing
* through the device, and an 'inactive' one which is a table
* that is being prepared as a replacement for the 'active' one.
*
* DM_VERSION:
* Just get the version information for the ioctl interface.
*
* DM_REMOVE_ALL:
* Remove all dm devices, destroy all tables. Only really used
* for debug.
*
* DM_LIST_DEVICES:
* Get a list of all the dm device names.
*
* DM_DEV_CREATE:
* Create a new device, neither the 'active' or 'inactive' table
* slots will be filled. The device will be in suspended state
* after creation, however any io to the device will get errored
* since it will be out-of-bounds.
*
* DM_DEV_REMOVE:
* Remove a device, destroy any tables.
*
* DM_DEV_RENAME:
* Rename a device.
*
* DM_SUSPEND:
* This performs both suspend and resume, depending which flag is
* passed in.
* Suspend: This command will not return until all pending io to
* the device has completed. Further io will be deferred until
* the device is resumed.
* Resume: It is no longer an error to issue this command on an
* unsuspended device. If a table is present in the 'inactive'
* slot, it will be moved to the active slot, then the old table
* from the active slot will be _destroyed_. Finally the device
* is resumed.
*
* DM_DEV_STATUS:
* Retrieves the status for the table in the 'active' slot.
*
* DM_DEV_WAIT:
* Wait for a significant event to occur to the device. This
* could either be caused by an event triggered by one of the
* targets of the table in the 'active' slot, or a table change.
*
* DM_TABLE_LOAD:
* Load a table into the 'inactive' slot for the device. The
* device does _not_ need to be suspended prior to this command.
*
* DM_TABLE_CLEAR:
* Destroy any table in the 'inactive' slot (ie. abort).
*
* DM_TABLE_DEPS:
* Return a set of device dependencies for the 'active' table.
*
* DM_TABLE_STATUS:
* Return the targets status for the 'active' table.
*/
/*
* All ioctl arguments consist of a single chunk of memory, with
* this structure at the start. If a uuid is specified any
* lookup (eg. for a DM_INFO) will be done on that, *not* the
* name.
*/
struct dm_ioctl {
/*
* The version number is made up of three parts:
* major - no backward or forward compatibility,
* minor - only backwards compatible,
* patch - both backwards and forwards compatible.
*
* All clients of the ioctl interface should fill in the
* version number of the interface that they were
* compiled with.
*
* All recognised ioctl commands (ie. those that don't
* return -ENOTTY) fill out this field, even if the
* command failed.
*/
uint32_t version[3]; /* in/out */
uint32_t data_size; /* total size of data passed in
* including this struct */
uint32_t data_start; /* offset to start of data
* relative to start of this struct */
uint32_t target_count; /* in/out */
int32_t open_count; /* out */
uint32_t flags; /* in/out */
uint32_t event_nr; /* in/out */
uint32_t padding;
uint64_t dev; /* in/out */
char name[DM_NAME_LEN]; /* device name */
char uuid[DM_UUID_LEN]; /* unique identifier for
* the block device */
};
/*
* Used to specify tables. These structures appear after the
* dm_ioctl.
*/
struct dm_target_spec {
uint64_t sector_start;
uint64_t length;
int32_t status; /* used when reading from kernel only */
/*
* Offset in bytes (from the start of this struct) to
* next target_spec.
*/
uint32_t next;
char target_type[DM_MAX_TYPE_NAME];
/*
* Parameter string starts immediately after this object.
* Be careful to add padding after string to ensure correct
* alignment of subsequent dm_target_spec.
*/
};
/*
* Used to retrieve the target dependencies.
*/
struct dm_target_deps {
uint32_t count; /* Array size */
uint32_t padding; /* unused */
uint64_t dev[0]; /* out */
};
/*
* Used to get a list of all dm devices.
*/
struct dm_name_list {
uint64_t dev;
uint32_t next; /* offset to the next record from
the _start_ of this */
char name[0];
};
/*
* If you change this make sure you make the corresponding change
* to dm-ioctl.c:lookup_ioctl()
*/
enum {
/* Top level cmds */
DM_VERSION_CMD = 0,
DM_REMOVE_ALL_CMD,
DM_LIST_DEVICES_CMD,
/* device level cmds */
DM_DEV_CREATE_CMD,
DM_DEV_REMOVE_CMD,
DM_DEV_RENAME_CMD,
DM_DEV_SUSPEND_CMD,
DM_DEV_STATUS_CMD,
DM_DEV_WAIT_CMD,
/* Table level cmds */
DM_TABLE_LOAD_CMD,
DM_TABLE_CLEAR_CMD,
DM_TABLE_DEPS_CMD,
DM_TABLE_STATUS_CMD,
};
#define DM_IOCTL 0xfd
#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
#define DM_LIST_DEVICES _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
#define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
#define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
#define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
#define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
#define DM_TABLE_STATUS _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
#define DM_VERSION_MINOR 0
#define DM_VERSION_PATCHLEVEL 0
#define DM_VERSION_EXTRA "-ioctl (2003-06-04)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */
#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */
/*
* Flag passed into ioctl STATUS command to get table information
* rather than current status.
*/
#define DM_STATUS_TABLE_FLAG (1 << 4) /* In */
/*
* Flags that indicate whether a table is present in either of
* the two table slots that a device has.
*/
#define DM_ACTIVE_PRESENT_FLAG (1 << 5) /* Out */
#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
/*
* Indicates that the buffer passed in wasn't big enough for the
* results.
*/
#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */
#endif /* _LINUX_DM_IOCTL_H */
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
* Copyright (C) 2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
......@@ -7,143 +7,12 @@
#ifndef _LINUX_DM_IOCTL_H
#define _LINUX_DM_IOCTL_H
#include <linux/types.h>
#include <linux/config.h>
#define DM_DIR "mapper" /* Slashes not supported */
#define DM_MAX_TYPE_NAME 16
#define DM_NAME_LEN 128
#define DM_UUID_LEN 129
#ifdef CONFIG_DM_IOCTL_V4
#include "dm-ioctl-v4.h"
#else
#include "dm-ioctl-v1.h"
#endif
/*
* Implements a traditional ioctl interface to the device mapper.
*/
/*
* All ioctl arguments consist of a single chunk of memory, with
* this structure at the start. If a uuid is specified any
* lookup (eg. for a DM_INFO) will be done on that, *not* the
* name.
*/
struct dm_ioctl {
/*
* The version number is made up of three parts:
* major - no backward or forward compatibility,
* minor - only backwards compatible,
* patch - both backwards and forwards compatible.
*
* All clients of the ioctl interface should fill in the
* version number of the interface that they were
* compiled with.
*
* All recognised ioctl commands (ie. those that don't
* return -ENOTTY) fill out this field, even if the
* command failed.
*/
uint32_t version[3]; /* in/out */
uint32_t data_size; /* total size of data passed in
* including this struct */
uint32_t data_start; /* offset to start of data
* relative to start of this struct */
uint32_t target_count; /* in/out */
uint32_t open_count; /* out */
uint32_t flags; /* in/out */
__kernel_dev_t dev; /* in/out */
char name[DM_NAME_LEN]; /* device name */
char uuid[DM_UUID_LEN]; /* unique identifier for
* the block device */
};
/*
* Used to specify tables. These structures appear after the
* dm_ioctl.
*/
struct dm_target_spec {
int32_t status; /* used when reading from kernel only */
uint64_t sector_start;
uint32_t length;
/*
* Offset in bytes (from the start of this struct) to
* next target_spec.
*/
uint32_t next;
char target_type[DM_MAX_TYPE_NAME];
/*
* Parameter string starts immediately after this object.
* Be careful to add padding after string to ensure correct
* alignment of subsequent dm_target_spec.
*/
};
/*
* Used to retrieve the target dependencies.
*/
struct dm_target_deps {
uint32_t count;
__kernel_dev_t dev[0]; /* out */
};
/*
* If you change this make sure you make the corresponding change
* to dm-ioctl.c:lookup_ioctl()
*/
enum {
/* Top level cmds */
DM_VERSION_CMD = 0,
DM_REMOVE_ALL_CMD,
/* device level cmds */
DM_DEV_CREATE_CMD,
DM_DEV_REMOVE_CMD,
DM_DEV_RELOAD_CMD,
DM_DEV_RENAME_CMD,
DM_DEV_SUSPEND_CMD,
DM_DEV_DEPS_CMD,
DM_DEV_STATUS_CMD,
/* target level cmds */
DM_TARGET_STATUS_CMD,
DM_TARGET_WAIT_CMD
};
#define DM_IOCTL 0xfd
#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
#define DM_DEV_RELOAD _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD, struct dm_ioctl)
#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
#define DM_DEV_DEPS _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD, struct dm_ioctl)
#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
#define DM_TARGET_STATUS _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD, struct dm_ioctl)
#define DM_TARGET_WAIT _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 1
#define DM_VERSION_MINOR 0
#define DM_VERSION_PATCHLEVEL 6
#define DM_VERSION_EXTRA "-ioctl (2002-10-15)"
/* Status bits */
#define DM_READONLY_FLAG 0x00000001
#define DM_SUSPEND_FLAG 0x00000002
#define DM_EXISTS_FLAG 0x00000004
#define DM_PERSISTENT_DEV_FLAG 0x00000008
/*
* Flag passed into ioctl STATUS command to get table information
* rather than current status.
*/
#define DM_STATUS_TABLE_FLAG 0x00000010
#endif /* _LINUX_DM_IOCTL_H */
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment