]>
Commit | Line | Data |
---|---|---|
4f81a417 MS |
1 | /* |
2 | * Copyright (C) 2011-2012 Red Hat, Inc. | |
3 | * | |
4 | * This file is released under the GPL. | |
5 | */ | |
6 | ||
7 | #ifndef DM_BIO_PRISON_H | |
8 | #define DM_BIO_PRISON_H | |
9 | ||
10 | #include "persistent-data/dm-block-manager.h" /* FIXME: for dm_block_t */ | |
11 | #include "dm-thin-metadata.h" /* FIXME: for dm_thin_id */ | |
12 | ||
13 | #include <linux/list.h> | |
14 | #include <linux/bio.h> | |
15 | ||
16 | /*----------------------------------------------------------------*/ | |
17 | ||
18 | /* | |
19 | * Sometimes we can't deal with a bio straight away. We put them in prison | |
20 | * where they can't cause any mischief. Bios are put in a cell identified | |
21 | * by a key, multiple bios can be in the same cell. When the cell is | |
22 | * subsequently unlocked the bios become available. | |
23 | */ | |
24 | struct dm_bio_prison; | |
4f81a417 MS |
25 | |
26 | /* FIXME: this needs to be more abstract */ | |
27 | struct dm_cell_key { | |
28 | int virtual; | |
29 | dm_thin_id dev; | |
30 | dm_block_t block; | |
31 | }; | |
32 | ||
025b9685 JT |
33 | /* |
34 | * Treat this as opaque, only in header so callers can manage allocation | |
35 | * themselves. | |
36 | */ | |
37 | struct dm_bio_prison_cell { | |
38 | struct hlist_node list; | |
39 | struct dm_cell_key key; | |
40 | struct bio *holder; | |
41 | struct bio_list bios; | |
42 | }; | |
43 | ||
4f81a417 MS |
44 | struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells); |
45 | void dm_bio_prison_destroy(struct dm_bio_prison *prison); | |
46 | ||
47 | /* | |
6beca5eb JT |
48 | * These two functions just wrap a mempool. This is a transitory step: |
49 | * Eventually all bio prison clients should manage their own cell memory. | |
4f81a417 | 50 | * |
6beca5eb JT |
51 | * Like mempool_alloc(), dm_bio_prison_alloc_cell() can only fail if called |
52 | * in interrupt context or passed GFP_NOWAIT. | |
4f81a417 | 53 | */ |
6beca5eb JT |
54 | struct dm_bio_prison_cell *dm_bio_prison_alloc_cell(struct dm_bio_prison *prison, |
55 | gfp_t gfp); | |
56 | void dm_bio_prison_free_cell(struct dm_bio_prison *prison, | |
57 | struct dm_bio_prison_cell *cell); | |
4f81a417 | 58 | |
c6b4fcba JT |
59 | /* |
60 | * Creates, or retrieves a cell for the given key. | |
61 | * | |
62 | * Returns 1 if pre-existing cell returned, zero if new cell created using | |
63 | * @cell_prealloc. | |
64 | */ | |
65 | int dm_get_cell(struct dm_bio_prison *prison, | |
66 | struct dm_cell_key *key, | |
67 | struct dm_bio_prison_cell *cell_prealloc, | |
68 | struct dm_bio_prison_cell **cell_result); | |
69 | ||
6beca5eb JT |
70 | /* |
71 | * An atomic op that combines retrieving a cell, and adding a bio to it. | |
72 | * | |
73 | * Returns 1 if the cell was already held, 0 if @inmate is the new holder. | |
74 | */ | |
75 | int dm_bio_detain(struct dm_bio_prison *prison, | |
76 | struct dm_cell_key *key, | |
77 | struct bio *inmate, | |
78 | struct dm_bio_prison_cell *cell_prealloc, | |
79 | struct dm_bio_prison_cell **cell_result); | |
80 | ||
81 | void dm_cell_release(struct dm_bio_prison *prison, | |
82 | struct dm_bio_prison_cell *cell, | |
83 | struct bio_list *bios); | |
84 | void dm_cell_release_no_holder(struct dm_bio_prison *prison, | |
85 | struct dm_bio_prison_cell *cell, | |
86 | struct bio_list *inmates); | |
87 | void dm_cell_error(struct dm_bio_prison *prison, | |
af91805a | 88 | struct dm_bio_prison_cell *cell, int error); |
4f81a417 MS |
89 | |
90 | /*----------------------------------------------------------------*/ | |
91 | ||
92 | /* | |
93 | * We use the deferred set to keep track of pending reads to shared blocks. | |
94 | * We do this to ensure the new mapping caused by a write isn't performed | |
95 | * until these prior reads have completed. Otherwise the insertion of the | |
96 | * new mapping could free the old block that the read bios are mapped to. | |
97 | */ | |
98 | ||
99 | struct dm_deferred_set; | |
100 | struct dm_deferred_entry; | |
101 | ||
102 | struct dm_deferred_set *dm_deferred_set_create(void); | |
103 | void dm_deferred_set_destroy(struct dm_deferred_set *ds); | |
104 | ||
105 | struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds); | |
106 | void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head); | |
107 | int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work); | |
108 | ||
109 | /*----------------------------------------------------------------*/ | |
110 | ||
111 | #endif |