]>
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 | ||
4f81a417 | 13 | #include <linux/bio.h> |
a195db2d | 14 | #include <linux/rbtree.h> |
4f81a417 MS |
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 { | |
a195db2d JT |
38 | struct rb_node node; |
39 | ||
025b9685 JT |
40 | struct dm_cell_key key; |
41 | struct bio *holder; | |
42 | struct bio_list bios; | |
43 | }; | |
44 | ||
a195db2d | 45 | struct dm_bio_prison *dm_bio_prison_create(void); |
4f81a417 MS |
46 | void dm_bio_prison_destroy(struct dm_bio_prison *prison); |
47 | ||
48 | /* | |
6beca5eb JT |
49 | * These two functions just wrap a mempool. This is a transitory step: |
50 | * Eventually all bio prison clients should manage their own cell memory. | |
4f81a417 | 51 | * |
6beca5eb JT |
52 | * Like mempool_alloc(), dm_bio_prison_alloc_cell() can only fail if called |
53 | * in interrupt context or passed GFP_NOWAIT. | |
4f81a417 | 54 | */ |
6beca5eb JT |
55 | struct dm_bio_prison_cell *dm_bio_prison_alloc_cell(struct dm_bio_prison *prison, |
56 | gfp_t gfp); | |
57 | void dm_bio_prison_free_cell(struct dm_bio_prison *prison, | |
58 | struct dm_bio_prison_cell *cell); | |
4f81a417 | 59 | |
c6b4fcba JT |
60 | /* |
61 | * Creates, or retrieves a cell for the given key. | |
62 | * | |
63 | * Returns 1 if pre-existing cell returned, zero if new cell created using | |
64 | * @cell_prealloc. | |
65 | */ | |
66 | int dm_get_cell(struct dm_bio_prison *prison, | |
67 | struct dm_cell_key *key, | |
68 | struct dm_bio_prison_cell *cell_prealloc, | |
69 | struct dm_bio_prison_cell **cell_result); | |
70 | ||
6beca5eb JT |
71 | /* |
72 | * An atomic op that combines retrieving a cell, and adding a bio to it. | |
73 | * | |
74 | * Returns 1 if the cell was already held, 0 if @inmate is the new holder. | |
75 | */ | |
76 | int dm_bio_detain(struct dm_bio_prison *prison, | |
77 | struct dm_cell_key *key, | |
78 | struct bio *inmate, | |
79 | struct dm_bio_prison_cell *cell_prealloc, | |
80 | struct dm_bio_prison_cell **cell_result); | |
81 | ||
82 | void dm_cell_release(struct dm_bio_prison *prison, | |
83 | struct dm_bio_prison_cell *cell, | |
84 | struct bio_list *bios); | |
85 | void dm_cell_release_no_holder(struct dm_bio_prison *prison, | |
86 | struct dm_bio_prison_cell *cell, | |
87 | struct bio_list *inmates); | |
88 | void dm_cell_error(struct dm_bio_prison *prison, | |
af91805a | 89 | struct dm_bio_prison_cell *cell, int error); |
4f81a417 MS |
90 | |
91 | /*----------------------------------------------------------------*/ | |
92 | ||
93 | /* | |
94 | * We use the deferred set to keep track of pending reads to shared blocks. | |
95 | * We do this to ensure the new mapping caused by a write isn't performed | |
96 | * until these prior reads have completed. Otherwise the insertion of the | |
97 | * new mapping could free the old block that the read bios are mapped to. | |
98 | */ | |
99 | ||
100 | struct dm_deferred_set; | |
101 | struct dm_deferred_entry; | |
102 | ||
103 | struct dm_deferred_set *dm_deferred_set_create(void); | |
104 | void dm_deferred_set_destroy(struct dm_deferred_set *ds); | |
105 | ||
106 | struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds); | |
107 | void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head); | |
108 | int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work); | |
109 | ||
110 | /*----------------------------------------------------------------*/ | |
111 | ||
112 | #endif |