1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2011-2017 Red Hat, Inc. |
4 | * |
5 | * This file is released under the GPL. |
6 | */ |
7 | |
8 | #ifndef DM_BIO_PRISON_H |
9 | #define DM_BIO_PRISON_H |
10 | |
11 | #include "persistent-data/dm-block-manager.h" /* FIXME: for dm_block_t */ |
12 | #include "dm-thin-metadata.h" /* FIXME: for dm_thin_id */ |
13 | |
14 | #include <linux/bio.h> |
15 | #include <linux/rbtree.h> |
16 | |
17 | /*----------------------------------------------------------------*/ |
18 | |
19 | /* |
20 | * Sometimes we can't deal with a bio straight away. We put them in prison |
21 | * where they can't cause any mischief. Bios are put in a cell identified |
22 | * by a key, multiple bios can be in the same cell. When the cell is |
23 | * subsequently unlocked the bios become available. |
24 | */ |
25 | struct dm_bio_prison; |
26 | |
27 | /* |
28 | * Keys define a range of blocks within either a virtual or physical |
29 | * device. |
30 | */ |
31 | struct dm_cell_key { |
32 | int virtual; |
33 | dm_thin_id dev; |
34 | dm_block_t block_begin, block_end; |
35 | }; |
36 | |
37 | /* |
38 | * The range of a key (block_end - block_begin) must not |
39 | * exceed BIO_PRISON_MAX_RANGE. Also the range must not |
40 | * cross a similarly sized boundary. |
41 | * |
42 | * Must be a power of 2. |
43 | */ |
44 | #define BIO_PRISON_MAX_RANGE 1024 |
45 | #define BIO_PRISON_MAX_RANGE_SHIFT 10 |
46 | |
47 | /* |
48 | * Treat this as opaque, only in header so callers can manage allocation |
49 | * themselves. |
50 | */ |
51 | struct dm_bio_prison_cell { |
52 | struct list_head user_list; /* for client use */ |
53 | struct rb_node node; |
54 | |
55 | struct dm_cell_key key; |
56 | struct bio *holder; |
57 | struct bio_list bios; |
58 | }; |
59 | |
60 | struct dm_bio_prison *dm_bio_prison_create(void); |
61 | void dm_bio_prison_destroy(struct dm_bio_prison *prison); |
62 | |
63 | /* |
64 | * These two functions just wrap a mempool. This is a transitory step: |
65 | * Eventually all bio prison clients should manage their own cell memory. |
66 | * |
67 | * Like mempool_alloc(), dm_bio_prison_alloc_cell() can only fail if called |
68 | * in interrupt context or passed GFP_NOWAIT. |
69 | */ |
70 | struct dm_bio_prison_cell *dm_bio_prison_alloc_cell(struct dm_bio_prison *prison, |
71 | gfp_t gfp); |
72 | void dm_bio_prison_free_cell(struct dm_bio_prison *prison, |
73 | struct dm_bio_prison_cell *cell); |
74 | |
75 | /* |
76 | * Creates, or retrieves a cell that overlaps the given key. |
77 | * |
78 | * Returns 1 if pre-existing cell returned, zero if new cell created using |
79 | * @cell_prealloc. |
80 | */ |
81 | int dm_get_cell(struct dm_bio_prison *prison, |
82 | struct dm_cell_key *key, |
83 | struct dm_bio_prison_cell *cell_prealloc, |
84 | struct dm_bio_prison_cell **cell_result); |
85 | |
86 | /* |
87 | * Returns false if key is beyond BIO_PRISON_MAX_RANGE or spans a boundary. |
88 | */ |
89 | bool dm_cell_key_has_valid_range(struct dm_cell_key *key); |
90 | |
91 | /* |
92 | * An atomic op that combines retrieving or creating a cell, and adding a |
93 | * bio to it. |
94 | * |
95 | * Returns 1 if the cell was already held, 0 if @inmate is the new holder. |
96 | */ |
97 | int dm_bio_detain(struct dm_bio_prison *prison, |
98 | struct dm_cell_key *key, |
99 | struct bio *inmate, |
100 | struct dm_bio_prison_cell *cell_prealloc, |
101 | struct dm_bio_prison_cell **cell_result); |
102 | |
103 | void dm_cell_release(struct dm_bio_prison *prison, |
104 | struct dm_bio_prison_cell *cell, |
105 | struct bio_list *bios); |
106 | void dm_cell_release_no_holder(struct dm_bio_prison *prison, |
107 | struct dm_bio_prison_cell *cell, |
108 | struct bio_list *inmates); |
109 | void dm_cell_error(struct dm_bio_prison *prison, |
110 | struct dm_bio_prison_cell *cell, blk_status_t error); |
111 | |
112 | /* |
113 | * Visits the cell and then releases. Guarantees no new inmates are |
114 | * inserted between the visit and release. |
115 | */ |
116 | void dm_cell_visit_release(struct dm_bio_prison *prison, |
117 | void (*visit_fn)(void *, struct dm_bio_prison_cell *), |
118 | void *context, struct dm_bio_prison_cell *cell); |
119 | |
120 | /* |
121 | * Rather than always releasing the prisoners in a cell, the client may |
122 | * want to promote one of them to be the new holder. There is a race here |
123 | * though between releasing an empty cell, and other threads adding new |
124 | * inmates. So this function makes the decision with its lock held. |
125 | * |
126 | * This function can have two outcomes: |
127 | * i) An inmate is promoted to be the holder of the cell (return value of 0). |
128 | * ii) The cell has no inmate for promotion and is released (return value of 1). |
129 | */ |
130 | int dm_cell_promote_or_release(struct dm_bio_prison *prison, |
131 | struct dm_bio_prison_cell *cell); |
132 | |
133 | /*----------------------------------------------------------------*/ |
134 | |
135 | /* |
136 | * We use the deferred set to keep track of pending reads to shared blocks. |
137 | * We do this to ensure the new mapping caused by a write isn't performed |
138 | * until these prior reads have completed. Otherwise the insertion of the |
139 | * new mapping could free the old block that the read bios are mapped to. |
140 | */ |
141 | |
142 | struct dm_deferred_set; |
143 | struct dm_deferred_entry; |
144 | |
145 | struct dm_deferred_set *dm_deferred_set_create(void); |
146 | void dm_deferred_set_destroy(struct dm_deferred_set *ds); |
147 | |
148 | struct dm_deferred_entry *dm_deferred_entry_inc(struct dm_deferred_set *ds); |
149 | void dm_deferred_entry_dec(struct dm_deferred_entry *entry, struct list_head *head); |
150 | int dm_deferred_set_add_work(struct dm_deferred_set *ds, struct list_head *work); |
151 | |
152 | /*----------------------------------------------------------------*/ |
153 | |
154 | #endif |
155 | |