Skip to content

Commit

Permalink
Merge tag 'block-6.15-20250411' of git://git.kernel.dk/linux
Browse files Browse the repository at this point in the history
Pull more block fixes from Jens Axboe:
 "Apparently my internal clock was off, or perhaps it was just wishful
  thinking, but I sent out block fixes yesterday as my brain assumed it
  was Friday. Subsequently, that missed the NVMe fixes that should go
  into this weeks release as well. Hence, here's a followup with those,
  and another simple fix.

   - NVMe pull request via Christoph:
       - nvmet fc/fcloop refcounting fixes (Daniel Wagner)
       - fix missed namespace/ANA scans (Hannes Reinecke)
       - fix a use after free in the new TCP netns support (Kuniyuki
         Iwashima)
       - fix a NULL instead of false review in multipath (Uday Shankar)

   - Use strscpy() for null_blk disk name copy"

* tag 'block-6.15-20250411' of git://git.kernel.dk/linux:
  null_blk: Use strscpy() instead of strscpy_pad() in null_add_dev()
  nvmet-fc: put ref when assoc->del_work is already scheduled
  nvmet-fc: take tgtport reference only once
  nvmet-fc: update tgtport ref per assoc
  nvmet-fc: inline nvmet_fc_free_hostport
  nvmet-fc: inline nvmet_fc_delete_assoc
  nvmet-fcloop: add ref counting to lport
  nvmet-fcloop: replace kref with refcount
  nvmet-fcloop: swap list_add_tail arguments
  nvme-tcp: fix use-after-free of netns by kernel TCP socket.
  nvme: multipath: fix return value of nvme_available_path
  nvme: re-read ANA log page after ns scan completes
  nvme: requeue namespace scan on missed AENs
  • Loading branch information
Linus Torvalds committed Apr 11, 2025
2 parents 023e62c + 3b607b7 commit ff88562
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 76 deletions.
2 changes: 1 addition & 1 deletion drivers/block/null_blk/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2031,7 +2031,7 @@ static int null_add_dev(struct nullb_device *dev)
nullb->disk->minors = 1;
nullb->disk->fops = &null_ops;
nullb->disk->private_data = nullb;
strscpy_pad(nullb->disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
strscpy(nullb->disk->disk_name, nullb->disk_name);

if (nullb->dev->zoned) {
rv = null_register_zoned_dev(nullb);
Expand Down
9 changes: 9 additions & 0 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4295,6 +4295,15 @@ static void nvme_scan_work(struct work_struct *work)
nvme_scan_ns_sequential(ctrl);
}
mutex_unlock(&ctrl->scan_lock);

/* Requeue if we have missed AENs */
if (test_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events))
nvme_queue_scan(ctrl);
#ifdef CONFIG_NVME_MULTIPATH
else
/* Re-read the ANA log page to not miss updates */
queue_work(nvme_wq, &ctrl->ana_work);
#endif
}

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/nvme/host/multipath.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ static bool nvme_available_path(struct nvme_ns_head *head)
struct nvme_ns *ns;

if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
return NULL;
return false;

list_for_each_entry_srcu(ns, &head->list, siblings,
srcu_read_lock_held(&head->srcu)) {
Expand Down
2 changes: 2 additions & 0 deletions drivers/nvme/host/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1803,6 +1803,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
ret = PTR_ERR(sock_file);
goto err_destroy_mutex;
}

sk_net_refcnt_upgrade(queue->sock->sk);
nvme_tcp_reclassify_socket(queue->sock);

/* Single syn retry */
Expand Down
60 changes: 20 additions & 40 deletions drivers/nvme/target/fc.c
Original file line number Diff line number Diff line change
Expand Up @@ -995,16 +995,6 @@ nvmet_fc_hostport_get(struct nvmet_fc_hostport *hostport)
return kref_get_unless_zero(&hostport->ref);
}

static void
nvmet_fc_free_hostport(struct nvmet_fc_hostport *hostport)
{
/* if LLDD not implemented, leave as NULL */
if (!hostport || !hostport->hosthandle)
return;

nvmet_fc_hostport_put(hostport);
}

static struct nvmet_fc_hostport *
nvmet_fc_match_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
{
Expand All @@ -1028,33 +1018,24 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
struct nvmet_fc_hostport *newhost, *match = NULL;
unsigned long flags;

/*
* Caller holds a reference on tgtport.
*/

/* if LLDD not implemented, leave as NULL */
if (!hosthandle)
return NULL;

/*
* take reference for what will be the newly allocated hostport if
* we end up using a new allocation
*/
if (!nvmet_fc_tgtport_get(tgtport))
return ERR_PTR(-EINVAL);

spin_lock_irqsave(&tgtport->lock, flags);
match = nvmet_fc_match_hostport(tgtport, hosthandle);
spin_unlock_irqrestore(&tgtport->lock, flags);

if (match) {
/* no new allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
if (match)
return match;
}

newhost = kzalloc(sizeof(*newhost), GFP_KERNEL);
if (!newhost) {
/* no new allocation - release reference */
nvmet_fc_tgtport_put(tgtport);
if (!newhost)
return ERR_PTR(-ENOMEM);
}

spin_lock_irqsave(&tgtport->lock, flags);
match = nvmet_fc_match_hostport(tgtport, hosthandle);
Expand All @@ -1063,6 +1044,7 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
kfree(newhost);
newhost = match;
} else {
nvmet_fc_tgtport_get(tgtport);
newhost->tgtport = tgtport;
newhost->hosthandle = hosthandle;
INIT_LIST_HEAD(&newhost->host_list);
Expand All @@ -1075,29 +1057,24 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
return newhost;
}

