Skip to content

Commit 78d964c

Browse files
committed
Merge tag 'block-7.0-20260227' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
Pull block fixes from Jens Axboe: "Two sets of fixes, one for drbd, and one for the zoned loop driver" * tag 'block-7.0-20260227' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: zloop: check for spurious options passed to remove zloop: advertise a volatile write cache drbd: fix null-pointer dereference on local read error drbd: Replace deprecated strcpy with strscpy drbd: fix "LOGIC BUG" in drbd_al_begin_io_nonblock()
2 parents 530b0b6 + 3c46171 commit 78d964c

File tree

6 files changed

+64
-46
lines changed

6 files changed

+64
-46
lines changed

drivers/block/drbd/drbd_actlog.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -483,38 +483,20 @@ void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i)
483483

484484
int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i)
485485
{
486-
struct lru_cache *al = device->act_log;
487486
/* for bios crossing activity log extent boundaries,
488487
* we may need to activate two extents in one go */
489488
unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
490489
unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
491-
unsigned nr_al_extents;
492-
unsigned available_update_slots;
493490
unsigned enr;
494491

495-
D_ASSERT(device, first <= last);
496-
497-
nr_al_extents = 1 + last - first; /* worst case: all touched extends are cold. */
498-
available_update_slots = min(al->nr_elements - al->used,
499-
al->max_pending_changes - al->pending_changes);
500-
501-
/* We want all necessary updates for a given request within the same transaction
502-
* We could first check how many updates are *actually* needed,
503-
* and use that instead of the worst-case nr_al_extents */
504-
if (available_update_slots < nr_al_extents) {
505-
/* Too many activity log extents are currently "hot".
506-
*
507-
* If we have accumulated pending changes already,
508-
* we made progress.
509-
*
510-
* If we cannot get even a single pending change through,
511-
* stop the fast path until we made some progress,
512-
* or requests to "cold" extents could be starved. */
513-
if (!al->pending_changes)
514-
__set_bit(__LC_STARVING, &device->act_log->flags);
515-
return -ENOBUFS;
492+
if (i->partially_in_al_next_enr) {
493+
D_ASSERT(device, first < i->partially_in_al_next_enr);
494+
D_ASSERT(device, last >= i->partially_in_al_next_enr);
495+
first = i->partially_in_al_next_enr;
516496
}
517497

498+
D_ASSERT(device, first <= last);
499+
518500
/* Is resync active in this area? */
519501
for (enr = first; enr <= last; enr++) {
520502
struct lc_element *tmp;
@@ -529,14 +511,21 @@ int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *
529511
}
530512
}
531513

532-
/* Checkout the refcounts.
533-
* Given that we checked for available elements and update slots above,
534-
* this has to be successful. */
514+
/* Try to checkout the refcounts. */
535515
for (enr = first; enr <= last; enr++) {
536516
struct lc_element *al_ext;
537517
al_ext = lc_get_cumulative(device->act_log, enr);
538-
if (!al_ext)
539-
drbd_info(device, "LOGIC BUG for enr=%u\n", enr);
518+
519+
if (!al_ext) {
520+
/* Did not work. We may have exhausted the possible
521+
* changes per transaction. Or raced with someone
522+
* "locking" it against changes.
523+
* Remember where to continue from.
524+
*/
525+
if (enr > first)
526+
i->partially_in_al_next_enr = enr;
527+
return -ENOBUFS;
528+
}
540529
}
541530
return 0;
542531
}
@@ -556,7 +545,11 @@ void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i)
556545

557546
for (enr = first; enr <= last; enr++) {
558547
extent = lc_find(device->act_log, enr);
559-
if (!extent) {
548+
/* Yes, this masks a bug elsewhere. However, during normal
549+
* operation this is harmless, so no need to crash the kernel
550+
* by the BUG_ON(refcount == 0) in lc_put().
551+
*/
552+
if (!extent || extent->refcnt == 0) {
560553
drbd_err(device, "al_complete_io() called on inactive extent %u\n", enr);
561554
continue;
562555
}

drivers/block/drbd/drbd_interval.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
struct drbd_interval {
99
struct rb_node rb;
1010
sector_t sector; /* start sector of the interval */
11-
unsigned int size; /* size in bytes */
1211
sector_t end; /* highest interval end in subtree */
12+
unsigned int size; /* size in bytes */
1313
unsigned int local:1 /* local or remote request? */;
1414
unsigned int waiting:1; /* someone is waiting for completion */
1515
unsigned int completed:1; /* this has been completed already;
1616
* ignore for conflict detection */
17+
18+
/* to resume a partially successful drbd_al_begin_io_nonblock(); */
19+
unsigned int partially_in_al_next_enr;
1720
};
1821

1922
static inline void drbd_clear_interval(struct drbd_interval *i)

drivers/block/drbd/drbd_main.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/memcontrol.h>
3333
#include <linux/mm_inline.h>
3434
#include <linux/slab.h>
35+
#include <linux/string.h>
3536
#include <linux/random.h>
3637
#include <linux/reboot.h>
3738
#include <linux/notifier.h>
@@ -732,9 +733,9 @@ int drbd_send_sync_param(struct drbd_peer_device *peer_device)
732733
}
733734

734735
if (apv >= 88)
735-
strcpy(p->verify_alg, nc->verify_alg);
736+
strscpy(p->verify_alg, nc->verify_alg);
736737
if (apv >= 89)
737-
strcpy(p->csums_alg, nc->csums_alg);
738+
strscpy(p->csums_alg, nc->csums_alg);
738739
rcu_read_unlock();
739740

740741
return drbd_send_command(peer_device, sock, cmd, size, NULL, 0);
@@ -745,6 +746,7 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
745746
struct drbd_socket *sock;
746747
struct p_protocol *p;
747748
struct net_conf *nc;
749+
size_t integrity_alg_len;
748750
int size, cf;
749751

750752
sock = &connection->data;
@@ -762,8 +764,10 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
762764
}
763765

