armbian-build/patch/kernel/archive/odroidxu4-6.6/patch-6.6.124-125.patch
2026-03-05 22:02:47 +01:00

1214 lines
39 KiB
Diff

diff --git a/Makefile b/Makefile
index 4ec8ec24a35414..4a944e80769044 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 6
-SUBLEVEL = 124
+SUBLEVEL = 125
EXTRAVERSION =
NAME = Pinguïn Aangedreven
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 0b491449b022a1..35e14bebbfb2c2 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -165,9 +165,18 @@ void device_set_deferred_probe_reason(const struct device *dev, struct va_format
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
+ device_lock_assert(dev);
+
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
+static inline int driver_match_device_locked(struct device_driver *drv,
+ struct device *dev)
+{
+ guard(device)(dev);
+ return driver_match_device(drv, dev);
+}
+
static inline void dev_sync_state(struct device *dev)
{
if (dev->bus->sync_state)
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index b97e13a52c3308..27f8442a3aa9dd 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -263,7 +263,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
int err = -ENODEV;
dev = bus_find_device_by_name(bus, NULL, buf);
- if (dev && driver_match_device(drv, dev)) {
+ if (dev && driver_match_device_locked(drv, dev)) {
err = device_driver_attach(drv, dev);
if (!err) {
/* success */
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 7e2fb159bb895b..07f1332dd3a440 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -1169,7 +1169,7 @@ static int __driver_attach(struct device *dev, void *data)
* is an error.
*/
- ret = driver_match_device(drv, dev);
+ ret = driver_match_device_locked(drv, dev);
if (ret == 0) {
/* no match */
return 0;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 1309e9318bdb55..eaeacdadb20232 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -516,6 +516,8 @@ static const struct usb_device_id quirks_table[] = {
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x2001, 0x332a), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x7392, 0xe611), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
/* Realtek 8852AE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
index c4250e5fcf8f7b..11dfbd4beba9cd 100644
--- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
+++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
@@ -1336,7 +1336,7 @@ static ssize_t ucode_load_store(struct device *dev,
int del_grp_idx = -1;
int ucode_idx = 0;
- if (strlen(buf) > OTX_CPT_UCODE_NAME_LENGTH)
+ if (count >= OTX_CPT_UCODE_NAME_LENGTH)
return -EINVAL;
eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr);
diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c
index a4cc6bf146ec09..0345c9383d5097 100644
--- a/drivers/crypto/omap-crypto.c
+++ b/drivers/crypto/omap-crypto.c
@@ -21,7 +21,7 @@ static int omap_crypto_copy_sg_lists(int total, int bs,
struct scatterlist *tmp;
if (!(flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY)) {
- new_sg = kmalloc_array(n, sizeof(*sg), GFP_KERNEL);
+ new_sg = kmalloc_array(n, sizeof(*new_sg), GFP_KERNEL);
if (!new_sg)
return -ENOMEM;
diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c
index b909c6a2bf1c34..6ec9a95b4db073 100644
--- a/drivers/crypto/virtio/virtio_crypto_core.c
+++ b/drivers/crypto/virtio/virtio_crypto_core.c
@@ -77,15 +77,20 @@ static void virtcrypto_done_task(unsigned long data)
struct data_queue *data_vq = (struct data_queue *)data;
struct virtqueue *vq = data_vq->vq;
struct virtio_crypto_request *vc_req;
+ unsigned long flags;
unsigned int len;
+ spin_lock_irqsave(&data_vq->lock, flags);
do {
virtqueue_disable_cb(vq);
while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
+ spin_unlock_irqrestore(&data_vq->lock, flags);
if (vc_req->alg_cb)
vc_req->alg_cb(vc_req, len);
+ spin_lock_irqsave(&data_vq->lock, flags);
}
} while (!virtqueue_enable_cb(vq));
+ spin_unlock_irqrestore(&data_vq->lock, flags);
}
static void virtcrypto_dataq_callback(struct virtqueue *vq)
diff --git a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c
index 23c41d87d835ff..487f60e35df193 100644
--- a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c
+++ b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c
@@ -550,8 +550,6 @@ int virtio_crypto_skcipher_crypt_req(
if (ret < 0)
return ret;
- virtqueue_kick(data_vq->vq);
-
return 0;
}
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index a927680c66f88d..772fddc02b8181 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -799,10 +799,13 @@ static struct platform_device omap_mpuio_device = {
static inline void omap_mpuio_init(struct gpio_bank *bank)
{
- platform_set_drvdata(&omap_mpuio_device, bank);
+ static bool registered;
- if (platform_driver_register(&omap_mpuio_driver) == 0)
- (void) platform_device_register(&omap_mpuio_device);
+ platform_set_drvdata(&omap_mpuio_device, bank);
+ if (!registered) {
+ (void)platform_device_register(&omap_mpuio_device);
+ registered = true;
+ }
}
/*---------------------------------------------------------------------*/
@@ -1575,13 +1578,24 @@ static struct platform_driver omap_gpio_driver = {
*/
static int __init omap_gpio_drv_reg(void)
{
- return platform_driver_register(&omap_gpio_driver);
+ int ret;
+
+ ret = platform_driver_register(&omap_mpuio_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&omap_gpio_driver);
+ if (ret)
+ platform_driver_unregister(&omap_mpuio_driver);
+
+ return ret;
}
postcore_initcall(omap_gpio_drv_reg);
static void __exit omap_gpio_exit(void)
{
platform_driver_unregister(&omap_gpio_driver);
+ platform_driver_unregister(&omap_mpuio_driver);
}
module_exit(omap_gpio_exit);
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index dc62f141f40382..ff438be4c186e1 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -431,6 +431,8 @@ static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
*/
linkmode_zero(modes);
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
+ phy_interface_zero(interfaces);
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces);
}
#define SFP_QUIRK(_v, _p, _m, _f) \
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 0d0b5123b5fe28..c7396ae9256b9b 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -2401,10 +2401,10 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
if (enable) {
rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ rtw_write8_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
} else {
rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ rtw_write8_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
}
}
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index d2bddca7045aa1..4cef9a34934380 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3356,9 +3356,6 @@ login_logout:
atomic_read(&fcport->state) == FCS_ONLINE) ||
do_delete) {
if (fcport->loop_id != FC_NO_LOOP_ID) {
- if (fcport->flags & FCF_FCP2_DEVICE)
- continue;
-
ql_log(ql_log_warn, vha, 0x20f0,
"%s %d %8phC post del sess\n",
__func__, __LINE__,
@@ -3625,8 +3622,8 @@ int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
if (vha->scan.scan_flags & SF_SCANNING) {
spin_unlock_irqrestore(&vha->work_lock, flags);
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
- "%s: scan active\n", __func__);
- return rval;
+ "%s: scan active for sp:%p\n", __func__, sp);
+ goto done_free_sp;
}
vha->scan.scan_flags |= SF_SCANNING;
if (!sp)
@@ -3791,23 +3788,25 @@ int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
return rval;
done_free_sp:
- if (sp->u.iocb_cmd.u.ctarg.req) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.req_allocated_size,
- sp->u.iocb_cmd.u.ctarg.req,
- sp->u.iocb_cmd.u.ctarg.req_dma);
- sp->u.iocb_cmd.u.ctarg.req = NULL;
- }
- if (sp->u.iocb_cmd.u.ctarg.rsp) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
- sp->u.iocb_cmd.u.ctarg.rsp,
- sp->u.iocb_cmd.u.ctarg.rsp_dma);
- sp->u.iocb_cmd.u.ctarg.rsp = NULL;
- }
+ if (sp) {
+ if (sp->u.iocb_cmd.u.ctarg.req) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.req_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+ }
+ if (sp->u.iocb_cmd.u.ctarg.rsp) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
- /* ref: INIT */
- kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e881d704b45d1b..b736575e2d9fc8 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1859,15 +1859,6 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
case RSCN_PORT_ADDR:
fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
if (fcport) {
- if (ql2xfc2target &&
- fcport->flags & FCF_FCP2_DEVICE &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
- ql_dbg(ql_dbg_disc, vha, 0x2115,
- "Delaying session delete for FCP2 portid=%06x %8phC ",
- fcport->d_id.b24, fcport->port_name);
- return;
- }
-
if (vha->hw->flags.edif_enabled && DBELL_ACTIVE(vha)) {
/*
* On ipsec start by remote port, Target port
@@ -2471,8 +2462,23 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
ea->sp->gen1, fcport->rscn_gen,
ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]);
- if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
- (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
+ if (fcport->fw_login_state == DSC_LS_PLOGI_PEND) {
+ ql_dbg(ql_dbg_disc, vha, 0x20ea,
+ "%s %d %8phC Remote is trying to login\n",
+ __func__, __LINE__, fcport->port_name);
+ /*
+ * If we get here, there is port thats already logged in,
+ * but it's state has not moved ahead. Recheck with FW on
+ * what state it is in and proceed ahead
+ */
+ if (!N2N_TOPO(vha->hw)) {
+ fcport->fw_login_state = DSC_LS_PRLI_COMP;
+ qla24xx_post_gpdb_work(vha, fcport, 0);
+ }
+ return;
+ }
+
+ if (fcport->fw_login_state == DSC_LS_PRLI_PEND) {
ql_dbg(ql_dbg_disc, vha, 0x20ea,
"%s %d %8phC Remote is trying to login\n",
__func__, __LINE__, fcport->port_name);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ae2bea27a18a67..38214f8e30fa6d 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1676,13 +1676,28 @@ skip_rio:
/* Port logout */
fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]);
- if (!fcport)
+ if (!fcport) {
+ ql_dbg(ql_dbg_async, vha, 0x5011,
+ "Could not find fcport:%04x %04x %04x\n",
+ mb[1], mb[2], mb[3]);
break;
- if (atomic_read(&fcport->state) != FCS_ONLINE)
+ }
+
+ if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ ql_dbg(ql_dbg_async, vha, 0x5012,
+ "Port state is not online State:0x%x \n",
+ atomic_read(&fcport->state));
+ ql_dbg(ql_dbg_async, vha, 0x5012,
+ "Scheduling session for deletion \n");
+ fcport->logout_on_delete = 0;
+ qlt_schedule_sess_for_deletion(fcport);
break;
+ }
+
ql_dbg(ql_dbg_async, vha, 0x508a,
"Marking port lost loopid=%04x portid=%06x.\n",
fcport->loop_id, fcport->d_id.b24);
+
if (qla_ini_mode_enabled(vha)) {
fcport->logout_on_delete = 0;
qlt_schedule_sess_for_deletion(fcport);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index d10389ee92ba4b..b08abdf5ebf4e7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1194,7 +1194,8 @@ qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha)
while ((qla2x00_reset_active(vha) || ha->dpc_active ||
ha->flags.mbox_busy) ||
test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
- test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
+ test_bit(FX00_TARGET_SCAN, &vha->dpc_flags) ||
+ (vha->scan.scan_flags & SF_SCANNING)) {
if (test_bit(UNLOADING, &base_vha->dpc_flags))
break;
msleep(1000);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index eed88aba2cfe92..3e7bf76be22bb7 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -100,6 +100,8 @@ struct cqspi_st {
bool apb_ahb_hazard;
bool is_jh7110; /* Flag for StarFive JH7110 SoC */
+ refcount_t refcount;
+ refcount_t inflight_ops;
};
struct cqspi_driver_platdata {
@@ -705,6 +707,9 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
u8 *rxbuf_end = rxbuf + n_rx;
int ret = 0;
+ if (!refcount_read(&cqspi->refcount))
+ return -ENODEV;
+
writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR);
writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES);
@@ -1021,6 +1026,9 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata,
unsigned int write_bytes;
int ret;
+ if (!refcount_read(&cqspi->refcount))
+ return -ENODEV;
+
writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR);
writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES);
@@ -1412,11 +1420,29 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op)
static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
{
int ret;
+ struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller);
+
+ if (refcount_read(&cqspi->inflight_ops) == 0)
+ return -ENODEV;
+
+ if (!refcount_read(&cqspi->refcount))
+ return -EBUSY;
+
+ refcount_inc(&cqspi->inflight_ops);
+
+ if (!refcount_read(&cqspi->refcount)) {
+ if (refcount_read(&cqspi->inflight_ops))
+ refcount_dec(&cqspi->inflight_ops);
+ return -EBUSY;
+ }
ret = cqspi_mem_process(mem, op);
if (ret)
dev_err(&mem->spi->dev, "operation failed with %d\n", ret);
+ if (refcount_read(&cqspi->inflight_ops) > 1)
+ refcount_dec(&cqspi->inflight_ops);
+
return ret;
}
@@ -1847,6 +1873,9 @@ static int cqspi_probe(struct platform_device *pdev)
}
}
+ refcount_set(&cqspi->refcount, 1);
+ refcount_set(&cqspi->inflight_ops, 1);
+
ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0,
pdev->name, cqspi);
if (ret) {
@@ -1899,6 +1928,11 @@ static void cqspi_remove(struct platform_device *pdev)
{
struct cqspi_st *cqspi = platform_get_drvdata(pdev);
+ refcount_set(&cqspi->refcount, 0);
+
+ if (!refcount_dec_and_test(&cqspi->inflight_ops))
+ cqspi_wait_idle(cqspi);
+
spi_unregister_controller(cqspi->host);
cqspi_controller_enable(cqspi, 0);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 78ebdf20c1efa3..4703e2a935684b 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1526,17 +1526,24 @@ static __net_init int nfsd_net_init(struct net *net)
retval = nfsd_stat_counters_init(nn);
if (retval)
goto out_repcache_error;
+
memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats));
nn->nfsd_svcstats.program = &nfsd_program;
+ if (!nfsd_proc_stat_init(net)) {
+ retval = -ENOMEM;
+ goto out_proc_error;
+ }
+
nn->nfsd_versions = NULL;
nn->nfsd4_minorversions = NULL;
nfsd4_init_leases_net(nn);
get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key));
seqlock_init(&nn->writeverf_lock);
- nfsd_proc_stat_init(net);
return 0;
+out_proc_error:
+ nfsd_stat_counters_destroy(nn);
out_repcache_error:
nfsd_idmap_shutdown(net);
out_idmap_error:
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 9f606fa08bd4b8..0a629a18831f19 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -115,11 +115,11 @@ void nfsd_stat_counters_destroy(struct nfsd_net *nn)
nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM);
}
-void nfsd_proc_stat_init(struct net *net)
+struct proc_dir_entry *nfsd_proc_stat_init(struct net *net)
{
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
- svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
+ return svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
}
void nfsd_proc_stat_shutdown(struct net *net)
diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h
index d2753e975dfd34..b1f7d21cbcd12c 100644
--- a/fs/nfsd/stats.h
+++ b/fs/nfsd/stats.h
@@ -15,7 +15,7 @@ void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num);
void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
int nfsd_stat_counters_init(struct nfsd_net *nn);
void nfsd_stat_counters_destroy(struct nfsd_net *nn);
-void nfsd_proc_stat_init(struct net *net);
+struct proc_dir_entry *nfsd_proc_stat_init(struct net *net);
void nfsd_proc_stat_shutdown(struct net *net);
static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn)
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index 58ca7c936393c4..aa39cdce59930b 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -1091,6 +1091,9 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range)
else
end_block = start_block + len - 1;
+ if (end_block < nilfs->ns_first_data_block)
+ goto out;
+
segnum = nilfs_get_segnum_of_block(nilfs, start_block);
segnum_end = nilfs_get_segnum_of_block(nilfs, end_block);
@@ -1188,6 +1191,7 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range)
out_sem:
up_read(&NILFS_MDT(sufile)->mi_sem);
+out:
range->len = ndiscarded << nilfs->ns_blocksize_bits;
return ret;
}
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index bc8a812ff95f8b..96697c78b3a650 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -34,10 +34,10 @@ struct cached_fid {
struct list_head entry;
struct cached_fids *cfids;
const char *path;
- bool has_lease:1;
- bool is_open:1;
- bool on_list:1;
- bool file_all_info_is_valid:1;
+ bool has_lease;
+ bool is_open;
+ bool on_list;
+ bool file_all_info_is_valid;
unsigned long time; /* jiffies of when lease was taken */
struct kref refcount;
struct cifs_fid fid;
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
index 80050b2178980a..598601a4bf92c7 100644
--- a/fs/smb/server/server.c
+++ b/fs/smb/server/server.c
@@ -126,21 +126,21 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
andx_again:
if (command >= conn->max_cmds) {
conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
- return SERVER_HANDLER_CONTINUE;
+ return SERVER_HANDLER_ABORT;
}
cmds = &conn->cmds[command];
if (!cmds->proc) {
ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
- return SERVER_HANDLER_CONTINUE;
+ return SERVER_HANDLER_ABORT;
}
if (work->sess && conn->ops->is_sign_req(work, command)) {
ret = conn->ops->check_sign_req(work);
if (!ret) {
conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
- return SERVER_HANDLER_CONTINUE;
+ return SERVER_HANDLER_ABORT;
}
}
diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
index 08275db6446c2b..d05af46257cf4f 100644
--- a/fs/smb/server/transport_tcp.c
+++ b/fs/smb/server/transport_tcp.c
@@ -41,6 +41,7 @@ static struct ksmbd_transport_ops ksmbd_tcp_transport_ops;
static void tcp_stop_kthread(struct task_struct *kthread);
static struct interface *alloc_iface(char *ifname);
+static void ksmbd_tcp_disconnect(struct ksmbd_transport *t);
#define KSMBD_TRANS(t) (&(t)->transport)
#define TCP_TRANS(t) ((struct tcp_transport *)container_of(t, \
@@ -219,7 +220,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
if (IS_ERR(handler)) {
pr_err("cannot start conn thread\n");
rc = PTR_ERR(handler);
- free_transport(t);
+ ksmbd_tcp_disconnect(KSMBD_TRANS(t));
}
return rc;
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 9f25cfd96f980f..4b805d7f5769f7 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -1859,16 +1859,26 @@ static void __reset_counters(struct pm_nl_pernet *pernet)
static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
{
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
- LIST_HEAD(free_list);
+ struct list_head free_list;
spin_lock_bh(&pernet->lock);
- list_splice_init(&pernet->local_addr_list, &free_list);
+ free_list = pernet->local_addr_list;
+ INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
__reset_counters(pernet);
pernet->next_id = 1;
bitmap_zero(pernet->id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
spin_unlock_bh(&pernet->lock);
- mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
+
+ if (free_list.next == &pernet->local_addr_list)
+ return 0;
+
synchronize_rcu();
+
+ /* Adjust the pointers to free_list instead of pernet->local_addr_list */
+ free_list.prev->next = &free_list;
+ free_list.next->prev = &free_list;
+
+ mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
__flush_addrs(&free_list);
return 0;
}
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 120d9bd53321ca..a0a5d19fa8506b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -6615,7 +6615,7 @@ static int nft_setelem_catchall_insert(const struct net *net,
}
}
- catchall = kmalloc(sizeof(*catchall), GFP_KERNEL);
+ catchall = kmalloc(sizeof(*catchall), GFP_KERNEL_ACCOUNT);
if (!catchall)
return -ENOMEM;
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 52cdfee17f73f1..7ca4f0d21fe2a2 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -535,7 +535,7 @@ nft_match_large_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
struct xt_match *m = expr->ops->data;
int ret;
- priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL);
+ priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL_ACCOUNT);
if (!priv->info)
return -ENOMEM;
@@ -808,7 +808,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
goto err;
}
- ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL_ACCOUNT);
if (!ops) {
err = -ENOMEM;
goto err;
@@ -898,7 +898,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
goto err;
}
- ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL_ACCOUNT);
if (!ops) {
err = -ENOMEM;
goto err;
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 5defe6e4fd9820..e3558813799579 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -163,7 +163,7 @@ static int nft_log_init(const struct nft_ctx *ctx,
nla = tb[NFTA_LOG_PREFIX];
if (nla != NULL) {
- priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL);
+ priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL_ACCOUNT);
if (priv->prefix == NULL)
return -ENOMEM;
nla_strscpy(priv->prefix, nla, nla_len(nla) + 1);
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 8c8eb14d647b07..05cd1e6e6a2f61 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -952,7 +952,7 @@ static int nft_secmark_obj_init(const struct nft_ctx *ctx,
if (tb[NFTA_SECMARK_CTX] == NULL)
return -EINVAL;
- priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL);
+ priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL_ACCOUNT);
if (!priv->ctx)
return -ENOMEM;
diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c
index 7d29db7c2ac0f0..bd058babfc820c 100644
--- a/net/netfilter/nft_numgen.c
+++ b/net/netfilter/nft_numgen.c
@@ -66,7 +66,7 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
if (priv->offset + priv->modulus - 1 < priv->offset)
return -EOVERFLOW;
- priv->counter = kmalloc(sizeof(*priv->counter), GFP_KERNEL);
+ priv->counter = kmalloc(sizeof(*priv->counter), GFP_KERNEL_ACCOUNT);
if (!priv->counter)
return -ENOMEM;
diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
index ebd0f704c863c3..c3ada6798d4a3f 100644
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -610,6 +610,30 @@ static void *nft_pipapo_get(const struct net *net, const struct nft_set *set,
nft_genmask_cur(net), get_jiffies_64());
}
+
+/**
+ * lt_calculate_size() - Get storage size for lookup table with overflow check
+ * @groups: Amount of bit groups
+ * @bb: Number of bits grouped together in lookup table buckets
+ * @bsize: Size of each bucket in lookup table, in longs
+ *
+ * Return: allocation size including alignment overhead, negative on overflow
+ */
+static ssize_t lt_calculate_size(unsigned int groups, unsigned int bb,
+ unsigned int bsize)
+{
+ ssize_t ret = groups * NFT_PIPAPO_BUCKETS(bb) * sizeof(long);
+
+ if (check_mul_overflow(ret, bsize, &ret))
+ return -1;
+ if (check_add_overflow(ret, NFT_PIPAPO_ALIGN_HEADROOM, &ret))
+ return -1;
+ if (ret > INT_MAX)
+ return -1;
+
+ return ret;
+}
+
/**
* pipapo_resize() - Resize lookup or mapping table, or both
* @f: Field containing lookup and mapping tables
@@ -628,6 +652,7 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules)
union nft_pipapo_map_bucket *new_mt, *old_mt = f->mt;
size_t new_bucket_size, copy;
int group, bucket;
+ ssize_t lt_size;
new_bucket_size = DIV_ROUND_UP(rules, BITS_PER_LONG);
#ifdef NFT_PIPAPO_ALIGN
@@ -643,10 +668,11 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules)
else
copy = new_bucket_size;
- new_lt = kvzalloc(f->groups * NFT_PIPAPO_BUCKETS(f->bb) *
- new_bucket_size * sizeof(*new_lt) +
- NFT_PIPAPO_ALIGN_HEADROOM,
- GFP_KERNEL);
+ lt_size = lt_calculate_size(f->groups, f->bb, new_bucket_size);
+ if (lt_size < 0)
+ return -ENOMEM;
+
+ new_lt = kvzalloc(lt_size, GFP_KERNEL_ACCOUNT);
if (!new_lt)
return -ENOMEM;
@@ -845,7 +871,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
{
unsigned long *new_lt;
int groups, bb;
- size_t lt_size;
+ ssize_t lt_size;
lt_size = f->groups * NFT_PIPAPO_BUCKETS(f->bb) * f->bsize *
sizeof(*f->lt);
@@ -855,15 +881,17 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
groups = f->groups * 2;
bb = NFT_PIPAPO_GROUP_BITS_LARGE_SET;
- lt_size = groups * NFT_PIPAPO_BUCKETS(bb) * f->bsize *
- sizeof(*f->lt);
+ lt_size = lt_calculate_size(groups, bb, f->bsize);
+ if (lt_size < 0)
+ return;
} else if (f->bb == NFT_PIPAPO_GROUP_BITS_LARGE_SET &&
lt_size < NFT_PIPAPO_LT_SIZE_LOW) {
groups = f->groups / 2;
bb = NFT_PIPAPO_GROUP_BITS_SMALL_SET;
- lt_size = groups * NFT_PIPAPO_BUCKETS(bb) * f->bsize *
- sizeof(*f->lt);
+ lt_size = lt_calculate_size(groups, bb, f->bsize);
+ if (lt_size < 0)
+ return;
/* Don't increase group width if the resulting lookup table size
* would exceed the upper size threshold for a "small" set.
@@ -874,7 +902,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
return;
}
- new_lt = kvzalloc(lt_size + NFT_PIPAPO_ALIGN_HEADROOM, GFP_KERNEL);
+ new_lt = kvzalloc(lt_size, GFP_KERNEL_ACCOUNT);
if (!new_lt)
return;
@@ -1150,7 +1178,7 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone,
scratch = kzalloc_node(struct_size(scratch, map,
bsize_max * 2) +
NFT_PIPAPO_ALIGN_HEADROOM,
- GFP_KERNEL, cpu_to_node(i));
+ GFP_KERNEL_ACCOUNT, cpu_to_node(i));
if (!scratch) {
/* On failure, there's no need to undo previous
* allocations: this means that some scratch maps have
@@ -1323,7 +1351,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
struct nft_pipapo_match *new;
int i;
- new = kmalloc(struct_size(new, f, old->field_count), GFP_KERNEL);
+ new = kmalloc(struct_size(new, f, old->field_count), GFP_KERNEL_ACCOUNT);
if (!new)
return ERR_PTR(-ENOMEM);
@@ -1347,13 +1375,15 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
for (i = 0; i < old->field_count; i++) {
unsigned long *new_lt;
+ ssize_t lt_size;
memcpy(dst, src, offsetof(struct nft_pipapo_field, lt));
- new_lt = kvzalloc(src->groups * NFT_PIPAPO_BUCKETS(src->bb) *
- src->bsize * sizeof(*dst->lt) +
- NFT_PIPAPO_ALIGN_HEADROOM,
- GFP_KERNEL);
+ lt_size = lt_calculate_size(src->groups, src->bb, src->bsize);
+ if (lt_size < 0)
+ goto out_lt;
+
+ new_lt = kvzalloc(lt_size, GFP_KERNEL_ACCOUNT);
if (!new_lt)
goto out_lt;
@@ -1367,7 +1397,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
if (src->rules > (INT_MAX / sizeof(*src->mt)))
goto out_mt;
- dst->mt = kvmalloc(src->rules * sizeof(*src->mt), GFP_KERNEL);
+ dst->mt = kvmalloc(src->rules * sizeof(*src->mt), GFP_KERNEL_ACCOUNT);
if (!dst->mt)
goto out_mt;
diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c
index 3e3ae29dde3359..f77a5bf6991138 100644
--- a/net/netfilter/nft_tunnel.c
+++ b/net/netfilter/nft_tunnel.c
@@ -503,13 +503,14 @@ static int nft_tunnel_obj_init(const struct nft_ctx *ctx,
return err;
}
- md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL, GFP_KERNEL);
+ md = metadata_dst_alloc(priv->opts.len, METADATA_IP_TUNNEL,
+ GFP_KERNEL_ACCOUNT);
if (!md)
return -ENOMEM;
memcpy(&md->u.tun_info, &info, sizeof(info));
#ifdef CONFIG_DST_CACHE
- err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL);
+ err = dst_cache_init(&md->u.tun_info.dst_cache, GFP_KERNEL_ACCOUNT);
if (err < 0) {
metadata_dst_free(md);
return err;
diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh
index 3528e730e4d37c..c089d4e06d5999 100755
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
+++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
@@ -127,6 +127,10 @@ id 8 flags signal 10.0.1.8" "id limit"
ip netns exec $ns1 ./pm_nl_ctl flush
check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs"
+ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 flags unknown
+check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1" "ignore unknown flags"
+ip netns exec $ns1 ./pm_nl_ctl flush
+
ip netns exec $ns1 ./pm_nl_ctl limits 9 1 2>/dev/null
check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit"
diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
index 234c267dd2aad3..f586f1272bd784 100644
--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
@@ -29,6 +29,8 @@
#define IPPROTO_MPTCP 262
#endif
+#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
+
static void syntax(char *argv[])
{
fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
@@ -825,6 +827,8 @@ int add_addr(int fd, int pm_family, int argc, char *argv[])
flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
else if (!strcmp(tok, "fullmesh"))
flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
+ else if (!strcmp(tok, "unknown"))
+ flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN;
else
error(1, errno,
"unknown flag %s", argv[arg]);
@@ -1030,6 +1034,13 @@ static void print_addr(struct rtattr *attrs, int len)
printf(",");
}
+ if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) {
+ printf("unknown");
+ flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN;
+ if (flags)
+ printf(",");
+ }
+
/* bump unknown flags, if any */
if (flags)
printf("0x%x", flags);
diff --git a/tools/testing/vsock/control.c b/tools/testing/vsock/control.c
index d2deb4b15b943c..0066e0324d35c6 100644
--- a/tools/testing/vsock/control.c
+++ b/tools/testing/vsock/control.c
@@ -27,6 +27,7 @@
#include "timeout.h"
#include "control.h"
+#include "util.h"
static int control_fd = -1;
@@ -50,7 +51,6 @@ void control_init(const char *control_host,
for (ai = result; ai; ai = ai->ai_next) {
int fd;
- int val = 1;
fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (fd < 0)
@@ -65,11 +65,8 @@ void control_init(const char *control_host,
break;
}
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- &val, sizeof(val)) < 0) {
- perror("setsockopt");
- exit(EXIT_FAILURE);
- }
+ setsockopt_int_check(fd, SOL_SOCKET, SO_REUSEADDR, 1,
+ "setsockopt SO_REUSEADDR");
if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
goto next;
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index 751fe7c6632eac..e67e26636f5796 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -12,6 +12,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <signal.h>
+#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/epoll.h>
@@ -420,3 +421,145 @@ unsigned long hash_djb2(const void *data, size_t len)
return hash;
}
+
+/* Set "unsigned long long" socket option and check that it's indeed set */
+void setsockopt_ull_check(int fd, int level, int optname,
+ unsigned long long val, char const *errmsg)
+{
+ unsigned long long chkval;
+ socklen_t chklen;
+ int err;
+
+ err = setsockopt(fd, level, optname, &val, sizeof(val));
+ if (err) {
+ fprintf(stderr, "setsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ chkval = ~val; /* just make storage != val */
+ chklen = sizeof(chkval);
+
+ err = getsockopt(fd, level, optname, &chkval, &chklen);
+ if (err) {
+ fprintf(stderr, "getsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ if (chklen != sizeof(chkval)) {
+ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
+ chklen);
+ goto fail;
+ }
+
+ if (chkval != val) {
+ fprintf(stderr, "value mismatch: set %llu got %llu\n", val,
+ chkval);
+ goto fail;
+ }
+ return;
+fail:
+ fprintf(stderr, "%s val %llu\n", errmsg, val);
+ exit(EXIT_FAILURE);
+;
+}
+
+/* Set "int" socket option and check that it's indeed set */
+void setsockopt_int_check(int fd, int level, int optname, int val,
+ char const *errmsg)
+{
+ int chkval;
+ socklen_t chklen;
+ int err;
+
+ err = setsockopt(fd, level, optname, &val, sizeof(val));
+ if (err) {
+ fprintf(stderr, "setsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ chkval = ~val; /* just make storage != val */
+ chklen = sizeof(chkval);
+
+ err = getsockopt(fd, level, optname, &chkval, &chklen);
+ if (err) {
+ fprintf(stderr, "getsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ if (chklen != sizeof(chkval)) {
+ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
+ chklen);
+ goto fail;
+ }
+
+ if (chkval != val) {
+ fprintf(stderr, "value mismatch: set %d got %d\n", val, chkval);
+ goto fail;
+ }
+ return;
+fail:
+ fprintf(stderr, "%s val %d\n", errmsg, val);
+ exit(EXIT_FAILURE);
+}
+
+static void mem_invert(unsigned char *mem, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ mem[i] = ~mem[i];
+}
+
+/* Set "timeval" socket option and check that it's indeed set */
+void setsockopt_timeval_check(int fd, int level, int optname,
+ struct timeval val, char const *errmsg)
+{
+ struct timeval chkval;
+ socklen_t chklen;
+ int err;
+
+ err = setsockopt(fd, level, optname, &val, sizeof(val));
+ if (err) {
+ fprintf(stderr, "setsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ /* just make storage != val */
+ chkval = val;
+ mem_invert((unsigned char *)&chkval, sizeof(chkval));
+ chklen = sizeof(chkval);
+
+ err = getsockopt(fd, level, optname, &chkval, &chklen);
+ if (err) {
+ fprintf(stderr, "getsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ if (chklen != sizeof(chkval)) {
+ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
+ chklen);
+ goto fail;
+ }
+
+ if (memcmp(&chkval, &val, sizeof(val)) != 0) {
+ fprintf(stderr, "value mismatch: set %ld:%ld got %ld:%ld\n",
+ val.tv_sec, val.tv_usec, chkval.tv_sec, chkval.tv_usec);
+ goto fail;
+ }
+ return;
+fail:
+ fprintf(stderr, "%s val %ld:%ld\n", errmsg, val.tv_sec, val.tv_usec);
+ exit(EXIT_FAILURE);
+}
+
+void enable_so_zerocopy_check(int fd)
+{
+ setsockopt_int_check(fd, SOL_SOCKET, SO_ZEROCOPY, 1,
+ "setsockopt SO_ZEROCOPY");
+}
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index fb99208a95eab7..a05438851919c7 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -50,4 +50,11 @@ void list_tests(const struct test_case *test_cases);
void skip_test(struct test_case *test_cases, size_t test_cases_len,
const char *test_id_str);
unsigned long hash_djb2(const void *data, size_t len);
+void setsockopt_ull_check(int fd, int level, int optname,
+ unsigned long long val, char const *errmsg);
+void setsockopt_int_check(int fd, int level, int optname, int val,
+ char const *errmsg);
+void setsockopt_timeval_check(int fd, int level, int optname,
+ struct timeval val, char const *errmsg);
+void enable_so_zerocopy_check(int fd);
#endif /* UTIL_H */
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 793d688cd4da6d..01ad8cfa9bde37 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -503,17 +503,13 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
sock_buf_size = SOCK_BUF_SIZE;
- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
- &sock_buf_size, sizeof(sock_buf_size))) {
- perror("setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
- &sock_buf_size, sizeof(sock_buf_size))) {
- perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
/* Ready to receive data. */
control_writeln("SRVREADY");
@@ -648,10 +644,8 @@ static void test_seqpacket_timeout_client(const struct test_opts *opts)
tv.tv_sec = RCVTIMEO_TIMEOUT_SEC;
tv.tv_usec = 0;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) {
- perror("setsockopt(SO_RCVTIMEO)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_timeval_check(fd, SOL_SOCKET, SO_RCVTIMEO, tv,
+ "setsockopt(SO_RCVTIMEO)");
read_enter_ns = current_nsec();
@@ -928,11 +922,8 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
exit(EXIT_FAILURE);
}
- if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT,
- &lowat_val, sizeof(lowat_val))) {
- perror("setsockopt(SO_RCVLOWAT)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_int_check(fd, SOL_SOCKET, SO_RCVLOWAT,
+ lowat_val, "setsockopt(SO_RCVLOWAT)");
control_expectln("SRVSENT");