static void
nvmet_fc_delete_assoc(struct nvmet_fc_tgt_assoc *assoc)
{
nvmet_fc_delete_target_assoc(assoc);
nvmet_fc_tgt_a_put(assoc);
}

static void
nvmet_fc_delete_assoc_work(struct work_struct *work)
{
struct nvmet_fc_tgt_assoc *assoc =
container_of(work, struct nvmet_fc_tgt_assoc, del_work);
struct nvmet_fc_tgtport *tgtport = assoc->tgtport;

nvmet_fc_delete_assoc(assoc);
nvmet_fc_delete_target_assoc(assoc);
nvmet_fc_tgt_a_put(assoc);
nvmet_fc_tgtport_put(tgtport);
}

static void
nvmet_fc_schedule_delete_assoc(struct nvmet_fc_tgt_assoc *assoc)
{
nvmet_fc_tgtport_get(assoc->tgtport);
queue_work(nvmet_wq, &assoc->del_work);
if (!queue_work(nvmet_wq, &assoc->del_work))
nvmet_fc_tgtport_put(assoc->tgtport);
}

static bool
Expand Down Expand Up @@ -1143,6 +1120,7 @@ nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
goto out_ida;

assoc->tgtport = tgtport;
nvmet_fc_tgtport_get(tgtport);
assoc->a_id = idx;
INIT_LIST_HEAD(&assoc->a_list);
kref_init(&assoc->ref);
Expand Down Expand Up @@ -1190,7 +1168,7 @@ nvmet_fc_target_assoc_free(struct kref *ref)
/* Send Disconnect now that all i/o has completed */
nvmet_fc_xmt_disconnect_assoc(assoc);

nvmet_fc_free_hostport(assoc->hostport);
nvmet_fc_hostport_put(assoc->hostport);
spin_lock_irqsave(&tgtport->lock, flags);
oldls = assoc->rcv_disconn;
spin_unlock_irqrestore(&tgtport->lock, flags);
Expand Down Expand Up @@ -1244,6 +1222,8 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc)
dev_info(tgtport->dev,
"{%d:%d} Association deleted\n",
tgtport->fc_target_port.port_num, assoc->a_id);

nvmet_fc_tgtport_put(tgtport);
}

static struct nvmet_fc_tgt_assoc *
Expand Down Expand Up @@ -1455,11 +1435,6 @@ nvmet_fc_free_tgtport(struct kref *ref)
struct nvmet_fc_tgtport *tgtport =
container_of(ref, struct nvmet_fc_tgtport, ref);
struct device *dev = tgtport->dev;
unsigned long flags;

spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
list_del(&tgtport->tgt_list);
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);

nvmet_fc_free_ls_iodlist(tgtport);

Expand Down Expand Up @@ -1620,6 +1595,11 @@ int
nvmet_fc_unregister_targetport(struct nvmet_fc_target_port *target_port)
{
struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
unsigned long flags;

spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
list_del(&tgtport->tgt_list);
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);

nvmet_fc_portentry_unbind_tgt(tgtport);

Expand Down
74 changes: 40 additions & 34 deletions drivers/nvme/target/fcloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ struct fcloop_lport {
struct nvme_fc_local_port *localport;
struct list_head lport_list;
struct completion unreg_done;
refcount_t ref;
};