764766
size = sizeof(*p);
765-
if (connection->agreed_pro_version >= 87)
766-
size += strlen(nc->integrity_alg) + 1;
767+
if (connection->agreed_pro_version >= 87) {
768+
integrity_alg_len = strlen(nc->integrity_alg) + 1;
769+
size += integrity_alg_len;
770+
}
767771

768772
p->protocol = cpu_to_be32(nc->wire_protocol);
769773
p->after_sb_0p = cpu_to_be32(nc->after_sb_0p);
@@ -778,7 +782,7 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
778782
p->conn_flags = cpu_to_be32(cf);
779783

780784
if (connection->agreed_pro_version >= 87)
781-
strcpy(p->integrity_alg, nc->integrity_alg);
785+
strscpy(p->integrity_alg, nc->integrity_alg, integrity_alg_len);
782786
rcu_read_unlock();
783787

784788
return __conn_send_command(connection, sock, cmd, size, NULL, 0);

drivers/block/drbd/drbd_receiver.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3801,14 +3801,14 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i
38013801
*new_net_conf = *old_net_conf;
38023802

38033803
if (verify_tfm) {
3804-
strcpy(new_net_conf->verify_alg, p->verify_alg);
3804+
strscpy(new_net_conf->verify_alg, p->verify_alg);
38053805
new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1;
38063806
crypto_free_shash(peer_device->connection->verify_tfm);
38073807
peer_device->connection->verify_tfm = verify_tfm;
38083808
drbd_info(device, "using verify-alg: \"%s\"\n", p->verify_alg);
38093809
}
38103810
if (csums_tfm) {
3811-
strcpy(new_net_conf->csums_alg, p->csums_alg);
3811+
strscpy(new_net_conf->csums_alg, p->csums_alg);
38123812
new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1;
38133813
crypto_free_shash(peer_device->connection->csums_tfm);
38143814
peer_device->connection->csums_tfm = csums_tfm;

drivers/block/drbd/drbd_req.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
621621
break;
622622

623623
case READ_COMPLETED_WITH_ERROR:
624-
drbd_set_out_of_sync(peer_device, req->i.sector, req->i.size);
624+
drbd_set_out_of_sync(first_peer_device(device),
625+
req->i.sector, req->i.size);
625626
drbd_report_io_error(device, req);
626627
__drbd_chk_io_error(device, DRBD_READ_ERROR);
627628
fallthrough;

drivers/block/zloop.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,21 @@ static void zloop_rw(struct zloop_cmd *cmd)
542542
zloop_put_cmd(cmd);
543543
}
544544

545+
/*
546+
* Sync the entire FS containing the zone files instead of walking all files.
547+
*/
548+
static int zloop_flush(struct zloop_device *zlo)
549+
{
550+
struct super_block *sb = file_inode(zlo->data_dir)->i_sb;
551+
int ret;
552+
553+
down_read(&sb->s_umount);
554+
ret = sync_filesystem(sb);
555+
up_read(&sb->s_umount);
556+
557+
return ret;
558+
}
559+
545560
static void zloop_handle_cmd(struct zloop_cmd *cmd)
546561
{
547562
struct request *rq = blk_mq_rq_from_pdu(cmd);
@@ -562,11 +577,7 @@ static void zloop_handle_cmd(struct zloop_cmd *cmd)
562577
zloop_rw(cmd);
563578
return;
564579
case REQ_OP_FLUSH:
565-
/*
566-
* Sync the entire FS containing the zone files instead of
567-
* walking all files
568-
*/
569-
cmd->ret = sync_filesystem(file_inode(zlo->data_dir)->i_sb);
580+
cmd->ret = zloop_flush(zlo);
570581
break;
571582
case REQ_OP_ZONE_RESET:
572583
cmd->ret = zloop_reset_zone(zlo, rq_zone_no(rq));
@@ -981,7 +992,8 @@ static int zloop_ctl_add(struct zloop_options *opts)
981992
struct queue_limits lim = {
982993
.max_hw_sectors = SZ_1M >> SECTOR_SHIFT,
983994
.chunk_sectors = opts->zone_size,
984-
.features = BLK_FEAT_ZONED,
995+
.features = BLK_FEAT_ZONED | BLK_FEAT_WRITE_CACHE,
996+
985997
};
986998
unsigned int nr_zones, i, j;
987999
struct zloop_device *zlo;
@@ -1162,7 +1174,12 @@ static int zloop_ctl_remove(struct zloop_options *opts)
11621174
int ret;
11631175

11641176
if (!(opts->mask & ZLOOP_OPT_ID)) {
1165-
pr_err("No ID specified\n");
1177+
pr_err("No ID specified for remove\n");
1178+
return -EINVAL;
1179+
}
1180+
1181+
if (opts->mask & ~ZLOOP_OPT_ID) {
1182+
pr_err("Invalid option specified for remove\n");
11661183
return -EINVAL;
11671184
}
11681185

0 commit comments

Comments
 (0)