Skip to content

Commit bb37d77

Browse files
damien-lemoalsnitm
authored andcommitted
dm: introduce zone append emulation
For zoned targets that cannot support zone append operations, implement an emulation using regular write operations. If the original BIO submitted by the user is a zone append operation, change its clone into a regular write operation directed at the target zone write pointer position. To do so, an array of write pointer offsets (write pointer position relative to the start of a zone) is added to struct mapped_device. All operations that modify a sequential zone write pointer (writes, zone reset, zone finish and zone append) are intersepted in __map_bio() and processed using the new functions dm_zone_map_bio(). Detection of the target ability to natively support zone append operations is done from dm_table_set_restrictions() by calling the function dm_set_zones_restrictions(). A target that does not support zone append operation, either by explicitly declaring it using the new struct dm_target field zone_append_not_supported, or because the device table contains a non-zoned device, has its mapped device marked with the new flag DMF_ZONE_APPEND_EMULATED. The helper function dm_emulate_zone_append() is introduced to test a mapped device for this new flag. Atomicity of the zones write pointer tracking and updates is done using a zone write locking mechanism based on a bitmap. This is similar to the block layer method but based on BIOs rather than struct request. A zone write lock is taken in dm_zone_map_bio() for any clone BIO with an operation type that changes the BIO target zone write pointer position. The zone write lock is released if the clone BIO is failed before submission or when dm_zone_endio() is called when the clone BIO completes. The zone write lock bitmap of the mapped device, together with a bitmap indicating zone types (conv_zones_bitmap) and the write pointer offset array (zwp_offset) are allocated and initialized with a full device zone report in dm_set_zones_restrictions() using the function dm_revalidate_zones(). For failed operations that may have modified a zone write pointer, the zone write pointer offset is marked as invalid in dm_zone_endio(). Zones with an invalid write pointer offset are checked and the write pointer updated using an internal report zone operation when the faulty zone is accessed again by the user. All functions added for this emulation have a minimal overhead for zoned targets natively supporting zone append operations. Regular device targets are also not affected. The added code also does not impact builds with CONFIG_BLK_DEV_ZONED disabled by stubbing out all dm zone related functions. Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
1 parent e2118b3 commit bb37d77

File tree

6 files changed

+618
-54
lines changed

6 files changed

+618
-54
lines changed

drivers/md/dm-core.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ struct mapped_device {
114114
bool init_tio_pdu:1;
115115

116116
struct srcu_struct io_barrier;
117+
118+
#ifdef CONFIG_BLK_DEV_ZONED
119+
unsigned int nr_zones;
120+
unsigned int *zwp_offset;
121+
#endif
117122
};
118123

119124
/*
@@ -128,6 +133,7 @@ struct mapped_device {
128133
#define DMF_DEFERRED_REMOVE 6
129134
#define DMF_SUSPENDED_INTERNALLY 7
130135
#define DMF_POST_SUSPENDING 8
136+
#define DMF_EMULATE_ZONE_APPEND 9
131137

132138
void disable_discard(struct mapped_device *md);
133139
void disable_write_same(struct mapped_device *md);
@@ -143,6 +149,13 @@ static inline struct dm_stats *dm_get_stats(struct mapped_device *md)
143149
return &md->stats;
144150
}
145151

152+
static inline bool dm_emulate_zone_append(struct mapped_device *md)
153+
{
154+
if (blk_queue_is_zoned(md->queue))
155+
return test_bit(DMF_EMULATE_ZONE_APPEND, &md->flags);
156+
return false;
157+
}
158+
146159
#define DM_TABLE_MAX_DEPTH 16
147160

148161
struct dm_table {

drivers/md/dm-table.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,11 +1981,12 @@ static int device_requires_stable_pages(struct dm_target *ti,
19811981
return blk_queue_stable_writes(q);
19821982
}
19831983

1984-
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1985-
struct queue_limits *limits)
1984+
int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1985+
struct queue_limits *limits)
19861986
{
19871987
bool wc = false, fua = false;
19881988
int page_size = PAGE_SIZE;
1989+
int r;
19891990

19901991
/*
19911992
* Copy table's limits to the DM device's request_queue
@@ -2064,12 +2065,20 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
20642065
dm_table_any_dev_attr(t, device_is_not_random, NULL))
20652066
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
20662067

2067-
/* For a zoned target, setup the zones related queue attributes */
2068-
if (blk_queue_is_zoned(q))
2069-
dm_set_zones_restrictions(t, q);
2068+
/*
2069+
* For a zoned target, setup the zones related queue attributes
2070+
* and resources necessary for zone append emulation if necessary.
2071+
*/
2072+
if (blk_queue_is_zoned(q)) {
2073+
r = dm_set_zones_restrictions(t, q);
2074+
if (r)
2075+
return r;
2076+
}
20702077

20712078
dm_update_keyslot_manager(q, t);
20722079
blk_queue_update_readahead(q);
2080+
2081+
return 0;
20732082
}
20742083

20752084
unsigned int dm_table_get_num_targets(struct dm_table *t)

0 commit comments

Comments
 (0)