struct fcloop_lport_priv {
Expand Down Expand Up @@ -239,7 +240,7 @@ struct fcloop_nport {
struct fcloop_tport *tport;
struct fcloop_lport *lport;
struct list_head nport_list;
struct kref ref;
refcount_t ref;
u64 node_name;
u64 port_name;
u32 port_role;
Expand Down Expand Up @@ -274,7 +275,7 @@ struct fcloop_fcpreq {
u32 inistate;
bool active;
bool aborted;
struct kref ref;
refcount_t ref;
struct work_struct fcp_rcv_work;
struct work_struct abort_rcv_work;
struct work_struct tio_done_work;
Expand Down Expand Up @@ -478,7 +479,7 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport,
if (targetport) {
tport = targetport->private;
spin_lock(&tport->lock);
list_add_tail(&tport->ls_list, &tls_req->ls_list);
list_add_tail(&tls_req->ls_list, &tport->ls_list);
spin_unlock(&tport->lock);
queue_work(nvmet_wq, &tport->ls_work);
}
Expand Down Expand Up @@ -534,24 +535,18 @@ fcloop_tgt_discovery_evt(struct nvmet_fc_target_port *tgtport)
}

static void
fcloop_tfcp_req_free(struct kref *ref)
fcloop_tfcp_req_put(struct fcloop_fcpreq *tfcp_req)
{
struct fcloop_fcpreq *tfcp_req =
container_of(ref, struct fcloop_fcpreq, ref);
if (!refcount_dec_and_test(&tfcp_req->ref))
return;

kfree(tfcp_req);
}

static void
fcloop_tfcp_req_put(struct fcloop_fcpreq *tfcp_req)
{
kref_put(&tfcp_req->ref, fcloop_tfcp_req_free);
}

static int
fcloop_tfcp_req_get(struct fcloop_fcpreq *tfcp_req)
{
return kref_get_unless_zero(&tfcp_req->ref);
return refcount_inc_not_zero(&tfcp_req->ref);
}

static void
Expand Down Expand Up @@ -748,7 +743,7 @@ fcloop_fcp_req(struct nvme_fc_local_port *localport,
INIT_WORK(&tfcp_req->fcp_rcv_work, fcloop_fcp_recv_work);
INIT_WORK(&tfcp_req->abort_rcv_work, fcloop_fcp_abort_recv_work);
INIT_WORK(&tfcp_req->tio_done_work, fcloop_tgt_fcprqst_done_work);
kref_init(&tfcp_req->ref);
refcount_set(&tfcp_req->ref, 1);

queue_work(nvmet_wq, &tfcp_req->fcp_rcv_work);

Expand Down Expand Up @@ -1001,24 +996,39 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
}

static void
fcloop_nport_free(struct kref *ref)
fcloop_lport_put(struct fcloop_lport *lport)
{
struct fcloop_nport *nport =
container_of(ref, struct fcloop_nport, ref);
unsigned long flags;

kfree(nport);
if (!refcount_dec_and_test(&lport->ref))
return;

spin_lock_irqsave(&fcloop_lock, flags);
list_del(&lport->lport_list);
spin_unlock_irqrestore(&fcloop_lock, flags);

kfree(lport);
}

static int
fcloop_lport_get(struct fcloop_lport *lport)
{
return refcount_inc_not_zero(&lport->ref);
}

static void
fcloop_nport_put(struct fcloop_nport *nport)
{
kref_put(&nport->ref, fcloop_nport_free);
if (!refcount_dec_and_test(&nport->ref))
return;

kfree(nport);
}

static int
fcloop_nport_get(struct fcloop_nport *nport)
{
return kref_get_unless_zero(&nport->ref);
return refcount_inc_not_zero(&nport->ref);
}

static void
Expand All @@ -1029,6 +1039,8 @@ fcloop_localport_delete(struct nvme_fc_local_port *localport)

/* release any threads waiting for the unreg to complete */
complete(&lport->unreg_done);

fcloop_lport_put(lport);
}

static void
Expand Down Expand Up @@ -1140,6 +1152,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,

lport->localport = localport;
INIT_LIST_HEAD(&lport->lport_list);
refcount_set(&lport->ref, 1);

spin_lock_irqsave(&fcloop_lock, flags);
list_add_tail(&lport->lport_list, &fcloop_lports);
Expand All @@ -1156,13 +1169,6 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
return ret ? ret : count;
}


static void
__unlink_local_port(struct fcloop_lport *lport)
{
list_del(&lport->lport_list);
}

static int
__wait_localport_unreg(struct fcloop_lport *lport)
{
Expand All @@ -1175,8 +1181,6 @@ __wait_localport_unreg(struct fcloop_lport *lport)
if (!ret)
wait_for_completion(&lport->unreg_done);

kfree(lport);

return ret;
}

Expand All @@ -1199,8 +1203,9 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
list_for_each_entry(tlport, &fcloop_lports, lport_list) {
if (tlport->localport->node_name == nodename &&
tlport->localport->port_name == portname) {
if (!fcloop_lport_get(tlport))
break;
lport = tlport;
__unlink_local_port(lport);
break;
}
}
Expand All @@ -1210,6 +1215,7 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
return -ENOENT;

ret = __wait_localport_unreg(lport);
fcloop_lport_put(lport);

return ret ? ret : count;
}
Expand Down Expand Up @@ -1249,7 +1255,7 @@ fcloop_alloc_nport(const char *buf, size_t count, bool remoteport)
newnport->port_role = opts->roles;
if (opts->mask & NVMF_OPT_FCADDR)
newnport->port_id = opts->fcaddr;
kref_init(&newnport->ref);
refcount_set(&newnport->ref, 1);

spin_lock_irqsave(&fcloop_lock, flags);

Expand Down Expand Up @@ -1637,17 +1643,17 @@ static void __exit fcloop_exit(void)
for (;;) {
lport = list_first_entry_or_null(&fcloop_lports,
typeof(*lport), lport_list);
if (!lport)
if (!lport || !fcloop_lport_get(lport))
break;

__unlink_local_port(lport);

spin_unlock_irqrestore(&fcloop_lock, flags);

ret = __wait_localport_unreg(lport);
if (ret)
pr_warn("%s: Failed deleting local port\n", __func__);

fcloop_lport_put(lport);

spin_lock_irqsave(&fcloop_lock, flags);
}

Expand Down

0 comments on commit ff88562

Please sign in to comment.