Skip to content

Commit 4368fc6

Browse files
committed
Merge branch 'for-7.1/block' into for-next
* for-7.1/block: zloop: add max_open_zones option
2 parents 7fa8af9 + b2a78fe commit 4368fc6

2 files changed

Lines changed: 168 additions & 17 deletions

File tree

Documentation/admin-guide/blockdev/zoned_loop.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ The options available for the add command can be listed by reading the
6262
/dev/zloop-control device::
6363

6464
$ cat /dev/zloop-control
65-
add id=%d,capacity_mb=%u,zone_size_mb=%u,zone_capacity_mb=%u,conv_zones=%u,base_dir=%s,nr_queues=%u,queue_depth=%u,buffered_io
65+
add id=%d,capacity_mb=%u,zone_size_mb=%u,zone_capacity_mb=%u,conv_zones=%u,max_open_zones=%u,base_dir=%s,nr_queues=%u,queue_depth=%u,buffered_io,zone_append=%u,ordered_zone_append,discard_write_cache
6666
remove id=%d
6767

6868
In more details, the options that can be used with the "add" command are as
@@ -80,6 +80,9 @@ zone_capacity_mb Device zone capacity (must always be equal to or lower
8080
conv_zones Total number of conventioanl zones starting from
8181
sector 0
8282
Default: 8
83+
max_open_zones Maximum number of open sequential write required zones
84+
(0 for no limit).
85+
Default: 0
8386
base_dir Path to the base directory where to create the directory
8487
containing the zone files of the device.
8588
Default=/var/local/zloop.

drivers/block/zloop.c

Lines changed: 164 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ enum {
3636
ZLOOP_OPT_ZONE_APPEND = (1 << 9),
3737
ZLOOP_OPT_ORDERED_ZONE_APPEND = (1 << 10),
3838
ZLOOP_OPT_DISCARD_WRITE_CACHE = (1 << 11),
39+
ZLOOP_OPT_MAX_OPEN_ZONES = (1 << 12),
3940
};
4041

4142
static const match_table_t zloop_opt_tokens = {
@@ -51,6 +52,7 @@ static const match_table_t zloop_opt_tokens = {
5152
{ ZLOOP_OPT_ZONE_APPEND, "zone_append=%u" },
5253
{ ZLOOP_OPT_ORDERED_ZONE_APPEND, "ordered_zone_append" },
5354
{ ZLOOP_OPT_DISCARD_WRITE_CACHE, "discard_write_cache" },
55+
{ ZLOOP_OPT_MAX_OPEN_ZONES, "max_open_zones=%u" },
5456
{ ZLOOP_OPT_ERR, NULL }
5557
};
5658

@@ -59,6 +61,7 @@ static const match_table_t zloop_opt_tokens = {
5961
#define ZLOOP_DEF_ZONE_SIZE ((256ULL * SZ_1M) >> SECTOR_SHIFT)
6062
#define ZLOOP_DEF_NR_ZONES 64
6163
#define ZLOOP_DEF_NR_CONV_ZONES 8
64+
#define ZLOOP_DEF_MAX_OPEN_ZONES 0
6265
#define ZLOOP_DEF_BASE_DIR "/var/local/zloop"
6366
#define ZLOOP_DEF_NR_QUEUES 1
6467
#define ZLOOP_DEF_QUEUE_DEPTH 128
@@ -76,6 +79,7 @@ struct zloop_options {
7679
sector_t zone_size;
7780
sector_t zone_capacity;
7881
unsigned int nr_conv_zones;
82+
unsigned int max_open_zones;
7983
char *base_dir;
8084
unsigned int nr_queues;
8185
unsigned int queue_depth;
@@ -99,7 +103,12 @@ enum zloop_zone_flags {
99103
ZLOOP_ZONE_SEQ_ERROR,
100104
};
101105

106+
/*
107+
* Zone descriptor.
108+
* Locking order: z.lock -> z.wp_lock -> zlo.open_zones_lock
109+
*/
102110
struct zloop_zone {
111+
struct list_head open_zone_entry;
103112
struct file *file;
104113

105114
unsigned long flags;
@@ -133,8 +142,13 @@ struct zloop_device {
133142
sector_t zone_capacity;
134143
unsigned int nr_zones;
135144
unsigned int nr_conv_zones;
145+
unsigned int max_open_zones;
136146
unsigned int block_size;
137147

148+
spinlock_t open_zones_lock;
149+
struct list_head open_zones_lru_list;
150+
unsigned int nr_open_zones;
151+
138152
struct zloop_zone zones[] __counted_by(nr_zones);
139153
};
140154

@@ -158,6 +172,122 @@ static unsigned int rq_zone_no(struct request *rq)
158172
return blk_rq_pos(rq) >> zlo->zone_shift;
159173
}
160174

175+
/*
176+
* Open an already open zone. This is mostly a no-op, except for the imp open ->
177+
* exp open condition change that may happen. We also move a zone at the tail of
178+
* the list of open zones so that if we need to
179+
* implicitly close one open zone, we can do so in LRU order.
180+
*/
181+
static inline void zloop_lru_rotate_open_zone(struct zloop_device *zlo,
182+
struct zloop_zone *zone)
183+
{
184+
if (zlo->max_open_zones) {
185+
spin_lock(&zlo->open_zones_lock);
186+
list_move_tail(&zone->open_zone_entry,
187+
&zlo->open_zones_lru_list);
188+
spin_unlock(&zlo->open_zones_lock);
189+
}
190+
}
191+
192+
static inline void zloop_lru_remove_open_zone(struct zloop_device *zlo,
193+
struct zloop_zone *zone)
194+
{
195+
if (zone->cond == BLK_ZONE_COND_IMP_OPEN ||
196+
zone->cond == BLK_ZONE_COND_EXP_OPEN) {
197+
spin_lock(&zlo->open_zones_lock);
198+
list_del_init(&zone->open_zone_entry);
199+
zlo->nr_open_zones--;
200+
spin_unlock(&zlo->open_zones_lock);
201+
}
202+
}
203+
204+
static inline bool zloop_can_open_zone(struct zloop_device *zlo)
205+
{
206+
return !zlo->max_open_zones || zlo->nr_open_zones < zlo->max_open_zones;
207+
}
208+
209+
/*
210+
* If we have reached the maximum open zones limit, attempt to close an
211+
* implicitly open zone (if we have any) so that we can implicitly open another
212+
* zone without exceeding the maximum number of open zones.
213+
*/
214+
static bool zloop_close_imp_open_zone(struct zloop_device *zlo)
215+
{
216+
struct zloop_zone *zone;
217+
218+
lockdep_assert_held(&zlo->open_zones_lock);
219+
220+
if (zloop_can_open_zone(zlo))
221+
return true;
222+
223+
list_for_each_entry(zone, &zlo->open_zones_lru_list, open_zone_entry) {
224+
if (zone->cond == BLK_ZONE_COND_IMP_OPEN) {
225+
zone->cond = BLK_ZONE_COND_CLOSED;
226+
list_del_init(&zone->open_zone_entry);
227+
zlo->nr_open_zones--;
228+
return true;
229+
}
230+
}
231+
232+
return false;
233+
}
234+
235+
static bool zloop_open_closed_or_empty_zone(struct zloop_device *zlo,
236+
struct zloop_zone *zone,
237+
bool explicit)
238+
{
239+
spin_lock(&zlo->open_zones_lock);
240+
241+
if (explicit) {
242+
/*
243+
* Explicit open: we cannot allow this if we have reached the
244+
* maximum open zones limit.
245+
*/
246+
if (!zloop_can_open_zone(zlo))
247+
goto fail;
248+
zone->cond = BLK_ZONE_COND_EXP_OPEN;
249+
} else {
250+
/*
251+
* Implicit open case: if we have reached the maximum open zones
252+
* limit, try to close an implicitly open zone first.
253+
*/
254+
if (!zloop_close_imp_open_zone(zlo))
255+
goto fail;
256+
zone->cond = BLK_ZONE_COND_IMP_OPEN;
257+
}
258+
259+
zlo->nr_open_zones++;
260+
list_add_tail(&zone->open_zone_entry,
261+
&zlo->open_zones_lru_list);
262+
263+
spin_unlock(&zlo->open_zones_lock);
264+
265+
return true;
266+
267+
fail:
268+
spin_unlock(&zlo->open_zones_lock);
269+
270+
return false;
271+
}
272+
273+
static bool zloop_do_open_zone(struct zloop_device *zlo,
274+
struct zloop_zone *zone, bool explicit)
275+
{
276+
switch (zone->cond) {
277+
case BLK_ZONE_COND_IMP_OPEN:
278+
case BLK_ZONE_COND_EXP_OPEN:
279+
if (explicit)
280+
zone->cond = BLK_ZONE_COND_EXP_OPEN;
281+
zloop_lru_rotate_open_zone(zlo, zone);
282+
return true;
283+
case BLK_ZONE_COND_EMPTY:
284+
case BLK_ZONE_COND_CLOSED:
285+
return zloop_open_closed_or_empty_zone(zlo, zone, explicit);
286+
default:
287+
return false;
288+
}
289+
}
290+
161291
static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no)
162292
{
163293
struct zloop_zone *zone = &zlo->zones[zone_no];
@@ -191,13 +321,17 @@ static int zloop_update_seq_zone(struct zloop_device *zlo, unsigned int zone_no)
191321

192322
spin_lock_irqsave(&zone->wp_lock, flags);
193323
if (!file_sectors) {
324+
zloop_lru_remove_open_zone(zlo, zone);
194325
zone->cond = BLK_ZONE_COND_EMPTY;
195326
zone->wp = zone->start;
196327
} else if (file_sectors == zlo->zone_capacity) {
328+
zloop_lru_remove_open_zone(zlo, zone);
197329
zone->cond = BLK_ZONE_COND_FULL;
198330
zone->wp = ULLONG_MAX;
199331
} else {
200-
zone->cond = BLK_ZONE_COND_CLOSED;
332+
if (zone->cond != BLK_ZONE_COND_IMP_OPEN &&
333+
zone->cond != BLK_ZONE_COND_EXP_OPEN)
334+
zone->cond = BLK_ZONE_COND_CLOSED;
201335
zone->wp = zone->start + file_sectors;
202336
}
203337
spin_unlock_irqrestore(&zone->wp_lock, flags);
@@ -221,19 +355,8 @@ static int zloop_open_zone(struct zloop_device *zlo, unsigned int zone_no)
221355
goto unlock;
222356
}
223357

224-
switch (zone->cond) {
225-
case BLK_ZONE_COND_EXP_OPEN:
226-
break;
227-
case BLK_ZONE_COND_EMPTY:
228-
case BLK_ZONE_COND_CLOSED:
229-
case BLK_ZONE_COND_IMP_OPEN:
230-
zone->cond = BLK_ZONE_COND_EXP_OPEN;
231-
break;
232-
case BLK_ZONE_COND_FULL:
233-
default:
358+
if (!zloop_do_open_zone(zlo, zone, true))
234359
ret = -EIO;
235-
break;
236-
}
237360

238361
unlock:
239362
mutex_unlock(&zone->lock);
@@ -264,6 +387,7 @@ static int zloop_close_zone(struct zloop_device *zlo, unsigned int zone_no)
264387
case BLK_ZONE_COND_IMP_OPEN:
265388
case BLK_ZONE_COND_EXP_OPEN:
266389
spin_lock_irqsave(&zone->wp_lock, flags);
390+
zloop_lru_remove_open_zone(zlo, zone);
267391
if (zone->wp == zone->start)
268392
zone->cond = BLK_ZONE_COND_EMPTY;
269393
else
@@ -305,6 +429,7 @@ static int zloop_reset_zone(struct zloop_device *zlo, unsigned int zone_no)
305429
}
306430

307431
spin_lock_irqsave(&zone->wp_lock, flags);
432+
zloop_lru_remove_open_zone(zlo, zone);
308433
zone->cond = BLK_ZONE_COND_EMPTY;
309434
zone->wp = zone->start;
310435
clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags);
@@ -352,6 +477,7 @@ static int zloop_finish_zone(struct zloop_device *zlo, unsigned int zone_no)
352477
}
353478

