diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /Documentation/device-mapper |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'Documentation/device-mapper')
-rw-r--r-- | Documentation/device-mapper/dm-io.txt | 75 | ||||
-rw-r--r-- | Documentation/device-mapper/kcopyd.txt | 47 | ||||
-rw-r--r-- | Documentation/device-mapper/linear.txt | 61 | ||||
-rw-r--r-- | Documentation/device-mapper/striped.txt | 58 | ||||
-rw-r--r-- | Documentation/device-mapper/zero.txt | 37 |
5 files changed, 278 insertions, 0 deletions
diff --git a/Documentation/device-mapper/dm-io.txt b/Documentation/device-mapper/dm-io.txt new file mode 100644 index 000000000000..3b5d9a52cdcf --- /dev/null +++ b/Documentation/device-mapper/dm-io.txt | |||
@@ -0,0 +1,75 @@ | |||
1 | dm-io | ||
2 | ===== | ||
3 | |||
4 | Dm-io provides synchronous and asynchronous I/O services. There are three | ||
5 | types of I/O services available, and each type has a sync and an async | ||
6 | version. | ||
7 | |||
8 | The user must set up an io_region structure to describe the desired location | ||
9 | of the I/O. Each io_region indicates a block-device along with the starting | ||
10 | sector and size of the region. | ||
11 | |||
12 | struct io_region { | ||
13 | struct block_device *bdev; | ||
14 | sector_t sector; | ||
15 | sector_t count; | ||
16 | }; | ||
17 | |||
18 | Dm-io can read from one io_region or write to one or more io_regions. Writes | ||
19 | to multiple regions are specified by an array of io_region structures. | ||
20 | |||
21 | The first I/O service type takes a list of memory pages as the data buffer for | ||
22 | the I/O, along with an offset into the first page. | ||
23 | |||
24 | struct page_list { | ||
25 | struct page_list *next; | ||
26 | struct page *page; | ||
27 | }; | ||
28 | |||
29 | int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, | ||
30 | struct page_list *pl, unsigned int offset, | ||
31 | unsigned long *error_bits); | ||
32 | int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, | ||
33 | struct page_list *pl, unsigned int offset, | ||
34 | io_notify_fn fn, void *context); | ||
35 | |||
36 | The second I/O service type takes an array of bio vectors as the data buffer | ||
37 | for the I/O. This service can be handy if the caller has a pre-assembled bio, | ||
38 | but wants to direct different portions of the bio to different devices. | ||
39 | |||
40 | int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, | ||
41 | int rw, struct bio_vec *bvec, | ||
42 | unsigned long *error_bits); | ||
43 | int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, | ||
44 | int rw, struct bio_vec *bvec, | ||
45 | io_notify_fn fn, void *context); | ||
46 | |||
47 | The third I/O service type takes a pointer to a vmalloc'd memory buffer as the | ||
48 | data buffer for the I/O. This service can be handy if the caller needs to do | ||
49 | I/O to a large region but doesn't want to allocate a large number of individual | ||
50 | memory pages. | ||
51 | |||
52 | int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, | ||
53 | void *data, unsigned long *error_bits); | ||
54 | int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, | ||
55 | void *data, io_notify_fn fn, void *context); | ||
56 | |||
57 | Callers of the asynchronous I/O services must include the name of a completion | ||
58 | callback routine and a pointer to some context data for the I/O. | ||
59 | |||
60 | typedef void (*io_notify_fn)(unsigned long error, void *context); | ||
61 | |||
62 | The "error" parameter in this callback, as well as the "*error" parameter in | ||
63 | all of the synchronous versions, is a bitset (instead of a simple error value). | ||
64 | In the case of an write-I/O to multiple regions, this bitset allows dm-io to | ||
65 | indicate success or failure on each individual region. | ||
66 | |||
67 | Before using any of the dm-io services, the user should call dm_io_get() | ||
68 | and specify the number of pages they expect to perform I/O on concurrently. | ||
69 | Dm-io will attempt to resize its mempool to make sure enough pages are | ||
70 | always available in order to avoid unnecessary waiting while performing I/O. | ||
71 | |||
72 | When the user is finished using the dm-io services, they should call | ||
73 | dm_io_put() and specify the same number of pages that were given on the | ||
74 | dm_io_get() call. | ||
75 | |||
diff --git a/Documentation/device-mapper/kcopyd.txt b/Documentation/device-mapper/kcopyd.txt new file mode 100644 index 000000000000..820382c4cecf --- /dev/null +++ b/Documentation/device-mapper/kcopyd.txt | |||
@@ -0,0 +1,47 @@ | |||
1 | kcopyd | ||
2 | ====== | ||
3 | |||
4 | Kcopyd provides the ability to copy a range of sectors from one block-device | ||
5 | to one or more other block-devices, with an asynchronous completion | ||
6 | notification. It is used by dm-snapshot and dm-mirror. | ||
7 | |||
8 | Users of kcopyd must first create a client and indicate how many memory pages | ||
9 | to set aside for their copy jobs. This is done with a call to | ||
10 | kcopyd_client_create(). | ||
11 | |||
12 | int kcopyd_client_create(unsigned int num_pages, | ||
13 | struct kcopyd_client **result); | ||
14 | |||
15 | To start a copy job, the user must set up io_region structures to describe | ||
16 | the source and destinations of the copy. Each io_region indicates a | ||
17 | block-device along with the starting sector and size of the region. The source | ||
18 | of the copy is given as one io_region structure, and the destinations of the | ||
19 | copy are given as an array of io_region structures. | ||
20 | |||
21 | struct io_region { | ||
22 | struct block_device *bdev; | ||
23 | sector_t sector; | ||
24 | sector_t count; | ||
25 | }; | ||
26 | |||
27 | To start the copy, the user calls kcopyd_copy(), passing in the client | ||
28 | pointer, pointers to the source and destination io_regions, the name of a | ||
29 | completion callback routine, and a pointer to some context data for the copy. | ||
30 | |||
31 | int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, | ||
32 | unsigned int num_dests, struct io_region *dests, | ||
33 | unsigned int flags, kcopyd_notify_fn fn, void *context); | ||
34 | |||
35 | typedef void (*kcopyd_notify_fn)(int read_err, unsigned int write_err, | ||
36 | void *context); | ||
37 | |||
38 | When the copy completes, kcopyd will call the user's completion routine, | ||
39 | passing back the user's context pointer. It will also indicate if a read or | ||
40 | write error occurred during the copy. | ||
41 | |||
42 | When a user is done with all their copy jobs, they should call | ||
43 | kcopyd_client_destroy() to delete the kcopyd client, which will release the | ||
44 | associated memory pages. | ||
45 | |||
46 | void kcopyd_client_destroy(struct kcopyd_client *kc); | ||
47 | |||
diff --git a/Documentation/device-mapper/linear.txt b/Documentation/device-mapper/linear.txt new file mode 100644 index 000000000000..d5307d380a45 --- /dev/null +++ b/Documentation/device-mapper/linear.txt | |||
@@ -0,0 +1,61 @@ | |||
1 | dm-linear | ||
2 | ========= | ||
3 | |||
4 | Device-Mapper's "linear" target maps a linear range of the Device-Mapper | ||
5 | device onto a linear range of another device. This is the basic building | ||
6 | block of logical volume managers. | ||
7 | |||
8 | Parameters: <dev path> <offset> | ||
9 | <dev path>: Full pathname to the underlying block-device, or a | ||
10 | "major:minor" device-number. | ||
11 | <offset>: Starting sector within the device. | ||
12 | |||
13 | |||
14 | Example scripts | ||
15 | =============== | ||
16 | [[ | ||
17 | #!/bin/sh | ||
18 | # Create an identity mapping for a device | ||
19 | echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity | ||
20 | ]] | ||
21 | |||
22 | |||
23 | [[ | ||
24 | #!/bin/sh | ||
25 | # Join 2 devices together | ||
26 | size1=`blockdev --getsize $1` | ||
27 | size2=`blockdev --getsize $2` | ||
28 | echo "0 $size1 linear $1 0 | ||
29 | $size1 $size2 linear $2 0" | dmsetup create joined | ||
30 | ]] | ||
31 | |||
32 | |||
33 | [[ | ||
34 | #!/usr/bin/perl -w | ||
35 | # Split a device into 4M chunks and then join them together in reverse order. | ||
36 | |||
37 | my $name = "reverse"; | ||
38 | my $extent_size = 4 * 1024 * 2; | ||
39 | my $dev = $ARGV[0]; | ||
40 | my $table = ""; | ||
41 | my $count = 0; | ||
42 | |||
43 | if (!defined($dev)) { | ||
44 | die("Please specify a device.\n"); | ||
45 | } | ||
46 | |||
47 | my $dev_size = `blockdev --getsize $dev`; | ||
48 | my $extents = int($dev_size / $extent_size) - | ||
49 | (($dev_size % $extent_size) ? 1 : 0); | ||
50 | |||
51 | while ($extents > 0) { | ||
52 | my $this_start = $count * $extent_size; | ||
53 | $extents--; | ||
54 | $count++; | ||
55 | my $this_offset = $extents * $extent_size; | ||
56 | |||
57 | $table .= "$this_start $extent_size linear $dev $this_offset\n"; | ||
58 | } | ||
59 | |||
60 | `echo \"$table\" | dmsetup create $name`; | ||
61 | ]] | ||
diff --git a/Documentation/device-mapper/striped.txt b/Documentation/device-mapper/striped.txt new file mode 100644 index 000000000000..f34d3236b9da --- /dev/null +++ b/Documentation/device-mapper/striped.txt | |||
@@ -0,0 +1,58 @@ | |||
1 | dm-stripe | ||
2 | ========= | ||
3 | |||
4 | Device-Mapper's "striped" target is used to create a striped (i.e. RAID-0) | ||
5 | device across one or more underlying devices. Data is written in "chunks", | ||
6 | with consecutive chunks rotating among the underlying devices. This can | ||
7 | potentially provide improved I/O throughput by utilizing several physical | ||
8 | devices in parallel. | ||
9 | |||
10 | Parameters: <num devs> <chunk size> [<dev path> <offset>]+ | ||
11 | <num devs>: Number of underlying devices. | ||
12 | <chunk size>: Size of each chunk of data. Must be a power-of-2 and at | ||
13 | least as large as the system's PAGE_SIZE. | ||
14 | <dev path>: Full pathname to the underlying block-device, or a | ||
15 | "major:minor" device-number. | ||
16 | <offset>: Starting sector within the device. | ||
17 | |||
18 | One or more underlying devices can be specified. The striped device size must | ||
19 | be a multiple of the chunk size and a multiple of the number of underlying | ||
20 | devices. | ||
21 | |||
22 | |||
23 | Example scripts | ||
24 | =============== | ||
25 | |||
26 | [[ | ||
27 | #!/usr/bin/perl -w | ||
28 | # Create a striped device across any number of underlying devices. The device | ||
29 | # will be called "stripe_dev" and have a chunk-size of 128k. | ||
30 | |||
31 | my $chunk_size = 128 * 2; | ||
32 | my $dev_name = "stripe_dev"; | ||
33 | my $num_devs = @ARGV; | ||
34 | my @devs = @ARGV; | ||
35 | my ($min_dev_size, $stripe_dev_size, $i); | ||
36 | |||
37 | if (!$num_devs) { | ||
38 | die("Specify at least one device\n"); | ||
39 | } | ||
40 | |||
41 | $min_dev_size = `blockdev --getsize $devs[0]`; | ||
42 | for ($i = 1; $i < $num_devs; $i++) { | ||
43 | my $this_size = `blockdev --getsize $devs[$i]`; | ||
44 | $min_dev_size = ($min_dev_size < $this_size) ? | ||
45 | $min_dev_size : $this_size; | ||
46 | } | ||
47 | |||
48 | $stripe_dev_size = $min_dev_size * $num_devs; | ||
49 | $stripe_dev_size -= $stripe_dev_size % ($chunk_size * $num_devs); | ||
50 | |||
51 | $table = "0 $stripe_dev_size striped $num_devs $chunk_size"; | ||
52 | for ($i = 0; $i < $num_devs; $i++) { | ||
53 | $table .= " $devs[$i] 0"; | ||
54 | } | ||
55 | |||
56 | `echo $table | dmsetup create $dev_name`; | ||
57 | ]] | ||
58 | |||
diff --git a/Documentation/device-mapper/zero.txt b/Documentation/device-mapper/zero.txt new file mode 100644 index 000000000000..20fb38e7fa7e --- /dev/null +++ b/Documentation/device-mapper/zero.txt | |||
@@ -0,0 +1,37 @@ | |||
1 | dm-zero | ||
2 | ======= | ||
3 | |||
4 | Device-Mapper's "zero" target provides a block-device that always returns | ||
5 | zero'd data on reads and silently drops writes. This is similar behavior to | ||
6 | /dev/zero, but as a block-device instead of a character-device. | ||
7 | |||
8 | Dm-zero has no target-specific parameters. | ||
9 | |||
10 | One very interesting use of dm-zero is for creating "sparse" devices in | ||
11 | conjunction with dm-snapshot. A sparse device reports a device-size larger | ||
12 | than the amount of actual storage space available for that device. A user can | ||
13 | write data anywhere within the sparse device and read it back like a normal | ||
14 | device. Reads to previously unwritten areas will return a zero'd buffer. When | ||
15 | enough data has been written to fill up the actual storage space, the sparse | ||
16 | device is deactivated. This can be very useful for testing device and | ||
17 | filesystem limitations. | ||
18 | |||
19 | To create a sparse device, start by creating a dm-zero device that's the | ||
20 | desired size of the sparse device. For this example, we'll assume a 10TB | ||
21 | sparse device. | ||
22 | |||
23 | TEN_TERABYTES=`expr 10 \* 1024 \* 1024 \* 1024 \* 2` # 10 TB in sectors | ||
24 | echo "0 $TEN_TERABYTES zero" | dmsetup create zero1 | ||
25 | |||
26 | Then create a snapshot of the zero device, using any available block-device as | ||
27 | the COW device. The size of the COW device will determine the amount of real | ||
28 | space available to the sparse device. For this example, we'll assume /dev/sdb1 | ||
29 | is an available 10GB partition. | ||
30 | |||
31 | echo "0 $TEN_TERABYTES snapshot /dev/mapper/zero1 /dev/sdb1 p 128" | \ | ||
32 | dmsetup create sparse1 | ||
33 | |||
34 | This will create a 10TB sparse device called /dev/mapper/sparse1 that has | ||
35 | 10GB of actual storage space available. If more than 10GB of data is written | ||
36 | to this device, it will start returning I/O errors. | ||
37 | |||