354479
spin_lock_irqsave(&zone->wp_lock, flags);
480+
zloop_lru_remove_open_zone(zlo, zone);
355481
zone->cond = BLK_ZONE_COND_FULL;
356482
zone->wp = ULLONG_MAX;
357483
clear_bit(ZLOOP_ZONE_SEQ_ERROR, &zone->flags);
@@ -478,9 +604,10 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd)
478604
}
479605

480606
/* Implicitly open the target zone. */
481-
if (zone->cond == BLK_ZONE_COND_CLOSED ||
482-
zone->cond == BLK_ZONE_COND_EMPTY)
483-
zone->cond = BLK_ZONE_COND_IMP_OPEN;
607+
if (!zloop_do_open_zone(zlo, zone, false)) {
608+
ret = -EIO;
609+
goto out_unlock;
610+
}
484611

485612
/*
486613
* Advance the write pointer, unless ordered zone append is in use. If
@@ -490,6 +617,7 @@ static int zloop_seq_write_prep(struct zloop_cmd *cmd)
490617
if (!is_append || !zlo->ordered_zone_append) {
491618
zone->wp += nr_sectors;
492619
if (zone->wp == zone_end) {
620+
zloop_lru_remove_open_zone(zlo, zone);
493621
zone->cond = BLK_ZONE_COND_FULL;
494622
zone->wp = ULLONG_MAX;
495623
}
@@ -746,6 +874,7 @@ static bool zloop_set_zone_append_sector(struct request *rq)
746874
rq->__sector = zone->wp;
747875
zone->wp += blk_rq_sectors(rq);
748876
if (zone->wp >= zone_end) {
877+
zloop_lru_remove_open_zone(zlo, zone);
749878
zone->cond = BLK_ZONE_COND_FULL;
750879
zone->wp = ULLONG_MAX;
751880
}
@@ -943,6 +1072,7 @@ static int zloop_init_zone(struct zloop_device *zlo, struct zloop_options *opts,
9431072
int ret;
9441073

9451074
mutex_init(&zone->lock);
1075+
INIT_LIST_HEAD(&zone->open_zone_entry);
9461076
spin_lock_init(&zone->wp_lock);
9471077
zone->start = (sector_t)zone_no << zlo->zone_shift;
9481078

@@ -1063,12 +1193,20 @@ static int zloop_ctl_add(struct zloop_options *opts)
10631193
goto out;
10641194
}
10651195

1196+
if (opts->max_open_zones > nr_zones - opts->nr_conv_zones) {
1197+
pr_err("Invalid maximum number of open zones %u\n",
1198+
opts->max_open_zones);
1199+
goto out;
1200+
}
1201+
10661202
zlo = kvzalloc_flex(*zlo, zones, nr_zones);
10671203
if (!zlo) {
10681204
ret = -ENOMEM;
10691205
goto out;
10701206
}
10711207
WRITE_ONCE(zlo->state, Zlo_creating);
1208+
spin_lock_init(&zlo->open_zones_lock);
1209+
INIT_LIST_HEAD(&zlo->open_zones_lru_list);
10721210

10731211
ret = mutex_lock_killable(&zloop_ctl_mutex);
10741212
if (ret)
@@ -1096,6 +1234,7 @@ static int zloop_ctl_add(struct zloop_options *opts)
10961234
zlo->zone_capacity = zlo->zone_size;
10971235
zlo->nr_zones = nr_zones;
10981236
zlo->nr_conv_zones = opts->nr_conv_zones;
1237+
zlo->max_open_zones = opts->max_open_zones;
10991238
zlo->buffered_io = opts->buffered_io;
11001239
zlo->zone_append = opts->zone_append;
11011240
if (zlo->zone_append)
@@ -1143,6 +1282,7 @@ static int zloop_ctl_add(struct zloop_options *opts)
11431282
lim.logical_block_size = zlo->block_size;
11441283
if (zlo->zone_append)
11451284
lim.max_hw_zone_append_sectors = lim.max_hw_sectors;
1285+
lim.max_open_zones = zlo->max_open_zones;
11461286

11471287
zlo->tag_set.ops = &zloop_mq_ops;
11481288
zlo->tag_set.nr_hw_queues = opts->nr_queues;
@@ -1326,6 +1466,7 @@ static int zloop_parse_options(struct zloop_options *opts, const char *buf)
13261466
opts->capacity = ZLOOP_DEF_ZONE_SIZE * ZLOOP_DEF_NR_ZONES;
13271467
opts->zone_size = ZLOOP_DEF_ZONE_SIZE;
13281468
opts->nr_conv_zones = ZLOOP_DEF_NR_CONV_ZONES;
1469+
opts->max_open_zones = ZLOOP_DEF_MAX_OPEN_ZONES;
13291470
opts->nr_queues = ZLOOP_DEF_NR_QUEUES;
13301471
opts->queue_depth = ZLOOP_DEF_QUEUE_DEPTH;
13311472
opts->buffered_io = ZLOOP_DEF_BUFFERED_IO;
@@ -1404,6 +1545,13 @@ static int zloop_parse_options(struct zloop_options *opts, const char *buf)
14041545
}
14051546
opts->nr_conv_zones = token;
14061547
break;
1548+
case ZLOOP_OPT_MAX_OPEN_ZONES:
1549+
if (match_uint(args, &token)) {
1550+
ret = -EINVAL;
1551+
goto out;
1552+
}
1553+
opts->max_open_zones = token;
1554+
break;
14071555
case ZLOOP_OPT_BASE_DIR:
14081556
p = match_strdup(args);
14091557
if (!p) {

0 commit comments

Comments
 (0)